From 52b7e1c1f72b30945e1dd3921674cd1aa0c9a582 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 5 Sep 2023 16:26:16 +0200 Subject: [PATCH 01/17] v117 patches --- ...le-find-bad-constructs-external-repo.patch | 5 +- .../00Add-a-flag-to-disable-GamePad-API.patch | 7 +- .../00Add-option-to-disable-snapshots.patch | 25 +- .../00Add-setting-to-clear-data-on-exit.patch | 43 +- ...d-setting-to-invert-tap-and-long-tap.patch | 72 +- ...PiP-if-PopupsAndRedirects-are-active.patch | 4 +- ...ORS-Preflight-Cache-on-clearing-data.patch | 11 +- ...ress-libchrome-to-free-up-some-space.patch | 4 +- build/patches/00Cromite-Branding.patch | 19 +- ...0Deprecate-Data-URL-in-SVGUseElement.patch | 5 +- .../patches/00Disable-BackForwardCache.patch | 5 +- ...ble-Compression-Dictionary-Transport.patch | 15 +- build/patches/00Disable-FedCm.patch | 13 +- .../patches/00Disable-Feeback-Collector.patch | 3 +- ...-FirstPartySets-and-StorageAccessAPI.patch | 5 +- build/patches/00Disable-GSA-by-default.patch | 27 +- ...0Disable-GetInstalledRelatedApps-API.patch | 7 +- .../00Disable-PartnerCustomizations.patch | 5 +- .../00Disable-PrivateStateTokens-API.patch | 7 +- .../00Disable-SHA1-Server-Signature.patch | 3 +- ...ble-remote-altsvc-for-h3-connections.patch | 4 +- ...isable-speechSynthesis-getVoices-API.patch | 14 +- .../00Disable-visited-pseudo-class.patch | 6 +- ...sallowing-MIDI-permission-by-default.patch | 3 +- ...ndroid-Dynamic-Performance-Framework.patch | 7 +- ...le-Document-Open-Inheritance-Removal.patch | 5 +- .../00Fonts-fingerprinting-mitigation.patch | 24 +- build/patches/00Internal-firewall.patch | 40 +- ...00Keep-Side-Panel-Companion-disabled.patch | 7 +- .../patches/00Keyboard-protection-flag.patch | 31 +- .../00Lock-Profile-Cookie-Database.patch | 15 +- ...ing-attributes-in-some-html-elements.patch | 18 +- ...ulti-Screen-Window-Placement-API-fix.patch | 33 +- .../00Partition-HSTS-cache-by-NAK.patch | 49 +- ...ning-all-cookies-by-top-frame-domain.patch | 22 +- .../00Remove-ChromiumNetworkAdapter.patch | 14 +- ...th-header-upon-cross-origin-redirect.patch | 3 +- ...0Remove-detection-of-captive-portals.patch | 3 +- ...xperimental-relative-c---abi-vtables.patch | 7 +- ...t-for-device-memory-and-cpu-recovery.patch | 5 +- .../00Restore-LastTabStandingTracker.patch | 25 +- ...Show-warnings-on-downloads-over-HTTP.patch | 3 +- ...-Add-a-log-to-track-strange-behavior.patch | 3 +- ...e-kAutomaticLazyFrameLoadingToEmbeds.patch | 5 +- ...Temp-disable-predictive-back-gesture.patch | 5 +- ...O-AImageReader-CFI-crash-mitigations.patch | 26 - ...ADDTO-Add-AllowUserCertificates-flag.patch | 26 - ...ADDTO-Add-a-proxy-configuration-page.patch | 39 - ...O-Add-bookmark-import-export-actions.patch | 96 - ...isable-requests-for-single-word-Omni.patch | 29 - .../00WIN-ADDTO-Disable-various-metrics.patch | 45 - ...-ADDTO-Do-not-build-API-keys-infobar.patch | 23 - ...TO-Experimental-user-scripts-support.patch | 337 - .../00WIN-ADDTO-Logcat-crash-reports-UI.patch | 81 - ...TO-Restore-Search-Ready-Omnibox-flag.patch | 25 - ...Revert-flags--remove-num-raster-thre.patch | 29 - ...penH264--enable-ARM-ARM64-optimizati.patch | 26 - ...ngoogled-chr--Disable-profile-avatar.patch | 22 - .../00WIN-Disable-TabHoverCard-images.patch | 3 +- build/patches/00WIN-Disable-sharing-hub.patch | 7 +- ...able-Network-Service-Sandbox-and-CIG.patch | 5 +- ...enable-HighEfficiencyMode-by-default.patch | 7 +- ...-enable-file-system-access-blocklist.patch | 5 +- build/patches/00WIN-enable-pdf-plugin.patch | 5 +- ...message-for-unsupported-hardware-aes.patch | 40 +- build/patches/00add-browser-policy.patch | 57 +- ...ot-block-build-incompatible-profiles.patch | 7 +- build/patches/00v113-temp-fix-build.patch | 3 +- .../AImageReader-CFI-crash-mitigations.patch | 16 +- .../Add-AllowUserCertificates-flag.patch | 47 +- ...dd-Alt-D-hotkey-to-focus-address-bar.patch | 2 +- .../Add-IsCleartextPermitted-flag.patch | 22 +- .../Add-a-proxy-configuration-page.patch | 53 +- .../Add-an-always-incognito-mode.patch | 198 +- build/patches/Add-autoplay-site-setting.patch | 2 +- .../Add-bookmark-import-export-actions.patch | 201 +- ...dd-custom-tab-intents-privacy-option.patch | 35 +- build/patches/Add-exit-menu-item.patch | 12 +- ...g-for-omnibox-autocomplete-filtering.patch | 12 +- .../Add-flag-for-save-data-header.patch | 8 +- ...nfigure-maximum-connections-per-host.patch | 8 +- ...ontrol-video-playback-resume-feature.patch | 6 +- .../Add-flag-to-disable-IPv6-probes.patch | 16 +- ...-to-disable-external-intent-requests.patch | 6 +- .../Add-flag-to-disable-vibration.patch | 18 +- ...-switch-for-unsupported-clangd-flags.patch | 15 +- ...Add-lifetime-options-for-permissions.patch | 96 +- .../Add-menu-item-to-bookmark-all-tabs.patch | 131 +- .../Add-menu-item-to-view-source.patch | 14 +- .../Add-option-to-force-tablet-UI.patch | 16 +- ...-to-not-persist-tabs-across-sessions.patch | 10 +- .../Add-option-to-use-home-page-as-NTP.patch | 44 +- build/patches/Add-site-engagement-flag.patch | 8 +- ...-support-for-ISupportHelpAndFeedback.patch | 4 +- build/patches/Add-webGL-site-setting.patch | 6 +- build/patches/Add-webRTC-site-settings.patch | 12 +- ...ow-building-without-enable_reporting.patch | 18 +- ...ow-building-without-supervised-users.patch | 48 +- .../Allow-playing-audio-in-background.patch | 2 +- ...e-new-tab-page-for-default-home-page.patch | 2 +- ...ioBuffer-AnalyserNode-fp-mitigations.patch | 18 +- ...Block-gateway-attacks-via-websockets.patch | 16 +- .../Block-qjz9zk-or-trk-requests.patch | 6 +- .../Bookmarks-select-all-menu-entry.patch | 10 +- build/patches/Bromite-auto-updater.patch | 77 +- .../Bromite-subresource-adblocker.patch | 80 +- build/patches/Client-hints-overrides.patch | 22 +- .../Content-settings-infrastructure.patch | 168 +- ...ctionary-suggestions-for-the-Omnibox.patch | 2 +- ...ble-Accessibility-service-by-default.patch | 4 +- .../patches/Disable-AsyncDNS-by-default.patch | 2 +- ...DRM-media-origin-IDs-preprovisioning.patch | 2 +- .../Disable-FLoC-and-privacy-sandbox.patch | 18 +- build/patches/Disable-PrivacyGuide.patch | 6 +- .../Disable-StartSurface-feature.patch | 4 +- build/patches/Disable-TLS-resumption.patch | 26 +- build/patches/Disable-UA-full-version.patch | 10 +- .../patches/Disable-all-predictors-code.patch | 137 +- build/patches/Disable-all-promo-dialogs.patch | 2 +- .../Disable-conversion-measurement-api.patch | 134 +- build/patches/Disable-crash-reporting.patch | 4 +- .../Disable-feeds-support-by-default.patch | 4 +- ...Disable-fetching-of-all-field-trials.patch | 78 +- build/patches/Disable-idle-detection.patch | 4 +- ...-lock-icon-in-address-bar-by-default.patch | 8 +- ...media-router-and-remoting-by-default.patch | 2 +- .../Disable-minidump-upload-scheduling.patch | 2 +- .../patches/Disable-plugins-enumeration.patch | 2 +- ...sts-for-single-word-Omnibar-searches.patch | 22 +- build/patches/Disable-safety-check.patch | 36 +- .../Disable-smart-selection-by-default.patch | 14 +- ...isable-some-signed-exchange-features.patch | 2 +- ...ble-support-for-RAR-files-inspection.patch | 25 +- .../Disable-text-fragments-by-default.patch | 20 +- .../Disable-third-party-origin-trials.patch | 16 +- build/patches/Disable-various-metrics.patch | 54 +- .../Do-not-build-API-keys-infobar.patch | 20 +- .../Do-not-compile-QR-code-sharing.patch | 28 +- .../Do-not-hide-component-extensions.patch | 2 +- .../patches/Do-not-link-with-libatomic.patch | 2 +- .../Do-not-store-passwords-by-default.patch | 4 +- build/patches/DoH-improvements.patch | 2 +- .../Enable-Certificate-Transparency.patch | 120 +- build/patches/Enable-ECH-by-default.patch | 2 +- build/patches/Enable-HEVC-by-default.patch | 4 +- ...able-PermuteTLSExtensions-by-default.patch | 2 +- ...ctOriginIsolation-and-SitePerProcess.patch | 10 +- ...e-darken-websites-checkbox-in-themes.patch | 2 +- ...fwrapv-in-Clang-for-non-UBSan-builds.patch | 2 +- .../Enable-native-Android-autofill.patch | 100 +- .../Enable-network-isolation-features.patch | 81 +- ...-prefetch-privacy-changes-by-default.patch | 2 +- build/patches/Enable-share-intent.patch | 36 +- ...ble-third-party-storage-partitioning.patch | 2 +- .../Experimental-user-scripts-support.patch | 189 +- .../Guard-for-user-agent-reduction.patch | 6 +- ...story-number-of-days-privacy-setting.patch | 24 +- ...e-enterprise-policies-for-secure-DNS.patch | 2 +- ...number-of-autocomplete-matches-to-10.patch | 30 +- ...ripts-for-AMP-tracking-ads-and-video.patch | 21 +- build/patches/JIT-site-settings.patch | 2 +- .../Keep-empty-tabs-between-sessions.patch | 2 +- ...-allow-screenshots-in-Incognito-mode.patch | 4 +- build/patches/Logcat-crash-reports-UI.patch | 39 +- .../patches/Modify-default-preferences.patch | 30 +- .../Move-navigation-bar-to-bottom.patch | 240 +- ...nt-settings-back-to-privacy-settings.patch | 8 +- .../Multiple-fingerprinting-mitigations.patch | 48 +- build/patches/Never-fetch-popular-sites.patch | 6 +- ...HTTP-probes-for-connection-detection.patch | 2 +- ...uiltin-autocomplete-for-chrome-flags.patch | 2 +- build/patches/OpenSearch-miscellaneous.patch | 24 +- .../patches/Override-Navigator-Language.patch | 2 +- .../Partition-Blink-memory-cache.patch | 16 +- ...-modal-dialog-flag-to-close-all-tabs.patch | 138 +- ...e-introduce-override_build_timestamp.patch | 2 +- ...ders-in-DoH-requests-to-bare-minimum.patch | 31 +- ...referrals-in-cross-origin-navigation.patch | 52 +- build/patches/Remove-SMS-integration.patch | 8 +- .../Remove-binary-blob-integrations.patch | 255 +- build/patches/Remove-help-menu-item.patch | 8 +- .../Remove-navigator.connection-info.patch | 4 +- .../Remove-segmentation-platform.patch | 2 +- ...Remove-voice-recognition-integration.patch | 74 +- ...ndow-name-on-cross-origin-navigation.patch | 4 +- .../Restore-Search-Ready-Omnibox-flag.patch | 40 +- .../Restore-Simplified-NTP-launch.patch | 28 +- ...-button-in-top-toolbar-customization.patch | 18 +- .../Restore-offline-indicator-v2-flag.patch | 24 +- ...Delete-block-external-form-redirects.patch | 34 +- ...emove-disable-pull-to-refresh-effect.patch | 22 +- ...vert-flags-remove-num-raster-threads.patch | 16 +- ...l-of-execution-context-address-space.patch | 20 +- ...-Note-9-SDK27-crazylinker-workaround.patch | 4 +- ...tings-for-cookies-javascript-and-ads.patch | 10 +- build/patches/Site-setting-for-images.patch | 2 +- .../Switch-to-fstack-protector-strong.patch | 2 +- build/patches/Timezone-customization.patch | 46 +- .../Use-4-tile-rows-never-show-logo.patch | 4 +- .../Use-64-bit-WebView-processes.patch | 2 +- build/patches/User-agent-customization.patch | 114 +- .../Viewport-Protection-Site-Setting.patch | 6 +- build/patches/Viewport-Protection-flag.patch | 73 +- build/patches/Welcome-screen.patch | 50 +- build/patches/autofill-miscellaneous.patch | 66 +- build/patches/bromite-build-utils.patch | 8 +- ...build-remove-calling-untrusted-hooks.patch | 21 +- .../disable-WebView-variations-support.patch | 2 +- .../enable-ftrivial-auto-var-init-zero.patch | 2 +- .../eyeo-117.0.5938.0-android_api.patch | 6282 ++ ... eyeo-117.0.5938.0-android_settings.patch} | 392 +- ...ase.patch => eyeo-117.0.5938.0-base.patch} | 54378 +++++++--------- ...eyeo-117.0.5938.0-chrome_integration.patch | 8165 +++ ... => eyeo-117.0.5938.0-extension_api.patch} | 1537 +- ...t_run-deactivate-autoupdate-globally.patch | 2 +- build/patches/kill-Vision.patch | 4 +- ...nH264-enable-ARM-ARM64-optimizations.patch | 17 +- ...gled-chromium-Disable-profile-avatar.patch | 21 +- ...romium-Disable-translate-integration.patch | 14 +- ...ed-chromium-Disable-untraceable-URLs.patch | 30 +- ...ed-chromium-no-special-hosts-domains.patch | 85 +- ...iew-Hard-no-to-persistent-histograms.patch | 2 +- 222 files changed, 40801 insertions(+), 36142 deletions(-) delete mode 100644 build/patches/00WIN-ADDTO-AImageReader-CFI-crash-mitigations.patch delete mode 100644 build/patches/00WIN-ADDTO-Add-AllowUserCertificates-flag.patch delete mode 100644 build/patches/00WIN-ADDTO-Add-a-proxy-configuration-page.patch delete mode 100644 build/patches/00WIN-ADDTO-Add-bookmark-import-export-actions.patch delete mode 100644 build/patches/00WIN-ADDTO-Disable-requests-for-single-word-Omni.patch delete mode 100644 build/patches/00WIN-ADDTO-Disable-various-metrics.patch delete mode 100644 build/patches/00WIN-ADDTO-Do-not-build-API-keys-infobar.patch delete mode 100644 build/patches/00WIN-ADDTO-Experimental-user-scripts-support.patch delete mode 100644 build/patches/00WIN-ADDTO-Logcat-crash-reports-UI.patch delete mode 100644 build/patches/00WIN-ADDTO-Restore-Search-Ready-Omnibox-flag.patch delete mode 100644 build/patches/00WIN-ADDTO-Revert-flags--remove-num-raster-thre.patch delete mode 100644 build/patches/00WIN-ADDTO-openH264--enable-ARM-ARM64-optimizati.patch delete mode 100644 build/patches/00WIN-ADDTO-ungoogled-chr--Disable-profile-avatar.patch create mode 100644 build/patches/eyeo-117.0.5938.0-android_api.patch rename build/patches/{eyeo-beta-114.0.5735.53-v1-android_settings.patch => eyeo-117.0.5938.0-android_settings.patch} (93%) rename build/patches/{eyeo-beta-114.0.5735.53-v1-base.patch => eyeo-117.0.5938.0-base.patch} (84%) create mode 100644 build/patches/eyeo-117.0.5938.0-chrome_integration.patch rename build/patches/{eyeo-beta-114.0.5735.53-v1-extension_api.patch => eyeo-117.0.5938.0-extension_api.patch} (87%) diff --git a/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch b/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch index 40324b0f..bf37cee2 100644 --- a/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch +++ b/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 30 May 2023 15:45:59 +0000 Subject: 114 temp disable find_bad_constructs external repo +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- build/config/android/rules.gni | 1 + crypto/BUILD.gn | 1 + @@ -12,7 +13,7 @@ Subject: 114 temp disable find_bad_constructs external repo diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni -@@ -4950,6 +4950,7 @@ if (enable_java_templates && is_android) { +@@ -4989,6 +4989,7 @@ if (enable_java_templates && is_android) { _module_build_config = _module.build_config _module_build_config_target = _module.build_config_target _module_target_name = get_label_info(_module_target, "name") @@ -34,7 +35,7 @@ diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn diff --git a/net/BUILD.gn b/net/BUILD.gn --- a/net/BUILD.gn +++ b/net/BUILD.gn -@@ -1653,6 +1653,7 @@ component("net") { +@@ -1657,6 +1657,7 @@ component("net") { configs -= [ "//build/config/compiler:default_optimization" ] configs += [ "//build/config/compiler:optimize_max" ] } diff --git a/build/patches/00Add-a-flag-to-disable-GamePad-API.patch b/build/patches/00Add-a-flag-to-disable-GamePad-API.patch index 708ab899..73999974 100644 --- a/build/patches/00Add-a-flag-to-disable-GamePad-API.patch +++ b/build/patches/00Add-a-flag-to-disable-GamePad-API.patch @@ -3,6 +3,7 @@ Date: Fri, 21 Apr 2023 13:10:20 +0000 Subject: Add a flag to disable GamePad API Adds restrict-gamepad-access flag (default active) to disable GamePad API. +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/flag-metadata.json | 4 ++-- chrome/browser/flag_descriptions.cc | 2 +- @@ -13,7 +14,7 @@ Adds restrict-gamepad-access flag (default active) to disable GamePad API. diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -6842,9 +6842,9 @@ +@@ -7094,9 +7094,9 @@ "expiry_milestone": 117 }, { @@ -28,7 +29,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -2984,7 +2984,7 @@ const char kReduceAcceptLanguageDescription[] = +@@ -3038,7 +3038,7 @@ const char kReduceAcceptLanguageDescription[] = const char kRestrictGamepadAccessName[] = "Restrict gamepad access"; const char kRestrictGamepadAccessDescription[] = @@ -41,7 +42,7 @@ diff --git a/device/gamepad/public/cpp/gamepad_features.cc b/device/gamepad/publ --- a/device/gamepad/public/cpp/gamepad_features.cc +++ b/device/gamepad/public/cpp/gamepad_features.cc @@ -27,8 +27,8 @@ BASE_FEATURE(kEnableWindowsGamingInputDataFetcher, - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kRestrictGamepadAccess, - "RestrictGamepadAccess", diff --git a/build/patches/00Add-option-to-disable-snapshots.patch b/build/patches/00Add-option-to-disable-snapshots.patch index 982d6d35..6ab7c1d8 100644 --- a/build/patches/00Add-option-to-disable-snapshots.patch +++ b/build/patches/00Add-option-to-disable-snapshots.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 21 Aug 2023 14:03:25 +0000 Subject: Add option to disable snapshots +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../tab_management/TabGridViewBinder.java | 8 +++- .../java/res/xml/privacy_preferences.xml | 5 +++ @@ -14,7 +15,7 @@ Subject: Add option to disable snapshots diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java -@@ -314,8 +314,12 @@ class TabGridViewBinder { +@@ -315,8 +315,12 @@ class TabGridViewBinder { updateThumbnailMatrix(thumbnail, result, thumbnailSize); thumbnail.setImageBitmap(result); } else if (isMostRecentRequest) { @@ -47,18 +48,18 @@ diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/androi diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java -@@ -144,6 +144,7 @@ import org.chromium.chrome.browser.page_info.ChromePageInfoHighlight; - import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; +@@ -146,6 +146,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.Pref; + import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.printing.TabPrinter; +import org.chromium.chrome.browser.privacy.settings.PrivacySettings; import org.chromium.chrome.browser.profiles.Profile; + import org.chromium.chrome.browser.readaloud.ReadAloudController; import org.chromium.chrome.browser.selection.SelectionPopupBackPressHandler; - import org.chromium.chrome.browser.settings.SettingsLauncherImpl; -@@ -642,7 +643,7 @@ public abstract class ChromeActivity +@@ -657,7 +658,7 @@ public abstract class ChromeActivity TabModelSelector tabModelSelector = mTabModelOrchestrator.getTabModelSelector(); - setTabContentManager(new TabContentManager(this, getContentOffsetProvider(), + setTabContentManager(new TabContentManager(this, mBrowserControlsManagerSupplier.get(), - !SysUtils.isLowEndDevice(), + !ContextUtils.getAppSharedPreferences().getBoolean(PrivacySettings.PREF_TABGRID_USE_ICONS, false), tabModelSelector != null ? tabModelSelector::getTabById : null)); @@ -67,7 +68,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java -@@ -331,9 +331,12 @@ public class TabContentManager { +@@ -333,9 +333,12 @@ public class TabContentManager { * @param forceUpdate Whether to obtain the thumbnail from the live content. * @param writeBack When {@code forceUpdate}, whether to write the thumbnail to cache. */ @@ -114,7 +115,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting private static final String PREF_CAN_MAKE_PAYMENT = "can_make_payment"; private static final String PREF_PRELOAD_PAGES = "preload_pages"; private static final String PREF_HTTPS_FIRST_MODE = "https_first_mode"; -@@ -147,6 +160,21 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -145,6 +158,21 @@ public class PrivacySettings extends PreferenceFragmentCompat }); } @@ -136,7 +137,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting Preference privacyGuidePreference = findPreference(PREF_PRIVACY_GUIDE); // Record the launch of PG from the S&P link-row entry point privacyGuidePreference.setOnPreferenceClickListener(preference -> { -@@ -297,6 +325,7 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -293,6 +321,7 @@ public class PrivacySettings extends PreferenceFragmentCompat public static final String PREF_ALLOW_CUSTOM_TAB_INTENTS = "allow_custom_tab_intents"; public static final String PREF_OPEN_EXTERNAL_LINKS_INCOGNITO = "open_external_links_incognito"; @@ -144,7 +145,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting @Override public boolean onPreferenceChange(Preference preference, Object newValue) { -@@ -320,6 +349,13 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -316,6 +345,13 @@ public class PrivacySettings extends PreferenceFragmentCompat SharedPreferences.Editor sharedPreferencesEditor = ContextUtils.getAppSharedPreferences().edit(); sharedPreferencesEditor.putBoolean(PREF_OPEN_EXTERNAL_LINKS_INCOGNITO, (boolean)newValue); sharedPreferencesEditor.apply(); @@ -158,7 +159,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting } return true; } -@@ -360,6 +396,10 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -356,6 +392,10 @@ public class PrivacySettings extends PreferenceFragmentCompat : R.string.text_off); } @@ -172,7 +173,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -5239,6 +5239,14 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

%1$swww.amazon.com timer ran out. It'll start again tomorrow. diff --git a/build/patches/00Add-setting-to-clear-data-on-exit.patch b/build/patches/00Add-setting-to-clear-data-on-exit.patch index 6cc845b9..c483feee 100644 --- a/build/patches/00Add-setting-to-clear-data-on-exit.patch +++ b/build/patches/00Add-setting-to-clear-data-on-exit.patch @@ -2,6 +2,7 @@ From: uazo Date: Thu, 16 Feb 2023 15:28:16 +0000 Subject: Add setting to clear data on exit +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/android/chrome_java_sources.gni | 1 + .../chrome/browser/ChromeTabbedActivity.java | 7 +- @@ -33,7 +34,7 @@ Subject: Add setting to clear data on exit diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -289,6 +289,7 @@ chrome_java_sources = [ +@@ -300,6 +300,7 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentAdvanced.java", "java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasic.java", "java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataTabsFragment.java", @@ -44,7 +45,7 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -140,6 +140,7 @@ import org.chromium.chrome.browser.profiles.ProfileManager; +@@ -141,6 +141,7 @@ import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.quick_delete.QuickDeleteController; import org.chromium.chrome.browser.quick_delete.QuickDeleteDelegateImpl; import org.chromium.chrome.browser.quick_delete.QuickDeleteMetricsDelegate; @@ -52,7 +53,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.read_later.ReadingListBackPressHandler; import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.chrome.browser.reengagement.ReengagementNotificationController; -@@ -1283,7 +1284,11 @@ public class ChromeTabbedActivity extends ChromeActivity Clear browsing data @@ -240,7 +241,7 @@ diff --git a/chrome/browser/android/browsing_data/browsing_data_bridge.cc b/chro diff --git a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc --- a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc -@@ -326,8 +326,25 @@ void ChromeBrowsingDataLifetimeManager::Shutdown() { +@@ -329,8 +329,25 @@ void ChromeBrowsingDataLifetimeManager::Shutdown() { void ChromeBrowsingDataLifetimeManager::ClearBrowsingDataForOnExitPolicy( bool keep_browser_alive) { @@ -268,7 +269,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager. if (!data_types.empty() && IsConditionSatisfiedForBrowsingDataRemoval(GetSyncTypesForPolicyPref( -@@ -427,6 +444,7 @@ void ChromeBrowsingDataLifetimeManager::StartScheduledBrowsingDataRemoval() { +@@ -439,6 +456,7 @@ void ChromeBrowsingDataLifetimeManager::StartScheduledBrowsingDataRemoval() { bool ChromeBrowsingDataLifetimeManager:: IsConditionSatisfiedForBrowsingDataRemoval( const syncer::UserSelectableTypeSet sync_types) { @@ -279,7 +280,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager. diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc -@@ -419,6 +419,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( +@@ -426,6 +426,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( delete_end_, CreateTaskCompletionClosure(TracingDataType::kHistory), &history_task_tracker_); } @@ -289,7 +290,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate. if (ClipboardRecentContent::GetInstance()) ClipboardRecentContent::GetInstance()->SuppressClipboardContent(); -@@ -469,7 +472,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( +@@ -476,7 +479,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( prerender::NoStatePrefetchManager::CLEAR_PRERENDER_CONTENTS | prerender::NoStatePrefetchManager::CLEAR_PRERENDER_HISTORY); } @@ -299,7 +300,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate. // The saved Autofill profiles and credit cards can include the origin from // which these profiles and credit cards were learned. These are a form of // history, so clear them as well. -@@ -490,7 +495,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( +@@ -497,7 +502,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( if (data_manager) data_manager->Refresh(); } @@ -309,7 +310,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate. base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, base::BindOnce( -@@ -565,9 +572,13 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( +@@ -572,9 +579,13 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( } device_event_log::Clear(delete_begin_, delete_end_); @@ -326,7 +327,7 @@ diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate. diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc -@@ -500,6 +500,23 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { +@@ -506,6 +506,23 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { (*s_allowlist)[browsing_data::prefs::kLastClearBrowsingDataTab] = settings_api::PrefType::PREF_TYPE_NUMBER; @@ -383,7 +384,7 @@ diff --git a/chrome/browser/profiles/android/profile_manager_utils.cc b/chrome/b diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc -@@ -1444,6 +1444,19 @@ void ProfileManager::DoFinalInit(ProfileInfo* profile_info, +@@ -1449,6 +1449,19 @@ void ProfileManager::DoFinalInit(ProfileInfo* profile_info, } } @@ -406,7 +407,7 @@ diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profile diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h --- a/chrome/browser/profiles/profile_manager.h +++ b/chrome/browser/profiles/profile_manager.h -@@ -198,6 +198,8 @@ class ProfileManager : public Profile::Delegate { +@@ -202,6 +202,8 @@ class ProfileManager : public Profile::Delegate { // profiles. std::vector GetLoadedProfiles() const; @@ -483,7 +484,7 @@ diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1582,6 +1582,9 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1609,6 +1609,9 @@ Your Google account may have other forms of browsing history like searches and a Basic @@ -496,7 +497,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc -@@ -1771,6 +1771,7 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, +@@ -1813,6 +1813,7 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, {"clearedData", IDS_SETTINGS_CLEARED_DATA}, {"clearBrowsingData", IDS_SETTINGS_CLEAR_BROWSING_DATA}, {"clearBrowsingDataDescription", IDS_SETTINGS_CLEAR_DATA_DESCRIPTION}, @@ -555,7 +556,7 @@ diff --git a/components/browsing_data/core/browsing_data_policies_utils.h b/comp diff --git a/components/browsing_data/core/browsing_data_utils.cc b/components/browsing_data/core/browsing_data_utils.cc --- a/components/browsing_data/core/browsing_data_utils.cc +++ b/components/browsing_data/core/browsing_data_utils.cc -@@ -318,6 +318,40 @@ bool GetDeletionPreferenceFromDataType( +@@ -327,6 +327,40 @@ bool GetDeletionPreferenceFromDataType( BrowsingDataType data_type, ClearBrowsingDataTab clear_browsing_data_tab, std::string* out_pref) { diff --git a/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch b/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch index 767538d7..329c1ecb 100644 --- a/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch +++ b/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch @@ -4,6 +4,8 @@ Subject: Add setting to invert tap and long tap Reverses single tap to long tap in android for accessibility reasons. The feature can be activated from the accessibility settings. + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/android/java/res/values/ids.xml | 1 + .../ChromeAccessibilitySettingsDelegate.java | 18 ++++++++++ @@ -72,7 +74,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/s diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java -@@ -89,8 +89,9 @@ class ChromeContextMenuItem { +@@ -88,8 +88,9 @@ class ChromeContextMenuItem { int SHARE_HIGHLIGHT = 32; int REMOVE_HIGHLIGHT = 33; int LEARN_MORE = 34; @@ -83,7 +85,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr } /** -@@ -132,6 +133,7 @@ class ChromeContextMenuItem { +@@ -131,6 +132,7 @@ class ChromeContextMenuItem { R.id.contextmenu_share_highlight, // Item.SHARE_HIGHLIGHT R.id.contextmenu_remove_highlight, // Item.REMOVE_HIGHLIGHT R.id.contextmenu_learn_more, // Item.LEARN_MORE @@ -91,7 +93,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr }; /** -@@ -173,6 +175,7 @@ class ChromeContextMenuItem { +@@ -172,6 +174,7 @@ class ChromeContextMenuItem { R.string.contextmenu_share_highlight, // Item.SHARE_HIGHLIGHT R.string.contextmenu_remove_highlight, // Item.REMOVE_HIGHLIGHT R.string.contextmenu_learn_more, // Item.LEARN_MORE @@ -102,7 +104,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java -@@ -240,6 +240,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { +@@ -239,6 +239,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { if (mParams.isAnchor()) { ModelList linkGroup = new ModelList(); @@ -112,7 +114,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr if (FirstRunStatus.getFirstRunFlowComplete() && !isEmptyUrl(mParams.getUrl()) && UrlUtilities.isAcceptedScheme(mParams.getUrl())) { if (mMode == ContextMenuMode.NORMAL) { -@@ -598,6 +601,8 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { +@@ -588,6 +591,8 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { ShareHelper.shareDirectly( params, ShareHelper.getLastShareComponentName(), getProfile(), false); }); @@ -142,18 +144,18 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextM diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -7921,6 +7921,11 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kMoveTopToolbarToBottomDescription, kOsAndroid, - FEATURE_VALUE_TYPE(features::kMoveTopToolbarToBottom)}, +@@ -8085,6 +8085,11 @@ const FeatureEntry kFeatureEntries[] = { + FEATURE_VALUE_TYPE(features::kElasticOverscroll)}, + #endif + {"show-always-context-menu-on-links", + flag_descriptions::kShowAlwaysContextMenuOnLinksName, + flag_descriptions::kShowAlwaysContextMenuOnLinksDescription, kOsAndroid, + FEATURE_VALUE_TYPE(blink::features::kShowAlwaysContextMenuOnLinks)}, + - {"scroll-unification", flag_descriptions::kScrollUnificationName, - flag_descriptions::kScrollUnificationDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kScrollUnification)}, + {"device-posture", flag_descriptions::kDevicePostureName, + flag_descriptions::kDevicePostureDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kDevicePosture)}, diff --git a/chrome/browser/contextmenu/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java b/chrome/browser/contextmenu/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java --- a/chrome/browser/contextmenu/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java +++ b/chrome/browser/contextmenu/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java @@ -169,7 +171,7 @@ diff --git a/chrome/browser/contextmenu/java/src/org/chromium/chrome/browser/con diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1970,6 +1970,10 @@ const char kMoveTopToolbarToBottomName[] = "Move top toolbar to bottom"; +@@ -2002,6 +2002,10 @@ const char kMoveTopToolbarToBottomName[] = "Move top toolbar to bottom"; const char kMoveTopToolbarToBottomDescription[] = "Move the top toolbar to the bottom."; @@ -183,7 +185,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1104,6 +1104,9 @@ extern const char kImprovedKeyboardShortcutsDescription[]; +@@ -1132,6 +1132,9 @@ extern const char kImprovedKeyboardShortcutsDescription[]; extern const char kMoveTopToolbarToBottomName[]; extern const char kMoveTopToolbarToBottomDescription[]; @@ -196,10 +198,10 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -314,6 +314,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -320,6 +320,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { + &kTabGroupsAndroid, &kTabGroupsContinuationAndroid, &kTabGroupsForTablets, - &kDiscoverFeedMultiColumn, + &blink::features::kShowAlwaysContextMenuOnLinks, &kTabStripRedesign, &kTabletToolbarReordering, @@ -207,7 +209,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -312,6 +312,8 @@ public abstract class ChromeFeatureList { +@@ -317,6 +317,8 @@ public abstract class ChromeFeatureList { public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid"; public static final String MOVE_TOP_TOOLBAR_TO_BOTTOM = "MoveTopToolbarToBottom"; @@ -216,7 +218,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant"; public static final String NOTIFICATION_PERMISSION_BOTTOM_SHEET = "NotificationPermissionBottomSheet"; -@@ -571,6 +573,8 @@ public abstract class ChromeFeatureList { +@@ -578,6 +580,8 @@ public abstract class ChromeFeatureList { new CachedFlag(OMNIBOX_MATCH_TOOLBAR_AND_STATUS_BAR_COLOR, false); public static final CachedFlag sMoveTopToolbarToBottom = new CachedFlag(MOVE_TOP_TOOLBAR_TO_BOTTOM, false); @@ -225,7 +227,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final CachedFlag sOmniboxModernizeVisualUpdate = new CachedFlag(OMNIBOX_MODERNIZE_VISUAL_UPDATE, false); public static final CachedFlag sOmniboxMostVisitedTilesAddRecycledViewPool = -@@ -693,6 +697,7 @@ public abstract class ChromeFeatureList { +@@ -701,6 +705,7 @@ public abstract class ChromeFeatureList { sTabStripRedesign, sTabStripStartupRefactoring, sTabletToolbarReordering, @@ -236,7 +238,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1749,6 +1749,12 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1776,6 +1776,12 @@ Your Google account may have other forms of browsing history like searches and a Move toolbar to bottom @@ -249,7 +251,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro -@@ -2750,6 +2756,9 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

Open in new Chrome tab @@ -331,7 +333,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -217,6 +217,10 @@ BASE_FEATURE(kBackgroundResourceFetch, +@@ -227,6 +227,10 @@ BASE_FEATURE(kBackgroundResourceFetch, "BackgroundResourceFetch", base::FEATURE_DISABLED_BY_DEFAULT); @@ -345,7 +347,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -127,6 +127,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheWithKeepaliveRequest); +@@ -134,6 +134,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheWithKeepaliveRequest); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackgroundResourceFetch); @@ -365,7 +367,7 @@ diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -@@ -436,6 +437,17 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, +@@ -446,6 +447,17 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, bool is_trusted, base::TimeTicks platform_time_stamp, KURL completed_url) { @@ -383,8 +385,8 @@ diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third LocalDOMWindow* window = GetDocument().domWindow(); if (!window) { return; -@@ -489,6 +501,15 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, - /*element=*/this)); +@@ -499,6 +511,15 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, + /*element=*/this, request.HasUserGesture())); } + if (!do_not_show_context_menu && @@ -399,7 +401,7 @@ diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third Frame* target_frame = frame->Tree().FindOrCreateFrameForNavigation(frame_request, target).frame; -@@ -508,7 +529,7 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, +@@ -518,7 +539,7 @@ void HTMLAnchorElement::NavigateToHyperlink(ResourceRequest request, } } @@ -408,7 +410,7 @@ diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third event.SetDefaultHandled(); LocalDOMWindow* window = GetDocument().domWindow(); -@@ -607,12 +628,12 @@ void HTMLAnchorElement::HandleClick(Event& event) { +@@ -617,12 +638,12 @@ void HTMLAnchorElement::HandleClick(Event& event) { } NavigationPolicy navigation_policy = NavigationPolicyFromEvent(&event); @@ -425,7 +427,7 @@ diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third // If Alt is held down it will force a download, however, wait to see if // this is an alt-double-click which should instead select the text of the // link. -@@ -624,7 +645,9 @@ void HTMLAnchorElement::HandleClick(Event& event) { +@@ -634,7 +655,9 @@ void HTMLAnchorElement::HandleClick(Event& event) { frame->GetEventHandler().SetDownloadModifierTaskHandle( std::move(task_handle)); } else { @@ -477,7 +479,7 @@ diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_ #include "third_party/blink/renderer/core/frame/attribution_src_loader.h" #include "third_party/blink/renderer/core/frame/deprecation/deprecation.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" -@@ -62,6 +63,7 @@ +@@ -63,6 +64,7 @@ #include "third_party/blink/renderer/core/media_type_names.h" #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" @@ -485,7 +487,7 @@ diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_ #include "third_party/blink/renderer/core/paint/timing/paint_timing.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/style/content_data.h" -@@ -718,6 +720,21 @@ void HTMLImageElement::DidFinishLifecycleUpdate( +@@ -744,6 +746,21 @@ void HTMLImageElement::DidFinishLifecycleUpdate( } } @@ -510,7 +512,7 @@ diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_ diff --git a/third_party/blink/renderer/core/html/html_image_element.h b/third_party/blink/renderer/core/html/html_image_element.h --- a/third_party/blink/renderer/core/html/html_image_element.h +++ b/third_party/blink/renderer/core/html/html_image_element.h -@@ -217,6 +217,8 @@ class CORE_EXPORT HTMLImageElement final +@@ -220,6 +220,8 @@ class CORE_EXPORT HTMLImageElement final void DidAddUserAgentShadowRoot(ShadowRoot&) override; void AdjustStyle(ComputedStyleBuilder&) override; @@ -522,7 +524,7 @@ diff --git a/third_party/blink/renderer/core/html/html_image_element.h b/third_p diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc -@@ -171,14 +171,16 @@ void ContextMenuController::DocumentDetached(Document* document) { +@@ -226,14 +226,16 @@ void ContextMenuController::DocumentDetached(Document* document) { } } @@ -542,7 +544,7 @@ diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/t mouse_event->SetDefaultHandled(); } -@@ -414,7 +416,8 @@ bool ContextMenuController::ShouldShowContextMenuFromTouch( +@@ -451,7 +453,8 @@ bool ContextMenuController::ShouldShowContextMenuFromTouch( bool ContextMenuController::ShowContextMenu(LocalFrame* frame, const PhysicalOffset& point, WebMenuSourceType source_type, @@ -552,7 +554,7 @@ diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/t // Displaying the context menu in this function is a big hack as we don't // have context, i.e. whether this is being invoked via a script or in // response to user input (Mouse event WM_RBUTTONDOWN, -@@ -437,6 +440,15 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame, +@@ -474,6 +477,15 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame, if (!result.InnerNodeOrImageMapImage()) return false; @@ -568,7 +570,7 @@ diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/t // Clear any previously set cached results if we are resetting the hit test // result. image_selection_cached_result_ = nullptr; -@@ -790,11 +802,13 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame, +@@ -827,11 +839,13 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame, data.form_renderer_id = GetFormRendererId(result); data.field_renderer_id = GetFieldRendererId(result); diff --git a/build/patches/00Allow-DocumentPiP-if-PopupsAndRedirects-are-active.patch b/build/patches/00Allow-DocumentPiP-if-PopupsAndRedirects-are-active.patch index 3e862b67..70c5841b 100644 --- a/build/patches/00Allow-DocumentPiP-if-PopupsAndRedirects-are-active.patch +++ b/build/patches/00Allow-DocumentPiP-if-PopupsAndRedirects-are-active.patch @@ -3,6 +3,8 @@ Date: Mon, 7 Aug 2023 11:02:18 +0000 Subject: Allow DocumentPiP if PopupsAndRedirects are active Allow documentPiP api use only with content setting popup allowed + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../picture_in_picture_controller_impl.cc | 7 +++++++ 1 file changed, 7 insertions(+) @@ -10,7 +12,7 @@ Allow documentPiP api use only with content setting popup allowed diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc --- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc +++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc -@@ -361,6 +361,13 @@ void PictureInPictureControllerImpl::CreateDocumentPictureInPictureWindow( +@@ -370,6 +370,13 @@ void PictureInPictureControllerImpl::CreateDocumentPictureInPictureWindow( return; } diff --git a/build/patches/00Clear-CORS-Preflight-Cache-on-clearing-data.patch b/build/patches/00Clear-CORS-Preflight-Cache-on-clearing-data.patch index 3147ba59..05b542c2 100644 --- a/build/patches/00Clear-CORS-Preflight-Cache-on-clearing-data.patch +++ b/build/patches/00Clear-CORS-Preflight-Cache-on-clearing-data.patch @@ -2,6 +2,7 @@ From: uazo Date: Wed, 19 Apr 2023 09:59:18 +0000 Subject: Clear CORS Preflight Cache on clearing data +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- services/network/cors/preflight_cache.cc | 4 ++++ services/network/cors/preflight_cache.h | 2 ++ @@ -40,7 +41,7 @@ diff --git a/services/network/cors/preflight_cache.h b/services/network/cors/pre diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc -@@ -674,6 +674,10 @@ void PreflightController::ClearCorsPreflightCache( +@@ -803,6 +803,10 @@ void PreflightController::ClearCorsPreflightCache( cache_.ClearCache(std::move(url_filter)); } @@ -54,9 +55,9 @@ diff --git a/services/network/cors/preflight_controller.cc b/services/network/co diff --git a/services/network/cors/preflight_controller.h b/services/network/cors/preflight_controller.h --- a/services/network/cors/preflight_controller.h +++ b/services/network/cors/preflight_controller.h -@@ -139,6 +139,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final { - const net::NetLogWithSource& net_log, - bool acam_preflight_spec_conformant); +@@ -141,6 +141,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final { + mojo::PendingRemote + url_loader_network_service_observer); + void ClearCache(); + @@ -78,7 +79,7 @@ diff --git a/services/network/cors/preflight_result.cc b/services/network/cors/p diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -1070,6 +1070,8 @@ void NetworkContext::ClearHttpCache(base::Time start_time, +@@ -1084,6 +1084,8 @@ void NetworkContext::ClearHttpCache(base::Time start_time, base::BindOnce(&NetworkContext::OnHttpCacheCleared, base::Unretained(this), std::move(callback)))); diff --git a/build/patches/00Compress-libchrome-to-free-up-some-space.patch b/build/patches/00Compress-libchrome-to-free-up-some-space.patch index 51fc6c9a..ab2608ce 100644 --- a/build/patches/00Compress-libchrome-to-free-up-some-space.patch +++ b/build/patches/00Compress-libchrome-to-free-up-some-space.patch @@ -4,6 +4,8 @@ Subject: Compress libchrome to free up some space upstream removed ModernLinker support for developer build (apk releases). see https://bugs.chromium.org/p/chromium/issues/detail?id=1383210 + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/android/chrome_public_apk_tmpl.gni | 1 + 1 file changed, 1 insertion(+) @@ -11,7 +13,7 @@ see https://bugs.chromium.org/p/chromium/issues/detail?id=1383210 diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni -@@ -632,6 +632,7 @@ template("chrome_common_apk_or_module_tmpl") { +@@ -637,6 +637,7 @@ template("chrome_common_apk_or_module_tmpl") { [ "//components/crash/core/app:chrome_crashpad_handler_named_as_so" ] loadable_modules += [ "$root_out_dir/libchrome_crashpad_handler.so" ] library_always_compress += [ "libchrome_crashpad_handler.so" ] diff --git a/build/patches/00Cromite-Branding.patch b/build/patches/00Cromite-Branding.patch index e78757ec..b75ce82c 100644 --- a/build/patches/00Cromite-Branding.patch +++ b/build/patches/00Cromite-Branding.patch @@ -2,6 +2,7 @@ From: uazo Date: Wed, 19 Jul 2023 12:37:39 +0000 Subject: Cromite Branding +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- build/BUILD.gn | 8 ++++ build/config/BUILDCONFIG.gn | 4 ++ @@ -81,7 +82,7 @@ diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml -@@ -172,7 +172,7 @@ by a child template that "extends" this file. +@@ -170,7 +170,7 @@ by a child template that "extends" this file. No description provided @@ -503,7 +503,7 @@ - Extensions + My extensions - -- Open Chrome Web Store -+ Open Chromedontreplace Web Store + +- Discover more extensions and themes on the <a target="_blank" href="$1">Chrome Web Store</a> </a> ++ Discover more extensions and themes on the <a target="_blank" href="$1">Chromedontreplace Web Store</a> </a> Keyboard shortcuts diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp -@@ -255,7 +255,7 @@ +@@ -263,7 +263,7 @@ Change @@ -13122,7 +13123,7 @@ e)fqMZZ`3a)Ds&5H CreateProfilePrefStoreManager( +@@ -304,10 +305,7 @@ std::unique_ptr CreateProfilePrefStoreManager( #endif std::string seed; CHECK(ui::ResourceBundle::HasSharedInstance()); @@ -13184,7 +13185,7 @@ diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -2152,7 +2152,7 @@ Your Google account may have other forms of browsing history like searches and a +@@ -2185,7 +2185,7 @@ Your Google account may have other forms of browsing history like searches and a About Chrome diff --git a/build/patches/00Deprecate-Data-URL-in-SVGUseElement.patch b/build/patches/00Deprecate-Data-URL-in-SVGUseElement.patch index ba5edd74..9504dfb1 100644 --- a/build/patches/00Deprecate-Data-URL-in-SVGUseElement.patch +++ b/build/patches/00Deprecate-Data-URL-in-SVGUseElement.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 5 Jun 2023 17:02:33 +0000 Subject: Deprecate Data URL in SVGUseElement +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../blink/renderer/platform/runtime_enabled_features.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) @@ -9,7 +10,7 @@ Subject: Deprecate Data URL in SVGUseElement diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2967,8 +2967,8 @@ +@@ -2974,8 +2974,8 @@ base_feature: "none", }, { @@ -19,6 +20,6 @@ diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 + status: "stable", // by default }, { - name: "RemoveLegacySizeComputation", + name: "RemoveMobileViewportDoubleTap", -- 2.25.1 diff --git a/build/patches/00Disable-BackForwardCache.patch b/build/patches/00Disable-BackForwardCache.patch index 56541854..e4936a6c 100644 --- a/build/patches/00Disable-BackForwardCache.patch +++ b/build/patches/00Disable-BackForwardCache.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Tue, 14 Feb 2023 16:29:12 +0000 Subject: Disable BackForwardCache +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- content/public/common/content_features.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -9,7 +10,7 @@ Subject: Disable BackForwardCache diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -97,9 +97,9 @@ BASE_FEATURE(kBackgroundFetch, +@@ -109,9 +109,9 @@ BASE_FEATURE(kBackgroundFetch, base::FEATURE_ENABLED_BY_DEFAULT); // Enable using the BackForwardCache. diff --git a/build/patches/00Disable-Compression-Dictionary-Transport.patch b/build/patches/00Disable-Compression-Dictionary-Transport.patch index 52734599..49a06f1b 100644 --- a/build/patches/00Disable-Compression-Dictionary-Transport.patch +++ b/build/patches/00Disable-Compression-Dictionary-Transport.patch @@ -2,29 +2,30 @@ From: uazo Date: Sat, 3 Jun 2023 15:04:55 +0000 Subject: Disable Compression Dictionary Transport +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - .../renderer/platform/runtime_enabled_features.json5 | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) + .../blink/renderer/platform/runtime_enabled_features.json5 | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -670,16 +670,16 @@ - status: "experimental", +@@ -680,16 +680,18 @@ + status: "stable", }, { - name: "CompressionDictionaryTransport", -- base_feature_status: "enabled", -- copied_from_base_feature_if: "overridden", + name: "CompressionDictionaryTransport", // need to be disabled + base_feature: "none", origin_trial_feature_name: "CompressionDictionaryTransport", + origin_trial_allows_third_party: true, public: true, + status: "experimental", }, { - name: "CompressionDictionaryTransportBackend", + name: "CompressionDictionaryTransportBackend", // need to be disabled - base_feature_status: "disabled", + base_feature: "none", public: true, + status: "experimental", }, diff --git a/build/patches/00Disable-FedCm.patch b/build/patches/00Disable-FedCm.patch index bfd73df0..1492d255 100644 --- a/build/patches/00Disable-FedCm.patch +++ b/build/patches/00Disable-FedCm.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Tue, 14 Feb 2023 16:26:17 +0000 Subject: Disable FedCm +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- content/public/common/content_features.cc | 10 +++++----- .../renderer/platform/runtime_enabled_features.json5 | 2 +- @@ -10,7 +11,7 @@ Subject: Disable FedCm diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -389,7 +389,7 @@ BASE_FEATURE(kExtraSafelistedRequestHeadersForOutOfBlinkCors, +@@ -387,7 +387,7 @@ BASE_FEATURE(kExtraSafelistedRequestHeadersForOutOfBlinkCors, // by the flag in RuntimeEnabledFeatures on the blink side. See also // the use of kSetOnlyIfOverridden in content/child/runtime_features.cc. // We enable it here by default to support use in origin trials. @@ -19,7 +20,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c // Field trial boolean parameter which indicates whether FedCM IDP sign-out // is enabled. -@@ -453,15 +453,15 @@ BASE_FEATURE(kFedCmLoginHint, +@@ -421,15 +421,15 @@ BASE_FEATURE(kFedCmSelectiveDisclosure, // Enables metrics collection for signin status mismatches. Also enables // parsing the signin status HTTP headers. // kFedCmIdpSigninStatusEnabled takes precedence over this feature flag. @@ -37,12 +38,12 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c - base::FEATURE_DISABLED_BY_DEFAULT); // on bromite + base::FEATURE_ENABLED_BY_DEFAULT); // on bromite - // Enables the MDocs API in the IdentityCredential. - BASE_FEATURE(kWebIdentityMDocs, + // Enables bypassing the well-known file enforcement. + BASE_FEATURE(kFedCmWithoutWellKnownEnforcement, diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -1590,7 +1590,7 @@ +@@ -1560,7 +1560,7 @@ { name: "FedCm", public: true, diff --git a/build/patches/00Disable-Feeback-Collector.patch b/build/patches/00Disable-Feeback-Collector.patch index 22f49f85..e3198574 100644 --- a/build/patches/00Disable-Feeback-Collector.patch +++ b/build/patches/00Disable-Feeback-Collector.patch @@ -2,6 +2,7 @@ From: uazo Date: Sat, 22 Jul 2023 13:58:40 +0000 Subject: Disable Feeback Collector +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../browser/feedback/FeedbackCollector.java | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) @@ -32,7 +33,7 @@ diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browse - identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)); - } - -- // Sanity check in case a source is added to the wrong list. +- // Validation check in case a source is added to the wrong list. - for (FeedbackSource source : mSynchronousSources) { - assert !(source instanceof AsyncFeedbackSource); - } diff --git a/build/patches/00Disable-FirstPartySets-and-StorageAccessAPI.patch b/build/patches/00Disable-FirstPartySets-and-StorageAccessAPI.patch index 3aea3daa..973f870b 100644 --- a/build/patches/00Disable-FirstPartySets-and-StorageAccessAPI.patch +++ b/build/patches/00Disable-FirstPartySets-and-StorageAccessAPI.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 2 May 2023 15:26:46 +0000 Subject: Disable FirstPartySets and StorageAccessAPI +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- components/privacy_sandbox/privacy_sandbox_prefs.cc | 2 +- content/public/common/content_features.cc | 6 +++--- @@ -10,7 +11,7 @@ Subject: Disable FirstPartySets and StorageAccessAPI diff --git a/components/privacy_sandbox/privacy_sandbox_prefs.cc b/components/privacy_sandbox/privacy_sandbox_prefs.cc --- a/components/privacy_sandbox/privacy_sandbox_prefs.cc +++ b/components/privacy_sandbox/privacy_sandbox_prefs.cc -@@ -155,7 +155,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { +@@ -58,7 +58,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref( prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized, false); registry->RegisterBooleanPref( @@ -22,7 +23,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_prefs.cc b/components/pr diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -469,9 +469,9 @@ BASE_FEATURE(kWebIdentityMDocs, +@@ -442,9 +442,9 @@ BASE_FEATURE(kWebIdentityMDocs, base::FEATURE_DISABLED_BY_DEFAULT); // Enables usage of First Party Sets to determine cookie availability. diff --git a/build/patches/00Disable-GSA-by-default.patch b/build/patches/00Disable-GSA-by-default.patch index 3077c8b8..92267fde 100644 --- a/build/patches/00Disable-GSA-by-default.patch +++ b/build/patches/00Disable-GSA-by-default.patch @@ -2,6 +2,7 @@ From: uazo Date: Sun, 7 May 2023 14:01:56 +0000 Subject: Disable GSA by default +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../org/chromium/chrome/browser/IntentHandler.java | 5 ----- .../org/chromium/chrome/browser/share/LensUtils.java | 12 +----------- @@ -20,7 +21,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteControllerProvider; import org.chromium.chrome.browser.profiles.Profile; -@@ -265,8 +264,6 @@ public class IntentHandler { +@@ -271,8 +270,6 @@ public class IntentHandler { private static int sReferrerId; private static String sPendingIncognitoUrl; @@ -29,7 +30,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j private static final String PACKAGE_GMAIL = "com.google.android.gm"; private static final String PACKAGE_PLUS = "com.google.android.apps.plus"; private static final String PACKAGE_HANGOUTS = "com.google.android.talk"; -@@ -498,8 +495,6 @@ public class IntentHandler { +@@ -494,8 +491,6 @@ public class IntentHandler { return ExternalAppId.LINE; } else if (packageName.equals(PACKAGE_WHATSAPP)) { return ExternalAppId.WHATSAPP; @@ -41,7 +42,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java --- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java -@@ -11,7 +11,6 @@ import android.text.TextUtils; +@@ -12,7 +12,6 @@ import org.chromium.base.ResettersForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -49,7 +50,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils import org.chromium.components.externalauth.ExternalAuthUtils; /** -@@ -62,12 +61,7 @@ public class LensUtils { +@@ -64,12 +63,7 @@ public class LensUtils { if (context == null) { return ""; } @@ -62,7 +63,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils } } -@@ -119,11 +113,7 @@ public class LensUtils { +@@ -121,11 +115,7 @@ public class LensUtils { * @return Whether the package is valid. */ public static boolean isValidAgsaPackage(final ExternalAuthUtils externalAuthUtils) { @@ -78,7 +79,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -676,8 +676,8 @@ BASE_FEATURE(kContextMenuGoogleLensSearchOptimizations, +@@ -690,8 +690,8 @@ BASE_FEATURE(kContextMenuGoogleLensSearchOptimizations, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kContextMenuSearchWithGoogleLens, @@ -89,7 +90,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse BASE_FEATURE(kContextMenuShopWithGoogleLens, "ContextMenuShopWithGoogleLens", -@@ -758,8 +758,8 @@ BASE_FEATURE(kOfflineIndicatorV2, +@@ -776,8 +776,8 @@ BASE_FEATURE(kOfflineIndicatorV2, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kExperimentsForAgsa, @@ -103,7 +104,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java --- a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java +++ b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java -@@ -33,8 +33,6 @@ import java.util.regex.Pattern; +@@ -34,8 +34,6 @@ import java.util.regex.Pattern; * A class responsible for representing the current state of Chrome's integration with GSA. */ public class GSAState { @@ -112,7 +113,7 @@ diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAStat /** Used to observe state changes in the class. */ public interface Observer { /** Called when the GSA account name is set. */ -@@ -74,7 +72,7 @@ public class GSAState { +@@ -75,7 +73,7 @@ public class GSAState { /** * Caches the result of a computation on whether GSA is available. */ @@ -121,7 +122,7 @@ diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAStat /** * The Google account email address being used by GSA according to the latest update we have -@@ -155,7 +153,7 @@ public class GSAState { +@@ -156,7 +154,7 @@ public class GSAState { /** Returns whether the GSA package is installed on device. */ public boolean isGsaInstalled() { @@ -130,7 +131,7 @@ diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAStat } /** -@@ -178,6 +176,7 @@ public class GSAState { +@@ -179,6 +177,7 @@ public class GSAState { */ public boolean isAgsaVersionBelowMinimum( String installedVersionName, String minimumVersionName) { @@ -138,7 +139,7 @@ diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAStat if (TextUtils.isEmpty(installedVersionName) || TextUtils.isEmpty(minimumVersionName)) { return true; } -@@ -209,7 +208,7 @@ public class GSAState { +@@ -210,7 +209,7 @@ public class GSAState { * @return Whether the given intent can be handled by Agsa. */ public boolean canAgsaHandleIntent(@NonNull Intent intent) { @@ -147,7 +148,7 @@ diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAStat ComponentName activity = intent.resolveActivity(ContextUtils.getApplicationContext().getPackageManager()); -@@ -223,7 +222,7 @@ public class GSAState { +@@ -224,7 +223,7 @@ public class GSAState { * @return The version name of the Agsa package or null if it can't be found. */ public @Nullable String getAgsaVersionName() { diff --git a/build/patches/00Disable-GetInstalledRelatedApps-API.patch b/build/patches/00Disable-GetInstalledRelatedApps-API.patch index 164237bf..fcfa659a 100644 --- a/build/patches/00Disable-GetInstalledRelatedApps-API.patch +++ b/build/patches/00Disable-GetInstalledRelatedApps-API.patch @@ -2,6 +2,7 @@ From: uazo Date: Sun, 7 May 2023 13:13:47 +0000 Subject: Disable GetInstalledRelatedApps API +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../components/installedapp/InstalledAppProviderImpl.java | 1 + .../browser/installedapp/installed_app_provider_impl_win.cc | 1 + @@ -34,7 +35,7 @@ diff --git a/content/browser/installedapp/installed_app_provider_impl_win.cc b/c diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -568,12 +568,12 @@ BASE_FEATURE(kInnerFrameCompositorSurfaceEviction, +@@ -541,12 +541,12 @@ BASE_FEATURE(kInnerFrameCompositorSurfaceEviction, base::FEATURE_ENABLED_BY_DEFAULT); // guard this // Kill switch for the GetInstalledRelatedApps API. @@ -52,8 +53,8 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2077,9 +2077,9 @@ - name: "FingerprintingCanvasImageDataNoise", +@@ -2022,9 +2022,9 @@ + status: {"Android": "test", "default": "stable"}, }, { + // disable GetInstalledRelatedApps diff --git a/build/patches/00Disable-PartnerCustomizations.patch b/build/patches/00Disable-PartnerCustomizations.patch index e678c36c..3c581da5 100644 --- a/build/patches/00Disable-PartnerCustomizations.patch +++ b/build/patches/00Disable-PartnerCustomizations.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 22 Aug 2023 09:02:50 +0000 Subject: Disable PartnerCustomizations +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/flags/android/chrome_feature_list.cc | 4 ++-- .../partnercustomizations/PartnerBrowserCustomizations.java | 2 +- @@ -10,7 +11,7 @@ Subject: Disable PartnerCustomizations diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -865,8 +865,8 @@ BASE_FEATURE(kOpaqueOriginForIncomingIntents, +@@ -889,8 +889,8 @@ BASE_FEATURE(kOpaqueOriginForIncomingIntents, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kPartnerCustomizationsUma, @@ -24,7 +25,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java --- a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java +++ b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java -@@ -213,7 +213,7 @@ public class PartnerBrowserCustomizations { +@@ -214,7 +214,7 @@ public class PartnerBrowserCustomizations { boolean systemOrPreStable = (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 1 || !VersionInfo.isStableBuild(); diff --git a/build/patches/00Disable-PrivateStateTokens-API.patch b/build/patches/00Disable-PrivateStateTokens-API.patch index dab9a58b..dfc38106 100644 --- a/build/patches/00Disable-PrivateStateTokens-API.patch +++ b/build/patches/00Disable-PrivateStateTokens-API.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 15 May 2023 12:33:18 +0000 Subject: Disable PrivateStateTokens API +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- services/network/public/cpp/features.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -9,18 +10,18 @@ Subject: Disable PrivateStateTokens API diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc -@@ -154,12 +154,12 @@ BASE_FEATURE(kAttributionReportingCrossAppWeb, // in bromite +@@ -167,12 +167,12 @@ BASE_FEATURE(kAttributionReportingCrossAppWeb, // in bromite // set, and handling their responses, according to the protocol. // (See https://github.com/WICG/trust-token-api.) BASE_FEATURE(kPrivateStateTokens, - "PrivateStateTokens", -- base::FEATURE_DISABLED_BY_DEFAULT); +- base::FEATURE_ENABLED_BY_DEFAULT); + "PrivateStateTokens", // must be disabled + base::FEATURE_DISABLED_BY_DEFAULT); // in bromite // Secondary flag used by the FLEDGE ads experiment in the interim before // PSTs are fully rolled out to stable. --BASE_FEATURE(kFledgePst, "TrustTokens", base::FEATURE_DISABLED_BY_DEFAULT); +-BASE_FEATURE(kFledgePst, "TrustTokens", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kFledgePst, "TrustTokens", base::FEATURE_DISABLED_BY_DEFAULT); // must be disabled // Determines which Trust Tokens operations require the TrustTokens origin trial diff --git a/build/patches/00Disable-SHA1-Server-Signature.patch b/build/patches/00Disable-SHA1-Server-Signature.patch index 8f4b3cf2..616969fb 100644 --- a/build/patches/00Disable-SHA1-Server-Signature.patch +++ b/build/patches/00Disable-SHA1-Server-Signature.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 18 Apr 2023 14:17:19 +0000 Subject: Disable SHA1 Server Signature +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- net/base/features.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) @@ -9,7 +10,7 @@ Subject: Disable SHA1 Server Signature diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -79,8 +79,8 @@ BASE_FEATURE(kUseDnsHttpsSvcbAlpn, +@@ -88,8 +88,8 @@ BASE_FEATURE(kUseAlternativePortForGloballyReachableCheck, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kSHA1ServerSignature, diff --git a/build/patches/00Disable-remote-altsvc-for-h3-connections.patch b/build/patches/00Disable-remote-altsvc-for-h3-connections.patch index 5fec33ce..a8cb20dd 100644 --- a/build/patches/00Disable-remote-altsvc-for-h3-connections.patch +++ b/build/patches/00Disable-remote-altsvc-for-h3-connections.patch @@ -3,6 +3,8 @@ Date: Tue, 1 Aug 2023 13:56:42 +0000 Subject: Disable remote altsvc for h3 connections and only sets the use of port 443 + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- net/http/http_server_properties_manager.cc | 2 +- net/http/http_stream_factory_job_controller.cc | 9 ++------- @@ -50,7 +52,7 @@ diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stre diff --git a/net/quic/quic_context.h b/net/quic/quic_context.h --- a/net/quic/quic_context.h +++ b/net/quic/quic_context.h -@@ -177,7 +177,7 @@ struct NET_EXPORT QuicParams { +@@ -179,7 +179,7 @@ struct NET_EXPORT QuicParams { bool allow_server_migration = false; // If true, allows QUIC to use alternative services with a different // hostname from the origin. diff --git a/build/patches/00Disable-speechSynthesis-getVoices-API.patch b/build/patches/00Disable-speechSynthesis-getVoices-API.patch index 26d86360..d3386f98 100644 --- a/build/patches/00Disable-speechSynthesis-getVoices-API.patch +++ b/build/patches/00Disable-speechSynthesis-getVoices-API.patch @@ -8,6 +8,8 @@ If not active the user must also set the system timezone override to enable it. Disable LiveCaption Require: Timezone-customization.patch + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/about_flags.cc | 5 +++++ .../renderer/chrome_content_renderer_client.cc | 2 +- @@ -23,7 +25,7 @@ Require: Timezone-customization.patch diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -7464,6 +7464,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -7613,6 +7613,11 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kFileHandlingIconsDescription, kOsDesktop, FEATURE_VALUE_TYPE(blink::features::kFileHandlingIcons)}, @@ -38,7 +40,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc -@@ -1594,7 +1594,7 @@ ChromeContentRendererClient::CreateWorkerContentSettingsClient( +@@ -1589,7 +1589,7 @@ ChromeContentRendererClient::CreateWorkerContentSettingsClient( std::unique_ptr ChromeContentRendererClient::CreateSpeechRecognitionClient( content::RenderFrame* render_frame) { @@ -88,7 +90,7 @@ diff --git a/components/content_settings/renderer/content_settings_agent_impl.h diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc -@@ -865,7 +865,7 @@ const base::FeatureParam kMediaFoundationClearKeyCdmPathForTesting{ +@@ -869,7 +869,7 @@ const base::FeatureParam kMediaFoundationClearKeyCdmPathForTesting{ #endif // BUILDFLAG(IS_WIN) // Enables the Live Caption feature on supported devices. @@ -97,7 +99,7 @@ diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc // Controls whether a "Share this tab instead" button should be shown for // getDisplayMedia captures. Note: This flag does not control if the "Share this -@@ -902,9 +902,9 @@ BASE_FEATURE(kLiveCaptionRightClick, +@@ -906,9 +906,9 @@ BASE_FEATURE(kLiveCaptionRightClick, base::FEATURE_DISABLED_BY_DEFAULT); // Enable or disable Live Caption support for WebAudio. @@ -113,7 +115,7 @@ diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -657,6 +657,10 @@ BASE_FEATURE(kDirectCompositorThreadIpc, +@@ -680,6 +680,10 @@ BASE_FEATURE(kDirectCompositorThreadIpc, "DirectCompositorThreadIpc", base::FEATURE_DISABLED_BY_DEFAULT); @@ -127,7 +129,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -330,6 +330,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDesktopPWAsTabStripCustomizations); +@@ -337,6 +337,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDesktopPWAsTabStripCustomizations); // hopping through the IO thread first. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDirectCompositorThreadIpc); diff --git a/build/patches/00Disable-visited-pseudo-class.patch b/build/patches/00Disable-visited-pseudo-class.patch index 1be807f2..33135371 100644 --- a/build/patches/00Disable-visited-pseudo-class.patch +++ b/build/patches/00Disable-visited-pseudo-class.patch @@ -2,7 +2,9 @@ From: uazo Date: Tue, 14 Feb 2023 16:41:42 +0000 Subject: Disable visited pseudo class -Disable support for pseduo css visited class +Disable support for pseudo css visited class + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- components/visitedlink/browser/visitedlink_writer.cc | 8 ++++---- components/visitedlink/common/visitedlink_common.cc | 1 + @@ -41,7 +43,7 @@ diff --git a/components/visitedlink/browser/visitedlink_writer.cc b/components/v // Extra check that we are not incognito. This should not happen. // TODO(boliu): Move this check to HistoryService when IsOffTheRecord is // removed from BrowserContext. -@@ -1032,7 +1033,6 @@ bool VisitedLinkWriter::RebuildTableFromDelegate() { +@@ -1033,7 +1034,6 @@ bool VisitedLinkWriter::RebuildTableFromDelegate() { // TODO(brettw) make sure we have reasonable salt! table_builder_ = new TableBuilder(this, salt_); diff --git a/build/patches/00Disallowing-MIDI-permission-by-default.patch b/build/patches/00Disallowing-MIDI-permission-by-default.patch index 4e70d6e0..887b8b67 100644 --- a/build/patches/00Disallowing-MIDI-permission-by-default.patch +++ b/build/patches/00Disallowing-MIDI-permission-by-default.patch @@ -2,6 +2,7 @@ From: uazo Date: Sat, 3 Jun 2023 13:11:22 +0000 Subject: Disallowing MIDI permission by default +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- components/permissions/features.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +10,7 @@ Subject: Disallowing MIDI permission by default diff --git a/components/permissions/features.cc b/components/permissions/features.cc --- a/components/permissions/features.cc +++ b/components/permissions/features.cc -@@ -145,7 +145,7 @@ BASE_FEATURE(kWindowManagementPermissionAlias, +@@ -159,7 +159,7 @@ BASE_FEATURE(kWindowManagementPermissionAlias, // Enables disallowing MIDI permission by default. BASE_FEATURE(kBlockMidiByDefault, "BlockMidiByDefault", diff --git a/build/patches/00Enable-Android-Dynamic-Performance-Framework.patch b/build/patches/00Enable-Android-Dynamic-Performance-Framework.patch index 4c070418..b7630023 100644 --- a/build/patches/00Enable-Android-Dynamic-Performance-Framework.patch +++ b/build/patches/00Enable-Android-Dynamic-Performance-Framework.patch @@ -2,6 +2,7 @@ From: uazo Date: Wed, 23 Aug 2023 13:49:19 +0000 Subject: Enable Android Dynamic Performance Framework +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/version.gni | 2 +- components/viz/common/features.cc | 5 +++-- @@ -22,7 +23,7 @@ diff --git a/chrome/version.gni b/chrome/version.gni diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc -@@ -286,9 +286,10 @@ const base::FeatureParam kADPFMidFrameBoostDurationMultiplier{ +@@ -298,9 +298,10 @@ const base::FeatureParam kADPFMidFrameBoostDurationMultiplier{ // If enabled, Chrome includes the Renderer Main thread(s) into the // ADPF(Android Dynamic Performance Framework) hint session. @@ -33,7 +34,7 @@ diff --git a/components/viz/common/features.cc b/components/viz/common/features. + "EnableADPFRendererMain", // enabled + base::FEATURE_ENABLED_BY_DEFAULT); // by default - bool IsDelegatedCompositingEnabled() { - return base::FeatureList::IsEnabled(kDelegatedCompositing); + // If enabled, surface activation and draw do not block on dependencies. + BASE_FEATURE(kDrawImmediatelyWhenInteractive, -- 2.25.1 diff --git a/build/patches/00Enable-Document-Open-Inheritance-Removal.patch b/build/patches/00Enable-Document-Open-Inheritance-Removal.patch index 0ca0848b..0622ecd6 100644 --- a/build/patches/00Enable-Document-Open-Inheritance-Removal.patch +++ b/build/patches/00Enable-Document-Open-Inheritance-Removal.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 28 Mar 2023 15:43:18 +0000 Subject: Enable Document Open Inheritance Removal +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../blink/renderer/core/dom/document.cc | 64 ------------------- .../platform/runtime_enabled_features.json5 | 1 - @@ -10,7 +11,7 @@ Subject: Enable Document Open Inheritance Removal diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc -@@ -3384,70 +3384,6 @@ void Document::open(LocalDOMWindow* entered_window, +@@ -3397,70 +3397,6 @@ void Document::open(LocalDOMWindow* entered_window, // https://chromestatus.com/metrics/feature/timeline/popularity/4375 CountUse(WebFeature::kDocumentOpenMutateSandbox); } @@ -84,7 +85,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -1439,7 +1439,6 @@ +@@ -1415,7 +1415,6 @@ { name: "DocumentOpenSandboxInheritanceRemoval", status: "stable", diff --git a/build/patches/00Fonts-fingerprinting-mitigation.patch b/build/patches/00Fonts-fingerprinting-mitigation.patch index 3ff6bcaf..0dd29221 100644 --- a/build/patches/00Fonts-fingerprinting-mitigation.patch +++ b/build/patches/00Fonts-fingerprinting-mitigation.patch @@ -12,6 +12,8 @@ eliminating the ability to retrieve fonts handled differently by gdi and directwrite. It is possible to restore the original behavior via the fonts-fingerprint-mitigation flag, which is active by default. + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/about_flags.cc | 5 + chrome/browser/flag_descriptions.cc | 5 + @@ -32,7 +34,7 @@ fonts-fingerprint-mitigation flag, which is active by default. diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -10016,6 +10016,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -10083,6 +10083,11 @@ const FeatureEntry kFeatureEntries[] = { kClipboardMaximumAgeVariations, "ClipboardMaximumAge")}, @@ -47,7 +49,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -140,6 +140,11 @@ const char kClipboardUnsanitizedContentDescription[] = +@@ -157,6 +157,11 @@ const char kClipboardUnsanitizedContentDescription[] = "Allows reading/writing unsanitized content from/to the clipboard. " "Currently, it is only applicable to HTML format. See crbug.com/1268679."; @@ -62,7 +64,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -115,6 +115,9 @@ extern const char kClickToCallDescription[]; +@@ -127,6 +127,9 @@ extern const char kClickToCallDescription[]; extern const char kClipboardUnsanitizedContentName[]; extern const char kClipboardUnsanitizedContentDescription[]; @@ -84,7 +86,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c #if BUILDFLAG(IS_ANDROID) // Use chromim's implementation of selection magnifier built using surface -@@ -501,7 +501,7 @@ const base::FeatureParam +@@ -474,7 +474,7 @@ const base::FeatureParam // enables a font indexer on Android which we need to test in the field first. BASE_FEATURE(kFontSrcLocalMatching, "FontSrcLocalMatching", @@ -146,7 +148,7 @@ diff --git a/skia/ext/skia_utils_win.h b/skia/ext/skia_utils_win.h diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -888,7 +888,7 @@ BASE_FEATURE(kFrequencyCappingForOverlayPopupDetection, +@@ -935,7 +935,7 @@ BASE_FEATURE(kFrequencyCappingForOverlayPopupDetection, "FrequencyCappingForOverlayPopupDetection", base::FEATURE_ENABLED_BY_DEFAULT); @@ -155,7 +157,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea BASE_FEATURE(kGainmapHdrImages, "GainmapHdrImages", -@@ -1837,6 +1837,10 @@ BASE_FEATURE(kWebRtcH264WithOpenH264FFmpeg, +@@ -1955,6 +1955,10 @@ BASE_FEATURE(kWebRtcH264WithOpenH264FFmpeg, base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) @@ -169,9 +171,9 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -239,6 +239,9 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kClipboardUnsanitizedContent); - - BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kCompressParkableStrings); +@@ -246,6 +246,9 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kCompressParkableStrings); + BLINK_COMMON_EXPORT extern const base::FeatureParam + kMaxDiskDataAllocatorCapacityMB; +// Filter the list of fonts allowing the use of only standard fonts +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kFontsFingerprintMitigation); @@ -182,7 +184,7 @@ diff --git a/third_party/blink/public/common/features.h b/third_party/blink/publ diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn -@@ -732,6 +732,7 @@ component("platform") { +@@ -725,6 +725,7 @@ component("platform") { "fonts/simple_font_data.cc", "fonts/simple_font_data.h", "fonts/skia/font_cache_skia.cc", @@ -193,7 +195,7 @@ diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/re diff --git a/third_party/blink/renderer/platform/fonts/font_cache.h b/third_party/blink/renderer/platform/fonts/font_cache.h --- a/third_party/blink/renderer/platform/fonts/font_cache.h +++ b/third_party/blink/renderer/platform/fonts/font_cache.h -@@ -342,7 +342,7 @@ class PLATFORM_EXPORT FontCache final { +@@ -328,7 +328,7 @@ class PLATFORM_EXPORT FontCache final { sk_sp CreateTypeface(const FontDescription&, const FontFaceCreationParams&, diff --git a/build/patches/00Internal-firewall.patch b/build/patches/00Internal-firewall.patch index ef584397..7fa92859 100644 --- a/build/patches/00Internal-firewall.patch +++ b/build/patches/00Internal-firewall.patch @@ -6,6 +6,8 @@ Introduces a kind of firewall on http calls made by the browser that allows selective blocking via the NetworkTrafficAnnotationTag. allowed or explicitly blocked calls are defined in services/firewall/tools/rules.xml + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/BUILD.gn | 1 + chrome/browser/about_flags.cc | 6 + @@ -53,7 +55,7 @@ in services/firewall/tools/rules.xml diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -2452,6 +2452,7 @@ static_library("browser") { +@@ -2472,6 +2472,7 @@ static_library("browser") { "//third_party/ungoogled:switches", "//services/device/public/mojom", "//services/device/public/mojom:usb", @@ -64,7 +66,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -200,6 +200,7 @@ +@@ -198,6 +198,7 @@ #include "sandbox/policy/features.h" #include "sandbox/policy/switches.h" #include "services/device/public/cpp/device_features.h" @@ -72,7 +74,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc #include "services/media_session/public/cpp/features.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" -@@ -8126,6 +8127,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -8275,6 +8276,11 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(page_info::kPageInfoHideSiteSettings)}, #endif // !BUILDFLAG(IS_ANDROID) @@ -233,7 +235,7 @@ diff --git a/components/webapps/browser/android/webapk/webapk_icon_hasher.cc b/c diff --git a/net/BUILD.gn b/net/BUILD.gn --- a/net/BUILD.gn +++ b/net/BUILD.gn -@@ -1087,6 +1087,7 @@ component("net") { +@@ -1096,6 +1096,7 @@ component("net") { "//build:chromeos_buildflags", "//net/data/ssl/chrome_root_store:gen_root_store_inc", "//net/http:transport_security_state_generated_files", @@ -258,7 +260,7 @@ diff --git a/net/traffic_annotation/network_traffic_annotation.h b/net/traffic_a diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc -@@ -240,6 +240,9 @@ URLRequestHttpJob::URLRequestHttpJob( +@@ -241,6 +241,9 @@ URLRequestHttpJob::URLRequestHttpJob( throttling_entry_ = manager->RegisterRequestUrl(request->url()); ResetTimer(); @@ -268,7 +270,7 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque } URLRequestHttpJob::~URLRequestHttpJob() { -@@ -546,6 +549,18 @@ void URLRequestHttpJob::MaybeStartTransactionInternal(int result) { +@@ -545,6 +548,18 @@ void URLRequestHttpJob::MaybeStartTransactionInternal(int result) { void URLRequestHttpJob::StartTransactionInternal() { DCHECK(!override_response_headers_); @@ -298,7 +300,7 @@ diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_reques namespace net { -@@ -79,6 +80,8 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { +@@ -81,6 +82,8 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { return priority_; } @@ -1526,7 +1528,7 @@ new file mode 100644 diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -86,6 +86,7 @@ +@@ -87,6 +87,7 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" @@ -1534,7 +1536,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont #include "services/network/brokered_client_socket_factory.h" #include "services/network/cookie_manager.h" #include "services/network/cors/cors_url_loader_factory.h" -@@ -1566,6 +1567,9 @@ void NetworkContext::OnNewSCTAuditingReportSent() { +@@ -1580,6 +1581,9 @@ void NetworkContext::OnNewSCTAuditingReportSent() { void NetworkContext::CreateUDPSocket( mojo::PendingReceiver receiver, mojo::PendingRemote listener) { @@ -1544,7 +1546,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont socket_factory_->CreateUDPSocket(std::move(receiver), std::move(listener)); } -@@ -1578,6 +1582,17 @@ void NetworkContext::CreateRestrictedUDPSocket( +@@ -1592,6 +1596,17 @@ void NetworkContext::CreateRestrictedUDPSocket( mojo::PendingRemote listener, CreateRestrictedUDPSocketCallback callback) { // SimpleHostResolver is transitively owned by |this|. @@ -1562,7 +1564,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont socket_factory_->CreateRestrictedUDPSocket( addr, mode, traffic_annotation, std::move(params), std::move(receiver), std::move(listener), SimpleHostResolver::Create(this), -@@ -1590,6 +1605,17 @@ void NetworkContext::CreateTCPServerSocket( +@@ -1604,6 +1619,17 @@ void NetworkContext::CreateTCPServerSocket( const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojo::PendingReceiver receiver, CreateTCPServerSocketCallback callback) { @@ -1580,7 +1582,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont socket_factory_->CreateTCPServerSocket( local_addr, std::move(options), static_cast(traffic_annotation), -@@ -1604,6 +1630,21 @@ void NetworkContext::CreateTCPConnectedSocket( +@@ -1618,6 +1644,21 @@ void NetworkContext::CreateTCPConnectedSocket( mojo::PendingReceiver receiver, mojo::PendingRemote observer, CreateTCPConnectedSocketCallback callback) { @@ -1602,7 +1604,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont socket_factory_->CreateTCPConnectedSocket( local_addr, remote_addr_list, std::move(tcp_connected_socket_options), static_cast(traffic_annotation), -@@ -1615,6 +1656,20 @@ void NetworkContext::CreateTCPBoundSocket( +@@ -1629,6 +1670,20 @@ void NetworkContext::CreateTCPBoundSocket( const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojo::PendingReceiver receiver, CreateTCPBoundSocketCallback callback) { @@ -1623,7 +1625,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont socket_factory_->CreateTCPBoundSocket( local_addr, static_cast(traffic_annotation), -@@ -1680,6 +1735,24 @@ void NetworkContext::CreateWebSocket( +@@ -1694,6 +1749,24 @@ void NetworkContext::CreateWebSocket( mojo::PendingRemote auth_handler, mojo::PendingRemote header_client, const absl::optional& throttling_profile_id) { @@ -1645,13 +1647,13 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont + return; + } + } - #if !BUILDFLAG(IS_IOS) + #if BUILDFLAG(ENABLE_WEBSOCKETS) if (!websocket_factory_) websocket_factory_ = std::make_unique(this); diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc --- a/services/network/public/cpp/simple_url_loader.cc +++ b/services/network/public/cpp/simple_url_loader.cc -@@ -1239,6 +1239,8 @@ SimpleURLLoaderImpl::SimpleURLLoaderImpl( +@@ -1240,6 +1240,8 @@ SimpleURLLoaderImpl::SimpleURLLoaderImpl( timeout_timer_(timeout_tick_clock_) { // Allow creation and use on different threads. DETACH_FROM_SEQUENCE(sequence_checker_); @@ -1660,7 +1662,7 @@ diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network #if DCHECK_IS_ON() if (resource_request_->request_body) { for (const DataElement& element : -@@ -1658,6 +1660,22 @@ void SimpleURLLoaderImpl::StartRequest( +@@ -1659,6 +1661,22 @@ void SimpleURLLoaderImpl::StartRequest( resource_request_->request_body->AppendDataPipe( string_upload_data_pipe_getter_->GetRemoteForNewUpload()); } @@ -1706,7 +1708,7 @@ diff --git a/services/network/public/cpp/simple_url_loader.h b/services/network/ diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc -@@ -654,23 +654,150 @@ net::NetworkTrafficAnnotationTag URLLoader::Context::GetTrafficAnnotationTag( +@@ -652,23 +652,150 @@ net::NetworkTrafficAnnotationTag URLLoader::Context::GetTrafficAnnotationTag( NOTREACHED(); [[fallthrough]]; @@ -1869,7 +1871,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loa diff --git a/tools/traffic_annotation/scripts/auditor/auditor.py b/tools/traffic_annotation/scripts/auditor/auditor.py --- a/tools/traffic_annotation/scripts/auditor/auditor.py +++ b/tools/traffic_annotation/scripts/auditor/auditor.py -@@ -829,6 +829,7 @@ class ArchivedAnnotation: +@@ -830,6 +830,7 @@ class ArchivedAnnotation: # the XML. This is used to serialize/deserialize the XML. FIELDS = [ "id", "added_in_milestone", "type", "second_id", "reserved", diff --git a/build/patches/00Keep-Side-Panel-Companion-disabled.patch b/build/patches/00Keep-Side-Panel-Companion-disabled.patch index 5db02669..c10cbfc8 100644 --- a/build/patches/00Keep-Side-Panel-Companion-disabled.patch +++ b/build/patches/00Keep-Side-Panel-Companion-disabled.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 17 Jul 2023 15:24:16 +0000 Subject: Keep Side Panel Companion disabled +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/companion/core/features.cc | 19 ++++++++++--------- .../ui/side_search/side_search_prefs.cc | 2 +- @@ -39,7 +40,7 @@ diff --git a/chrome/browser/companion/core/features.cc b/chrome/browser/companio } // namespace internal // When search companion is enabled, show a context menu item that allows the -@@ -51,6 +51,7 @@ const char kDisableCheckUserPermissionsForCompanion[] = +@@ -57,6 +57,7 @@ const char kDisableCheckUserPermissionsForCompanion[] = const char kForceCompanionPinnedState[] = "force-companion-pinned-state"; bool ShouldOverrideCheckingUserPermissionsForCompanion() { @@ -62,7 +63,7 @@ diff --git a/chrome/browser/ui/side_search/side_search_prefs.cc b/chrome/browser diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc -@@ -95,7 +95,7 @@ BASE_FEATURE(kQuickCommands, +@@ -112,7 +112,7 @@ BASE_FEATURE(kResponsiveToolbar, // Enables the side search feature for Google Search. Presents recent Google // search results in a browser side panel. @@ -74,7 +75,7 @@ diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc -@@ -1823,7 +1823,7 @@ GURL TemplateURL::GenerateSuggestionURL( +@@ -1829,7 +1829,7 @@ GURL TemplateURL::GenerateSuggestionURL( } bool TemplateURL::IsSideSearchSupported() const { diff --git a/build/patches/00Keyboard-protection-flag.patch b/build/patches/00Keyboard-protection-flag.patch index 84513606..ac68c887 100644 --- a/build/patches/00Keyboard-protection-flag.patch +++ b/build/patches/00Keyboard-protection-flag.patch @@ -5,6 +5,8 @@ Subject: Keyboard protection flag Hides user preference on the system keyboard by setting the standard eng layout and removing the layout information from the javascript keyboard events. + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/about_flags.cc | 3 + chrome/browser/flag_descriptions.cc | 6 ++ @@ -13,16 +15,15 @@ keyboard events. .../renderer/core/events/keyboard_event.h | 3 + ui/base/ui_base_features.cc | 8 +++ ui/base/ui_base_features.h | 2 + - ui/events/event.cc | 3 +- .../dom/dom_keyboard_layout_map_win.cc | 13 ++++ .../keycodes/keyboard_code_conversion.cc | 10 ++- ui/events/keycodes/keyboard_code_conversion.h | 2 +- - 11 files changed, 115 insertions(+), 4 deletions(-) + 10 files changed, 113 insertions(+), 3 deletions(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5080,6 +5080,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5140,6 +5140,9 @@ const FeatureEntry kFeatureEntries[] = { {"system-keyboard-lock", flag_descriptions::kSystemKeyboardLockName, flag_descriptions::kSystemKeyboardLockDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kSystemKeyboardLock)}, @@ -35,7 +36,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3245,6 +3245,12 @@ const char kSystemKeyboardLockDescription[] = +@@ -3311,6 +3311,12 @@ const char kSystemKeyboardLockDescription[] = "keyboard shortcuts and have the events routed directly to the website " "when in fullscreen mode."; @@ -51,7 +52,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1836,6 +1836,9 @@ extern const char kSuppressToolbarCapturesDescription[]; +@@ -1888,6 +1888,9 @@ extern const char kSuppressToolbarCapturesDescription[]; extern const char kSystemKeyboardLockName[]; extern const char kSystemKeyboardLockDescription[]; @@ -185,7 +186,7 @@ diff --git a/third_party/blink/renderer/core/events/keyboard_event.h b/third_par diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc -@@ -174,6 +174,14 @@ BASE_FEATURE(kSystemKeyboardLock, +@@ -180,6 +180,14 @@ BASE_FEATURE(kSystemKeyboardLock, "SystemKeyboardLock", base::FEATURE_ENABLED_BY_DEFAULT); @@ -212,20 +213,6 @@ diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kUiCompositorScrollWithLayers); -diff --git a/ui/events/event.cc b/ui/events/event.cc ---- a/ui/events/event.cc -+++ b/ui/events/event.cc -@@ -1096,8 +1096,9 @@ char16_t KeyEvent::GetCharacter() const { - // consult the keyboard layout to retrieve the shifted character but we - // only supported US layout for this case in the past, so we only - // support this behavior. -+ int need_shit; - if (char16_t maybe_character = DomCodeToUsLayoutCharacter( -- UsLayoutDomKeyToDomCode(key_), EF_SHIFT_DOWN); -+ UsLayoutDomKeyToDomCode(key_, &need_shit), EF_SHIFT_DOWN); - maybe_character) { - shifted_character = maybe_character; - } diff --git a/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc b/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc --- a/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc +++ b/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc @@ -259,7 +246,7 @@ diff --git a/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc b/ui/events/k diff --git a/ui/events/keycodes/keyboard_code_conversion.cc b/ui/events/keycodes/keyboard_code_conversion.cc --- a/ui/events/keycodes/keyboard_code_conversion.cc +++ b/ui/events/keycodes/keyboard_code_conversion.cc -@@ -216,16 +216,22 @@ int ModifierDomKeyToEventFlag(DomKey key) { +@@ -293,16 +293,22 @@ int ModifierDomKeyToEventFlag(DomKey key) { // DomKey::SYMBOL_LOCK } @@ -287,7 +274,7 @@ diff --git a/ui/events/keycodes/keyboard_code_conversion.cc b/ui/events/keycodes diff --git a/ui/events/keycodes/keyboard_code_conversion.h b/ui/events/keycodes/keyboard_code_conversion.h --- a/ui/events/keycodes/keyboard_code_conversion.h +++ b/ui/events/keycodes/keyboard_code_conversion.h -@@ -99,7 +99,7 @@ EVENTS_BASE_EXPORT int ModifierDomKeyToEventFlag(DomKey key); +@@ -111,7 +111,7 @@ EVENTS_BASE_EXPORT int ModifierDomKeyToEventFlag(DomKey key); // Returns the physical DOM code along with a corresponding non-located // Windows-based key_code. diff --git a/build/patches/00Lock-Profile-Cookie-Database.patch b/build/patches/00Lock-Profile-Cookie-Database.patch index 71f40cfc..13fbc7b4 100644 --- a/build/patches/00Lock-Profile-Cookie-Database.patch +++ b/build/patches/00Lock-Profile-Cookie-Database.patch @@ -2,19 +2,22 @@ From: uazo Date: Mon, 17 Jul 2023 15:24:54 +0000 Subject: Lock Profile Cookie Database +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - chrome/browser/browser_features.cc | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + chrome/browser/browser_features.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc -@@ -201,7 +201,7 @@ BASE_FEATURE(kAppBoundEncryptionMetrics, +@@ -207,8 +207,8 @@ BASE_FEATURE(kAppBoundEncryptionMetrics, + // Enables locking the cookie database for profiles. // TODO(crbug.com/1430226): Remove after fully launched. BASE_FEATURE(kLockProfileCookieDatabase, - "LockProfileCookieDatabase", -- base::FEATURE_DISABLED_BY_DEFAULT); -+ base::FEATURE_ENABLED_BY_DEFAULT); +- "LockProfileCookieDatabase", +- base::FEATURE_ENABLED_BY_DEFAULT); ++ "LockProfileCookieDatabase", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // by default #endif // Enables showing the email of the flex org admin that setup CBCM in the diff --git a/build/patches/00Log-dangling-attributes-in-some-html-elements.patch b/build/patches/00Log-dangling-attributes-in-some-html-elements.patch index 8524f9f1..500badfc 100644 --- a/build/patches/00Log-dangling-attributes-in-some-html-elements.patch +++ b/build/patches/00Log-dangling-attributes-in-some-html-elements.patch @@ -6,6 +6,8 @@ Log for iframes and the base tag all attributes containing newlines or the less-then sign that can be exploited to extract or send otherwise inaccessible information. under enable-log-dangling-attributes about flag + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/about_flags.cc | 5 ++++- .../blink/renderer/core/dom/document.cc | 18 +++++++++++++++ @@ -25,7 +27,7 @@ under enable-log-dangling-attributes about flag diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5031,7 +5031,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5088,7 +5088,10 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kWebShareDescription, kOsWin | kOsCrOS | kOsMac, FEATURE_VALUE_TYPE(features::kWebShare)}, #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) @@ -40,7 +42,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc -@@ -4512,6 +4512,14 @@ void Document::ProcessBaseElement() { +@@ -4525,6 +4525,14 @@ void Document::ProcessBaseElement() { KURL base_element_url; if (href) { String stripped_href = StripLeadingAndTrailingHTMLSpaces(*href); @@ -55,7 +57,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink if (!stripped_href.empty()) base_element_url = KURL(FallbackBaseURL(), stripped_href); } -@@ -4530,6 +4538,14 @@ void Document::ProcessBaseElement() { +@@ -4543,6 +4551,14 @@ void Document::ProcessBaseElement() { !GetExecutionContext()->GetSecurityOrigin()->CanRequest( base_element_url)) { UseCounter::Count(*this, WebFeature::kBaseWithCrossOriginHref); @@ -70,7 +72,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink } } -@@ -4549,6 +4565,8 @@ void Document::ProcessBaseElement() { +@@ -4562,6 +4578,8 @@ void Document::ProcessBaseElement() { if (target->Contains('<')) UseCounter::Count(*this, WebFeature::kBaseWithOpenBracketInTarget); base_target_ = *target; @@ -82,7 +84,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc -@@ -2550,8 +2550,26 @@ void Element::StripScriptingAttributes( +@@ -2576,8 +2576,26 @@ void Element::StripScriptingAttributes( attribute_vector.Shrink(destination); } @@ -113,7 +115,7 @@ diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/ diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h -@@ -568,7 +568,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { +@@ -575,7 +575,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { virtual const QualifiedName& SubResourceAttributeName() const; // Only called by the parser immediately after element construction. @@ -317,7 +319,7 @@ diff --git a/third_party/blink/renderer/core/page/frame_tree.cc b/third_party/bl diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -1514,8 +1514,8 @@ +@@ -1486,8 +1486,8 @@ // Experiment with preventing some instances of mutation XSS // by escaping "<" and ">" in attribute values. // See: crbug.com/1175016 @@ -328,7 +330,7 @@ diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 }, { name: "EventTimingInteractionCount", -@@ -2214,6 +2214,12 @@ +@@ -2175,6 +2175,12 @@ // Use LongAnimationFrameMonitor to emit longtask entries name: "LongTaskFromLongAnimationFrame" }, diff --git a/build/patches/00Multi-Screen-Window-Placement-API-fix.patch b/build/patches/00Multi-Screen-Window-Placement-API-fix.patch index ebeaf2cd..7b35c2cb 100644 --- a/build/patches/00Multi-Screen-Window-Placement-API-fix.patch +++ b/build/patches/00Multi-Screen-Window-Placement-API-fix.patch @@ -4,6 +4,8 @@ Subject: Multi-Screen Window Placement API fix Links the use of screen.isExtended to WINDOW_MANAGEMENT permission granted by user + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../blink/renderer/core/frame/screen.cc | 25 +++++++++++++++++-- .../blink/renderer/core/frame/screen.h | 8 ++++++ @@ -20,12 +22,12 @@ diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink #include "ui/display/screen_info.h" #include "ui/display/screen_infos.h" -@@ -49,7 +50,26 @@ Screen::Screen(LocalDOMWindow* window, - bool use_size_override) - : ExecutionContextClient(window), - display_id_(display_id), -- use_size_override_(use_size_override) {} -+ use_size_override_(use_size_override), +@@ -45,7 +46,26 @@ namespace { + } // namespace + + Screen::Screen(LocalDOMWindow* window, int64_t display_id) +- : ExecutionContextClient(window), display_id_(display_id) {} ++ : ExecutionContextClient(window), display_id_(display_id), + permission_service_(window) { + if (!permission_service_.is_bound()) { + ConnectToPermissionService( @@ -48,15 +50,15 @@ diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink // static bool Screen::AreWebExposedScreenPropertiesEqual( -@@ -159,6 +179,7 @@ int Screen::availWidth() const { +@@ -144,6 +164,7 @@ int Screen::availWidth() const { } void Screen::Trace(Visitor* visitor) const { + visitor->Trace(permission_service_); - EventTargetWithInlineData::Trace(visitor); + EventTarget::Trace(visitor); ExecutionContextClient::Trace(visitor); Supplementable::Trace(visitor); -@@ -181,7 +202,7 @@ bool Screen::isExtended() const { +@@ -166,7 +187,7 @@ bool Screen::isExtended() const { return false; } @@ -68,7 +70,7 @@ diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink diff --git a/third_party/blink/renderer/core/frame/screen.h b/third_party/blink/renderer/core/frame/screen.h --- a/third_party/blink/renderer/core/frame/screen.h +++ b/third_party/blink/renderer/core/frame/screen.h -@@ -33,6 +33,8 @@ +@@ -33,12 +33,20 @@ #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -77,18 +79,17 @@ diff --git a/third_party/blink/renderer/core/frame/screen.h b/third_party/blink/ #include "third_party/blink/renderer/platform/supplementable.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "ui/gfx/geometry/rect.h" -@@ -99,6 +101,12 @@ class CORE_EXPORT Screen : public EventTargetWithInlineData, - // dimensions match window.innerWidth/innerHeight while a page is fullscreen, - // but that is not always true. crbug.com/1367416 - const bool use_size_override_; + + namespace display { + struct ScreenInfo; + + private: + void DidGetPermissionState(mojom::blink::PermissionStatus status); + + bool has_permission_ = false; + HeapMojoRemote permission_service_; - }; + } - } // namespace blink + namespace blink { -- 2.25.1 diff --git a/build/patches/00Partition-HSTS-cache-by-NAK.patch b/build/patches/00Partition-HSTS-cache-by-NAK.patch index c46ad7d4..51bcbb86 100644 --- a/build/patches/00Partition-HSTS-cache-by-NAK.patch +++ b/build/patches/00Partition-HSTS-cache-by-NAK.patch @@ -2,8 +2,8 @@ From: uazo Date: Thu, 16 Mar 2023 14:17:22 +0000 Subject: Partition HSTS cache by NAK +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - .../https_only_mode_upgrade_interceptor.cc | 1 + .../browser/ssl/https_upgrades_interceptor.cc | 1 + .../webui/net_internals/net_internals_ui.cc | 14 ++- .../core/browser/hsts_query.cc | 1 + @@ -16,19 +16,8 @@ Subject: Partition HSTS cache by NAK services/network/network_context.cc | 26 +++-- services/network/network_context.h | 11 ++- .../public/mojom/network_context.mojom | 8 +- - 13 files changed, 132 insertions(+), 84 deletions(-) + 12 files changed, 131 insertions(+), 84 deletions(-) -diff --git a/chrome/browser/ssl/https_only_mode_upgrade_interceptor.cc b/chrome/browser/ssl/https_only_mode_upgrade_interceptor.cc ---- a/chrome/browser/ssl/https_only_mode_upgrade_interceptor.cc -+++ b/chrome/browser/ssl/https_only_mode_upgrade_interceptor.cc -@@ -131,6 +131,7 @@ void HttpsOnlyModeUpgradeInterceptor::MaybeCreateLoader( - network::mojom::NetworkContext* network_context = - profile->GetDefaultStoragePartition()->GetNetworkContext(); - network_context->IsHSTSActiveForHost( -+ tentative_resource_request.trusted_params->isolation_info.network_anonymization_key(), - tentative_resource_request.url.host(), - mojo::WrapCallbackWithDefaultInvokeIfNotRun( - std::move(query_complete_callback), diff --git a/chrome/browser/ssl/https_upgrades_interceptor.cc b/chrome/browser/ssl/https_upgrades_interceptor.cc --- a/chrome/browser/ssl/https_upgrades_interceptor.cc +++ b/chrome/browser/ssl/https_upgrades_interceptor.cc @@ -43,7 +32,7 @@ diff --git a/chrome/browser/ssl/https_upgrades_interceptor.cc b/chrome/browser/s diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc --- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc -@@ -299,7 +299,10 @@ void NetInternalsMessageHandler::OnDomainSecurityPolicyDelete( +@@ -395,7 +395,10 @@ void NetInternalsMessageHandler::OnDomainSecurityPolicyDelete( // There cannot be a unicode entry in the HSTS set. return; } @@ -54,7 +43,7 @@ diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/ *domain, base::BindOnce(&IgnoreBoolCallback)); } -@@ -309,7 +312,10 @@ void NetInternalsMessageHandler::OnHSTSQuery(const base::Value::List& list) { +@@ -405,7 +408,10 @@ void NetInternalsMessageHandler::OnHSTSQuery(const base::Value::List& list) { DCHECK(callback_id && domain); AllowJavascript(); @@ -65,7 +54,7 @@ diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/ *domain, base::BindOnce(&NetInternalsMessageHandler::ResolveCallbackWithResult, weak_factory_.GetWeakPtr(), *callback_id)); -@@ -335,8 +341,12 @@ void NetInternalsMessageHandler::OnHSTSAdd(const base::Value::List& list) { +@@ -431,8 +437,12 @@ void NetInternalsMessageHandler::OnHSTSAdd(const base::Value::List& list) { const bool sts_include_subdomains = list[1].GetBool(); base::Time expiry = base::Time::Now() + base::Days(1000); @@ -482,7 +471,7 @@ diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc -@@ -392,20 +392,6 @@ std::unique_ptr URLRequestContextBuilder::Build() { +@@ -393,20 +393,6 @@ std::unique_ptr URLRequestContextBuilder::Build() { context->set_transport_security_state( std::make_unique(hsts_policy_bypass_list_)); @@ -506,7 +495,7 @@ diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/ur diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc -@@ -204,7 +204,7 @@ std::unique_ptr URLRequestHttpJob::Create(URLRequest* request) { +@@ -205,7 +205,7 @@ std::unique_ptr URLRequestHttpJob::Create(URLRequest* request) { // Check for HSTS upgrade. TransportSecurityState* hsts = request->context()->transport_security_state(); @@ -515,7 +504,7 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque return std::make_unique( request, UpgradeSchemeToCryptographic(url), // Use status code 307 to preserve the method, so POST requests work. -@@ -993,7 +993,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() { +@@ -1026,7 +1026,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() { HttpResponseHeaders* headers = GetResponseHeaders(); std::string value; if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value)) @@ -524,7 +513,7 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque } void URLRequestHttpJob::OnStartCompleted(int result) { -@@ -1063,7 +1063,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) { +@@ -1096,7 +1096,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) { TransportSecurityState* state = context->transport_security_state(); NotifySSLCertificateError( result, transaction_->GetResponseInfo()->ssl_info, @@ -536,7 +525,7 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -1828,17 +1828,19 @@ void NetworkContext::SetCorsOriginAccessListsForOrigin( +@@ -1842,17 +1842,19 @@ void NetworkContext::SetCorsOriginAccessListsForOrigin( std::move(callback).Run(); } @@ -559,7 +548,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont IsHSTSActiveForHostCallback callback) { net::TransportSecurityState* security_state = url_request_context_->transport_security_state(); -@@ -1848,10 +1850,10 @@ void NetworkContext::IsHSTSActiveForHost(const std::string& host, +@@ -1862,10 +1864,10 @@ void NetworkContext::IsHSTSActiveForHost(const std::string& host, return; } @@ -572,7 +561,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont GetHSTSStateCallback callback) { base::Value::Dict result; -@@ -1887,10 +1889,10 @@ void NetworkContext::GetHSTSState(const std::string& domain, +@@ -1901,10 +1903,10 @@ void NetworkContext::GetHSTSState(const std::string& domain, net::TransportSecurityState::STSState dynamic_sts_state; net::TransportSecurityState::PKPState dynamic_pkp_state; bool found_sts_dynamic = transport_security_state->GetDynamicSTSState( @@ -585,7 +574,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont if (found_sts_dynamic) { result.Set("dynamic_upgrade_mode", static_cast(dynamic_sts_state.upgrade_mode)); -@@ -1926,6 +1928,7 @@ void NetworkContext::GetHSTSState(const std::string& domain, +@@ -1940,6 +1942,7 @@ void NetworkContext::GetHSTSState(const std::string& domain, } void NetworkContext::DeleteDynamicDataForHost( @@ -593,7 +582,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont const std::string& host, DeleteDynamicDataForHostCallback callback) { net::TransportSecurityState* transport_security_state = -@@ -1936,7 +1939,7 @@ void NetworkContext::DeleteDynamicDataForHost( +@@ -1950,7 +1953,7 @@ void NetworkContext::DeleteDynamicDataForHost( } std::move(callback).Run( @@ -602,7 +591,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont } void NetworkContext::EnableStaticKeyPinningForTesting( -@@ -1977,7 +1980,7 @@ void NetworkContext::PreconnectSockets( +@@ -2017,7 +2020,7 @@ void NetworkContext::PreconnectSockets( DCHECK(!require_network_anonymization_key_ || !network_anonymization_key.IsEmpty()); @@ -611,7 +600,7 @@ diff --git a/services/network/network_context.cc b/services/network/network_cont // |PreconnectSockets| may receive arguments from the renderer, which is not // guaranteed to validate them. -@@ -2767,12 +2770,15 @@ void NetworkContext::OnConnectionError() { +@@ -2833,12 +2836,15 @@ void NetworkContext::OnConnectionError() { std::move(on_connection_close_callback_).Run(this); } @@ -652,7 +641,7 @@ diff --git a/services/network/network_context.h b/services/network/network_conte const std::string& host, DeleteDynamicDataForHostCallback callback) override; void SetCorsOriginAccessListsForOrigin( -@@ -686,7 +688,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext +@@ -702,7 +704,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext mojo::PendingRemote cookie_observer, net::FirstPartySetMetadata first_party_set_metadata); @@ -665,7 +654,7 @@ diff --git a/services/network/network_context.h b/services/network/network_conte diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom -@@ -1434,16 +1434,16 @@ interface NetworkContext { +@@ -1489,16 +1489,16 @@ interface NetworkContext { // Adds explicitly-specified data as if it was processed from an // HSTS header. Used by tests and implementation of chrome://net-internals. @@ -685,7 +674,7 @@ diff --git a/services/network/public/mojom/network_context.mojom b/services/netw => (mojo_base.mojom.DictionaryValue state); // Sets allowed and blocked origins respectively for the URLLoaderFactory -@@ -1462,7 +1462,7 @@ interface NetworkContext { +@@ -1517,7 +1517,7 @@ interface NetworkContext { // Deletes any dynamic data stored for |host| from the transport // security state. Returns true iff an entry was deleted. // See net::TransportSecurityState::DeleteDynamicDataForHost for more detail. diff --git a/build/patches/00Partitioning-all-cookies-by-top-frame-domain.patch b/build/patches/00Partitioning-all-cookies-by-top-frame-domain.patch index 8e7901e3..47138acf 100644 --- a/build/patches/00Partitioning-all-cookies-by-top-frame-domain.patch +++ b/build/patches/00Partitioning-all-cookies-by-top-frame-domain.patch @@ -6,6 +6,8 @@ Enables cookie partitioning by top frame etld, respecting the user's possible wish to disable all third-party cookies. Disabling the flag via the ui restores the normal mode, where samesite=none first-party cookies are sent in third-party contexts. + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- net/base/features.cc | 8 ++++---- net/cookies/canonical_cookie.cc | 12 +----------- @@ -22,7 +24,7 @@ samesite=none first-party cookies are sent in third-party contexts. diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -252,8 +252,8 @@ BASE_FEATURE(kWaitForFirstPartySetsInit, +@@ -268,8 +268,8 @@ BASE_FEATURE(kWaitForFirstPartySetsInit, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kPartitionedCookies, @@ -33,7 +35,7 @@ diff --git a/net/base/features.cc b/net/base/features.cc BASE_FEATURE(kNoncedPartitionedCookies, "NoncedPartitionedCookies", -@@ -268,8 +268,8 @@ BASE_FEATURE(kStaticKeyPinningEnforcement, +@@ -284,8 +284,8 @@ BASE_FEATURE(kStaticKeyPinningEnforcement, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kCookieDomainRejectNonASCII, @@ -47,7 +49,7 @@ diff --git a/net/base/features.cc b/net/base/features.cc diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc -@@ -1576,8 +1576,6 @@ bool CanonicalCookie::IsCanonicalForFromStorage() const { +@@ -1468,8 +1468,6 @@ bool CanonicalCookie::IsCanonicalForFromStorage() const { if (IsPartitioned()) { if (CookiePartitionKey::HasNonce(partition_key_)) return true; @@ -56,7 +58,7 @@ diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc } return true; -@@ -1851,15 +1849,7 @@ bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, +@@ -1726,15 +1724,7 @@ bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, bool secure, bool is_partitioned, bool partition_has_nonce) { @@ -113,7 +115,7 @@ diff --git a/net/cookies/parsed_cookie.h b/net/cookies/parsed_cookie.h diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc --- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc -@@ -864,6 +864,16 @@ bool SQLitePersistentCookieStore::Backend::DoInitializeDatabase() { +@@ -803,6 +803,16 @@ bool SQLitePersistentCookieStore::Backend::DoInitializeDatabase() { if (!restore_old_session_cookies_) DeleteSessionCookiesOnStartup(); @@ -133,9 +135,9 @@ diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sq diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc --- a/services/network/cookie_settings.cc +++ b/services/network/cookie_settings.cc -@@ -35,6 +35,11 @@ bool IsExplicitSetting(const ContentSettingPatternSource& setting) { - !setting.secondary_pattern.MatchesAllHosts(); - } +@@ -30,6 +30,11 @@ + namespace network { + namespace { +bool IsThirdPartyAllowed(const ContentSettingPatternSource& setting) { + return setting.primary_pattern.MatchesAllHosts() && @@ -145,7 +147,7 @@ diff --git a/services/network/cookie_settings.cc b/services/network/cookie_setti const ContentSettingPatternSource* FindMatchingSetting( const GURL& primary_url, const GURL& secondary_url, -@@ -193,11 +198,14 @@ net::NetworkDelegate::PrivacySetting CookieSettings::IsPrivacyModeEnabled( +@@ -185,11 +190,14 @@ net::NetworkDelegate::PrivacySetting CookieSettings::IsPrivacyModeEnabled( CookieSettings::ThirdPartyBlockingScope CookieSettings::GetThirdPartyBlockingScope(const GURL& first_party_url) const { @@ -165,7 +167,7 @@ diff --git a/services/network/cookie_settings.cc b/services/network/cookie_setti diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc --- a/services/network/restricted_cookie_manager.cc +++ b/services/network/restricted_cookie_manager.cc -@@ -773,6 +773,9 @@ void RestrictedCookieManager::SetCookieFromString( +@@ -783,6 +783,9 @@ void RestrictedCookieManager::SetCookieFromString( std::move(callback).Run(site_for_cookies_ok, top_frame_origin_ok); callback = base::DoNothing(); diff --git a/build/patches/00Remove-ChromiumNetworkAdapter.patch b/build/patches/00Remove-ChromiumNetworkAdapter.patch index 3690676b..2a4d7fdc 100644 --- a/build/patches/00Remove-ChromiumNetworkAdapter.patch +++ b/build/patches/00Remove-ChromiumNetworkAdapter.patch @@ -4,6 +4,8 @@ Subject: Remove ChromiumNetworkAdapter Removes from java code the ability to make http connections without asking the native code + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../browser/download/OMADownloadHandler.java | 38 ------------- .../browser/feedback/ConnectivityChecker.java | 37 +------------ @@ -17,7 +19,7 @@ without asking the native code diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java -@@ -969,44 +969,6 @@ public class OMADownloadHandler extends BroadcastReceiver { +@@ -968,44 +968,6 @@ public class OMADownloadHandler extends BroadcastReceiver { protected Boolean doInBackground() { HttpURLConnection urlConnection = null; boolean success = false; @@ -65,7 +67,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADow diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java -@@ -137,42 +137,7 @@ public final class ConnectivityChecker { +@@ -136,42 +136,7 @@ public final class ConnectivityChecker { postResult(callback, ConnectivityCheckResult.ERROR); return; } @@ -112,7 +114,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/Connec diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java --- a/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java -@@ -389,60 +389,6 @@ public class ConnectivityDetector implements NetworkChangeNotifier.ConnectionTyp +@@ -390,60 +390,6 @@ public class ConnectivityDetector implements NetworkChangeNotifier.ConnectionTyp new AsyncTask() { @Override protected Integer doInBackground() { @@ -205,8 +207,8 @@ diff --git a/components/minidump_uploader/android/java/src/org/chromium/componen diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java --- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java +++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java -@@ -184,14 +184,6 @@ public class VariationsSeedFetcher { - sInstance = fetcher; +@@ -186,14 +186,6 @@ public class VariationsSeedFetcher { + ResettersForTesting.register(() -> sInstance = oldValue); } - @VisibleForTesting @@ -220,7 +222,7 @@ diff --git a/components/variations/android/java/src/org/chromium/components/vari @VisibleForTesting protected List getAvailableInstanceManipulations() { List compressions = new ArrayList(); -@@ -506,24 +498,8 @@ public class VariationsSeedFetcher { +@@ -508,24 +500,8 @@ public class VariationsSeedFetcher { HttpURLConnection connection = null; try { long startTimeMillis = SystemClock.elapsedRealtime(); diff --git a/build/patches/00Remove-auth-header-upon-cross-origin-redirect.patch b/build/patches/00Remove-auth-header-upon-cross-origin-redirect.patch index 4f2d4def..affb68de 100644 --- a/build/patches/00Remove-auth-header-upon-cross-origin-redirect.patch +++ b/build/patches/00Remove-auth-header-upon-cross-origin-redirect.patch @@ -2,6 +2,7 @@ From: uazo Date: Wed, 19 Apr 2023 06:53:19 +0000 Subject: Remove auth header upon cross origin redirect +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../blink/renderer/platform/loader/fetch/resource_loader.cc | 3 +++ .../platform/loader/fetch/url_loader/sync_load_context.cc | 3 +++ @@ -10,7 +11,7 @@ Subject: Remove auth header upon cross origin redirect diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc -@@ -837,6 +837,9 @@ bool ResourceLoader::WillFollowRedirect( +@@ -821,6 +821,9 @@ bool ResourceLoader::WillFollowRedirect( new_url)) { fetcher_->GetUseCounter().CountUse( mojom::WebFeature::kAuthorizationCrossOrigin); diff --git a/build/patches/00Remove-detection-of-captive-portals.patch b/build/patches/00Remove-detection-of-captive-portals.patch index 9e3837de..57d40ab9 100644 --- a/build/patches/00Remove-detection-of-captive-portals.patch +++ b/build/patches/00Remove-detection-of-captive-portals.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 17 Apr 2023 12:43:19 +0000 Subject: Remove detection of captive portals +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/net/profile_network_context_service.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +10,7 @@ Subject: Remove detection of captive portals diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc -@@ -389,7 +389,7 @@ void ProfileNetworkContextService::UpdateAdditionalCertificates() { +@@ -413,7 +413,7 @@ void ProfileNetworkContextService::UpdateAdditionalCertificates() { void ProfileNetworkContextService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref( diff --git a/build/patches/00Remove-experimental-relative-c---abi-vtables.patch b/build/patches/00Remove-experimental-relative-c---abi-vtables.patch index f3737007..1ad06815 100644 --- a/build/patches/00Remove-experimental-relative-c---abi-vtables.patch +++ b/build/patches/00Remove-experimental-relative-c---abi-vtables.patch @@ -1,7 +1,10 @@ -From: Your Name +From: uazo Date: Mon, 30 Jan 2023 15:20:53 +0000 Subject: Remove experimental-relative-c++-abi-vtables +although it is really interesting, it breaks execution with CFI active + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- build/config/compiler/BUILD.gn | 5 ----- 1 file changed, 5 deletions(-) @@ -9,7 +12,7 @@ Subject: Remove experimental-relative-c++-abi-vtables diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -682,11 +682,6 @@ config("compiler") { +@@ -681,11 +681,6 @@ config("compiler") { cflags_cc += [ "-Wno-trigraphs" ] } diff --git a/build/patches/00Remove-support-for-device-memory-and-cpu-recovery.patch b/build/patches/00Remove-support-for-device-memory-and-cpu-recovery.patch index 8356b284..ca6eb9ab 100644 --- a/build/patches/00Remove-support-for-device-memory-and-cpu-recovery.patch +++ b/build/patches/00Remove-support-for-device-memory-and-cpu-recovery.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 27 Jun 2023 11:11:53 +0000 Subject: Remove support for device memory and cpu recovery +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../browser/blob/blob_memory_controller.cc | 20 ++++++++++--------- .../browser/quota/quota_device_info_helper.cc | 17 ++++++++++++++-- @@ -119,7 +120,7 @@ diff --git a/third_party/blink/common/device_memory/approximated_device_memory.c diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1835,8 +1835,8 @@ BASE_FEATURE(kWebFontsCacheAwareTimeoutAdaption, +@@ -1953,8 +1953,8 @@ BASE_FEATURE(kWebFontsCacheAwareTimeoutAdaption, // Controls whether the implementation of the performance.measureMemory // web API uses PerformanceManager or not. BASE_FEATURE(kWebMeasureMemoryViaPerformanceManager, @@ -193,7 +194,7 @@ diff --git a/third_party/blink/renderer/core/timing/memory_info.cc b/third_party diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc -@@ -254,7 +254,7 @@ MemoryInfo* WindowPerformance::memory(ScriptState* script_state) const { +@@ -255,7 +255,7 @@ MemoryInfo* WindowPerformance::memory(ScriptState* script_state) const { auto* memory_info = MakeGarbageCollected( Platform::Current()->IsLockedToSite() ? MemoryInfo::Precision::kPrecise diff --git a/build/patches/00Restore-LastTabStandingTracker.patch b/build/patches/00Restore-LastTabStandingTracker.patch index 061b89de..6258d0bb 100644 --- a/build/patches/00Restore-LastTabStandingTracker.patch +++ b/build/patches/00Restore-LastTabStandingTracker.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 30 May 2023 15:13:31 +0000 Subject: Restore LastTabStandingTracker +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/BUILD.gn | 10 ++++ .../host_content_settings_map_factory.cc | 2 + @@ -26,9 +27,9 @@ Subject: Restore LastTabStandingTracker diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -1875,6 +1875,16 @@ static_library("browser") { - "webid/federated_identity_permission_context_factory.h", - ] +@@ -1903,6 +1903,16 @@ static_library("browser") { + ] + } + sources += [ + "permissions/last_tab_standing_tracker.cc", @@ -377,34 +378,34 @@ new file mode 100644 diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc -@@ -104,6 +104,7 @@ +@@ -118,6 +118,7 @@ #include "chrome/browser/password_manager/password_reuse_manager_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/permissions/adaptive_quiet_notification_permission_ui_enabler.h" +#include "chrome/browser/permissions/last_tab_standing_tracker_factory.h" - #include "chrome/browser/permissions/notification_permission_review_service_factory.h" #include "chrome/browser/permissions/notifications_engagement_service_factory.h" #include "chrome/browser/permissions/one_time_permissions_tracker_factory.h" -@@ -717,6 +718,7 @@ void ChromeBrowserMainExtraPartsProfiles:: + #include "chrome/browser/permissions/origin_keyed_permission_action_service_factory.h" +@@ -873,6 +874,7 @@ void ChromeBrowserMainExtraPartsProfiles:: + #if BUILDFLAG(BUILD_WITH_TFLITE_LIB) + OnDeviceTailModelServiceFactory::GetInstance(); #endif - KAnonymityServiceFactory::GetInstance(); - LanguageModelManagerFactory::GetInstance(); + LastTabStandingTrackerFactory::GetInstance(); #if !BUILDFLAG(IS_ANDROID) + OneGoogleBarServiceFactory::GetInstance(); if (base::FeatureList::IsEnabled(permissions::features::kOneTimePermission)) { - OneTimePermissionsTrackerFactory::GetInstance(); diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc -@@ -55,6 +55,7 @@ +@@ -66,6 +66,7 @@ #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" +#include "chrome/browser/permissions/last_tab_standing_tracker_tab_helper.h" #include "chrome/browser/permissions/one_time_permissions_tracker_helper.h" - #include "chrome/browser/permissions/unused_site_permissions_service_factory.h" #include "chrome/browser/predictors/loading_predictor_factory.h" -@@ -368,6 +369,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { + #include "chrome/browser/predictors/loading_predictor_tab_helper.h" +@@ -399,6 +400,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { HistoryClustersTabHelper::CreateForWebContents(web_contents); HttpsOnlyModeTabHelper::CreateForWebContents(web_contents); webapps::InstallableManager::CreateForWebContents(web_contents); diff --git a/build/patches/00Show-warnings-on-downloads-over-HTTP.patch b/build/patches/00Show-warnings-on-downloads-over-HTTP.patch index 82b5430d..21ba70d2 100644 --- a/build/patches/00Show-warnings-on-downloads-over-HTTP.patch +++ b/build/patches/00Show-warnings-on-downloads-over-HTTP.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 17 Jul 2023 15:26:11 +0000 Subject: Show warnings on downloads over HTTP +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/common/chrome_features.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -9,7 +10,7 @@ Subject: Show warnings on downloads over HTTP diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -1129,9 +1129,9 @@ BASE_FEATURE(kTreatUnsafeDownloadsAsActive, +@@ -1171,9 +1171,9 @@ BASE_FEATURE(kTreatUnsafeDownloadsAsActive, base::FEATURE_ENABLED_BY_DEFAULT); // Show warnings on downloads not delivered over HTTPS. diff --git a/build/patches/00TEMP-Add-a-log-to-track-strange-behavior.patch b/build/patches/00TEMP-Add-a-log-to-track-strange-behavior.patch index 4a20e04f..27aba87a 100644 --- a/build/patches/00TEMP-Add-a-log-to-track-strange-behavior.patch +++ b/build/patches/00TEMP-Add-a-log-to-track-strange-behavior.patch @@ -2,6 +2,7 @@ From: uazo Date: Fri, 19 May 2023 12:26:37 +0000 Subject: TEMP Add a log to track strange behavior +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- net/spdy/spdy_session.cc | 1 + 1 file changed, 1 insertion(+) @@ -9,7 +10,7 @@ Subject: TEMP Add a log to track strange behavior diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc -@@ -3196,6 +3196,7 @@ void SpdySession::OnHeaders(spdy::SpdyStreamId stream_id, +@@ -2982,6 +2982,7 @@ void SpdySession::OnHeaders(spdy::SpdyStreamId stream_id, if (it == active_streams_.end()) { // NOTE: it may just be that the stream was cancelled. LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; diff --git a/build/patches/00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch b/build/patches/00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch index 7c95a86e..663b1908 100644 --- a/build/patches/00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch +++ b/build/patches/00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Tue, 20 Dec 2022 15:09:46 +0000 Subject: Temp Disable kAutomaticLazyFrameLoadingToEmbeds +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- third_party/blink/common/features.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +10,7 @@ Subject: Temp Disable kAutomaticLazyFrameLoadingToEmbeds diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -160,7 +160,7 @@ const base::FeatureParam kSkipFrameCountForLazyAds( +@@ -166,7 +166,7 @@ const base::FeatureParam kSkipFrameCountForLazyAds( // Vitals. BASE_FEATURE(kAutomaticLazyFrameLoadingToEmbeds, "AutomaticLazyFrameLoadingToEmbeds", // must be enabled diff --git a/build/patches/00Temp-disable-predictive-back-gesture.patch b/build/patches/00Temp-disable-predictive-back-gesture.patch index a754a914..cab4237c 100644 --- a/build/patches/00Temp-disable-predictive-back-gesture.patch +++ b/build/patches/00Temp-disable-predictive-back-gesture.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Sat, 12 Aug 2023 14:48:57 +0000 Subject: Temp disable predictive back gesture +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/android/java/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +10,7 @@ Subject: Temp disable predictive back gesture diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml -@@ -189,7 +189,7 @@ by a child template that "extends" this file. +@@ -187,7 +187,7 @@ by a child template that "extends" this file. android:networkSecurityConfig="@xml/network_security_config" android:allowAudioPlaybackCapture="false" android:appComponentFactory="org.chromium.chrome.browser.base.SplitCompatAppComponentFactory" diff --git a/build/patches/00WIN-ADDTO-AImageReader-CFI-crash-mitigations.patch b/build/patches/00WIN-ADDTO-AImageReader-CFI-crash-mitigations.patch deleted file mode 100644 index 9bc7903c..00000000 --- a/build/patches/00WIN-ADDTO-AImageReader-CFI-crash-mitigations.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:36:56 +0000 -Subject: WIN ADDTO AImageReader CFI crash mitigations - ---- - gpu/ipc/service/gpu_init.cc | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc ---- a/gpu/ipc/service/gpu_init.cc -+++ b/gpu/ipc/service/gpu_init.cc -@@ -616,10 +616,12 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, - } - #endif // BUILDFLAG(IS_WIN) - -+#if BUILDFLAG(IS_ANDROID) - // Disable AImageReader if the workaround is enabled. - if (gpu_feature_info_.IsWorkaroundEnabled(DISABLE_AIMAGEREADER)) { - base::android::AndroidImageReader::DisableSupport(); - } -+#endif - - if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] != - kGpuFeatureStatusEnabled || --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Add-AllowUserCertificates-flag.patch b/build/patches/00WIN-ADDTO-Add-AllowUserCertificates-flag.patch deleted file mode 100644 index d2e180e8..00000000 --- a/build/patches/00WIN-ADDTO-Add-AllowUserCertificates-flag.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Your Name -Date: Mon, 19 Dec 2022 11:23:10 +0000 -Subject: WIN ADDTO Add AllowUserCertificates flag - ---- - chrome/browser/about_flags.cc | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -9239,10 +9239,12 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kHttpsUpgradesDescription, kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE(features::kHttpsUpgrades)}, - -+#if BUILDFLAG(IS_ANDROID) - {"allow-user-certificates", - flag_descriptions::kAllowUserCertificatesName, - flag_descriptions::kAllowUserCertificatesDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kAllowUserCertificates)}, -+#endif - {"omnibox-updated-connection-security-indicators", - flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsName, - flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsDescription, --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Add-a-proxy-configuration-page.patch b/build/patches/00WIN-ADDTO-Add-a-proxy-configuration-page.patch deleted file mode 100644 index 451c083e..00000000 --- a/build/patches/00WIN-ADDTO-Add-a-proxy-configuration-page.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 10:59:27 +0000 -Subject: WIN ADDTO Add a proxy configuration page - ---- - chrome/browser/browser_resources.grd | 6 ++---- - chrome/browser/extensions/api/proxy/proxy_api_helpers.cc | 2 +- - 2 files changed, 3 insertions(+), 5 deletions(-) - -diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd ---- a/chrome/browser/browser_resources.grd -+++ b/chrome/browser/browser_resources.grd -@@ -285,10 +285,8 @@ - - - -- -- -- -- -+ -+ - - - -diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc ---- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc -+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc -@@ -388,7 +388,7 @@ absl::optional CreateProxyConfigDict( - return absl::nullopt; - } - return ProxyConfigDictionary::CreateFixedServers(proxy_rules_string, -- bypass_list); -+ bypass_list, /*reverse_bypass*/false); - } - case ProxyPrefs::MODE_SYSTEM: - return ProxyConfigDictionary::CreateSystem(); --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Add-bookmark-import-export-actions.patch b/build/patches/00WIN-ADDTO-Add-bookmark-import-export-actions.patch deleted file mode 100644 index d7eb8ca9..00000000 --- a/build/patches/00WIN-ADDTO-Add-bookmark-import-export-actions.patch +++ /dev/null @@ -1,96 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:30:34 +0000 -Subject: WIN ADDTO Add bookmark import/export actions - ---- - chrome/browser/about_flags.cc | 2 ++ - chrome/browser/bookmarks/bookmark_html_writer.cc | 7 ++++++- - .../select_file_dialog/headless_select_file_dialog.cc | 4 ++++ - ui/shell_dialogs/select_file_dialog_win.cc | 5 +++++ - 4 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -9466,11 +9466,13 @@ const FeatureEntry kFeatureEntries[] = { - FEATURE_VALUE_TYPE(net::features::kIsCleartextPermitted)}, - #endif - -+#if BUILDFLAG(IS_ANDROID) - {"export-bookmarks-use-saf", - flag_descriptions::kBookmarksExportUseSafName, - flag_descriptions::kBookmarksExportUseSafDescription, kOsAndroid, - FEATURE_VALUE_TYPE( - chrome::android::kBookmarksExportUseSaf)}, -+#endif - - #if BUILDFLAG(IS_CHROMEOS_ASH) - {"video-conference", flag_descriptions::kVideoConferenceName, -diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc ---- a/chrome/browser/bookmarks/bookmark_html_writer.cc -+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc -@@ -27,7 +27,9 @@ - #include "base/task/thread_pool.h" - #include "base/time/time.h" - #include "base/values.h" -+#if BUILDFLAG(IS_ANDROID) - #include "base/android/content_uri_utils.h" -+#endif - #include "chrome/browser/bookmarks/bookmark_model_factory.h" - #include "chrome/browser/favicon/favicon_service_factory.h" - #include "chrome/browser/profiles/profile.h" -@@ -234,12 +236,15 @@ class Writer : public base::RefCountedThreadSafe { - // Opens the file, returning true on success. - bool OpenFile() { - int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; -+#if BUILDFLAG(IS_ANDROID) - if (path_.IsContentUri()) { - file_ = std::make_unique(base::OpenContentUriForWrite(path_)); - } else { - file_ = std::make_unique(path_, flags); - } -- -+#else -+ file_ = std::make_unique(path_, flags); -+#endif - if (!file_->IsValid()) { - PLOG(ERROR) << "Could not create " << path_; - return false; -diff --git a/components/headless/select_file_dialog/headless_select_file_dialog.cc b/components/headless/select_file_dialog/headless_select_file_dialog.cc ---- a/components/headless/select_file_dialog/headless_select_file_dialog.cc -+++ b/components/headless/select_file_dialog/headless_select_file_dialog.cc -@@ -58,6 +58,10 @@ class HeadlessSelectFileDialog : public ui::SelectFileDialog { - // ui::SelectFileDialog: - bool HasMultipleFileTypeChoicesImpl() override { return false; } - -+ void ShowToast(const std::string& message) override { -+ // nothing to do, used only on android -+ } -+ - SelectFileDialogCallback callback_; - }; - -diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc ---- a/ui/shell_dialogs/select_file_dialog_win.cc -+++ b/ui/shell_dialogs/select_file_dialog_win.cc -@@ -193,6 +193,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog, - int index); - - bool HasMultipleFileTypeChoicesImpl() override; -+ void ShowToast(const std::string& message) override; - - // Returns the filter to be used while displaying the open/save file dialog. - // This is computed from the extensions for the file types being opened. -@@ -271,6 +272,10 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() { - return has_multiple_file_type_choices_; - } - -+void SelectFileDialogImpl::ShowToast(const std::string& message) { -+ // nothing to do, used only on android -+} -+ - bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow owning_window) const { - if (!owning_window->GetRootWindow()) - return false; --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Disable-requests-for-single-word-Omni.patch b/build/patches/00WIN-ADDTO-Disable-requests-for-single-word-Omni.patch deleted file mode 100644 index bc9b08f6..00000000 --- a/build/patches/00WIN-ADDTO-Disable-requests-for-single-word-Omni.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 12:02:16 +0000 -Subject: WIN ADDTO Disable requests for single-word Omni - ---- - chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc ---- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc -+++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc -@@ -76,6 +76,7 @@ bool OnlyChangeIsFromHTTPToHTTPS(const GURL& origin, const GURL& destination) { - return origin_with_https == destination; - } - -+#if BUILDFLAG(IS_ANDROID) - // Choose the appropriate URLLoaderFactory: either an explicitly specified or a - // default for the given profile. - network::mojom::URLLoaderFactory* GetURLLoaderFactory( -@@ -87,6 +88,7 @@ network::mojom::URLLoaderFactory* GetURLLoaderFactory( - ->GetURLLoaderFactoryForBrowserProcess() - .get(); - } -+#endif - - // Helper to keep ChromeOmniboxNavigationObserver alive while the initiated - // navigation is pending. --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Disable-various-metrics.patch b/build/patches/00WIN-ADDTO-Disable-various-metrics.patch deleted file mode 100644 index 97a09b66..00000000 --- a/build/patches/00WIN-ADDTO-Disable-various-metrics.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:53:36 +0000 -Subject: WIN ADDTO Disable various metrics - ---- - chrome/browser/ui/search/ntp_user_data_logger.cc | 4 ---- - components/ntp_tiles/custom_links_manager_impl.cc | 1 - - 2 files changed, 5 deletions(-) - -diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc ---- a/chrome/browser/ui/search/ntp_user_data_logger.cc -+++ b/chrome/browser/ui/search/ntp_user_data_logger.cc -@@ -394,8 +394,6 @@ void NTPUserDataLogger::LogMostVisitedImpression( - - void NTPUserDataLogger::LogMostVisitedNavigation( - const ntp_tiles::NTPTileImpression& impression) { -- ntp_tiles::metrics::RecordTileClick(impression); -- - // Records the action. This will be available as a time-stamped stream - // server-side and can be used to compute time-to-long-dwell. - base::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); -@@ -424,10 +422,8 @@ void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time, - if (!impression.has_value()) { - break; - } -- ntp_tiles::metrics::RecordTileImpression(*impression); - ++tiles_count; - } -- ntp_tiles::metrics::RecordPageImpression(tiles_count); - - DVLOG(1) << "Emitting NTP load time: " << load_time << ", " - << "number of tiles: " << tiles_count; -diff --git a/components/ntp_tiles/custom_links_manager_impl.cc b/components/ntp_tiles/custom_links_manager_impl.cc ---- a/components/ntp_tiles/custom_links_manager_impl.cc -+++ b/components/ntp_tiles/custom_links_manager_impl.cc -@@ -203,7 +203,6 @@ void CustomLinksManagerImpl::RemoveCustomLinksForPreinstalledApps() { - } - } - if (default_app_links_deleted) { -- metrics::RecordsMigratedDefaultAppDeleted(DeletedTileType::kCustomLink); - prefs_->SetBoolean(prefs::kCustomLinksForPreinstalledAppsRemoved, true); - } - } --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Do-not-build-API-keys-infobar.patch b/build/patches/00WIN-ADDTO-Do-not-build-API-keys-infobar.patch deleted file mode 100644 index 91b2e501..00000000 --- a/build/patches/00WIN-ADDTO-Do-not-build-API-keys-infobar.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:58:29 +0000 -Subject: WIN ADDTO Do not build API keys infobar - ---- - chrome/browser/ui/startup/infobar_utils.cc | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/chrome/browser/ui/startup/infobar_utils.cc b/chrome/browser/ui/startup/infobar_utils.cc ---- a/chrome/browser/ui/startup/infobar_utils.cc -+++ b/chrome/browser/ui/startup/infobar_utils.cc -@@ -133,9 +133,6 @@ void AddInfoBarsIfNecessary(Browser* browser, - infobars::ContentInfoBarManager* infobar_manager = - infobars::ContentInfoBarManager::FromWebContents(web_contents); - -- if (!google_apis::HasAPIKeyConfigured()) -- GoogleApiKeysInfoBarDelegate::Create(infobar_manager); -- - if (ObsoleteSystem::IsObsoleteNowOrSoon()) { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state || --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Experimental-user-scripts-support.patch b/build/patches/00WIN-ADDTO-Experimental-user-scripts-support.patch deleted file mode 100644 index 01fcafae..00000000 --- a/build/patches/00WIN-ADDTO-Experimental-user-scripts-support.patch +++ /dev/null @@ -1,337 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 09:19:46 +0000 -Subject: WIN ADDTO Experimental user scripts support - ---- - chrome/browser/BUILD.gn | 12 +++++++----- - chrome/browser/about_flags.cc | 2 ++ - chrome/browser/prefs/browser_prefs.cc | 2 ++ - chrome/browser/profiles/BUILD.gn | 4 +++- - ...chrome_browser_main_extra_parts_profiles.cc | 4 ++++ - chrome/browser/profiles/profile_manager.cc | 4 ++++ - chrome/browser/profiles/renderer_updater.cc | 11 ++++++++++- - chrome/browser/profiles/renderer_updater.h | 2 ++ - .../webui/chrome_web_ui_controller_factory.cc | 2 ++ - chrome/renderer/BUILD.gn | 7 ++++++- - .../renderer/chrome_content_renderer_client.cc | 18 ++++++++++++++++++ - .../renderer/chrome_render_thread_observer.cc | 2 ++ - 12 files changed, 62 insertions(+), 8 deletions(-) - -diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn ---- a/chrome/browser/BUILD.gn -+++ b/chrome/browser/BUILD.gn -@@ -3517,11 +3517,13 @@ static_library("browser") { - ] - deps += [ "//chrome/android/modules/dev_ui/provider:native" ] - } -- deps += [ -- "//components/user_scripts/common", -- "//components/user_scripts/browser", -- "//components/user_scripts/android", -- ] -+ if (is_android) { -+ deps += [ -+ "//components/user_scripts/common", -+ "//components/user_scripts/browser", -+ "//components/user_scripts/android", -+ ] -+ } - } else { - #!is_android - sources += [ -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -8162,9 +8162,11 @@ const FeatureEntry kFeatureEntries[] = { - FEATURE_VALUE_TYPE(ash::features::kClipboardHistoryLongpress)}, - #endif // BUILDFLAG(IS_CHROMEOS_ASH) - -+#if BUILDFLAG(IS_ANDROID) - {"enable-userscripts-log", flag_descriptions::kEnableLoggingUserScriptsName, - flag_descriptions::kEnableLoggingUserScriptsDescription, kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE(user_scripts::features::kEnableLoggingUserScripts)}, -+#endif - - #if BUILDFLAG(IS_WIN) - {"enable-media-foundation-video-capture", -diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc ---- a/chrome/browser/prefs/browser_prefs.cc -+++ b/chrome/browser/prefs/browser_prefs.cc -@@ -1634,7 +1634,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, - translate::TranslatePrefs::RegisterProfilePrefs(registry); - omnibox::RegisterProfilePrefs(registry); - ZeroSuggestProvider::RegisterProfilePrefs(registry); -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsPrefs::RegisterProfilePrefs(registry); -+#endif - - #if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) - promos_utils::RegisterProfilePrefs(registry); -diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn ---- a/chrome/browser/profiles/BUILD.gn -+++ b/chrome/browser/profiles/BUILD.gn -@@ -57,10 +57,12 @@ source_set("profile") { - "//components/profile_metrics", - "//components/sync/service", - "//components/variations", -- "//components/user_scripts/browser", - "//content/public/browser", - "//extensions/buildflags", - ] -+ if (is_android) { -+ deps += [ "//components/user_scripts/browser" ] -+ } - if (enable_extensions) { - deps += [ "//extensions/browser" ] - } -diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc ---- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc -+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc -@@ -469,7 +469,9 @@ - #include "chrome/browser/offline_pages/request_coordinator_factory.h" - #endif - -+#if BUILDFLAG(IS_ANDROID) - #include "components/user_scripts/browser/userscripts_browser_client.h" -+#endif - - namespace chrome { - -@@ -1097,7 +1099,9 @@ void ChromeBrowserMainExtraPartsProfiles:: - #endif - WebDataServiceFactory::GetInstance(); - webrtc_event_logging::WebRtcEventLogManagerKeyedServiceFactory::GetInstance(); -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsBrowserClient::GetInstance(); -+#endif - } - - void ChromeBrowserMainExtraPartsProfiles::PreProfileInit() { -diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc ---- a/chrome/browser/profiles/profile_manager.cc -+++ b/chrome/browser/profiles/profile_manager.cc -@@ -106,7 +106,9 @@ - #include "extensions/common/manifest.h" - #endif - -+#if BUILDFLAG(IS_ANDROID) - #include "components/user_scripts/browser/userscripts_browser_client.h" -+#endif - - #if BUILDFLAG(ENABLE_SESSION_SERVICE) - #include "chrome/browser/sessions/app_session_service_factory.h" -@@ -1491,11 +1493,13 @@ void ProfileManager::DoFinalInitForServices(Profile* profile, - - #endif - -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsBrowserClient* userscript_client = - user_scripts::UserScriptsBrowserClient::GetInstance(); - if (userscript_client) { - userscript_client->SetProfile(profile); - } -+#endif - - #if BUILDFLAG(ENABLE_SUPERVISED_USERS) - // Initialization needs to happen after extension system initialization (for -diff --git a/chrome/browser/profiles/renderer_updater.cc b/chrome/browser/profiles/renderer_updater.cc ---- a/chrome/browser/profiles/renderer_updater.cc -+++ b/chrome/browser/profiles/renderer_updater.cc -@@ -78,7 +78,9 @@ RendererUpdater::RendererUpdater(Profile* profile) - force_youtube_restrict_.Init(policy::policy_prefs::kForceYouTubeRestrict, - pref_service); - allowed_domains_for_apps_.Init(prefs::kAllowedDomainsForApps, pref_service); -+#if BUILDFLAG(IS_ANDROID) - activate_userscripts_.Init(user_scripts::prefs::kUserScriptsEnabled, pref_service); -+#endif - - pref_change_registrar_.Init(pref_service); - pref_change_registrar_.Add( -@@ -93,10 +95,12 @@ RendererUpdater::RendererUpdater(Profile* profile) - prefs::kAllowedDomainsForApps, - base::BindRepeating(&RendererUpdater::UpdateAllRenderers, - base::Unretained(this))); -+#if BUILDFLAG(IS_ANDROID) - pref_change_registrar_.Add( - user_scripts::prefs::kUserScriptsEnabled, - base::BindRepeating(&RendererUpdater::UpdateAllRenderers, - base::Unretained(this))); -+#endif - } - - RendererUpdater::~RendererUpdater() { -@@ -250,5 +254,10 @@ chrome::mojom::DynamicParamsPtr RendererUpdater::CreateRendererDynamicParams() - #endif - force_google_safesearch_.GetValue(), force_youtube_restrict_.GetValue(), - allowed_domains_for_apps_.GetValue(), -- activate_userscripts_.GetValue()); -+#if BUILDFLAG(IS_ANDROID) -+ activate_userscripts_.GetValue() -+#else -+ false -+#endif -+ ); - } -diff --git a/chrome/browser/profiles/renderer_updater.h b/chrome/browser/profiles/renderer_updater.h ---- a/chrome/browser/profiles/renderer_updater.h -+++ b/chrome/browser/profiles/renderer_updater.h -@@ -108,7 +108,9 @@ class RendererUpdater : public KeyedService, - - // Prefs that we sync to the renderers. - BooleanPrefMember force_google_safesearch_; -+#if BUILDFLAG(IS_ANDROID) - BooleanPrefMember activate_userscripts_; -+#endif - IntegerPrefMember force_youtube_restrict_; - StringPrefMember allowed_domains_for_apps_; - }; -diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc ---- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc -+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc -@@ -529,8 +529,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, - return &NewWebUI; - if (url.host_piece() == chrome::kChromeUIVersionHost) - return &NewWebUI; -+#if BUILDFLAG(IS_ANDROID) - if (url.host_piece() == user_scripts::kChromeUIUserScriptsHost) - return &NewWebUI; -+#endif - - #if !BUILDFLAG(IS_ANDROID) - #if !BUILDFLAG(IS_CHROMEOS) -diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn ---- a/chrome/renderer/BUILD.gn -+++ b/chrome/renderer/BUILD.gn -@@ -154,7 +154,6 @@ static_library("renderer") { - "//components/content_capture/common", - "//components/content_capture/renderer", - "//components/content_settings/common:mojom", -- "//components/user_scripts/renderer", - "//components/content_settings/renderer", - "//components/continuous_search/renderer", - "//components/dom_distiller/content/renderer", -@@ -234,6 +233,12 @@ static_library("renderer") { - "//v8", - ] - -+ if (is_android) { -+ deps += [ -+ "//components/user_scripts/renderer", -+ ] -+ } -+ - data_deps = [ "//tools/v8_context_snapshot" ] - - configs += [ "//build/config/compiler:wexit_time_destructors" ] -diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc ---- a/chrome/renderer/chrome_content_renderer_client.cc -+++ b/chrome/renderer/chrome_content_renderer_client.cc -@@ -252,8 +252,10 @@ - #include "chrome/renderer/media/chrome_key_systems.h" - #endif - -+#if BUILDFLAG(IS_ANDROID) - #include "components/user_scripts/common/user_scripts_features.h" - #include "components/user_scripts/renderer/user_scripts_renderer_client.h" -+#endif - - using autofill::AutofillAgent; - using autofill::PasswordAutofillAgent; -@@ -431,11 +433,13 @@ void ChromeContentRendererClient::RenderThreadStarted() { - WebString::FromASCII(extensions::kExtensionScheme)); - #endif - -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsRendererClient* userscript_client = - user_scripts::UserScriptsRendererClient::GetInstance(); - if (userscript_client) { - userscript_client->RenderThreadStarted(GetChromeObserver()); - } -+#endif - - #if BUILDFLAG(ENABLE_SPELLCHECK) - if (!spellcheck_) -@@ -605,12 +609,14 @@ void ChromeContentRendererClient::RenderFrameCreated( - render_frame, registry); - #endif - -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsRendererClient* userscript_client = - user_scripts::UserScriptsRendererClient::GetInstance(); - if (userscript_client) { - userscript_client->RenderFrameCreated( - render_frame, registry); - } -+#endif - - #if BUILDFLAG(ENABLE_PPAPI) - new PepperHelper(render_frame); -@@ -1619,6 +1625,9 @@ void ChromeContentRendererClient::RunScriptsAtDocumentStart( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart( - render_frame); - // |render_frame| might be dead by now. -+#endif -+#if BUILDFLAG(IS_ANDROID) -+#if BUILDFLAG(ENABLE_EXTENSIONS) - static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); - #endif - user_scripts::UserScriptsRendererClient* userscript_client = -@@ -1627,6 +1636,7 @@ void ChromeContentRendererClient::RunScriptsAtDocumentStart( - userscript_client->RunScriptsAtDocumentStart( - render_frame); - } -+#endif - } - - void ChromeContentRendererClient::RunScriptsAtDocumentEnd( -@@ -1635,6 +1645,9 @@ void ChromeContentRendererClient::RunScriptsAtDocumentEnd( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd( - render_frame); - // |render_frame| might be dead by now. -+#endif -+#if BUILDFLAG(IS_ANDROID) -+#if BUILDFLAG(ENABLE_EXTENSIONS) - static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); - #endif - user_scripts::UserScriptsRendererClient* userscript_client = -@@ -1643,6 +1656,7 @@ void ChromeContentRendererClient::RunScriptsAtDocumentEnd( - userscript_client->RunScriptsAtDocumentEnd( - render_frame); - } -+#endif - } - - void ChromeContentRendererClient::RunScriptsAtDocumentIdle( -@@ -1651,6 +1665,9 @@ void ChromeContentRendererClient::RunScriptsAtDocumentIdle( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentIdle( - render_frame); - // |render_frame| might be dead by now. -+#endif -+#if BUILDFLAG(IS_ANDROID) -+#if BUILDFLAG(ENABLE_EXTENSIONS) - static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); - #endif - user_scripts::UserScriptsRendererClient* userscript_client = -@@ -1659,6 +1676,7 @@ void ChromeContentRendererClient::RunScriptsAtDocumentIdle( - userscript_client->RunScriptsAtDocumentIdle( - render_frame); - } -+#endif - } - - void ChromeContentRendererClient:: -diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc ---- a/chrome/renderer/chrome_render_thread_observer.cc -+++ b/chrome/renderer/chrome_render_thread_observer.cc -@@ -219,7 +219,9 @@ void ChromeRenderThreadObserver::SetConfiguration( - chrome::mojom::DynamicParamsPtr params) { - base::AutoLock lock(dynamic_params_lock_); - dynamic_params_ = std::move(params); -+#if BUILDFLAG(IS_ANDROID) - user_scripts::UserScriptsRendererClient::GetInstance()->ConfigurationUpdated(); -+#endif - } - - void ChromeRenderThreadObserver::OnRendererConfigurationAssociatedRequest( --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Logcat-crash-reports-UI.patch b/build/patches/00WIN-ADDTO-Logcat-crash-reports-UI.patch deleted file mode 100644 index e650fda1..00000000 --- a/build/patches/00WIN-ADDTO-Logcat-crash-reports-UI.patch +++ /dev/null @@ -1,81 +0,0 @@ -From: Your Name -Date: Thu, 13 Oct 2022 11:27:08 +0000 -Subject: WIN ADDTO Logcat crash reports UI - ---- - chrome/browser/ui/webui/crashes_ui.cc | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc ---- a/chrome/browser/ui/webui/crashes_ui.cc -+++ b/chrome/browser/ui/webui/crashes_ui.cc -@@ -44,7 +44,9 @@ - #include "base/files/scoped_temp_dir.h" - #include "base/task/task_traits.h" - #include "base/task/thread_pool.h" -+#if BUILDFLAG(IS_ANDROID) - #include "base/android/path_utils.h" -+#endif - #include "net/base/filename_util.h" - #include "third_party/zlib/google/zip.h" - -@@ -146,6 +148,9 @@ CrashesDOMHandler::CrashesDOMHandler(content::WebContents* web_contents) - : list_available_(false), first_load_(true), - web_contents_(web_contents) { - upload_list_ = CreateCrashUploadList(); -+#if !BUILDFLAG(IS_ANDROID) -+ web_contents_ = nullptr; -+#endif - } - - CrashesDOMHandler::~CrashesDOMHandler() { -@@ -276,6 +281,7 @@ void CrashesDOMHandler::HandleRequestSingleCrashUpload( - } - - std::string CrashesDOMHandler::RequestSingleUpload(const std::string& local_id) const { -+#if BUILDFLAG(IS_ANDROID) - // get crash file path - std::string info_file_path = upload_list_->GetFilePathByLocalId(local_id); - if (info_file_path.empty()) { -@@ -323,13 +329,14 @@ std::string CrashesDOMHandler::RequestSingleUpload(const std::string& local_id) - if (result) { - return zip_file_name.value(); - } -- -+#endif - LOG(ERROR) << "Crash report: cannot create zip content"; - return std::string(); - } - - void CrashesDOMHandler::RequestSingleUploadCallback(const std::string& local_id, - const std::string& file_name) { -+#if BUILDFLAG(IS_ANDROID) - if (!file_name.empty()) { - upload_list_->RequestSingleUploadAsync(local_id); - -@@ -337,6 +344,7 @@ void CrashesDOMHandler::RequestSingleUploadCallback(const std::string& local_id, - web_contents_->GetController().LoadURL( - net::FilePathToFileURL(file_path), {}, {}, {}); - } -+#endif - } - - void CrashesDOMHandler::HandleRequestNewExtraction( -@@ -361,6 +369,7 @@ void CrashesDOMHandler::HandleRequestClearAll( - } - - void CrashesDOMHandler::ClearAll() { -+#if BUILDFLAG(IS_ANDROID) - // get android crash report dir - base::FilePath cache_dir; - base::android::GetCacheDirectory(&cache_dir); -@@ -374,6 +383,7 @@ void CrashesDOMHandler::ClearAll() { - // remove all files, don't care for result - base::DeleteFile(full_name); - } -+#endif - } - - } // namespace --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Restore-Search-Ready-Omnibox-flag.patch b/build/patches/00WIN-ADDTO-Restore-Search-Ready-Omnibox-flag.patch deleted file mode 100644 index 1033cac8..00000000 --- a/build/patches/00WIN-ADDTO-Restore-Search-Ready-Omnibox-flag.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 12:01:37 +0000 -Subject: WIN ADDTO Restore Search Ready Omnibox flag - ---- - chrome/browser/about_flags.cc | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -9436,9 +9436,11 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kDesksTemplatesDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kDesksTemplates)}, - #endif -+#if BUILDFLAG(IS_ANDROID) - {"enable-search-ready-omnibox", flag_descriptions::kSearchReadyOmniboxName, - flag_descriptions::kSearchReadyOmniboxDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kSearchReadyOmniboxFeature)}, -+#endif - - {"large-favicon-from-google", - flag_descriptions::kLargeFaviconFromGoogleName, --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-Revert-flags--remove-num-raster-thre.patch b/build/patches/00WIN-ADDTO-Revert-flags--remove-num-raster-thre.patch deleted file mode 100644 index 7c0fd331..00000000 --- a/build/patches/00WIN-ADDTO-Revert-flags--remove-num-raster-thre.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:59:30 +0000 -Subject: WIN ADDTO Revert flags: remove num-raster-thre - ---- - chrome/browser/about_flags.cc | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -390,6 +390,7 @@ const FeatureEntry::Choice kOverlayStrategiesChoices[] = { - "single-fullscreen,single-on-top,underlay"}, - }; - -+#if BUILDFLAG(IS_ANDROID) - const FeatureEntry::Choice kNumRasterThreadsChoices[] = { - {flags_ui::kGenericExperimentChoiceDefault, "", ""}, - {flag_descriptions::kNumRasterThreadsOne, cc::switches::kNumRasterThreads, "1"}, -@@ -398,6 +399,7 @@ const FeatureEntry::Choice kNumRasterThreadsChoices[] = { - "3"}, - {flag_descriptions::kNumRasterThreadsFour, cc::switches::kNumRasterThreads, - "4"}}; -+#endif - - const FeatureEntry::Choice kTouchTextSelectionStrategyChoices[] = { - {flags_ui::kGenericExperimentChoiceDefault, "", ""}, --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-openH264--enable-ARM-ARM64-optimizati.patch b/build/patches/00WIN-ADDTO-openH264--enable-ARM-ARM64-optimizati.patch deleted file mode 100644 index 549a0080..00000000 --- a/build/patches/00WIN-ADDTO-openH264--enable-ARM-ARM64-optimizati.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 11:31:11 +0000 -Subject: WIN ADDTO openH264: enable ARM/ARM64 optimizati - ---- - .../blink/renderer/modules/mediarecorder/h264_encoder.cc | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc ---- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc -+++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc -@@ -212,9 +212,9 @@ bool H264Encoder::ConfigureEncoder(const gfx::Size& size) { - init_params.iRCMode = RC_OFF_MODE; - } - --#if BUILDFLAG(OS_MACOSX) -- // Threading model: Set to 1 due to https://crbug.com/583348. -- init_params.iMultipleThreadIdc = 1; -+#if BUILDFLAG(IS_MAC) -+ // Threading model: Set to 1 due to https://crbug.com/583348. -+ init_params.iMultipleThreadIdc = 1; - #else - init_params.iMultipleThreadIdc = 0; - #endif --- -2.25.1 diff --git a/build/patches/00WIN-ADDTO-ungoogled-chr--Disable-profile-avatar.patch b/build/patches/00WIN-ADDTO-ungoogled-chr--Disable-profile-avatar.patch deleted file mode 100644 index 93e30df2..00000000 --- a/build/patches/00WIN-ADDTO-ungoogled-chr--Disable-profile-avatar.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Your Name -Date: Wed, 12 Oct 2022 10:04:39 +0000 -Subject: WIN ADDTO ungoogled-chr: Disable profile avatar - ---- - chrome/browser/profiles/profile_attributes_storage.cc | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc ---- a/chrome/browser/profiles/profile_attributes_storage.cc -+++ b/chrome/browser/profiles/profile_attributes_storage.cc -@@ -845,7 +845,7 @@ void ProfileAttributesStorage::DownloadHighResAvatarIfNeeded( - void ProfileAttributesStorage::DownloadHighResAvatar( - size_t icon_index, - const base::FilePath& profile_path) { --#if !BUILDFLAG(IS_ANDROID) -+#if false - const char* file_name = - profiles::GetDefaultAvatarIconFileNameAtIndex(icon_index); - DCHECK(file_name); --- -2.25.1 diff --git a/build/patches/00WIN-Disable-TabHoverCard-images.patch b/build/patches/00WIN-Disable-TabHoverCard-images.patch index 867bdbe1..7e53e366 100644 --- a/build/patches/00WIN-Disable-TabHoverCard-images.patch +++ b/build/patches/00WIN-Disable-TabHoverCard-images.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 14 Mar 2023 15:58:00 +0000 Subject: WIN Disable TabHoverCard images +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/ui/ui_features.cc | 4 ---- 1 file changed, 4 deletions(-) @@ -9,7 +10,7 @@ Subject: WIN Disable TabHoverCard images diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc -@@ -186,11 +186,7 @@ BASE_FEATURE(kTabHoverCardImageSettings, +@@ -203,11 +203,7 @@ BASE_FEATURE(kTabHoverCardImageSettings, // https://crbug.com/928954 BASE_FEATURE(kTabHoverCardImages, "TabHoverCardImages", diff --git a/build/patches/00WIN-Disable-sharing-hub.patch b/build/patches/00WIN-Disable-sharing-hub.patch index 1047fcdc..91c4b64e 100644 --- a/build/patches/00WIN-Disable-sharing-hub.patch +++ b/build/patches/00WIN-Disable-sharing-hub.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Fri, 17 Feb 2023 16:22:00 +0000 Subject: WIN Disable sharing hub +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/sharing_hub/sharing_hub_features.cc | 2 +- chrome/browser/ui/browser_command_controller.cc | 6 +++--- @@ -24,7 +25,7 @@ diff --git a/chrome/browser/sharing_hub/sharing_hub_features.cc b/chrome/browser diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc -@@ -1700,10 +1700,10 @@ void BrowserCommandController::UpdateCommandsForFullscreenMode() { +@@ -1701,10 +1701,10 @@ void BrowserCommandController::UpdateCommandsForFullscreenMode() { command_updater_.UpdateCommandEnabled(IDC_CHROME_WHATS_NEW, show_main_ui); #endif command_updater_.UpdateCommandEnabled(IDC_CONTENT_CONTEXT_SHARING_SUBMENU, @@ -41,7 +42,7 @@ diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc -@@ -1479,6 +1479,7 @@ void SendTabToSelfFromPageAction(Browser* browser) { +@@ -1537,6 +1537,7 @@ void SendTabToSelfFromPageAction(Browser* browser) { } bool CanGenerateQrCode(const Browser* browser) { diff --git a/build/patches/00WIN-Enable-Network-Service-Sandbox-and-CIG.patch b/build/patches/00WIN-Enable-Network-Service-Sandbox-and-CIG.patch index 7069b3f0..8c669fc1 100644 --- a/build/patches/00WIN-Enable-Network-Service-Sandbox-and-CIG.patch +++ b/build/patches/00WIN-Enable-Network-Service-Sandbox-and-CIG.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Fri, 17 Feb 2023 16:23:20 +0000 Subject: WIN Enable Network Service Sandbox and CIG +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/chrome_content_browser_client.cc | 2 +- sandbox/policy/features.cc | 6 +++++- @@ -10,7 +11,7 @@ Subject: WIN Enable Network Service Sandbox and CIG diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -766,7 +766,7 @@ BASE_FEATURE(kRendererCodeIntegrity, +@@ -774,7 +774,7 @@ BASE_FEATURE(kRendererCodeIntegrity, // https://blogs.windows.com/blog/tag/code-integrity-guard/. BASE_FEATURE(kNetworkServiceCodeIntegrity, "NetworkServiceCodeIntegrity", diff --git a/build/patches/00WIN-enable-HighEfficiencyMode-by-default.patch b/build/patches/00WIN-enable-HighEfficiencyMode-by-default.patch index 76e14a65..dd678785 100644 --- a/build/patches/00WIN-enable-HighEfficiencyMode-by-default.patch +++ b/build/patches/00WIN-enable-HighEfficiencyMode-by-default.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Wed, 28 Dec 2022 15:47:58 +0000 Subject: WIN enable HighEfficiencyMode by default +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- components/performance_manager/user_tuning/prefs.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) @@ -9,8 +10,8 @@ Subject: WIN enable HighEfficiencyMode by default diff --git a/components/performance_manager/user_tuning/prefs.cc b/components/performance_manager/user_tuning/prefs.cc --- a/components/performance_manager/user_tuning/prefs.cc +++ b/components/performance_manager/user_tuning/prefs.cc -@@ -35,13 +35,13 @@ const char kManagedTabDiscardingExceptions[] = - "performance_tuning.tab_discarding.exceptions_managed"; +@@ -12,13 +12,13 @@ + namespace performance_manager::user_tuning::prefs { void RegisterLocalStatePrefs(PrefRegistrySimple* registry) { - registry->RegisterBooleanPref(kHighEfficiencyModeEnabled, false); diff --git a/build/patches/00WIN-enable-file-system-access-blocklist.patch b/build/patches/00WIN-enable-file-system-access-blocklist.patch index d0feff51..7857b6da 100644 --- a/build/patches/00WIN-enable-file-system-access-blocklist.patch +++ b/build/patches/00WIN-enable-file-system-access-blocklist.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Tue, 14 Feb 2023 16:32:30 +0000 Subject: WIN enable file system access blocklist +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- content/browser/file_system_access/features.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -18,7 +19,7 @@ diff --git a/content/browser/file_system_access/features.cc b/content/browser/fi // TODO(crbug.com/1381621): Remove this flag eventually. // When enabled, move() will result in a promise rejection when the specified -@@ -51,8 +51,8 @@ BASE_FEATURE(kFileSystemAccessRemoveEntryExclusiveLock, +@@ -44,8 +44,8 @@ BASE_FEATURE(kFileSystemAccessRemove, // When enabled, a user gesture is required to rename a file if the site does // not have write access to the parent. See http://b/254157070 for more context. BASE_FEATURE(kFileSystemAccessRenameWithoutParentAccessRequiresUserActivation, diff --git a/build/patches/00WIN-enable-pdf-plugin.patch b/build/patches/00WIN-enable-pdf-plugin.patch index 1139b074..18ea1bc5 100644 --- a/build/patches/00WIN-enable-pdf-plugin.patch +++ b/build/patches/00WIN-enable-pdf-plugin.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Wed, 28 Dec 2022 15:46:38 +0000 Subject: WIN enable pdf plugin +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- third_party/blink/renderer/core/frame/local_frame.cc | 2 ++ 1 file changed, 2 insertions(+) @@ -9,7 +10,7 @@ Subject: WIN enable pdf plugin diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc -@@ -2058,7 +2058,9 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() { +@@ -2052,7 +2052,9 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() { } PluginData* LocalFrame::GetPluginData() const { diff --git a/build/patches/00Warning-message-for-unsupported-hardware-aes.patch b/build/patches/00Warning-message-for-unsupported-hardware-aes.patch index 39b090b1..ed8af0cc 100644 --- a/build/patches/00Warning-message-for-unsupported-hardware-aes.patch +++ b/build/patches/00Warning-message-for-unsupported-hardware-aes.patch @@ -27,7 +27,7 @@ you can remove the message by going to chrome://flags/#no-hw-aes-warning diff --git a/base/base_switches.cc b/base/base_switches.cc --- a/base/base_switches.cc +++ b/base/base_switches.cc -@@ -176,6 +176,8 @@ extern const char kEnableCrashpad[] = "enable-crashpad"; +@@ -171,6 +171,8 @@ extern const char kEnableCrashpad[] = "enable-crashpad"; const char kDesktopModeViewportMetaEnabled[] = "dm-viewport-meta-enabled"; @@ -39,7 +39,7 @@ diff --git a/base/base_switches.cc b/base/base_switches.cc diff --git a/base/base_switches.h b/base/base_switches.h --- a/base/base_switches.h +++ b/base/base_switches.h -@@ -35,6 +35,7 @@ extern const char kTraceToFileName[]; +@@ -34,6 +34,7 @@ extern const char kTraceToFileName[]; extern const char kV[]; extern const char kVModule[]; extern const char kWaitForDebugger[]; @@ -50,7 +50,7 @@ diff --git a/base/base_switches.h b/base/base_switches.h diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn -@@ -452,6 +452,7 @@ if (is_win) { +@@ -448,6 +448,7 @@ if (is_win) { "//components/policy:generated", "//content/public/app", "//crypto", @@ -58,7 +58,7 @@ diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn "//headless:headless_non_renderer", "//headless:headless_shell_browser_lib", "//net:net_resources", -@@ -1696,6 +1697,8 @@ if (is_android) { +@@ -1713,6 +1714,8 @@ if (is_android) { "//chrome/common/profiler", "//chrome/gpu", "//chrome/renderer", @@ -97,7 +97,7 @@ diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegat diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd -@@ -6699,6 +6699,10 @@ Keep your key file in a safe place. You will need it to create new versions of y +@@ -7004,6 +7004,10 @@ Keep your key file in a safe place. You will need it to create new versions of y You are using an unsupported feature flag: $1SignedHTTPExchange. Stability and security will suffer. @@ -111,9 +111,9 @@ diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -7935,6 +7935,10 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kDevicePostureDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kDevicePosture)}, +@@ -8093,6 +8093,10 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kViewportSegmentsDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kViewportSegments)}, + {"no-hw-aes-warning", flag_descriptions::kNoAESHardwareMessageName, + flag_descriptions::kNoAESHardwareMessageDescription, kOsDesktop | kOsAndroid, @@ -125,9 +125,9 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -840,6 +840,10 @@ const char kDevicePostureName[] = "Device Posture API"; - const char kDevicePostureDescription[] = - "Enables Device Posture API (foldable devices)"; +@@ -882,6 +882,10 @@ const char kViewportSegmentsDescription[] = + "Enable the viewport segment API, giving information about the logical " + "segments of the device (dual screen and foldable devices)"; +const char kNoAESHardwareMessageName[] = "Enable no aes warning message"; +const char kNoAESHardwareMessageDescription[] = @@ -139,20 +139,20 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -612,6 +612,9 @@ extern const char kDeviceForceScheduledRebootDescription[]; +@@ -636,6 +636,9 @@ extern const char kDeviceForceScheduledRebootDescription[]; extern const char kDevicePostureName[]; extern const char kDevicePostureDescription[]; +extern const char kNoAESHardwareMessageName[]; +extern const char kNoAESHardwareMessageDescription[]; + - extern const char kEnablePreinstalledWebAppDuplicationFixerName[]; - extern const char kEnablePreinstalledWebAppDuplicationFixerDescription[]; + extern const char kEnableTLS13EarlyDataName[]; + extern const char kEnableTLS13EarlyDataDescription[]; diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc --- a/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/chrome/browser/ui/startup/bad_flags_prompt.cc -@@ -221,6 +221,15 @@ void ShowBadFlagsPrompt(content::WebContents* web_contents) { +@@ -227,6 +227,15 @@ void ShowBadFlagsPrompt(content::WebContents* web_contents) { return; } } @@ -171,18 +171,18 @@ diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/s diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc -@@ -3727,6 +3727,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( +@@ -3747,6 +3747,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kLacrosUseChromeosProtectedAv1, #endif switches::kDesktopModeViewportMetaEnabled, + switches::kNoAESHardware, }; - renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, - std::size(kSwitchNames)); + renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames); + diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -766,6 +766,11 @@ BASE_FEATURE(kNoStatePrefetchHoldback, +@@ -728,6 +728,11 @@ BASE_FEATURE(kNoStatePrefetchHoldback, "NoStatePrefetchHoldback", base::FEATURE_DISABLED_BY_DEFAULT); @@ -197,7 +197,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h -@@ -170,6 +170,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kNetworkServiceInProcess); +@@ -163,6 +163,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kNetworkServiceInProcess); CONTENT_EXPORT BASE_DECLARE_FEATURE(kNotificationContentImage); CONTENT_EXPORT BASE_DECLARE_FEATURE(kNotificationTriggers); CONTENT_EXPORT BASE_DECLARE_FEATURE(kNoStatePrefetchHoldback); diff --git a/build/patches/00add-browser-policy.patch b/build/patches/00add-browser-policy.patch index 09b82b32..aee5c10d 100644 --- a/build/patches/00add-browser-policy.patch +++ b/build/patches/00add-browser-policy.patch @@ -2,6 +2,7 @@ From: uazo Date: Tue, 22 Nov 2022 16:49:58 +0000 Subject: Add browser policy +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- base/win/win_util.cc | 63 +------- chrome/android/java/AndroidManifest.xml | 4 - @@ -133,7 +134,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro -@@ -131,7 +128,6 @@ by a child template that "extends" this file. +@@ -129,7 +126,6 @@ by a child template that "extends" this file. @@ -159,7 +160,7 @@ diff --git a/chrome/browser/android/preferences/privacy_preferences_manager_impl diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc --- a/chrome/browser/metrics/chrome_feature_list_creator.cc +++ b/chrome/browser/metrics/chrome_feature_list_creator.cc -@@ -56,6 +56,8 @@ +@@ -57,6 +57,8 @@ #include "content/public/common/content_switches.h" #include "services/network/public/cpp/network_switches.h" #include "ui/base/resource/resource_bundle.h" @@ -168,7 +169,7 @@ diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/brow #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" -@@ -196,6 +198,16 @@ void ChromeFeatureListCreator::CreatePrefService() { +@@ -219,6 +221,16 @@ void ChromeFeatureListCreator::CreatePrefService() { // ManagementService's cache. if (local_state_pref_store->ReadPrefs() == JsonPrefStore::PREF_READ_ERROR_NONE) { @@ -188,7 +189,7 @@ diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/brow diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc --- a/chrome/browser/policy/chrome_browser_policy_connector.cc +++ b/chrome/browser/policy/chrome_browser_policy_connector.cc -@@ -155,8 +155,6 @@ bool ChromeBrowserPolicyConnector::HasMachineLevelPolicies() { +@@ -158,8 +158,6 @@ bool ChromeBrowserPolicyConnector::HasMachineLevelPolicies() { if (ProviderHasPolicies(machine_level_user_cloud_policy_manager())) return true; #endif // !BUILDFLAG(IS_CHROMEOS_ASH) @@ -200,7 +201,7 @@ diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/b diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc -@@ -1946,9 +1946,9 @@ bool AreFuturePoliciesEnabledByDefault() { +@@ -1997,9 +1997,9 @@ bool AreFuturePoliciesEnabledByDefault() { // Enable future policies for branded browser tests. if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) return true; @@ -216,7 +217,7 @@ diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc --- a/chrome/browser/signin/account_consistency_mode_manager.cc +++ b/chrome/browser/signin/account_consistency_mode_manager.cc -@@ -199,7 +199,8 @@ AccountConsistencyModeManager::ComputeAccountConsistencyMethod( +@@ -198,7 +198,8 @@ AccountConsistencyModeManager::ComputeAccountConsistencyMethod( #endif #if BUILDFLAG(ENABLE_MIRROR) @@ -226,7 +227,7 @@ diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/ #endif #if BUILDFLAG(ENABLE_DICE_SUPPORT) -@@ -209,7 +210,7 @@ AccountConsistencyModeManager::ComputeAccountConsistencyMethod( +@@ -208,7 +209,7 @@ AccountConsistencyModeManager::ComputeAccountConsistencyMethod( return AccountConsistencyMethod::kDisabled; } @@ -238,31 +239,31 @@ diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/ diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc -@@ -126,7 +126,9 @@ void ChromeSigninClient::DoFinalInit() { +@@ -130,7 +130,9 @@ void ChromeSigninClient::DoFinalInit() { bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) { - content_settings::CookieSettings* cookie_settings = - CookieSettingsFactory::GetForProfile(profile).get(); -- return signin::SettingsAllowSigninCookies(cookie_settings); + scoped_refptr cookie_settings = + CookieSettingsFactory::GetForProfile(profile); +- return signin::SettingsAllowSigninCookies(cookie_settings.get()); + // Make ChromeSigninClient compliant to SigninAllowed policy -+ bool cookiesAllowed = signin::SettingsAllowSigninCookies(cookie_settings); ++ bool cookiesAllowed = signin::SettingsAllowSigninCookies(cookie_settings.get()); + return cookiesAllowed && profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed); } PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); } -@@ -264,6 +266,9 @@ bool ChromeSigninClient::AreNetworkCallsDelayed() { +@@ -234,6 +236,9 @@ bool ChromeSigninClient::AreNetworkCallsDelayed() { } void ChromeSigninClient::DelayNetworkCall(base::OnceClosure callback) { + // Make ChromeSigninClient compliant to SigninAllowed policy + if (!AreSigninCookiesAllowed()) return; + - if (!AreNetworkCallsDelayed()) { - std::move(callback).Run(); - return; + wait_for_network_callback_helper_->DelayNetworkCall(std::move(callback)); + } + diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.cc b/chrome/browser/ui/webui/policy/policy_ui_handler.cc --- a/chrome/browser/ui/webui/policy/policy_ui_handler.cc +++ b/chrome/browser/ui/webui/policy/policy_ui_handler.cc -@@ -21,6 +21,7 @@ +@@ -22,6 +22,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/notreached.h" @@ -270,15 +271,15 @@ diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.cc b/chrome/browse #include "base/strings/utf_string_conversions.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" -@@ -55,6 +56,7 @@ - #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" - #include "components/policy/core/common/cloud/cloud_policy_util.h" +@@ -68,6 +69,7 @@ #include "components/policy/core/common/policy_details.h" + #include "components/policy/core/common/policy_logger.h" + #include "components/policy/core/common/policy_pref_names.h" +#include "components/policy/core/common/policy_pref_names.h" #include "components/policy/core/common/policy_scheduler.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/core/common/remote_commands/remote_commands_service.h" -@@ -167,6 +169,10 @@ void PolicyUIHandler::RegisterMessages() { +@@ -194,6 +196,10 @@ void PolicyUIHandler::RegisterMessages() { "exportPoliciesJSON", base::BindRepeating(&PolicyUIHandler::HandleExportPoliciesJson, base::Unretained(this))); @@ -289,7 +290,7 @@ diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.cc b/chrome/browse web_ui()->RegisterMessageCallback( "listenPoliciesUpdates", base::BindRepeating(&PolicyUIHandler::HandleListenPoliciesUpdates, -@@ -330,8 +336,102 @@ void PolicyUIHandler::SendPolicies() { +@@ -569,8 +575,102 @@ void PolicyUIHandler::SendPolicies() { "policies-updated", base::Value( policy_value_and_status_aggregator_->GetAggregatedPolicyNames()), @@ -397,7 +398,7 @@ diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.cc b/chrome/browse diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.h b/chrome/browser/ui/webui/policy/policy_ui_handler.h --- a/chrome/browser/ui/webui/policy/policy_ui_handler.h +++ b/chrome/browser/ui/webui/policy/policy_ui_handler.h -@@ -56,6 +56,8 @@ class PolicyUIHandler : public content::WebUIMessageHandler, +@@ -94,6 +94,8 @@ class PolicyUIHandler : public content::WebUIMessageHandler, private: void HandleExportPoliciesJson(const base::Value::List& args); @@ -594,7 +595,7 @@ diff --git a/components/policy/core/common/policy_loader_command_line.cc b/compo diff --git a/components/policy/core/common/policy_pref_names.cc b/components/policy/core/common/policy_pref_names.cc --- a/components/policy/core/common/policy_pref_names.cc +++ b/components/policy/core/common/policy_pref_names.cc -@@ -90,6 +90,9 @@ const char kBackForwardCacheEnabled[] = "policy.back_forward_cache_enabled"; +@@ -93,6 +93,9 @@ const char kReadAloudEnabled[] = "policy.read_aloud_enabled"; const char kUserAgentClientHintsGREASEUpdateEnabled[] = "policy.user_agent_client_hints_grease_update_enabled"; @@ -614,11 +615,11 @@ diff --git a/components/policy/core/common/policy_pref_names.h b/components/poli +extern const char kDisabledDefaultPoliciesList[]; #if BUILDFLAG(IS_ANDROID) extern const char kBackForwardCacheEnabled[]; - #endif // BUILDFLAG(IS_ANDROID) + extern const char kReadAloudEnabled[]; diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc --- a/components/policy/core/common/policy_service_impl.cc +++ b/components/policy/core/common/policy_service_impl.cc -@@ -64,6 +64,9 @@ void IgnoreUserCloudPrecedencePolicies(PolicyMap* policies) { +@@ -47,6 +47,9 @@ namespace { // Metrics should not be enforced so if this policy is set as mandatory // downgrade it to a recommended level policy. void DowngradeMetricsReportingToRecommendedPolicy(PolicyMap* policies) { @@ -673,7 +674,7 @@ diff --git a/components/policy/resources/templates/policy_definitions/Miscellane diff --git a/components/policy/resources/webui/policy_row.html b/components/policy/resources/webui/policy_row.html --- a/components/policy/resources/webui/policy_row.html +++ b/components/policy/resources/webui/policy_row.html -@@ -139,6 +139,7 @@ a { +@@ -147,6 +147,7 @@ a {

@@ -712,7 +713,7 @@ diff --git a/components/policy/resources/webui/policy_row.ts b/components/policy // Populate the remaining columns with policy scope, level and value if a // value has been set. Otherwise, leave them blank. if (!this.unset_) { -@@ -213,6 +220,11 @@ export class PolicyRowElement extends CustomElement { +@@ -220,6 +227,11 @@ export class PolicyRowElement extends CustomElement { } } diff --git a/build/patches/00do-not-block-build-incompatible-profiles.patch b/build/patches/00do-not-block-build-incompatible-profiles.patch index d364ca88..dd799a04 100644 --- a/build/patches/00do-not-block-build-incompatible-profiles.patch +++ b/build/patches/00do-not-block-build-incompatible-profiles.patch @@ -2,6 +2,7 @@ From: uazo Date: Wed, 2 Aug 2023 15:15:48 +0000 Subject: Do not block the build for incompatible profiles +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .gitignore | 1 - v8/BUILD.gn | 2 +- @@ -10,7 +11,7 @@ Subject: Do not block the build for incompatible profiles diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore -@@ -345,7 +345,6 @@ vs-chromium-project.txt +@@ -348,7 +348,6 @@ vs-chromium-project.txt /ui/surface/surface.xml /ui/surface/surface_gpu_tests.xml /ui/webui/internal @@ -21,14 +22,14 @@ diff --git a/.gitignore b/.gitignore diff --git a/v8/BUILD.gn b/v8/BUILD.gn --- a/v8/BUILD.gn +++ b/v8/BUILD.gn -@@ -2293,7 +2293,7 @@ template("run_mksnapshot") { +@@ -2347,7 +2347,7 @@ template("run_mksnapshot") { # Replace this with --warn-about-builtin-profile-data to see the full # list of builtins with incompatible profiles. - "--abort-on-bad-builtin-profile-data", + "--warn-about-builtin-profile-data", ] - } + if (!v8_enable_builtins_profiling && v8_enable_builtins_reordering) { -- 2.25.1 diff --git a/build/patches/00v113-temp-fix-build.patch b/build/patches/00v113-temp-fix-build.patch index 97cd8e2c..8a9c88f8 100644 --- a/build/patches/00v113-temp-fix-build.patch +++ b/build/patches/00v113-temp-fix-build.patch @@ -2,6 +2,7 @@ From: uazo Date: Mon, 1 May 2023 12:08:46 +0000 Subject: v113 temp fix build +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- android_webview/system_webview_bundle.gni | 4 ++++ chrome/browser/safe_browsing/BUILD.gn | 1 + @@ -24,7 +25,7 @@ diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_ diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn -@@ -214,6 +214,7 @@ static_library("safe_browsing") { +@@ -210,6 +210,7 @@ static_library("safe_browsing") { "//components/version_info", "//content/public/browser", "//services/preferences/public/mojom:mojom", diff --git a/build/patches/AImageReader-CFI-crash-mitigations.patch b/build/patches/AImageReader-CFI-crash-mitigations.patch index bd06a285..515bce43 100644 --- a/build/patches/AImageReader-CFI-crash-mitigations.patch +++ b/build/patches/AImageReader-CFI-crash-mitigations.patch @@ -28,11 +28,11 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html gpu/config/gpu_finch_features.h | 1 + gpu/config/gpu_util.cc | 8 ++++++++ gpu/config/gpu_workaround_list.txt | 1 + - gpu/ipc/service/gpu_init.cc | 5 +++++ + gpu/ipc/service/gpu_init.cc | 7 +++++++ gpu/ipc/service/stream_texture_android.cc | 11 ++++++++++- media/base/media_switches.cc | 5 +++++ media/base/media_switches.h | 1 + - 12 files changed, 66 insertions(+), 5 deletions(-) + 12 files changed, 68 insertions(+), 5 deletions(-) diff --git a/base/android/android_image_reader_compat.cc b/base/android/android_image_reader_compat.cc --- a/base/android/android_image_reader_compat.cc @@ -84,7 +84,7 @@ diff --git a/base/android/android_image_reader_compat.h b/base/android/android_i diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -2798,9 +2798,9 @@ +@@ -2928,9 +2928,9 @@ "expiry_milestone": 125 }, { @@ -100,7 +100,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json -@@ -3698,6 +3698,22 @@ +@@ -3688,6 +3688,22 @@ "no_downscaled_overlay_promotion" ] }, @@ -188,14 +188,16 @@ diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc -@@ -616,6 +616,11 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, +@@ -628,6 +628,13 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, } #endif // BUILDFLAG(IS_WIN) ++#if BUILDFLAG(IS_ANDROID) + // Disable AImageReader if the workaround is enabled. + if (gpu_feature_info_.IsWorkaroundEnabled(DISABLE_AIMAGEREADER)) { + base::android::AndroidImageReader::DisableSupport(); + } ++#endif + if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] != kGpuFeatureStatusEnabled || @@ -231,7 +233,7 @@ diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_ diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc -@@ -946,6 +946,11 @@ BASE_FEATURE(kHardwareSecureDecryptionExperiment, +@@ -950,6 +950,11 @@ BASE_FEATURE(kHardwareSecureDecryptionExperiment, // Allows automatically disabling hardware secure Content Decryption Module // (CDM) after failures or crashes to fallback to software secure CDMs. If this // feature is disabled, the fallback will never happen and users could be stuck @@ -246,7 +248,7 @@ diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc diff --git a/media/base/media_switches.h b/media/base/media_switches.h --- a/media/base/media_switches.h +++ b/media/base/media_switches.h -@@ -327,6 +327,7 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kVideoBlitColorAccuracy); +@@ -328,6 +328,7 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kVideoBlitColorAccuracy); MEDIA_EXPORT BASE_DECLARE_FEATURE(kVideoToolboxVideoDecoder); #endif // BUILDFLAG(IS_APPLE) MEDIA_EXPORT BASE_DECLARE_FEATURE(kWebRTCColorAccuracy); diff --git a/build/patches/Add-AllowUserCertificates-flag.patch b/build/patches/Add-AllowUserCertificates-flag.patch index 6dc3e03f..90440eee 100644 --- a/build/patches/Add-AllowUserCertificates-flag.patch +++ b/build/patches/Add-AllowUserCertificates-flag.patch @@ -5,20 +5,20 @@ Subject: Add AllowUserCertificates flag Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../src/org/chromium/chrome/browser/app/ChromeActivity.java | 3 +++ - chrome/browser/about_flags.cc | 4 ++++ - chrome/browser/flag_descriptions.cc | 5 +++++ - chrome/browser/flag_descriptions.h | 3 +++ - chrome/browser/flags/android/chrome_feature_list.cc | 5 +++++ - chrome/browser/flags/android/chrome_feature_list.h | 1 + - .../org/chromium/chrome/browser/flags/ChromeFeatureList.java | 4 ++++ - net/android/java/src/org/chromium/net/X509Util.java | 5 +++++ - 8 files changed, 30 insertions(+) + .../org/chromium/chrome/browser/app/ChromeActivity.java | 3 +++ + chrome/browser/about_flags.cc | 7 +++++++ + chrome/browser/flag_descriptions.cc | 5 +++++ + chrome/browser/flag_descriptions.h | 3 +++ + chrome/browser/flags/android/chrome_feature_list.cc | 5 +++++ + chrome/browser/flags/android/chrome_feature_list.h | 1 + + .../chromium/chrome/browser/flags/ChromeFeatureList.java | 4 ++++ + net/android/java/src/org/chromium/net/X509Util.java | 5 +++++ + 8 files changed, 33 insertions(+) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java -@@ -231,6 +231,7 @@ import org.chromium.content_public.browser.ScreenOrientationProvider; +@@ -230,6 +230,7 @@ import org.chromium.content_public.browser.ScreenOrientationProvider; import org.chromium.content_public.browser.SelectionPopupController; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.ContentSwitches; @@ -26,7 +26,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv import org.chromium.printing.PrintManagerDelegateImpl; import org.chromium.printing.PrintingController; import org.chromium.printing.PrintingControllerImpl; -@@ -973,6 +974,8 @@ public abstract class ChromeActivity +@@ -981,6 +982,8 @@ public abstract class ChromeActivity super.onStartWithNative(); ChromeActivitySessionTracker.getInstance().onStartWithNative(); ChromeCachedFlags.getInstance().cacheNativeFlags(); @@ -38,17 +38,20 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9184,6 +9184,10 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kHttpsUpgradesDescription, kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE(features::kHttpsUpgrades)}, +@@ -9305,6 +9305,13 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kEnableDrDcDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kEnableDrDc)}, ++#if BUILDFLAG(IS_ANDROID) + {"allow-user-certificates", + flag_descriptions::kAllowUserCertificatesName, + flag_descriptions::kAllowUserCertificatesDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kAllowUserCertificates)}, - {"omnibox-updated-connection-security-indicators", - flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsName, - flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsDescription, ++#endif // BUILDFLAG(IS_ANDROID) ++ + {"force-gpu-main-thread-to-normal-priority-drdc", + flag_descriptions::kForceGpuMainThreadToNormalPriorityDrDcName, + flag_descriptions::kForceGpuMainThreadToNormalPriorityDrDcDescription, diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc @@ -88,7 +91,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &feed::kInterestFeedV2, &feed::kInterestFeedV2Autoplay, &feed::kInterestFeedV2Hearts, -@@ -458,6 +459,10 @@ BASE_FEATURE(kSearchReadyOmniboxFeature, +@@ -467,6 +468,10 @@ BASE_FEATURE(kSearchReadyOmniboxFeature, "SearchReadyOmnibox", base::FEATURE_DISABLED_BY_DEFAULT); @@ -102,8 +105,8 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -20,6 +20,7 @@ BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarCustomizationV2); - BASE_DECLARE_FEATURE(kAddToHomescreenIPH); +@@ -22,6 +22,7 @@ BASE_DECLARE_FEATURE(kAdvancedPeripheralsSupport); + BASE_DECLARE_FEATURE(kAdvancedPeripheralsSupportTabStrip); BASE_DECLARE_FEATURE(kAllowNewIncognitoTabIntents); BASE_DECLARE_FEATURE(kAndroidAppIntegration); +BASE_DECLARE_FEATURE(kAllowUserCertificates); @@ -121,7 +124,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR = "AdaptiveButtonInTopToolbar"; public static final String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_TRANSLATE = "AdaptiveButtonInTopToolbarTranslate"; -@@ -499,6 +500,8 @@ public abstract class ChromeFeatureList { +@@ -504,6 +505,8 @@ public abstract class ChromeFeatureList { public static final String XSURFACE_METRICS_REPORTING = "XsurfaceMetricsReporting"; /* Alphabetical: */ @@ -130,7 +133,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final CachedFlag sAppMenuMobileSiteOption = new CachedFlag(APP_MENU_MOBILE_SITE_OPTION, false); public static final CachedFlag sBackGestureActivityTabProvider = -@@ -622,6 +625,7 @@ public abstract class ChromeFeatureList { +@@ -629,6 +632,7 @@ public abstract class ChromeFeatureList { public static final List sFlagsCachedFullBrowser = List.of( // clang-format off diff --git a/build/patches/Add-Alt-D-hotkey-to-focus-address-bar.patch b/build/patches/Add-Alt-D-hotkey-to-focus-address-bar.patch index e497c656..72323e7d 100644 --- a/build/patches/Add-Alt-D-hotkey-to-focus-address-bar.patch +++ b/build/patches/Add-Alt-D-hotkey-to-focus-address-bar.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java --- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java -@@ -151,6 +151,8 @@ public class KeyboardShortcuts { +@@ -152,6 +152,8 @@ public class KeyboardShortcuts { KeyEvent.KEYCODE_F, KeyEvent.META_CTRL_ON); addShortcut(context, chromeFeatureShortcutGroup, R.string.keyboard_shortcut_address_bar, KeyEvent.KEYCODE_L, KeyEvent.META_CTRL_ON); diff --git a/build/patches/Add-IsCleartextPermitted-flag.patch b/build/patches/Add-IsCleartextPermitted-flag.patch index 97c2eca8..5852db05 100644 --- a/build/patches/Add-IsCleartextPermitted-flag.patch +++ b/build/patches/Add-IsCleartextPermitted-flag.patch @@ -16,21 +16,21 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9395,6 +9395,10 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kRequestDesktopSiteExceptionsName, - flag_descriptions::kRequestDesktopSiteExceptionsDescription, kOsAndroid, - FEATURE_VALUE_TYPE(features::kRequestDesktopSiteExceptions)}, +@@ -9512,6 +9512,10 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kForceOffTextAutosizingName, + flag_descriptions::kForceOffTextAutosizingDescription, kOsAndroid, + FEATURE_VALUE_TYPE(features::kForceOffTextAutosizing)}, + {"cleartext-permitted", + flag_descriptions::kIsCleartextPermittedName, + flag_descriptions::kIsCleartextPermittedDescription, kOsAndroid, + FEATURE_VALUE_TYPE(net::features::kIsCleartextPermitted)}, #endif - {"export-bookmarks-use-saf", + #if BUILDFLAG(IS_ANDROID) diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1915,6 +1915,10 @@ const char kHttpsUpgradesDescription[] = +@@ -1947,6 +1947,10 @@ const char kHttpsUpgradesDescription[] = "Enable automatically upgrading all top-level navigations to HTTPS with " "fast fallback to HTTP."; @@ -44,7 +44,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1062,6 +1062,9 @@ extern const char kHiddenNetworkMigrationDescription[]; +@@ -1090,6 +1090,9 @@ extern const char kHideIncognitoMediaMetadataDescription[]; extern const char kHttpsOnlyModeName[]; extern const char kHttpsOnlyModeDescription[]; @@ -57,9 +57,9 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -131,6 +131,10 @@ BASE_FEATURE(kEnableCrossSiteFlagNetworkIsolationKey, // must be - "EnableCrossSiteFlagNetworkIsolationKey", // disabled - base::FEATURE_DISABLED_BY_DEFAULT); // in Bromite +@@ -146,6 +146,10 @@ BASE_FEATURE(kHttpCacheKeyingExperimentControlGroup, + "HttpCacheKeyingExperimentControlGroup", + base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kIsCleartextPermitted, + "IsCleartextPermitted", @@ -83,7 +83,7 @@ diff --git a/net/base/features.h b/net/base/features.h diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc -@@ -212,6 +212,10 @@ std::unique_ptr URLRequestHttpJob::Create(URLRequest* request) { +@@ -213,6 +213,10 @@ std::unique_ptr URLRequestHttpJob::Create(URLRequest* request) { } #if BUILDFLAG(IS_ANDROID) diff --git a/build/patches/Add-a-proxy-configuration-page.patch b/build/patches/Add-a-proxy-configuration-page.patch index cc48a91b..31531a36 100644 --- a/build/patches/Add-a-proxy-configuration-page.patch +++ b/build/patches/Add-a-proxy-configuration-page.patch @@ -19,7 +19,8 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../java/res/xml/privacy_preferences.xml | 4 + .../privacy/settings/PrivacySettings.java | 1 + .../chrome_autocomplete_provider_client.cc | 2 + - chrome/browser/browser_resources.grd | 6 +- + chrome/browser/browser_resources.grd | 4 +- + .../extensions/api/proxy/proxy_api_helpers.cc | 2 +- chrome/browser/net/proxy_service_factory.cc | 24 +- chrome/browser/net/proxy_service_factory.h | 3 + chrome/browser/prefs/browser_prefs.cc | 4 + @@ -39,7 +40,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../proxy_config/proxy_policy_handler.cc | 2 +- net/proxy_resolution/proxy_config.cc | 52 ++- net/proxy_resolution/proxy_config.h | 3 + - 24 files changed, 982 insertions(+), 17 deletions(-) + 25 files changed, 981 insertions(+), 18 deletions(-) create mode 100644 chrome/browser/resources/proxy_config.css create mode 100644 chrome/browser/resources/proxy_config.html create mode 100644 chrome/browser/resources/proxy_config.js @@ -87,7 +88,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc -@@ -304,6 +304,8 @@ ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() { +@@ -297,6 +297,8 @@ ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() { builtins_to_provide.push_back( base::ASCIIToUTF16(chrome::kChromeUISettingsURL)); #endif @@ -99,15 +100,13 @@ diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd -@@ -284,11 +284,15 @@ +@@ -277,11 +277,13 @@ + -+ -+ -+ -+ ++ ++ @@ -116,6 +115,18 @@ diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resou +diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc +--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc ++++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc +@@ -388,7 +388,7 @@ absl::optional CreateProxyConfigDict( + return absl::nullopt; + } + return ProxyConfigDictionary::CreateFixedServers(proxy_rules_string, +- bypass_list); ++ bypass_list, /*reverse_bypass*/false); + } + case ProxyPrefs::MODE_SYSTEM: + return ProxyConfigDictionary::CreateSystem(); diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc --- a/chrome/browser/net/proxy_service_factory.cc +++ b/chrome/browser/net/proxy_service_factory.cc @@ -191,7 +202,7 @@ diff --git a/chrome/browser/net/proxy_service_factory.h b/chrome/browser/net/pro diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -175,6 +175,8 @@ +@@ -177,6 +177,8 @@ #include "rlz/buildflags/buildflags.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -200,7 +211,7 @@ diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browse #if BUILDFLAG(ENABLE_BACKGROUND_MODE) #include "chrome/browser/background/background_mode_manager.h" #endif -@@ -1315,6 +1317,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) { +@@ -1410,6 +1412,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) { component_updater::RegisterPrefs(registry); domain_reliability::RegisterPrefs(registry); embedder_support::OriginTrialPrefs::RegisterPrefs(registry); @@ -655,7 +666,7 @@ new file mode 100644 diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -397,6 +397,8 @@ static_library("ui") { +@@ -307,6 +307,8 @@ static_library("ui") { "webui/metrics_internals/metrics_internals_ui.h", "webui/net_export_ui.cc", "webui/net_export_ui.h", @@ -667,7 +678,7 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc -@@ -59,6 +59,7 @@ +@@ -64,6 +64,7 @@ #include "chrome/browser/ui/webui/ntp_tiles_internals_ui.h" #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h" #include "chrome/browser/ui/webui/policy/policy_ui.h" @@ -675,7 +686,7 @@ diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrom #include "chrome/browser/ui/webui/predictors/predictors_ui.h" #include "chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.h" #include "chrome/browser/ui/webui/signin_internals_ui.h" -@@ -489,6 +490,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, +@@ -502,6 +503,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; if (url.host_piece() == chrome::kChromeUINetExportHost) return &NewWebUI; @@ -1121,7 +1132,7 @@ new file mode 100644 diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc -@@ -50,6 +50,8 @@ const char kChromeUICertificateViewerHost[] = "view-cert"; +@@ -56,6 +56,8 @@ const char kChromeUICertificateViewerHost[] = "view-cert"; const char kChromeUICertificateViewerURL[] = "chrome://view-cert/"; const char kChromeUIChromeSigninHost[] = "chrome-signin"; const char kChromeUIChromeSigninURL[] = "chrome://chrome-signin/"; @@ -1130,7 +1141,7 @@ diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_cons const char kChromeUIChromeURLsHost[] = "chrome-urls"; const char kChromeUIChromeURLsURL[] = "chrome://chrome-urls/"; const char kChromeUIComponentsHost[] = "components"; -@@ -431,6 +433,7 @@ bool IsSystemWebUIHost(base::StringPiece host) { +@@ -441,6 +443,7 @@ bool IsSystemWebUIHost(base::StringPiece host) { kChromeUILockScreenNetworkHost, kChromeUILockScreenStartReauthHost, kChromeUIMobileSetupHost, @@ -1138,9 +1149,9 @@ diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_cons kChromeUIMultiDeviceSetupHost, kChromeUINetworkHost, kChromeUINotificationTesterHost, -@@ -730,6 +733,7 @@ const char* const kChromeHostURLs[] = { +@@ -746,6 +749,7 @@ const char* const kChromeHostURLs[] = { #if !BUILDFLAG(IS_ANDROID) - #if !BUILDFLAG(IS_CHROMEOS_ASH) + #if !BUILDFLAG(IS_CHROMEOS) kChromeUIAppLauncherPageHost, + kChromeUIProxyConfigHost, #endif @@ -1149,7 +1160,7 @@ diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_cons diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h -@@ -136,6 +136,8 @@ extern const char kChromeUINTPTilesInternalsHost[]; +@@ -143,6 +143,8 @@ extern const char kChromeUINTPTilesInternalsHost[]; extern const char kChromeUINaClHost[]; extern const char kChromeUINetExportHost[]; extern const char kChromeUINetExportURL[]; @@ -1178,7 +1189,7 @@ diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/compone registry->RegisterBooleanPref(proxy_config::prefs::kUseSharedProxies, false); } -@@ -384,6 +384,7 @@ bool PrefProxyConfigTrackerImpl::PrefConfigToNetConfig( +@@ -388,6 +388,7 @@ bool PrefProxyConfigTrackerImpl::PrefConfigToNetConfig( if (proxy_dict.GetBypassList(&proxy_bypass)) { proxy_config.proxy_rules().bypass_rules.ParseFromString(proxy_bypass); } @@ -1327,7 +1338,7 @@ diff --git a/components/proxy_config/proxy_policy_handler.cc b/components/proxy_ diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc --- a/net/proxy_resolution/proxy_config.cc +++ b/net/proxy_resolution/proxy_config.cc -@@ -109,7 +109,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { +@@ -112,7 +112,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { &single_proxies, ProxyServer::SCHEME_HTTP); type = Type::PROXY_LIST; @@ -1336,7 +1347,7 @@ diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_c } // Trim whitespace off the url scheme. -@@ -140,6 +140,56 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { +@@ -143,6 +143,56 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { } } diff --git a/build/patches/Add-an-always-incognito-mode.patch b/build/patches/Add-an-always-incognito-mode.patch index a65f2783..8ee5ed5c 100644 --- a/build/patches/Add-an-always-incognito-mode.patch +++ b/build/patches/Add-an-always-incognito-mode.patch @@ -74,7 +74,6 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../browser/toolbar/LocationBarModel.java | 5 +- chrome/browser/ui/messages/android/BUILD.gn | 1 + .../snackbar/INeedSnackbarManager.java | 27 +++ - chrome/common/pref_names.cc | 6 + chrome/common/pref_names.h | 6 + .../browser/content_settings_pref_provider.cc | 8 +- .../browser/content_settings_pref_provider.h | 2 + @@ -87,7 +86,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../omnibox/browser/base_search_provider.cc | 2 +- components/omnibox/browser/search_provider.cc | 4 +- .../host_content_settings_map_factory.cc | 1 + - 68 files changed, 765 insertions(+), 91 deletions(-) + 67 files changed, 759 insertions(+), 91 deletions(-) create mode 100644 chrome/android/java/res/xml/incognito_preferences.xml create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java @@ -96,7 +95,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -663,6 +663,7 @@ chrome_java_resources = [ +@@ -667,6 +667,7 @@ chrome_java_resources = [ "java/res/xml/main_preferences.xml", "java/res/xml/manage_sync_preferences.xml", "java/res/xml/phone_as_a_security_key_accessory_filter.xml", @@ -115,7 +114,7 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java "java/src/com/google/android/apps/chrome/appwidget/bookmarks/BookmarkThumbnailWidgetProvider.java", "java/src/org/chromium/chrome/browser/ActivityTabProvider.java", "java/src/org/chromium/chrome/browser/ActivityUtils.java", -@@ -944,6 +945,7 @@ chrome_java_sources = [ +@@ -953,6 +954,7 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/privacy/settings/IncognitoLockSettings.java", "java/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImpl.java", "java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java", @@ -241,7 +240,7 @@ new file mode 100644 diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -56,6 +56,10 @@ import org.chromium.base.task.TaskTraits; +@@ -58,6 +58,10 @@ import org.chromium.base.task.TaskTraits; import org.chromium.build.annotations.UsedByReflection; import org.chromium.cc.input.BrowserControlsState; import org.chromium.chrome.R; @@ -252,7 +251,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout; -@@ -591,9 +595,14 @@ public class ChromeTabbedActivity extends ChromeActivity +@@ -1897,6 +1898,9 @@ public abstract class ChromeActivity throw new IllegalStateException( "Attempting to access TabCreator before initialization"); } @@ -306,15 +305,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java -@@ -35,6 +35,7 @@ import org.chromium.base.supplier.ObservableSupplier; - import org.chromium.base.supplier.OneshotSupplier; +@@ -37,6 +37,7 @@ import org.chromium.base.supplier.OneshotSupplier; + import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor; import org.chromium.chrome.browser.banners.AppMenuVerbiage; import org.chromium.chrome.browser.bookmarks.BookmarkFeatures; import org.chromium.chrome.browser.bookmarks.BookmarkModel; -@@ -103,6 +104,10 @@ import java.lang.annotation.RetentionPolicy; +@@ -104,6 +105,10 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -325,7 +324,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/App /** * Base implementation of {@link AppMenuPropertiesDelegate} that handles hiding and showing menu * items based on activity state. -@@ -559,6 +564,13 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate +@@ -567,6 +572,13 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate } private void prepareCommonMenuItems(Menu menu, @MenuGroup int menuGroup, boolean isIncognito) { @@ -339,7 +338,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/App // We have to iterate all menu items since same menu item ID may be associated with more // than one menu items. boolean isOverviewModeMenu = menuGroup == MenuGroup.OVERVIEW_MODE_MENU; -@@ -619,7 +631,15 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate +@@ -627,7 +639,15 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate } if (item.getItemId() == R.id.recent_tabs_menu_id) { @@ -356,7 +355,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/App } if (item.getItemId() == R.id.menu_select_tabs) { item.setVisible(isMenuSelectTabsVisible); -@@ -823,7 +843,9 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate +@@ -831,7 +851,9 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate // is not persisted when adding to the homescreen. // * If creating shortcuts it not supported by the current home screen. return WebappsUtils.isAddToHomeIntentSupported() && !isChromeScheme && !isFileScheme @@ -378,7 +377,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator; import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem.Item; import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType; -@@ -232,6 +233,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { +@@ -231,6 +232,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { public List> buildContextMenu() { mShowEphemeralTabNewLabel = null; @@ -388,15 +387,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr List> groupedItems = new ArrayList<>(); if (mParams.isAnchor()) { -@@ -250,6 +254,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { - linkGroup.add(createListItem(Item.OPEN_IN_NEW_TAB_IN_GROUP)); - } - } +@@ -240,6 +244,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { + if (mMode == ContextMenuMode.NORMAL) { + linkGroup.add(createListItem(Item.OPEN_IN_NEW_TAB_IN_GROUP)); + linkGroup.add(createListItem(Item.OPEN_IN_NEW_TAB)); + if (!mItemDelegate.isIncognito() && mItemDelegate.isIncognitoSupported()) { linkGroup.add(createListItem(Item.OPEN_IN_INCOGNITO_TAB)); } -@@ -274,7 +279,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { +@@ -264,7 +269,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator { } } if (FirstRunStatus.getFirstRunFlowComplete()) { @@ -408,7 +407,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/Chr diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java -@@ -50,31 +50,6 @@ public class CustomTabActivityLifecycleUmaTracker +@@ -67,31 +67,6 @@ public class CustomTabActivityLifecycleUmaTracker private boolean mIsInitialResume = true; private void recordIncognitoLaunchReason() { @@ -451,7 +450,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/Cust import org.chromium.chrome.browser.DefaultBrowserInfo; import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl; import org.chromium.chrome.browser.app.appmenu.DividerLineMenuItemViewBinder; -@@ -178,6 +179,9 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat +@@ -179,6 +180,9 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat downloadItemVisible = false; openInChromeItemVisible = false; } @@ -464,7 +463,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/Cust diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java -@@ -57,6 +57,9 @@ import org.chromium.components.embedder_support.util.UrlConstants; +@@ -63,6 +63,9 @@ import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.version_info.VersionInfo; import org.chromium.device.mojom.ScreenOrientationLockType; @@ -474,7 +473,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/Cust import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -@@ -1223,7 +1226,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid +@@ -1210,7 +1213,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid @Override public boolean isIncognito() { @@ -494,7 +493,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/Downlo import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.app.download.home.DownloadActivity; -@@ -73,6 +74,10 @@ import org.chromium.url.GURL; +@@ -74,6 +75,10 @@ import org.chromium.url.GURL; import java.io.File; @@ -534,7 +533,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; -@@ -78,6 +79,12 @@ import java.io.Serializable; +@@ -76,6 +77,12 @@ import java.io.Serializable; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -547,7 +546,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History /** * Combines and manages the different UI components of browsing history. */ -@@ -159,7 +166,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve +@@ -157,7 +164,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve recordUserAction("Show"); // If incognito placeholder is shown, we don't need to create History UI elements. @@ -556,7 +555,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History mSelectableListLayout = null; mRootView = getIncognitoHistoryPlaceholderView(); return; -@@ -596,7 +603,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve +@@ -594,7 +601,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve private void swapContentView() { boolean toHistoryClusters; @@ -565,7 +564,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History return; } else if (isHistoryClustersUIShowing()) { toHistoryClusters = false; -@@ -659,11 +666,24 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve +@@ -657,11 +664,24 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve && mContentView == mHistoryClustersCoordinator.getActivityContentView(); } @@ -591,7 +590,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History // If Incognito placeholder is shown no need to call any destroy method. return; } -@@ -683,7 +703,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve +@@ -681,7 +701,7 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve * @return True if manager handles this event, false if it decides to ignore. */ public boolean onBackPressed() { @@ -603,7 +602,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java -@@ -11,6 +11,7 @@ import androidx.annotation.VisibleForTesting; +@@ -9,6 +9,7 @@ import android.net.Uri; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; @@ -611,7 +610,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History import org.chromium.chrome.browser.history_clusters.HistoryClustersConstants; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; -@@ -19,6 +20,12 @@ import org.chromium.chrome.browser.ui.native_page.BasicNativePage; +@@ -17,6 +18,12 @@ import org.chromium.chrome.browser.ui.native_page.BasicNativePage; import org.chromium.chrome.browser.ui.native_page.NativePageHost; import org.chromium.components.embedder_support.util.UrlConstants; @@ -624,7 +623,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History /** * Native page for managing browsing history. */ -@@ -41,6 +48,15 @@ public class HistoryPage extends BasicNativePage { +@@ -39,6 +46,15 @@ public class HistoryPage extends BasicNativePage { boolean isIncognito, Supplier tabSupplier, String url) { super(host); @@ -643,15 +642,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/History diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java --- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java -@@ -14,6 +14,7 @@ import androidx.annotation.VisibleForTesting; - +@@ -15,6 +15,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.supplier.DestroyableObservableSupplier; + import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.download.home.DownloadPage; import org.chromium.chrome.browser.bookmarks.BookmarkPage; -@@ -216,7 +217,8 @@ public class NativePageFactory { +@@ -226,7 +227,8 @@ public class NativePageFactory { String url, NativePage candidatePage, Tab tab, boolean isIncognito) { NativePage page; @@ -664,7 +663,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/Nat diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java -@@ -36,6 +36,15 @@ import org.chromium.components.signin.metrics.SigninAccessPoint; +@@ -35,6 +35,15 @@ import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.sync.SyncService; import org.chromium.url.GURL; @@ -680,7 +679,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsM import java.util.HashMap; import java.util.List; import java.util.Map; -@@ -100,7 +109,8 @@ public class RecentTabsManager implements SyncService.SyncStateChangedListener, +@@ -99,7 +108,8 @@ public class RecentTabsManager implements SyncService.SyncStateChangedListener, */ public RecentTabsManager(Tab tab, TabModelSelector tabModelSelector, Profile profile, Context context, Runnable showHistoryManager) { @@ -690,7 +689,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsM mActiveTab = tab; mTabModelSelector = tabModelSelector; mShowHistoryManager = showHistoryManager; -@@ -252,6 +262,22 @@ public class RecentTabsManager implements SyncService.SyncStateChangedListener, +@@ -251,6 +261,22 @@ public class RecentTabsManager implements SyncService.SyncStateChangedListener, */ public void openRecentlyClosedTab(RecentlyClosedTab tab, int windowDisposition) { if (mIsDestroyed) return; @@ -881,7 +880,7 @@ new file mode 100644 diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java -@@ -70,6 +70,7 @@ import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings; +@@ -72,6 +72,7 @@ import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings; import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl; import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate; import org.chromium.chrome.browser.sync.SyncServiceFactory; @@ -889,7 +888,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/Settin import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarManageable; import org.chromium.components.browser_ui.accessibility.AccessibilitySettings; -@@ -320,6 +321,9 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity +@@ -322,6 +323,9 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity ((PrivacySandboxSettingsBaseFragment) fragment) .setSnackbarManager(getSnackbarManager()); } @@ -944,7 +943,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java -@@ -27,6 +27,8 @@ import java.util.Arrays; +@@ -26,6 +26,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -953,7 +952,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore /** * Creates historical entries in TabRestoreService. */ -@@ -60,10 +62,10 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { +@@ -59,10 +61,10 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { // HistoricalTabSaver implementation. @Override @@ -966,7 +965,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore } @Override -@@ -115,7 +117,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { +@@ -114,7 +116,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { // If there is only a single valid tab remaining save it individually. if (validEntries.size() == 1 && validEntries.get(0).isSingleTab()) { @@ -976,7 +975,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore } @@ -140,11 +142,12 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { - CollectionUtil.integerListToIntArray(savedStateVersions)); + CollectionUtil.integerCollectionToIntArray(savedStateVersions)); } - private void createHistoricalTabInternal(Tab tab) { @@ -999,7 +998,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore // {@link GURL#getScheme()} is not available in unit tests. if (mIgnoreUrlSchemesForTesting) return true; -@@ -225,7 +228,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { +@@ -224,7 +227,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver { @NativeMethods interface Natives { @@ -1011,7 +1010,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java -@@ -125,6 +125,8 @@ import org.chromium.components.webapps.bottomsheet.PwaBottomSheetControllerFacto +@@ -123,6 +123,8 @@ import org.chromium.components.webapps.bottomsheet.PwaBottomSheetControllerFacto import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.DeviceFormFactor; @@ -1020,7 +1019,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab import org.chromium.ui.base.IntentRequestTracker; import org.chromium.ui.modaldialog.ModalDialogManager; -@@ -797,7 +799,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { +@@ -794,7 +796,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { mAppMenuCoordinator.getAppMenuHandler(), mActivityTabProvider, mToolbarManager.getMenuButtonView(), () -> { mTabCreatorManagerSupplier.get() @@ -1100,7 +1099,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPer diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java -@@ -37,6 +37,7 @@ import org.chromium.base.supplier.OneshotSupplier; +@@ -40,6 +40,7 @@ import org.chromium.base.supplier.OneshotSupplier; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; @@ -1108,7 +1107,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.app.tab_activity_glue.TabReparentingController; import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton; -@@ -500,7 +501,8 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +@@ -509,7 +510,8 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve return ret; } }, @@ -1131,16 +1130,16 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappI /** * Stores info about a web app. */ -@@ -45,6 +48,8 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider - private final Intent mIntent; +@@ -46,6 +49,8 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider private final ColorProviderImpl mColorProvider; + private final ColorProviderImpl mDarkColorProvider; + private boolean mIsIncognito = false; + /** * Returns the toolbar color to use if a custom color is not specified by the webapp. */ -@@ -67,6 +72,10 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider +@@ -77,6 +82,10 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider mWebappExtras = webappExtras; mWebApkExtras = webApkExtras; mActivityType = (webApkExtras != null) ? ActivityType.WEB_APK : ActivityType.WEBAPP; @@ -1151,7 +1150,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappI } @Override -@@ -147,6 +156,11 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider +@@ -162,6 +171,11 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider return mWebApkExtras; } @@ -1166,7 +1165,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappI diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5073,6 +5073,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5136,6 +5136,10 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kOfflinePagesLivePageSharingName, flag_descriptions::kOfflinePagesLivePageSharingDescription, kOsAndroid, FEATURE_VALUE_TYPE(offline_pages::kOfflinePagesLivePageSharingFeature)}, @@ -1240,7 +1239,7 @@ diff --git a/chrome/browser/android/historical_tab_saver.cc b/chrome/browser/and diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc -@@ -350,6 +350,15 @@ ChromeAutocompleteProviderClient::GetOnDeviceTailModelService() const { +@@ -343,6 +343,15 @@ ChromeAutocompleteProviderClient::GetOnDeviceTailModelService() const { #endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB) } @@ -1259,7 +1258,7 @@ diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h -@@ -86,6 +86,7 @@ class ChromeAutocompleteProviderClient : public AutocompleteProviderClient { +@@ -84,6 +84,7 @@ class ChromeAutocompleteProviderClient : public AutocompleteProviderClient { const override; OnDeviceTailModelService* GetOnDeviceTailModelService() const override; bool IsOffTheRecord() const override; @@ -1276,9 +1275,9 @@ diff --git a/chrome/browser/autocomplete/remote_suggestions_service_factory.cc b +#include "build/build_config.h" #include "base/no_destructor.h" + #include "chrome/browser/autocomplete/document_suggestions_service_factory.h" #include "chrome/browser/profiles/profile.h" - #include "components/omnibox/browser/remote_suggestions_service.h" -@@ -36,7 +37,11 @@ RemoteSuggestionsServiceFactory::RemoteSuggestionsServiceFactory() +@@ -39,7 +40,11 @@ RemoteSuggestionsServiceFactory::RemoteSuggestionsServiceFactory() : ProfileKeyedServiceFactory( "RemoteSuggestionsService", ProfileSelections::Builder() @@ -1341,7 +1340,7 @@ diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.c diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4047,6 +4047,12 @@ const char kOfflinePagesLivePageSharingDescription[] = +@@ -4111,6 +4111,12 @@ const char kOfflinePagesLivePageSharingDescription[] = "Enables to share current loaded page as offline page by saving as MHTML " "first."; @@ -1357,7 +1356,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2358,6 +2358,9 @@ extern const char kOmahaMinSdkVersionAndroidDescription[]; +@@ -2411,6 +2411,9 @@ extern const char kOmahaMinSdkVersionAndroidDescription[]; extern const char kOmahaMinSdkVersionAndroidMinSdk1Description[]; extern const char kOmahaMinSdkVersionAndroidMinSdk1000Description[]; @@ -1370,7 +1369,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -537,8 +537,8 @@ BASE_FEATURE(kCCTFeatureUsage, +@@ -554,8 +554,8 @@ BASE_FEATURE(kCCTFeatureUsage, BASE_FEATURE(kCCTIncognito, "CCTIncognito", base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kCCTIncognitoAvailableToThirdParty, @@ -1394,7 +1393,7 @@ diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/histo #else #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" -@@ -474,6 +477,13 @@ void HistoryTabHelper::TitleWasSet(NavigationEntry* entry) { +@@ -476,6 +479,13 @@ void HistoryTabHelper::TitleWasSet(NavigationEntry* entry) { history::HistoryService* HistoryTabHelper::GetHistoryService() { Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); @@ -1408,7 +1407,7 @@ diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/histo if (profile->IsOffTheRecord()) return nullptr; -@@ -481,6 +491,16 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() { +@@ -483,6 +493,16 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() { profile, ServiceAccessType::IMPLICIT_ACCESS); } @@ -1704,15 +1703,15 @@ diff --git a/chrome/browser/offline_pages/request_coordinator_factory.h b/chrome diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -232,6 +232,7 @@ - #include "components/feed/core/shared_prefs/pref_names.h" +@@ -236,6 +236,7 @@ #if BUILDFLAG(IS_ANDROID) + #include "chrome/browser/accessibility/accessibility_prefs/android/accessibility_prefs_controller.h" +#include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/android/bookmarks/partner_bookmarks_shim.h" #include "chrome/browser/android/ntp/recent_tabs_page_prefs.h" #include "chrome/browser/android/oom_intervention/oom_intervention_decider.h" -@@ -1698,6 +1699,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, +@@ -1796,6 +1797,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, usage_stats::UsageStatsBridge::RegisterProfilePrefs(registry); variations::VariationsService::RegisterProfilePrefs(registry); webapps::InstallPromptPrefs::RegisterProfilePrefs(registry); @@ -1851,9 +1850,9 @@ diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1384,6 +1384,37 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1408,6 +1408,37 @@ Your Google account may have other forms of browsing history like searches and a - Clears history from all synced devices. + Clears history from all synced devices + + @@ -1892,7 +1891,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java -@@ -179,6 +179,7 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro +@@ -178,6 +178,7 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro protected String mFormattedFullUrl; protected String mUrlForDisplay; private boolean mOmniboxUpdatedConnectionSecurityIndicatorsEnabled; @@ -1900,7 +1899,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow // notifyUrlChanged and notifySecurityStateChanged are usually called 3 times across a same // document navigation. The first call is usually necessary, which updates the UrlBar to reflect -@@ -204,7 +205,9 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro +@@ -200,7 +201,9 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro public LocationBarModel(Context context, NewTabPageDelegate newTabPageDelegate, @NonNull UrlFormatter urlFormatter, @NonNull ProfileProvider profileProvider, @NonNull OfflineStatus offlineStatus, @@ -1954,49 +1953,26 @@ new file mode 100644 +public interface INeedSnackbarManager { + void setSnackbarManager(SnackbarManager manager); +} -diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc ---- a/chrome/common/pref_names.cc -+++ b/chrome/common/pref_names.cc -@@ -3460,6 +3460,12 @@ const char kLacrosLaunchSwitch[] = "lacros_launch_switch"; - const char kLacrosSelection[] = "lacros_selection"; - #endif - -+#if BUILDFLAG(IS_ANDROID) -+const char kAlwaysIncognitoEnabled[] = "always_incognito_enabled"; -+const char kIncognitoTabHistoryEnabled[] = "incognito_tab_history_enabled"; -+const char kIncognitoSaveSiteSettingEnabled[] = "incognito_site_setting_enabled"; -+#endif -+ - #if BUILDFLAG(IS_CHROMEOS_ASH) - // String enum pref determining what should happen when a user who authenticates - // via a security token is removing this token. "IGNORE" - nothing happens diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h -@@ -1214,6 +1214,8 @@ extern const char kDiscountConsentShowInterestIn[]; - - #if BUILDFLAG(IS_ANDROID) - extern const char kWebXRImmersiveArEnabled[]; -+extern const char kAlwaysIncognitoEnabled[]; -+extern const char kIncognitoSaveSiteSettingEnabled[]; - #endif - - #if !BUILDFLAG(IS_ANDROID) -@@ -1255,6 +1257,10 @@ extern const char kPrivacyGuideViewed[]; - - extern const char kCorsNonWildcardRequestHeadersSupport[]; +@@ -3942,6 +3942,12 @@ inline constexpr char kOutOfProcessSystemDnsResolutionEnabled[] = + "net.out_of_process_system_dns_resolution_enabled"; + #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) +#if BUILDFLAG(IS_ANDROID) -+extern const char kIncognitoTabHistoryEnabled[]; ++inline constexpr char kAlwaysIncognitoEnabled[] = "always_incognito_enabled"; ++inline constexpr char kIncognitoSaveSiteSettingEnabled[] = "incognito_tab_history_enabled"; ++inline constexpr char kIncognitoTabHistoryEnabled[] = "incognito_site_setting_enabled"; +#endif + - extern const char kOriginAgentClusterDefaultEnabled[]; + // A list of hostnames to disable HTTPS Upgrades / HTTPS-First Mode warnings on. + inline constexpr char kHttpAllowlist[] = "https_upgrades.policy.http_allowlist"; - extern const char kForceMajorVersionToMinorPositionInUserAgent[]; diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc --- a/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc -@@ -86,10 +86,12 @@ void PrefProvider::RegisterProfilePrefs( +@@ -87,10 +87,12 @@ void PrefProvider::RegisterProfilePrefs( PrefProvider::PrefProvider(PrefService* prefs, bool off_the_record, @@ -2009,7 +1985,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov store_last_modified_(store_last_modified), clock_(base::DefaultClock::GetInstance()) { TRACE_EVENT_BEGIN("startup", "PrefProvider::PrefProvider"); -@@ -112,10 +114,14 @@ PrefProvider::PrefProvider(PrefService* prefs, +@@ -113,10 +115,14 @@ PrefProvider::PrefProvider(PrefService* prefs, WebsiteSettingsRegistry* website_settings = WebsiteSettingsRegistry::GetInstance(); for (const WebsiteSettingsInfo* info : *website_settings) { @@ -2036,7 +2012,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov bool store_last_modified, bool restore_session); -@@ -93,6 +94,7 @@ class PrefProvider : public UserModifiableProvider { +@@ -110,6 +111,7 @@ class PrefProvider : public UserModifiableProvider { raw_ptr prefs_; const bool off_the_record_; @@ -2047,7 +2023,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc -@@ -276,6 +276,7 @@ struct ContentSettingEntry { +@@ -280,6 +280,7 @@ struct ContentSettingEntry { HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, bool is_off_the_record, @@ -2055,7 +2031,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. bool store_last_modified, bool restore_session, bool should_record_metrics) -@@ -285,6 +286,7 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, +@@ -289,6 +290,7 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, #endif prefs_(prefs), is_off_the_record_(is_off_the_record), @@ -2063,7 +2039,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. store_last_modified_(store_last_modified), allow_invalid_secondary_pattern_for_testing_(false), clock_(base::DefaultClock::GetInstance()) { -@@ -297,7 +299,7 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, +@@ -301,7 +303,7 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, policy_provider->AddObserver(this); auto pref_provider_ptr = std::make_unique( @@ -2083,7 +2059,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. bool store_last_modified, bool restore_session, bool should_record_metrics); -@@ -507,6 +508,8 @@ class HostContentSettingsMap : public content_settings::Observer, +@@ -521,6 +522,8 @@ class HostContentSettingsMap : public content_settings::Observer, // Whether this settings map is for an incognito or guest session. bool is_off_the_record_; @@ -2130,7 +2106,7 @@ diff --git a/components/omnibox/browser/autocomplete_provider_client.cc b/compon diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h --- a/components/omnibox/browser/autocomplete_provider_client.h +++ b/components/omnibox/browser/autocomplete_provider_client.h -@@ -139,6 +139,7 @@ class AutocompleteProviderClient : public OmniboxAction::Client { +@@ -136,6 +136,7 @@ class AutocompleteProviderClient : public OmniboxAction::Client { virtual bool IsOffTheRecord() const = 0; virtual bool IsIncognitoProfile() const = 0; virtual bool IsGuestSession() const = 0; diff --git a/build/patches/Add-autoplay-site-setting.patch b/build/patches/Add-autoplay-site-setting.patch index 0ac0787e..a242e6d3 100644 --- a/build/patches/Add-autoplay-site-setting.patch +++ b/build/patches/Add-autoplay-site-setting.patch @@ -278,7 +278,7 @@ new file mode 100644 diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc -@@ -244,7 +244,7 @@ void ContentSettingsRegistry::Init() { +@@ -246,7 +246,7 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::INHERIT_IN_INCOGNITO, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); diff --git a/build/patches/Add-bookmark-import-export-actions.patch b/build/patches/Add-bookmark-import-export-actions.patch index e6e98752..db8874e9 100644 --- a/build/patches/Add-bookmark-import-export-actions.patch +++ b/build/patches/Add-bookmark-import-export-actions.patch @@ -25,10 +25,10 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../bookmarks/BookmarkToolbarViewBinder.java | 6 + .../native_page/NativePageFactory.java | 11 +- chrome/browser/BUILD.gn | 11 +- - chrome/browser/about_flags.cc | 6 + + chrome/browser/about_flags.cc | 8 + .../bookmarks/android/bookmark_bridge.cc | 283 ++++++++++++++++++ .../bookmarks/android/bookmark_bridge.h | 30 +- - .../browser/bookmarks/bookmark_html_writer.cc | 8 +- + .../browser/bookmarks/bookmark_html_writer.cc | 11 + .../dialogs/DownloadLocationCustomView.java | 8 +- .../DownloadLocationDialogCoordinator.java | 8 +- chrome/browser/flag_descriptions.cc | 5 + @@ -44,12 +44,14 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html chrome/utility/BUILD.gn | 7 +- .../utility/importer/bookmark_html_reader.cc | 27 +- .../utility/importer/bookmark_html_reader.h | 8 + + .../headless_select_file_dialog.cc | 4 + .../chromium/ui/base/SelectFileDialog.java | 18 +- .../java/strings/android_ui_strings.grd | 3 + ui/shell_dialogs/select_file_dialog.h | 2 + .../select_file_dialog_android.cc | 6 + ui/shell_dialogs/select_file_dialog_android.h | 2 + - 39 files changed, 886 insertions(+), 30 deletions(-) + ui/shell_dialogs/select_file_dialog_win.cc | 5 + + 41 files changed, 901 insertions(+), 29 deletions(-) diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml @@ -89,15 +91,15 @@ diff --git a/chrome/android/java/res/menu/bookmark_toolbar_menu.xml b/chrome/and diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java --- a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java -@@ -9,6 +9,7 @@ import android.app.Activity; - import androidx.annotation.Nullable; +@@ -10,6 +10,7 @@ import androidx.annotation.Nullable; + import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.tab_activity_glue.ActivityTabWebContentsDelegateAndroid; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.compositor.CompositorViewHolder; -@@ -47,7 +48,7 @@ import org.chromium.ui.modaldialog.ModalDialogManager; +@@ -49,7 +50,7 @@ import org.chromium.ui.modaldialog.ModalDialogManager; * {@link ChromeTabbedActivity}. */ public class TabbedModeTabDelegateFactory implements TabDelegateFactory { @@ -106,7 +108,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDe private final BrowserControlsVisibilityDelegate mAppBrowserControlsVisibilityDelegate; private final Supplier mShareDelegateSupplier; private final Supplier mEphemeralTabCoordinatorSupplier; -@@ -71,7 +72,7 @@ public class TabbedModeTabDelegateFactory implements TabDelegateFactory { +@@ -74,7 +75,7 @@ public class TabbedModeTabDelegateFactory implements TabDelegateFactory { private NativePageFactory mNativePageFactory; @@ -244,7 +246,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * Provides the communication channel for Android to fetch and manipulate the * bookmark model stored in native. -@@ -435,6 +474,209 @@ class BookmarkBridge { +@@ -432,6 +471,209 @@ class BookmarkBridge { mNativeBookmarkBridge, BookmarkBridge.this, id.getId(), id.getType()); } @@ -454,7 +456,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * Synchronously gets a list of bookmarks that match the specified search query. * @param query Keyword used for searching bookmarks. -@@ -919,6 +1161,39 @@ class BookmarkBridge { +@@ -931,6 +1173,39 @@ class BookmarkBridge { depthList.add(depth); } @@ -494,7 +496,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm private static List> createPairsList(int[] left, int[] right) { List> pairList = new ArrayList<>(); for (int i = 0; i < left.length; i++) { -@@ -954,6 +1229,9 @@ class BookmarkBridge { +@@ -966,6 +1241,9 @@ class BookmarkBridge { int getChildCount(long nativeBookmarkBridge, BookmarkBridge caller, long id, int type); void getChildIds(long nativeBookmarkBridge, BookmarkBridge caller, long id, int type, List bookmarksList); @@ -553,7 +555,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java -@@ -56,6 +56,8 @@ import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelega +@@ -51,6 +51,8 @@ import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelega import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate.SelectionObserver; import org.chromium.components.commerce.core.CommerceSubscription; import org.chromium.components.commerce.core.ShoppingService; @@ -562,7 +564,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.power_bookmarks.PowerBookmarkMeta; -@@ -80,6 +82,9 @@ class BookmarkManagerMediator +@@ -77,6 +79,9 @@ class BookmarkManagerMediator private static boolean sPreventLoadingForTesting; @@ -572,7 +574,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * Keeps track of whether drag is enabled / active for bookmark lists. */ -@@ -453,6 +458,14 @@ class BookmarkManagerMediator +@@ -461,6 +466,14 @@ class BookmarkManagerMediator mNativePage = nativePage; } @@ -587,7 +589,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * See BookmarkManager(Coordinator)#updateForUrl */ -@@ -628,6 +641,16 @@ class BookmarkManagerMediator +@@ -635,6 +648,16 @@ class BookmarkManagerMediator } } @@ -603,11 +605,11 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm + @Override public void openSearchUi() { - setState(BookmarkUiState.createSearchState()); + onQueryCallback(""); diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java -@@ -15,6 +15,9 @@ import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +@@ -13,6 +13,9 @@ import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.native_page.BasicNativePage; import org.chromium.chrome.browser.ui.native_page.NativePageHost; import org.chromium.components.embedder_support.util.UrlConstants; @@ -617,7 +619,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * A native page holding a {@link BookmarkManagerCoordinator} on _tablet_. -@@ -31,7 +34,7 @@ public class BookmarkPage extends BasicNativePage { +@@ -29,7 +32,7 @@ public class BookmarkPage extends BasicNativePage { * @param host A NativePageHost to load urls. */ public BookmarkPage(ComponentName componentName, SnackbarManager snackbarManager, @@ -626,7 +628,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm super(host); mBookmarkManagerCoordinator = -@@ -39,6 +42,9 @@ public class BookmarkPage extends BasicNativePage { +@@ -37,6 +40,9 @@ public class BookmarkPage extends BasicNativePage { snackbarManager, Profile.getLastUsedRegularProfile(), new BookmarkUiPrefs(SharedPreferencesManager.getInstance())); mBookmarkManagerCoordinator.setBasicNativePage(this); @@ -657,7 +659,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm void setSearchButtonVisible(boolean visible) { // The improved bookmarks experience embeds search in the list. if (BookmarkFeatures.isAndroidImprovedBookmarksEnabled()) return; -@@ -147,6 +158,8 @@ public class BookmarkToolbar extends SelectableListToolbar +@@ -156,6 +167,8 @@ public class BookmarkToolbar extends SelectableListToolbar void setCurrentFolder(BookmarkId folder) { mCurrentFolder = mBookmarkModel.getBookmarkById(folder); @@ -665,8 +667,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm + getMenu().findItem(R.id.export_menu_id).setVisible(true); } - void setOpenFolderCallback(Callback openFolderCallback) { -@@ -166,6 +179,13 @@ public class BookmarkToolbar extends SelectableListToolbar + void setNavigateBackRunnable(Runnable navigateBackRunnable) { +@@ -175,6 +188,13 @@ public class BookmarkToolbar extends SelectableListToolbar @Override public boolean onMenuItemClick(MenuItem menuItem) { hideOverflowMenu(); @@ -680,7 +682,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm return mMenuIdClickedFunction.apply(menuItem.getItemId()); } -@@ -186,6 +206,9 @@ public class BookmarkToolbar extends SelectableListToolbar +@@ -195,6 +215,9 @@ public class BookmarkToolbar extends SelectableListToolbar protected void showNormalView() { super.showNormalView(); @@ -695,8 +697,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarMediator.java @@ -81,6 +81,10 @@ class BookmarkToolbarMediator implements BookmarkUiObserver, DragListener, mBookmarkDelegate = bookmarkDelegate; - mModel.set( - BookmarkToolbarProperties.OPEN_FOLDER_CALLBACK, mBookmarkDelegate::openFolder); + mModel.set(BookmarkToolbarProperties.NAVIGATE_BACK_RUNNABLE, + this::openParentForCurrentFolder); + mModel.set( + BookmarkToolbarProperties.IMPORT_BOOKMARK_RUNNABLE, mBookmarkDelegate::importBookmarks); + mModel.set( @@ -707,9 +709,9 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarProperties.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarProperties.java -@@ -60,10 +60,15 @@ class BookmarkToolbarProperties { +@@ -61,11 +61,16 @@ class BookmarkToolbarProperties { new WritableObjectPropertyKey<>(); - static final WritableObjectPropertyKey> OPEN_FOLDER_CALLBACK = + static final WritableObjectPropertyKey NAVIGATE_BACK_RUNNABLE = new WritableObjectPropertyKey<>(); + static final WritableObjectPropertyKey IMPORT_BOOKMARK_RUNNABLE = + new WritableObjectPropertyKey<>(); @@ -719,15 +721,16 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm static final PropertyKey[] ALL_KEYS = {BOOKMARK_MODEL, BOOKMARK_OPENER, SELECTION_DELEGATE, TITLE, BOOKMARK_UI_MODE, SOFT_KEYBOARD_VISIBLE, IS_DIALOG_UI, DRAG_ENABLED, SEARCH_BUTTON_VISIBLE, EDIT_BUTTON_VISIBLE, NEW_FOLDER_BUTTON_VISIBLE, - NAVIGATION_BUTTON_STATE, CURRENT_FOLDER, CHECKED_SORT_MENU_ID, CHECKED_VIEW_MENU_ID, -- MENU_ID_CLICKED_FUNCTION, OPEN_FOLDER_CALLBACK, FAKE_SELECTION_STATE_CHANGE}; -+ MENU_ID_CLICKED_FUNCTION, OPEN_FOLDER_CALLBACK, FAKE_SELECTION_STATE_CHANGE, + NEW_FOLDER_BUTTON_ENABLED, NAVIGATION_BUTTON_STATE, CURRENT_FOLDER, + CHECKED_SORT_MENU_ID, CHECKED_VIEW_MENU_ID, MENU_ID_CLICKED_FUNCTION, +- NAVIGATE_BACK_RUNNABLE, FAKE_SELECTION_STATE_CHANGE}; ++ NAVIGATE_BACK_RUNNABLE, FAKE_SELECTION_STATE_CHANGE, + IMPORT_BOOKMARK_RUNNABLE, EXPORT_BOOKMARK_RUNNABLE}; } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarViewBinder.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarViewBinder.java -@@ -53,6 +53,12 @@ class BookmarkToolbarViewBinder { +@@ -56,6 +56,12 @@ class BookmarkToolbarViewBinder { model.get(BookmarkToolbarProperties.CHECKED_VIEW_MENU_ID)); } else if (key == BookmarkToolbarProperties.CURRENT_FOLDER) { bookmarkToolbar.setCurrentFolder(model.get(BookmarkToolbarProperties.CURRENT_FOLDER)); @@ -737,21 +740,21 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm + } else if (key == BookmarkToolbarProperties.EXPORT_BOOKMARK_RUNNABLE) { + bookmarkToolbar.setExportBookmarkRunnable( + model.get(BookmarkToolbarProperties.EXPORT_BOOKMARK_RUNNABLE)); - } else if (key == BookmarkToolbarProperties.OPEN_FOLDER_CALLBACK) { - bookmarkToolbar.setOpenFolderCallback( - model.get(BookmarkToolbarProperties.OPEN_FOLDER_CALLBACK)); + } else if (key == BookmarkToolbarProperties.NAVIGATE_BACK_RUNNABLE) { + bookmarkToolbar.setNavigateBackRunnable( + model.get(BookmarkToolbarProperties.NAVIGATE_BACK_RUNNABLE)); diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java --- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java -@@ -14,6 +14,7 @@ import androidx.annotation.VisibleForTesting; - +@@ -15,6 +15,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.supplier.DestroyableObservableSupplier; + import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.download.home.DownloadPage; import org.chromium.chrome.browser.bookmarks.BookmarkPage; import org.chromium.chrome.browser.browser_controls.BrowserControlsMarginSupplier; -@@ -51,7 +52,7 @@ import org.chromium.ui.util.ColorUtils; +@@ -53,7 +54,7 @@ import org.chromium.ui.util.ColorUtils; * Creates NativePage objects to show chrome-native:// URLs using the native Android view system. */ public class NativePageFactory { @@ -760,7 +763,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/Nat private final BottomSheetController mBottomSheetController; private final BrowserControlsManager mBrowserControlsManager; private final Supplier mCurrentTabSupplier; -@@ -66,7 +67,7 @@ public class NativePageFactory { +@@ -69,7 +70,7 @@ public class NativePageFactory { private NativePageBuilder mNativePageBuilder; @@ -769,7 +772,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/Nat @NonNull BottomSheetController sheetController, @NonNull BrowserControlsManager browserControlsManager, @NonNull Supplier currentTabSupplier, -@@ -109,7 +110,7 @@ public class NativePageFactory { +@@ -115,7 +116,7 @@ public class NativePageFactory { @VisibleForTesting static class NativePageBuilder { @@ -778,16 +781,16 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/Nat private final BottomSheetController mBottomSheetController; private final Supplier mUma; private final BrowserControlsManager mBrowserControlsManager; -@@ -122,7 +123,7 @@ public class NativePageFactory { - private final Supplier mToolbarSupplier; +@@ -129,7 +130,7 @@ public class NativePageFactory { private final HomeSurfaceTracker mHomeSurfaceTracker; + private final ObservableSupplier mTabContentManagerSupplier; - public NativePageBuilder(Activity activity, Supplier uma, + public NativePageBuilder(ChromeActivity activity, Supplier uma, BottomSheetController sheetController, BrowserControlsManager browserControlsManager, Supplier currentTabSupplier, Supplier snackbarManagerSupplier, -@@ -159,7 +160,7 @@ public class NativePageFactory { +@@ -169,7 +170,7 @@ public class NativePageFactory { protected NativePage buildBookmarksPage(Tab tab) { return new BookmarkPage(mActivity.getComponentName(), mSnackbarManagerSupplier.get(), mTabModelSelector.isIncognitoSelected(), @@ -799,7 +802,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/Nat diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -204,6 +204,8 @@ static_library("browser") { +@@ -225,6 +225,8 @@ static_library("browser") { "bluetooth/chrome_bluetooth_delegate_impl_client.h", "bookmarks/bookmark_model_factory.cc", "bookmarks/bookmark_model_factory.h", @@ -808,9 +811,9 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "bookmarks/chrome_bookmark_client.cc", "bookmarks/chrome_bookmark_client.h", "bookmarks/managed_bookmark_service_factory.cc", -@@ -1873,6 +1875,13 @@ static_library("browser") { - "webid/federated_identity_permission_context_factory.h", - ] +@@ -1901,6 +1903,13 @@ static_library("browser") { + ] + } + if (is_android) { + sources += [ @@ -822,7 +825,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn configs += [ "//build/config/compiler:wexit_time_destructors", "//build/config:precompiled_headers", -@@ -3498,8 +3507,6 @@ static_library("browser") { +@@ -3587,8 +3596,6 @@ static_library("browser") { "badging/badge_manager_factory.h", "banners/app_banner_manager_desktop.cc", "banners/app_banner_manager_desktop.h", @@ -834,15 +837,17 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9361,6 +9361,12 @@ const FeatureEntry kFeatureEntries[] = { - FEATURE_VALUE_TYPE(features::kRequestDesktopSiteExceptions)}, +@@ -9471,6 +9471,14 @@ const FeatureEntry kFeatureEntries[] = { + FEATURE_VALUE_TYPE(features::kForceOffTextAutosizing)}, #endif ++#if BUILDFLAG(IS_ANDROID) + {"export-bookmarks-use-saf", + flag_descriptions::kBookmarksExportUseSafName, + flag_descriptions::kBookmarksExportUseSafDescription, kOsAndroid, + FEATURE_VALUE_TYPE( + chrome::android::kBookmarksExportUseSaf)}, ++#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) {"video-conference", flag_descriptions::kVideoConferenceName, @@ -1254,25 +1259,29 @@ diff --git a/chrome/browser/bookmarks/android/bookmark_bridge.h b/chrome/browser diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc --- a/chrome/browser/bookmarks/bookmark_html_writer.cc +++ b/chrome/browser/bookmarks/bookmark_html_writer.cc -@@ -27,6 +27,7 @@ +@@ -27,6 +27,9 @@ #include "base/task/thread_pool.h" #include "base/time/time.h" #include "base/values.h" ++#if BUILDFLAG(IS_ANDROID) +#include "base/android/content_uri_utils.h" ++#endif #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" -@@ -229,7 +230,12 @@ class Writer : public base::RefCountedThreadSafe { +@@ -229,7 +232,15 @@ class Writer : public base::RefCountedThreadSafe { // Opens the file, returning true on success. bool OpenFile() { int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; -- file_ = std::make_unique(path_, flags); ++#if BUILDFLAG(IS_ANDROID) + if (path_.IsContentUri()) { + file_ = std::make_unique(base::OpenContentUriForWrite(path_)); + } else { + file_ = std::make_unique(path_, flags); + } -+ ++#else + file_ = std::make_unique(path_, flags); ++#endif if (!file_->IsValid()) { PLOG(ERROR) << "Could not create " << path_; return false; @@ -1346,9 +1355,9 @@ diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browse diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -7346,6 +7346,11 @@ const char kEnableAudioFocusEnforcementDescription[] = - "any one time. Requires #enable-media-session-service to be enabled too."; - #endif // BUILDFLAG(IS_CHROMEOS_ASH) +@@ -7520,6 +7520,11 @@ const char kThirdPartyProfileManagementDescription[] = + "Enables profile management triggered by third-party sign-ins."; + #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) +const char kBookmarksExportUseSafName[] = "Use saf for bookmarks export"; +const char kBookmarksExportUseSafDescription[] = @@ -1361,9 +1370,9 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -4246,6 +4246,9 @@ extern const char kEnableAudioFocusEnforcementName[]; - extern const char kEnableAudioFocusEnforcementDescription[]; - #endif // BUILDFLAG(IS_CHROMEOS_ASH) +@@ -4350,6 +4350,9 @@ extern const char kThirdPartyProfileManagementName[]; + extern const char kThirdPartyProfileManagementDescription[]; + #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) +extern const char kBookmarksExportUseSafName[]; +extern const char kBookmarksExportUseSafDescription[]; @@ -1374,7 +1383,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -176,6 +176,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -180,6 +180,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kClearOmniboxFocusAfterNavigation, &kCloseTabSuggestions, &kCloseTabSaveTabList, @@ -1382,7 +1391,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &kCriticalPersistedTabData, &kCreateNewTabInitializeRenderer, &kCCTBackgroundTab, -@@ -1155,5 +1156,10 @@ BASE_FEATURE(kWebApkTrampolineOnInitialIntent, +@@ -1173,5 +1174,10 @@ BASE_FEATURE(kWebApkTrampolineOnInitialIntent, "WebApkTrampolineOnInitialIntent", base::FEATURE_ENABLED_BY_DEFAULT); @@ -1396,7 +1405,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -177,6 +177,7 @@ BASE_DECLARE_FEATURE(kTabStripRedesign); +@@ -185,6 +185,7 @@ BASE_DECLARE_FEATURE(kTabStripRedesign); BASE_DECLARE_FEATURE(kTabletToolbarReordering); BASE_DECLARE_FEATURE(kTabStripStartupRefactoring); BASE_DECLARE_FEATURE(kTabToGTSAnimation); @@ -1407,10 +1416,10 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -472,6 +472,7 @@ public abstract class ChromeFeatureList { - public static final String USE_CHIME_ANDROID_SDK = "UseChimeAndroidSdk"; +@@ -478,6 +478,7 @@ public abstract class ChromeFeatureList { public static final String USE_LIBUNWINDSTACK_NATIVE_UNWINDER_ANDROID = "UseLibunwindstackNativeUnwinderAndroid"; + public static final String USER_BYPASS_UI = "UserBypassUI"; + public static final String BOOKMARKS_EXPORT_USESAF = "BookmarksExportUseSaf"; public static final String VOICE_BUTTON_IN_TOP_TOOLBAR = "VoiceButtonInTopToolbar"; public static final String VOICE_SEARCH_AUDIO_CAPTURE_POLICY = "VoiceSearchAudioCapturePolicy"; @@ -1485,7 +1494,7 @@ diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/bro /** * Whether Chrome is set as the default browser. -@@ -984,6 +986,7 @@ public final class ChromePreferenceKeys { +@@ -982,6 +984,7 @@ public final class ChromePreferenceKeys { AUTOFILL_ASSISTANT_PROACTIVE_HELP_ENABLED, APP_LAUNCH_LAST_KNOWN_ACTIVE_TAB_STATE, APP_LAUNCH_SEARCH_ENGINE_HAD_LOGO, @@ -1496,7 +1505,7 @@ diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/bro diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -240,6 +240,24 @@ CHAR_LIMIT guidelines: +@@ -245,6 +245,24 @@ CHAR_LIMIT guidelines: Sites @@ -1524,7 +1533,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn -@@ -414,6 +414,9 @@ static_library("common_lib") { +@@ -400,6 +400,9 @@ static_library("common_lib") { sources += [ "media/chrome_media_drm_bridge_client.cc", "media/chrome_media_drm_bridge_client.h", @@ -1537,7 +1546,7 @@ diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn -@@ -89,8 +89,6 @@ static_library("utility") { +@@ -85,8 +85,6 @@ static_library("utility") { if (!is_android) { sources += [ @@ -1546,7 +1555,7 @@ diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn "importer/bookmarks_file_importer.cc", "importer/bookmarks_file_importer.h", "importer/external_process_importer_bridge.cc", -@@ -220,6 +218,11 @@ static_library("utility") { +@@ -215,6 +213,11 @@ static_library("utility") { ] } @@ -1658,17 +1667,31 @@ diff --git a/chrome/utility/importer/bookmark_html_reader.h b/chrome/utility/imp // Returns true if |url| should be imported as a search engine, i.e. because it // has replacement terms. Chrome treats such bookmarks as search engines rather // than true bookmarks. +diff --git a/components/headless/select_file_dialog/headless_select_file_dialog.cc b/components/headless/select_file_dialog/headless_select_file_dialog.cc +--- a/components/headless/select_file_dialog/headless_select_file_dialog.cc ++++ b/components/headless/select_file_dialog/headless_select_file_dialog.cc +@@ -58,6 +58,10 @@ class HeadlessSelectFileDialog : public ui::SelectFileDialog { + // ui::SelectFileDialog: + bool HasMultipleFileTypeChoicesImpl() override { return false; } + ++ void ShowToast(const std::string& message) override { ++ // nothing to do, used only on android ++ } ++ + SelectFileDialogCallback callback_; + }; + diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java --- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java +++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java -@@ -44,6 +44,7 @@ import org.chromium.base.task.AsyncTask; +@@ -45,6 +45,7 @@ import org.chromium.base.task.AsyncTask; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.ui.R; +import org.chromium.ui.widget.Toast; import org.chromium.ui.UiUtils; - import org.chromium.ui.permissions.PermissionConstants; + import java.io.File; @@ -67,6 +68,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick private static final String TAG = "SelectFileDialog"; private static final String IMAGE_TYPE = "image"; @@ -1677,8 +1700,8 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui private static final String AUDIO_TYPE = "audio"; private static final String ALL_TYPES = "*/*"; -@@ -263,6 +265,11 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick - mFileTypes = fileTypes; +@@ -264,6 +266,11 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick + ResettersForTesting.register(() -> mFileTypes = oldValue); } + @CalledByNative @@ -1689,7 +1712,7 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui /** * Creates and starts an intent based on the passed fileTypes and capture value. * @param fileTypes MIME types requested (i.e. "image/*") -@@ -289,7 +296,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick +@@ -290,7 +297,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick List missingPermissions = new ArrayList<>(); String storagePermission = Manifest.permission.READ_EXTERNAL_STORAGE; boolean shouldUsePhotoPicker = shouldUsePhotoPicker(); @@ -1698,7 +1721,7 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui // The permission scenario for accessing media has evolved a bit over the years: // Early on, READ_EXTERNAL_STORAGE was required to access media, but that permission was // later deprecated. In its place (starting with Android T) READ_MEDIA_IMAGES and -@@ -338,7 +345,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick +@@ -339,7 +346,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick } // TODO(finnur): Remove once we figure out the cause of crbug.com/950024. @@ -1707,16 +1730,16 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui if (permissions.length != requestPermissions.length) { throw new RuntimeException( String.format("Permissions arrays misaligned: %d != %d", -@@ -352,7 +359,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick +@@ -353,7 +360,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick } } - if (shouldUsePhotoPicker) { + if (shouldUsePhotoPicker || shouldShowHtmlTypes()) { if (permissions[i].equals(storagePermission) - || permissions[i].equals(PermissionConstants.READ_MEDIA_IMAGES) + || permissions[i].equals(Manifest.permission.READ_MEDIA_IMAGES) || permissions[i].equals( -@@ -629,6 +636,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick +@@ -630,6 +637,7 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick } if (!mimeTypes.contains(mimeType)) mimeTypes.add(mimeType); } @@ -1724,7 +1747,7 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui return mimeTypes; } -@@ -957,6 +965,10 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick +@@ -958,6 +966,10 @@ public class SelectFileDialog implements WindowAndroid.IntentCallback, PhotoPick return countAcceptTypesFor(superType) == mFileTypes.size(); } @@ -1788,5 +1811,27 @@ diff --git a/ui/shell_dialogs/select_file_dialog_android.h b/ui/shell_dialogs/se protected: ~SelectFileDialogImpl() override; +diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc +--- a/ui/shell_dialogs/select_file_dialog_win.cc ++++ b/ui/shell_dialogs/select_file_dialog_win.cc +@@ -193,6 +193,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog, + int index); + + bool HasMultipleFileTypeChoicesImpl() override; ++ void ShowToast(const std::string& message) override; + + // Returns the filter to be used while displaying the open/save file dialog. + // This is computed from the extensions for the file types being opened. +@@ -271,6 +272,10 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() { + return has_multiple_file_type_choices_; + } + ++void SelectFileDialogImpl::ShowToast(const std::string& message) { ++ // nothing to do, used only on android ++} ++ + bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow owning_window) const { + if (!owning_window->GetRootWindow()) + return false; -- 2.25.1 diff --git a/build/patches/Add-custom-tab-intents-privacy-option.patch b/build/patches/Add-custom-tab-intents-privacy-option.patch index c5c3ef9e..b7eea0d3 100644 --- a/build/patches/Add-custom-tab-intents-privacy-option.patch +++ b/build/patches/Add-custom-tab-intents-privacy-option.patch @@ -44,24 +44,17 @@ diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/androi diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java -@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.notifications.NotificationPlatformBridge; - import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; - import org.chromium.chrome.browser.searchwidget.SearchActivity; - import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.browser.tab.TabLaunchType; - import org.chromium.chrome.browser.translate.TranslateIntentHandler; - import org.chromium.chrome.browser.util.AndroidTaskUtils; - import org.chromium.chrome.browser.webapps.WebappLauncherActivity; -@@ -56,6 +57,8 @@ import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Method; +@@ -52,6 +52,9 @@ import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; import java.util.Set; +import org.chromium.chrome.browser.privacy.settings.PrivacySettings; ++import org.chromium.chrome.browser.tab.TabLaunchType; + /** * Dispatches incoming intents to the appropriate activity based on the current configuration and * Intent fired. -@@ -268,6 +271,9 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega +@@ -242,6 +245,9 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega */ public static boolean isCustomTabIntent(Intent intent) { if (intent == null) return false; @@ -71,7 +64,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDis if (CustomTabsIntent.shouldAlwaysUseBrowserUI(intent) || !intent.hasExtra(CustomTabsIntent.EXTRA_SESSION)) { return false; -@@ -287,6 +293,10 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega +@@ -261,6 +267,10 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega newIntent.setData(uri); newIntent.setClassName(context, CustomTabActivity.class.getName()); @@ -82,7 +75,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDis // Since configureIntentForResizableCustomTab() might change the componenet/class // associated with the passed intent, it needs to be called after #setClassName(context, // CustomTabActivity.class.getName()); -@@ -447,6 +457,17 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega +@@ -407,6 +417,17 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega if (Intent.ACTION_VIEW.equals(newIntent.getAction()) && !IntentHandler.wasIntentSenderChrome(newIntent)) { @@ -135,8 +128,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - PrivacyPreferencesManagerImpl privacyPrefManager = -@@ -250,6 +253,9 @@ public class PrivacySettings extends PreferenceFragmentCompat + getActivity().setTitle(R.string.prefs_privacy_security); +@@ -246,6 +249,9 @@ public class PrivacySettings extends PreferenceFragmentCompat new SpanApplier.SpanInfo("", "", servicesLink)); } @@ -146,7 +139,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting @Override public boolean onPreferenceChange(Preference preference, Object newValue) { String key = preference.getKey(); -@@ -264,6 +270,14 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -260,6 +266,14 @@ public class PrivacySettings extends PreferenceFragmentCompat } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) { UserPrefs.get(Profile.getLastUsedRegularProfile()) .setBoolean(Pref.SEARCH_SUGGEST_ENABLED, (boolean) newValue); @@ -161,7 +154,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting } return true; } -@@ -287,6 +301,16 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -283,6 +297,16 @@ public class PrivacySettings extends PreferenceFragmentCompat UserPrefs.get(mProfile).getBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED)); } @@ -181,7 +174,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -541,8 +541,8 @@ BASE_FEATURE(kCCTIncognitoAvailableToThirdParty, +@@ -558,8 +558,8 @@ BASE_FEATURE(kCCTIncognitoAvailableToThirdParty, base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite BASE_FEATURE(kCCTIntentFeatureOverrides, @@ -192,7 +185,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse BASE_FEATURE(kCCTPageInsightsHub, "CCTPageInsightsHub", -@@ -550,7 +550,7 @@ BASE_FEATURE(kCCTPageInsightsHub, +@@ -567,7 +567,7 @@ BASE_FEATURE(kCCTPageInsightsHub, BASE_FEATURE(kCCTPostMessageAPI, "CCTPostMessageAPI", @@ -220,7 +213,7 @@ diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAsso diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -5015,6 +5015,20 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

Resume @@ -244,7 +237,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/components/language/core/common/language_experiments.cc b/components/language/core/common/language_experiments.cc --- a/components/language/core/common/language_experiments.cc +++ b/components/language/core/common/language_experiments.cc -@@ -39,8 +39,8 @@ BASE_FEATURE(kContentLanguagesInLanguagePicker, +@@ -18,8 +18,8 @@ BASE_FEATURE(kContentLanguagesInLanguagePicker, "ContentLanguagesInLanguagePicker", base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kCctAutoTranslate, diff --git a/build/patches/Add-exit-menu-item.patch b/build/patches/Add-exit-menu-item.patch index d780c951..068feda4 100644 --- a/build/patches/Add-exit-menu-item.patch +++ b/build/patches/Add-exit-menu-item.patch @@ -17,7 +17,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml -@@ -158,6 +158,9 @@ found in the LICENSE file. +@@ -161,6 +161,9 @@ found in the LICENSE file. @@ -27,7 +27,7 @@ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/re -@@ -184,6 +187,9 @@ found in the LICENSE file. +@@ -187,6 +190,9 @@ found in the LICENSE file. @@ -59,7 +59,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ApplicationLife diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -230,6 +230,8 @@ import java.util.Locale; +@@ -229,6 +229,8 @@ import java.util.Locale; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -68,7 +68,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct /** * This is the main activity for ChromeMobile when not running in document mode. All the tabs * are accessible via a chrome specific tab switching UI. -@@ -2260,6 +2262,8 @@ public class ChromeTabbedActivity extends ChromeActivity +@@ -2408,6 +2409,11 @@ public abstract class ChromeActivity return true; } @@ -119,7 +119,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeLife diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -3687,6 +3687,9 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

Dark theme diff --git a/build/patches/Add-flag-for-omnibox-autocomplete-filtering.patch b/build/patches/Add-flag-for-omnibox-autocomplete-filtering.patch index 35cd8a5f..36b28c64 100644 --- a/build/patches/Add-flag-for-omnibox-autocomplete-filtering.patch +++ b/build/patches/Add-flag-for-omnibox-autocomplete-filtering.patch @@ -17,7 +17,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -582,6 +582,22 @@ const FeatureEntry::FeatureVariation kReaderModeDiscoverabilityVariations[] = { +@@ -589,6 +589,22 @@ const FeatureEntry::FeatureVariation kReaderModeDiscoverabilityVariations[] = { #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) @@ -40,7 +40,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc const FeatureEntry::FeatureParam kAdaptiveButton_AlwaysNone[] = { {"mode", "always-none"}}; const FeatureEntry::FeatureParam kAdaptiveButton_AlwaysNewTab[] = { -@@ -4626,7 +4642,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -4697,7 +4713,11 @@ const FeatureEntry kFeatureEntries[] = { kOsMac | kOsLinux | kOsWin, FEATURE_VALUE_TYPE(features::kSystemNotifications)}, #endif // BUILDFLAG(ENABLE_SYSTEM_NOTIFICATIONS) && !BUILDFLAG(IS_CHROMEOS_ASH) @@ -64,10 +64,10 @@ diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/ #include "base/feature_list.h" #include "base/format_macros.h" #include "base/functional/bind.h" -@@ -359,6 +360,15 @@ AutocompleteController::AutocompleteController( - template_url_service_(provider_client_->GetTemplateURLService()), - triggered_feature_service_( - provider_client_->GetOmniboxTriggeredFeatureService()) { +@@ -366,6 +367,15 @@ AutocompleteController::AutocompleteController( + provider_client_->GetOmniboxTriggeredFeatureService()), + steady_state_omnibox_position_( + metrics::OmniboxEventProto::UNKNOWN_POSITION) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch("omnibox-autocomplete-filtering")) { + const std::string flag_value = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII("omnibox-autocomplete-filtering"); + provider_types &= AutocompleteProvider::TYPE_KEYWORD | AutocompleteProvider::TYPE_SEARCH | diff --git a/build/patches/Add-flag-for-save-data-header.patch b/build/patches/Add-flag-for-save-data-header.patch index 481214a2..e729ec3b 100644 --- a/build/patches/Add-flag-for-save-data-header.patch +++ b/build/patches/Add-flag-for-save-data-header.patch @@ -15,7 +15,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5242,7 +5242,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5304,7 +5304,10 @@ const FeatureEntry kFeatureEntries[] = { {"force-text-direction", flag_descriptions::kForceTextDirectionName, flag_descriptions::kForceTextDirectionDescription, kOsAll, MULTI_VALUE_TYPE(kForceTextDirectionChoices)}, @@ -30,7 +30,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1332,6 +1332,10 @@ const char kDeprecateAltBasedSixPackDescription[] = +@@ -1386,6 +1386,10 @@ const char kDeprecateAltBasedSixPackDescription[] = "Show deprecation notifications and disable functionality for Alt based " "six pack deprecations. The Search based versions continue to work."; @@ -44,7 +44,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -694,6 +694,9 @@ extern const char kDeprecateAltBasedSixPackDescription[]; +@@ -715,6 +715,9 @@ extern const char kDeprecateAltBasedSixPackDescription[]; extern const char kDeprecateOldKeyboardShortcutsAcceleratorName[]; extern const char kDeprecateOldKeyboardShortcutsAcceleratorDescription[]; @@ -99,7 +99,7 @@ diff --git a/services/network/public/cpp/features.cc b/services/network/public/c diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h -@@ -84,6 +84,8 @@ extern uint32_t GetLoaderChunkSize(); +@@ -89,6 +89,8 @@ extern uint32_t GetLoaderChunkSize(); COMPONENT_EXPORT(NETWORK_CPP) BASE_DECLARE_FEATURE(kCorsNonWildcardRequestHeadersSupport); diff --git a/build/patches/Add-flag-to-configure-maximum-connections-per-host.patch b/build/patches/Add-flag-to-configure-maximum-connections-per-host.patch index 8cc91cb1..7e50eac4 100644 --- a/build/patches/Add-flag-to-configure-maximum-connections-per-host.patch +++ b/build/patches/Add-flag-to-configure-maximum-connections-per-host.patch @@ -21,7 +21,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -1230,6 +1230,11 @@ const FeatureEntry::Choice kForceColorProfileChoices[] = { +@@ -1236,6 +1236,11 @@ const FeatureEntry::Choice kForceColorProfileChoices[] = { switches::kForceDisplayColorProfile, "hdr10"}, }; @@ -33,7 +33,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc const FeatureEntry::Choice kMemlogModeChoices[] = { {flags_ui::kGenericExperimentChoiceDisabled, "", ""}, {flag_descriptions::kMemlogModeMinimal, heap_profiling::kMemlogMode, -@@ -5143,6 +5148,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5206,6 +5211,9 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(chrome::android::kShareSheetCustomActionsPolish)}, #endif // BUILDFLAG(IS_ANDROID) @@ -46,7 +46,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -2115,6 +2115,10 @@ const char kUnthrottledNestedTimeoutDescription[] = +@@ -2157,6 +2157,10 @@ const char kUnthrottledNestedTimeoutDescription[] = "websites abusing the API will still eventually have their setTimeouts " "clamped."; @@ -60,7 +60,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1185,6 +1185,9 @@ extern const char kLogJsConsoleMessagesDescription[]; +@@ -1219,6 +1219,9 @@ extern const char kUndoAutofillDescription[]; extern const char kUnthrottledNestedTimeoutName[]; extern const char kUnthrottledNestedTimeoutDescription[]; diff --git a/build/patches/Add-flag-to-control-video-playback-resume-feature.patch b/build/patches/Add-flag-to-control-video-playback-resume-feature.patch index e227321d..abfe716a 100644 --- a/build/patches/Add-flag-to-control-video-playback-resume-feature.patch +++ b/build/patches/Add-flag-to-control-video-playback-resume-feature.patch @@ -15,7 +15,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -3909,6 +3909,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -3940,6 +3940,10 @@ const FeatureEntry kFeatureEntries[] = { chrome::android::kContextualSearchSuppressShortView, kContextualSearchSuppressShortViewVariations, "ContextualSearchSuppressShortView")}, @@ -29,7 +29,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1408,6 +1408,11 @@ const char kEnableManagedConfigurationWebApiDescription[] = +@@ -1462,6 +1462,11 @@ const char kEnableManagedConfigurationWebApiDescription[] = "Allows website to access a managed configuration provided by the device " "administrator for the origin."; @@ -44,7 +44,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -766,6 +766,9 @@ extern const char kEnablePenetratingImageSelectionDescription[]; +@@ -800,6 +800,9 @@ extern const char kEnablePenetratingImageSelectionDescription[]; extern const char kEnablePerfettoSystemTracingName[]; extern const char kEnablePerfettoSystemTracingDescription[]; diff --git a/build/patches/Add-flag-to-disable-IPv6-probes.patch b/build/patches/Add-flag-to-disable-IPv6-probes.patch index 2631c7cb..169df4b8 100644 --- a/build/patches/Add-flag-to-disable-IPv6-probes.patch +++ b/build/patches/Add-flag-to-disable-IPv6-probes.patch @@ -18,7 +18,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -6479,6 +6479,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -6577,6 +6577,10 @@ const FeatureEntry kFeatureEntries[] = { {"enable-reader-mode-in-cct", flag_descriptions::kReaderModeInCCTName, flag_descriptions::kReaderModeInCCTDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kReaderModeInCCT)}, @@ -28,11 +28,11 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc + FEATURE_VALUE_TYPE(net::features::kIPv6Probing)}, #endif // BUILDFLAG(IS_ANDROID) - {"shopping-list", commerce::flag_descriptions::kShoppingListName, + {"shopping-collection", diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3824,6 +3824,10 @@ const char kCCTTextFragmentLookupApiEnabledName[] = +@@ -3878,6 +3878,10 @@ const char kCCTTextFragmentLookupApiEnabledName[] = const char kCCTTextFragmentLookupApiEnabledDescription[] = "Enable CCT API to lookup text fragments"; @@ -46,7 +46,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -846,6 +846,9 @@ extern const char kEnableWasmStringrefName[]; +@@ -880,6 +880,9 @@ extern const char kEnableWasmStringrefName[]; extern const char kEnableWasmStringrefDescription[]; extern const char kEnableWasmTieringName[]; @@ -59,7 +59,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/net/BUILD.gn b/net/BUILD.gn --- a/net/BUILD.gn +++ b/net/BUILD.gn -@@ -1085,6 +1085,7 @@ component("net") { +@@ -1094,6 +1094,7 @@ component("net") { "//build:chromeos_buildflags", "//net/data/ssl/chrome_root_store:gen_root_store_inc", "//net/http:transport_security_state_generated_files", @@ -70,7 +70,7 @@ diff --git a/net/BUILD.gn b/net/BUILD.gn diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -40,6 +40,10 @@ BASE_FEATURE(kUseDnsHttpsSvcb, +@@ -41,6 +41,10 @@ BASE_FEATURE(kUseDnsHttpsSvcb, const base::FeatureParam kUseDnsHttpsSvcbEnforceSecureResponse{ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbEnforceSecureResponse", false}; @@ -105,7 +105,7 @@ diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc #include "net/log/net_log_with_source.h" #include "net/socket/client_socket_factory.h" #include "net/url_request/url_request_context.h" -@@ -677,6 +678,9 @@ class HostResolverManager::RequestImpl +@@ -685,6 +686,9 @@ class HostResolverManager::RequestImpl // request source is LOCAL_ONLY. This is due to LOCAL_ONLY requiring a // synchronous response, so it cannot wait on an async probe result and // cannot make assumptions about reachability. @@ -115,7 +115,7 @@ diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc if (parameters_.source == HostResolverSource::LOCAL_ONLY) { int rv = resolver_->StartIPv6ReachabilityCheck( source_net_log_, GetClientSocketFactory(), -@@ -3895,6 +3899,13 @@ int HostResolverManager::StartIPv6ReachabilityCheck( +@@ -3903,6 +3907,13 @@ int HostResolverManager::StartIPv6ReachabilityCheck( return OK; } diff --git a/build/patches/Add-flag-to-disable-external-intent-requests.patch b/build/patches/Add-flag-to-disable-external-intent-requests.patch index 10d55ca6..aae9ee41 100644 --- a/build/patches/Add-flag-to-disable-external-intent-requests.patch +++ b/build/patches/Add-flag-to-disable-external-intent-requests.patch @@ -15,7 +15,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -3849,6 +3849,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -3881,6 +3881,11 @@ const FeatureEntry kFeatureEntries[] = { {"ui-disable-partial-swap", flag_descriptions::kUiPartialSwapName, flag_descriptions::kUiPartialSwapDescription, kOsAll, SINGLE_DISABLE_VALUE_TYPE(switches::kUIDisablePartialSwap)}, @@ -30,7 +30,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4115,6 +4115,12 @@ const char kPolicyLogsPageAndroidDescription[] = +@@ -4179,6 +4179,12 @@ const char kPolicyLogsPageAndroidDescription[] = "Enable the new chrome://policy-logs page containing logs for debugging " "policy related issues on Android."; @@ -46,7 +46,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2411,6 +2411,9 @@ extern const char kQueryTilesNTPDescription[]; +@@ -2464,6 +2464,9 @@ extern const char kQueryTilesNTPDescription[]; extern const char kQueryTilesOnStartName[]; extern const char kQueryTilesOnStartDescription[]; extern const char kQueryTilesSingleTierName[]; diff --git a/build/patches/Add-flag-to-disable-vibration.patch b/build/patches/Add-flag-to-disable-vibration.patch index 39516b71..7d4bf3c7 100644 --- a/build/patches/Add-flag-to-disable-vibration.patch +++ b/build/patches/Add-flag-to-disable-vibration.patch @@ -19,7 +19,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -7947,6 +7947,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -8111,6 +8111,10 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(features::kNewMacNotificationAPI)}, #endif @@ -33,20 +33,20 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -6962,6 +6962,9 @@ const char kLacrosMergeIcuDataFileDescription[] = +@@ -7118,6 +7118,9 @@ const char kLacrosMergeIcuDataFileDescription[] = "Enables sharing common areas of icudtl.dat between Ash and Lacros."; #endif // #if BUILDFLAG(IS_CHROMEOS_LACROS) +const char kEnableVibrationName[] = "Vibration"; +const char kEnableVibrationDescription[] = "Enable vibration API; an user gesture will still be needed."; + - #if BUILDFLAG(IS_CHROMEOS) - const char kCrOSDspBasedAecAllowedName[] = - "Allow CRAS to use a DSP-based AEC if available"; + #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) + const char kGetAllScreensMediaName[] = "GetAllScreensMedia API"; + const char kGetAllScreensMediaDescription[] = diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -4230,6 +4230,8 @@ extern const char kWebUITabStripTabDragIntegrationName[]; +@@ -4338,6 +4338,8 @@ extern const char kWebUITabStripTabDragIntegrationName[]; extern const char kWebUITabStripTabDragIntegrationDescription[]; #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && BUILDFLAG(IS_CHROMEOS_ASH) @@ -69,7 +69,7 @@ diff --git a/content/child/runtime_features.cc b/content/child/runtime_features. diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -157,6 +157,11 @@ BASE_FEATURE(kBackForwardCacheMemoryControls, +@@ -169,6 +169,11 @@ BASE_FEATURE(kBackForwardCacheMemoryControls, #endif ); @@ -84,7 +84,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h -@@ -344,6 +344,8 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kWarmUpNetworkProcess); +@@ -346,6 +346,8 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kWarmUpNetworkProcess); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebNfc); #endif // BUILDFLAG(IS_ANDROID) @@ -141,7 +141,7 @@ diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.c diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2495,6 +2495,10 @@ +@@ -2461,6 +2461,10 @@ status: {"Android": "stable"}, base_feature: "none", }, diff --git a/build/patches/Add-kill-switch-for-unsupported-clangd-flags.patch b/build/patches/Add-kill-switch-for-unsupported-clangd-flags.patch index 046b9f53..e32af1bc 100644 --- a/build/patches/Add-kill-switch-for-unsupported-clangd-flags.patch +++ b/build/patches/Add-kill-switch-for-unsupported-clangd-flags.patch @@ -7,26 +7,25 @@ Allows build with clangd by suppressing unsupported parameters Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - build/config/compiler/BUILD.gn | 6 +++++- + build/config/compiler/BUILD.gn | 5 +++++ build_overrides/build.gni | 3 +++ - 2 files changed, 8 insertions(+), 1 deletion(-) + 2 files changed, 8 insertions(+) diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -1772,7 +1772,11 @@ config("default_warnings") { +@@ -1777,6 +1777,11 @@ config("default_warnings") { # TODO(crbug.com/1412713) Evaluate and possibly enable. "-Wno-deprecated-this-capture", ] -- + if (skip_clangd_unsupported_options) { + cflags -= [ + "-Wno-deprecated-builtins", + ] + } - if (llvm_force_head_revision) { - # TODO(https://crbug.com/1448905): Evaluate and possibly enable. - cflags += [ "-Wno-builtin-macro-redefined" ] + } + } + diff --git a/build_overrides/build.gni b/build_overrides/build.gni --- a/build_overrides/build.gni +++ b/build_overrides/build.gni @@ -39,6 +38,6 @@ diff --git a/build_overrides/build.gni b/build_overrides/build.gni + skip_clangd_unsupported_options = false } - # Allows different projects to specify their own suppression/ignore lists for + # Features used by //base/trace_event. -- 2.25.1 diff --git a/build/patches/Add-lifetime-options-for-permissions.patch b/build/patches/Add-lifetime-options-for-permissions.patch index 2a5ec8ce..8d09942a 100644 --- a/build/patches/Add-lifetime-options-for-permissions.patch +++ b/build/patches/Add-lifetime-options-for-permissions.patch @@ -293,8 +293,8 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c +import org.chromium.components.content_settings.SessionModel; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.BrowserContextHandle; - import org.chromium.content_public.browser.ContentFeatureList; -@@ -541,6 +542,11 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment + +@@ -542,6 +543,11 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment } } @@ -306,7 +306,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c private void setUpClearDataPreference() { ClearWebsiteStorage preference = findPreference(PREF_CLEAR_DATA); long usage = mSite.getTotalUsage(); -@@ -970,6 +976,10 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -971,6 +977,10 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment if (contentType == mHighlightedPermission) { switchPreference.setBackgroundColor(mHighlightColor); } @@ -350,7 +350,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc --- a/components/browser_ui/site_settings/android/website_preference_bridge.cc +++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc -@@ -125,7 +125,8 @@ typedef void (*InfoListInsertionFunction)( +@@ -131,7 +131,8 @@ typedef void (*InfoListInsertionFunction)( const base::android::JavaRef&, const base::android::JavaRef&, const base::android::JavaRef&, @@ -360,7 +360,7 @@ diff --git a/components/browser_ui/site_settings/android/website_preference_brid void GetOrigins(JNIEnv* env, const JavaParamRef& jbrowser_context_handle, -@@ -167,7 +168,7 @@ void GetOrigins(JNIEnv* env, +@@ -173,7 +174,7 @@ void GetOrigins(JNIEnv* env, seen_origins.push_back(origin); insertionFunc(env, static_cast(content_type), list, ConvertOriginToJavaString(env, origin), jembedder, @@ -369,7 +369,7 @@ diff --git a/components/browser_ui/site_settings/android/website_preference_brid } // Add any origins which have a default content setting value (thus skipped -@@ -189,7 +190,7 @@ void GetOrigins(JNIEnv* env, +@@ -195,7 +196,7 @@ void GetOrigins(JNIEnv* env, seen_origins.push_back(origin); insertionFunc(env, static_cast(content_type), list, ConvertOriginToJavaString(env, origin), jembedder, @@ -381,7 +381,7 @@ diff --git a/components/browser_ui/site_settings/android/website_preference_brid diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd -@@ -597,6 +597,11 @@ +@@ -642,6 +642,11 @@ URL truncated @@ -396,8 +396,8 @@ diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/comp diff --git a/components/content_settings/android/BUILD.gn b/components/content_settings/android/BUILD.gn --- a/components/content_settings/android/BUILD.gn +++ b/components/content_settings/android/BUILD.gn -@@ -58,6 +58,7 @@ java_cpp_enum("content_settings_enums_javagen") { - "../core/common/content_settings_types.h", +@@ -59,6 +59,7 @@ java_cpp_enum("content_settings_enums_javagen") { + "../core/common/cookie_controls_breakage_confidence_level.h", "../core/common/cookie_controls_enforcement.h", "../core/common/cookie_controls_status.h", + "../core/common/content_settings_constraints.h", @@ -407,7 +407,7 @@ diff --git a/components/content_settings/android/BUILD.gn b/components/content_s diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc -@@ -175,6 +175,42 @@ bool IsConstraintPersistent(const ContentSettingConstraints& constraints) { +@@ -174,6 +174,42 @@ bool IsConstraintPersistent(const ContentSettingConstraints& constraints) { return constraints.session_model() == SessionModel::Durable; } @@ -497,7 +497,7 @@ diff --git a/components/content_settings/core/common/content_settings_constraint diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java -@@ -340,9 +340,9 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr +@@ -336,9 +336,9 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr */ @CalledByNative private void addPermissionSection(String name, String nameMidSentence, int type, @@ -555,7 +555,7 @@ diff --git a/components/page_info/android/java/src/org/chromium/components/page_ diff --git a/components/page_info/android/page_info_controller_android.cc b/components/page_info/android/page_info_controller_android.cc --- a/components/page_info/android/page_info_controller_android.cc +++ b/components/page_info/android/page_info_controller_android.cc -@@ -153,6 +153,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( +@@ -148,6 +148,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( std::map user_specified_settings_to_display; @@ -564,7 +564,7 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp for (const auto& permission : permission_info_list) { if (base::Contains(permissions_to_display, permission.type)) { -@@ -161,6 +163,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( +@@ -156,6 +158,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( if (setting_to_display) { user_specified_settings_to_display[permission.type] = *setting_to_display; @@ -573,7 +573,7 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp } } } -@@ -177,7 +181,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( +@@ -172,7 +176,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( ConvertUTF16ToJavaString(env, setting_title), ConvertUTF16ToJavaString(env, setting_title_mid_sentence), static_cast(permission), @@ -583,7 +583,7 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp } } -@@ -190,7 +195,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( +@@ -185,7 +190,8 @@ void PageInfoControllerAndroid::SetPermissionInfo( env, controller_jobject_, ConvertUTF16ToJavaString(env, object_title), ConvertUTF16ToJavaString(env, object_title), static_cast(chosen_object->ui_info->content_settings_type), @@ -596,19 +596,19 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc -@@ -1141,6 +1141,8 @@ void PageInfo::PopulatePermissionInfo(PermissionInfo& permission_info, +@@ -1171,6 +1171,8 @@ void PageInfo::PopulatePermissionInfo(PermissionInfo& permission_info, permission_info.source = info.source; permission_info.is_one_time = (info.metadata.session_model() == content_settings::SessionModel::OneTime); + permission_info.is_user_session = + (info.metadata.session_model() == content_settings::SessionModel::UserSession); - if (info.primary_pattern == ContentSettingsPattern::Wildcard() && - info.secondary_pattern == ContentSettingsPattern::Wildcard()) { + auto* page_specific_content_settings = GetPageSpecificContentSettings(); + if (page_specific_content_settings && setting == CONTENT_SETTING_ALLOW) { diff --git a/components/page_info/page_info.h b/components/page_info/page_info.h --- a/components/page_info/page_info.h +++ b/components/page_info/page_info.h -@@ -197,6 +197,7 @@ class PageInfo : private content_settings::OldCookieControlsObserver { +@@ -199,6 +199,7 @@ class PageInfo : private content_settings::CookieControlsObserver, content_settings::SETTING_SOURCE_NONE; // Whether the permission is a one-time grant. bool is_one_time = false; @@ -814,7 +814,7 @@ diff --git a/components/permissions/android/permission_prompt/permission_dialog_ diff --git a/components/permissions/android/permission_prompt/permission_prompt_android.cc b/components/permissions/android/permission_prompt/permission_prompt_android.cc --- a/components/permissions/android/permission_prompt/permission_prompt_android.cc +++ b/components/permissions/android/permission_prompt/permission_prompt_android.cc -@@ -41,6 +41,14 @@ void PermissionPromptAndroid::Accept() { +@@ -46,6 +46,14 @@ void PermissionPromptAndroid::Accept() { delegate_->Accept(); } @@ -832,7 +832,7 @@ diff --git a/components/permissions/android/permission_prompt/permission_prompt_ diff --git a/components/permissions/android/permission_prompt/permission_prompt_android.h b/components/permissions/android/permission_prompt/permission_prompt_android.h --- a/components/permissions/android/permission_prompt/permission_prompt_android.h +++ b/components/permissions/android/permission_prompt/permission_prompt_android.h -@@ -43,7 +43,9 @@ class PermissionPromptAndroid : public PermissionPrompt { +@@ -46,7 +46,9 @@ class PermissionPromptAndroid : public PermissionPrompt { void Closing(); void Accept(); @@ -872,7 +872,7 @@ diff --git a/components/permissions/android/permissions_android_strings.grd b/co diff --git a/components/permissions/contexts/geolocation_permission_context_android.cc b/components/permissions/contexts/geolocation_permission_context_android.cc --- a/components/permissions/contexts/geolocation_permission_context_android.cc +++ b/components/permissions/contexts/geolocation_permission_context_android.cc -@@ -130,7 +130,20 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( +@@ -161,7 +161,20 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( bool is_final_decision) { DCHECK(!is_one_time); DCHECK(is_final_decision); @@ -893,7 +893,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr bool is_default_search = IsRequestingOriginDSE(requesting_origin); if (content_setting == CONTENT_SETTING_ALLOW && !location_settings_->IsSystemLocationSettingEnabled()) { -@@ -143,7 +156,8 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( +@@ -174,7 +187,8 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( if (IsInLocationSettingsBackOff(is_default_search)) { FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, std::move(callback), false /* persist */, @@ -903,7 +903,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr return; } -@@ -161,7 +175,8 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( +@@ -192,7 +206,8 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( !location_settings_dialog_callback_.is_null()) { FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, std::move(callback), false /* persist */, @@ -913,7 +913,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr return; } -@@ -173,12 +188,13 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( +@@ -204,12 +219,13 @@ void GeolocationPermissionContextAndroid::NotifyPermissionSet( base::BindOnce( &GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown, weak_factory_.GetWeakPtr(), requesting_origin, embedding_origin, @@ -929,7 +929,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr } PermissionResult -@@ -345,6 +361,7 @@ void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( +@@ -376,6 +392,7 @@ void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( const GURL& embedding_origin, bool persist, ContentSetting content_setting, @@ -937,7 +937,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr LocationSettingsDialogOutcome prompt_outcome) { bool is_default_search = IsRequestingOriginDSE(requesting_origin); if (prompt_outcome == GRANTED) { -@@ -362,7 +379,8 @@ void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( +@@ -393,7 +410,8 @@ void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( FinishNotifyPermissionSet( location_settings_dialog_request_id_, requesting_origin, embedding_origin, @@ -947,7 +947,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr location_settings_dialog_request_id_ = PermissionRequestID(content::GlobalRenderFrameHostId(0, 0), -@@ -375,10 +393,11 @@ void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet( +@@ -406,10 +424,11 @@ void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet( const GURL& embedding_origin, BrowserPermissionCallback callback, bool persist, @@ -965,7 +965,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr diff --git a/components/permissions/contexts/geolocation_permission_context_android.h b/components/permissions/contexts/geolocation_permission_context_android.h --- a/components/permissions/contexts/geolocation_permission_context_android.h +++ b/components/permissions/contexts/geolocation_permission_context_android.h -@@ -88,6 +88,15 @@ class GeolocationPermissionContextAndroid +@@ -91,6 +91,15 @@ class GeolocationPermissionContextAndroid ContentSetting content_setting, bool is_one_time, bool is_final_decision) override; @@ -981,7 +981,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr PermissionResult UpdatePermissionStatusWithDeviceStatus( PermissionResult result, const GURL& requesting_origin, -@@ -130,6 +139,7 @@ class GeolocationPermissionContextAndroid +@@ -133,6 +142,7 @@ class GeolocationPermissionContextAndroid const GURL& embedding_origin, bool persist, ContentSetting content_setting, @@ -989,7 +989,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr LocationSettingsDialogOutcome prompt_outcome); void FinishNotifyPermissionSet(const PermissionRequestID& id, -@@ -137,7 +147,9 @@ class GeolocationPermissionContextAndroid +@@ -140,7 +150,9 @@ class GeolocationPermissionContextAndroid const GURL& embedding_origin, BrowserPermissionCallback callback, bool persist, @@ -1003,7 +1003,7 @@ diff --git a/components/permissions/contexts/geolocation_permission_context_andr diff --git a/components/permissions/permission_context_base.cc b/components/permissions/permission_context_base.cc --- a/components/permissions/permission_context_base.cc +++ b/components/permissions/permission_context_base.cc -@@ -250,6 +250,20 @@ PermissionContextBase::CreatePermissionRequest( +@@ -249,6 +249,20 @@ PermissionContextBase::CreatePermissionRequest( std::move(delete_callback)); } @@ -1024,7 +1024,7 @@ diff --git a/components/permissions/permission_context_base.cc b/components/perm PermissionResult PermissionContextBase::GetPermissionStatus( content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, -@@ -429,7 +443,8 @@ void PermissionContextBase::PermissionDecided(const PermissionRequestID& id, +@@ -428,7 +442,8 @@ void PermissionContextBase::PermissionDecided(const PermissionRequestID& id, const GURL& embedding_origin, ContentSetting content_setting, bool is_one_time, @@ -1034,7 +1034,7 @@ diff --git a/components/permissions/permission_context_base.cc b/components/perm DCHECK(content_setting == CONTENT_SETTING_ALLOW || content_setting == CONTENT_SETTING_BLOCK || content_setting == CONTENT_SETTING_DEFAULT); -@@ -444,13 +459,14 @@ void PermissionContextBase::PermissionDecided(const PermissionRequestID& id, +@@ -443,13 +458,14 @@ void PermissionContextBase::PermissionDecided(const PermissionRequestID& id, // missing if a permission prompt was preignored and we already notified an // origin about it. if (request->second.second) { @@ -1053,7 +1053,7 @@ diff --git a/components/permissions/permission_context_base.cc b/components/perm } } -@@ -502,11 +518,27 @@ void PermissionContextBase::NotifyPermissionSet( +@@ -501,11 +517,27 @@ void PermissionContextBase::NotifyPermissionSet( ContentSetting content_setting, bool is_one_time, bool is_final_decision) { @@ -1082,7 +1082,7 @@ diff --git a/components/permissions/permission_context_base.cc b/components/perm } if (is_final_decision) { -@@ -536,6 +568,15 @@ void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin, +@@ -535,6 +567,15 @@ void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin, const GURL& embedding_origin, ContentSetting content_setting, bool is_one_time) { @@ -1098,7 +1098,7 @@ diff --git a/components/permissions/permission_context_base.cc b/components/perm DCHECK_EQ(requesting_origin, requesting_origin.DeprecatedGetOriginAsURL()); DCHECK_EQ(embedding_origin, embedding_origin.DeprecatedGetOriginAsURL()); DCHECK(content_setting == CONTENT_SETTING_ALLOW || -@@ -545,6 +586,8 @@ void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin, +@@ -544,6 +585,8 @@ void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin, constraints.set_session_model(is_one_time ? content_settings::SessionModel::OneTime : content_settings::SessionModel::Durable); @@ -1166,7 +1166,7 @@ diff --git a/components/permissions/permission_context_base.h b/components/permi diff --git a/components/permissions/permission_prompt.h b/components/permissions/permission_prompt.h --- a/components/permissions/permission_prompt.h +++ b/components/permissions/permission_prompt.h -@@ -63,8 +63,9 @@ class PermissionPrompt { +@@ -65,8 +65,9 @@ class PermissionPrompt { virtual GURL GetEmbeddingOrigin() const = 0; virtual void Accept() = 0; @@ -1199,7 +1199,7 @@ diff --git a/components/permissions/permission_request.cc b/components/permissio PermissionRequest::~PermissionRequest() { DCHECK(delete_callback_.is_null()); } -@@ -263,19 +275,37 @@ bool PermissionRequest::ShouldUseTwoOriginPrompt() const { +@@ -257,19 +269,37 @@ bool PermissionRequest::ShouldUseTwoOriginPrompt() const { permissions::features::kPermissionStorageAccessAPI); } @@ -1311,7 +1311,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p } request->RequestFinished(); return; -@@ -566,7 +566,8 @@ void PermissionRequestManager::Accept() { +@@ -568,7 +568,8 @@ void PermissionRequestManager::Accept() { (*requests_iter)->request_type(), PermissionAction::GRANTED); PermissionGrantedIncludingDuplicates(*requests_iter, @@ -1321,7 +1321,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p #if !BUILDFLAG(IS_ANDROID) absl::optional content_settings_type = -@@ -584,7 +585,7 @@ void PermissionRequestManager::Accept() { +@@ -586,7 +587,7 @@ void PermissionRequestManager::Accept() { FinalizeCurrentRequests(PermissionAction::GRANTED); } @@ -1330,7 +1330,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p if (ignore_callbacks_from_prompt_) return; DCHECK(view_); -@@ -595,7 +596,8 @@ void PermissionRequestManager::AcceptThisTime() { +@@ -597,7 +598,8 @@ void PermissionRequestManager::AcceptThisTime() { (*requests_iter)->request_type(), PermissionAction::GRANTED_ONCE); PermissionGrantedIncludingDuplicates(*requests_iter, @@ -1340,7 +1340,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p } NotifyRequestDecided(PermissionAction::GRANTED_ONCE); -@@ -603,6 +605,15 @@ void PermissionRequestManager::AcceptThisTime() { +@@ -605,6 +607,15 @@ void PermissionRequestManager::AcceptThisTime() { } void PermissionRequestManager::Deny() { @@ -1356,7 +1356,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p if (ignore_callbacks_from_prompt_) return; DCHECK(view_); -@@ -625,7 +636,7 @@ void PermissionRequestManager::Deny() { +@@ -627,7 +638,7 @@ void PermissionRequestManager::Deny() { StorePermissionActionForUMA((*requests_iter)->requesting_origin(), (*requests_iter)->request_type(), PermissionAction::DENIED); @@ -1365,7 +1365,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p } NotifyRequestDecided(PermissionAction::DENIED); -@@ -1155,32 +1166,32 @@ PermissionRequestManager::VisitDuplicateRequests( +@@ -1162,32 +1173,32 @@ PermissionRequestManager::VisitDuplicateRequests( void PermissionRequestManager::PermissionGrantedIncludingDuplicates( PermissionRequest* request, @@ -1408,7 +1408,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p request); } -@@ -1429,7 +1440,7 @@ void PermissionRequestManager::LogWarningToConsole(const char* message) { +@@ -1436,7 +1447,7 @@ void PermissionRequestManager::LogWarningToConsole(const char* message) { void PermissionRequestManager::DoAutoResponseForTesting() { switch (auto_response_for_test_) { case ACCEPT_ONCE: @@ -1420,7 +1420,7 @@ diff --git a/components/permissions/permission_request_manager.cc b/components/p diff --git a/components/permissions/permission_request_manager.h b/components/permissions/permission_request_manager.h --- a/components/permissions/permission_request_manager.h +++ b/components/permissions/permission_request_manager.h -@@ -157,8 +157,10 @@ class PermissionRequestManager +@@ -159,8 +159,10 @@ class PermissionRequestManager GURL GetRequestingOrigin() const override; GURL GetEmbeddingOrigin() const override; void Accept() override; @@ -1432,7 +1432,7 @@ diff --git a/components/permissions/permission_request_manager.h b/components/pe void Dismiss() override; void Ignore() override; void OpenHelpCenterLink(const ui::Event& event) override; -@@ -356,9 +358,12 @@ class PermissionRequestManager +@@ -362,9 +364,12 @@ class PermissionRequestManager // Calls PermissionGranted on a request and all its duplicates. void PermissionGrantedIncludingDuplicates(PermissionRequest* request, diff --git a/build/patches/Add-menu-item-to-bookmark-all-tabs.patch b/build/patches/Add-menu-item-to-bookmark-all-tabs.patch index 73adcd76..f6a5362d 100644 --- a/build/patches/Add-menu-item-to-bookmark-all-tabs.patch +++ b/build/patches/Add-menu-item-to-bookmark-all-tabs.patch @@ -21,11 +21,13 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../bookmarks/browser/bookmark_load_details.h | 3 + .../bookmarks/browser/bookmark_model.cc | 3 +- components/bookmarks/browser/bookmark_model.h | 7 +++ - components/bookmarks/browser/bookmark_node.cc | 15 +++++ - components/bookmarks/browser/bookmark_node.h | 5 ++ + components/bookmarks/browser/bookmark_node.cc | 11 ++++ + components/bookmarks/browser/bookmark_node.h | 4 ++ + .../bookmarks/browser/bookmark_uuids.cc | 3 + + components/bookmarks/browser/bookmark_uuids.h | 1 + components/bookmarks/browser/model_loader.cc | 3 +- .../bookmark_specifics_conversions.cc | 1 + - 21 files changed, 201 insertions(+), 11 deletions(-) + 23 files changed, 200 insertions(+), 11 deletions(-) diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml --- a/chrome/android/java/res/menu/main_menu.xml @@ -41,7 +43,7 @@ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/re -@@ -181,6 +185,9 @@ found in the LICENSE file. +@@ -184,6 +188,9 @@ found in the LICENSE file. @@ -54,7 +56,7 @@ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/re diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -80,6 +80,7 @@ import org.chromium.chrome.browser.back_press.MinimizeAppAndCloseTabBackPressHan +@@ -82,6 +82,7 @@ import org.chromium.chrome.browser.back_press.MinimizeAppAndCloseTabBackPressHan import org.chromium.chrome.browser.bookmarks.BookmarkUtils; import org.chromium.chrome.browser.browserservices.intents.WebappConstants; import org.chromium.chrome.browser.compositor.CompositorViewHolder; @@ -62,17 +64,17 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone; -@@ -2282,6 +2283,8 @@ public class ChromeTabbedActivity extends ChromeActivity getTabModelSelector().closeAllTabs(), /*isIncognito=*/false); +@@ -2278,6 +2279,8 @@ public class ChromeTabbedActivity extends ChromeActivity getTabModelSelector().closeAllTabs()); RecordUserAction.record("MobileMenuCloseAllTabs"); + } else if (id == R.id.bookmark_all_tabs_menu_id) { + bookmarkAllTabs(); } else if (id == R.id.close_all_incognito_tabs_menu_id) { // Close only incognito tabs CloseAllTabsDialog.show(this, getModalDialogManagerSupplier(), -@@ -2347,6 +2350,27 @@ public class ChromeTabbedActivity extends ChromeActivity folderList, List depthList); BookmarkId getRootFolderId(long nativeBookmarkBridge, BookmarkBridge caller); @@ -208,7 +210,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java -@@ -575,6 +575,7 @@ public class BookmarkUtils { +@@ -615,6 +615,7 @@ public class BookmarkUtils { List topLevelFolders = new ArrayList<>(); BookmarkId desktopNodeId = bookmarkModel.getDesktopFolderId(); BookmarkId mobileNodeId = bookmarkModel.getMobileFolderId(); @@ -216,7 +218,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm BookmarkId othersNodeId = bookmarkModel.getOtherFolderId(); List specialFoldersIds = -@@ -600,6 +601,9 @@ public class BookmarkUtils { +@@ -640,6 +641,9 @@ public class BookmarkUtils { if (bookmarkModel.isFolderVisible(mobileNodeId)) { topLevelFolders.add(mobileNodeId); } @@ -291,7 +293,7 @@ diff --git a/chrome/browser/bookmarks/android/bookmark_bridge.h b/chrome/browser diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc --- a/chrome/browser/bookmarks/bookmark_html_writer.cc +++ b/chrome/browser/bookmarks/bookmark_html_writer.cc -@@ -188,15 +188,19 @@ class Writer : public base::RefCountedThreadSafe { +@@ -190,15 +190,19 @@ class Writer : public base::RefCountedThreadSafe { roots->FindDict(BookmarkCodec::kOtherBookmarkFolderNameKey); base::Value::Dict* mobile_folder_value = roots->FindDict(BookmarkCodec::kMobileBookmarkFolderNameKey); @@ -312,7 +314,7 @@ diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/b NotifyOnFinish(BookmarksExportObserver::Result::kCouldNotWriteNodes); return; } -@@ -460,6 +464,8 @@ void BookmarkFaviconFetcher::ExportBookmarks() { +@@ -465,6 +469,8 @@ void BookmarkFaviconFetcher::ExportBookmarks() { BookmarkModelFactory::GetForBrowserContext(profile_)->other_node()); ExtractUrls( BookmarkModelFactory::GetForBrowserContext(profile_)->mobile_node()); @@ -357,7 +359,7 @@ diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browse diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -3817,6 +3817,9 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

Select tabs @@ -393,7 +395,7 @@ diff --git a/components/bookmark_bar_strings.grdp b/components/bookmark_bar_stri diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmarks/browser/bookmark_codec.cc --- a/components/bookmarks/browser/bookmark_codec.cc +++ b/components/bookmarks/browser/bookmark_codec.cc -@@ -35,6 +35,7 @@ const char BookmarkCodec::kBookmarkBarFolderNameKey[] = "bookmark_bar"; +@@ -36,6 +36,7 @@ const char BookmarkCodec::kBookmarkBarFolderNameKey[] = "bookmark_bar"; const char BookmarkCodec::kOtherBookmarkFolderNameKey[] = "other"; // The value is left as 'synced' for historical reasons. const char BookmarkCodec::kMobileBookmarkFolderNameKey[] = "synced"; @@ -401,7 +403,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar const char BookmarkCodec::kVersionKey[] = "version"; const char BookmarkCodec::kChecksumKey[] = "checksum"; const char BookmarkCodec::kIdKey[] = "id"; -@@ -74,7 +75,8 @@ BookmarkCodec::~BookmarkCodec() = default; +@@ -75,7 +76,8 @@ BookmarkCodec::~BookmarkCodec() = default; base::Value::Dict BookmarkCodec::Encode(BookmarkModel* model, std::string sync_metadata_str) { return Encode(model->bookmark_bar_node(), model->other_node(), @@ -411,7 +413,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar model->root_node()->GetUnsyncedMetaInfoMap(), std::move(sync_metadata_str)); } -@@ -83,6 +85,7 @@ base::Value::Dict BookmarkCodec::Encode( +@@ -84,6 +86,7 @@ base::Value::Dict BookmarkCodec::Encode( const BookmarkNode* bookmark_bar_node, const BookmarkNode* other_folder_node, const BookmarkNode* mobile_folder_node, @@ -419,7 +421,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar const BookmarkNode::MetaInfoMap* model_meta_info_map, const BookmarkNode::MetaInfoMap* model_unsynced_meta_info_map, std::string sync_metadata_str) { -@@ -104,6 +107,7 @@ base::Value::Dict BookmarkCodec::Encode( +@@ -105,6 +108,7 @@ base::Value::Dict BookmarkCodec::Encode( roots.Set(kBookmarkBarFolderNameKey, EncodeNode(bookmark_bar_node)); roots.Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); roots.Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); @@ -427,7 +429,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar if (model_meta_info_map) roots.Set(kMetaInfo, EncodeMetaInfo(*model_meta_info_map)); if (model_unsynced_meta_info_map) { -@@ -124,6 +128,7 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, +@@ -125,6 +129,7 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, BookmarkNode* bb_node, BookmarkNode* other_folder_node, BookmarkNode* mobile_folder_node, @@ -435,17 +437,17 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar int64_t* max_id, std::string* sync_metadata_str) { ids_.clear(); -@@ -131,7 +136,8 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, - base::Uuid::ParseLowercase(BookmarkNode::kBookmarkBarNodeUuid), - base::Uuid::ParseLowercase(BookmarkNode::kOtherBookmarksNodeUuid), - base::Uuid::ParseLowercase(BookmarkNode::kMobileBookmarksNodeUuid), -- base::Uuid::ParseLowercase(BookmarkNode::kManagedNodeUuid)}; -+ base::Uuid::ParseLowercase(BookmarkNode::kManagedNodeUuid), -+ base::Uuid::ParseLowercase(BookmarkNode::kTabsCollectionBookmarksNodeUuid)}; +@@ -132,7 +137,8 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, + base::Uuid::ParseLowercase(kBookmarkBarNodeUuid), + base::Uuid::ParseLowercase(kOtherBookmarksNodeUuid), + base::Uuid::ParseLowercase(kMobileBookmarksNodeUuid), +- base::Uuid::ParseLowercase(kManagedNodeUuid)}; ++ base::Uuid::ParseLowercase(kManagedNodeUuid), ++ base::Uuid::ParseLowercase(kTabsCollectionBookmarksNodeUuid)}; ids_reassigned_ = false; uuids_reassigned_ = false; ids_valid_ = true; -@@ -139,12 +145,13 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, +@@ -140,12 +146,13 @@ bool BookmarkCodec::Decode(const base::Value::Dict& value, stored_checksum_.clear(); InitializeChecksum(); bool success = DecodeHelper(bb_node, other_folder_node, mobile_folder_node, @@ -460,7 +462,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar *max_id = maximum_id_ + 1; return success; } -@@ -200,6 +207,7 @@ base::Value::Dict BookmarkCodec::EncodeMetaInfo( +@@ -201,6 +208,7 @@ base::Value::Dict BookmarkCodec::EncodeMetaInfo( bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, BookmarkNode* other_folder_node, BookmarkNode* mobile_folder_node, @@ -468,7 +470,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar const base::Value::Dict& value, std::string* sync_metadata_str) { absl::optional version = value.FindInt(kVersionKey); -@@ -224,6 +232,8 @@ bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, +@@ -225,6 +233,8 @@ bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, roots->FindDict(kOtherBookmarkFolderNameKey); const base::Value::Dict* mobile_folder_value = roots->FindDict(kMobileBookmarkFolderNameKey); @@ -477,7 +479,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar if (!bb_value || !other_folder_value || !mobile_folder_value) return false; -@@ -231,6 +241,8 @@ bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, +@@ -232,6 +242,8 @@ bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, DecodeNode(*bb_value, nullptr, bb_node); DecodeNode(*other_folder_value, nullptr, other_folder_node); DecodeNode(*mobile_folder_value, nullptr, mobile_folder_node); @@ -486,7 +488,7 @@ diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmar if (!DecodeMetaInfo(*roots, &model_meta_info_map_)) return false; -@@ -496,11 +508,13 @@ void BookmarkCodec::DecodeMetaInfoHelper( +@@ -510,11 +522,13 @@ void BookmarkCodec::DecodeMetaInfoHelper( void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, BookmarkNode* other_node, @@ -583,7 +585,7 @@ diff --git a/components/bookmarks/browser/bookmark_load_details.h b/components/b diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc -@@ -817,7 +817,7 @@ bool BookmarkModel::HasBookmarks() { +@@ -818,7 +818,7 @@ bool BookmarkModel::HasBookmarks() { bool BookmarkModel::HasNoUserCreatedBookmarksOrFolders() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return bookmark_bar_node_->children().empty() && @@ -592,7 +594,7 @@ diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmar } bool BookmarkModel::IsBookmarked(const GURL& url) { -@@ -1123,6 +1123,7 @@ void BookmarkModel::DoneLoading(std::unique_ptr details) { +@@ -1124,6 +1124,7 @@ void BookmarkModel::DoneLoading(std::unique_ptr details) { bookmark_bar_node_ = details->bb_node(); other_node_ = details->other_folder_node(); mobile_node_ = details->mobile_folder_node(); @@ -616,10 +618,10 @@ diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmark bool is_root_node(const BookmarkNode* node) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return node == root_; -@@ -489,6 +495,7 @@ class BookmarkModel final : public BookmarkUndoProvider, +@@ -491,6 +497,7 @@ class BookmarkModel final : public BookmarkUndoProvider, + nullptr; + raw_ptr mobile_node_ = nullptr; - raw_ptr other_node_ = nullptr; - raw_ptr mobile_node_ = nullptr; + raw_ptr tabs_collection_node_ = nullptr; // The maximum ID assigned to the bookmark nodes in the model. @@ -627,18 +629,7 @@ diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmark diff --git a/components/bookmarks/browser/bookmark_node.cc b/components/bookmarks/browser/bookmark_node.cc --- a/components/bookmarks/browser/bookmark_node.cc +++ b/components/bookmarks/browser/bookmark_node.cc -@@ -60,6 +60,10 @@ const char BookmarkNode::kOtherBookmarksNodeUuid[] = - const char BookmarkNode::kMobileBookmarksNodeUuid[] = - "4cf2e351-0e85-532b-bb37-df045d8f8d0f"; - -+// static -+const char BookmarkNode::kTabsCollectionBookmarksNodeUuid[] = -+ "00000000-0000-4000-a000-000000000006"; -+ - // static - const char BookmarkNode::kManagedNodeUuid[] = - "323123f4-9381-5aee-80e6-ea5fca2f7672"; -@@ -275,6 +279,17 @@ BookmarkPermanentNode::CreateMobileBookmarks(int64_t id, +@@ -239,6 +239,17 @@ BookmarkPermanentNode::CreateMobileBookmarks(int64_t id, visible_when_empty)); } @@ -667,15 +658,7 @@ diff --git a/components/bookmarks/browser/bookmark_node.h b/components/bookmarks MOBILE }; -@@ -52,6 +53,7 @@ class BookmarkNode : public ui::TreeNode, public TitledUrlNode { - static const char kBookmarkBarNodeUuid[]; - static const char kOtherBookmarksNodeUuid[]; - static const char kMobileBookmarksNodeUuid[]; -+ static const char kTabsCollectionBookmarksNodeUuid[]; - static const char kManagedNodeUuid[]; - - // A bug in sync caused some problematic UUIDs to be produced. -@@ -270,6 +272,9 @@ class BookmarkPermanentNode : public BookmarkNode { +@@ -259,6 +260,9 @@ class BookmarkPermanentNode : public BookmarkNode { static std::unique_ptr CreateMobileBookmarks( int64_t id, bool visible_when_empty); @@ -685,6 +668,30 @@ diff --git a/components/bookmarks/browser/bookmark_node.h b/components/bookmarks // Constructor is private to disallow the construction of permanent nodes // other than the well-known ones, see factory methods. +diff --git a/components/bookmarks/browser/bookmark_uuids.cc b/components/bookmarks/browser/bookmark_uuids.cc +--- a/components/bookmarks/browser/bookmark_uuids.cc ++++ b/components/bookmarks/browser/bookmark_uuids.cc +@@ -33,6 +33,9 @@ const char kManagedNodeUuid[] = "323123f4-9381-5aee-80e6-ea5fca2f7672"; + // > uuid.uuid5(bookmarks_namespace, "shopping_collection") + const char kShoppingCollectionUuid[] = "e55c13d5-c108-52a6-bfd5-590b885500d0"; + ++const char kTabsCollectionBookmarksNodeUuid[] = ++ "00000000-0000-4000-a000-000000000006"; ++ + // This value is the result of exercising sync's function + // syncer::InferGuidForLegacyBookmark() with an empty input. + const char kBannedUuidDueToPastSyncBug[] = +diff --git a/components/bookmarks/browser/bookmark_uuids.h b/components/bookmarks/browser/bookmark_uuids.h +--- a/components/bookmarks/browser/bookmark_uuids.h ++++ b/components/bookmarks/browser/bookmark_uuids.h +@@ -14,6 +14,7 @@ extern const char kBookmarkBarNodeUuid[]; + extern const char kOtherBookmarksNodeUuid[]; + extern const char kMobileBookmarksNodeUuid[]; + extern const char kManagedNodeUuid[]; ++extern const char kTabsCollectionBookmarksNodeUuid[]; + extern const char kShoppingCollectionUuid[]; + + // A bug in sync caused some problematic UUIDs to be produced. diff --git a/components/bookmarks/browser/model_loader.cc b/components/bookmarks/browser/model_loader.cc --- a/components/bookmarks/browser/model_loader.cc +++ b/components/bookmarks/browser/model_loader.cc @@ -701,7 +708,7 @@ diff --git a/components/bookmarks/browser/model_loader.cc b/components/bookmarks diff --git a/components/sync_bookmarks/bookmark_specifics_conversions.cc b/components/sync_bookmarks/bookmark_specifics_conversions.cc --- a/components/sync_bookmarks/bookmark_specifics_conversions.cc +++ b/components/sync_bookmarks/bookmark_specifics_conversions.cc -@@ -446,6 +446,7 @@ sync_pb::BookmarkSpecifics::Type GetProtoTypeFromBookmarkNode( +@@ -447,6 +447,7 @@ sync_pb::BookmarkSpecifics::Type GetProtoTypeFromBookmarkNode( case bookmarks::BookmarkNode::BOOKMARK_BAR: case bookmarks::BookmarkNode::OTHER_NODE: case bookmarks::BookmarkNode::MOBILE: diff --git a/build/patches/Add-menu-item-to-view-source.patch b/build/patches/Add-menu-item-to-view-source.patch index 526f3211..4da2da07 100644 --- a/build/patches/Add-menu-item-to-view-source.patch +++ b/build/patches/Add-menu-item-to-view-source.patch @@ -29,7 +29,7 @@ diff --git a/chrome/android/java/res/menu/custom_tabs_menu.xml b/chrome/android/ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml -@@ -108,6 +108,9 @@ found in the LICENSE file. +@@ -111,6 +111,9 @@ found in the LICENSE file. @@ -42,7 +42,7 @@ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/re diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -2308,6 +2308,8 @@ public class ChromeTabbedActivity extends ChromeActivity +@@ -2542,6 +2542,11 @@ public abstract class ChromeActivity return doOpenWebApk(currentTab); } @@ -69,7 +69,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java -@@ -544,6 +544,7 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate +@@ -552,6 +552,7 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate isChromeScheme, isFileScheme, isContentScheme, isIncognito, url)); updateRequestDesktopSiteMenuItem(menu, currentTab, true /* can show */, isChromeScheme); @@ -77,7 +77,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/App updateAutoDarkMenuItem(menu, currentTab, isChromeScheme); -@@ -1114,6 +1115,23 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate +@@ -1133,6 +1134,23 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate } } @@ -104,7 +104,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/App diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java -@@ -240,6 +240,7 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat +@@ -241,6 +241,7 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat updateRequestDesktopSiteMenuItem( menu, currentTab, requestDesktopSiteVisible, isChromeScheme); @@ -115,7 +115,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/Cust diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -309,6 +309,10 @@ CHAR_LIMIT guidelines: +@@ -314,6 +314,10 @@ CHAR_LIMIT guidelines: USB diff --git a/build/patches/Add-option-to-force-tablet-UI.patch b/build/patches/Add-option-to-force-tablet-UI.patch index 7ddc3bdd..2e8d722d 100644 --- a/build/patches/Add-option-to-force-tablet-UI.patch +++ b/build/patches/Add-option-to-force-tablet-UI.patch @@ -50,7 +50,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/s diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java -@@ -386,6 +386,7 @@ public final class ChromePreferenceKeys { +@@ -374,6 +374,7 @@ public final class ChromePreferenceKeys { AccessibilityConstants.FONT_USER_SET_FORCE_ENABLE_ZOOM; public static final String HISTORY_SHOW_HISTORY_INFO = "history_home_show_info"; @@ -72,7 +72,7 @@ diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/bro diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java -@@ -669,7 +669,7 @@ public class LocationBarCoordinator +@@ -685,7 +685,7 @@ public class LocationBarCoordinator } private boolean isTabletWindow() { @@ -84,7 +84,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1675,6 +1675,12 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1702,6 +1702,12 @@ Your Google account may have other forms of browsing history like searches and a Temporarily links this data to your Google Account when you’re signed in, to protect you across Google apps @@ -100,7 +100,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java -@@ -165,9 +165,8 @@ public class ToolbarControlContainer extends OptimizedFrameLayout implements Con +@@ -166,9 +166,8 @@ public class ToolbarControlContainer extends OptimizedFrameLayout implements Con return backgroundDrawable; } else { @@ -115,7 +115,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow diff --git a/components/BUILD.gn b/components/BUILD.gn --- a/components/BUILD.gn +++ b/components/BUILD.gn -@@ -68,7 +68,7 @@ if (is_ios) { +@@ -71,7 +71,7 @@ if (is_ios) { # Omit Lacros because it allows //components to depend on //chrome, which in # turn depends on //extensions. @@ -124,7 +124,7 @@ diff --git a/components/BUILD.gn b/components/BUILD.gn disallowed_extension_deps_ = [ # Components should largely not depend on //extensions. Since // extensions # is not a component target and is linked with //chrome, depending on most -@@ -730,7 +730,7 @@ test("components_unittests") { +@@ -748,7 +748,7 @@ test("components_unittests") { # On other platforms, no components should depend on Chrome. # Since //chrome depends on //extensions, we also only assert_no_deps on # extensions targets for non-lacros builds. @@ -133,7 +133,7 @@ diff --git a/components/BUILD.gn b/components/BUILD.gn assert_no_deps = [ "//chrome/*" ] assert_no_deps += disallowed_extension_deps_ } -@@ -1018,7 +1018,7 @@ if (use_blink) { +@@ -1037,7 +1037,7 @@ if (use_blink) { # dependency. On other platforms, no components should depend on Chrome. # Since //chrome depends on //extensions, we also only assert_no_deps on # extensions targets for non-lacros builds. @@ -214,7 +214,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn -@@ -408,6 +408,8 @@ android_library("ui_no_recycler_view_java") { +@@ -409,6 +409,8 @@ android_library("ui_no_recycler_view_java") { ":ui_android_features_java", ":ui_java_resources", ":ui_utils_java", diff --git a/build/patches/Add-option-to-not-persist-tabs-across-sessions.patch b/build/patches/Add-option-to-not-persist-tabs-across-sessions.patch index 3f8e51b6..fe8f4c84 100644 --- a/build/patches/Add-option-to-not-persist-tabs-across-sessions.patch +++ b/build/patches/Add-option-to-not-persist-tabs-across-sessions.patch @@ -28,7 +28,7 @@ diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/androi diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java -@@ -38,6 +38,7 @@ import org.chromium.base.BuildInfo; +@@ -39,6 +39,7 @@ import org.chromium.base.BuildInfo; import org.chromium.base.Callback; import org.chromium.base.CallbackController; import org.chromium.base.CommandLine; @@ -36,7 +36,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.base.IntentUtils; import org.chromium.base.Log; import org.chromium.base.MemoryPressureListener; -@@ -1283,8 +1284,10 @@ public class ChromeTabbedActivity extends ChromeActivity<resetlink>reset sync

<resetlink>reset sync

IMAGE diff --git a/build/patches/Add-option-to-use-home-page-as-NTP.patch b/build/patches/Add-option-to-use-home-page-as-NTP.patch index a4c9b2b4..ea5bc375 100644 --- a/build/patches/Add-option-to-use-home-page-as-NTP.patch +++ b/build/patches/Add-option-to-use-home-page-as-NTP.patch @@ -15,9 +15,8 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../preferences/LegacyChromePreferenceKeys.java | 1 + .../android/strings/android_chrome_strings.grd | 3 +++ chrome/browser/ui/browser_ui_prefs.cc | 2 ++ - chrome/common/pref_names.cc | 4 ++++ - chrome/common/pref_names.h | 1 + - 11 files changed, 52 insertions(+), 1 deletion(-) + chrome/common/pref_names.h | 4 ++++ + 10 files changed, 51 insertions(+), 1 deletion(-) diff --git a/chrome/android/java/res/xml/homepage_preferences.xml b/chrome/android/java/res/xml/homepage_preferences.xml --- a/chrome/android/java/res/xml/homepage_preferences.xml @@ -37,7 +36,7 @@ diff --git a/chrome/android/java/res/xml/homepage_preferences.xml b/chrome/andro diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java -@@ -227,6 +227,22 @@ public class HomepageManager implements HomepagePolicyManager.HomepagePolicyStat +@@ -228,6 +228,22 @@ public class HomepageManager implements HomepagePolicyManager.HomepagePolicyStat notifyHomepageUpdated(); } @@ -134,7 +133,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/Chrome diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java -@@ -397,6 +397,7 @@ public final class ChromePreferenceKeys { +@@ -385,6 +385,7 @@ public final class ChromePreferenceKeys { public static final String HOMEPAGE_PARTNER_CUSTOMIZED_DEFAULT_GURL = "Chrome.Homepage.PartnerCustomizedDefaultGurl"; @@ -156,7 +155,7 @@ diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/bro diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1487,6 +1487,9 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1514,6 +1514,9 @@ Your Google account may have other forms of browsing history like searches and a Last hour @@ -178,30 +177,19 @@ diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_u registry->RegisterInt64Pref(prefs::kDefaultBrowserLastDeclined, 0); bool reset_check_default = false; -diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc ---- a/chrome/common/pref_names.cc -+++ b/chrome/common/pref_names.cc -@@ -82,6 +82,10 @@ const char kForceEphemeralProfiles[] = "profile.ephemeral_mode"; - // A boolean specifying whether the New Tab page is the home page or not. - const char kHomePageIsNewTabPage[] = "homepage_is_newtabpage"; - -+// A boolean specifying whether opening a new tab should open the Home page -+// instead of the New Tab page. -+const char kNewTabPageIsHomePage[] = "newtabpage_is_homepage"; -+ - // This is the URL of the page to load when opening new tabs. - const char kHomePage[] = "homepage"; - diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h -@@ -372,6 +372,7 @@ extern const char kRestrictedManagedGuestSessionExtensionCleanupExemptList[]; - extern const char kUsedPolicyCertificates[]; - #endif // BUILDFLAG(IS_CHROMEOS) - extern const char kShowHomeButton[]; -+extern const char kNewTabPageIsHomePage[]; - extern const char kSpeechRecognitionFilterProfanities[]; - extern const char kAllowedDomainsForApps[]; - #if BUILDFLAG(IS_CHROMEOS_LACROS) +@@ -1310,6 +1310,10 @@ inline constexpr char kUsedPolicyCertificates[] = + // visible on the toolbar. + inline constexpr char kShowHomeButton[] = "browser.show_home_button"; + ++// A boolean specifying whether opening a new tab should open the Home page ++// instead of the New Tab page. ++inline constexpr char kNewTabPageIsHomePage[] = "newtabpage_is_homepage"; ++ + // Boolean pref to define the default setting for "block offensive words". + // The old key value is kept to avoid unnecessary migration code. + inline constexpr char kSpeechRecognitionFilterProfanities[] = -- 2.25.1 diff --git a/build/patches/Add-site-engagement-flag.patch b/build/patches/Add-site-engagement-flag.patch index fa1d9f45..a61e3ac9 100644 --- a/build/patches/Add-site-engagement-flag.patch +++ b/build/patches/Add-site-engagement-flag.patch @@ -21,7 +21,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -146,6 +146,7 @@ +@@ -144,6 +144,7 @@ #include "components/segmentation_platform/public/features.h" #include "components/send_tab_to_self/features.h" #include "components/services/heap_profiling/public/cpp/switches.h" @@ -29,7 +29,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc #include "components/shared_highlighting/core/common/shared_highlighting_features.h" #include "components/signin/core/browser/dice_account_reconcilor_delegate.h" #include "components/signin/public/base/signin_buildflags.h" -@@ -9441,6 +9442,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -9560,6 +9561,11 @@ const FeatureEntry kFeatureEntries[] = { kLargeFaviconFromGoogleVariations, "LargeFaviconFromGoogle")}, @@ -44,7 +44,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3694,6 +3694,11 @@ const char kSkipServiceWorkerFetchHandlerDescription[] = +@@ -3765,6 +3765,11 @@ const char kSkipServiceWorkerFetchHandlerDescription[] = "Skips starting the service worker and run the fetch handler if the fetch " "handler is recognized as skippable."; @@ -59,7 +59,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2143,6 +2143,9 @@ extern const char kReduceAcceptLanguageDescription[]; +@@ -2195,6 +2195,9 @@ extern const char kReduceAcceptLanguageDescription[]; extern const char kSkipServiceWorkerFetchHandlerName[]; extern const char kSkipServiceWorkerFetchHandlerDescription[]; diff --git a/build/patches/Add-support-for-ISupportHelpAndFeedback.patch b/build/patches/Add-support-for-ISupportHelpAndFeedback.patch index 93423c66..d1e94a2c 100644 --- a/build/patches/Add-support-for-ISupportHelpAndFeedback.patch +++ b/build/patches/Add-support-for-ISupportHelpAndFeedback.patch @@ -12,7 +12,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java -@@ -81,6 +81,7 @@ import org.chromium.components.browser_ui.settings.CustomDividerFragment; +@@ -83,6 +83,7 @@ import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher; import org.chromium.components.browser_ui.settings.PaddedDividerItemDecoration; import org.chromium.components.browser_ui.settings.SettingsLauncher; @@ -20,7 +20,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/Settin import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; import org.chromium.components.browser_ui.site_settings.SiteSettingsPreferenceFragment; import org.chromium.components.browser_ui.util.TraceEventVectorDrawableCompat; -@@ -396,8 +397,12 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity +@@ -398,8 +399,12 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity finish(); return true; } else if (item.getItemId() == R.id.menu_id_general_help) { diff --git a/build/patches/Add-webGL-site-setting.patch b/build/patches/Add-webGL-site-setting.patch index 39e5ab7c..71500535 100644 --- a/build/patches/Add-webGL-site-setting.patch +++ b/build/patches/Add-webGL-site-setting.patch @@ -231,7 +231,7 @@ diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_ba unsigned WebGLRenderingContextBase::CurrentMaxGLContexts() { base::AutoLock locker(WebGLContextLimitLock()); DCHECK(webgl_context_limits_initialized_); -@@ -494,25 +501,6 @@ static String ExtractWebGLContextCreationError( +@@ -521,25 +528,6 @@ static String ExtractWebGLContextCreationError( const Platform::GraphicsInfo& info) { StringBuilder builder; builder.Append("Could not create a WebGL context"); @@ -257,7 +257,7 @@ diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_ba FormatWebGLStatusString("ErrorMessage", info.error_message.Utf8().c_str(), builder); builder.Append('.'); -@@ -572,6 +560,12 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider( +@@ -599,6 +587,12 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider( const CanvasContextCreationAttributesCore& attributes, Platform::ContextType context_type, Platform::GraphicsInfo* graphics_info) { @@ -273,7 +273,7 @@ diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_ba diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h -@@ -1933,6 +1933,8 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext, +@@ -1936,6 +1936,8 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext, DOMArrayBufferView* pixels, int64_t offset); diff --git a/build/patches/Add-webRTC-site-settings.patch b/build/patches/Add-webRTC-site-settings.patch index 6612ffce..4bfa8441 100644 --- a/build/patches/Add-webRTC-site-settings.patch +++ b/build/patches/Add-webRTC-site-settings.patch @@ -209,16 +209,16 @@ diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_d diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc -@@ -11,6 +11,8 @@ - #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" +@@ -12,6 +12,8 @@ #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h" + #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" +#include "third_party/blink/public/platform/web_content_settings_client.h" +#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_insertable_streams.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_parameters.h" -@@ -251,6 +253,14 @@ RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(ScriptState* state, +@@ -255,6 +257,14 @@ RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(ScriptState* state, if (kind != "audio" && kind != "video") return nullptr; @@ -236,16 +236,16 @@ diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver. diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc -@@ -16,6 +16,8 @@ - #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" +@@ -17,6 +17,8 @@ #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h" + #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" +#include "third_party/blink/public/platform/web_content_settings_client.h" +#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_insertable_streams.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_parameters.h" -@@ -946,6 +948,14 @@ RTCRtpCapabilities* RTCRtpSender::getCapabilities(ScriptState* state, +@@ -950,6 +952,14 @@ RTCRtpCapabilities* RTCRtpSender::getCapabilities(ScriptState* state, if (kind != "audio" && kind != "video") return nullptr; diff --git a/build/patches/Allow-building-without-enable_reporting.patch b/build/patches/Allow-building-without-enable_reporting.patch index aed5a084..1bf318d4 100644 --- a/build/patches/Allow-building-without-enable_reporting.patch +++ b/build/patches/Allow-building-without-enable_reporting.patch @@ -40,7 +40,7 @@ diff --git a/chrome/browser/net/chrome_report_sender.cc b/chrome/browser/net/chr diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc -@@ -1306,6 +1306,7 @@ String BuildReportStatus(const net::ReportingReport::Status status) { +@@ -1299,6 +1299,7 @@ String BuildReportStatus(const net::ReportingReport::Status status) { } } @@ -48,7 +48,7 @@ diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/brow std::vector ComputeReportingURLs(RenderFrameHostImpl* frame_host) { std::vector urls; frame_host->ForEachRenderFrameHostWithAction( -@@ -1319,6 +1320,7 @@ std::vector ComputeReportingURLs(RenderFrameHostImpl* frame_host) { +@@ -1312,6 +1313,7 @@ std::vector ComputeReportingURLs(RenderFrameHostImpl* frame_host) { }); return urls; } @@ -200,7 +200,7 @@ diff --git a/content/browser/network/reporting_service_proxy.cc b/content/browse diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc -@@ -13027,12 +13027,6 @@ void RenderFrameHostImpl::MaybeGenerateCrashReport( +@@ -13368,12 +13368,6 @@ void RenderFrameHostImpl::MaybeGenerateCrashReport( base::Value::Dict body; if (!reason.empty()) body.Set("reason", reason); @@ -246,7 +246,7 @@ diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -222,7 +222,7 @@ extern const base::FeatureParam kTimeoutTcpConnectAttemptMax( +@@ -242,7 +242,7 @@ extern const base::FeatureParam kTimeoutTcpConnectAttemptMax( #if BUILDFLAG(ENABLE_REPORTING) BASE_FEATURE(kDocumentReporting, "DocumentReporting", @@ -307,7 +307,7 @@ diff --git a/services/network/public/cpp/features.cc b/services/network/public/c diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn -@@ -1382,7 +1382,6 @@ mojom("mojom") { +@@ -1431,7 +1431,6 @@ mojom("mojom") { export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" export_header_blink = "third_party/blink/public/platform/web_common.h" if (enable_reporting) { @@ -318,7 +318,7 @@ diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mo diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom -@@ -1118,6 +1118,7 @@ interface NetworkContext { +@@ -1169,6 +1169,7 @@ interface NetworkContext { // provided |network_isolation_key|. // // Spec: https://w3c.github.io/reporting/#concept-reports @@ -326,7 +326,7 @@ diff --git a/services/network/public/mojom/network_context.mojom b/services/netw QueueReport(string type, string group, url.mojom.Url url, -@@ -1131,6 +1132,7 @@ interface NetworkContext { +@@ -1182,6 +1183,7 @@ interface NetworkContext { // Note that this queued report will never be delivered if no reporting // endpoint matching is registered for with the provided // |network_isolation_key|. @@ -372,7 +372,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/ #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/content_security_policy.mojom-blink.h" #include "services/network/public/mojom/source_location.mojom-blink.h" -@@ -2510,9 +2511,11 @@ void LocalFrame::MainFrameInteractive() { +@@ -2504,9 +2505,11 @@ void LocalFrame::MainFrameInteractive() { } } @@ -398,7 +398,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/b #include "services/device/public/mojom/device_posture_provider.mojom-blink-forward.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/mojom/fetch_api.mojom-blink-forward.h" -@@ -630,9 +630,9 @@ class CORE_EXPORT LocalFrame final +@@ -629,9 +629,9 @@ class CORE_EXPORT LocalFrame final void FinishedScrollSequence(); SmoothScrollSequencer* GetSmoothScrollSequencer() const; diff --git a/build/patches/Allow-building-without-supervised-users.patch b/build/patches/Allow-building-without-supervised-users.patch index c5d3cc55..5604a17d 100644 --- a/build/patches/Allow-building-without-supervised-users.patch +++ b/build/patches/Allow-building-without-supervised-users.patch @@ -7,17 +7,16 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html chrome/android/BUILD.gn | 1 - chrome/android/chrome_java_sources.gni | 1 - chrome/browser/BUILD.gn | 6 ------ - chrome/browser/about_flags.cc | 4 ++++ components/supervised_user/buildflags.gni | 6 +----- - 5 files changed, 5 insertions(+), 13 deletions(-) + 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -3420,7 +3420,6 @@ generate_jni("chrome_jni_headers") { +@@ -3488,7 +3488,6 @@ generate_jni("chrome_jni_headers") { + "java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java", "java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java", "java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java", @@ -25,10 +24,10 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -1051,7 +1051,6 @@ chrome_java_sources = [ +@@ -1060,7 +1060,6 @@ chrome_java_sources = [ + "java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TopSitesTileView.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java", "java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java", "java/src/org/chromium/chrome/browser/survey/SurveyController.java", @@ -36,7 +35,7 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -3003,8 +3003,6 @@ static_library("browser") { +@@ -3074,8 +3074,6 @@ static_library("browser") { "feed/android/refresh_task_scheduler_impl.cc", "feed/android/refresh_task_scheduler_impl.h", "feed/android/web_feed_bridge.cc", @@ -45,7 +44,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "file_select_helper_contacts_android.cc", "file_select_helper_contacts_android.h", "first_run/android/first_run_prefs.cc", -@@ -3219,10 +3217,6 @@ static_library("browser") { +@@ -3290,10 +3288,6 @@ static_library("browser") { "ssl/chrome_security_state_model_delegate.h", "ssl/known_interception_disclosure_infobar.cc", "ssl/known_interception_disclosure_infobar.h", @@ -56,39 +55,6 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "sync/glue/synced_tab_delegate_android.cc", "sync/glue/synced_tab_delegate_android.h", "sync/glue/synced_window_delegate_android.cc", -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -1495,6 +1495,7 @@ const FeatureEntry::FeatureVariation kJourneysLabelsVariations[] = { - }; - - #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID) -+#if BUILDFLAG(ENABLE_SUPERVISED_USERS) - const FeatureEntry::FeatureParam kLocalWebApprovalsPreferLocalParams[] = { - {"preferred_button", "local"}}; - const FeatureEntry::FeatureParam kLocalWebApprovalsPreferRemoteParams[] = { -@@ -1506,6 +1507,7 @@ const FeatureEntry::FeatureVariation kLocalWebApprovalsVariations[] = { - std::size(kLocalWebApprovalsPreferRemoteParams), nullptr}, - }; - #endif -+#endif - - const FeatureEntry::FeatureParam kChromeRefresh2023Level1[] = {{"level", "1"}}; - -@@ -7693,11 +7695,13 @@ const FeatureEntry kFeatureEntries[] = { - #endif // BUILDFLAG(IS_CHROMEOS_ASH) - - #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID) -+#if BUILDFLAG(ENABLE_SUPERVISED_USERS) - {"enable-local-web-approvals", flag_descriptions::kLocalWebApprovalsName, - flag_descriptions::kLocalWebApprovalsDescription, kOsCrOS | kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(supervised_user::kLocalWebApprovals, - kLocalWebApprovalsVariations, - "LocalWebApprovals")}, -+#endif - #endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID) - - #if BUILDFLAG(ENABLE_SUPERVISED_USERS) diff --git a/components/supervised_user/buildflags.gni b/components/supervised_user/buildflags.gni --- a/components/supervised_user/buildflags.gni +++ b/components/supervised_user/buildflags.gni diff --git a/build/patches/Allow-playing-audio-in-background.patch b/build/patches/Allow-playing-audio-in-background.patch index bc996f45..6cfe2da2 100644 --- a/build/patches/Allow-playing-audio-in-background.patch +++ b/build/patches/Allow-playing-audio-in-background.patch @@ -24,7 +24,7 @@ diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc void WebMediaPlayerImpl::EnabledAudioTracksChanged( const WebVector& enabledTrackIds) { DCHECK(main_task_runner_->BelongsToCurrentThread()); -@@ -3503,7 +3509,10 @@ bool WebMediaPlayerImpl::ShouldPausePlaybackWhenHidden() const { +@@ -3513,7 +3519,10 @@ bool WebMediaPlayerImpl::ShouldPausePlaybackWhenHidden() const { : HasAudio(); // Audio only stream is allowed to play when in background. diff --git a/build/patches/Always-use-new-tab-page-for-default-home-page.patch b/build/patches/Always-use-new-tab-page-for-default-home-page.patch index 7043453f..5148a649 100644 --- a/build/patches/Always-use-new-tab-page-for-default-home-page.patch +++ b/build/patches/Always-use-new-tab-page-for-default-home-page.patch @@ -12,7 +12,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java -@@ -151,10 +151,6 @@ public class HomepageManager implements HomepagePolicyManager.HomepagePolicyStat +@@ -152,10 +152,6 @@ public class HomepageManager implements HomepagePolicyManager.HomepagePolicyStat * if the homepage button is force enabled via flag. */ public static String getDefaultHomepageUri() { diff --git a/build/patches/AudioBuffer-AnalyserNode-fp-mitigations.patch b/build/patches/AudioBuffer-AnalyserNode-fp-mitigations.patch index 84a98372..8f4a1654 100644 --- a/build/patches/AudioBuffer-AnalyserNode-fp-mitigations.patch +++ b/build/patches/AudioBuffer-AnalyserNode-fp-mitigations.patch @@ -23,7 +23,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -3888,6 +3888,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -3916,6 +3916,10 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kKioskEnableAppServiceDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kKioskEnableAppService)}, #endif // BUILDFLAG(IS_CHROMEOS) @@ -37,9 +37,9 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3614,6 +3614,11 @@ const char kWebrtcUseMinMaxVEADimensionsDescription[] = - "When enabled, WebRTC will only use the Video Encode Accelerator for " - "video resolutions inside those published as supported."; +@@ -3685,6 +3685,11 @@ const char kWebTransportDeveloperModeDescription[] = + "When enabled, removes the requirement that all certificates used for " + "WebTransport over HTTP/3 are issued by a known certificate root."; +const char kAudioContextShuffleEnabledName[] = + "Enable Audio Context fingerprint deception"; @@ -52,20 +52,20 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2086,6 +2086,9 @@ extern const char kWebRtcRemoteEventLogDescription[]; +@@ -2135,6 +2135,9 @@ extern const char kWebRtcRemoteEventLogDescription[]; extern const char kWebrtcUseMinMaxVEADimensionsName[]; extern const char kWebrtcUseMinMaxVEADimensionsDescription[]; +extern const char kAudioContextShuffleEnabledName[]; +extern const char kAudioContextShuffleEnabledDescription[]; + - extern const char kWebUsbDeviceDetectionName[]; - extern const char kWebUsbDeviceDetectionDescription[]; + extern const char kWebTransportDeveloperModeName[]; + extern const char kWebTransportDeveloperModeDescription[]; diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -234,6 +234,10 @@ BASE_FEATURE(kBiddingAndScoringDebugReportingAPI, +@@ -244,6 +244,10 @@ BASE_FEATURE(kBiddingAndScoringDebugReportingAPI, "BiddingAndScoringDebugReportingAPI", base::FEATURE_DISABLED_BY_DEFAULT); @@ -79,7 +79,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -142,6 +142,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapConcurrentSweeping); +@@ -149,6 +149,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapConcurrentSweeping); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarking); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarkingStress); diff --git a/build/patches/Block-gateway-attacks-via-websockets.patch b/build/patches/Block-gateway-attacks-via-websockets.patch index 521e4740..672e7513 100644 --- a/build/patches/Block-gateway-attacks-via-websockets.patch +++ b/build/patches/Block-gateway-attacks-via-websockets.patch @@ -23,7 +23,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc -@@ -721,4 +721,20 @@ void ExecutionContext::WriteIntoTrace( +@@ -713,4 +713,20 @@ void ExecutionContext::WriteIntoTrace( proto->set_world_type(GetWorldType(*this)); } @@ -69,7 +69,7 @@ diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc -@@ -578,6 +578,26 @@ bool FrameFetchContext::ShouldBlockRequestByInspector(const KURL& url) const { +@@ -591,6 +591,26 @@ bool FrameFetchContext::ShouldBlockRequestByInspector(const KURL& url) const { return should_block_request; } @@ -99,7 +99,7 @@ diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/thi diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h -@@ -173,6 +173,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext, +@@ -175,6 +175,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext, bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const override; std::unique_ptr CreateWebSocketHandshakeThrottle() override; @@ -159,7 +159,7 @@ diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/thi diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc -@@ -102,6 +102,30 @@ bool ShouldBlockDanglingMarkup(const KURL& request_url) { +@@ -101,6 +101,30 @@ bool ShouldBlockDanglingMarkup(const KURL& request_url) { request_url.ProtocolIsInHTTPFamily(); } @@ -190,7 +190,7 @@ diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetc scoped_refptr ExtractBlobHandle( Request* request, ExceptionState& exception_state) { -@@ -216,6 +240,13 @@ ScriptPromise BackgroundFetchManager::fetch( +@@ -187,6 +211,13 @@ ScriptPromise BackgroundFetchManager::fetch( exception_state); } @@ -201,9 +201,9 @@ diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetc + exception_state); + } + - kurls.insert(request_url); - } - + if (ShouldBlockPort(request_url)) { + return RejectWithTypeError(script_state, request_url, + "that port is not allowed", exception_state); diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc diff --git a/build/patches/Block-qjz9zk-or-trk-requests.patch b/build/patches/Block-qjz9zk-or-trk-requests.patch index 084b8172..b183d82d 100644 --- a/build/patches/Block-qjz9zk-or-trk-requests.patch +++ b/build/patches/Block-qjz9zk-or-trk-requests.patch @@ -50,7 +50,7 @@ diff --git a/chrome/browser/history/history_utils.cc b/chrome/browser/history/hi diff --git a/chrome/browser/ui/singleton_tabs.cc b/chrome/browser/ui/singleton_tabs.cc --- a/chrome/browser/ui/singleton_tabs.cc +++ b/chrome/browser/ui/singleton_tabs.cc -@@ -127,6 +127,11 @@ int GetIndexOfExistingTab(Browser* browser, const NavigateParams& params) { +@@ -174,6 +174,11 @@ int GetIndexOfExistingTab(Browser* browser, const NavigateParams& params) { continue; } @@ -119,7 +119,7 @@ diff --git a/content/browser/child_process_security_policy_impl.cc b/content/bro diff --git a/net/BUILD.gn b/net/BUILD.gn --- a/net/BUILD.gn +++ b/net/BUILD.gn -@@ -1047,6 +1047,8 @@ component("net") { +@@ -1056,6 +1056,8 @@ component("net") { "url_request/url_request_http_job.cc", "url_request/url_request_http_job.h", "url_request/url_request_interceptor.cc", @@ -236,7 +236,7 @@ diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/ur #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_throttler_manager.h" -@@ -572,6 +573,8 @@ std::unique_ptr URLRequestContextBuilder::Build() { +@@ -573,6 +574,8 @@ std::unique_ptr URLRequestContextBuilder::Build() { job_factory->SetProtocolHandler(scheme_handler.first, std::move(scheme_handler.second)); } diff --git a/build/patches/Bookmarks-select-all-menu-entry.patch b/build/patches/Bookmarks-select-all-menu-entry.patch index 289af638..ab6efbb7 100644 --- a/build/patches/Bookmarks-select-all-menu-entry.patch +++ b/build/patches/Bookmarks-select-all-menu-entry.patch @@ -29,7 +29,7 @@ diff --git a/chrome/android/java/res/menu/bookmark_toolbar_menu.xml b/chrome/and diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbar.java --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbar.java -@@ -28,6 +28,8 @@ import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelega +@@ -27,6 +27,8 @@ import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelega import java.util.ArrayList; import java.util.List; import java.util.function.Function; @@ -38,7 +38,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm /** * Main toolbar of bookmark UI. It is responsible for displaying title and buttons * associated with the current context. -@@ -158,6 +160,7 @@ public class BookmarkToolbar extends SelectableListToolbar +@@ -167,6 +169,7 @@ public class BookmarkToolbar extends SelectableListToolbar void setCurrentFolder(BookmarkId folder) { mCurrentFolder = mBookmarkModel.getBookmarkById(folder); @@ -46,7 +46,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm getMenu().findItem(R.id.import_menu_id).setVisible(true); getMenu().findItem(R.id.export_menu_id).setVisible(true); } -@@ -186,6 +189,17 @@ public class BookmarkToolbar extends SelectableListToolbar +@@ -195,6 +198,17 @@ public class BookmarkToolbar extends SelectableListToolbar mExportBookmarkRunnable.run(); return true; } @@ -64,7 +64,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm return mMenuIdClickedFunction.apply(menuItem.getItemId()); } -@@ -208,6 +222,7 @@ public class BookmarkToolbar extends SelectableListToolbar +@@ -217,6 +231,7 @@ public class BookmarkToolbar extends SelectableListToolbar getMenu().findItem(R.id.import_menu_id).setVisible(mCurrentFolder != null); getMenu().findItem(R.id.export_menu_id).setVisible(mCurrentFolder != null); @@ -75,7 +75,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/Bookm diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -240,6 +240,9 @@ CHAR_LIMIT guidelines: +@@ -245,6 +245,9 @@ CHAR_LIMIT guidelines: Sites diff --git a/build/patches/Bromite-auto-updater.patch b/build/patches/Bromite-auto-updater.patch index 19e5323d..25c91918 100644 --- a/build/patches/Bromite-auto-updater.patch +++ b/build/patches/Bromite-auto-updater.patch @@ -50,7 +50,7 @@ diff --git a/build/android/java/templates/BuildConfig.template b/build/android/j diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni -@@ -2151,6 +2151,9 @@ if (enable_java_templates && is_android) { +@@ -2144,6 +2144,9 @@ if (enable_java_templates && is_android) { if (defined(testonly) && testonly) { defines += [ "_IS_FOR_TEST" ] } @@ -63,7 +63,7 @@ diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -849,6 +849,9 @@ chrome_java_sources = [ +@@ -858,6 +858,9 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/omaha/UpdateConfigs.java", "java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java", "java/src/org/chromium/chrome/browser/omaha/UpdateStatusProvider.java", @@ -148,7 +148,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java -@@ -32,6 +32,8 @@ import java.net.HttpURLConnection; +@@ -33,6 +33,8 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; @@ -157,7 +157,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase /** * Keeps tabs on the current state of Chrome, tracking if and when a request should be sent to the * Omaha Server. -@@ -98,7 +100,10 @@ public class OmahaBase { +@@ -99,7 +101,10 @@ public class OmahaBase { static final String PREF_TIMESTAMP_FOR_NEW_REQUEST = "timestampForNewRequest"; static final String PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT = "timestampForNextPostAttempt"; static final String PREF_TIMESTAMP_OF_INSTALL = "timestampOfInstall"; @@ -170,10 +170,10 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase private static final int UNKNOWN_DATE = -2; @@ -157,7 +162,8 @@ public class OmahaBase { + } - /** See {@link #sIsDisabled}. */ static boolean isDisabled() { -- return sIsDisabled; +- return sDisabledForTesting; + // do not enable version control via Omaha Update Server + return true; } @@ -315,10 +315,10 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMen import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; - import androidx.annotation.VisibleForTesting; import org.chromium.base.BuildInfo; -@@ -137,8 +138,21 @@ public class UpdateMenuItemHelper { + import org.chromium.base.Callback; +@@ -135,8 +136,21 @@ public class UpdateMenuItemHelper { Log.e(TAG, "Failed to launch Activity for: %s", mStatus.updateUrl); } break; @@ -340,7 +340,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMen default: return; } -@@ -184,7 +198,7 @@ public class UpdateMenuItemHelper { +@@ -182,7 +196,7 @@ public class UpdateMenuItemHelper { mMenuUiState = new MenuUiState(); switch (mStatus.updateState) { @@ -349,7 +349,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMen // The badge is hidden if the update menu item has been clicked until there is an // even newer version of Chrome available. showBadge |= !TextUtils.equals( -@@ -239,6 +253,72 @@ public class UpdateMenuItemHelper { +@@ -237,6 +251,72 @@ public class UpdateMenuItemHelper { mMenuUiState.itemState.icon = R.drawable.ic_error_24dp_filled; mMenuUiState.itemState.enabled = false; break; @@ -727,7 +727,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateSta diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java -@@ -51,7 +51,8 @@ public class VersionNumberGetter { +@@ -50,7 +50,8 @@ public class VersionNumberGetter { private static VersionNumberGetter sInstanceForTests; /** If false, OmahaClient will never report that a newer version is available. */ @@ -1125,7 +1125,7 @@ diff --git a/chrome/browser/endpoint_fetcher/endpoint_fetcher_android.cc b/chrom #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/channel_info.h" -@@ -30,6 +31,24 @@ static void OnEndpointFetcherComplete( +@@ -31,6 +32,24 @@ static void OnEndpointFetcherComplete( base::android::AttachCurrentThread(), std::move(endpoint_response->response)))); } @@ -1150,7 +1150,7 @@ diff --git a/chrome/browser/endpoint_fetcher/endpoint_fetcher_android.cc b/chrom } // namespace // TODO(crbug.com/1077537) Create a KeyProvider so -@@ -109,6 +128,7 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( +@@ -113,6 +132,7 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( JNIEnv* env, const base::android::JavaParamRef& jprofile, const base::android::JavaParamRef& jurl, @@ -1158,7 +1158,7 @@ diff --git a/chrome/browser/endpoint_fetcher/endpoint_fetcher_android.cc b/chrom jint jannotation_hash_code, const base::android::JavaParamRef& jcallback) { auto endpoint_fetcher = std::make_unique( -@@ -116,6 +136,9 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( +@@ -120,6 +140,9 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( ->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), GURL(base::android::ConvertJavaStringToUTF8(env, jurl)), @@ -1168,7 +1168,7 @@ diff --git a/chrome/browser/endpoint_fetcher/endpoint_fetcher_android.cc b/chrom net::NetworkTrafficAnnotationTag::FromJavaAnnotation( jannotation_hash_code)); auto* const endpoint_fetcher_ptr = endpoint_fetcher.get(); -@@ -127,3 +150,30 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( +@@ -131,3 +154,30 @@ static void JNI_EndpointFetcher_NativeFetchWithNoAuth( std::move(endpoint_fetcher)), nullptr); } @@ -1281,7 +1281,7 @@ new file mode 100644 diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -247,6 +247,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -252,6 +252,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kNotificationPermissionBottomSheet, &kPageAnnotationsService, &kPreconnectOnTabCreation, @@ -1289,7 +1289,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &kBookmarksImprovedSaveFlow, &kBookmarksRefresh, &kOmahaMinSdkVersionAndroid, -@@ -673,6 +674,10 @@ BASE_FEATURE(kContextMenuTranslateWithGoogleLens, +@@ -687,6 +688,10 @@ BASE_FEATURE(kContextMenuTranslateWithGoogleLens, "ContextMenuTranslateWithGoogleLens", base::FEATURE_DISABLED_BY_DEFAULT); @@ -1303,8 +1303,8 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -99,6 +99,7 @@ BASE_DECLARE_FEATURE(kFoldableJankFix); - BASE_DECLARE_FEATURE(kGridTabSwitcherForTablets); +@@ -105,6 +105,7 @@ BASE_DECLARE_FEATURE(kFoldableJankFix); + BASE_DECLARE_FEATURE(kGridTabSwitcherLandscapeAspectRatioPhones); BASE_DECLARE_FEATURE(kImprovedIncognitoScreenshot); BASE_DECLARE_FEATURE(kIncognitoReauthenticationForAndroid); +BASE_DECLARE_FEATURE(kInlineUpdateFlow); @@ -1314,7 +1314,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -285,6 +285,7 @@ public abstract class ChromeFeatureList { +@@ -291,6 +291,7 @@ public abstract class ChromeFeatureList { "IncognitoReauthenticationForAndroid"; public static final String INCOGNITO_SCREENSHOT = "IncognitoScreenshot"; public static final String INFOBAR_SCROLL_OPTIMIZATION = "InfobarScrollOptimization"; @@ -1325,7 +1325,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -2073,6 +2073,12 @@ Your Google account may have other forms of browsing history like searches and a +@@ -2106,6 +2106,12 @@ Your Google account may have other forms of browsing history like searches and a Chrome updates are no longer supported for this version of Android @@ -1338,7 +1338,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro -@@ -3668,7 +3674,10 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

@@ -1350,7 +1350,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro Newer version is available -@@ -3679,6 +3688,18 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

Android version is unsupported @@ -1372,7 +1372,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoint_fetcher/endpoint_fetcher.cc --- a/components/endpoint_fetcher/endpoint_fetcher.cc +++ b/components/endpoint_fetcher/endpoint_fetcher.cc -@@ -17,6 +17,11 @@ +@@ -18,6 +18,11 @@ #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" @@ -1384,7 +1384,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi namespace { const char kContentTypeKey[] = "Content-Type"; const char kDeveloperKey[] = "X-Developer-Key"; -@@ -61,6 +66,7 @@ EndpointFetcher::EndpointFetcher( +@@ -64,6 +69,7 @@ EndpointFetcher::EndpointFetcher( http_method_(http_method), content_type_(content_type), timeout_ms_(timeout_ms), @@ -1392,7 +1392,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi post_data_(post_data), headers_(headers), annotation_tag_(annotation_tag), -@@ -78,6 +84,7 @@ EndpointFetcher::EndpointFetcher( +@@ -82,6 +88,7 @@ EndpointFetcher::EndpointFetcher( http_method_("GET"), content_type_(std::string()), timeout_ms_(0), @@ -1400,7 +1400,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi post_data_(std::string()), annotation_tag_(annotation_tag), url_loader_factory_(url_loader_factory), -@@ -101,6 +108,7 @@ EndpointFetcher::EndpointFetcher( +@@ -107,6 +114,7 @@ EndpointFetcher::EndpointFetcher( http_method_(http_method), content_type_(content_type), timeout_ms_(timeout_ms), @@ -1408,7 +1408,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi post_data_(post_data), annotation_tag_(annotation_tag), url_loader_factory_(url_loader_factory), -@@ -127,6 +135,7 @@ EndpointFetcher::EndpointFetcher( +@@ -134,6 +142,7 @@ EndpointFetcher::EndpointFetcher( http_method_(http_method), content_type_(content_type), timeout_ms_(timeout_ms), @@ -1416,13 +1416,14 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi post_data_(post_data), headers_(headers), cors_exempt_headers_(cors_exempt_headers), -@@ -138,10 +147,28 @@ EndpointFetcher::EndpointFetcher( +@@ -146,11 +155,29 @@ EndpointFetcher::EndpointFetcher( EndpointFetcher::EndpointFetcher( const net::NetworkTrafficAnnotationTag& annotation_tag) : timeout_ms_(kDefaultTimeOutMs), + intercept_redirect_(false), annotation_tag_(annotation_tag), identity_manager_(nullptr), + consent_level_(absl::nullopt), sanitize_response_(true) {} +// constructor used by Bromite @@ -1445,7 +1446,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi EndpointFetcher::~EndpointFetcher() = default; void EndpointFetcher::Fetch(EndpointFetcherCallback endpoint_fetcher_callback) { -@@ -198,6 +225,8 @@ void EndpointFetcher::PerformRequest( +@@ -209,6 +236,8 @@ void EndpointFetcher::PerformRequest( resource_request->method = http_method_; resource_request->url = url_; resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; @@ -1454,7 +1455,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi if (base::EqualsCaseInsensitiveASCII(http_method_, "POST")) { resource_request->headers.SetHeader(kContentTypeKey, content_type_); } -@@ -228,25 +257,52 @@ void EndpointFetcher::PerformRequest( +@@ -239,25 +268,52 @@ void EndpointFetcher::PerformRequest( default: break; } @@ -1513,7 +1514,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi } void EndpointFetcher::OnResponseFetched( -@@ -325,3 +381,38 @@ void EndpointFetcher::OnSanitizationResult( +@@ -336,3 +392,38 @@ void EndpointFetcher::OnSanitizationResult( std::string EndpointFetcher::GetUrlForTesting() { return url_.spec(); } @@ -1555,7 +1556,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoi diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoint_fetcher/endpoint_fetcher.h --- a/components/endpoint_fetcher/endpoint_fetcher.h +++ b/components/endpoint_fetcher/endpoint_fetcher.h -@@ -16,6 +16,8 @@ +@@ -17,6 +17,8 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/data_decoder/public/cpp/json_sanitizer.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -1564,7 +1565,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoin namespace network { struct ResourceRequest; -@@ -38,6 +40,8 @@ enum class FetchErrorType { +@@ -39,6 +41,8 @@ enum class FetchErrorType { struct EndpointResponse { std::string response; @@ -1573,7 +1574,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoin int http_status_code{-1}; absl::optional error_type; }; -@@ -90,6 +94,14 @@ class EndpointFetcher { +@@ -92,6 +96,14 @@ class EndpointFetcher { const GURL& url, const net::NetworkTrafficAnnotationTag& annotation_tag); @@ -1588,7 +1589,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoin // Used for tests. Can be used if caller constructs their own // url_loader_factory and identity_manager. EndpointFetcher( -@@ -144,6 +156,11 @@ class EndpointFetcher { +@@ -147,6 +159,11 @@ class EndpointFetcher { void OnSanitizationResult(std::unique_ptr response, EndpointFetcherCallback endpoint_fetcher_callback, data_decoder::JsonSanitizer::Result result); @@ -1600,7 +1601,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoin enum AuthType { CHROME_API_KEY, OAUTH, NO_AUTH }; AuthType auth_type_; -@@ -151,10 +168,11 @@ class EndpointFetcher { +@@ -154,10 +171,11 @@ class EndpointFetcher { // Members set in constructor to be passed to network::ResourceRequest or // network::SimpleURLLoader. const std::string oauth_consumer_name_; @@ -1613,7 +1614,7 @@ diff --git a/components/endpoint_fetcher/endpoint_fetcher.h b/components/endpoin const std::string post_data_; const std::vector headers_; const std::vector cors_exempt_headers_; -@@ -172,6 +190,9 @@ class EndpointFetcher { +@@ -181,6 +199,9 @@ class EndpointFetcher { access_token_fetcher_; std::unique_ptr simple_url_loader_; diff --git a/build/patches/Bromite-subresource-adblocker.patch b/build/patches/Bromite-subresource-adblocker.patch index 16003d7c..0e9301eb 100644 --- a/build/patches/Bromite-subresource-adblocker.patch +++ b/build/patches/Bromite-subresource-adblocker.patch @@ -34,8 +34,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../net/system_network_context_manager.cc | 3 + .../sessions/session_restore_android.cc | 6 +- .../strings/android_chrome_strings.grd | 14 + - chrome/common/pref_names.cc | 3 + - chrome/common/pref_names.h | 1 + + chrome/common/pref_names.h | 3 + .../strings/android/site_settings.grdp | 4 +- components/component_updater/BUILD.gn | 7 + .../adblock_updater_service.cc | 268 ++++++++++++++++++ @@ -52,7 +51,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../browser/subresource_filter_features.cc | 116 +------- .../core/common/indexed_ruleset.cc | 5 +- third_party/blink/common/features.cc | 12 +- - 40 files changed, 1189 insertions(+), 135 deletions(-) + 39 files changed, 1188 insertions(+), 135 deletions(-) create mode 100644 chrome/android/java/res/layout/adblock_editor.xml create mode 100644 chrome/android/java/res/xml/adblock_preferences.xml create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/settings/AdBlockEditor.java @@ -65,7 +64,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -284,6 +284,7 @@ if (current_toolchain == default_toolchain) { +@@ -293,6 +293,7 @@ if (current_toolchain == default_toolchain) { "//chrome/android/modules/image_editor/provider:java", "//chrome/android/modules/stack_unwinder/provider:java", "//chrome/android/webapk/libs/client:client_java", @@ -76,7 +75,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -459,6 +459,7 @@ chrome_java_resources = [ +@@ -460,6 +460,7 @@ chrome_java_resources = [ "java/res/layout/account_chooser_dialog_title.xml", "java/res/layout/account_divider_preference.xml", "java/res/layout/account_management_account_row.xml", @@ -84,7 +83,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja "java/res/layout/auto_sign_in_first_run_dialog.xml", "java/res/layout/autofill_billing_address_dropdown.xml", "java/res/layout/autofill_card_name_and_number.xml", -@@ -652,6 +653,7 @@ chrome_java_resources = [ +@@ -656,6 +657,7 @@ chrome_java_resources = [ "java/res/xml/about_chrome_preferences.xml", "java/res/xml/account_management_preferences.xml", "java/res/xml/ad_services_config.xml", @@ -95,7 +94,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -937,6 +937,8 @@ chrome_java_sources = [ +@@ -946,6 +946,8 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/permissions/PermissionSettingsBridge.java", "java/src/org/chromium/chrome/browser/permissions/PermissionUpdateRequester.java", "java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceImpl.java", @@ -249,9 +248,9 @@ new file mode 100644 diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml -@@ -67,6 +67,11 @@ found in the LICENSE file. +@@ -66,6 +66,11 @@ android:key="safety_check" - android:order="11" + android:order="12" android:title="@string/prefs_safety_check"/> + @@ -487,7 +486,7 @@ diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h class BackgroundModeManager; class BrowserProcessPlatformPart; -@@ -70,6 +71,10 @@ namespace component_updater { +@@ -71,6 +72,10 @@ namespace component_updater { class ComponentUpdateService; } @@ -498,7 +497,7 @@ diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h namespace extensions { class EventRouterForwarder; } -@@ -240,6 +245,7 @@ class BrowserProcess { +@@ -241,6 +246,7 @@ class BrowserProcess { #endif virtual component_updater::ComponentUpdateService* component_updater() = 0; @@ -509,7 +508,7 @@ diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc -@@ -1107,6 +1107,26 @@ BrowserProcessImpl::component_updater() { +@@ -1129,6 +1129,26 @@ BrowserProcessImpl::component_updater() { return component_updater_.get(); } @@ -539,7 +538,7 @@ diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_pro diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h -@@ -203,6 +203,7 @@ class BrowserProcessImpl : public BrowserProcess, +@@ -204,6 +204,7 @@ class BrowserProcessImpl : public BrowserProcess, #endif component_updater::ComponentUpdateService* component_updater() override; @@ -547,7 +546,7 @@ diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_proc MediaFileSystemRegistry* media_file_system_registry() override; WebRtcLogUploader* webrtc_log_uploader() override; network_time::NetworkTimeTracker* network_time_tracker() override; -@@ -390,6 +391,7 @@ class BrowserProcessImpl : public BrowserProcess, +@@ -398,6 +399,7 @@ class BrowserProcessImpl : public BrowserProcess, // to concerns over integrity of data shared between profiles, // but some users of component updater only install per-user. std::unique_ptr component_updater_; @@ -596,8 +595,8 @@ diff --git a/chrome/browser/flags/android/cached_feature_flags.cc b/chrome/brows diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java -@@ -98,6 +98,14 @@ public class CachedFeatureFlags { - ChromeFeatureList.isEnabled(ChromeFeatureList.BACKGROUND_THREAD_POOL)); +@@ -101,6 +101,14 @@ public class CachedFeatureFlags { + ChromeFeatureList.isEnabled(ChromeFeatureList.CACHE_ACTIVITY_TASKID)); } + public static void setAdBlockFiltersURL(String url) { @@ -622,7 +621,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc -@@ -518,6 +518,9 @@ SystemNetworkContextManager::~SystemNetworkContextManager() { +@@ -567,6 +567,9 @@ SystemNetworkContextManager::~SystemNetworkContextManager() { void SystemNetworkContextManager::RegisterPrefs(PrefRegistrySimple* registry) { StubResolverConfigReader::RegisterPrefs(registry); @@ -651,7 +650,7 @@ diff --git a/chrome/browser/sessions/session_restore_android.cc b/chrome/browser diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -212,6 +212,20 @@ CHAR_LIMIT guidelines: +@@ -217,6 +217,20 @@ CHAR_LIMIT guidelines: Advanced @@ -672,34 +671,23 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro General -diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc ---- a/chrome/common/pref_names.cc -+++ b/chrome/common/pref_names.cc -@@ -2414,6 +2414,9 @@ const char kAudioCaptureAllowed[] = "hardware.audio_capture_enabled"; - // capture devices without prompt. - const char kAudioCaptureAllowedUrls[] = "hardware.audio_capture_allowed_urls"; +diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h +--- a/chrome/common/pref_names.h ++++ b/chrome/common/pref_names.h +@@ -2608,6 +2608,9 @@ inline constexpr char kAudioCaptureAllowed[] = "hardware.audio_capture_enabled"; + inline constexpr char kAudioCaptureAllowedUrls[] = + "hardware.audio_capture_allowed_urls"; +// Holds the URL to an indexed subresource filters file. -+const char kAdBlockFiltersURL[] = "adblock.filters_url"; ++inline constexpr char kAdBlockFiltersURL[] = "adblock.filters_url"; + // A pref holding the value of the policy used to explicitly allow or deny // access to video capture devices. When enabled or not set, the user is // prompted for device access. When disabled, access to video capture devices -diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h ---- a/chrome/common/pref_names.h -+++ b/chrome/common/pref_names.h -@@ -36,6 +36,7 @@ extern const char kDownloadDuplicateFilePromptEnabled[]; - extern const char kForceEphemeralProfiles[]; - extern const char kHomePageIsNewTabPage[]; - extern const char kHomePage[]; -+extern const char kAdBlockFiltersURL[]; - extern const char kHttpsOnlyModeEnabled[]; - extern const char kImportantSitesDialogHistory[]; - extern const char kProfileCreationTime[]; diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp --- a/components/browser_ui/strings/android/site_settings.grdp +++ b/components/browser_ui/strings/android/site_settings.grdp -@@ -346,8 +346,8 @@ +@@ -362,8 +362,8 @@ This site shows intrusive or misleading ads @@ -1530,7 +1518,7 @@ diff --git a/components/subresource_filter/content/browser/content_subresource_f diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h -@@ -411,6 +411,8 @@ class ContentSubresourceFilterThrottleManager +@@ -412,6 +412,8 @@ class ContentSubresourceFilterThrottleManager std::unique_ptr profile_interaction_manager_; @@ -1658,7 +1646,7 @@ diff --git a/components/subresource_filter/content/browser/ruleset_service.cc b/ DCHECK(indexed_version.IsValid()); return indexed_version; -@@ -453,6 +475,7 @@ void RulesetService::IndexAndStoreRuleset( +@@ -449,6 +471,7 @@ void RulesetService::IndexAndStoreRuleset( void RulesetService::OnWrittenRuleset(WriteRulesetCallback result_callback, const IndexedRulesetVersion& version) { DCHECK(!result_callback.is_null()); @@ -1666,7 +1654,7 @@ diff --git a/components/subresource_filter/content/browser/ruleset_service.cc b/ if (!version.IsValid()) return; version.SaveToPrefs(local_state_); -@@ -465,7 +488,6 @@ void RulesetService::OpenAndPublishRuleset( +@@ -461,7 +484,6 @@ void RulesetService::OpenAndPublishRuleset( IndexedRulesetLocator::GetRulesetDataFilePath( IndexedRulesetLocator::GetSubdirectoryPathForVersion( indexed_ruleset_base_dir_, version)); @@ -1930,7 +1918,7 @@ diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/comp diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -138,8 +138,8 @@ BASE_FEATURE(kAutofillSendUnidentifiedKeyAfterFill, +@@ -144,8 +144,8 @@ BASE_FEATURE(kAutofillSendUnidentifiedKeyAfterFill, // Apply lazy-loading to ad frames which have embeds likely impacting Core Web // Vitals. BASE_FEATURE(kAutomaticLazyFrameLoadingToAds, @@ -1941,7 +1929,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea // The timeout value that forces loading iframes that are lazy loaded by // LazyAds. After this timeout, the frame loading is triggered even when the -@@ -159,8 +159,8 @@ const base::FeatureParam kSkipFrameCountForLazyAds( +@@ -165,8 +165,8 @@ const base::FeatureParam kSkipFrameCountForLazyAds( // Apply lazy-loading to frames which have embeds likely impacting Core Web // Vitals. BASE_FEATURE(kAutomaticLazyFrameLoadingToEmbeds, @@ -1952,7 +1940,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea // The timeout value that forces loading iframes that are lazy loaded by // LazyEmbeds. After this timeout, the frame loading is triggered even when the -@@ -182,8 +182,8 @@ const base::FeatureParam kSkipFrameCountForLazyEmbeds( +@@ -188,8 +188,8 @@ const base::FeatureParam kSkipFrameCountForLazyEmbeds( // to gather Blink.AutomaticLazyLoadFrame.LazyEmbedFrameCount UKM data even when // kAutomaticLazyFrameLoadingToEmbeds is disabled. BASE_FEATURE(kAutomaticLazyFrameLoadingToEmbedUrls, diff --git a/build/patches/Client-hints-overrides.patch b/build/patches/Client-hints-overrides.patch index b01f7215..8b05d04e 100644 --- a/build/patches/Client-hints-overrides.patch +++ b/build/patches/Client-hints-overrides.patch @@ -49,7 +49,7 @@ diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/clie diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc -@@ -1061,6 +1061,11 @@ void NavigationURLLoaderImpl::OnAcceptCHFrameReceived( +@@ -1086,6 +1086,11 @@ void NavigationURLLoaderImpl::OnAcceptCHFrameReceived( return; } @@ -64,7 +64,7 @@ diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/brow diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -281,8 +281,8 @@ BASE_FEATURE(kCrashReporting, +@@ -284,8 +284,8 @@ BASE_FEATURE(kCrashReporting, // Enables support for the `Critical-CH` response header. // https://github.com/WICG/client-hints-infrastructure/blob/master/reliability.md#critical-ch BASE_FEATURE(kCriticalClientHint, @@ -73,12 +73,12 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c + "CriticalClientHint", // disabled by default + base::FEATURE_DISABLED_BY_DEFAULT); // in Bromite - // Enable debugging the issue crbug.com/1201355 - BASE_FEATURE(kDebugHistoryInterventionNoUserActivation, + // Enable changing source dynamically for desktop capture. + BASE_FEATURE(kDesktopCaptureChangeSource, diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc -@@ -110,6 +110,7 @@ void SetProxyInfoInReponse(const ProxyInfo& proxy_info, +@@ -99,6 +99,7 @@ const size_t kMaxRestarts = 32; // Returns true when Early Hints are allowed on the given protocol. bool EarlyHintsAreAllowedOn(HttpResponseInfo::ConnectionInfo connection_info) { @@ -89,7 +89,7 @@ diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transa diff --git a/services/network/public/cpp/client_hints.cc b/services/network/public/cpp/client_hints.cc --- a/services/network/public/cpp/client_hints.cc +++ b/services/network/public/cpp/client_hints.cc -@@ -113,6 +113,7 @@ const DecodeMap& GetDecodeMap() { +@@ -115,6 +115,7 @@ const DecodeMap& GetDecodeMap() { absl::optional> ParseClientHintsHeader(const std::string& header) { @@ -100,7 +100,7 @@ diff --git a/services/network/public/cpp/client_hints.cc b/services/network/publ diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc -@@ -193,7 +193,7 @@ BASE_FEATURE(kWebSocketReassembleShortMessages, +@@ -206,7 +206,7 @@ BASE_FEATURE(kWebSocketReassembleShortMessages, // Enable support for ACCEPT_CH H2/3 frame as part of Client Hint Reliability. // See: // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02#section-4.3 @@ -112,7 +112,7 @@ diff --git a/services/network/public/cpp/features.cc b/services/network/public/c diff --git a/third_party/blink/common/client_hints/client_hints.cc b/third_party/blink/common/client_hints/client_hints.cc --- a/third_party/blink/common/client_hints/client_hints.cc +++ b/third_party/blink/common/client_hints/client_hints.cc -@@ -101,6 +101,7 @@ const PolicyFeatureToClientHintMap& GetPolicyFeatureToClientHintMap() { +@@ -103,6 +103,7 @@ const PolicyFeatureToClientHintMap& GetPolicyFeatureToClientHintMap() { } bool IsClientHintSentByDefault(network::mojom::WebClientHintsType type) { @@ -131,7 +131,7 @@ diff --git a/third_party/blink/common/client_hints/enabled_client_hints.cc b/thi switch (type) { case WebClientHintsType::kUA: case WebClientHintsType::kUAArch: -@@ -90,7 +91,7 @@ bool IsDisabledByFeature(const WebClientHintsType type) { +@@ -96,7 +97,7 @@ bool IsDisabledByFeature(const WebClientHintsType type) { } // namespace bool EnabledClientHints::IsEnabled(const WebClientHintsType type) const { @@ -140,7 +140,7 @@ diff --git a/third_party/blink/common/client_hints/enabled_client_hints.cc b/thi } void EnabledClientHints::SetIsEnabled(const WebClientHintsType type, -@@ -101,6 +102,7 @@ void EnabledClientHints::SetIsEnabled(const WebClientHintsType type, +@@ -107,6 +108,7 @@ void EnabledClientHints::SetIsEnabled(const WebClientHintsType type, std::vector EnabledClientHints::GetEnabledHints() const { std::vector hints; @@ -151,7 +151,7 @@ diff --git a/third_party/blink/common/client_hints/enabled_client_hints.cc b/thi diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -3666,8 +3666,8 @@ +@@ -3694,8 +3694,8 @@ public: true, }, { diff --git a/build/patches/Content-settings-infrastructure.patch b/build/patches/Content-settings-infrastructure.patch index 2c0c06a3..c9c49f7a 100644 --- a/build/patches/Content-settings-infrastructure.patch +++ b/build/patches/Content-settings-infrastructure.patch @@ -96,7 +96,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/C /** * A SiteSettingsDelegate instance that contains Chrome-specific Site Settings logic. */ -@@ -266,6 +270,17 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate { +@@ -278,6 +282,17 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate { return PrivacySandboxBridge.getFirstPartySetOwner(memberOrigin); } @@ -129,7 +129,7 @@ diff --git a/chrome/browser/installable/installed_webapp_bridge.cc b/chrome/brow diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html -@@ -1136,4 +1136,5 @@ +@@ -1147,4 +1147,5 @@ @@ -263,7 +263,7 @@ diff --git a/chrome/browser/resources/settings/site_settings/site_details.ts b/c diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts -@@ -41,7 +41,7 @@ function getCategoryItemMap(): Map { +@@ -42,7 +42,7 @@ function getCategoryItemMap(): Map { } // The following list is ordered alphabetically by |id|. The order in which // these appear in the UI is determined elsewhere in this file. @@ -307,7 +307,7 @@ diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_ function buildItemListFromIds(orderedIdList: ContentSettingsTypes[]): CategoryListItem[] { const map = getCategoryItemMap(); -@@ -429,7 +453,7 @@ export class SettingsSiteSettingsPageElement extends +@@ -439,7 +463,7 @@ export class SettingsSiteSettingsPageElement extends Id.IMAGES, Id.POPUPS, ]), @@ -391,7 +391,7 @@ diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -1981,6 +1981,7 @@ static_library("ui") { +@@ -1927,6 +1927,7 @@ static_library("ui") { "//components/commerce/core:shopping_service", "//components/commerce/core/mojom:mojo_bindings", "//components/commerce/core/webui", @@ -411,8 +411,8 @@ diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.cc b/chrom #include "components/page_info/core/features.h" #include "components/page_info/core/proto/about_this_site_metadata.pb.h" #include "components/page_info/page_info.h" -@@ -487,6 +489,17 @@ const ui::ImageModel PageInfoViewFactory::GetPermissionIcon( - icon = &vector_icons::kCookieIcon; +@@ -498,6 +500,17 @@ const ui::ImageModel PageInfoViewFactory::GetPermissionIcon( + icon = &vector_icons::kStorageAccessIcon; break; default: + bool found = false; @@ -440,7 +440,7 @@ diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provide #include "build/branding_buildflags.h" #include "build/build_config.h" #include "build/buildflag.h" -@@ -73,6 +74,8 @@ +@@ -74,6 +75,8 @@ #include "components/google/core/common/google_util.h" #include "components/history/core/common/pref_names.h" #include "components/omnibox/common/omnibox_features.h" @@ -449,7 +449,7 @@ diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provide #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/manage_passwords_referrer.h" #include "components/password_manager/core/common/password_manager_features.h" -@@ -3635,6 +3638,42 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source, +@@ -3711,6 +3714,42 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source, policy_indicator::AddLocalizedStrings(html_source); AddSecurityKeysStrings(html_source); @@ -504,7 +504,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" -@@ -199,7 +201,7 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = { +@@ -203,7 +205,7 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = { static_assert(std::size(kContentSettingsTypeGroupNames) == // ContentSettingsType starts at -1, so add 1 here. @@ -513,7 +513,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b "kContentSettingsTypeGroupNames should have " "CONTENT_SETTINGS_NUM_TYPES elements"); -@@ -481,6 +483,13 @@ bool HasRegisteredGroupName(ContentSettingsType type) { +@@ -487,6 +489,13 @@ bool HasRegisteredGroupName(ContentSettingsType type) { return true; } } @@ -527,7 +527,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b return false; } -@@ -494,7 +503,13 @@ ContentSettingsType ContentSettingsTypeFromGroupName(base::StringPiece name) { +@@ -500,7 +509,13 @@ ContentSettingsType ContentSettingsTypeFromGroupName(base::StringPiece name) { return entry.type; } } @@ -542,7 +542,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b return ContentSettingsType::DEFAULT; } -@@ -514,6 +529,13 @@ base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { +@@ -520,6 +535,13 @@ base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { } } @@ -556,7 +556,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b NOTREACHED() << static_cast(type) << " is not a recognized content settings type."; return base::StringPiece(); -@@ -582,6 +604,13 @@ const std::vector& GetVisiblePermissionCategories() { +@@ -588,6 +610,13 @@ const std::vector& GetVisiblePermissionCategories() { base_types->push_back(ContentSettingsType::PRIVATE_NETWORK_GUARD); } @@ -573,7 +573,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn -@@ -143,6 +143,20 @@ android_library("java") { +@@ -145,6 +145,20 @@ android_library("java") { ":site_settings_jni_headers", "//components/content_settings/android:java_pref_names_srcjar", ] @@ -594,7 +594,7 @@ diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/b } android_library("javatests") { -@@ -186,6 +200,7 @@ robolectric_library("junit") { +@@ -190,6 +204,7 @@ robolectric_library("junit") { } android_resources("java_resources") { @@ -1269,7 +1269,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java -@@ -306,6 +306,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -310,6 +310,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment @ContentSettingValues Integer contentSetting = website.site().getContentSetting( browserContextHandle, mCategory.getContentSettingsType()); @@ -1280,7 +1280,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (contentSetting != null) { return ContentSettingValues.BLOCK == contentSetting; } -@@ -464,6 +468,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -469,6 +473,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment ? new HashSet<>(getArguments().getStringArrayList(EXTRA_SELECTED_DOMAINS)) : null; @@ -1288,7 +1288,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c configureGlobalToggles(); if (mCategory.getType() == SiteSettingsCategory.Type.REQUEST_DESKTOP_SITE) { RecordUserAction.record("DesktopSiteContentSetting.SettingsPage.Entered"); -@@ -488,7 +493,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -493,7 +498,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment if (queryHasChanged) getInfoForOrigins(); }); @@ -1297,7 +1297,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c MenuItem help = menu.add( Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help); help.setIcon(TraceEventVectorDrawableCompat.create( -@@ -499,6 +504,12 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -504,6 +509,12 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_id_site_settings_help) { @@ -1310,7 +1310,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (mCategory.getType() == SiteSettingsCategory.Type.PROTECTED_MEDIA) { getSiteSettingsDelegate().launchProtectedContentHelpAndFeedbackActivity( getActivity()); -@@ -572,6 +583,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -577,6 +588,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment BrowserContextHandle browserContextHandle = getSiteSettingsDelegate().getBrowserContextHandle(); PrefService prefService = UserPrefs.get(browserContextHandle); @@ -1322,7 +1322,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (BINARY_TOGGLE_KEY.equals(preference.getKey())) { assert !mCategory.isManaged(); boolean toggleValue = (boolean) newValue; -@@ -788,6 +804,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -796,6 +812,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment : R.string.website_settings_allowed_group_heading_request_desktop_site; break; } @@ -1331,7 +1331,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c assert resource > 0; return getString(resource); } -@@ -909,6 +927,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -914,6 +932,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment default: break; } @@ -1340,7 +1340,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (allowSpecifyingExceptions) { getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(), ADD_EXCEPTION_KEY, getAddExceptionDialogMessage(), mCategory, this)); -@@ -1082,6 +1102,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1087,6 +1107,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment case GlobalToggleLayout.TRI_STATE_TOGGLE: TriStateSiteSettingsPreference triStateToggle = getPreferenceScreen().findPreference(TRI_STATE_TOGGLE_KEY); @@ -1350,7 +1350,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK); case GlobalToggleLayout.FOUR_STATE_COOKIE_TOGGLE: FourStateCookieSettingsPreference fourStateCookieToggle = -@@ -1159,7 +1182,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1165,7 +1188,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment } else if (mCategory.getType() == SiteSettingsCategory.Type.THIRD_PARTY_COOKIES) { infoText.setSummary(R.string.website_settings_third_party_cookies_page_description); } else { @@ -1363,7 +1363,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } // Hide the anti-abuse text preferences, as needed. -@@ -1183,6 +1210,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1189,6 +1216,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment screen.removePreference(antiAbuseThingsToConsiderHeader); screen.removePreference(antiAbuseThingsToConsiderSectionOne); } @@ -1371,7 +1371,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (permissionBlockedByOs) { maybeShowOsWarning(screen); -@@ -1335,7 +1363,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1352,7 +1380,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment getSiteSettingsDelegate().getBrowserContextHandle(), contentType); int[] descriptionIds = ContentSettingsResources.getTriStateSettingDescriptionIDs(contentType); @@ -1380,7 +1380,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } private void configureBinaryToggle(ChromeSwitchPreference binaryToggle, int contentType) { -@@ -1439,6 +1467,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1478,6 +1506,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment @ContentSettingValues Integer value = site.getContentSetting(browserContextHandle, contentSettingsType); @@ -1398,7 +1398,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java -@@ -47,6 +47,7 @@ import org.chromium.content_public.browser.ContentFeatureMap; +@@ -45,6 +45,7 @@ import org.chromium.content_public.browser.BrowserContextHandle; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -1406,7 +1406,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c /** * Shows the permissions and other settings for a particular website. -@@ -172,7 +173,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -170,7 +171,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment case ContentSettingsType.CLIPBOARD_READ_WRITE: return "clipboard_permission_list"; default: @@ -1415,7 +1415,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } } -@@ -517,7 +518,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -520,7 +521,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment private void setupContentSettingsPreferences() { mMaxPermissionOrder = findPreference(PREF_PERMISSIONS_HEADER).getOrder(); @@ -1425,7 +1425,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c Preference preference = new ChromeSwitchPreference(getStyledContext()); preference.setKey(getPreferenceKey(type)); -@@ -962,14 +964,22 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -963,14 +965,22 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment private void setupContentSettingsPreference(Preference preference, @ContentSettingValues @Nullable Integer value, boolean isEmbargoed) { @@ -1451,7 +1451,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c switchPreference.setOnPreferenceChangeListener(this); @ContentSettingsType int contentType = getContentSettingsTypeFromPreferenceKey(preference.getKey()); -@@ -1135,7 +1145,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -1123,7 +1133,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment public @ContentSettingsType int getContentSettingsTypeFromPreferenceKey(String preferenceKey) { if (mPreferenceMap == null) { mPreferenceMap = new HashMap<>(); @@ -1460,7 +1460,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c String key = getPreferenceKey(type); if (key != null) { mPreferenceMap.put(key, type); -@@ -1177,7 +1187,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -1165,7 +1175,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment } mSite.setContentSetting(browserContextHandle, type, permission); @@ -1469,7 +1469,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c preference.setIcon(getContentSettingsIcon(type, permission)); if (mWebsiteSettingsObserver != null) { -@@ -1207,7 +1217,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -1195,7 +1205,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment // TODO(mvanouwerkerk): Refactor this class so that it does not depend on the screen state // for its logic. This class should maintain its own data model, and only update the screen // after a change is made. @@ -1507,10 +1507,10 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c Preference p = findPreference(prefCategory); int contentType = SiteSettingsCategory.contentSettingsType(prefCategory); // p can be null if the Preference was removed in configurePreferences. -@@ -130,10 +131,13 @@ public class SiteSettings extends SiteSettingsPreferenceFragment - p.setSummary(ContentSettingsResources.getDesktopSiteListSummary(checked)); - } else if (Type.AUTO_DARK_WEB_CONTENT == prefCategory) { - p.setSummary(ContentSettingsResources.getAutoDarkWebContentListSummary(checked)); +@@ -133,10 +134,13 @@ public class SiteSettings extends SiteSettingsPreferenceFragment + } else if (Type.ZOOM == prefCategory) { + // Don't want to set a summary for Zoom because we don't want any message to display + // under the Zoom row on site settings. - } else if (requiresTriStateSetting) { - p.setSummary(ContentSettingsResources.getCategorySummary(setting)); } else { @@ -1531,21 +1531,21 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY, Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE, Type.FEDERATED_IDENTITY_API, Type.THIRD_PARTY_COOKIES, Type.SITE_DATA, Type.ANTI_ABUSE, -- Type.NUM_ENTRIES}) -+ Type.NUM_ENTRIES_CHROMIUM}) +- Type.ZOOM, Type.NUM_ENTRIES}) ++ Type.ZOOM, Type.NUM_ENTRIES_CHROMIUM}) @Retention(RetentionPolicy.SOURCE) public @interface Type { // All updates here must also be reflected in {@link #preferenceKey(int) -@@ -84,7 +84,7 @@ public class SiteSettingsCategory { +@@ -85,7 +85,7 @@ public class SiteSettingsCategory { /** * Number of handled categories used for calculating array sizes. */ -- int NUM_ENTRIES = 29; -+ int NUM_ENTRIES_CHROMIUM = 29; +- int NUM_ENTRIES = 30; ++ int NUM_ENTRIES_CHROMIUM = 30; } private final BrowserContextHandle mBrowserContextHandle; -@@ -128,6 +128,9 @@ public class SiteSettingsCategory { +@@ -129,6 +129,9 @@ public class SiteSettingsCategory { } else { permission = ""; } @@ -1555,7 +1555,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c return new SiteSettingsCategory(browserContextHandle, type, permission); } -@@ -136,7 +139,7 @@ public class SiteSettingsCategory { +@@ -137,7 +140,7 @@ public class SiteSettingsCategory { @ContentSettingsType int contentSettingsType) { assert contentSettingsType != -1; assert Type.ALL_SITES == 0; @@ -1564,7 +1564,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (contentSettingsType(i) == contentSettingsType) { return createFromType(browserContextHandle, i); } -@@ -147,7 +150,7 @@ public class SiteSettingsCategory { +@@ -148,7 +151,7 @@ public class SiteSettingsCategory { public static SiteSettingsCategory createFromPreferenceKey( BrowserContextHandle browserContextHandle, String preferenceKey) { assert Type.ALL_SITES == 0; @@ -1573,8 +1573,8 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (preferenceKey(i).equals(preferenceKey)) { return createFromType(browserContextHandle, i); } -@@ -217,8 +220,7 @@ public class SiteSettingsCategory { - case Type.USE_STORAGE: +@@ -219,8 +222,7 @@ public class SiteSettingsCategory { + case Type.ZOOM: return ContentSettingsType.DEFAULT; // Conversion unavailable. } - assert false; @@ -1583,9 +1583,9 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } /** -@@ -301,8 +303,12 @@ public class SiteSettingsCategory { - case Type.THIRD_PARTY_COOKIES: - return "third_party_cookies"; +@@ -305,8 +307,12 @@ public class SiteSettingsCategory { + case Type.ZOOM: + return "zoom"; default: + { + String value = BromiteCustomContentSettingImpl.getPreferenceKey(type); @@ -1599,7 +1599,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java -@@ -163,6 +163,8 @@ public interface SiteSettingsDelegate { +@@ -173,6 +173,8 @@ public interface SiteSettingsDelegate { */ String getFirstPartySetOwner(String memberOrigin); @@ -1655,7 +1655,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java -@@ -244,6 +244,12 @@ public final class Website implements WebsiteEntry { +@@ -245,6 +245,12 @@ public final class Website implements WebsiteEntry { RecordUserAction.record("SoundContentSetting.UnmuteBy.SiteSettings"); } } @@ -1671,7 +1671,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java -@@ -94,7 +94,7 @@ public class WebsitePermissionsFetcher { +@@ -93,7 +93,7 @@ public class WebsitePermissionsFetcher { case ContentSettingsType.USB_GUARD: return WebsitePermissionsType.CHOSEN_OBJECT_INFO; default: @@ -1680,7 +1680,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } } -@@ -210,7 +210,7 @@ public class WebsitePermissionsFetcher { +@@ -209,7 +209,7 @@ public class WebsitePermissionsFetcher { if (SiteSettingsFeatureList.isEnabled(SiteSettingsFeatureList.SITE_DATA_IMPROVEMENTS)) { queue.add(new CookiesInfoFetcher()); } @@ -1692,7 +1692,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java -@@ -246,7 +246,7 @@ public class WebsitePreferenceBridge { +@@ -265,7 +265,7 @@ public class WebsitePreferenceBridge { case ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER: return true; default: @@ -1701,7 +1701,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } } -@@ -261,7 +261,6 @@ public class WebsitePreferenceBridge { +@@ -280,7 +280,6 @@ public class WebsitePreferenceBridge { public static boolean isCategoryEnabled(BrowserContextHandle browserContextHandle, @ContentSettingsType int contentSettingsType) { @@ -1788,7 +1788,7 @@ diff --git a/components/content_settings/android/BUILD.gn b/components/content_s diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn -@@ -83,6 +83,13 @@ static_library("browser") { +@@ -85,6 +85,13 @@ static_library("browser") { } configs += [ "//build/config/compiler:wexit_time_destructors" ] @@ -1819,7 +1819,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. namespace content_settings { -@@ -598,6 +599,8 @@ void ContentSettingsRegistry::Init() { +@@ -609,6 +610,8 @@ void ContentSettingsRegistry::Init() { WebsiteSettingsRegistry::ALL_PLATFORMS, ContentSettingsInfo::INHERIT_IN_INCOGNITO, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS); @@ -1831,7 +1831,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. diff --git a/components/content_settings/core/browser/content_settings_uma_util.cc b/components/content_settings/core/browser/content_settings_uma_util.cc --- a/components/content_settings/core/browser/content_settings_uma_util.cc +++ b/components/content_settings/core/browser/content_settings_uma_util.cc -@@ -171,8 +171,9 @@ void RecordContentSettingsHistogram(const std::string& name, +@@ -173,8 +173,9 @@ void RecordContentSettingsHistogram(const std::string& name, } int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting) { @@ -1869,12 +1869,12 @@ diff --git a/components/content_settings/core/browser/content_settings_utils.cc + } + } #if !BUILDFLAG(IS_ANDROID) - map->GetSettingsForOneType(ContentSettingsType::IMAGES, - &(rules->image_rules)); + rules->image_rules = map->GetSettingsForOneType(ContentSettingsType::IMAGES); + rules->mixed_content_rules = diff --git a/components/content_settings/core/browser/website_settings_info.h b/components/content_settings/core/browser/website_settings_info.h --- a/components/content_settings/core/browser/website_settings_info.h +++ b/components/content_settings/core/browser/website_settings_info.h -@@ -120,6 +120,30 @@ class WebsiteSettingsInfo { +@@ -125,6 +125,30 @@ class WebsiteSettingsInfo { ScopingType scoping_type() const { return scoping_type_; } IncognitoBehavior incognito_behavior() const { return incognito_behavior_; } @@ -1905,7 +1905,7 @@ diff --git a/components/content_settings/core/browser/website_settings_info.h b/ private: const ContentSettingsType type_; const std::string name_; -@@ -131,6 +155,17 @@ class WebsiteSettingsInfo { +@@ -136,6 +160,17 @@ class WebsiteSettingsInfo { const LossyStatus lossy_status_; const ScopingType scoping_type_; const IncognitoBehavior incognito_behavior_; @@ -1953,7 +1953,7 @@ diff --git a/components/content_settings/core/browser/website_settings_registry. diff --git a/components/content_settings/core/common/BUILD.gn b/components/content_settings/core/common/BUILD.gn --- a/components/content_settings/core/common/BUILD.gn +++ b/components/content_settings/core/common/BUILD.gn -@@ -51,6 +51,13 @@ static_library("common") { +@@ -52,6 +52,13 @@ static_library("common") { if (use_blink) { deps += [ "//components/privacy_sandbox:features" ] } @@ -2046,7 +2046,7 @@ diff --git a/components/content_settings/core/common/content_settings.h b/compon diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom --- a/components/content_settings/core/common/content_settings.mojom +++ b/components/content_settings/core/common/content_settings.mojom -@@ -78,6 +78,11 @@ struct RuleMetaData { +@@ -79,6 +79,11 @@ struct RuleMetaData { mojo_base.mojom.TimeDelta lifetime; }; @@ -2058,7 +2058,7 @@ diff --git a/components/content_settings/core/common/content_settings.mojom b/co // This mirrors the C++ type in content_settings.h. struct ContentSettingPatternSource { ContentSettingsPattern primary_pattern; -@@ -90,6 +95,7 @@ struct ContentSettingPatternSource { +@@ -91,6 +96,7 @@ struct ContentSettingPatternSource { // This mirrors the C++ type in content_settings.h. struct RendererContentSettingRules { @@ -2069,7 +2069,7 @@ diff --git a/components/content_settings/core/common/content_settings.mojom b/co diff --git a/components/content_settings/core/common/content_settings_mojom_traits.cc b/components/content_settings/core/common/content_settings_mojom_traits.cc --- a/components/content_settings/core/common/content_settings_mojom_traits.cc +++ b/components/content_settings/core/common/content_settings_mojom_traits.cc -@@ -153,12 +153,22 @@ bool StructTraitsmetadata) && data.ReadSource(&out->source); } @@ -2096,7 +2096,7 @@ diff --git a/components/content_settings/core/common/content_settings_mojom_trai diff --git a/components/content_settings/core/common/content_settings_mojom_traits.h b/components/content_settings/core/common/content_settings_mojom_traits.h --- a/components/content_settings/core/common/content_settings_mojom_traits.h +++ b/components/content_settings/core/common/content_settings_mojom_traits.h -@@ -165,10 +165,34 @@ struct StructTraits< +@@ -169,10 +169,34 @@ struct StructTraits< ContentSettingPatternSource* out); }; @@ -2146,9 +2146,9 @@ diff --git a/components/content_settings/core/common/content_settings_param_trai diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h --- a/components/content_settings/core/common/content_settings_types.h +++ b/components/content_settings/core/common/content_settings_types.h -@@ -331,7 +331,9 @@ enum class ContentSettingsType : int32_t { - // https://github.com/screen-share/capture-all-screens - ALL_SCREEN_CAPTURE, +@@ -343,7 +343,9 @@ enum class ContentSettingsType : int32_t { + // Setting for supporting 3PCD. + TPCD_SUPPORT, - NUM_TYPES, + NUM_TYPES_CHROMIUM, @@ -2256,7 +2256,7 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/page_info/android/jni_headers/PageInfoController_jni.h" -@@ -151,6 +152,15 @@ void PageInfoControllerAndroid::SetPermissionInfo( +@@ -146,6 +147,15 @@ void PageInfoControllerAndroid::SetPermissionInfo( ContentSettingsType::FEDERATED_IDENTITY_API); } @@ -2272,7 +2272,7 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp std::map user_specified_settings_to_display; std::map -@@ -210,6 +220,14 @@ absl::optional PageInfoControllerAndroid::GetSettingToDisplay( +@@ -205,6 +215,14 @@ absl::optional PageInfoControllerAndroid::GetSettingToDisplay( return permission.setting; } @@ -2290,15 +2290,15 @@ diff --git a/components/page_info/android/page_info_controller_android.cc b/comp diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc -@@ -27,6 +27,7 @@ +@@ -24,6 +24,7 @@ #include "components/browsing_data/content/browsing_data_helper.h" - #include "components/browsing_data/content/local_storage_helper.h" + #include "components/browsing_data/core/features.h" #include "components/content_settings/browser/page_specific_content_settings.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "components/content_settings/browser/ui/cookie_controls_controller.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_uma_util.h" -@@ -1193,6 +1194,14 @@ void PageInfo::PopulatePermissionInfo(PermissionInfo& permission_info, +@@ -1232,6 +1233,14 @@ void PageInfo::PopulatePermissionInfo(PermissionInfo& permission_info, // applies to permissions listed in |kPermissionType|. bool PageInfo::ShouldShowPermission( const PageInfo::PermissionInfo& info) const { @@ -2313,7 +2313,7 @@ diff --git a/components/page_info/page_info.cc b/components/page_info/page_info. // Note |ContentSettingsType::ADS| will show up regardless of its default // value when it has been activated on the current origin. if (info.type == ContentSettingsType::ADS) { -@@ -1281,7 +1290,19 @@ void PageInfo::PresentSitePermissions() { +@@ -1320,7 +1329,19 @@ void PageInfo::PresentSitePermissions() { HostContentSettingsMap* content_settings = GetContentSettings(); DCHECK(web_contents_); @@ -2342,10 +2342,10 @@ diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_in #include "build/chromeos_buildflags.h" #include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/browser/website_settings_registry.h" - #include "components/omnibox/common/omnibox_features.h" #include "components/page_info/core/features.h" #include "components/page_info/page_info.h" -@@ -576,6 +577,12 @@ PageInfoUI::~PageInfoUI() = default; + #include "components/page_info/page_info_ui_delegate.h" +@@ -571,6 +572,12 @@ PageInfoUI::~PageInfoUI() = default; // static std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { @@ -2358,7 +2358,7 @@ diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_in for (const PermissionUIInfo& info : GetContentSettingsUIInfo()) { if (info.type == type) return l10n_util::GetStringUTF16(info.string_id); -@@ -587,6 +594,12 @@ std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { +@@ -582,6 +589,12 @@ std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { // static std::u16string PageInfoUI::PermissionTypeToUIStringMidSentence( ContentSettingsType type) { @@ -2371,7 +2371,7 @@ diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_in for (const PermissionUIInfo& info : GetContentSettingsUIInfo()) { if (info.type == type) return l10n_util::GetStringUTF16(info.string_id_mid_sentence); -@@ -977,6 +990,11 @@ bool PageInfoUI::ContentSettingsTypeInPageInfo(ContentSettingsType type) { +@@ -990,6 +1003,11 @@ bool PageInfoUI::ContentSettingsTypeInPageInfo(ContentSettingsType type) { if (info.type == type) return true; } @@ -2466,7 +2466,7 @@ diff --git a/third_party/blink/renderer/core/execution_context/execution_context diff --git a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java --- a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java -@@ -155,6 +155,9 @@ public class WebLayerSiteSettingsDelegate +@@ -163,6 +163,9 @@ public class WebLayerSiteSettingsDelegate @Override public void dismissPrivacySandboxSnackbar() {} diff --git a/build/patches/Dictionary-suggestions-for-the-Omnibox.patch b/build/patches/Dictionary-suggestions-for-the-Omnibox.patch index c75e2ab3..07b7e742 100644 --- a/build/patches/Dictionary-suggestions-for-the-Omnibox.patch +++ b/build/patches/Dictionary-suggestions-for-the-Omnibox.patch @@ -964,7 +964,7 @@ new file mode 100644 diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java -@@ -227,8 +227,7 @@ public abstract class UrlBar extends AutocompleteEditText { +@@ -228,8 +228,7 @@ public abstract class UrlBar extends AutocompleteEditText { setFocusableInTouchMode(mAllowFocus); }); diff --git a/build/patches/Disable-Accessibility-service-by-default.patch b/build/patches/Disable-Accessibility-service-by-default.patch index 92837216..51ced81b 100644 --- a/build/patches/Disable-Accessibility-service-by-default.patch +++ b/build/patches/Disable-Accessibility-service-by-default.patch @@ -14,7 +14,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1736,6 +1736,12 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1763,6 +1763,12 @@ Your Google account may have other forms of browsing history like searches and a Check now @@ -58,7 +58,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java -@@ -909,6 +909,11 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProviderCompa +@@ -996,6 +996,11 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProviderCompa structure.setChildCount(0); return; } diff --git a/build/patches/Disable-AsyncDNS-by-default.patch b/build/patches/Disable-AsyncDNS-by-default.patch index edb53d18..58dedfa6 100644 --- a/build/patches/Disable-AsyncDNS-by-default.patch +++ b/build/patches/Disable-AsyncDNS-by-default.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -66,13 +66,8 @@ BASE_FEATURE(kAppShimNewCloseBehavior, +@@ -67,13 +67,8 @@ BASE_FEATURE(kAppShimNewCloseBehavior, // Enables the built-in DNS resolver. BASE_FEATURE(kAsyncDns, diff --git a/build/patches/Disable-DRM-media-origin-IDs-preprovisioning.patch b/build/patches/Disable-DRM-media-origin-IDs-preprovisioning.patch index 07c488e4..e2bb4756 100644 --- a/build/patches/Disable-DRM-media-origin-IDs-preprovisioning.patch +++ b/build/patches/Disable-DRM-media-origin-IDs-preprovisioning.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc -@@ -1041,8 +1041,8 @@ BASE_FEATURE(kMediaDrmPersistentLicense, +@@ -1056,8 +1056,8 @@ BASE_FEATURE(kMediaDrmPersistentLicense, // MediaDrmBridge. If disabled, MediaDrmBridge will get unprovisioned origin IDs // which will trigger provisioning process after MediaDrmBridge is created. BASE_FEATURE(kMediaDrmPreprovisioning, diff --git a/build/patches/Disable-FLoC-and-privacy-sandbox.patch b/build/patches/Disable-FLoC-and-privacy-sandbox.patch index 104d853d..fb127fc6 100644 --- a/build/patches/Disable-FLoC-and-privacy-sandbox.patch +++ b/build/patches/Disable-FLoC-and-privacy-sandbox.patch @@ -22,7 +22,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -3395,6 +3395,9 @@ bool ChromeContentBrowserClient::IsAttributionReportingOperationAllowed( +@@ -3424,6 +3424,9 @@ bool ChromeContentBrowserClient::IsAttributionReportingOperationAllowed( const url::Origin* source_origin, const url::Origin* destination_origin, const url::Origin* reporting_origin) { @@ -114,7 +114,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_features.cc b/components diff --git a/components/privacy_sandbox/privacy_sandbox_prefs.cc b/components/privacy_sandbox/privacy_sandbox_prefs.cc --- a/components/privacy_sandbox/privacy_sandbox_prefs.cc +++ b/components/privacy_sandbox/privacy_sandbox_prefs.cc -@@ -108,7 +108,7 @@ namespace privacy_sandbox { +@@ -11,7 +11,7 @@ namespace privacy_sandbox { void RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref( @@ -126,7 +126,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_prefs.cc b/components/pr diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc --- a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc +++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc -@@ -170,7 +170,8 @@ PrivacySandboxSettingsImpl::GetFinchDisabledTopics() { +@@ -204,7 +204,8 @@ PrivacySandboxSettingsImpl::GetFinchDisabledTopics() { return finch_disabled_topics_; } @@ -136,7 +136,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo // M1 specific if (base::FeatureList::IsEnabled(privacy_sandbox::kPrivacySandboxSettings4)) { Status status = GetM1TopicAllowedStatus(); -@@ -221,7 +222,8 @@ bool PrivacySandboxSettingsImpl::IsTopicsAllowedForContext( +@@ -261,7 +262,8 @@ bool PrivacySandboxSettingsImpl::IsTopicsAllowedForContext( IsPrivacySandboxEnabledForContext(top_frame_origin, url); } @@ -146,7 +146,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo const auto& blocked_topics = pref_service_->GetList(prefs::kPrivacySandboxBlockedTopics); -@@ -463,7 +465,8 @@ void PrivacySandboxSettingsImpl::ClearFledgeJoiningAllowedSettings( +@@ -517,7 +519,8 @@ void PrivacySandboxSettingsImpl::ClearFledgeJoiningAllowedSettings( } bool PrivacySandboxSettingsImpl::IsFledgeJoiningAllowed( @@ -156,7 +156,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo ScopedDictPrefUpdate scoped_pref_update( pref_service_, prefs::kPrivacySandboxFledgeJoinBlocked); auto& pref_data = scoped_pref_update.Get(); -@@ -595,7 +598,8 @@ bool PrivacySandboxSettingsImpl::IsPrivateAggregationAllowed( +@@ -672,7 +675,8 @@ bool PrivacySandboxSettingsImpl::IsPrivateAggregationAllowed( reporting_origin.GetURL()); } @@ -166,7 +166,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo PrivacySandboxSettingsImpl::Status status = GetPrivacySandboxAllowedStatus(); if (!IsAllowed(status)) { return false; -@@ -633,7 +637,8 @@ void PrivacySandboxSettingsImpl::SetTopicsBlockedForTesting() { +@@ -710,7 +714,8 @@ void PrivacySandboxSettingsImpl::SetTopicsBlockedForTesting() { pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, false); } @@ -176,7 +176,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, enabled); } -@@ -695,7 +700,10 @@ bool PrivacySandboxSettingsImpl::IsPrivacySandboxEnabledForContext( +@@ -772,7 +777,10 @@ bool PrivacySandboxSettingsImpl::IsPrivacySandboxEnabledForContext( net::CookieSettingOverrides()); } @@ -188,7 +188,7 @@ diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/compo pref_service_->SetTime(prefs::kPrivacySandboxTopicsDataAccessibleSince, base::Time::Now()); -@@ -708,6 +716,7 @@ PrivacySandboxSettingsImpl::Status +@@ -785,6 +793,7 @@ PrivacySandboxSettingsImpl::Status PrivacySandboxSettingsImpl::GetSiteAccessAllowedStatus( const url::Origin& top_frame_origin, const GURL& url) const { diff --git a/build/patches/Disable-PrivacyGuide.patch b/build/patches/Disable-PrivacyGuide.patch index d7f54bfa..0862813e 100644 --- a/build/patches/Disable-PrivacyGuide.patch +++ b/build/patches/Disable-PrivacyGuide.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -479,8 +479,8 @@ BASE_FEATURE(kHaTSDesktopDevToolsIssuesCSP, +@@ -480,8 +480,8 @@ BASE_FEATURE(kPrivacyGuide3, // Enables or disables the Happiness Tracking System for Desktop Privacy Guide. BASE_FEATURE(kHappinessTrackingSurveysForDesktopPrivacyGuide, @@ -21,8 +21,8 @@ diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc const base::FeatureParam kHappinessTrackingSurveysForDesktopPrivacyGuideTime{ &kHappinessTrackingSurveysForDesktopPrivacyGuide, "settings-time", -@@ -949,8 +949,8 @@ BASE_FEATURE(kPrerenderFallbackToPreconnect, - base::FEATURE_DISABLED_BY_DEFAULT); +@@ -992,8 +992,8 @@ BASE_FEATURE(kPrintPreviewSetupAssistance, + #endif BASE_FEATURE(kPrivacyGuideAndroid, - "PrivacyGuideAndroid", diff --git a/build/patches/Disable-StartSurface-feature.patch b/build/patches/Disable-StartSurface-feature.patch index 7b9f7ed0..43df0c70 100644 --- a/build/patches/Disable-StartSurface-feature.patch +++ b/build/patches/Disable-StartSurface-feature.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -1109,8 +1109,8 @@ BASE_FEATURE(kResizeOnlyActiveTab, +@@ -1127,8 +1127,8 @@ BASE_FEATURE(kResizeOnlyActiveTab, BASE_FEATURE(kSpareTab, "SpareTab", base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kStartSurfaceAndroid, @@ -27,7 +27,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -584,7 +584,7 @@ public abstract class ChromeFeatureList { +@@ -591,7 +591,7 @@ public abstract class ChromeFeatureList { new CachedFlag(SHOULD_IGNORE_INTENT_SKIP_INTERNAL_CHECK, true); public static final CachedFlag sSpareTab = new CachedFlag(SPARE_TAB, false); public static final CachedFlag sStartSurfaceAndroid = new CachedFlag( diff --git a/build/patches/Disable-TLS-resumption.patch b/build/patches/Disable-TLS-resumption.patch index dadf04cf..617dd994 100644 --- a/build/patches/Disable-TLS-resumption.patch +++ b/build/patches/Disable-TLS-resumption.patch @@ -39,7 +39,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5280,6 +5280,12 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5342,6 +5342,12 @@ const FeatureEntry kFeatureEntries[] = { {"enable-tls13-kyber", flag_descriptions::kEnableTLS13KyberName, flag_descriptions::kEnableTLS13KyberDescription, kOsAll, FEATURE_VALUE_TYPE(net::features::kPostQuantumKyber)}, @@ -50,12 +50,12 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc + flag_descriptions::kLogTLSResumptionDescription, kOsAll, + FEATURE_VALUE_TYPE(net::features::kLogTLSResumption)}, #if BUILDFLAG(IS_ANDROID) - {"feed-bottom-sync-banner", flag_descriptions::kFeedBottomSyncBannerName, - flag_descriptions::kFeedBottomSyncBannerDescription, kOsAndroid, + {"feed-boc-signin-interstitial", + flag_descriptions::kFeedBoCSigninInterstitialName, diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1077,6 +1077,14 @@ const char kAccessibilityAcceleratorNotificationsTimeoutDescription[] = +@@ -1111,6 +1111,14 @@ const char kAccessibilityAcceleratorNotificationsTimeoutDescription[] = "shortcut (docked magnifier, screen magnifier and high contrast) to time " "out instead of remaining pinned."; @@ -73,7 +73,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -615,6 +615,12 @@ extern const char kEnablePreinstalledWebAppDuplicationFixerDescription[]; +@@ -636,6 +636,12 @@ extern const char kDevicePostureDescription[]; extern const char kEnableTLS13EarlyDataName[]; extern const char kEnableTLS13EarlyDataDescription[]; @@ -89,7 +89,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -66,6 +66,14 @@ const base::FeatureParam kUseDnsHttpsSvcbSecureExtraTimeMin{ +@@ -67,6 +67,14 @@ const base::FeatureParam kUseDnsHttpsSvcbSecureExtraTimeMin{ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbSecureExtraTimeMin", base::Milliseconds(5)}; @@ -107,7 +107,7 @@ diff --git a/net/base/features.cc b/net/base/features.cc diff --git a/net/base/features.h b/net/base/features.h --- a/net/base/features.h +++ b/net/base/features.h -@@ -99,6 +99,12 @@ NET_EXPORT BASE_DECLARE_FEATURE(kSHA1ServerSignature); +@@ -107,6 +107,12 @@ NET_EXPORT BASE_DECLARE_FEATURE(kSHA1ServerSignature); // Enables TLS 1.3 early data. NET_EXPORT BASE_DECLARE_FEATURE(kEnableTLS13EarlyData); @@ -123,7 +123,7 @@ diff --git a/net/base/features.h b/net/base/features.h diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc -@@ -213,6 +213,7 @@ HttpNetworkSession::HttpNetworkSession(const HttpNetworkSessionParams& params, +@@ -208,6 +208,7 @@ HttpNetworkSession::HttpNetworkSession(const HttpNetworkSessionParams& params, next_protos_.push_back(kProtoHTTP11); @@ -134,7 +134,7 @@ diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc -@@ -71,6 +71,7 @@ +@@ -70,6 +70,7 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" #include "third_party/boringssl/src/include/openssl/aead.h" @@ -142,7 +142,7 @@ diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc #include "url/gurl.h" #include "url/scheme_host_port.h" #include "url/url_constants.h" -@@ -197,6 +198,38 @@ std::set HostsFromOrigins(std::set origins) { +@@ -196,6 +197,38 @@ std::set HostsFromOrigins(std::set origins) { } // namespace @@ -181,7 +181,7 @@ diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc // Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many // consumers are using it currently. When the last reference is freed, the // QuicCryptoClientConfigHandle informs the owning QuicStreamFactory, moves it -@@ -2365,7 +2398,7 @@ QuicStreamFactory::CreateCryptoConfigHandle( +@@ -2355,7 +2388,7 @@ QuicStreamFactory::CreateCryptoConfigHandle( sct_auditing_delegate_, HostsFromOrigins(params_.origins_to_force_quic_on), actual_network_anonymization_key), @@ -189,7 +189,7 @@ diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc + std::make_unique(), this); quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config(); - crypto_config->set_user_agent_id(params_.user_agent_id); + crypto_config->AddCanonicalSuffix(".c.youtube.com"); diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc @@ -272,7 +272,7 @@ diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket UMA_HISTOGRAM_ENUMERATION("Net.SSLHandshakeDetails", details); // Measure TLS connections that implement the renegotiation_info extension. -@@ -1746,6 +1803,8 @@ bool SSLClientSocketImpl::IsRenegotiationAllowed() const { +@@ -1734,6 +1791,8 @@ bool SSLClientSocketImpl::IsRenegotiationAllowed() const { } bool SSLClientSocketImpl::IsCachingEnabled() const { diff --git a/build/patches/Disable-UA-full-version.patch b/build/patches/Disable-UA-full-version.patch index 6cb0500c..934d64ca 100644 --- a/build/patches/Disable-UA-full-version.patch +++ b/build/patches/Disable-UA-full-version.patch @@ -13,16 +13,16 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/third_party/blink/renderer/core/frame/navigator_ua_data.cc b/third_party/blink/renderer/core/frame/navigator_ua_data.cc --- a/third_party/blink/renderer/core/frame/navigator_ua_data.cc +++ b/third_party/blink/renderer/core/frame/navigator_ua_data.cc -@@ -6,6 +6,8 @@ - +@@ -7,6 +7,8 @@ #include "base/compiler_specific.h" #include "base/task/single_thread_task_runner.h" + #include "third_party/blink/public/common/features.h" +#include "base/version.h" +#include "base/strings/strcat.h" #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" -@@ -39,6 +41,16 @@ void MaybeRecordMetric(bool record_identifiability, +@@ -40,6 +42,16 @@ void MaybeRecordMetric(bool record_identifiability, .Record(execution_context->UkmRecorder()); } @@ -39,7 +39,7 @@ diff --git a/third_party/blink/renderer/core/frame/navigator_ua_data.cc b/third_ } // namespace NavigatorUAData::NavigatorUAData(ExecutionContext* context) -@@ -77,7 +89,7 @@ void NavigatorUAData::SetFullVersionList( +@@ -78,7 +90,7 @@ void NavigatorUAData::SetFullVersionList( const UserAgentBrandList& full_version_list) { for (const auto& brand_version : full_version_list) { AddBrandFullVersion(String::FromUTF8(brand_version.brand), @@ -48,7 +48,7 @@ diff --git a/third_party/blink/renderer/core/frame/navigator_ua_data.cc b/third_ } } -@@ -99,7 +111,7 @@ void NavigatorUAData::SetModel(const String& model) { +@@ -100,7 +112,7 @@ void NavigatorUAData::SetModel(const String& model) { } void NavigatorUAData::SetUAFullVersion(const String& ua_full_version) { diff --git a/build/patches/Disable-all-predictors-code.patch b/build/patches/Disable-all-predictors-code.patch index 32f38607..85385f9d 100644 --- a/build/patches/Disable-all-predictors-code.patch +++ b/build/patches/Disable-all-predictors-code.patch @@ -9,7 +9,9 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../ranking/history_clusters_module_ranker.cc | 3 +- .../chrome_hints_manager.cc | 1 + .../optimization_guide_keyed_service.cc | 1 - + .../browser/predictors/loading_predictor.cc | 4 +- .../predictors/loading_predictor_config.cc | 4 +- + .../browser/predictors/predictors_features.cc | 14 ++---- chrome/common/chrome_features.cc | 10 ++-- .../optimization_guide/core/hints_fetcher.cc | 1 + .../optimization_guide/core/hints_manager.cc | 5 ++ @@ -20,12 +22,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/permissions/features.cc | 8 ++-- third_party/blink/common/features.cc | 8 +--- .../platform/runtime_enabled_features.json5 | 2 +- - 15 files changed, 56 insertions(+), 55 deletions(-) + 17 files changed, 61 insertions(+), 68 deletions(-) diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc -@@ -233,17 +233,17 @@ BASE_FEATURE(kIncomingCallNotifications, +@@ -239,13 +239,13 @@ BASE_FEATURE(kIncomingCallNotifications, // Enables omnibox trigger prerendering. BASE_FEATURE(kOmniboxTriggerForPrerender2, @@ -41,6 +43,11 @@ diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_feature + "BookmarkTriggerForPrerender2", // always disabled + base::FEATURE_DISABLED_BY_DEFAULT); // in bromite + // Enables New Tab Page trigger prerendering. + BASE_FEATURE(kNewTabPageTriggerForPrerender2, +@@ -253,8 +253,8 @@ BASE_FEATURE(kNewTabPageTriggerForPrerender2, + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kSupportSearchSuggestionForPrerender2, - "SupportSearchSuggestionForPrerender2", - base::FEATURE_DISABLED_BY_DEFAULT); @@ -78,7 +85,7 @@ diff --git a/chrome/browser/optimization_guide/chrome_hints_manager.cc b/chrome/ diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc -@@ -332,7 +332,6 @@ void OptimizationGuideKeyedService::RemoveObserverForOptimizationTargetModel( +@@ -331,7 +331,6 @@ void OptimizationGuideKeyedService::RemoveObserverForOptimizationTargetModel( void OptimizationGuideKeyedService::RegisterOptimizationTypes( const std::vector& optimization_types) { @@ -86,24 +93,84 @@ diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service. } optimization_guide::OptimizationGuideDecision +diff --git a/chrome/browser/predictors/loading_predictor.cc b/chrome/browser/predictors/loading_predictor.cc +--- a/chrome/browser/predictors/loading_predictor.cc ++++ b/chrome/browser/predictors/loading_predictor.cc +@@ -184,7 +184,7 @@ ResourcePrefetchPredictor* LoadingPredictor::resource_prefetch_predictor() { + } + + PreconnectManager* LoadingPredictor::preconnect_manager() { +- if (shutdown_) { ++ if ((true)) { + return nullptr; + } + +@@ -200,7 +200,7 @@ PrefetchManager* LoadingPredictor::prefetch_manager() { + if (!base::FeatureList::IsEnabled(features::kLoadingPredictorPrefetch)) + return nullptr; + +- if (shutdown_) { ++ if ((true)) { + return nullptr; + } + diff --git a/chrome/browser/predictors/loading_predictor_config.cc b/chrome/browser/predictors/loading_predictor_config.cc --- a/chrome/browser/predictors/loading_predictor_config.cc +++ b/chrome/browser/predictors/loading_predictor_config.cc -@@ -12,8 +12,8 @@ +@@ -13,8 +13,8 @@ namespace predictors { - BASE_FEATURE(kSpeculativePreconnectFeature, -- "SpeculativePreconnect", -- base::FEATURE_ENABLED_BY_DEFAULT); -+ "SpeculativePreconnect", // always disabled -+ base::FEATURE_DISABLED_BY_DEFAULT); // in bromite + bool IsLoadingPredictorEnabled(Profile* profile) { +- // Disabled for off-the-record. Policy choice, not a technical limitation. +- return profile && !profile->IsOffTheRecord(); ++ // Disabled for all profiles ++ return false; + } - // Returns whether the speculative preconnect feature is enabled. - bool IsPreconnectFeatureEnabled() { + bool IsPreconnectAllowed(Profile* profile) { +diff --git a/chrome/browser/predictors/predictors_features.cc b/chrome/browser/predictors/predictors_features.cc +--- a/chrome/browser/predictors/predictors_features.cc ++++ b/chrome/browser/predictors/predictors_features.cc +@@ -11,8 +11,8 @@ namespace features { + + // Whether local predictions should be used to make preconnect predictions. + BASE_FEATURE(kLoadingPredictorUseLocalPredictions, +- "LoadingPredictorUseLocalPredictions", +- base::FEATURE_ENABLED_BY_DEFAULT); ++ "LoadingPredictorUseLocalPredictions", // disabled by ++ base::FEATURE_DISABLED_BY_DEFAULT); // default + + // Modifies loading predictor so that it only learns about subresources and + // origins that are high priority. +@@ -39,11 +39,7 @@ BASE_FEATURE(kLoadingPredictorDisregardAlwaysAccessesNetwork, + + const base::FeatureState + kLoadingPredictorUseOptimizationGuideDefaultFeatureState = +-#if BUILDFLAG(IS_ANDROID) +- base::FEATURE_ENABLED_BY_DEFAULT; +-#else +- base::FEATURE_DISABLED_BY_DEFAULT; +-#endif ++ base::FEATURE_DISABLED_BY_DEFAULT; + + // Modifies loading predictor so that it can also use predictions coming from + // the optimization guide. +@@ -52,11 +48,7 @@ BASE_FEATURE(kLoadingPredictorUseOptimizationGuide, + kLoadingPredictorUseOptimizationGuideDefaultFeatureState); + + const base::FeatureState kLoadingPredictorPrefetchDefaultFeatureState = +-#if BUILDFLAG(IS_ANDROID) +- base::FEATURE_ENABLED_BY_DEFAULT; +-#else + base::FEATURE_DISABLED_BY_DEFAULT; +-#endif + + // Modifies loading predictor so that it does prefetches of subresources instead + // of preconnects. diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -922,8 +922,8 @@ BASE_FEATURE(kPermissionAuditing, +@@ -958,8 +958,8 @@ BASE_FEATURE(kPermissionAuditing, // Enables using the prediction service for permission prompts. We will keep // this feature in order to allow us to update the holdback chance via finch. BASE_FEATURE(kPermissionPredictions, @@ -114,7 +181,7 @@ diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc // The holdback chance is 30% but it can also be configured/updated // through finch if needed. -@@ -934,8 +934,8 @@ const base::FeatureParam kPermissionPredictionsHoldbackChance( +@@ -970,8 +970,8 @@ const base::FeatureParam kPermissionPredictionsHoldbackChance( // Enables using the prediction service for geolocation permission prompts. BASE_FEATURE(kPermissionGeolocationPredictions, @@ -125,20 +192,20 @@ diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc const base::FeatureParam kPermissionGeolocationPredictionsHoldbackChance( -@@ -951,7 +951,7 @@ BASE_FEATURE(kPluginVm, "PluginVm", base::FEATURE_DISABLED_BY_DEFAULT); +@@ -987,7 +987,7 @@ BASE_FEATURE(kPluginVm, "PluginVm", base::FEATURE_DISABLED_BY_DEFAULT); // Allows Chrome to do preconnect when prerender fails. BASE_FEATURE(kPrerenderFallbackToPreconnect, "PrerenderFallbackToPreconnect", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kPrivacyGuideAndroid, - "PrivacyGuideAndroid", + #if BUILDFLAG(IS_CHROMEOS) + // Enable improved printer state and error state messaging for Print Preview. diff --git a/components/optimization_guide/core/hints_fetcher.cc b/components/optimization_guide/core/hints_fetcher.cc --- a/components/optimization_guide/core/hints_fetcher.cc +++ b/components/optimization_guide/core/hints_fetcher.cc -@@ -180,6 +180,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints( - const std::string& locale, +@@ -181,6 +181,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints( + absl::optional access_token, bool skip_cache, HintsFetchedCallback hints_fetched_callback) { + if ((true)) return false; @@ -148,7 +215,7 @@ diff --git a/components/optimization_guide/core/hints_fetcher.cc b/components/op diff --git a/components/optimization_guide/core/hints_manager.cc b/components/optimization_guide/core/hints_manager.cc --- a/components/optimization_guide/core/hints_manager.cc +++ b/components/optimization_guide/core/hints_manager.cc -@@ -357,6 +357,7 @@ void HintsManager::Shutdown() { +@@ -358,6 +358,7 @@ void HintsManager::Shutdown() { OptimizationGuideDecision HintsManager::GetOptimizationGuideDecisionFromOptimizationTypeDecision( OptimizationTypeDecision optimization_type_decision) { @@ -156,7 +223,7 @@ diff --git a/components/optimization_guide/core/hints_manager.cc b/components/op switch (optimization_type_decision) { case OptimizationTypeDecision::kAllowedByOptimizationFilter: case OptimizationTypeDecision::kAllowedByHint: -@@ -1063,6 +1064,7 @@ void HintsManager::CanApplyOptimizationOnDemand( +@@ -1066,6 +1067,7 @@ void HintsManager::CanApplyOptimizationOnDemand( proto::RequestContext request_context, OnDemandOptimizationGuideDecisionRepeatingCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -164,7 +231,7 @@ diff --git a/components/optimization_guide/core/hints_manager.cc b/components/op // This set contains URLs that require some information to be fetched, whether // that be a URL-keyed hint or a host-keyed hint. -@@ -1378,6 +1380,9 @@ OptimizationTypeDecision HintsManager::CanApplyOptimization( +@@ -1386,6 +1388,9 @@ OptimizationTypeDecision HintsManager::CanApplyOptimization( bool skip_cache, OptimizationMetadata* optimization_metadata) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -177,7 +244,7 @@ diff --git a/components/optimization_guide/core/hints_manager.cc b/components/op diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc -@@ -87,17 +87,17 @@ bool IsSupportedLocaleForFeature( +@@ -90,17 +90,17 @@ bool IsSupportedLocaleForFeature( // Enables the syncing of the Optimization Hints component, which provides // hints for what optimizations can be applied on a page load. BASE_FEATURE(kOptimizationHints, @@ -201,7 +268,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b // Enables performance info in the context menu and fetching from a remote // Optimization Guide Service. -@@ -107,17 +107,13 @@ BASE_FEATURE(kContextMenuPerformanceInfoAndRemoteHintFetching, +@@ -110,17 +110,13 @@ BASE_FEATURE(kContextMenuPerformanceInfoAndRemoteHintFetching, // Enables the prediction of optimization targets. BASE_FEATURE(kOptimizationTargetPrediction, @@ -223,7 +290,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b ); // Enables page content to be annotated. -@@ -127,8 +123,8 @@ BASE_FEATURE(kPageContentAnnotations, +@@ -130,8 +126,8 @@ BASE_FEATURE(kPageContentAnnotations, // Enables fetching page metadata from the remote Optimization Guide service. BASE_FEATURE(kRemotePageMetadata, @@ -234,7 +301,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b // Enables the page entities model to be annotated on every page load. BASE_FEATURE(kPageEntitiesPageContentAnnotations, -@@ -152,8 +148,8 @@ BASE_FEATURE(kPageEntitiesModelResetOnShutdown, +@@ -155,8 +151,8 @@ BASE_FEATURE(kPageEntitiesModelResetOnShutdown, // Enables push notification of hints. BASE_FEATURE(kPushNotifications, @@ -245,7 +312,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b // This feature flag does not turn off any behavior, it is only used for // experiment parameters. -@@ -166,9 +162,9 @@ BASE_FEATURE(kOptimizationGuideMetadataValidation, +@@ -169,9 +165,9 @@ BASE_FEATURE(kOptimizationGuideMetadataValidation, "OptimizationGuideMetadataValidation", base::FEATURE_DISABLED_BY_DEFAULT); @@ -256,9 +323,9 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b + "PageVisibilityBatchAnnotations", // by default + base::FEATURE_DISABLED_BY_DEFAULT); // in Bromite - BASE_FEATURE(kPageContentAnnotationsValidation, - "PageContentAnnotationsValidation", -@@ -176,7 +172,7 @@ BASE_FEATURE(kPageContentAnnotationsValidation, + BASE_FEATURE(kTextEmbeddingBatchAnnotations, + "TextEmbeddingBatchAnnotations", +@@ -183,7 +179,7 @@ BASE_FEATURE(kPageContentAnnotationsValidation, BASE_FEATURE(kPreventLongRunningPredictionModels, "PreventLongRunningPredictionModels", @@ -267,7 +334,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b BASE_FEATURE(kOptimizationGuideUseContinueOnShutdownForPageContentAnnotations, "OptimizationGuideUseContinueOnShutdownForPageContentAnnotations", -@@ -211,8 +207,8 @@ BASE_FEATURE(kPageContentAnnotationsPersistSalientImageMetadata, +@@ -218,8 +214,8 @@ BASE_FEATURE(kPageContentAnnotationsPersistSalientImageMetadata, // Killswitch for fetching on search results from a remote Optimization Guide // Service. BASE_FEATURE(kOptimizationGuideFetchingForSRP, @@ -278,7 +345,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b // Enables the model store to save relative paths computed from the base model // store dir. Storing as relative path in the model store is needed for IOS, -@@ -456,7 +452,7 @@ size_t MaxURLKeyedHintCacheSize() { +@@ -468,7 +464,7 @@ size_t MaxURLKeyedHintCacheSize() { bool ShouldPersistHintsToDisk() { return GetFieldTrialParamByFeatureAsBool(kOptimizationHints, @@ -286,7 +353,7 @@ diff --git a/components/optimization_guide/core/optimization_guide_features.cc b + "persist_hints_to_disk", false); } - bool ShouldOverrideOptimizationTargetDecisionForMetricsPurposes( + bool EnabledPersonalizedMetadata(proto::RequestContext request_context) { diff --git a/components/optimization_guide/core/prediction_model_download_manager.cc b/components/optimization_guide/core/prediction_model_download_manager.cc --- a/components/optimization_guide/core/prediction_model_download_manager.cc +++ b/components/optimization_guide/core/prediction_model_download_manager.cc @@ -351,7 +418,7 @@ diff --git a/components/optimization_guide/features.gni b/components/optimizatio diff --git a/components/permissions/features.cc b/components/permissions/features.cc --- a/components/permissions/features.cc +++ b/components/permissions/features.cc -@@ -82,12 +82,12 @@ BASE_FEATURE(kFailFastQuietChip, +@@ -92,12 +92,12 @@ BASE_FEATURE(kFailFastQuietChip, // When enabled, use the value of the `service_url` FeatureParam as the url // for the Web Permission Predictions Service. BASE_FEATURE(kPermissionPredictionServiceUseUrlOverride, @@ -371,7 +438,7 @@ diff --git a/components/permissions/features.cc b/components/permissions/feature diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1101,12 +1101,8 @@ BASE_FEATURE(kMemoryCacheStrongReferenceSingleUnload, +@@ -1175,12 +1175,8 @@ BASE_FEATURE(kMemoryCacheStrongReferenceSingleUnload, // in the first viewport after the page load and the metrics of the clicked // anchor element will be extracted and recorded. BASE_FEATURE(kNavigationPredictor, @@ -389,7 +456,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2840,7 +2840,7 @@ +@@ -2831,7 +2831,7 @@ { // https://crbug.com/1126305 name: "Prerender2", diff --git a/build/patches/Disable-all-promo-dialogs.patch b/build/patches/Disable-all-promo-dialogs.patch index 529a7bf2..44f674c9 100644 --- a/build/patches/Disable-all-promo-dialogs.patch +++ b/build/patches/Disable-all-promo-dialogs.patch @@ -11,7 +11,7 @@ Subject: Disable all promo dialogs diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java -@@ -959,6 +959,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { +@@ -943,6 +943,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { } private boolean maybeShowPromo() { diff --git a/build/patches/Disable-conversion-measurement-api.patch b/build/patches/Disable-conversion-measurement-api.patch index f7fd0fe3..68b4a107 100644 --- a/build/patches/Disable-conversion-measurement-api.patch +++ b/build/patches/Disable-conversion-measurement-api.patch @@ -23,7 +23,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../attribution_storage_sql.cc | 8 +- content/browser/storage_partition_impl.cc | 8 +- content/public/android/BUILD.gn | 2 - - .../browser/AttributionOsLevelManager.java | 168 +----------------- + .../browser/AttributionOsLevelManager.java | 219 ++---------------- .../public/browser/navigation_controller.cc | 1 - content/public/common/content_features.cc | 4 +- content/renderer/render_thread_impl.cc | 5 +- @@ -34,7 +34,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../platform/runtime_enabled_features.json5 | 7 + ui/base/ui_base_features.cc | 2 +- ui/events/android/motion_event_android.cc | 6 +- - 23 files changed, 78 insertions(+), 215 deletions(-) + 23 files changed, 89 insertions(+), 255 deletions(-) diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml @@ -126,8 +126,8 @@ diff --git a/content/browser/aggregation_service/aggregation_service_features.cc diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc --- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc -@@ -446,6 +446,11 @@ void AttributionDataHostManagerImpl::ParseSource( - RegistrarAndHeader header) { +@@ -499,6 +499,11 @@ void AttributionDataHostManagerImpl::ParseSource( + Registrar registrar) { DCHECK(it != registrations_.end()); + if ((true)) { @@ -135,13 +135,13 @@ diff --git a/content/browser/attribution_reporting/attribution_data_host_manager + return; + } + - switch (header.registrar) { + switch (registrar) { case Registrar::kWeb: if (!network::HasAttributionWebSupport( diff --git a/content/browser/attribution_reporting/attribution_host.cc b/content/browser/attribution_reporting/attribution_host.cc --- a/content/browser/attribution_reporting/attribution_host.cc +++ b/content/browser/attribution_reporting/attribution_host.cc -@@ -390,6 +390,7 @@ void AttributionHost::RegisterNavigationDataHost( +@@ -359,6 +359,7 @@ void AttributionHost::RegisterNavigationDataHost( return; } @@ -173,7 +173,7 @@ diff --git a/content/browser/attribution_reporting/attribution_report_network_se auto resource_request = std::make_unique(); resource_request->url = std::move(url); resource_request->headers = std::move(headers); -@@ -162,6 +165,12 @@ void AttributionReportNetworkSender::OnReportSent( +@@ -164,6 +167,12 @@ void AttributionReportNetworkSender::OnReportSent( ReportSentCallback sent_callback, UrlLoaderList::iterator it, scoped_refptr headers) { @@ -189,7 +189,7 @@ diff --git a/content/browser/attribution_reporting/attribution_report_network_se diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc -@@ -629,14 +629,16 @@ StorableSource::Result ThrottleResultToStorableSourceResult( +@@ -682,14 +682,16 @@ StorableSource::Result DestinationRateLimitResultToStorableSourceResult( } } @@ -212,7 +212,7 @@ diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/ diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc -@@ -1430,13 +1430,7 @@ void StoragePartitionImpl::Initialize( +@@ -1485,13 +1485,7 @@ void StoragePartitionImpl::Initialize( bucket_manager_ = std::make_unique(this); @@ -260,7 +260,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib import org.chromium.base.ContextUtils; import org.chromium.base.Log; -@@ -46,6 +35,8 @@ import java.util.concurrent.TimeoutException; +@@ -48,6 +37,8 @@ import java.util.concurrent.TimeoutException; */ @JNINamespace("content") public class AttributionOsLevelManager { @@ -269,7 +269,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib private static final String TAG = "AttributionManager"; // TODO: replace with constant in android.Manifest.permission once it becomes available in U. private static final String PERMISSION_ACCESS_ADSERVICES_ATTRIBUTION = -@@ -87,12 +78,7 @@ public class AttributionOsLevelManager { +@@ -91,12 +82,7 @@ public class AttributionOsLevelManager { } private MeasurementManagerFutures getManager() { @@ -283,7 +283,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib } private void onRegistrationCompleted( -@@ -117,40 +103,6 @@ public class AttributionOsLevelManager { +@@ -121,46 +107,6 @@ public class AttributionOsLevelManager { } } @@ -307,7 +307,13 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib - } else if (thrown instanceof IOException) { - result = RegistrationResult.ERROR_IO; - } else if (thrown instanceof IllegalStateException) { -- result = RegistrationResult.ERROR_ILLEGAL_STATE; +- // The Android API doesn't break out this error as a separate exception so we +- // are forced to inspect the message for now. +- if (thrown.getMessage().toLowerCase(Locale.US).contains("background")) { +- result = RegistrationResult.ERROR_BACKGROUND_CALLER; +- } else { +- result = RegistrationResult.ERROR_ILLEGAL_STATE; +- } - } else if (thrown instanceof SecurityException) { - result = RegistrationResult.ERROR_SECURITY; - } else if (thrown instanceof TimeoutException) { @@ -324,10 +330,21 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib /** * Registers a web attribution source with native, see `registerWebSourceAsync()`: * https://developer.android.com/reference/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFutures. -@@ -169,13 +121,6 @@ public class AttributionOsLevelManager { - requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); - return; - } +@@ -168,24 +114,8 @@ public class AttributionOsLevelManager { + @CalledByNative + private void registerWebAttributionSource(int requestId, GURL registrationUrl, + GURL topLevelOrigin, boolean isDebugKeyAllowed, MotionEvent event) { +- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { +- onRegistrationCompleted( +- requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); +- return; +- } +- MeasurementManagerFutures mm = getManager(); +- if (mm == null) { +- onRegistrationCompleted( +- requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); +- return; +- } - ListenableFuture future = mm.registerWebSourceAsync(new WebSourceRegistrationRequest( - Arrays.asList(new WebSourceParams( - Uri.parse(registrationUrl.getSpec()), isDebugKeyAllowed)), @@ -335,33 +352,63 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib - /*appDestination=*/null, /*webDestination=*/null, - /*verifiedDestination=*/null)); - addRegistrationFutureCallback(requestId, RegistrationType.SOURCE, future); ++ onRegistrationCompleted( ++ requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); } /** -@@ -195,9 +140,7 @@ public class AttributionOsLevelManager { - requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); - return; - } +@@ -194,20 +124,9 @@ public class AttributionOsLevelManager { + */ + @CalledByNative + private void registerAttributionSource(int requestId, GURL registrationUrl, MotionEvent event) { +- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { +- onRegistrationCompleted( +- requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); +- return; +- } +- MeasurementManagerFutures mm = getManager(); +- if (mm == null) { +- onRegistrationCompleted( +- requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); +- return; +- } - ListenableFuture future = - mm.registerSourceAsync(Uri.parse(registrationUrl.getSpec()), event); - addRegistrationFutureCallback(requestId, RegistrationType.SOURCE, future); -+ onRegistrationCompleted(requestId, RegistrationType.SOURCE, RegistrationResult.SUCCESS); ++ onRegistrationCompleted( ++ requestId, RegistrationType.SOURCE, RegistrationResult.ERROR_INTERNAL); ++ return; } /** -@@ -219,11 +162,6 @@ public class AttributionOsLevelManager { - requestId, RegistrationType.TRIGGER, RegistrationResult.ERROR_INTERNAL); - return; - } +@@ -217,23 +136,9 @@ public class AttributionOsLevelManager { + @CalledByNative + private void registerWebAttributionTrigger( + int requestId, GURL registrationUrl, GURL topLevelOrigin, boolean isDebugKeyAllowed) { +- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { +- onRegistrationCompleted( +- requestId, RegistrationType.TRIGGER, RegistrationResult.ERROR_INTERNAL); +- return; +- } +- +- MeasurementManagerFutures mm = getManager(); +- if (mm == null) { +- onRegistrationCompleted( +- requestId, RegistrationType.TRIGGER, RegistrationResult.ERROR_INTERNAL); +- return; +- } - ListenableFuture future = mm.registerWebTriggerAsync(new WebTriggerRegistrationRequest( - Arrays.asList(new WebTriggerParams( - Uri.parse(registrationUrl.getSpec()), isDebugKeyAllowed)), - Uri.parse(topLevelOrigin.getSpec()))); - addRegistrationFutureCallback(requestId, RegistrationType.TRIGGER, future); ++ onRegistrationCompleted( ++ requestId, RegistrationType.TRIGGER, RegistrationResult.ERROR_INTERNAL); ++ return; } private void onDataDeletionCompleted(int requestId) { -@@ -248,77 +186,7 @@ public class AttributionOsLevelManager { +@@ -258,77 +163,7 @@ public class AttributionOsLevelManager { onDataDeletionCompleted(requestId); return; } @@ -440,7 +487,18 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib } /** -@@ -343,32 +211,6 @@ public class AttributionOsLevelManager { +@@ -339,6 +174,10 @@ public class AttributionOsLevelManager { + private static void getMeasurementApiStatus() { + ThreadUtils.assertOnBackgroundThread(); + ++ if ((true)) { ++ AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); ++ return; ++ } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); + return; +@@ -356,32 +195,6 @@ public class AttributionOsLevelManager { AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); return; } @@ -487,7 +545,7 @@ diff --git a/content/public/browser/navigation_controller.cc b/content/public/br diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -864,8 +864,8 @@ BASE_FEATURE(kPrivacySandboxAdsAPIsM1Override, +@@ -816,8 +816,8 @@ BASE_FEATURE(kPrivacySandboxAdsAPIsM1Override, // FLEDGE, Topics, along with a number of other features actively in development // within these APIs. BASE_FEATURE(kPrivacySandboxAdsAPIsOverride, @@ -501,7 +559,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc -@@ -927,6 +927,9 @@ void RenderThreadImpl::InitializeRenderer( +@@ -924,6 +924,9 @@ void RenderThreadImpl::InitializeRenderer( GetContentClient()->renderer()->DidSetUserAgent(user_agent); user_agent_metadata_ = user_agent_metadata; cors_exempt_header_list_ = cors_exempt_header_list; @@ -511,7 +569,7 @@ diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_th attribution_support_ = attribution_support; blink::WebVector web_cors_exempt_header_list( -@@ -1834,7 +1837,7 @@ RenderThreadImpl::GetAttributionReportingSupport() { +@@ -1829,7 +1832,7 @@ RenderThreadImpl::GetAttributionReportingSupport() { void RenderThreadImpl::SetAttributionReportingSupport( network::mojom::AttributionSupport attribution_support) { @@ -553,7 +611,7 @@ diff --git a/services/network/public/cpp/attribution_utils.cc b/services/network diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc -@@ -141,9 +141,9 @@ BASE_FEATURE(kAttributionReportingReportVerification, +@@ -154,9 +154,9 @@ BASE_FEATURE(kAttributionReportingReportVerification, // Gate access to Attribution Reporting cross app and web APIs that allow // registering with a native attribution API. @@ -569,7 +627,7 @@ diff --git a/services/network/public/cpp/features.cc b/services/network/public/c diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -284,8 +284,8 @@ const base::FeatureParam kBoostImagePriorityTightMediumLimit{ +@@ -294,8 +294,8 @@ const base::FeatureParam kBoostImagePriorityTightMediumLimit{ // https://github.com/patcg-individual-drafts/topics // Kill switch for the Topics API. BASE_FEATURE(kBrowsingTopics, @@ -580,7 +638,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea // If enabled, the check for whether the IP address is publicly routable will be // bypassed when determining the eligibility for a page to be included in topics -@@ -300,14 +300,14 @@ BASE_FEATURE(kBrowsingTopicsBypassIPIsPubliclyRoutableCheck, +@@ -310,14 +310,14 @@ BASE_FEATURE(kBrowsingTopicsBypassIPIsPubliclyRoutableCheck, // either a valid Origin Trial token exists or `kPrivacySandboxAdsAPIsOverride` // is enabled.) BASE_FEATURE(kBrowsingTopicsDocumentAPI, @@ -599,7 +657,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea // The number of epochs from where to calculate the topics to give to a // requesting contexts. const base::FeatureParam kBrowsingTopicsNumberOfEpochsToExpose{ -@@ -520,8 +520,8 @@ BASE_FEATURE(kContentCaptureConstantStreaming, +@@ -543,8 +543,8 @@ BASE_FEATURE(kContentCaptureConstantStreaming, // Controls whether the Conversion Measurement API infrastructure is enabled. BASE_FEATURE(kConversionMeasurement, @@ -610,7 +668,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea BASE_FEATURE(kCorrectFloatExtensionTestForWebGL, "CorrectFloatExtensionTestForWebGL", -@@ -1270,16 +1270,16 @@ const base::FeatureParam kPrewarmFantasy = {&kPrewarmDefaultFontFamilies, +@@ -1357,16 +1357,16 @@ const base::FeatureParam kPrewarmFantasy = {&kPrewarmDefaultFontFamilies, "prewarm_fantasy", false}; #endif @@ -631,7 +689,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea + base::FEATURE_DISABLED_BY_DEFAULT); // in bromite // Selectively allows the JavaScript API to be disabled in just one of the - // contexts. + // contexts. The Protected Audience param's name has not been updated (from diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 @@ -652,7 +710,7 @@ diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc -@@ -500,7 +500,7 @@ BASE_FEATURE(kMacClipboardWriteImageWithPng, +@@ -553,7 +553,7 @@ BASE_FEATURE(kMacClipboardWriteImageWithPng, // We want to experiment with disabling it to align with CR2023 designs. BASE_FEATURE(kCr2023MacFontSmoothing, "Cr2023MacFontSmoothing", diff --git a/build/patches/Disable-crash-reporting.patch b/build/patches/Disable-crash-reporting.patch index 13e24406..870ea945 100644 --- a/build/patches/Disable-crash-reporting.patch +++ b/build/patches/Disable-crash-reporting.patch @@ -10,7 +10,7 @@ Subject: Disable crash reporting diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -2627,6 +2627,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( +@@ -2639,6 +2639,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( base::NumberToString(pid)); } #endif @@ -21,7 +21,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -275,8 +275,8 @@ BASE_FEATURE(kCooperativeScheduling, +@@ -278,8 +278,8 @@ BASE_FEATURE(kCooperativeScheduling, // Enables crash reporting via Reporting API. // https://www.w3.org/TR/reporting/#crash-report BASE_FEATURE(kCrashReporting, diff --git a/build/patches/Disable-feeds-support-by-default.patch b/build/patches/Disable-feeds-support-by-default.patch index 3bd73b31..2ffb607b 100644 --- a/build/patches/Disable-feeds-support-by-default.patch +++ b/build/patches/Disable-feeds-support-by-default.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedFeatures.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedFeatures.java --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedFeatures.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedFeatures.java -@@ -48,13 +48,7 @@ public final class FeedFeatures { +@@ -44,13 +44,7 @@ public final class FeedFeatures { * the user is signed in and confirms it's not a child profile. */ public static boolean isWebFeedUIEnabled() { @@ -31,7 +31,7 @@ diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/fe diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -1682,10 +1682,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, +@@ -1780,10 +1780,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, supervised_user::SupervisedUserService::RegisterProfilePrefs(registry); #endif diff --git a/build/patches/Disable-fetching-of-all-field-trials.patch b/build/patches/Disable-fetching-of-all-field-trials.patch index 9aa5bd2c..0a68ce47 100644 --- a/build/patches/Disable-fetching-of-all-field-trials.patch +++ b/build/patches/Disable-fetching-of-all-field-trials.patch @@ -18,19 +18,19 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/variations/net/BUILD.gn | 2 -- .../variations/net/omnibox_http_headers.cc | 4 +-- .../variations/net/variations_http_headers.cc | 3 ++ - .../service/variations_field_trial_creator.cc | 4 ++- + .../variations_field_trial_creator_base.cc | 8 ++--- .../variations/service/variations_service.cc | 15 ++------- .../browser/loader/url_loader_throttles.cc | 7 ---- .../origin_trials/origin_trials_utils.cc | 2 +- content/public/common/content_features.cc | 4 +-- .../variations_render_thread_observer.cc | 9 ------ .../renderer/core/loader/document_loader.cc | 7 ---- - 18 files changed, 29 insertions(+), 78 deletions(-) + 18 files changed, 29 insertions(+), 82 deletions(-) diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc --- a/android_webview/common/aw_features.cc +++ b/android_webview/common/aw_features.cc -@@ -96,8 +96,8 @@ BASE_FEATURE(kWebViewJavaJsBridgeMojo, +@@ -97,8 +97,8 @@ BASE_FEATURE(kWebViewMetricsFiltering, // Field trial feature for controlling support of Origin Trials on WebView. BASE_FEATURE(kWebViewOriginTrials, @@ -44,7 +44,7 @@ diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_f diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn --- a/android_webview/nonembedded/BUILD.gn +++ b/android_webview/nonembedded/BUILD.gn -@@ -100,7 +100,6 @@ android_library("services_java") { +@@ -103,7 +103,6 @@ android_library("services_java") { sources = [ "java/src/org/chromium/android_webview/services/AwMinidumpUploadJobService.java", "java/src/org/chromium/android_webview/services/AwMinidumpUploaderDelegate.java", @@ -52,7 +52,7 @@ diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/ "java/src/org/chromium/android_webview/services/ComponentUpdaterResetSafeModeAction.java", "java/src/org/chromium/android_webview/services/ComponentUpdaterSafeModeUtils.java", "java/src/org/chromium/android_webview/services/ComponentsProviderPathUtil.java", -@@ -119,7 +118,6 @@ android_library("services_java") { +@@ -122,7 +121,6 @@ android_library("services_java") { "java/src/org/chromium/android_webview/services/SafeModeService.java", "java/src/org/chromium/android_webview/services/SafeModeVariationsSeedContentProvider.java", "java/src/org/chromium/android_webview/services/StartupFeatureMetadataHolder.java", @@ -75,16 +75,16 @@ diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/s diff --git a/chrome/browser/metrics/chrome_browser_sampling_trials.cc b/chrome/browser/metrics/chrome_browser_sampling_trials.cc --- a/chrome/browser/metrics/chrome_browser_sampling_trials.cc +++ b/chrome/browser/metrics/chrome_browser_sampling_trials.cc -@@ -54,6 +54,8 @@ void CreateFallbackSamplingTrial( - const std::string& feature_name, +@@ -55,6 +55,8 @@ void CreateFallbackSamplingTrial( const int sampled_in_rate_per_mille, + const bool starts_active, base::FeatureList* feature_list) { + if ((true)) + return; scoped_refptr trial( base::FieldTrialList::FactoryGetFieldTrial( trial_name, /*total_probability=*/1000, "Default", entropy_provider)); -@@ -93,6 +95,8 @@ void CreateFallbackUkmSamplingTrial( +@@ -98,6 +100,8 @@ void CreateFallbackUkmSamplingTrial( const base::FieldTrial::EntropyProvider& entropy_provider, bool is_stable_channel, base::FeatureList* feature_list) { @@ -96,7 +96,7 @@ diff --git a/chrome/browser/metrics/chrome_browser_sampling_trials.cc b/chrome/b diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc -@@ -721,7 +721,6 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams( +@@ -771,7 +771,6 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams( void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams( network::mojom::NetworkContextParams* network_context_params) { @@ -132,7 +132,7 @@ diff --git a/components/variations/android/java/src/org/chromium/components/vari diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java --- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java +++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java -@@ -451,35 +451,13 @@ public class VariationsSeedFetcher { +@@ -453,35 +453,13 @@ public class VariationsSeedFetcher { */ public void fetchSeed(String restrictMode, String milestone, String channel) { assert !ThreadUtils.runningOnUiThread(); @@ -172,7 +172,7 @@ diff --git a/components/variations/android/java/src/org/chromium/components/vari } private void recordFetchResultOrCode(int resultOrCode) { -@@ -523,7 +501,7 @@ public class VariationsSeedFetcher { +@@ -525,7 +503,7 @@ public class VariationsSeedFetcher { * @param curSeedInfo optional currently saved seed info to set the `If-None-Match` header. * @return the object holds the request result and seed data with its related header fields. */ @@ -220,27 +220,45 @@ diff --git a/components/variations/net/variations_http_headers.cc b/components/v AppendOmniboxOnDeviceSuggestionsHeaderIfNeeded(url, resource_request_); // Note the criteria for attaching client experiment headers: -diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc ---- a/components/variations/service/variations_field_trial_creator.cc -+++ b/components/variations/service/variations_field_trial_creator.cc -@@ -142,7 +142,8 @@ Study::CpuArchitecture GetCurrentCpuArchitecture() { - // "--variations-server-url" switches are passed. It is however possible to - // apply the testing config as well as specify additional field trials (using - // "--force-fieldtrials") by using the "--enable-field-trial-config" switch. --bool ShouldUseFieldTrialTestingConfig(const base::CommandLine* command_line) { -+bool ShouldUseFieldTrialTestingConfig(const base::CommandLine* command_line) { // disabled in Bromite -+ if ((true)) return false; - #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - return command_line->HasSwitch(switches::kEnableFieldTrialTestingConfig); - #else -@@ -530,6 +531,7 @@ Study::FormFactor VariationsFieldTrialCreator::GetCurrentFormFactor() { +diff --git a/components/variations/service/variations_field_trial_creator_base.cc b/components/variations/service/variations_field_trial_creator_base.cc +--- a/components/variations/service/variations_field_trial_creator_base.cc ++++ b/components/variations/service/variations_field_trial_creator_base.cc +@@ -118,6 +118,7 @@ Study::CpuArchitecture GetCurrentCpuArchitecture() { } #if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED) +#error FIELDTRIAL_TESTING_ENABLED should be disabled. - void VariationsFieldTrialCreator::ApplyFieldTrialTestingConfig( - base::FeatureList* feature_list) { - VLOG(1) << "Applying FieldTrialTestingConfig"; + // Determines whether the field trial testing config defined in + // testing/variations/fieldtrial_testing_config.json should be applied. If the + // "disable_fieldtrial_testing_config" GN flag is set to true, then the testing +@@ -302,11 +303,6 @@ bool VariationsFieldTrialCreatorBase::SetUpFieldTrials( + safe_seed_manager); + } + +- platform_field_trials->SetUpClientSideFieldTrials( +- used_seed, *entropy_providers, feature_list.get()); +- +- platform_field_trials->RegisterFeatureOverrides(feature_list.get()); +- + base::FeatureList::SetInstance(std::move(feature_list)); + + // For testing Variations Safe Mode, maybe crash here. +@@ -585,6 +581,7 @@ bool VariationsFieldTrialCreatorBase::CreateTrialsFromSeed( + const EntropyProviders& entropy_providers, + base::FeatureList* feature_list, + SafeSeedManagerInterface* safe_seed_manager) { ++ if ((true)) return false; + // This histogram name uses "VariationsFieldTrialCreator" rather than + // "VariationsFieldTrialCreatorBase" for consistency with historical data + TRACE_EVENT0("startup", "VariationsFieldTrialCreator::CreateTrialsFromSeed"); +@@ -678,6 +675,7 @@ bool VariationsFieldTrialCreatorBase::CreateTrialsFromSeed( + + void VariationsFieldTrialCreatorBase::LoadSeedFromJsonFile( + const base::FilePath& json_seed_path) { ++ if ((true)) return; + VLOG(1) << "Loading seed from JSON file:" << json_seed_path; + JSONFileValueDeserializer file_deserializer(json_seed_path); + int error_code; diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc @@ -312,7 +330,7 @@ diff --git a/content/browser/origin_trials/origin_trials_utils.cc b/content/brow diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -791,8 +791,8 @@ BASE_FEATURE(kPepperCrossOriginRedirectRestriction, +@@ -753,8 +753,8 @@ BASE_FEATURE(kPepperCrossOriginRedirectRestriction, // things before receiving the response, for instance it can affect the next // navigation's network request. BASE_FEATURE(kPersistentOriginTrials, @@ -345,7 +363,7 @@ diff --git a/content/renderer/variations_render_thread_observer.cc b/content/ren diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc -@@ -188,13 +188,6 @@ Vector CopyInitiatorOriginTrials( +@@ -191,13 +191,6 @@ Vector CopyInitiatorOriginTrials( WebVector CopyInitiatorOriginTrials( const Vector& initiator_origin_trial_features) { WebVector result; diff --git a/build/patches/Disable-idle-detection.patch b/build/patches/Disable-idle-detection.patch index a0257eb3..de3cd576 100644 --- a/build/patches/Disable-idle-detection.patch +++ b/build/patches/Disable-idle-detection.patch @@ -11,7 +11,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -552,7 +552,7 @@ BASE_FEATURE(kHandleRendererThreadTypeChangesInBrowser, +@@ -525,7 +525,7 @@ BASE_FEATURE(kHandleRendererThreadTypeChangesInBrowser, // This is intended as a kill switch for the Idle Detection feature. To enable // this feature, the experimental web platform features flag should be set, // or the site should obtain an Origin Trial token. @@ -23,7 +23,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2014,10 +2014,9 @@ +@@ -1963,10 +1963,9 @@ base_feature: "none", }, { diff --git a/build/patches/Disable-lock-icon-in-address-bar-by-default.patch b/build/patches/Disable-lock-icon-in-address-bar-by-default.patch index adb53e9e..4dd47afa 100644 --- a/build/patches/Disable-lock-icon-in-address-bar-by-default.patch +++ b/build/patches/Disable-lock-icon-in-address-bar-by-default.patch @@ -10,12 +10,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc -@@ -603,8 +603,8 @@ BASE_FEATURE(kOmniboxModernizeVisualUpdate, - - // Experiment to introduce new security indicators for HTTPS. +@@ -470,8 +470,8 @@ BASE_FEATURE(kOmniboxModernizeVisualUpdate, + // used, on non-Android platforms this is controlled through the + // ChromeRefresh2023 flag. BASE_FEATURE(kUpdatedConnectionSecurityIndicators, - "OmniboxUpdatedConnectionSecurityIndicators", -- base::FEATURE_DISABLED_BY_DEFAULT); +- base::FEATURE_ENABLED_BY_DEFAULT); + "OmniboxUpdatedConnectionSecurityIndicators", // enabled by default + base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite diff --git a/build/patches/Disable-media-router-and-remoting-by-default.patch b/build/patches/Disable-media-router-and-remoting-by-default.patch index b284aeea..76227ee9 100644 --- a/build/patches/Disable-media-router-and-remoting-by-default.patch +++ b/build/patches/Disable-media-router-and-remoting-by-default.patch @@ -41,7 +41,7 @@ diff --git a/chrome/browser/media/router/media_router_feature.cc b/chrome/browse diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc -@@ -419,7 +419,7 @@ void ProfileImpl::RegisterProfilePrefs( +@@ -413,7 +413,7 @@ void ProfileImpl::RegisterProfilePrefs( #endif registry->RegisterBooleanPref(prefs::kForceEphemeralProfiles, false); diff --git a/build/patches/Disable-minidump-upload-scheduling.patch b/build/patches/Disable-minidump-upload-scheduling.patch index f4ae5d74..0cba662e 100644 --- a/build/patches/Disable-minidump-upload-scheduling.patch +++ b/build/patches/Disable-minidump-upload-scheduling.patch @@ -11,7 +11,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/components/endpoint_fetcher/endpoint_fetcher.cc b/components/endpoint_fetcher/endpoint_fetcher.cc --- a/components/endpoint_fetcher/endpoint_fetcher.cc +++ b/components/endpoint_fetcher/endpoint_fetcher.cc -@@ -355,7 +355,7 @@ void EndpointFetcher::OnResponseFetched( +@@ -366,7 +366,7 @@ void EndpointFetcher::OnResponseFetched( } } else { std::string net_error = net::ErrorToString(net_error_code); diff --git a/build/patches/Disable-plugins-enumeration.patch b/build/patches/Disable-plugins-enumeration.patch index d13afd45..07f45265 100644 --- a/build/patches/Disable-plugins-enumeration.patch +++ b/build/patches/Disable-plugins-enumeration.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc -@@ -2057,9 +2057,7 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() { +@@ -2051,9 +2051,7 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() { } PluginData* LocalFrame::GetPluginData() const { diff --git a/build/patches/Disable-requests-for-single-word-Omnibar-searches.patch b/build/patches/Disable-requests-for-single-word-Omnibar-searches.patch index 7c009759..c9fa9f78 100644 --- a/build/patches/Disable-requests-for-single-word-Omnibar-searches.patch +++ b/build/patches/Disable-requests-for-single-word-Omnibar-searches.patch @@ -6,13 +6,29 @@ Patch from https://github.com/Eloston/ungoogled-chromium/issues/814#issuecomment License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../ui/omnibox/chrome_omnibox_navigation_observer.cc | 7 ------- - 1 file changed, 7 deletions(-) + .../ui/omnibox/chrome_omnibox_navigation_observer.cc | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc --- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc -@@ -252,13 +252,6 @@ ChromeOmniboxNavigationObserver::ChromeOmniboxNavigationObserver( +@@ -76,6 +76,7 @@ bool OnlyChangeIsFromHTTPToHTTPS(const GURL& origin, const GURL& destination) { + return origin_with_https == destination; + } + ++#if BUILDFLAG(IS_ANDROID) + // Choose the appropriate URLLoaderFactory: either an explicitly specified or a + // default for the given profile. + network::mojom::URLLoaderFactory* GetURLLoaderFactory( +@@ -87,6 +88,7 @@ network::mojom::URLLoaderFactory* GetURLLoaderFactory( + ->GetURLLoaderFactoryForBrowserProcess() + .get(); + } ++#endif + + // Helper to keep ChromeOmniboxNavigationObserver alive while the initiated + // navigation is pending. +@@ -252,13 +254,6 @@ ChromeOmniboxNavigationObserver::ChromeOmniboxNavigationObserver( profile_(profile), show_infobar_(std::move(show_infobar)) { NavigationUserData::CreateForNavigationHandle(navigation, this); diff --git a/build/patches/Disable-safety-check.patch b/build/patches/Disable-safety-check.patch index acf2529f..4bf596b5 100644 --- a/build/patches/Disable-safety-check.patch +++ b/build/patches/Disable-safety-check.patch @@ -16,36 +16,36 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -370,7 +370,6 @@ if (current_toolchain == default_toolchain) { +@@ -381,7 +381,6 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/recent_tabs:helper_java", "//chrome/browser/recent_tabs:java", "//chrome/browser/safe_browsing/android:java", - "//chrome/browser/safety_check/android:java", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/search_resumption:java", - "//chrome/browser/segmentation_platform:factory_java", -@@ -974,8 +973,6 @@ if (current_toolchain == default_toolchain) { +@@ -993,8 +992,6 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/recent_tabs:java", "//chrome/browser/recent_tabs:junit", "//chrome/browser/recent_tabs/internal:junit", - "//chrome/browser/safety_check/android:java", - "//chrome/browser/safety_check/android:junit", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/search_resumption:junit", - "//chrome/browser/segmentation_platform:factory_java", -@@ -1552,8 +1549,6 @@ if (current_toolchain == default_toolchain) { +@@ -1584,8 +1581,6 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/recent_tabs/internal:javatests", "//chrome/browser/safe_browsing/android:java", "//chrome/browser/safe_browsing/android:javatests", - "//chrome/browser/safety_check/android:java", - "//chrome/browser/safety_check/android:javatests", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/selection/android:javatests", - "//chrome/browser/settings:java", diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -977,7 +977,6 @@ chrome_java_sources = [ +@@ -986,7 +986,6 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java", "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingReferringAppBridge.java", "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingSettingsLauncher.java", @@ -56,14 +56,14 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml -@@ -62,11 +62,6 @@ found in the LICENSE file. +@@ -61,11 +61,6 @@ android:key="privacy" - android:order="10" + android:order="11" android:title="@string/prefs_privacy_security"/> - temp_file_getter, AnalyzeRarFileCallback callback) { DCHECK(rar_file.IsValid()); @@ -41,11 +41,14 @@ diff --git a/chrome/services/file_util/safe_archive_analyzer.cc b/chrome/service - weak_factory_.GetWeakPtr()); - timeout_timer_.Start(FROM_HERE, kArchiveAnalysisTimeout, this, - &SafeArchiveAnalyzer::Timeout); -- rar_analyzer_.Analyze(std::move(rar_file), base::FilePath(), -- std::move(analysis_finished_callback), -- std::move(temp_file_getter_callback), &results_); + LOG(FATAL) << "AnalyzeRarFile is disabled in this build"; + safe_browsing::ArchiveAnalyzerResults results; + // TODO(crbug/1466287): Update RAR analyzer to use passwords and provide the + // password here. +- rar_analyzer_.Analyze(std::move(rar_file), base::FilePath(), +- /*password=*/absl::nullopt, +- std::move(analysis_finished_callback), +- std::move(temp_file_getter_callback), &results_); + std::move(callback).Run(results); } @@ -61,7 +64,7 @@ diff --git a/chrome/services/file_util/safe_archive_analyzer.h b/chrome/services #include "chrome/utility/safe_browsing/seven_zip_analyzer.h" #include "chrome/utility/safe_browsing/zip_analyzer.h" #include "mojo/public/cpp/bindings/remote.h" -@@ -63,7 +62,6 @@ class SafeArchiveAnalyzer : public chrome::mojom::SafeArchiveAnalyzer { +@@ -65,7 +64,6 @@ class SafeArchiveAnalyzer : public chrome::mojom::SafeArchiveAnalyzer { void Timeout(); safe_browsing::ZipAnalyzer zip_analyzer_; diff --git a/build/patches/Disable-text-fragments-by-default.patch b/build/patches/Disable-text-fragments-by-default.patch index 617f61d9..2ec77920 100644 --- a/build/patches/Disable-text-fragments-by-default.patch +++ b/build/patches/Disable-text-fragments-by-default.patch @@ -22,7 +22,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -6774,6 +6774,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -6897,6 +6897,11 @@ const FeatureEntry kFeatureEntries[] = { "")}, #endif @@ -37,7 +37,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -3018,6 +3018,11 @@ +@@ -3148,6 +3148,11 @@ "owners": [ "robsc", "napper", "alanlxl" ], "expiry_milestone": 130 }, @@ -52,7 +52,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1432,6 +1432,10 @@ extern const char kDropInputEventsBeforeFirstPaintDescription[] = +@@ -1486,6 +1486,10 @@ const char kDropInputEventsBeforeFirstPaintDescription[] = "intentionally interact with elements on that page. By dropping the events " "we prevent accidental interaction with a page the user has not seen yet."; @@ -66,7 +66,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -798,6 +798,9 @@ extern const char kExperimentalRgbKeyboardPatternsDescription[]; +@@ -832,6 +832,9 @@ extern const char kExperimentalRgbKeyboardPatternsDescription[]; extern const char kRetailCouponsName[]; extern const char kRetailCouponsDescription[]; @@ -91,8 +91,8 @@ diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/pre diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc -@@ -294,6 +294,8 @@ void SetRuntimeFeaturesFromChromiumFeatures() { - raw_ref(autofill::features::kAutofillSharedAutofill)}, +@@ -284,6 +284,8 @@ void SetRuntimeFeaturesFromChromiumFeatures() { + {wf::EnableSharedAutofill, raw_ref(features::kAutofillSharedAutofill)}, {wf::EnableTouchDragAndContextMenu, raw_ref(features::kTouchDragAndContextMenu)}, + {wf::EnableTextFragmentIdentifiers, @@ -103,7 +103,7 @@ diff --git a/content/child/runtime_features.cc b/content/child/runtime_features. diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -740,6 +740,11 @@ BASE_FEATURE(kFastPathPaintPropertyUpdates, +@@ -783,6 +783,11 @@ BASE_FEATURE(kExtendScriptResourceLifetime, // trials. BASE_FEATURE(kFencedFrames, "FencedFrames", base::FEATURE_DISABLED_BY_DEFAULT); @@ -118,7 +118,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -343,6 +343,7 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDispatchBeforeUnloadOnFreeze); +@@ -350,6 +350,7 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDispatchBeforeUnloadOnFreeze); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDisplayLocking); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDropInputEventsBeforeFirstPaint); @@ -129,7 +129,7 @@ diff --git a/third_party/blink/public/common/features.h b/third_party/blink/publ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc -@@ -4396,9 +4396,14 @@ void Document::SetURL(const KURL& url) { +@@ -4410,9 +4410,14 @@ void Document::SetURL(const KURL& url) { TRACE_EVENT1("navigation", "Document::SetURL", "url", new_url.GetString().Utf8()); @@ -147,7 +147,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -3512,10 +3512,9 @@ +@@ -3536,10 +3536,9 @@ }, { name: "TextFragmentIdentifiers", diff --git a/build/patches/Disable-third-party-origin-trials.patch b/build/patches/Disable-third-party-origin-trials.patch index aa2a1d33..f64def78 100644 --- a/build/patches/Disable-third-party-origin-trials.patch +++ b/build/patches/Disable-third-party-origin-trials.patch @@ -62,7 +62,7 @@ diff --git a/components/embedder_support/origin_trials/origin_trial_policy_impl. diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc -@@ -8195,7 +8195,6 @@ void NavigationRequest::RestartBackForwardCachedNavigationImpl() { +@@ -8211,7 +8211,6 @@ void NavigationRequest::SetSourceSiteInstanceToInitiatorIfNeeded() { void NavigationRequest::ForceEnableOriginTrials( const std::vector& trials) { DCHECK(!HasCommitted()); @@ -73,7 +73,7 @@ diff --git a/content/browser/renderer_host/navigation_request.cc b/content/brows diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc -@@ -474,10 +474,6 @@ void FillNavigationParamsRequest( +@@ -475,10 +475,6 @@ void FillNavigationParamsRequest( common_params.initiator_origin.value(); } @@ -84,7 +84,7 @@ diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_fra navigation_params->was_discarded = commit_params.was_discarded; navigation_params->document_ukm_source_id = commit_params.document_ukm_source_id; -@@ -505,12 +501,6 @@ void FillNavigationParamsRequest( +@@ -506,12 +502,6 @@ void FillNavigationParamsRequest( navigation_params->had_transient_user_activation = common_params.has_user_gesture; @@ -97,7 +97,7 @@ diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_fra if (!commit_params.early_hints_preloaded_resources.empty()) { navigation_params->early_hints_preloaded_resources = WebVector(); for (const auto& resource : commit_params.early_hints_preloaded_resources) { -@@ -572,11 +562,6 @@ blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams( +@@ -573,11 +563,6 @@ blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams( info->url_request.GetURLRequestExtraData().get()); DCHECK(url_request_extra_data); @@ -109,7 +109,7 @@ diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_fra blink::NavigationDownloadPolicy download_policy; download_policy.ApplyDownloadFramePolicy( info->is_opener_navigation, info->url_request.HasUserGesture(), -@@ -599,7 +584,7 @@ blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams( +@@ -600,7 +585,7 @@ blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams( info->url_request.HasUserGesture(), info->url_request.HasTextFragmentToken(), info->should_check_main_world_content_security_policy, @@ -161,7 +161,7 @@ diff --git a/third_party/blink/common/origin_trials/trial_token_validator.cc b/t diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc -@@ -175,13 +175,6 @@ BASE_FEATURE(kLoadNotificationsForSameDocumentNavigations, +@@ -178,13 +178,6 @@ BASE_FEATURE(kLoadNotificationsForSameDocumentNavigations, Vector CopyInitiatorOriginTrials( const WebVector& initiator_origin_trial_features) { Vector result; @@ -175,7 +175,7 @@ diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_p return result; } -@@ -194,18 +187,12 @@ WebVector CopyInitiatorOriginTrials( +@@ -197,18 +190,12 @@ WebVector CopyInitiatorOriginTrials( Vector CopyForceEnabledOriginTrials( const WebVector& force_enabled_origin_trials) { Vector result; @@ -194,7 +194,7 @@ diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_p return result; } -@@ -2777,10 +2764,6 @@ void DocumentLoader::CreateParserPostCommit() { +@@ -2809,10 +2796,6 @@ void DocumentLoader::CreateParserPostCommit() { OriginTrialFeature::kTouchEventFeatureDetection); } diff --git a/build/patches/Disable-various-metrics.patch b/build/patches/Disable-various-metrics.patch index 9bdb9dda..f4e3188b 100644 --- a/build/patches/Disable-various-metrics.patch +++ b/build/patches/Disable-various-metrics.patch @@ -14,22 +14,24 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html chrome/browser/browser_process_impl.cc | 2 +- chrome/browser/chrome_content_browser_client.cc | 15 --------------- .../chrome_metrics_services_manager_client.cc | 8 ++++---- + .../browser/ui/search/ntp_user_data_logger.cc | 4 ---- components/ntp_tiles/BUILD.gn | 3 --- + .../ntp_tiles/custom_links_manager_impl.cc | 1 - components/ntp_tiles/most_visited_sites.cc | 2 -- services/metrics/public/cpp/ukm_recorder.cc | 2 +- - 8 files changed, 7 insertions(+), 44 deletions(-) + 10 files changed, 7 insertions(+), 49 deletions(-) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java -@@ -56,7 +56,7 @@ public abstract class FirstRunActivityBase +@@ -57,7 +57,7 @@ public abstract class FirstRunActivityBase static final String SHOW_SEARCH_ENGINE_PAGE = "ShowSearchEnginePage"; static final String SHOW_SYNC_CONSENT_PAGE = "ShowSyncConsent"; - public static final boolean DEFAULT_METRICS_AND_CRASH_REPORTING = true; + public static final boolean DEFAULT_METRICS_AND_CRASH_REPORTING = false; - private static PolicyLoadListenerFactory sPolicyLoadListenerFactory; + private static PolicyLoadListenerFactory sPolicyLoadListenerFactoryForTesting; diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc --- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc @@ -89,7 +91,7 @@ diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/br diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc -@@ -1020,7 +1020,7 @@ void BrowserProcessImpl::RegisterPrefs(PrefRegistrySimple* registry) { +@@ -1042,7 +1042,7 @@ void BrowserProcessImpl::RegisterPrefs(PrefRegistrySimple* registry) { #endif // BUILDFLAG(IS_CHROMEOS_ASH) registry->RegisterBooleanPref(metrics::prefs::kMetricsReportingEnabled, @@ -101,7 +103,7 @@ diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_pro diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -78,7 +78,6 @@ +@@ -79,7 +79,6 @@ #include "chrome/browser/hid/chrome_hid_delegate.h" #include "chrome/browser/interstitials/enterprise_util.h" #include "chrome/browser/lifetime/browser_shutdown.h" @@ -109,7 +111,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch #include "chrome/browser/media/audio_service_util.h" #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/media/webrtc/audio_debug_recordings_handler.h" -@@ -4895,16 +4894,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( +@@ -4972,16 +4971,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( content::NavigationHandle* handle) { std::vector> throttles; @@ -126,7 +128,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch #if BUILDFLAG(ENABLE_SUPERVISED_USERS) MaybeAddThrottle( SupervisedUserNavigationThrottle::MaybeCreateThrottleFor(handle), -@@ -4983,10 +4972,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( +@@ -5066,10 +5055,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( throttle_manager->MaybeAppendNavigationThrottles(handle, &throttles); } @@ -162,6 +164,29 @@ diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/ #endif // BUILDFLAG(IS_ANDROID) // Name of the variations param that defines the sampling rate. +diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc +--- a/chrome/browser/ui/search/ntp_user_data_logger.cc ++++ b/chrome/browser/ui/search/ntp_user_data_logger.cc +@@ -394,8 +394,6 @@ void NTPUserDataLogger::LogMostVisitedImpression( + + void NTPUserDataLogger::LogMostVisitedNavigation( + const ntp_tiles::NTPTileImpression& impression) { +- ntp_tiles::metrics::RecordTileClick(impression); +- + // Records the action. This will be available as a time-stamped stream + // server-side and can be used to compute time-to-long-dwell. + base::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); +@@ -424,10 +422,8 @@ void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time, + if (!impression.has_value()) { + break; + } +- ntp_tiles::metrics::RecordTileImpression(*impression); + ++tiles_count; + } +- ntp_tiles::metrics::RecordPageImpression(tiles_count); + + DVLOG(1) << "Emitting NTP load time: " << load_time << ", " + << "number of tiles: " << tiles_count; diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn --- a/components/ntp_tiles/BUILD.gn +++ b/components/ntp_tiles/BUILD.gn @@ -174,7 +199,7 @@ diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn "most_visited_sites.cc", "most_visited_sites.h", "ntp_tile.cc", -@@ -93,7 +91,6 @@ source_set("unit_tests") { +@@ -92,7 +90,6 @@ source_set("unit_tests") { "custom_links_manager_impl_unittest.cc", "custom_links_store_unittest.cc", "icon_cacher_impl_unittest.cc", @@ -182,10 +207,21 @@ diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn "most_visited_sites_unittest.cc", "popular_sites_impl_unittest.cc", ] +diff --git a/components/ntp_tiles/custom_links_manager_impl.cc b/components/ntp_tiles/custom_links_manager_impl.cc +--- a/components/ntp_tiles/custom_links_manager_impl.cc ++++ b/components/ntp_tiles/custom_links_manager_impl.cc +@@ -203,7 +203,6 @@ void CustomLinksManagerImpl::RemoveCustomLinksForPreinstalledApps() { + } + } + if (default_app_links_deleted) { +- metrics::RecordsMigratedDefaultAppDeleted(DeletedTileType::kCustomLink); + prefs_->SetBoolean(prefs::kCustomLinksForPreinstalledAppsRemoved, true); + } + } diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc --- a/components/ntp_tiles/most_visited_sites.cc +++ b/components/ntp_tiles/most_visited_sites.cc -@@ -703,8 +703,6 @@ void MostVisitedSites::SaveTilesAndNotify( +@@ -702,8 +702,6 @@ void MostVisitedSites::SaveTilesAndNotify( : new_tiles; if (fixed_tiles.size() != new_tiles.size()) { diff --git a/build/patches/Do-not-build-API-keys-infobar.patch b/build/patches/Do-not-build-API-keys-infobar.patch index ab637191..3cb59e78 100644 --- a/build/patches/Do-not-build-API-keys-infobar.patch +++ b/build/patches/Do-not-build-API-keys-infobar.patch @@ -4,13 +4,14 @@ Subject: Do not build API keys infobar License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/ui/BUILD.gn | 2 -- - 1 file changed, 2 deletions(-) + chrome/browser/ui/BUILD.gn | 2 -- + chrome/browser/ui/startup/infobar_utils.cc | 3 --- + 2 files changed, 5 deletions(-) diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -1417,8 +1417,6 @@ static_library("ui") { +@@ -1367,8 +1367,6 @@ static_library("ui") { "singleton_tabs.h", "startup/automation_infobar_delegate.cc", "startup/automation_infobar_delegate.h", @@ -19,5 +20,18 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn "startup/infobar_utils.cc", "startup/infobar_utils.h", "startup/launch_mode_recorder.cc", +diff --git a/chrome/browser/ui/startup/infobar_utils.cc b/chrome/browser/ui/startup/infobar_utils.cc +--- a/chrome/browser/ui/startup/infobar_utils.cc ++++ b/chrome/browser/ui/startup/infobar_utils.cc +@@ -139,9 +139,6 @@ void AddInfoBarsIfNecessary(Browser* browser, + infobars::ContentInfoBarManager* infobar_manager = + infobars::ContentInfoBarManager::FromWebContents(web_contents); + +- if (!google_apis::HasAPIKeyConfigured()) +- GoogleApiKeysInfoBarDelegate::Create(infobar_manager); +- + if (ObsoleteSystem::IsObsoleteNowOrSoon()) { + PrefService* local_state = g_browser_process->local_state(); + if (!local_state || -- 2.25.1 diff --git a/build/patches/Do-not-compile-QR-code-sharing.patch b/build/patches/Do-not-compile-QR-code-sharing.patch index 2d9515e1..85c594f4 100644 --- a/build/patches/Do-not-compile-QR-code-sharing.patch +++ b/build/patches/Do-not-compile-QR-code-sharing.patch @@ -4,18 +4,29 @@ Subject: Do not compile QR code sharing License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- + chrome/android/BUILD.gn | 1 - .../chrome/browser/ui/RootUiCoordinator.java | 5 ----- chrome/browser/share/BUILD.gn | 2 -- - chrome/browser/share/android/BUILD.gn | 1 - ...omeProvidedSharingOptionsProviderBase.java | 19 ------------------- .../qrcode/scan_tab/QrCodeScanMediator.java | 11 ----------- chrome/browser/share/android/java_sources.gni | 18 ------------------ 6 files changed, 56 deletions(-) +diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn +--- a/chrome/android/BUILD.gn ++++ b/chrome/android/BUILD.gn +@@ -3304,7 +3304,6 @@ generate_jni("chrome_jni_headers") { + "../browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextBridge.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabService.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabServiceFactory.java", +- "../browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QRCodeGenerationRequest.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/EditorScreenshotTask.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/MetricsRecorder.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java", diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java -@@ -107,7 +107,6 @@ import org.chromium.chrome.browser.share.ShareButtonController; +@@ -111,7 +111,6 @@ import org.chromium.chrome.browser.share.ShareButtonController; import org.chromium.chrome.browser.share.ShareDelegate; import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin; import org.chromium.chrome.browser.share.ShareUtils; @@ -23,7 +34,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi import org.chromium.chrome.browser.share.scroll_capture.ScrollCaptureManager; import org.chromium.chrome.browser.tab.AccessibilityVisibilityHandler; import org.chromium.chrome.browser.tab.AutofillSessionLifetimeController; -@@ -527,10 +526,6 @@ public class RootUiCoordinator +@@ -534,10 +533,6 @@ public class RootUiCoordinator } public void onAttachFragment(Fragment fragment) { @@ -46,17 +57,6 @@ diff --git a/chrome/browser/share/BUILD.gn b/chrome/browser/share/BUILD.gn ] deps += [ ":jni_headers", -diff --git a/chrome/browser/share/android/BUILD.gn b/chrome/browser/share/android/BUILD.gn ---- a/chrome/browser/share/android/BUILD.gn -+++ b/chrome/browser/share/android/BUILD.gn -@@ -40,7 +40,6 @@ generate_jni("jni_headers") { - "java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextBridge.java", - "java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabService.java", - "java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabServiceFactory.java", -- "java/src/org/chromium/chrome/browser/share/qrcode/QRCodeGenerationRequest.java", - "java/src/org/chromium/chrome/browser/share/screenshot/EditorScreenshotTask.java", - "java/src/org/chromium/chrome/browser/share/send_tab_to_self/MetricsRecorder.java", - "java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java", diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java diff --git a/build/patches/Do-not-hide-component-extensions.patch b/build/patches/Do-not-hide-component-extensions.patch index f9271eb1..129c04de 100644 --- a/build/patches/Do-not-hide-component-extensions.patch +++ b/build/patches/Do-not-hide-component-extensions.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc -@@ -73,7 +73,8 @@ AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP; +@@ -74,7 +74,8 @@ AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP; // Returns true if the extension should be exposed via the chrome.management // API. bool ShouldExposeViaManagementAPI(const Extension& extension) { diff --git a/build/patches/Do-not-link-with-libatomic.patch b/build/patches/Do-not-link-with-libatomic.patch index e2020c68..cf44637f 100644 --- a/build/patches/Do-not-link-with-libatomic.patch +++ b/build/patches/Do-not-link-with-libatomic.patch @@ -14,7 +14,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/base/BUILD.gn b/base/BUILD.gn --- a/base/BUILD.gn +++ b/base/BUILD.gn -@@ -1152,7 +1152,7 @@ component("base") { +@@ -1114,7 +1114,7 @@ component("base") { # more robust check for this. if (!use_sysroot && (is_android || is_chromeos || (is_linux && !is_castos)) && host_toolchain != "//build/toolchain/cros:host") { diff --git a/build/patches/Do-not-store-passwords-by-default.patch b/build/patches/Do-not-store-passwords-by-default.patch index 62b3c3b1..69dab871 100644 --- a/build/patches/Do-not-store-passwords-by-default.patch +++ b/build/patches/Do-not-store-passwords-by-default.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc -@@ -257,14 +257,14 @@ base::CallbackListSubscription AddSyncEnabledOrDisabledCallback( +@@ -237,14 +237,14 @@ base::CallbackListSubscription AddSyncEnabledOrDisabledCallback( void PasswordManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref( @@ -27,7 +27,7 @@ diff --git a/components/password_manager/core/browser/password_manager.cc b/comp user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); registry->RegisterStringPref(prefs::kSyncPasswordHash, std::string(), PrefRegistry::NO_REGISTRATION_FLAGS); -@@ -307,9 +307,9 @@ void PasswordManager::RegisterProfilePrefs( +@@ -287,9 +287,9 @@ void PasswordManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref(prefs::kPasswordsPrefWithNewLabelUsed, false); #if BUILDFLAG(IS_ANDROID) diff --git a/build/patches/DoH-improvements.patch b/build/patches/DoH-improvements.patch index 5604952b..7281c4a7 100644 --- a/build/patches/DoH-improvements.patch +++ b/build/patches/DoH-improvements.patch @@ -82,7 +82,7 @@ diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc -@@ -3141,6 +3141,7 @@ void HostResolverManager::SetDnsConfigOverrides(DnsConfigOverrides overrides) { +@@ -3149,6 +3149,7 @@ void HostResolverManager::SetDnsConfigOverrides(DnsConfigOverrides overrides) { bool changed = dns_client_->SetConfigOverrides(std::move(overrides)); if (changed) { diff --git a/build/patches/Enable-Certificate-Transparency.patch b/build/patches/Enable-Certificate-Transparency.patch index fb4785f7..c4846e78 100644 --- a/build/patches/Enable-Certificate-Transparency.patch +++ b/build/patches/Enable-Certificate-Transparency.patch @@ -8,32 +8,30 @@ by default. License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/about_flags.cc | 7 +++++++ - chrome/browser/browser_features.cc | 4 ++-- - chrome/browser/flag_descriptions.cc | 4 ++++ - chrome/browser/flag_descriptions.h | 3 +++ - chrome/browser/net/system_network_context_manager.cc | 4 ---- - chrome/browser/ssl/sct_reporting_service.cc | 5 +++++ - chrome/common/chrome_features.cc | 6 +----- - net/http/transport_security_state.cc | 5 +++-- - net/url_request/report_sender.cc | 3 ++- - services/network/network_context.cc | 2 +- - services/network/sct_auditing/sct_auditing_handler.cc | 2 ++ - 11 files changed, 30 insertions(+), 15 deletions(-) + chrome/browser/about_flags.cc | 5 +++++ + chrome/browser/browser_features.cc | 13 +++++++------ + chrome/browser/flag_descriptions.cc | 4 ++++ + chrome/browser/flag_descriptions.h | 3 +++ + .../browser/net/system_network_context_manager.cc | 6 +----- + chrome/browser/ssl/sct_reporting_service.cc | 5 +++++ + chrome/common/chrome_features.cc | 10 ++-------- + net/http/transport_security_state.cc | 5 +++-- + net/url_request/report_sender.cc | 3 ++- + services/network/network_context.cc | 2 +- + .../network/sct_auditing/sct_auditing_handler.cc | 2 ++ + 11 files changed, 35 insertions(+), 23 deletions(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9399,6 +9399,13 @@ const FeatureEntry kFeatureEntries[] = { +@@ -9516,6 +9516,11 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kWebMidiDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebMidi)}, -+#if BUILDFLAG(IS_ANDROID) + {"certificate-transparency-enabled", + flag_descriptions::kCTEnabledName, -+ flag_descriptions::kCTEnabledDescription, kOsAndroid, -+ FEATURE_VALUE_TYPE(features::kCertificateTransparencyAndroid)}, -+#endif ++ flag_descriptions::kCTEnabledDescription, kOsAll, ++ FEATURE_VALUE_TYPE(features::kCertificateTransparency)}, + #if BUILDFLAG(IS_CHROMEOS_ASH) {"dns-over-https-with-identifiers-reuse-old-policy", @@ -41,21 +39,37 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc -@@ -168,8 +168,8 @@ BASE_FEATURE(kWebUsbDeviceDetection, - #if BUILDFLAG(IS_ANDROID) - // Enables Certificate Transparency on Android. - BASE_FEATURE(kCertificateTransparencyAndroid, -- "CertificateTransparencyAndroid", -- base::FEATURE_ENABLED_BY_DEFAULT); -+ "CertificateTransparencyAndroid", // must be enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite +@@ -71,6 +71,11 @@ BASE_FEATURE(kEnableUniveralLinks, + base::FEATURE_ENABLED_BY_DEFAULT); #endif ++// Enables Certificate Transparency ++BASE_FEATURE(kCertificateTransparency, ++ "CertificateTransparency", // must be enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ + #if BUILDFLAG(IS_CHROMEOS_ASH) + // Enables reading and writing PWA notification permissions from quick settings + // menu. +@@ -171,12 +176,8 @@ BASE_FEATURE(kWebUsbDeviceDetection, + // update the list of accepted logs. Embedders who are planning to enable this + // should first reach out to chrome-certificate-transparency@google.com. + BASE_FEATURE(kCertificateTransparencyAskBeforeEnabling, +- "CertificateTransparencyAskBeforeEnabling", +-#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +- base::FEATURE_ENABLED_BY_DEFAULT); +-#else +- base::FEATURE_DISABLED_BY_DEFAULT); +-#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) ++ "CertificateTransparencyAskBeforeEnabling", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // by default + BASE_FEATURE(kLargeFaviconFromGoogle, + "LargeFaviconFromGoogle", diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -7363,6 +7363,10 @@ const char kAutofillCreditCardUploadDescription[] = +@@ -7547,6 +7547,10 @@ const char kAutofillCreditCardUploadDescription[] = #endif // defined(TOOLKIT_VIEWS) || BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) @@ -69,7 +83,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -4261,6 +4261,9 @@ extern const char kAutofillCreditCardUploadDescription[]; +@@ -4369,6 +4369,9 @@ extern const char kAutofillCreditCardUploadDescription[]; #endif // defined(TOOLKIT_VIEWS) || BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) @@ -82,21 +96,23 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc -@@ -901,7 +901,6 @@ void SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting( +@@ -909,7 +909,6 @@ void SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting( bool SystemNetworkContextManager::IsCertificateTransparencyEnabled() { if (certificate_transparency_enabled_for_testing_.has_value()) return certificate_transparency_enabled_for_testing_.value(); --#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && defined(OFFICIAL_BUILD) - // TODO(carlosil): Figure out if we can/should remove the OFFICIAL_BUILD and - // GOOGLE_CHROME_BRANDING checks now that enforcement does not rely on build - // dates, and allow embedders to enforce. -@@ -915,9 +914,6 @@ bool SystemNetworkContextManager::IsCertificateTransparencyEnabled() { - #else - return true; - #endif // BUILDFLAG(IS_ANDROID) +-#if defined(OFFICIAL_BUILD) + // TODO(carlosil): Figure out if we can/should remove the OFFICIAL_BUILD + // check now that enforcement does not rely on build dates. + // Certificate Transparency is enabled: +@@ -917,10 +916,7 @@ bool SystemNetworkContextManager::IsCertificateTransparencyEnabled() { + // - on an opt-in basis for other builds and embedders, controlled with the + // kCertificateTransparencyAskBeforeEnabling flag + return base::FeatureList::IsEnabled( +- features::kCertificateTransparencyAskBeforeEnabling); -#else - return false; --#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) && defined(OFFICIAL_BUILD) +-#endif // defined(OFFICIAL_BUILD) ++ features::kCertificateTransparency); } #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL) @@ -118,19 +134,33 @@ diff --git a/chrome/browser/ssl/sct_reporting_service.cc b/chrome/browser/ssl/sc diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -1025,11 +1025,7 @@ BASE_FEATURE(kSchedulerConfiguration, +@@ -1070,15 +1070,9 @@ BASE_FEATURE(kSchedulerConfiguration, + base::FEATURE_DISABLED_BY_DEFAULT); + #endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Controls whether SCT audit reports are queued and the rate at which they - // should be sampled. Default sampling rate is 1/10,000 certificates. --#if BUILDFLAG(IS_ANDROID) --BASE_FEATURE(kSCTAuditing, "SCTAuditing", base::FEATURE_DISABLED_BY_DEFAULT); --#else +-// Controls whether SCT audit reports are queued and the rate at which they +-// should be sampled. Default sampling rate is 1/10,000 certificates. +-#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_ANDROID) -BASE_FEATURE(kSCTAuditing, "SCTAuditing", base::FEATURE_ENABLED_BY_DEFAULT); +-#else + // This requires backend infrastructure and a data collection policy. + // Non-Chrome builds should not use Chrome's infrastructure. + BASE_FEATURE(kSCTAuditing, "SCTAuditing", base::FEATURE_DISABLED_BY_DEFAULT); -#endif -+BASE_FEATURE(kSCTAuditing, "SCTAuditing", base::FEATURE_DISABLED_BY_DEFAULT); // disabled in Bromite constexpr base::FeatureParam kSCTAuditingSamplingRate{ &kSCTAuditing, "sampling_rate", 0.0001}; +@@ -1087,8 +1081,8 @@ constexpr base::FeatureParam kSCTAuditingSamplingRate{ + // about an SCT seen in the wild. If it hasn't been seen, then it is considered + // a security incident and uploaded to Google. + BASE_FEATURE(kSCTAuditingHashdance, +- "SCTAuditingHashdance", +- base::FEATURE_ENABLED_BY_DEFAULT); ++ "SCTAuditingHashdance", // disabled ++ base::FEATURE_DISABLED_BY_DEFAULT); // by default + + // An estimated high bound for the time it takes Google to ingest updates to an + // SCT log. Chrome will wait for at least this time plus the Log's Maximum Merge diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc @@ -169,7 +199,7 @@ diff --git a/net/url_request/report_sender.cc b/net/url_request/report_sender.cc diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -2624,7 +2624,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( +@@ -2684,7 +2684,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( // TransportSecurityState. Since no requests have been made yet, safe to do // this even after the call to Build(). diff --git a/build/patches/Enable-ECH-by-default.patch b/build/patches/Enable-ECH-by-default.patch index 1e6f7aa7..a1c38762 100644 --- a/build/patches/Enable-ECH-by-default.patch +++ b/build/patches/Enable-ECH-by-default.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -87,12 +87,12 @@ BASE_FEATURE(kEnableTLS13EarlyData, +@@ -96,12 +96,12 @@ BASE_FEATURE(kEnableTLS13EarlyData, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kEncryptedClientHello, diff --git a/build/patches/Enable-HEVC-by-default.patch b/build/patches/Enable-HEVC-by-default.patch index 9a683f5a..67de0a49 100644 --- a/build/patches/Enable-HEVC-by-default.patch +++ b/build/patches/Enable-HEVC-by-default.patch @@ -21,7 +21,7 @@ diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc + "PlatformHEVCDecoderSupport", // must be enabled + base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) - // Enables HEVC hardware accelerated encoding for Windows and Mac. + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID) + // Enables HEVC hardware accelerated encoding for Windows, Mac, and Android. -- 2.25.1 diff --git a/build/patches/Enable-PermuteTLSExtensions-by-default.patch b/build/patches/Enable-PermuteTLSExtensions-by-default.patch index fef6d579..303ec0c4 100644 --- a/build/patches/Enable-PermuteTLSExtensions-by-default.patch +++ b/build/patches/Enable-PermuteTLSExtensions-by-default.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -148,8 +148,8 @@ BASE_FEATURE(kTLS13KeyUpdate, +@@ -163,8 +163,8 @@ BASE_FEATURE(kTLS13KeyUpdate, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kPermuteTLSExtensions, diff --git a/build/patches/Enable-StrictOriginIsolation-and-SitePerProcess.patch b/build/patches/Enable-StrictOriginIsolation-and-SitePerProcess.patch index db957536..ed1abf05 100644 --- a/build/patches/Enable-StrictOriginIsolation-and-SitePerProcess.patch +++ b/build/patches/Enable-StrictOriginIsolation-and-SitePerProcess.patch @@ -19,7 +19,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -4768,9 +4768,6 @@ const FeatureEntry kFeatureEntries[] = { +@@ -4827,9 +4827,6 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kSiteIsolationForPasswordSitesDescription, kOsAndroid, FEATURE_VALUE_TYPE( site_isolation::features::kSiteIsolationForPasswordSites)}, @@ -32,7 +32,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -1572,7 +1572,7 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs( +@@ -1580,7 +1580,7 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs( registry->RegisterFilePathPref(prefs::kDiskCacheDir, base::FilePath()); registry->RegisterIntegerPref(prefs::kDiskCacheSize, 0); registry->RegisterStringPref(prefs::kIsolateOrigins, std::string()); @@ -41,7 +41,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch registry->RegisterBooleanPref(prefs::kTabFreezingEnabled, true); registry->RegisterIntegerPref(prefs::kSCTAuditingHashdanceReportCount, 0); registry->RegisterBooleanPref( -@@ -1594,7 +1594,7 @@ void ChromeContentBrowserClient::RegisterProfilePrefs( +@@ -1603,7 +1603,7 @@ void ChromeContentBrowserClient::RegisterProfilePrefs( // user policy in addition to the same named ones in Local State (which are // used for mapping the command-line flags). registry->RegisterStringPref(prefs::kIsolateOrigins, std::string()); @@ -53,7 +53,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc -@@ -1076,12 +1076,8 @@ BASE_FEATURE(kSecurityKeyAttestationPrompt, +@@ -1120,12 +1120,8 @@ const base::FeatureParam kSCTLogMaxIngestionRandomDelay{ // TODO(alexmos): Move this and the other site isolation features below to // browser_features, as they are only used on the browser side. BASE_FEATURE(kSitePerProcess, @@ -98,7 +98,7 @@ diff --git a/components/site_isolation/site_isolation_policy.cc b/components/sit diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -1255,8 +1255,8 @@ BASE_FEATURE(kStopVideoCaptureOnScreenLock, +@@ -1251,8 +1251,8 @@ BASE_FEATURE(kStopVideoCaptureOnScreenLock, // Controls whether site isolation should use origins instead of scheme and // eTLD+1. BASE_FEATURE(kStrictOriginIsolation, diff --git a/build/patches/Enable-darken-websites-checkbox-in-themes.patch b/build/patches/Enable-darken-websites-checkbox-in-themes.patch index f03edb84..6fdbf4bc 100644 --- a/build/patches/Enable-darken-websites-checkbox-in-themes.patch +++ b/build/patches/Enable-darken-websites-checkbox-in-themes.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -1427,9 +1427,9 @@ +@@ -1512,9 +1512,9 @@ "expiry_milestone": 125 }, { diff --git a/build/patches/Enable-fwrapv-in-Clang-for-non-UBSan-builds.patch b/build/patches/Enable-fwrapv-in-Clang-for-non-UBSan-builds.patch index ebd1733e..33a966d3 100644 --- a/build/patches/Enable-fwrapv-in-Clang-for-non-UBSan-builds.patch +++ b/build/patches/Enable-fwrapv-in-Clang-for-non-UBSan-builds.patch @@ -45,7 +45,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -378,6 +378,10 @@ config("compiler") { +@@ -377,6 +377,10 @@ config("compiler") { } } diff --git a/build/patches/Enable-native-Android-autofill.patch b/build/patches/Enable-native-Android-autofill.patch index f892cf00..3d3024c5 100644 --- a/build/patches/Enable-native-Android-autofill.patch +++ b/build/patches/Enable-native-Android-autofill.patch @@ -54,8 +54,8 @@ diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -392,6 +392,7 @@ if (current_toolchain == default_toolchain) { - "//chrome/browser/ui/android/favicon:java", +@@ -405,6 +405,7 @@ if (current_toolchain == default_toolchain) { + "//chrome/browser/ui/android/hats:java", "//chrome/browser/ui/android/layouts:java", "//chrome/browser/ui/android/layouts/glue:java", + "//components/android_autofill/browser:java", @@ -65,7 +65,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java -@@ -60,6 +60,11 @@ import java.lang.annotation.Retention; +@@ -62,6 +62,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Locale; @@ -77,7 +77,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage /** * The "Passwords" screen in Settings, which allows the user to enable or disable password saving, * to view saved passwords (just the username and URL), and to delete saved passwords. -@@ -67,7 +72,7 @@ import java.util.Locale; +@@ -69,7 +74,7 @@ import java.util.Locale; public class PasswordSettings extends PreferenceFragmentCompat implements PasswordListObserver, Preference.OnPreferenceClickListener, SyncService.SyncStateChangedListener, FragmentHelpAndFeedbackLauncher, @@ -86,7 +86,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage @IntDef({TrustedVaultBannerState.NOT_SHOWN, TrustedVaultBannerState.OFFER_OPT_IN, TrustedVaultBannerState.OPTED_IN}) @Retention(RetentionPolicy.SOURCE) -@@ -94,6 +99,12 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -96,6 +101,12 @@ public class PasswordSettings extends PreferenceFragmentCompat public static final String PREF_TRUSTED_VAULT_BANNER = "trusted_vault_banner"; public static final String PREF_KEY_MANAGE_ACCOUNT_LINK = "manage_account_link"; @@ -99,7 +99,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage private static final String PREF_KEY_CATEGORY_SAVED_PASSWORDS = "saved_passwords"; private static final String PREF_KEY_CATEGORY_EXCEPTIONS = "exceptions"; private static final String PREF_KEY_SAVED_PASSWORDS_NO_TEXT = "saved_passwords_no_text"; -@@ -129,6 +140,8 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -128,6 +139,8 @@ public class PasswordSettings extends PreferenceFragmentCompat private Preference mLinkPref; private Menu mMenu; @@ -108,7 +108,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage private @ManagePasswordsReferrer int mManagePasswordsReferrer; private HelpAndFeedbackLauncher mHelpAndFeedbackLauncher; private Profile mProfile; -@@ -304,6 +317,7 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -303,6 +316,7 @@ public class PasswordSettings extends PreferenceFragmentCompat } createSavePasswordsSwitch(); @@ -116,7 +116,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage createAutoSignInCheckbox(); if (mTrustedVaultBannerState == TrustedVaultBannerState.OPTED_IN) { -@@ -557,6 +571,71 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -556,6 +570,71 @@ public class PasswordSettings extends PreferenceFragmentCompat getPrefService().getBoolean(Pref.CREDENTIALS_ENABLE_SERVICE)); } @@ -218,7 +218,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.jav /** * Creates an instance of a {@link TabImpl}. * -@@ -795,6 +808,11 @@ public class TabImpl implements Tab { +@@ -798,6 +811,11 @@ public class TabImpl implements Tab { for (TabObserver observer : mObservers) observer.onDestroyed(this); mObservers.clear(); @@ -230,7 +230,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.jav mUserDataHost.destroy(); mTabViewManager.destroy(); hideNativePage(false, null); -@@ -1400,6 +1418,16 @@ public class TabImpl implements Tab { +@@ -1386,6 +1404,16 @@ public class TabImpl implements Tab { return tabsPtrArray; } @@ -247,7 +247,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.jav /** * Initializes the {@link WebContents}. Completes the browser content components initialization * around a native WebContents pointer. -@@ -1449,6 +1477,28 @@ public class TabImpl implements Tab { +@@ -1435,6 +1463,28 @@ public class TabImpl implements Tab { mDelegateFactory.createContextMenuPopulatorFactory(this), this)); mWebContents.notifyRendererPreferenceUpdate(); @@ -287,7 +287,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.jav diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java -@@ -22,6 +22,10 @@ import org.chromium.ui.dragdrop.DragAndDropBrowserDelegate; +@@ -21,6 +21,10 @@ import org.chromium.ui.dragdrop.DragAndDropBrowserDelegate; import org.chromium.ui.dragdrop.DragAndDropDelegate; import org.chromium.ui.dragdrop.DragStateTracker; @@ -298,7 +298,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndr /** * Implementation of the abstract class {@link ViewAndroidDelegate} for Chrome. */ -@@ -87,6 +91,16 @@ public class TabViewAndroidDelegate extends ViewAndroidDelegate { +@@ -86,6 +90,16 @@ public class TabViewAndroidDelegate extends ViewAndroidDelegate { mTab.onBackgroundColorChanged(color); } @@ -318,7 +318,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndr diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -2528,6 +2528,13 @@ static_library("browser") { +@@ -2580,6 +2580,13 @@ static_library("browser") { deps += [ "//chrome/browser/error_reporting" ] } @@ -349,9 +349,9 @@ diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_ using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; using base::android::JavaParamRef; -@@ -504,3 +511,11 @@ static void JNI_TabImpl_Init(JNIEnv* env, const JavaParamRef& obj) { +@@ -506,3 +513,11 @@ static void JNI_TabImpl_Init(JNIEnv* env, // This will automatically bind to the Java object and pass ownership there. - new TabAndroid(env, obj); + new TabAndroid(env, obj, id); } + +void TabAndroid::InitializeAutofillIfNecessary(JNIEnv* env) { @@ -364,7 +364,7 @@ diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_ diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h --- a/chrome/browser/android/tab_android.h +++ b/chrome/browser/android/tab_android.h -@@ -167,6 +167,8 @@ class TabAndroid : public base::SupportsUserData { +@@ -169,6 +169,8 @@ class TabAndroid : public base::SupportsUserData { void SetDevToolsAgentHost(scoped_refptr host); @@ -376,7 +376,7 @@ diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_a diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -616,6 +616,12 @@ CHAR_LIMIT guidelines: +@@ -619,6 +619,12 @@ CHAR_LIMIT guidelines: Save passwords @@ -392,7 +392,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc -@@ -1188,7 +1188,13 @@ ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents) +@@ -1270,7 +1270,13 @@ ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents) web_contents, base::BindRepeating(&BrowserDriverInitHook, this, @@ -422,7 +422,7 @@ diff --git a/components/android_autofill/browser/android_autofill_manager.cc b/c diff --git a/components/android_autofill/browser/android_autofill_manager.h b/components/android_autofill/browser/android_autofill_manager.h --- a/components/android_autofill/browser/android_autofill_manager.h +++ b/components/android_autofill/browser/android_autofill_manager.h -@@ -85,12 +85,12 @@ class AndroidAutofillManager : public AutofillManager { +@@ -86,12 +86,12 @@ class AndroidAutofillManager : public AutofillManager { const FieldTypeGroup field_type_group, const url::Origin& triggered_origin); @@ -440,7 +440,7 @@ diff --git a/components/android_autofill/browser/android_autofill_manager.h b/co diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc --- a/components/autofill/content/browser/content_autofill_driver.cc +++ b/components/autofill/content/browser/content_autofill_driver.cc -@@ -400,6 +400,8 @@ void ContentAutofillDriver::FormsSeen( +@@ -406,6 +406,8 @@ void ContentAutofillDriver::FormsSeen( const std::vector& removed_forms) { target->autofill_manager_->OnFormsSeen(WithNewVersion(updated_forms), removed_forms); @@ -449,7 +449,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -427,6 +429,10 @@ void ContentAutofillDriver::FormSubmitted( +@@ -433,6 +435,10 @@ void ContentAutofillDriver::FormSubmitted( } target->autofill_manager_->OnFormSubmitted( WithNewVersion(form), known_success, submission_source); @@ -460,7 +460,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -448,6 +454,10 @@ void ContentAutofillDriver::TextFieldDidChange(const FormData& raw_form, +@@ -454,6 +460,10 @@ void ContentAutofillDriver::TextFieldDidChange(const FormData& raw_form, base::TimeTicks timestamp) { target->autofill_manager_->OnTextFieldDidChange( WithNewVersion(form), field, bounding_box, timestamp); @@ -471,7 +471,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -467,6 +477,10 @@ void ContentAutofillDriver::TextFieldDidScroll(const FormData& raw_form, +@@ -473,6 +483,10 @@ void ContentAutofillDriver::TextFieldDidScroll(const FormData& raw_form, const FormFieldData& field, const gfx::RectF& bounding_box) { target->autofill_manager_->OnTextFieldDidScroll(WithNewVersion(form), field, bounding_box); @@ -482,7 +482,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -487,6 +501,10 @@ void ContentAutofillDriver::SelectControlDidChange( +@@ -493,6 +507,10 @@ void ContentAutofillDriver::SelectControlDidChange( const FormFieldData& field, const gfx::RectF& bounding_box) { target->autofill_manager_->OnSelectControlDidChange( WithNewVersion(form), field, bounding_box); @@ -493,7 +493,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -509,6 +527,10 @@ void ContentAutofillDriver::AskForValuesToFill( +@@ -515,6 +533,10 @@ void ContentAutofillDriver::AskForValuesToFill( AutofillSuggestionTriggerSource trigger_source) { target->autofill_manager_->OnAskForValuesToFill( WithNewVersion(form), field, bounding_box, trigger_source); @@ -504,7 +504,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -520,12 +542,16 @@ void ContentAutofillDriver::HidePopup() { +@@ -526,12 +548,16 @@ void ContentAutofillDriver::HidePopup() { DCHECK(!target->IsPrerendering()) << "We should never affect UI while prerendering"; target->autofill_manager_->OnHidePopup(); @@ -521,7 +521,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co } void ContentAutofillDriver::FocusNoLongerOnForm(bool had_interacted_form) { -@@ -555,6 +581,10 @@ void ContentAutofillDriver::FocusOnFormField(const FormData& raw_form, +@@ -561,6 +587,10 @@ void ContentAutofillDriver::FocusOnFormField(const FormData& raw_form, const FormFieldData& field, const gfx::RectF& bounding_box) { target->autofill_manager_->OnFocusOnFormField(WithNewVersion(form), field, bounding_box); @@ -532,7 +532,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -569,6 +599,10 @@ void ContentAutofillDriver::DidFillAutofillFormData(const FormData& raw_form, +@@ -575,6 +605,10 @@ void ContentAutofillDriver::DidFillAutofillFormData(const FormData& raw_form, base::TimeTicks timestamp) { target->autofill_manager_->OnDidFillAutofillFormData( WithNewVersion(form), timestamp); @@ -543,7 +543,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -579,6 +613,8 @@ void ContentAutofillDriver::DidPreviewAutofillFormData() { +@@ -585,6 +619,8 @@ void ContentAutofillDriver::DidPreviewAutofillFormData() { autofill_router().DidPreviewAutofillFormData( this, [](ContentAutofillDriver* target) { target->autofill_manager_->OnDidPreviewAutofillFormData(); @@ -552,7 +552,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -589,6 +625,8 @@ void ContentAutofillDriver::DidEndTextFieldEditing() { +@@ -595,6 +631,8 @@ void ContentAutofillDriver::DidEndTextFieldEditing() { autofill_router().DidEndTextFieldEditing( this, [](ContentAutofillDriver* target) { target->autofill_manager_->OnDidEndTextFieldEditing(); @@ -561,18 +561,18 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -602,6 +640,10 @@ void ContentAutofillDriver::SelectFieldOptionsDidChange( +@@ -608,6 +646,10 @@ void ContentAutofillDriver::SelectOrSelectMenuFieldOptionsDidChange( [](ContentAutofillDriver* target, const FormData& form) { - target->autofill_manager_->OnSelectFieldOptionsDidChange( + target->autofill_manager_->OnSelectOrSelectMenuFieldOptionsDidChange( WithNewVersion(form)); + if (target->secondary_autofill_manager_) { -+ target->secondary_autofill_manager_->OnSelectFieldOptionsDidChange( ++ target->secondary_autofill_manager_->OnSelectOrSelectMenuFieldOptionsDidChange( + WithNewVersion(form)); + } }); } -@@ -621,6 +663,10 @@ void ContentAutofillDriver::JavaScriptChangedAutofilledValue( +@@ -627,6 +669,10 @@ void ContentAutofillDriver::JavaScriptChangedAutofilledValue( const FormFieldData& field, const std::u16string& old_value) { target->autofill_manager_->OnJavaScriptChangedAutofilledValue( WithNewVersion(form), field, old_value); @@ -583,7 +583,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co }); } -@@ -628,6 +674,8 @@ void ContentAutofillDriver::OnContextMenuShownInFieldCallback( +@@ -634,6 +680,8 @@ void ContentAutofillDriver::OnContextMenuShownInFieldCallback( const FormGlobalId& form_global_id, const FieldGlobalId& field_global_id) { autofill_manager_->OnContextMenuShownInField(form_global_id, field_global_id); @@ -592,7 +592,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/co } void ContentAutofillDriver::OnContextMenuShownInField( -@@ -649,6 +697,8 @@ void ContentAutofillDriver::Reset() { +@@ -655,6 +703,8 @@ void ContentAutofillDriver::Reset() { owner_->autofill_router().UnregisterDriver(this, /*driver_is_dying=*/false); autofill_manager_->Reset(); @@ -619,7 +619,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver.h b/com content::RenderFrameHost* render_frame_host() { return &*render_frame_host_; } const content::RenderFrameHost* render_frame_host() const { -@@ -336,6 +339,10 @@ class ContentAutofillDriver : public AutofillDriver, +@@ -339,6 +342,10 @@ class ContentAutofillDriver : public AutofillDriver, std::unique_ptr autofill_manager_ = nullptr; @@ -674,7 +674,7 @@ diff --git a/components/autofill/content/browser/content_autofill_driver_factory diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc -@@ -779,7 +779,10 @@ void PasswordAutofillAgent::UpdateStateForTextChange( +@@ -822,7 +822,10 @@ void PasswordAutofillAgent::UpdateStateForTextChange( void PasswordAutofillAgent::TrackAutofilledElement( const blink::WebFormControlElement& element) { @@ -689,9 +689,9 @@ diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/c diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc --- a/components/autofill/core/common/autofill_prefs.cc +++ b/components/autofill/core/common/autofill_prefs.cc -@@ -126,6 +126,10 @@ const char kAutofillPaymentMethodsMandatoryReauthPromoShownCounter[] = - "autofill.payment_methods_mandatory_reauth_promo_counter"; - #endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) +@@ -133,6 +133,10 @@ const char kAutofillUsingVirtualViewStructure[] = + "autofill.using_virtual_view_structure"; + #endif // BUILDFLAG(IS_ANDROID) +// Boolean that is true to enable native Android Autofill +const char kAutofillAndroidEnabled[] = "autofill.android_autofill_enabled"; @@ -700,10 +700,10 @@ diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/auto void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { // Synced prefs. Used for cross-device choices, e.g., credit card Autofill. registry->RegisterBooleanPref( -@@ -158,6 +162,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { +@@ -164,6 +168,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref( prefs::kAutofillCreditCardFidoAuthOfferCheckboxState, true); #endif - registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true); + registry->RegisterBooleanPref(prefs::kAutofillAndroidEnabled, true); + registry->RegisterBooleanPref(prefs::kAutofillAndroidIncognitoEnabled, false); registry->RegisterIntegerPref( @@ -712,9 +712,9 @@ diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/auto diff --git a/components/autofill/core/common/autofill_prefs.h b/components/autofill/core/common/autofill_prefs.h --- a/components/autofill/core/common/autofill_prefs.h +++ b/components/autofill/core/common/autofill_prefs.h -@@ -46,6 +46,8 @@ extern const char kAutofillUploadEvents[]; +@@ -43,6 +43,8 @@ extern const char kAutofillUploadEncodingSeed[]; + extern const char kAutofillUploadEvents[]; extern const char kAutofillUploadEventsLastResetTimestamp[]; - extern const char kAutofillWalletImportEnabled[]; extern const char kAutocompleteLastVersionRetentionPolicy[]; +extern const char kAutofillAndroidEnabled[]; +extern const char kAutofillAndroidIncognitoEnabled[]; @@ -792,7 +792,7 @@ diff --git a/components/embedder_support/android/java/src/org/chromium/component diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java --- a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java +++ b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java -@@ -29,6 +29,10 @@ import org.chromium.ui.dragdrop.DragStateTracker; +@@ -30,6 +30,10 @@ import org.chromium.ui.dragdrop.DragStateTracker; import org.chromium.ui.dragdrop.DropDataAndroid; import org.chromium.ui.mojom.CursorType; @@ -803,9 +803,9 @@ diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java b /** * Class to acquire, position, and remove anchor views from the implementing View. */ -@@ -620,4 +624,8 @@ public class ViewAndroidDelegate { - public static void setDragAndDropDelegateForTest(DragAndDropDelegate testDelegate) { - sDragAndDropTestDelegate = testDelegate; +@@ -621,4 +625,8 @@ public class ViewAndroidDelegate { + sDragAndDropDelegateForTesting = testDelegate; + ResettersForTesting.register(() -> sDragAndDropDelegateForTesting = null); } + + public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {} diff --git a/build/patches/Enable-network-isolation-features.patch b/build/patches/Enable-network-isolation-features.patch index c236c8b7..d372762d 100644 --- a/build/patches/Enable-network-isolation-features.patch +++ b/build/patches/Enable-network-isolation-features.patch @@ -9,75 +9,88 @@ PartitionNelAndReportingByNetworkIsolationKey License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - net/base/features.cc | 48 ++++++++++++------------- + net/base/features.cc | 68 ++++++++++++------------- services/network/public/cpp/features.cc | 2 +- - 2 files changed, 25 insertions(+), 25 deletions(-) + 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -99,37 +99,37 @@ BASE_FEATURE(kSplitCacheByIncludeCredentials, +@@ -108,40 +108,40 @@ BASE_FEATURE(kSplitCacheByIncludeCredentials, "SplitCacheByIncludeCredentials", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kSplitCacheByNetworkIsolationKey, - "SplitCacheByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kSplitCacheByNetworkIsolationKey, // must be enabled -+ "SplitCacheByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kSplitCodeCacheByNetworkIsolationKey, - "SplitCodeCacheByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kSplitCodeCacheByNetworkIsolationKey, // must be enabled -+ "SplitCodeCacheByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kSplitHostCacheByNetworkIsolationKey, - "SplitHostCacheByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kSplitHostCacheByNetworkIsolationKey, // must be -+ "SplitHostCacheByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kPartitionConnectionsByNetworkIsolationKey, - "PartitionConnectionsByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kPartitionConnectionsByNetworkIsolationKey, // must be -+ "PartitionConnectionsByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kPartitionHttpServerPropertiesByNetworkIsolationKey, - "PartitionHttpServerPropertiesByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kPartitionHttpServerPropertiesByNetworkIsolationKey, // must be -+ "PartitionHttpServerPropertiesByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kPartitionSSLSessionsByNetworkIsolationKey, - "PartitionSSLSessionsByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kPartitionSSLSessionsByNetworkIsolationKey, // must be -+ "PartitionSSLSessionsByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey, - "PartitionNelAndReportingByNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey, // must be -+ "PartitionNelAndReportingByNetworkIsolationKey", // enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite - +- -BASE_FEATURE(kEnableCrossSiteFlagNetworkIsolationKey, - "EnableCrossSiteFlagNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); +-BASE_FEATURE(kEnableFrameSiteSharedOpaqueNetworkIsolationKey, +- "EnableFrameSiteSharedOpaqueNetworkIsolationKey", +- base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kSplitCacheByNetworkIsolationKey, // must be enabled ++ "SplitCacheByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kSplitCodeCacheByNetworkIsolationKey, // must be enabled ++ "SplitCodeCacheByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kSplitHostCacheByNetworkIsolationKey, // must be ++ "SplitHostCacheByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kPartitionConnectionsByNetworkIsolationKey, // must be ++ "PartitionConnectionsByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kPartitionHttpServerPropertiesByNetworkIsolationKey, // must be ++ "PartitionHttpServerPropertiesByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kPartitionSSLSessionsByNetworkIsolationKey, // must be ++ "PartitionSSLSessionsByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ ++BASE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey, // must be ++ "PartitionNelAndReportingByNetworkIsolationKey", // enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // in Bromite ++ +BASE_FEATURE(kEnableCrossSiteFlagNetworkIsolationKey, // must be + "EnableCrossSiteFlagNetworkIsolationKey", // disabled + base::FEATURE_DISABLED_BY_DEFAULT); // in Bromite - - BASE_FEATURE(kTLS13KeyUpdate, - "TLS13KeyUpdate", ++BASE_FEATURE(kEnableFrameSiteSharedOpaqueNetworkIsolationKey, // must be ++ "EnableFrameSiteSharedOpaqueNetworkIsolationKey", // disabled ++ base::FEATURE_DISABLED_BY_DEFAULT); // in Bromite + BASE_FEATURE(kHttpCacheKeyingExperimentControlGroup, + "HttpCacheKeyingExperimentControlGroup", + base::FEATURE_DISABLED_BY_DEFAULT); diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc diff --git a/build/patches/Enable-prefetch-privacy-changes-by-default.patch b/build/patches/Enable-prefetch-privacy-changes-by-default.patch index d73e18a2..31729659 100644 --- a/build/patches/Enable-prefetch-privacy-changes-by-default.patch +++ b/build/patches/Enable-prefetch-privacy-changes-by-default.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1221,8 +1221,8 @@ BASE_FEATURE(kPrefetchFontLookupTables, +@@ -1308,8 +1308,8 @@ BASE_FEATURE(kPrefetchFontLookupTables, // Prefetch request properties are updated to be privacy-preserving. See // crbug.com/988956. BASE_FEATURE(kPrefetchPrivacyChanges, diff --git a/build/patches/Enable-share-intent.patch b/build/patches/Enable-share-intent.patch index fa76f141..027d57ba 100644 --- a/build/patches/Enable-share-intent.patch +++ b/build/patches/Enable-share-intent.patch @@ -32,7 +32,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -603,6 +603,7 @@ chrome_java_resources = [ +@@ -607,6 +607,7 @@ chrome_java_resources = [ "java/res/layout/signin_activity.xml", "java/res/layout/status_indicator_container.xml", "java/res/layout/suggestions_tile_view_condensed.xml", @@ -43,7 +43,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -1013,6 +1013,7 @@ chrome_java_sources = [ +@@ -1023,6 +1023,7 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java", "java/src/org/chromium/chrome/browser/signin/SyncConsentActivityLauncherImpl.java", "java/src/org/chromium/chrome/browser/signin/SyncConsentFragment.java", @@ -54,7 +54,7 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml -@@ -243,12 +243,6 @@ by a child template that "extends" this file. +@@ -241,12 +241,6 @@ by a child template that "extends" this file. @@ -67,7 +67,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro -@@ -374,6 +368,24 @@ by a child template that "extends" this file. +@@ -361,6 +355,24 @@ by a child template that "extends" this file. @@ -187,7 +187,7 @@ new file mode 100644 diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java -@@ -210,6 +210,9 @@ public class IntentHandler { +@@ -209,6 +209,9 @@ public class IntentHandler { private static final String EXTRA_TAB_LAUNCH_TYPE = "org.chromium.chrome.browser.tab_launch_type"; @@ -197,7 +197,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j /** * A hash code for the URL to verify intent data hasn't been modified. */ -@@ -1517,6 +1520,17 @@ public class IntentHandler { +@@ -1504,6 +1507,17 @@ public class IntentHandler { return IntentUtils.safeGetSerializableExtra(intent, EXTRA_TAB_LAUNCH_TYPE); } @@ -215,7 +215,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j /** * Creates an Intent that will launch a ChromeTabbedActivity on the new tab page. The Intent * will be trusted and therefore able to launch Incognito tabs. -@@ -1641,7 +1655,7 @@ public class IntentHandler { +@@ -1628,7 +1642,7 @@ public class IntentHandler { String headers = getExtraHeadersFromIntent(intent); headers = maybeAddAdditionalContentHeaders(intent, url, headers); @@ -227,7 +227,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.j diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java -@@ -465,8 +465,8 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega +@@ -425,8 +425,8 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega /*incognito*/true); newIntent.setData(mIntent.getData()); newIntent.setPackage(applicationContext.getPackageName()); @@ -384,7 +384,7 @@ new file mode 100644 diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9802,6 +9802,10 @@ const FeatureEntry kFeatureEntries[] = { +@@ -9891,6 +9891,10 @@ const FeatureEntry kFeatureEntries[] = { features::kBrokerFileOperationsOnDiskCacheInNetworkService)}, #if BUILDFLAG(IS_ANDROID) @@ -398,7 +398,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3119,6 +3119,11 @@ const char kIsolateOriginsDescription[] = +@@ -3181,6 +3181,11 @@ const char kIsolateOriginsDescription[] = "Requires dedicated processes for an additional set of origins, " "specified as a comma-separated list."; @@ -413,7 +413,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1779,6 +1779,9 @@ extern const char kIsolateOriginsDescription[]; +@@ -1828,6 +1828,9 @@ extern const char kIsolateOriginsDescription[]; extern const char kIsolationByDefaultName[]; extern const char kIsolationByDefaultDescription[]; @@ -426,7 +426,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -271,6 +271,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -278,6 +278,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kReengagementNotification, &kSearchReadyOmniboxFeature, &kRelatedSearches, @@ -434,7 +434,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &kReportParentalControlSitesChild, &kRequestDesktopSiteDefaults, &kRequestDesktopSiteDefaultsControl, -@@ -974,6 +975,10 @@ BASE_FEATURE(kScrollToTLDOptimization, +@@ -992,6 +993,10 @@ BASE_FEATURE(kScrollToTLDOptimization, "ScrollToTLDOptimization", base::FEATURE_DISABLED_BY_DEFAULT); @@ -448,8 +448,8 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -156,6 +156,7 @@ BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsLogging); - BASE_DECLARE_FEATURE(kRequestDesktopSitePerSiteIph); +@@ -164,6 +164,7 @@ BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsDowngrade); + BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsLogging); BASE_DECLARE_FEATURE(kRestoreTabsOnFRE); BASE_DECLARE_FEATURE(kSearchReadyOmniboxFeature); +BASE_DECLARE_FEATURE(kSharedIntentUI); @@ -459,9 +459,9 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -381,6 +381,7 @@ public abstract class ChromeFeatureList { - public static final String QUIET_NOTIFICATION_PROMPTS = "QuietNotificationPrompts"; +@@ -391,6 +391,7 @@ public abstract class ChromeFeatureList { public static final String REACHED_CODE_PROFILER = "ReachedCodeProfiler"; + public static final String READALOUD = "ReadAloud"; public static final String READER_MODE_IN_CCT = "ReaderModeInCCT"; + public static final String SHARED_INTENT_UI = "SharedIntentUI"; public static final String RECORD_SUPPRESSION_METRICS = "RecordSuppressionMetrics"; @@ -470,7 +470,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -5088,6 +5088,19 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

diff --git a/build/patches/Enable-third-party-storage-partitioning.patch b/build/patches/Enable-third-party-storage-partitioning.patch index 6ade4216..b85ce6e6 100644 --- a/build/patches/Enable-third-party-storage-partitioning.patch +++ b/build/patches/Enable-third-party-storage-partitioning.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/net/base/features.cc b/net/base/features.cc --- a/net/base/features.cc +++ b/net/base/features.cc -@@ -278,8 +278,8 @@ BASE_FEATURE(kBlockSetCookieHeader, +@@ -294,8 +294,8 @@ BASE_FEATURE(kBlockSetCookieHeader, // Enables partitioning of third party storage (IndexedDB, CacheStorage, etc.) // by the top level site to reduce fingerprinting. BASE_FEATURE(kThirdPartyStoragePartitioning, diff --git a/build/patches/Experimental-user-scripts-support.patch b/build/patches/Experimental-user-scripts-support.patch index 9778b402..eb0fc351 100644 --- a/build/patches/Experimental-user-scripts-support.patch +++ b/build/patches/Experimental-user-scripts-support.patch @@ -32,22 +32,22 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../browser/download/DownloadUtils.java | 6 + .../init/ProcessInitializationHandler.java | 3 + chrome/android/java_sources.gni | 3 + - chrome/browser/BUILD.gn | 5 + - chrome/browser/about_flags.cc | 5 + + chrome/browser/BUILD.gn | 7 + + chrome/browser/about_flags.cc | 7 + chrome/browser/flag_descriptions.cc | 5 + chrome/browser/flag_descriptions.h | 3 + - chrome/browser/prefs/browser_prefs.cc | 2 + - chrome/browser/profiles/BUILD.gn | 1 + - ...hrome_browser_main_extra_parts_profiles.cc | 3 + - chrome/browser/profiles/profile_manager.cc | 9 + - chrome/browser/profiles/renderer_updater.cc | 10 +- - chrome/browser/profiles/renderer_updater.h | 1 + - .../webui/chrome_web_ui_controller_factory.cc | 3 + + chrome/browser/prefs/browser_prefs.cc | 4 + + chrome/browser/profiles/BUILD.gn | 3 + + ...hrome_browser_main_extra_parts_profiles.cc | 7 + + chrome/browser/profiles/profile_manager.cc | 13 + + chrome/browser/profiles/renderer_updater.cc | 19 +- + chrome/browser/profiles/renderer_updater.h | 3 + + .../webui/chrome_web_ui_controller_factory.cc | 5 + chrome/chrome_paks.gni | 2 + chrome/common/renderer_configuration.mojom | 1 + - chrome/renderer/BUILD.gn | 1 + - .../chrome_content_renderer_client.cc | 37 + - .../renderer/chrome_render_thread_observer.cc | 3 + + chrome/renderer/BUILD.gn | 6 + + .../chrome_content_renderer_client.cc | 55 ++ + .../renderer/chrome_render_thread_observer.cc | 5 + components/components_strings.grd | 1 + components/user_scripts/README.md | 150 ++++ components/user_scripts/android/BUILD.gn | 83 ++ @@ -135,7 +135,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../renderer/web_ui_injection_host.h | 27 + .../strings/userscripts_strings.grdp | 54 ++ tools/gritsettings/resource_ids.spec | 6 + - 108 files changed, 9435 insertions(+), 1 deletion(-) + 108 files changed, 9489 insertions(+), 1 deletion(-) create mode 100644 components/user_scripts/README.md create mode 100755 components/user_scripts/android/BUILD.gn create mode 100644 components/user_scripts/android/java/res/layout/accept_script_item.xml @@ -225,7 +225,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -236,6 +236,9 @@ if (current_toolchain == default_toolchain) { +@@ -241,6 +241,9 @@ if (current_toolchain == default_toolchain) { "//third_party/androidx:androidx_gridlayout_gridlayout_java", "//third_party/androidx:androidx_preference_preference_java", ] @@ -235,7 +235,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn } android_library("app_hooks_java") { -@@ -540,6 +543,7 @@ if (current_toolchain == default_toolchain) { +@@ -556,6 +559,7 @@ if (current_toolchain == default_toolchain) { "//components/ukm/android:java", "//components/url_formatter/android:url_formatter_java", "//components/user_prefs/android:java", @@ -246,7 +246,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml -@@ -111,6 +111,11 @@ found in the LICENSE file. +@@ -115,6 +115,11 @@ android:key="useragent_settings" android:order="20" android:title="@string/prefs_useragent_settings"/> @@ -261,7 +261,7 @@ diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/j diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java -@@ -71,6 +71,7 @@ import org.chromium.content_public.browser.WebContents; +@@ -72,6 +72,7 @@ import org.chromium.ui.UiUtils; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.widget.Toast; import org.chromium.url.GURL; @@ -321,22 +321,24 @@ diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -3478,6 +3478,11 @@ static_library("browser") { +@@ -3567,6 +3567,13 @@ static_library("browser") { ] deps += [ "//chrome/android/modules/dev_ui/provider:native" ] } -+ deps += [ -+ "//components/user_scripts/common", -+ "//components/user_scripts/browser", -+ "//components/user_scripts/android", -+ ] ++ if (is_android) { ++ deps += [ ++ "//components/user_scripts/common", ++ "//components/user_scripts/browser", ++ "//components/user_scripts/android", ++ ] ++ } } else { #!is_android sources += [ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -163,6 +163,7 @@ +@@ -161,6 +161,7 @@ #include "components/ui_devtools/switches.h" #include "components/variations/service/google_groups_updater_service.h" #include "components/variations/variations_switches.h" @@ -344,13 +346,15 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc #include "components/version_info/version_info.h" #include "components/viz/common/features.h" #include "components/viz/common/switches.h" -@@ -8145,6 +8146,10 @@ const FeatureEntry kFeatureEntries[] = { - FEATURE_VALUE_TYPE(ash::features::kClipboardHistoryLongpress)}, +@@ -8308,6 +8309,12 @@ const FeatureEntry kFeatureEntries[] = { + FEATURE_VALUE_TYPE(ash::features::kClipboardHistoryUrlTitles)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) ++#if BUILDFLAG(IS_ANDROID) + {"enable-userscripts-log", flag_descriptions::kEnableLoggingUserScriptsName, + flag_descriptions::kEnableLoggingUserScriptsDescription, kOsDesktop | kOsAndroid, + FEATURE_VALUE_TYPE(user_scripts::features::kEnableLoggingUserScripts)}, ++#endif + #if BUILDFLAG(IS_WIN) {"enable-media-foundation-video-capture", @@ -358,7 +362,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -7198,6 +7198,11 @@ const char kUseOutOfProcessVideoDecodingDescription[] = +@@ -7376,6 +7376,11 @@ const char kUseOutOfProcessVideoDecodingDescription[] = "enabled in ash-chrome)."; #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) @@ -373,7 +377,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -4120,6 +4120,9 @@ extern const char kQuickCommandsDescription[]; +@@ -4225,6 +4225,9 @@ extern const char kQuickCommandsDescription[]; #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || // defined (OS_FUCHSIA) @@ -386,7 +390,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -253,6 +253,7 @@ +@@ -257,6 +257,7 @@ #include "components/permissions/contexts/geolocation_permission_context_android.h" #include "components/query_tiles/tile_service_prefs.h" #include "components/webapps/browser/android/install_prompt_prefs.h" @@ -394,67 +398,79 @@ diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browse #else // BUILDFLAG(IS_ANDROID) #include "chrome/browser/cart/cart_service.h" #include "chrome/browser/companion/core/promo_handler.h" -@@ -1633,6 +1634,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, +@@ -1731,6 +1732,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, translate::TranslatePrefs::RegisterProfilePrefs(registry); omnibox::RegisterProfilePrefs(registry); ZeroSuggestProvider::RegisterProfilePrefs(registry); ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsPrefs::RegisterProfilePrefs(registry); ++#endif #if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) promos_utils::RegisterProfilePrefs(registry); diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn --- a/chrome/browser/profiles/BUILD.gn +++ b/chrome/browser/profiles/BUILD.gn -@@ -57,6 +57,7 @@ source_set("profile") { - "//components/profile_metrics", - "//components/sync/service", - "//components/variations", -+ "//components/user_scripts/browser", +@@ -60,6 +60,9 @@ source_set("profile") { "//content/public/browser", "//extensions/buildflags", ] ++ if (is_android) { ++ deps += [ "//components/user_scripts/browser" ] ++ } + if (enable_extensions) { + deps += [ "//extensions/browser" ] + } diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc -@@ -450,6 +450,8 @@ +@@ -476,6 +476,10 @@ #include "chrome/browser/offline_pages/request_coordinator_factory.h" #endif ++#if BUILDFLAG(IS_ANDROID) +#include "components/user_scripts/browser/userscripts_browser_client.h" ++#endif + namespace chrome { void AddProfilesExtraParts(ChromeBrowserMainParts* main_parts) { -@@ -1062,6 +1064,7 @@ void ChromeBrowserMainExtraPartsProfiles:: +@@ -1146,6 +1150,9 @@ void ChromeBrowserMainExtraPartsProfiles:: #endif WebDataServiceFactory::GetInstance(); webrtc_event_logging::WebRtcEventLogManagerKeyedServiceFactory::GetInstance(); ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsBrowserClient::GetInstance(); ++#endif } void ChromeBrowserMainExtraPartsProfiles::PreProfileInit() { diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc -@@ -106,6 +106,8 @@ +@@ -106,6 +106,10 @@ #include "extensions/common/manifest.h" #endif ++#if BUILDFLAG(IS_ANDROID) +#include "components/user_scripts/browser/userscripts_browser_client.h" ++#endif + #if BUILDFLAG(ENABLE_SESSION_SERVICE) #include "chrome/browser/sessions/app_session_service_factory.h" #include "chrome/browser/sessions/session_service_factory.h" -@@ -1488,6 +1490,13 @@ void ProfileManager::DoFinalInitForServices(Profile* profile, +@@ -1493,6 +1497,15 @@ void ProfileManager::DoFinalInitForServices(Profile* profile, #endif #endif + ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsBrowserClient* userscript_client = + user_scripts::UserScriptsBrowserClient::GetInstance(); + if (userscript_client) { + userscript_client->SetProfile(profile); + } ++#endif + #if BUILDFLAG(ENABLE_SUPERVISED_USERS) // Initialization needs to happen after extension system initialization (for @@ -471,61 +487,74 @@ diff --git a/chrome/browser/profiles/renderer_updater.cc b/chrome/browser/profil RendererUpdater::RendererUpdater(Profile* profile) : profile_(profile), is_off_the_record_(profile_->IsOffTheRecord()), -@@ -76,6 +78,7 @@ RendererUpdater::RendererUpdater(Profile* profile) +@@ -76,6 +78,9 @@ RendererUpdater::RendererUpdater(Profile* profile) force_youtube_restrict_.Init(policy::policy_prefs::kForceYouTubeRestrict, pref_service); allowed_domains_for_apps_.Init(prefs::kAllowedDomainsForApps, pref_service); ++#if BUILDFLAG(IS_ANDROID) + activate_userscripts_.Init(user_scripts::prefs::kUserScriptsEnabled, pref_service); ++#endif pref_change_registrar_.Init(pref_service); pref_change_registrar_.Add( -@@ -90,6 +93,10 @@ RendererUpdater::RendererUpdater(Profile* profile) +@@ -90,6 +95,12 @@ RendererUpdater::RendererUpdater(Profile* profile) prefs::kAllowedDomainsForApps, base::BindRepeating(&RendererUpdater::UpdateAllRenderers, base::Unretained(this))); ++#if BUILDFLAG(IS_ANDROID) + pref_change_registrar_.Add( + user_scripts::prefs::kUserScriptsEnabled, + base::BindRepeating(&RendererUpdater::UpdateAllRenderers, + base::Unretained(this))); ++#endif } RendererUpdater::~RendererUpdater() { -@@ -242,5 +249,6 @@ chrome::mojom::DynamicParamsPtr RendererUpdater::CreateRendererDynamicParams() +@@ -242,5 +253,11 @@ chrome::mojom::DynamicParamsPtr RendererUpdater::CreateRendererDynamicParams() GetBoundSessionParams(), #endif force_google_safesearch_.GetValue(), force_youtube_restrict_.GetValue(), - allowed_domains_for_apps_.GetValue()); + allowed_domains_for_apps_.GetValue(), -+ activate_userscripts_.GetValue()); ++#if BUILDFLAG(IS_ANDROID) ++ activate_userscripts_.GetValue() ++#else ++ false ++#endif ++ ); } diff --git a/chrome/browser/profiles/renderer_updater.h b/chrome/browser/profiles/renderer_updater.h --- a/chrome/browser/profiles/renderer_updater.h +++ b/chrome/browser/profiles/renderer_updater.h -@@ -108,6 +108,7 @@ class RendererUpdater : public KeyedService, +@@ -108,6 +108,9 @@ class RendererUpdater : public KeyedService, // Prefs that we sync to the renderers. BooleanPrefMember force_google_safesearch_; ++#if BUILDFLAG(IS_ANDROID) + BooleanPrefMember activate_userscripts_; ++#endif IntegerPrefMember force_youtube_restrict_; StringPrefMember allowed_domains_for_apps_; }; diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc -@@ -100,6 +100,7 @@ - #include "components/signin/public/base/signin_buildflags.h" +@@ -106,6 +106,7 @@ + #include "components/signin/public/base/signin_switches.h" #include "components/site_engagement/content/site_engagement_service.h" #include "components/supervised_user/core/common/buildflags.h" +#include "components/user_scripts/browser/ui/user_scripts_ui.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/common/content_client.h" -@@ -528,6 +529,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, +@@ -541,6 +542,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; if (url.host_piece() == chrome::kChromeUIVersionHost) return &NewWebUI; ++#if BUILDFLAG(IS_ANDROID) + if (url.host_piece() == user_scripts::kChromeUIUserScriptsHost) + return &NewWebUI; ++#endif #if !BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_CHROMEOS) @@ -562,96 +591,116 @@ diff --git a/chrome/common/renderer_configuration.mojom b/chrome/common/renderer diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn -@@ -154,6 +154,7 @@ static_library("renderer") { - "//components/content_capture/common", - "//components/content_capture/renderer", - "//components/content_settings/common:mojom", -+ "//components/user_scripts/renderer", - "//components/content_settings/renderer", - "//components/continuous_search/renderer", - "//components/dom_distiller/content/renderer", +@@ -233,6 +233,12 @@ static_library("renderer") { + "//v8", + ] + ++ if (is_android) { ++ deps += [ ++ "//components/user_scripts/renderer", ++ ] ++ } ++ + data_deps = [ "//tools/v8_context_snapshot" ] + + configs += [ "//build/config/compiler:wexit_time_destructors" ] diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc -@@ -252,6 +252,9 @@ +@@ -252,6 +252,11 @@ #include "chrome/renderer/media/chrome_key_systems.h" #endif ++#if BUILDFLAG(IS_ANDROID) +#include "components/user_scripts/common/user_scripts_features.h" +#include "components/user_scripts/renderer/user_scripts_renderer_client.h" ++#endif + using autofill::AutofillAgent; using autofill::PasswordAutofillAgent; using autofill::PasswordGenerationAgent; -@@ -428,6 +431,12 @@ void ChromeContentRendererClient::RenderThreadStarted() { +@@ -428,6 +433,14 @@ void ChromeContentRendererClient::RenderThreadStarted() { WebString::FromASCII(extensions::kExtensionScheme)); #endif ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsRendererClient* userscript_client = + user_scripts::UserScriptsRendererClient::GetInstance(); + if (userscript_client) { + userscript_client->RenderThreadStarted(GetChromeObserver()); + } ++#endif + #if BUILDFLAG(ENABLE_SPELLCHECK) if (!spellcheck_) InitSpellCheck(); -@@ -596,6 +605,13 @@ void ChromeContentRendererClient::RenderFrameCreated( +@@ -601,6 +614,15 @@ void ChromeContentRendererClient::RenderFrameCreated( render_frame, registry); #endif ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsRendererClient* userscript_client = + user_scripts::UserScriptsRendererClient::GetInstance(); + if (userscript_client) { + userscript_client->RenderFrameCreated( + render_frame, registry); + } ++#endif + #if BUILDFLAG(ENABLE_PPAPI) new PepperHelper(render_frame); #endif -@@ -1603,7 +1619,14 @@ void ChromeContentRendererClient::RunScriptsAtDocumentStart( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart( +@@ -1599,6 +1621,17 @@ void ChromeContentRendererClient::RunScriptsAtDocumentStart( render_frame); // |render_frame| might be dead by now. -+ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); #endif ++#if BUILDFLAG(IS_ANDROID) ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); ++#endif + user_scripts::UserScriptsRendererClient* userscript_client = + user_scripts::UserScriptsRendererClient::GetInstance(); + if (userscript_client) { + userscript_client->RunScriptsAtDocumentStart( + render_frame); + } ++#endif } void ChromeContentRendererClient::RunScriptsAtDocumentEnd( -@@ -1612,7 +1635,14 @@ void ChromeContentRendererClient::RunScriptsAtDocumentEnd( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd( +@@ -1608,6 +1641,17 @@ void ChromeContentRendererClient::RunScriptsAtDocumentEnd( render_frame); // |render_frame| might be dead by now. -+ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); #endif ++#if BUILDFLAG(IS_ANDROID) ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); ++#endif + user_scripts::UserScriptsRendererClient* userscript_client = + user_scripts::UserScriptsRendererClient::GetInstance(); + if (userscript_client) { + userscript_client->RunScriptsAtDocumentEnd( + render_frame); + } ++#endif } void ChromeContentRendererClient::RunScriptsAtDocumentIdle( -@@ -1621,7 +1651,14 @@ void ChromeContentRendererClient::RunScriptsAtDocumentIdle( - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentIdle( +@@ -1617,6 +1661,17 @@ void ChromeContentRendererClient::RunScriptsAtDocumentIdle( render_frame); // |render_frame| might be dead by now. -+ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); #endif ++#if BUILDFLAG(IS_ANDROID) ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ static_assert(false, "Compiler error: extensions cannot be enabled with user scripts"); ++#endif + user_scripts::UserScriptsRendererClient* userscript_client = + user_scripts::UserScriptsRendererClient::GetInstance(); + if (userscript_client) { + userscript_client->RunScriptsAtDocumentIdle( + render_frame); + } ++#endif } void ChromeContentRendererClient:: @@ -667,11 +716,13 @@ diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/renderer/ash_merge_session_loader_throttle.h" #endif -@@ -217,6 +219,7 @@ void ChromeRenderThreadObserver::SetConfiguration( +@@ -217,6 +219,9 @@ void ChromeRenderThreadObserver::SetConfiguration( chrome::mojom::DynamicParamsPtr params) { base::AutoLock lock(dynamic_params_lock_); dynamic_params_ = std::move(params); ++#if BUILDFLAG(IS_ANDROID) + user_scripts::UserScriptsRendererClient::GetInstance()->ConfigurationUpdated(); ++#endif } void ChromeRenderThreadObserver::OnRendererConfigurationAssociatedRequest( @@ -10439,7 +10490,7 @@ new file mode 100755 diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec -@@ -899,6 +899,12 @@ +@@ -915,6 +915,12 @@ "components/autofill/core/browser/autofill_address_rewriter_resources.grd":{ "includes": [6220] }, diff --git a/build/patches/Guard-for-user-agent-reduction.patch b/build/patches/Guard-for-user-agent-reduction.patch index c189f1cd..49c45a56 100644 --- a/build/patches/Guard-for-user-agent-reduction.patch +++ b/build/patches/Guard-for-user-agent-reduction.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -1630,7 +1630,7 @@ void ChromeContentBrowserClient::RegisterProfilePrefs( +@@ -1639,7 +1639,7 @@ void ChromeContentBrowserClient::RegisterProfilePrefs( registry->RegisterIntegerPref( prefs::kUserAgentReduction, static_cast( @@ -55,7 +55,7 @@ diff --git a/content/common/user_agent.cc b/content/common/user_agent.cc diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1345,8 +1345,8 @@ BASE_FEATURE(kReducedReferrerGranularity, +@@ -1435,8 +1435,8 @@ BASE_FEATURE(kReducedReferrerGranularity, const base::FeatureParam kUserAgentFrozenBuildVersion{ &kReduceUserAgentMinorVersion, "build_version", "0"}; @@ -69,7 +69,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2911,23 +2911,23 @@ +@@ -2912,23 +2912,23 @@ // If enabled, the deviceModel will be reduced to "K" and the // androidVersion will be reduced to a static "10" string in android // User-Agent string. diff --git a/build/patches/History-number-of-days-privacy-setting.patch b/build/patches/History-number-of-days-privacy-setting.patch index 0123a453..bbc38fc4 100644 --- a/build/patches/History-number-of-days-privacy-setting.patch +++ b/build/patches/History-number-of-days-privacy-setting.patch @@ -74,8 +74,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - PrivacyPreferencesManagerImpl privacyPrefManager = -@@ -218,6 +224,40 @@ public class PrivacySettings extends PreferenceFragmentCompat + getActivity().setTitle(R.string.prefs_privacy_security); +@@ -214,6 +220,40 @@ public class PrivacySettings extends PreferenceFragmentCompat Preference syncAndServicesLink = findPreference(PREF_SYNC_AND_SERVICES_LINK); syncAndServicesLink.setSummary(buildSyncAndServicesLink()); @@ -116,7 +116,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting Preference thirdPartyCookies = findPreference(PREF_THIRD_PARTY_COOKIES); if (thirdPartyCookies != null) { thirdPartyCookies.getExtras().putString( -@@ -405,6 +445,29 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -401,6 +441,29 @@ public class PrivacySettings extends PreferenceFragmentCompat privacyGuide.setTitle(privacyGuidePrefTitle); } @@ -161,7 +161,7 @@ diff --git a/chrome/browser/history/history_service_factory.cc b/chrome/browser/ diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc -@@ -372,6 +372,7 @@ std::unique_ptr Profile::CreateProfile(const base::FilePath& path, +@@ -368,6 +368,7 @@ std::unique_ptr Profile::CreateProfile(const base::FilePath& path, void ProfileImpl::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false); @@ -172,7 +172,7 @@ diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/p diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1369,6 +1369,18 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1393,6 +1393,18 @@ Your Google account may have other forms of browsing history like searches and a Browsing history @@ -279,7 +279,7 @@ diff --git a/components/browser_ui/settings/android/widget/java/src/org/chromium import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; -@@ -98,6 +99,12 @@ public class SpinnerPreference extends Preference { +@@ -96,6 +97,12 @@ public class SpinnerPreference extends Preference { super.onBindViewHolder(holder); ((TextView) holder.findViewById(R.id.title)).setText(getTitle()); @@ -353,7 +353,7 @@ diff --git a/components/history/core/browser/history_backend.cc b/components/his // The maximum number of days for which domain visit metrics are computed // each time HistoryBackend::GetDomainDiversity() is called. -@@ -1297,6 +1297,19 @@ void HistoryBackend::InitImpl( +@@ -1305,6 +1305,19 @@ void HistoryBackend::InitImpl( expirer_.StartExpiringOldStuff(base::Days(kExpireDaysThreshold)); } @@ -376,7 +376,7 @@ diff --git a/components/history/core/browser/history_backend.cc b/components/his diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h -@@ -220,6 +220,8 @@ class HistoryBackend : public base::RefCountedThreadSafe, +@@ -222,6 +222,8 @@ class HistoryBackend : public base::RefCountedThreadSafe, void Init(bool force_fail, const HistoryDatabaseParams& history_database_params); @@ -388,7 +388,7 @@ diff --git a/components/history/core/browser/history_backend.h b/components/hist diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc -@@ -36,6 +36,9 @@ +@@ -37,6 +37,9 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" @@ -398,7 +398,7 @@ diff --git a/components/history/core/browser/history_service.cc b/components/his #include "components/history/core/browser/download_row.h" #include "components/history/core/browser/features.h" #include "components/history/core/browser/history_backend.h" -@@ -1319,6 +1322,9 @@ void HistoryService::Cleanup() { +@@ -1339,6 +1342,9 @@ void HistoryService::Cleanup() { return; } @@ -408,7 +408,7 @@ diff --git a/components/history/core/browser/history_service.cc b/components/his NotifyHistoryServiceBeingDeleted(); weak_ptr_factory_.InvalidateWeakPtrs(); -@@ -1392,6 +1398,33 @@ bool HistoryService::Init( +@@ -1415,6 +1421,33 @@ bool HistoryService::Init( return true; } @@ -463,7 +463,7 @@ diff --git a/components/history/core/browser/history_service.h b/components/hist // Triggers the backend to load if it hasn't already, and then returns whether // it's finished loading. // Note: Virtual needed for mocking. -@@ -1129,6 +1133,10 @@ class HistoryService : public KeyedService, +@@ -1143,6 +1147,10 @@ class HistoryService : public KeyedService, raw_ptr local_device_info_provider_ = nullptr; diff --git a/build/patches/Ignore-enterprise-policies-for-secure-DNS.patch b/build/patches/Ignore-enterprise-policies-for-secure-DNS.patch index 05c35ed5..65273c93 100644 --- a/build/patches/Ignore-enterprise-policies-for-secure-DNS.patch +++ b/build/patches/Ignore-enterprise-policies-for-secure-DNS.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfo.java b/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfo.java --- a/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfo.java +++ b/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfo.java -@@ -81,13 +81,7 @@ public abstract class EnterpriseInfo { +@@ -83,13 +83,7 @@ public abstract class EnterpriseInfo { @CalledByNative public static void getManagedStateForNative() { Callback callback = (result) -> { diff --git a/build/patches/Increase-number-of-autocomplete-matches-to-10.patch b/build/patches/Increase-number-of-autocomplete-matches-to-10.patch index 8aa9ef29..20efd34d 100644 --- a/build/patches/Increase-number-of-autocomplete-matches-to-10.patch +++ b/build/patches/Increase-number-of-autocomplete-matches-to-10.patch @@ -7,13 +7,13 @@ Patch adapted from https://github.com/Eloston/ungoogled-chromium/issues/814#issu License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- components/omnibox/browser/autocomplete_result.cc | 5 +++-- - components/omnibox/browser/omnibox_field_trial.cc | 6 +++--- - 2 files changed, 6 insertions(+), 5 deletions(-) + components/omnibox/browser/omnibox_field_trial.cc | 6 +++++- + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc -@@ -84,10 +84,11 @@ constexpr size_t kMaxPedalMatchIndex = +@@ -85,10 +85,11 @@ constexpr size_t kMaxPedalMatchIndex = // static size_t AutocompleteResult::GetMaxMatches(bool is_zero_suggest) { @@ -30,26 +30,18 @@ diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omni diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc -@@ -288,9 +288,9 @@ void OmniboxFieldTrial::GetDemotionsByType( +@@ -289,7 +289,11 @@ void OmniboxFieldTrial::GetDemotionsByType( size_t OmniboxFieldTrial::GetProviderMaxMatches( AutocompleteProvider::Type provider) { - size_t default_max_matches_per_provider = 3; -+ size_t default_max_matches_per_provider = 5; // was 3; this needs to be half the value of kDefaultMaxAutocompleteMatches from components/omnibox/browser/autocomplete_result.cc ++ size_t default_max_matches_per_provider = 5; ++ // was 3; this needs to be half the value of ++ // kDefaultMaxAutocompleteMatches from ++ // components/omnibox/browser/autocomplete_result.cc ++ if ((true)) return default_max_matches_per_provider; -- std::string param_value = base::GetFieldTrialParamValueByFeature( -+/* std::string param_value = base::GetFieldTrialParamValueByFeature( - omnibox::kUIExperimentMaxAutocompleteMatches, - OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam); - -@@ -315,7 +315,7 @@ size_t OmniboxFieldTrial::GetProviderMaxMatches( - return v; - } - } -- } -+ }*/ - - return default_max_matches_per_provider; - } + std::string param_value; + if (OmniboxFieldTrial::IsMlUrlScoringEnabled()) { -- 2.25.1 diff --git a/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch b/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch index 1363b3a8..698a8a7a 100644 --- a/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch +++ b/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch @@ -10,20 +10,20 @@ Send a random key press to circumvent idle status detection License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- third_party/blink/renderer/core/dom/build.gni | 2 + - .../blink/renderer/core/dom/document.cc | 65 +++++++++++++++++++ + .../blink/renderer/core/dom/document.cc | 64 +++++++++++++++++++ .../blink/renderer/core/dom/document.h | 3 + .../core/dom/extensions/anti_amp_cure.h | 6 ++ .../core/dom/extensions/video_bg_play.h | 6 ++ .../renderer/core/html/html_script_element.cc | 5 ++ .../renderer/core/html/html_script_element.h | 1 + - 7 files changed, 88 insertions(+) + 7 files changed, 87 insertions(+) create mode 100644 third_party/blink/renderer/core/dom/extensions/anti_amp_cure.h create mode 100644 third_party/blink/renderer/core/dom/extensions/video_bg_play.h diff --git a/third_party/blink/renderer/core/dom/build.gni b/third_party/blink/renderer/core/dom/build.gni --- a/third_party/blink/renderer/core/dom/build.gni +++ b/third_party/blink/renderer/core/dom/build.gni -@@ -170,6 +170,8 @@ blink_core_sources_dom = [ +@@ -166,6 +166,8 @@ blink_core_sources_dom = [ "has_invalidation_flags.h", "icon_url.cc", "icon_url.h", @@ -35,7 +35,7 @@ diff --git a/third_party/blink/renderer/core/dom/build.gni b/third_party/blink/r diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc -@@ -292,6 +292,7 @@ +@@ -293,6 +293,7 @@ #include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h" #include "third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h" #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h" @@ -43,7 +43,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink #include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h" #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h" -@@ -368,6 +369,8 @@ +@@ -369,6 +370,8 @@ #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h" #include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h" @@ -52,7 +52,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink #ifndef NDEBUG using WeakDocumentSet = blink::HeapHashSet>; static WeakDocumentSet& LiveDocumentSet(); -@@ -7489,6 +7492,64 @@ void Document::OnPrepareToStopParsing() { +@@ -7440,6 +7443,64 @@ void Document::OnPrepareToStopParsing() { MilestoneForDelayedAsyncScript::kFinishedParsing); } @@ -117,17 +117,16 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink void Document::FinishedParsing() { DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing()); DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading); -@@ -7540,6 +7601,10 @@ void Document::FinishedParsing() { +@@ -7506,6 +7567,9 @@ void Document::FinishedParsing() { + } frame->Loader().FinishedParsing(); - + if (!IsPrefetchOnly()) { + injectScripts(); + } -+ - if (ShouldMarkFontPerformance()) - FontPerformance::MarkDomContentLoaded(); + } + // Schedule dropping of the ElementDataCache. We keep it alive for a while diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h diff --git a/build/patches/JIT-site-settings.patch b/build/patches/JIT-site-settings.patch index 81815557..3a80c144 100644 --- a/build/patches/JIT-site-settings.patch +++ b/build/patches/JIT-site-settings.patch @@ -273,7 +273,7 @@ new file mode 100644 diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc -@@ -516,7 +516,7 @@ void ContentSettingsRegistry::Init() { +@@ -527,7 +527,7 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); Register(ContentSettingsType::JAVASCRIPT_JIT, "javascript-jit", diff --git a/build/patches/Keep-empty-tabs-between-sessions.patch b/build/patches/Keep-empty-tabs-between-sessions.patch index 6fc617e6..a6d351d9 100644 --- a/build/patches/Keep-empty-tabs-between-sessions.patch +++ b/build/patches/Keep-empty-tabs-between-sessions.patch @@ -30,7 +30,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPer diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java -@@ -620,9 +620,6 @@ public class CriticalPersistedTabData extends PersistedTabData { +@@ -621,9 +621,6 @@ public class CriticalPersistedTabData extends PersistedTabData { if (getUrl() == null || getUrl().isEmpty()) { return false; } diff --git a/build/patches/Keep-flag-to-allow-screenshots-in-Incognito-mode.patch b/build/patches/Keep-flag-to-allow-screenshots-in-Incognito-mode.patch index 9aca3c9e..f027018a 100644 --- a/build/patches/Keep-flag-to-allow-screenshots-in-Incognito-mode.patch +++ b/build/patches/Keep-flag-to-allow-screenshots-in-Incognito-mode.patch @@ -15,7 +15,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -4706,9 +4706,9 @@ +@@ -4890,9 +4890,9 @@ "expiry_milestone": 120 }, { @@ -27,6 +27,6 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js + "expiry_milestone": -1 // - }, { - "name": "indicate-account-storage-error-in-account-cell", + "name": "info-card-acknowledgement-tracking", -- 2.25.1 diff --git a/build/patches/Logcat-crash-reports-UI.patch b/build/patches/Logcat-crash-reports-UI.patch index 187db08c..3e5f69d7 100644 --- a/build/patches/Logcat-crash-reports-UI.patch +++ b/build/patches/Logcat-crash-reports-UI.patch @@ -10,12 +10,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../crash_upload_list_android.h | 1 + chrome/browser/net/chrome_network_delegate.cc | 7 + chrome/browser/ui/BUILD.gn | 1 + - chrome/browser/ui/webui/crashes_ui.cc | 166 ++++++++++++++++-- + chrome/browser/ui/webui/crashes_ui.cc | 176 ++++++++++++++++-- .../crash/core/browser/crashes_ui_util.cc | 4 + .../crash/core/browser/crashes_ui_util.h | 2 + .../crash/core/browser/resources/crashes.css | 67 ++++++- .../crash/core/browser/resources/crashes.html | 17 ++ - .../crash/core/browser/resources/crashes.ts | 94 ++++------ + .../crash/core/browser/resources/crashes.ts | 94 +++------- components/crash_strings.grdp | 22 ++- .../minidump_uploader/CrashFileManager.java | 7 +- .../MinidumpUploadCallable.java | 21 +-- @@ -23,7 +23,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../upload_list/text_log_upload_list.cc | 1 + components/upload_list/upload_list.cc | 14 ++ components/upload_list/upload_list.h | 9 + - 18 files changed, 375 insertions(+), 134 deletions(-) + 18 files changed, 385 insertions(+), 134 deletions(-) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java @@ -160,7 +160,7 @@ diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -751,6 +751,7 @@ static_library("ui") { +@@ -674,6 +674,7 @@ static_library("ui") { "//third_party/re2", "//third_party/webrtc_overrides:webrtc_component", "//third_party/zlib", @@ -171,7 +171,7 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc -@@ -37,6 +37,17 @@ +@@ -37,6 +37,19 @@ #include "google_apis/gaia/gaia_auth_util.h" #include "ui/base/resource/resource_bundle.h" @@ -182,14 +182,16 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra +#include "base/files/scoped_temp_dir.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" ++#if BUILDFLAG(IS_ANDROID) +#include "base/android/path_utils.h" ++#endif +#include "net/base/filename_util.h" +#include "third_party/zlib/google/zip.h" + #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h" #endif -@@ -72,6 +83,10 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) { +@@ -72,6 +85,10 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) { source->SetDefaultResource(IDR_CRASH_CRASHES_HTML); } @@ -200,7 +202,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra //////////////////////////////////////////////////////////////////////////////// // // CrashesDOMHandler -@@ -81,7 +96,7 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) { +@@ -81,7 +98,7 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) { // The handler for Javascript messages for the chrome://crashes/ page. class CrashesDOMHandler : public WebUIMessageHandler { public: @@ -209,7 +211,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra CrashesDOMHandler(const CrashesDOMHandler&) = delete; CrashesDOMHandler& operator=(const CrashesDOMHandler&) = delete; -@@ -97,6 +112,8 @@ class CrashesDOMHandler : public WebUIMessageHandler { +@@ -97,6 +114,8 @@ class CrashesDOMHandler : public WebUIMessageHandler { // Asynchronously fetches the list of crashes. Called from JS. void HandleRequestCrashes(const base::Value::List& args); @@ -218,7 +220,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra #if BUILDFLAG(IS_CHROMEOS_ASH) // Asynchronously triggers crash uploading. Called from JS. void HandleRequestUploads(const base::Value::List& args); -@@ -108,13 +125,26 @@ class CrashesDOMHandler : public WebUIMessageHandler { +@@ -108,14 +127,30 @@ class CrashesDOMHandler : public WebUIMessageHandler { // Asynchronously requests a user triggered upload. Called from JS. void HandleRequestSingleCrashUpload(const base::Value::List& args); @@ -245,9 +247,13 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra + : list_available_(false), first_load_(true), + web_contents_(web_contents) { upload_list_ = CreateCrashUploadList(); ++#if !BUILDFLAG(IS_ANDROID) ++ web_contents_ = nullptr; ++#endif } -@@ -141,10 +171,24 @@ void CrashesDOMHandler::RegisterMessages() { + CrashesDOMHandler::~CrashesDOMHandler() { +@@ -141,10 +176,24 @@ void CrashesDOMHandler::RegisterMessages() { crash_reporter::kCrashesUIRequestSingleCrashUpload, base::BindRepeating(&CrashesDOMHandler::HandleRequestSingleCrashUpload, base::Unretained(this))); @@ -272,7 +278,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra if (first_load_) { first_load_ = false; if (list_available_) -@@ -176,8 +220,7 @@ void CrashesDOMHandler::OnUploadListAvailable() { +@@ -176,8 +225,7 @@ void CrashesDOMHandler::OnUploadListAvailable() { } void CrashesDOMHandler::UpdateUI() { @@ -282,7 +288,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra bool system_crash_reporter = false; #if BUILDFLAG(IS_CHROMEOS) -@@ -225,14 +268,112 @@ void CrashesDOMHandler::UpdateUI() { +@@ -225,14 +273,117 @@ void CrashesDOMHandler::UpdateUI() { void CrashesDOMHandler::HandleRequestSingleCrashUpload( const base::Value::List& args) { @@ -298,6 +304,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra +} + +std::string CrashesDOMHandler::RequestSingleUpload(const std::string& local_id) const { ++#if BUILDFLAG(IS_ANDROID) + // get crash file path + std::string info_file_path = upload_list_->GetFilePathByLocalId(local_id); + if (info_file_path.empty()) { @@ -347,13 +354,14 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra + if (result) { + return zip_file_name.value(); + } -+ ++#endif + LOG(ERROR) << "Crash report: cannot create zip content"; + return std::string(); +} + +void CrashesDOMHandler::RequestSingleUploadCallback(const std::string& local_id, + const std::string& file_name) { ++#if BUILDFLAG(IS_ANDROID) + if (!file_name.empty()) { + upload_list_->RequestSingleUploadAsync(local_id); + @@ -361,6 +369,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra + web_contents_->GetController().LoadURL( + net::FilePathToFileURL(file_path), {}, {}, {}); + } ++#endif +} + +void CrashesDOMHandler::HandleRequestNewExtraction( @@ -385,6 +394,7 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra +} + +void CrashesDOMHandler::ClearAll() { ++#if BUILDFLAG(IS_ANDROID) + // get android crash report dir + base::FilePath cache_dir; + base::android::GetCacheDirectory(&cache_dir); @@ -398,10 +408,11 @@ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/cra + // remove all files, don't care for result + base::DeleteFile(full_name); + } ++#endif } } // namespace -@@ -244,7 +385,8 @@ void CrashesDOMHandler::HandleRequestSingleCrashUpload( +@@ -244,7 +395,8 @@ void CrashesDOMHandler::HandleRequestSingleCrashUpload( /////////////////////////////////////////////////////////////////////////////// CrashesUI::CrashesUI(content::WebUI* web_ui) : WebUIController(web_ui) { diff --git a/build/patches/Modify-default-preferences.patch b/build/patches/Modify-default-preferences.patch index b540d7f5..45c4ac14 100644 --- a/build/patches/Modify-default-preferences.patch +++ b/build/patches/Modify-default-preferences.patch @@ -36,9 +36,9 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc #include "components/autofill/core/common/autofill_util.h" +#include "components/bookmarks/browser/features.h" #include "components/browser_sync/browser_sync_switches.h" - #include "components/browser_ui/site_settings/android/features.h" #include "components/browsing_data/core/features.h" -@@ -6388,6 +6389,11 @@ const FeatureEntry kFeatureEntries[] = { + #include "components/commerce/core/commerce_feature_list.h" +@@ -6486,6 +6487,11 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(features::kQuickSettingsPWANotifications)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -65,7 +65,7 @@ diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/brows diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -1590,7 +1590,7 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs( +@@ -1599,7 +1599,7 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs( void ChromeContentBrowserClient::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref(prefs::kDisable3DAPIs, false); @@ -77,7 +77,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3224,6 +3224,10 @@ const char kTabGroupsContinuationAndroidName[] = "Tab Groups Continuation"; +@@ -3290,6 +3290,10 @@ const char kTabGroupsContinuationAndroidName[] = "Tab Groups Continuation"; const char kTabGroupsContinuationAndroidDescription[] = "Allows users to access continuation features in Tab Group on phones."; @@ -91,7 +91,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1829,6 +1829,9 @@ extern const char kCommerceMerchantViewerAndroidDescription[]; +@@ -1881,6 +1881,9 @@ extern const char kCommerceMerchantViewerAndroidDescription[]; extern const char kTabGroupsContinuationAndroidName[]; extern const char kTabGroupsContinuationAndroidDescription[]; @@ -104,7 +104,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/prefetch/prefetch_prefs.h b/chrome/browser/prefetch/prefetch_prefs.h --- a/chrome/browser/prefetch/prefetch_prefs.h +++ b/chrome/browser/prefetch/prefetch_prefs.h -@@ -28,7 +28,7 @@ enum class NetworkPredictionOptions { +@@ -23,7 +23,7 @@ enum class NetworkPredictionOptions { kWifiOnlyDeprecated = 1, kDisabled = 2, kExtended = 3, @@ -158,18 +158,18 @@ diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_u diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn --- a/components/bookmarks/browser/BUILD.gn +++ b/components/bookmarks/browser/BUILD.gn -@@ -19,6 +19,7 @@ static_library("browser") { - "bookmark_storage.h", +@@ -20,6 +20,7 @@ static_library("browser") { "bookmark_undo_provider.h", "bookmark_utils.h", + "bookmark_uuids.h", + "features.h", "history_bookmark_model.h", "model_loader.h", "scoped_group_bookmark_actions.h", -@@ -40,6 +41,7 @@ static_library("browser") { - "bookmark_node_data.cc", +@@ -42,6 +43,7 @@ static_library("browser") { "bookmark_storage.cc", "bookmark_utils.cc", + "bookmark_uuids.cc", + "features.cc", "model_loader.cc", "scoped_group_bookmark_actions.cc", @@ -248,7 +248,7 @@ new file mode 100644 diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc -@@ -234,7 +234,7 @@ void ContentSettingsRegistry::Init() { +@@ -236,7 +236,7 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); Register(ContentSettingsType::BACKGROUND_SYNC, "background-sync", @@ -257,7 +257,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. /*allowlisted_schemes=*/{}, /*valid_settings=*/{CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK}, WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE, -@@ -325,7 +325,7 @@ void ContentSettingsRegistry::Init() { +@@ -336,7 +336,7 @@ void ContentSettingsRegistry::Init() { // TODO(crbug.com/904439): Update this to "SECURE_ONLY" once // DeviceOrientationEvents and DeviceMotionEvents are only fired in secure // contexts. @@ -269,7 +269,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc -@@ -73,7 +73,7 @@ void CookieSettings::RegisterProfilePrefs( +@@ -72,7 +72,7 @@ void CookieSettings::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterIntegerPref( prefs::kCookieControlsMode, @@ -293,7 +293,7 @@ diff --git a/components/payments/core/payment_prefs.cc b/components/payments/cor diff --git a/components/safe_browsing/core/common/safe_browsing_prefs.cc b/components/safe_browsing/core/common/safe_browsing_prefs.cc --- a/components/safe_browsing/core/common/safe_browsing_prefs.cc +++ b/components/safe_browsing/core/common/safe_browsing_prefs.cc -@@ -239,13 +239,13 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { +@@ -258,13 +258,13 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref( prefs::kSafeBrowsingSawInterstitialScoutReporting, false); registry->RegisterBooleanPref( @@ -327,7 +327,7 @@ diff --git a/components/signin/internal/identity_manager/primary_account_manager diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -946,8 +946,8 @@ const base::FeatureParam kInterestGroupStorageMaxOpsBeforeMaintenance{ +@@ -997,8 +997,8 @@ const base::FeatureParam kInterestGroupStorageMaxOpsBeforeMaintenance{ // the attribute. Note: At present, only iframes with origin-restricted // sandboxes are isolated. BASE_FEATURE(kIsolateSandboxedIframes, diff --git a/build/patches/Move-navigation-bar-to-bottom.patch b/build/patches/Move-navigation-bar-to-bottom.patch index e20c1a36..b0f1e5e0 100644 --- a/build/patches/Move-navigation-bar-to-bottom.patch +++ b/build/patches/Move-navigation-bar-to-bottom.patch @@ -141,7 +141,7 @@ diff --git a/cc/input/browser_controls_offset_manager.cc b/cc/input/browser_cont diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc -@@ -4213,6 +4213,9 @@ bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) { +@@ -4247,6 +4247,9 @@ bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) { if (scroll_delta.IsZero()) return false; @@ -154,7 +154,7 @@ diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java -@@ -105,6 +105,9 @@ import org.chromium.ui.util.ColorUtils; +@@ -108,6 +108,9 @@ import org.chromium.ui.util.ColorUtils; import java.util.List; @@ -164,7 +164,7 @@ diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/ /** The mediator implements the logic to interact with the surfaces and caller. */ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View.OnClickListener, StartSurface.OnTabSelectingListener, BackPressHandler, -@@ -1378,6 +1381,8 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. +@@ -1390,6 +1393,8 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. } private void setTopMargin(int topMargin) { @@ -176,7 +176,7 @@ diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java -@@ -44,6 +44,7 @@ import org.chromium.components.feature_engagement.FeatureConstants; +@@ -45,6 +45,7 @@ import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; @@ -184,7 +184,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser import java.util.List; -@@ -139,7 +140,8 @@ public class TabGroupUiCoordinator implements TabGroupUiMediator.ResetHandler, T +@@ -143,7 +144,8 @@ public class TabGroupUiCoordinator implements TabGroupUiMediator.ResetHandler, T @Override public void initializeWithNative(Activity activity, BottomControlsCoordinator.BottomControlsVisibilityController visibilityController, @@ -193,8 +193,8 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser + TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier tabSupplier) { try (TraceEvent e = TraceEvent.scoped("TabGroupUiCoordinator.initializeWithNative")) { mTabStripCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.STRIP, - mContext, mTabModelSelector, null, null, false, null, null, -@@ -176,7 +178,8 @@ public class TabGroupUiCoordinator implements TabGroupUiMediator.ResetHandler, T + mContext, mBrowserControlsStateProvider, mTabModelSelector, null, null, false, +@@ -180,7 +182,8 @@ public class TabGroupUiCoordinator implements TabGroupUiMediator.ResetHandler, T mMediator = new TabGroupUiMediator(mActivity, visibilityController, this, mModel, mTabModelSelector, mTabCreatorManager, mLayoutStateProviderSupplier, mIncognitoStateProvider, mTabGridDialogControllerSupplier, @@ -207,7 +207,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java -@@ -47,6 +47,12 @@ import org.chromium.url.GURL; +@@ -46,6 +46,12 @@ import org.chromium.url.GURL; import java.util.List; @@ -220,7 +220,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser /** * A mediator for the TabGroupUi. Responsible for managing the internal state of the component. */ -@@ -116,6 +122,11 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -115,6 +121,11 @@ public class TabGroupUiMediator implements BackPressHandler { private boolean mIsTabGroupUiVisible; private boolean mIsShowingOverViewMode; @@ -232,7 +232,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser TabGroupUiMediator(Context context, BottomControlsVisibilityController visibilityController, ResetHandler resetHandler, PropertyModel model, TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager, -@@ -123,7 +134,9 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -122,7 +133,9 @@ public class TabGroupUiMediator implements BackPressHandler { IncognitoStateProvider incognitoStateProvider, @Nullable OneshotSupplier dialogControllerSupplier, @@ -243,7 +243,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mContext = context; mResetHandler = resetHandler; mModel = model; -@@ -144,10 +157,29 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -143,10 +156,29 @@ public class TabGroupUiMediator implements BackPressHandler { mIsShowingOverViewMode = true; } @@ -273,7 +273,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mContext) && getTabsToShowForId(lastId).contains(tab)) { return; -@@ -204,6 +236,7 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -199,6 +231,7 @@ public class TabGroupUiMediator implements BackPressHandler { return; } resetTabStripWithRelatedTabsForId(currentTab.getId()); @@ -281,7 +281,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser } @Override -@@ -319,6 +352,8 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -314,6 +347,8 @@ public class TabGroupUiMediator implements BackPressHandler { resetTabStripWithRelatedTabsForId(tab.getId()); } @@ -290,7 +290,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mBackPressStateSupplier = new ObservableSupplierImpl<>(); if (mTabGridDialogControllerSupplier != null) { mTabGridDialogControllerSupplier.onAvailable(controller -> { -@@ -332,6 +367,18 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -327,6 +362,18 @@ public class TabGroupUiMediator implements BackPressHandler { mModel.set(TabGroupUiProperties.LEFT_BUTTON_DRAWABLE_ID, drawableId); } @@ -309,7 +309,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser void setupLeftButtonOnClickListener(View.OnClickListener listener) { mModel.set(TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER, listener); } -@@ -442,6 +489,7 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -437,6 +484,7 @@ public class TabGroupUiMediator implements BackPressHandler { } public void destroy() { @@ -399,15 +399,15 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java -@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.tasks.tab_management; - import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_TYPE; +@@ -8,6 +8,7 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.Card + import android.app.Activity; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -@@ -49,6 +50,9 @@ import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter; +@@ -51,6 +52,9 @@ import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; import org.chromium.ui.widget.ViewLookupCachingFrameLayout; @@ -417,9 +417,9 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; -@@ -98,6 +102,74 @@ public class TabListCoordinator - private ItemTouchHelper mItemTouchHelper; - private OnItemTouchListener mOnItemTouchListener; +@@ -108,6 +112,74 @@ public class TabListCoordinator + private int mEmptyStateSubheadingResId; + private boolean mIsEmptyViewInitialized; + public class GridLayoutManagerDockBottom extends GridLayoutManager { + Context mContext; @@ -492,7 +492,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser /** * Construct a coordinator for UI that shows a list of tabs. * @param mode Modes of showing the list of tabs. Can be used in GRID or STRIP. -@@ -246,6 +318,12 @@ public class TabListCoordinator +@@ -284,6 +356,12 @@ public class TabListCoordinator if (mMode == TabListMode.GRID) { GridLayoutManager gridLayoutManager = new GridLayoutManager(context, GRID_LAYOUT_SPAN_COUNT_COMPACT); @@ -505,7 +505,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mRecyclerView.setLayoutManager(gridLayoutManager); mMediator.registerOrientationListener(gridLayoutManager); mMediator.updateSpanCount( -@@ -507,6 +585,9 @@ public class TabListCoordinator +@@ -561,6 +639,9 @@ public class TabListCoordinator void prepareTabSwitcherView() { registerLayoutChangeListener(); mRecyclerView.prepareTabSwitcherView(); @@ -518,7 +518,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java -@@ -40,6 +40,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; +@@ -39,6 +39,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.chromium.base.Log; @@ -526,7 +526,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.tab_ui.R; -@@ -69,6 +70,8 @@ class TabListRecyclerView +@@ -68,6 +69,8 @@ class TabListRecyclerView public static final long BASE_ANIMATION_DURATION_MS = 218; public static final long FINAL_FADE_IN_DURATION_MS = 50; @@ -535,7 +535,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser /** * Field trial parameter for downsampling scaling factor. */ -@@ -250,6 +253,7 @@ class TabListRecyclerView +@@ -265,6 +268,7 @@ class TabListRecyclerView ? FINAL_FADE_IN_DURATION_MS : BASE_ANIMATION_DURATION_MS; @@ -543,7 +543,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser setAlpha(0); setVisibility(View.VISIBLE); mFadeInAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1); -@@ -299,6 +303,11 @@ class TabListRecyclerView +@@ -314,6 +318,11 @@ class TabListRecyclerView } void setShadowVisibility(boolean shouldShowShadow) { @@ -555,7 +555,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser if (mShadowImageView == null) { Context context = getContext(); mShadowImageView = new ImageView(context); -@@ -311,7 +320,10 @@ class TabListRecyclerView +@@ -326,7 +335,10 @@ class TabListRecyclerView if (getParent() instanceof FrameLayout) { // Add shadow for grid tab switcher. FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( @@ -567,7 +567,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mShadowImageView.setLayoutParams(params); mShadowImageView.setTranslationY(mShadowTopOffset); FrameLayout parent = (FrameLayout) getParent(); -@@ -339,6 +351,10 @@ class TabListRecyclerView +@@ -354,6 +366,10 @@ class TabListRecyclerView void setShadowTopOffset(int shadowTopOffset) { mShadowTopOffset = shadowTopOffset; @@ -578,7 +578,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser if (mShadowImageView != null && getParent() instanceof FrameLayout) { // Since the shadow has no functionality, other than just existing visually, we can use -@@ -535,6 +551,7 @@ class TabListRecyclerView +@@ -550,6 +566,7 @@ class TabListRecyclerView mListener.finishedHiding(); } }); @@ -589,15 +589,15 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java -@@ -44,6 +44,7 @@ import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider + import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl; + import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.flags.ChromeFeatureList; ++import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthController; import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager; -+import org.chromium.chrome.browser.flags.CachedFeatureFlags; - import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; - import org.chromium.chrome.browser.price_tracking.PriceTrackingUtilities; - import org.chromium.chrome.browser.tab.Tab; -@@ -498,11 +499,22 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView + import org.chromium.chrome.browser.layouts.LayoutStateProvider; +@@ -522,11 +523,22 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView updateTopControlsProperties(); mContainerViewModel.set( BOTTOM_CONTROLS_HEIGHT, browserControlsStateProvider.getBottomControlsHeight()); @@ -620,7 +620,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser if (backPressManager != null && BackPressManager.isEnabled()) { assert !mIsStartSurfaceEnabled || mIsStartSurfaceRefactorEnabled; backPressManager.addHandler(this, BackPressHandler.Type.TAB_SWITCHER); -@@ -625,6 +637,10 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView +@@ -647,6 +659,10 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView final int contentOffset = mBrowserControlsStateProvider.getContentOffset(); mContainerViewModel.set(TOP_MARGIN, contentOffset); @@ -710,7 +710,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/s diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java -@@ -254,6 +254,9 @@ import java.util.ArrayList; +@@ -253,6 +253,9 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -720,7 +720,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv /** * A {@link AsyncInitializationActivity} that builds and manages a {@link CompositorViewHolder} * and associated classes. -@@ -770,6 +773,16 @@ public abstract class ChromeActivity +@@ -785,6 +788,16 @@ public abstract class ChromeActivity int toolbarLayoutId = getToolbarLayoutId(); if (toolbarLayoutId != ActivityUtils.NO_RESOURCE_ID && controlContainer != null) { controlContainer.initWithToolbar(toolbarLayoutId); @@ -749,7 +749,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/Comp import java.util.ArrayList; import java.util.HashSet; -@@ -332,6 +334,10 @@ public class CompositorViewHolder extends FrameLayout +@@ -321,6 +323,10 @@ public class CompositorViewHolder extends FrameLayout @Override public void setCurrentTouchEventOffsets(float top) { EventForwarder forwarder = getEventForwarder(); @@ -760,7 +760,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/Comp if (forwarder != null) forwarder.setCurrentTouchEventOffsets(0, top); } -@@ -907,6 +913,9 @@ public class CompositorViewHolder extends FrameLayout +@@ -905,6 +911,9 @@ public class CompositorViewHolder extends FrameLayout int keyboardInset = mApplicationBottomInsetSupplier != null ? mApplicationBottomInsetSupplier.get().webContentsHeightInset : 0; @@ -782,7 +782,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo import java.util.List; -@@ -253,7 +255,10 @@ public class LayoutManagerChrome +@@ -261,7 +263,10 @@ public class LayoutManagerChrome @Override public SwipeHandler createToolbarSwipeHandler(boolean supportSwipeDown) { @@ -794,7 +794,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo } @Override -@@ -488,9 +493,11 @@ public class LayoutManagerChrome +@@ -496,9 +501,11 @@ public class LayoutManagerChrome private static final float SWIPE_RANGE_DEG = 25; private final boolean mSupportSwipeDown; @@ -807,7 +807,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo } @Override -@@ -522,6 +529,9 @@ public class LayoutManagerChrome +@@ -530,6 +537,9 @@ public class LayoutManagerChrome && mScrollDirection == ScrollDirection.DOWN) { RecordUserAction.record("MobileToolbarSwipeOpenStackView"); showLayout(LayoutType.TAB_SWITCHER, true); @@ -817,7 +817,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo } else if (mScrollDirection == ScrollDirection.LEFT || mScrollDirection == ScrollDirection.RIGHT) { startShowing(mToolbarSwipeLayout, true); -@@ -568,6 +578,8 @@ public class LayoutManagerChrome +@@ -576,6 +586,8 @@ public class LayoutManagerChrome direction = ScrollDirection.RIGHT; } else if (swipeAngle < 270 + SWIPE_RANGE_DEG && swipeAngle > 270 - SWIPE_RANGE_DEG) { direction = ScrollDirection.DOWN; @@ -826,19 +826,19 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo } return direction; -@@ -581,7 +593,7 @@ public class LayoutManagerChrome +@@ -589,7 +601,7 @@ public class LayoutManagerChrome return false; } - if (direction == ScrollDirection.DOWN) { + if (direction == ScrollDirection.DOWN || direction == ScrollDirection.UP) { - boolean isAccessibility = ChromeAccessibilityUtil.get().isAccessibilityEnabled(); + boolean isAccessibility = + DeviceClassManager.enableAccessibilityLayout(mHost.getContext()); return isTabSwitcherReady() && !isAccessibility; - } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java -@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.toolbar.ControlContainer; +@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.toolbar.ControlContainer; import org.chromium.chrome.features.start_surface.StartSurface; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; @@ -846,7 +846,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo import java.util.concurrent.Callable; -@@ -96,7 +97,8 @@ public class LayoutManagerChromeTablet extends LayoutManagerChrome { +@@ -100,7 +101,8 @@ public class LayoutManagerChromeTablet extends LayoutManagerChrome { () -> mLayerTitleCache, tabModelStartupInfoSupplier, lifecycleDispatcher, multiInstanceManager, @@ -898,7 +898,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layo diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java -@@ -514,7 +514,7 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate +@@ -521,7 +521,7 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate // position 0 is on the left. Account for that in the offset calculation. boolean isRtl = LocalizationUtils.isLayoutRtl(); boolean useUnadjustedScrollOffset = isRtl != isLeft; @@ -910,7 +910,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java -@@ -61,6 +61,9 @@ import org.chromium.ui.base.LocalizationUtils; +@@ -62,6 +62,9 @@ import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.PageTransition; import org.chromium.ui.resources.ResourceManager; import org.chromium.url.GURL; @@ -920,7 +920,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over import java.util.List; -@@ -151,9 +154,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -166,9 +169,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa private final String mDefaultTitle; private final Supplier mLayerTitleCacheSupplier; @@ -934,7 +934,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over if (mModelSelectorButton.onDown(x, y)) return; getActiveStripLayoutHelper().onDown(time(), x, y, fromMouse, buttons); } -@@ -171,12 +178,14 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -186,12 +193,14 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa @Override public void drag(float x, float y, float dx, float dy, float tx, float ty) { @@ -949,7 +949,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over long time = time(); if (mModelSelectorButton.click(x, y)) { mModelSelectorButton.handleClick(time); -@@ -187,11 +196,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -202,11 +211,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa @Override public void fling(float x, float y, float velocityX, float velocityY) { @@ -963,7 +963,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over getActiveStripLayoutHelper().onLongPress(time(), x, y); } -@@ -253,7 +264,8 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -283,7 +294,8 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa Supplier layerTitleCacheSupplier, ObservableSupplier tabModelStartupInfoSupplier, ActivityLifecycleDispatcher lifecycleDispatcher, @@ -973,7 +973,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over mUpdateHost = updateHost; mLayerTitleCacheSupplier = layerTitleCacheSupplier; mTabStripTreeProvider = new TabStripSceneLayer(context); -@@ -353,6 +365,8 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -387,6 +399,8 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa mModelSelectorButton, multiInstanceManager, toolbarContainerView); mIncognitoHelper = new StripLayoutHelper(context, managerHost, updateHost, renderHost, true, mModelSelectorButton, multiInstanceManager, toolbarContainerView); @@ -982,22 +982,22 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over if (tabModelStartupInfoSupplier != null) { if (tabModelStartupInfoSupplier.hasValue()) { -@@ -443,9 +457,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa - Tab selectedTab = mTabModelSelector.getCurrentModel().getTabAt( - mTabModelSelector.getCurrentModel().index()); - int selectedTabId = selectedTab == null ? TabModel.INVALID_TAB_INDEX : selectedTab.getId(); +@@ -480,9 +494,13 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa + int hoveredTabId = getActiveStripLayoutHelper().getLastHoveredTab() == null + ? TabModel.INVALID_TAB_INDEX + : getActiveStripLayoutHelper().getLastHoveredTab().getId(); + int topControlsHeight = 0; + if (mBrowserControlsManagerSupplier.get() != null) { + topControlsHeight = mBrowserControlsManagerSupplier.get().getTopControlsHeight(); + } mTabStripTreeProvider.pushAndUpdateStrip(this, mLayerTitleCacheSupplier.get(), resourceManager, getActiveStripLayoutHelper().getStripLayoutTabsToRender(), yOffset, -- selectedTabId); -+ selectedTabId, viewport.height(), topControlsHeight); +- selectedTabId, hoveredTabId); ++ selectedTabId, hoveredTabId, viewport.height(), topControlsHeight); return mTabStripTreeProvider; } -@@ -481,7 +499,17 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa +@@ -527,7 +545,17 @@ public class StripLayoutHelperManager implements SceneOverlay, PauseResumeWithNa mIncognitoHelper.onSizeChanged( mWidth, mHeight, orientationChanged, LayoutManagerImpl.time()); @@ -1019,7 +1019,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/over diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java -@@ -12,6 +12,9 @@ import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer; +@@ -13,6 +13,9 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -1029,7 +1029,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scen /** * A SceneLayer to render a static tab. */ -@@ -45,7 +48,10 @@ public class StaticTabSceneLayer extends SceneLayer { +@@ -46,7 +49,10 @@ public class StaticTabSceneLayer extends SceneLayer { float x = model.get(LayoutTab.RENDER_X) * LayoutTab.sDpToPx; float y = model.get(LayoutTab.CONTENT_OFFSET) + model.get(LayoutTab.RENDER_Y) * LayoutTab.sDpToPx; @@ -1038,9 +1038,9 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scen + // the page content window never moves, it is fixed at the top + y = 0; + } + // Check isActiveLayout to prevent pushing a TAB_ID for a static layer that may already be + // invalidated by the next layout. StaticTabSceneLayerJni.get().updateTabLayer(mNativePtr, StaticTabSceneLayer.this, - model.get(LayoutTab.TAB_ID), model.get(LayoutTab.CAN_USE_LIVE_TEXTURE), - model.get(LayoutTab.BACKGROUND_COLOR), x, y, diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java @@ -1082,7 +1082,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scen diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java -@@ -22,6 +22,10 @@ import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer; +@@ -21,6 +21,10 @@ import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.resources.ResourceManager; @@ -1093,12 +1093,12 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scen /** * The Java component of what is basically a CC Layer that manages drawing the Tab Strip (which is -@@ -75,9 +79,23 @@ public class TabStripSceneLayer extends SceneOverlayLayer { - */ +@@ -78,9 +82,23 @@ public class TabStripSceneLayer extends SceneOverlayLayer { public void pushAndUpdateStrip(StripLayoutHelperManager layoutHelper, LayerTitleCache layerTitleCache, ResourceManager resourceManager, -- StripLayoutTab[] stripLayoutTabsToRender, float yOffset, int selectedTabId) { -+ StripLayoutTab[] stripLayoutTabsToRender, float yOffset, int selectedTabId, + StripLayoutTab[] stripLayoutTabsToRender, float yOffset, int selectedTabId, +- int hoveredTabId) { ++ int hoveredTabId, + float viewportHeight, int topControlsHeight) { if (mNativePtr == 0) return; - final boolean visible = yOffset > -layoutHelper.getHeight(); @@ -1212,7 +1212,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/messages/Messag mContainer.setLayoutParams(params); } -@@ -120,6 +129,12 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider +@@ -129,6 +138,12 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider /** @return Offset of the message container from the top of the screen. */ private int getContainerTopOffset() { @@ -1228,7 +1228,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/messages/Messag diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java --- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java -@@ -284,7 +284,7 @@ public class ChromeTabModalPresenter +@@ -282,7 +282,7 @@ public class ChromeTabModalPresenter Resources resources, BrowserControlsStateProvider provider) { int scrimVerticalMargin = resources.getDimensionPixelSize(R.dimen.tab_modal_scrim_vertical_margin); @@ -1240,16 +1240,16 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/Chr diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java -@@ -106,6 +106,8 @@ import org.chromium.content_public.browser.NavigationEntry; +@@ -106,6 +106,8 @@ import org.chromium.content_public.browser.NavigationController; + import org.chromium.content_public.browser.NavigationEntry; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.WindowAndroid; - import org.chromium.ui.mojom.WindowOpenDisposition; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; import java.util.List; -@@ -573,10 +575,15 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -580,10 +582,15 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide // + topControlsDistanceToRest| will give the margin for the current animation frame. final int topControlsDistanceToRest = mBrowserControlsStateProvider.getContentOffset() - mBrowserControlsStateProvider.getTopControlsHeight(); @@ -1267,7 +1267,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. if (topMargin != layoutParams.topMargin || bottomMargin != layoutParams.bottomMargin) { layoutParams.topMargin = topMargin; -@@ -596,7 +603,7 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -603,7 +610,7 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide * strip. */ private int getToolbarExtraYOffset() { @@ -1347,7 +1347,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsP diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java -@@ -85,6 +85,11 @@ import org.chromium.ui.base.WindowDelegate; +@@ -86,6 +86,11 @@ import org.chromium.ui.base.WindowDelegate; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.url.GURL; @@ -1359,7 +1359,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/Se import java.lang.ref.WeakReference; /** Queries the user's default search engine and shows autocomplete suggestions. */ -@@ -211,6 +216,12 @@ public class SearchActivity extends AsyncInitializationActivity +@@ -212,6 +217,12 @@ public class SearchActivity extends AsyncInitializationActivity mSearchBox = (SearchActivityLocationBarLayout) mContentView.findViewById( R.id.search_location_bar); mAnchorView = mContentView.findViewById(R.id.toolbar); @@ -1372,7 +1372,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/Se updateAnchorViewLayout(); // Create status bar color controller and assign to search activity. -@@ -236,7 +247,7 @@ public class SearchActivity extends AsyncInitializationActivity +@@ -237,7 +248,7 @@ public class SearchActivity extends AsyncInitializationActivity getOnBackPressedDispatcher().addCallback(this, backPressManager.getCallback()); } // clang-format off @@ -1384,7 +1384,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/Se diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java -@@ -321,6 +321,11 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity +@@ -323,6 +323,11 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity if (fragment instanceof INeedSnackbarManager) { ((INeedSnackbarManager)fragment).setSnackbarManager(mSnackbarManager); } @@ -1399,7 +1399,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/Settin diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java -@@ -25,6 +25,11 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +@@ -24,6 +24,11 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.resources.ResourceManager; import org.chromium.ui.resources.dynamics.ViewResourceAdapter; @@ -1411,7 +1411,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicato /** * The coordinator for a status indicator that is positioned below the status bar and is persistent. * Typically used to relay status, e.g. indicate user is offline. -@@ -174,6 +179,11 @@ public class StatusIndicatorCoordinator { +@@ -173,6 +178,11 @@ public class StatusIndicatorCoordinator { private void initialize() { final ViewStub stub = mActivity.findViewById(R.id.status_indicator_stub); final ViewResourceFrameLayout root = (ViewResourceFrameLayout) stub.inflate(); @@ -1450,7 +1450,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicato diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java -@@ -179,6 +179,9 @@ import org.chromium.url.GURL; +@@ -184,6 +184,9 @@ import org.chromium.url.GURL; import java.util.List; @@ -1460,8 +1460,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar /** * Contains logic for managing the toolbar visual component. This class manages the interactions * with the rest of the application to ensure the toolbar is always visually up to date. -@@ -647,7 +650,7 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve - mEphemeralTabCoordinatorSupplier); +@@ -661,7 +664,7 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve + mIncognitoStateProvider.isIncognitoSelected())); // clang-format off LocationBarCoordinator locationBarCoordinator = new LocationBarCoordinator( - mActivity.findViewById(R.id.location_bar), toolbarLayout, profileSupplier, @@ -1469,7 +1469,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar PrivacyPreferencesManagerImpl.getInstance(), mLocationBarModel, mActionModeController.getActionModeCallback(), new WindowDelegate(mActivity.getWindow()), windowAndroid, mActivityTabProvider, -@@ -904,11 +907,13 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +@@ -929,11 +932,13 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve // the height won't be measured by the background image. if (mControlContainer.getBackground() == null) { setControlContainerTopMargin(getToolbarExtraYOffset()); @@ -1483,7 +1483,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar mControlContainer.removeOnLayoutChangeListener(mLayoutChangeListener); mLayoutChangeListener = null; } -@@ -1328,13 +1333,25 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +@@ -1354,13 +1359,25 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve return ((LocationBarCoordinator) mLocationBar).getUrlBarTextWithoutAutocomplete(); } @@ -1506,12 +1506,12 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar + mBottomRoot = ((ViewStub) mActivity.findViewById(R.id.bottom_controls_stub)).inflate(); + MoveBottomBarOverTopBar(); mTabGroupUi = TabManagementDelegateProvider.getDelegate().createTabGroupUi(mActivity, -- root.findViewById(R.id.bottom_container_slot), mIncognitoStateProvider, -+ mBottomRoot.findViewById(R.id.bottom_container_slot), mIncognitoStateProvider, - mScrimCoordinator, mOmniboxFocusStateSupplier, mBottomSheetController, - mActivityLifecycleDispatcher, mIsWarmOnResumeSupplier, mTabModelSelector, - mTabContentManager, mCompositorViewHolder, -@@ -1342,8 +1359,9 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +- root.findViewById(R.id.bottom_container_slot), mBrowserControlsSizer, ++ mBottomRoot.findViewById(R.id.bottom_container_slot), mBrowserControlsSizer, + mIncognitoStateProvider, mScrimCoordinator, mOmniboxFocusStateSupplier, + mBottomSheetController, mActivityLifecycleDispatcher, mIsWarmOnResumeSupplier, + mTabModelSelector, mTabContentManager, mCompositorViewHolder, +@@ -1368,8 +1385,9 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve mLayoutStateProviderSupplier, mSnackbarManager); var bottomControlsCoordinator = new BottomControlsCoordinator(mActivity, mWindowAndroid, mLayoutManager, mCompositorViewHolder.getResourceManager(), mBrowserControlsSizer, @@ -1523,7 +1523,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar mBottomControlsCoordinatorSupplier.set(bottomControlsCoordinator); bottomControlsCoordinator.getHandleBackPressChangedSupplier().addObserver( (x) -> { onBackPressStateChanged(); }); -@@ -2156,6 +2174,15 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +@@ -2188,6 +2206,15 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve private void setControlContainerTopMargin(int margin) { final ViewGroup.MarginLayoutParams layoutParams = ((ViewGroup.MarginLayoutParams) mControlContainer.getLayoutParams()); @@ -1594,13 +1594,13 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/Statu +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; + - import org.chromium.base.ApiCompatibilityUtils; - import org.chromium.base.BuildInfo; import org.chromium.base.CallbackController; -@@ -441,6 +445,12 @@ public class StatusBarColorController + import org.chromium.base.supplier.ObservableSupplier; + import org.chromium.chrome.R; +@@ -432,6 +436,12 @@ public class StatusBarColorController boolean needsDarkStatusBarIcons = !ColorUtils.shouldUseLightForegroundOnBackground(color); - ApiCompatibilityUtils.setStatusBarIconColor(root, needsDarkStatusBarIcons); - ApiCompatibilityUtils.setStatusBarColor(window, color); + UiUtils.setStatusBarIconColor(root, needsDarkStatusBarIcons); + UiUtils.setStatusBarColor(window, color); + if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled() && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + UiUtils.setNavigationBarIconColor(window.getDecorView().getRootView(), @@ -1613,7 +1613,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/Statu diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -7912,6 +7912,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -8072,6 +8072,11 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kWindowsScrollingPersonalityDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWindowsScrollingPersonality)}, @@ -1622,9 +1622,9 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc + flag_descriptions::kMoveTopToolbarToBottomDescription, kOsAndroid, + FEATURE_VALUE_TYPE(features::kMoveTopToolbarToBottom)}, + - {"scroll-unification", flag_descriptions::kScrollUnificationName, - flag_descriptions::kScrollUnificationDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kScrollUnification)}, + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) + {"elastic-overscroll", flag_descriptions::kElasticOverscrollName, + flag_descriptions::kElasticOverscrollDescription, kOsWin | kOsAndroid, diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc @@ -1712,7 +1712,7 @@ diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrom diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -1957,6 +1957,10 @@ const char kImprovedKeyboardShortcutsDescription[] = +@@ -1989,6 +1989,10 @@ const char kImprovedKeyboardShortcutsDescription[] = "Ensure keyboard shortcuts work consistently with international keyboard " "layouts and deprecate legacy shortcuts."; @@ -1726,7 +1726,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1095,6 +1095,9 @@ extern const char kImprovedIncognitoScreenshotDescription[]; +@@ -1123,6 +1123,9 @@ extern const char kImprovedIncognitoScreenshotDescription[]; extern const char kImprovedKeyboardShortcutsName[]; extern const char kImprovedKeyboardShortcutsDescription[]; @@ -1779,7 +1779,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse #include "base/no_destructor.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/feature_guide/notifications/feature_notification_guide_service.h" -@@ -247,6 +248,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -252,6 +253,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kInstantStart, &kLensCameraAssistedSearch, &kLensOnQuickActionSearchWidget, @@ -1790,7 +1790,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java -@@ -139,6 +139,23 @@ public class CachedFeatureFlags { +@@ -142,6 +142,23 @@ public class CachedFeatureFlags { CachedFeatureFlagsJni.get().isNetworkServiceWarmUpEnabled()); } @@ -1841,7 +1841,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -310,6 +310,8 @@ public abstract class ChromeFeatureList { +@@ -315,6 +315,8 @@ public abstract class ChromeFeatureList { "MessagesForAndroidPermissionUpdate"; public static final String SEARCH_READY_OMNIBOX = "SearchReadyOmnibox"; public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid"; @@ -1850,7 +1850,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant"; public static final String NOTIFICATION_PERMISSION_BOTTOM_SHEET = "NotificationPermissionBottomSheet"; -@@ -567,6 +569,8 @@ public abstract class ChromeFeatureList { +@@ -574,6 +576,8 @@ public abstract class ChromeFeatureList { new CachedFlag(PRIVACY_GUIDE_POST_MVP, false); public static final CachedFlag sOmniboxMatchToolbarAndStatusBarColor = new CachedFlag(OMNIBOX_MATCH_TOOLBAR_AND_STATUS_BAR_COLOR, false); @@ -1859,7 +1859,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f public static final CachedFlag sOmniboxModernizeVisualUpdate = new CachedFlag(OMNIBOX_MODERNIZE_VISUAL_UPDATE, false); public static final CachedFlag sOmniboxMostVisitedTilesAddRecycledViewPool = -@@ -662,6 +666,7 @@ public abstract class ChromeFeatureList { +@@ -670,6 +674,7 @@ public abstract class ChromeFeatureList { sInstantStart, sInterestFeedV2, sPrivacyGuidePostMVP, @@ -1870,7 +1870,7 @@ diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/f diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -1930,7 +1930,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, +@@ -2037,7 +2037,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, #if BUILDFLAG(IS_ANDROID) registry->RegisterBooleanPref(prefs::kVirtualKeyboardResizesLayoutByDefault, @@ -1993,7 +1993,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow private LocationBarMediator mLocationBarMediator; private View mUrlBar; private View mDeleteButton; -@@ -144,7 +145,7 @@ public class LocationBarCoordinator +@@ -145,7 +146,7 @@ public class LocationBarCoordinator * @param reportExceptionCallback A {@link Callback} to report exceptions. * @param backPressManager The {@link BackPressManager} for intercepting back press. */ @@ -2002,7 +2002,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow ObservableSupplier profileObservableSupplier, PrivacyPreferencesManager privacyPreferencesManager, LocationBarDataProvider locationBarDataProvider, ActionMode.Callback actionModeCallback, -@@ -176,11 +177,12 @@ public class LocationBarCoordinator +@@ -177,11 +178,12 @@ public class LocationBarCoordinator mActivityLifecycleDispatcher = activityLifecycleDispatcher; mActivityLifecycleDispatcher.register(this); mAutocompleteAnchorView = autocompleteAnchorView; @@ -2307,7 +2307,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1716,6 +1716,12 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1743,6 +1743,12 @@ Your Google account may have other forms of browsing history like searches and a Force Tablet Mode @@ -2323,7 +2323,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn --- a/chrome/browser/ui/android/toolbar/BUILD.gn +++ b/chrome/browser/ui/android/toolbar/BUILD.gn -@@ -173,6 +173,7 @@ android_library("java") { +@@ -174,6 +174,7 @@ android_library("java") { "//components/user_prefs/android:java", "//content/public/android:content_java", "//third_party/android_deps:material_design_java", @@ -2547,7 +2547,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java -@@ -61,6 +61,11 @@ import java.lang.annotation.Retention; +@@ -62,6 +62,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.function.BooleanSupplier; @@ -2559,7 +2559,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * Layout for the browser controls (omnibox, menu, tab strip, etc..). */ -@@ -119,6 +124,12 @@ public class ToolbarControlContainer extends OptimizedFrameLayout implements Con +@@ -120,6 +125,12 @@ public class ToolbarControlContainer extends OptimizedFrameLayout implements Con @Override public void initWithToolbar(int toolbarLayoutId) { try (TraceEvent te = TraceEvent.scoped("ToolbarControlContainer.initWithToolbar")) { diff --git a/build/patches/Move-some-account-settings-back-to-privacy-settings.patch b/build/patches/Move-some-account-settings-back-to-privacy-settings.patch index 9afb13e1..a9bfec08 100644 --- a/build/patches/Move-some-account-settings-back-to-privacy-settings.patch +++ b/build/patches/Move-some-account-settings-back-to-privacy-settings.patch @@ -68,7 +68,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting private IncognitoLockSettings mIncognitoLockSettings; private HelpAndFeedbackLauncher mHelpAndFeedbackLauncher; private Profile mProfile; -@@ -144,6 +161,16 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -142,6 +159,16 @@ public class PrivacySettings extends PreferenceFragmentCompat setHasOptionsMenu(true); @@ -85,7 +85,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting ChromeSwitchPreference canMakePaymentPref = (ChromeSwitchPreference) findPreference(PREF_CAN_MAKE_PAYMENT); canMakePaymentPref.setOnPreferenceChangeListener(this); -@@ -224,6 +251,9 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -220,6 +247,9 @@ public class PrivacySettings extends PreferenceFragmentCompat UserPrefs.get(mProfile).setBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED, (boolean) newValue); } else if (PREF_HTTPS_FIRST_MODE.equals(key)) { UserPrefs.get(mProfile).setBoolean(Pref.HTTPS_ONLY_MODE_ENABLED, (boolean) newValue); @@ -95,7 +95,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting } return true; } -@@ -238,6 +268,8 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -234,6 +264,8 @@ public class PrivacySettings extends PreferenceFragmentCompat * Updates the preferences. */ public void updatePreferences() { @@ -107,7 +107,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -447,6 +447,10 @@ CHAR_LIMIT guidelines: +@@ -452,6 +452,10 @@ CHAR_LIMIT guidelines: No statistics or crash reports are sent to Google diff --git a/build/patches/Multiple-fingerprinting-mitigations.patch b/build/patches/Multiple-fingerprinting-mitigations.patch index 63fac26e..05ed9ee5 100644 --- a/build/patches/Multiple-fingerprinting-mitigations.patch +++ b/build/patches/Multiple-fingerprinting-mitigations.patch @@ -62,7 +62,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -2407,6 +2407,7 @@ static_library("browser") { +@@ -2450,6 +2450,7 @@ static_library("browser") { "//services/device/public/cpp:device_features", "//services/device/public/cpp/geolocation", "//services/device/public/cpp/usb", @@ -73,7 +73,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -224,6 +224,8 @@ +@@ -222,6 +222,8 @@ #include "ui/ui_features.h" #include "url/url_features.h" @@ -82,7 +82,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "base/allocator/buildflags.h" #endif -@@ -3877,6 +3879,20 @@ const FeatureEntry kFeatureEntries[] = { +@@ -3908,6 +3910,20 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kWebrtcUseMinMaxVEADimensionsName, flag_descriptions::kWebrtcUseMinMaxVEADimensionsDescription, kOsAll, FEATURE_VALUE_TYPE(blink::features::kWebRtcUseMinMaxVEADimensions)}, @@ -125,7 +125,7 @@ diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content #if BUILDFLAG(IS_ANDROID) #include "base/android/child_process_binding_types.h" #include "content/browser/android/java_interfaces_impl.h" -@@ -3538,6 +3539,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( +@@ -3558,6 +3559,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kDisableBreakpad, switches::kDisableDatabases, switches::kDisableFileSystem, @@ -139,7 +139,7 @@ diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn @@ -102,6 +102,7 @@ target(link_target_type, "child") { - "//third_party/blink/public/common", + "//third_party/blink/public/common:buildflags", "//third_party/blink/public/strings", "//third_party/ced", + "//third_party/ungoogled:switches", @@ -158,7 +158,7 @@ diff --git a/content/child/runtime_features.cc b/content/child/runtime_features. #if BUILDFLAG(IS_ANDROID) #include "base/android/build_info.h" #endif -@@ -567,6 +569,13 @@ void SetCustomizedRuntimeFeaturesFromCombinedArgs( +@@ -556,6 +558,13 @@ void SetCustomizedRuntimeFeaturesFromCombinedArgs( if (!command_line.HasSwitch(switches::kDisableYUVImageDecoding) && base::FeatureList::IsEnabled( blink::features::kDecodeLossyWebPImagesToYUV)) { @@ -196,7 +196,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink #include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/task/single_thread_task_runner.h" -@@ -844,6 +845,17 @@ Document::Document(const DocumentInit& initializer, +@@ -843,6 +844,17 @@ Document::Document(const DocumentInit& initializer, : nullptr), data_(MakeGarbageCollected(GetExecutionContext())) { DCHECK(agent_); @@ -214,7 +214,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution)) script_runner_delayer_->Activate(); -@@ -2294,6 +2306,14 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() { +@@ -2296,6 +2308,14 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() { #endif } @@ -232,7 +232,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h -@@ -532,6 +532,10 @@ class CORE_EXPORT Document : public ContainerNode, +@@ -531,6 +531,10 @@ class CORE_EXPORT Document : public ContainerNode, has_xml_declaration_ = has_xml_declaration ? 1 : 0; } @@ -243,7 +243,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/ AtomicString visibilityState() const; bool IsPageVisible() const; bool hidden() const; -@@ -2432,6 +2436,9 @@ class CORE_EXPORT Document : public ContainerNode, +@@ -2419,6 +2423,9 @@ class CORE_EXPORT Document : public ContainerNode, base::ElapsedTimer start_time_; @@ -256,7 +256,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/ diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc -@@ -2093,6 +2093,7 @@ void Element::ClientQuads(Vector& quads) const { +@@ -2119,6 +2119,7 @@ void Element::ClientQuads(Vector& quads) const { quads.push_back(element_layout_object->LocalToAbsoluteQuad( gfx::QuadF(element_layout_object->ObjectBoundingBox()))); } @@ -264,7 +264,7 @@ diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/ return; } -@@ -2101,6 +2102,10 @@ void Element::ClientQuads(Vector& quads) const { +@@ -2127,6 +2128,10 @@ void Element::ClientQuads(Vector& quads) const { element_layout_object->IsBR()) { element_layout_object->AbsoluteQuads(quads); } @@ -275,7 +275,7 @@ diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/ } DOMRectList* Element::getClientRects() { -@@ -2143,6 +2148,9 @@ gfx::RectF Element::GetBoundingClientRectNoLifecycleUpdate() const { +@@ -2169,6 +2174,9 @@ gfx::RectF Element::GetBoundingClientRectNoLifecycleUpdate() const { DCHECK(element_layout_object); GetDocument().AdjustRectForScrollAndAbsoluteZoom(result, *element_layout_object); @@ -325,7 +325,7 @@ diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creat #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -@@ -208,6 +209,10 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator( +@@ -206,6 +207,10 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator( std::min(info.height(), max_dimension)); src_data_.reset(info, src_data_.addr(), src_data_.rowBytes()); } @@ -470,7 +470,7 @@ diff --git a/third_party/blink/renderer/core/svg/svg_text_content_element.cc b/t diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc -@@ -40,6 +40,7 @@ +@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/platform/graphics/bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h" #include "third_party/blink/renderer/platform/graphics/graphics_context.h" @@ -478,7 +478,7 @@ diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_c #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/stroke_data.h" #include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h" -@@ -2184,6 +2185,10 @@ ImageData* BaseRenderingContext2D::getImageDataInternal( +@@ -2186,6 +2187,10 @@ ImageData* BaseRenderingContext2D::getImageDataInternal( snapshot->PaintImageForCurrentFrame().GetSkImageInfo().bounds(); DCHECK(!bounds.intersect(SkIRect::MakeXYWH(sx, sy, sw, sh))); } @@ -492,7 +492,7 @@ diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_c diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc -@@ -942,9 +942,15 @@ TextMetrics* CanvasRenderingContext2D::measureText(const String& text) { +@@ -924,9 +924,15 @@ TextMetrics* CanvasRenderingContext2D::measureText(const String& text) { TextDirection direction = ToTextDirection(GetState().GetDirection(), canvas()); @@ -519,8 +519,8 @@ diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscre +#include "base/rand_util.h" #include "base/trace_event/trace_event.h" #include "third_party/blink/public/common/features.h" - #include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h" -@@ -747,9 +748,15 @@ TextMetrics* OffscreenCanvasRenderingContext2D::measureText( + #include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_font_stretch.h" +@@ -725,9 +726,15 @@ TextMetrics* OffscreenCanvasRenderingContext2D::measureText( TextDirection direction = ToTextDirection(GetState().GetDirection()); @@ -540,7 +540,7 @@ diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscre diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn -@@ -1656,7 +1656,9 @@ component("platform") { +@@ -1643,7 +1643,9 @@ component("platform") { "//third_party/blink/renderer:non_test_config", ] @@ -551,7 +551,7 @@ diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/re allow_circular_includes_from = [ "//third_party/blink/renderer/platform/blob", -@@ -1727,6 +1729,7 @@ component("platform") { +@@ -1714,6 +1716,7 @@ component("platform") { "//third_party/blink/public/strings", "//third_party/blink/renderer/platform/wtf", "//third_party/ced", @@ -795,8 +795,8 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -2062,6 +2062,15 @@ - status: {"Android": "test", "default": "stable"}, +@@ -2935,6 +2935,15 @@ + status: {"Android": "", "default": "stable"}, base_feature: "none", }, + { @@ -809,7 +809,7 @@ diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 + name: "FingerprintingCanvasImageDataNoise", + }, { - name: "InstalledApp", + name: "RemotePlayback", public: true, diff --git a/third_party/ungoogled/BUILD.gn b/third_party/ungoogled/BUILD.gn new file mode 100644 diff --git a/build/patches/Never-fetch-popular-sites.patch b/build/patches/Never-fetch-popular-sites.patch index 18e373c7..211f17e5 100644 --- a/build/patches/Never-fetch-popular-sites.patch +++ b/build/patches/Never-fetch-popular-sites.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc --- a/components/ntp_tiles/popular_sites_impl.cc +++ b/components/ntp_tiles/popular_sites_impl.cc -@@ -63,7 +63,6 @@ const char kPopularSitesDefaultDirectory[] = "chrome/ntp/"; +@@ -64,7 +64,6 @@ const char kPopularSitesDefaultDirectory[] = "chrome/ntp/"; const char kPopularSitesDefaultCountryCode[] = "DEFAULT"; const char kPopularSitesDefaultVersion[] = "5"; const int kSitesExplorationStartVersion = 6; @@ -18,7 +18,7 @@ diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/p #if BUILDFLAG(IS_IOS) const char kIOSDefaultPopularSitesLocaleUS[] = "https://www.gstatic.com/chrome/ntp/ios/" -@@ -329,7 +328,12 @@ bool PopularSitesImpl::MaybeStartFetch(bool force_download, +@@ -330,7 +329,12 @@ bool PopularSitesImpl::MaybeStartFetch(bool force_download, DCHECK(!callback_); callback_ = std::move(callback); @@ -32,7 +32,7 @@ diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/p prefs_->GetInt64(prefs::kPopularSitesLastDownloadPref)); const base::TimeDelta time_since_last_download = base::Time::Now() - last_download_time; -@@ -346,7 +350,7 @@ bool PopularSitesImpl::MaybeStartFetch(bool force_download, +@@ -347,7 +351,7 @@ bool PopularSitesImpl::MaybeStartFetch(bool force_download, (time_since_last_download > redownload_interval) || url_changed) { FetchPopularSites(); return true; diff --git a/build/patches/Never-use-HTTP-probes-for-connection-detection.patch b/build/patches/Never-use-HTTP-probes-for-connection-detection.patch index 83d3b15e..49c67b3f 100644 --- a/build/patches/Never-use-HTTP-probes-for-connection-detection.patch +++ b/build/patches/Never-use-HTTP-probes-for-connection-detection.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java --- a/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java -@@ -174,7 +174,8 @@ public class ConnectivityDetector implements NetworkChangeNotifier.ConnectionTyp +@@ -175,7 +175,8 @@ public class ConnectivityDetector implements NetworkChangeNotifier.ConnectionTyp @Override public boolean shouldSkipHttpProbes() { diff --git a/build/patches/Offer-builtin-autocomplete-for-chrome-flags.patch b/build/patches/Offer-builtin-autocomplete-for-chrome-flags.patch index 87132e77..05d4c0c0 100644 --- a/build/patches/Offer-builtin-autocomplete-for-chrome-flags.patch +++ b/build/patches/Offer-builtin-autocomplete-for-chrome-flags.patch @@ -10,7 +10,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc -@@ -296,6 +296,8 @@ std::vector ChromeAutocompleteProviderClient::GetBuiltinURLs() { +@@ -289,6 +289,8 @@ std::vector ChromeAutocompleteProviderClient::GetBuiltinURLs() { std::vector ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() { std::vector builtins_to_provide; diff --git a/build/patches/OpenSearch-miscellaneous.patch b/build/patches/OpenSearch-miscellaneous.patch index 2f362380..877e788d 100644 --- a/build/patches/OpenSearch-miscellaneous.patch +++ b/build/patches/OpenSearch-miscellaneous.patch @@ -22,7 +22,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java --- a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java +++ b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java -@@ -249,7 +249,9 @@ public class SearchEngineAdapter extends BaseAdapter +@@ -245,7 +245,9 @@ public class SearchEngineAdapter extends BaseAdapter continue; } if (recentEngineNum < MAX_RECENT_ENGINE_NUM @@ -188,7 +188,7 @@ diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/c #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" -@@ -260,6 +261,7 @@ void ChromeRenderFrameObserver::DidFinishLoad() { +@@ -258,6 +259,7 @@ void ChromeRenderFrameObserver::DidFinishLoad() { GURL osdd_url = frame->GetDocument().OpenSearchDescriptionURL(); if (!osdd_url.is_empty()) { @@ -240,19 +240,19 @@ diff --git a/components/search_engines/template_url_fetcher.cc b/components/sear diff --git a/components/search_engines/template_url_parser.cc b/components/search_engines/template_url_parser.cc --- a/components/search_engines/template_url_parser.cc +++ b/components/search_engines/template_url_parser.cc -@@ -171,7 +171,7 @@ void SafeTemplateURLParser::OnXmlParseComplete( - data_decoder::DataDecoder::ValueOrError value_or_error) { +@@ -173,7 +173,7 @@ void SafeTemplateURLParser::OnXmlParseComplete( std::move(callback_).Run([&]() -> std::unique_ptr { - if (!value_or_error.has_value()) { -- DLOG(ERROR) << "Failed to parse XML: " << value_or_error.error(); -+ LOG(ERROR) << "Failed to parse XML: " << value_or_error.error(); - return nullptr; - } - const base::Value& root = *value_or_error; + ASSIGN_OR_RETURN(const base::Value root, std::move(value_or_error), + [](std::string error) -> std::unique_ptr { +- DLOG(ERROR) ++ LOG(ERROR) + << "Failed to parse XML: " << std::move(error); + return nullptr; + }); diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h -@@ -264,7 +264,10 @@ class TemplateURLService : public WebDataServiceConsumer, +@@ -271,7 +271,10 @@ class TemplateURLService : public WebDataServiceConsumer, void UpdateProviderFavicons(const GURL& potential_search_url, const GURL& favicon_url); @@ -264,7 +264,7 @@ diff --git a/components/search_engines/template_url_service.h b/components/searc // regardless of |url| if the default search provider is managed by policy or // controlled by an extension. bool CanMakeDefault(const TemplateURL* url) const; -@@ -626,9 +629,6 @@ class TemplateURLService : public WebDataServiceConsumer, +@@ -633,9 +636,6 @@ class TemplateURLService : public WebDataServiceConsumer, // SetKeywordSearchTermsForURL is invoked. void UpdateKeywordSearchTermsForURL(const URLVisitedDetails& details); diff --git a/build/patches/Override-Navigator-Language.patch b/build/patches/Override-Navigator-Language.patch index 03841e7a..0225400f 100644 --- a/build/patches/Override-Navigator-Language.patch +++ b/build/patches/Override-Navigator-Language.patch @@ -60,7 +60,7 @@ diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content #include "components/metrics/single_sample_metrics.h" #include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h" #include "components/services/storage/public/cpp/buckets/bucket_id.h" -@@ -3463,8 +3464,11 @@ void RenderProcessHostImpl::AppendRendererCommandLine( +@@ -3473,8 +3474,11 @@ void RenderProcessHostImpl::AppendRendererCommandLine( PropagateBrowserCommandLineToRenderer(browser_command_line, command_line); // Pass on the browser locale. diff --git a/build/patches/Partition-Blink-memory-cache.patch b/build/patches/Partition-Blink-memory-cache.patch index e7bda119..2a665f70 100644 --- a/build/patches/Partition-Blink-memory-cache.patch +++ b/build/patches/Partition-Blink-memory-cache.patch @@ -54,7 +54,7 @@ diff --git a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc -@@ -2296,7 +2296,7 @@ bool InspectorNetworkAgent::FetchResourceContent(Document* document, +@@ -2315,7 +2315,7 @@ bool InspectorNetworkAgent::FetchResourceContent(Document* document, Resource* cached_resource = document->Fetcher()->CachedResource(url); if (!cached_resource) { cached_resource = MemoryCache::Get()->ResourceForURL( @@ -175,7 +175,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/t diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc -@@ -808,7 +808,8 @@ Resource* ResourceFetcher::CreateResourceForStaticData( +@@ -839,7 +839,8 @@ Resource* ResourceFetcher::CreateResourceForStaticData( if (!archive_ && factory.GetType() == ResourceType::kRaw) return nullptr; @@ -185,7 +185,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c // Most off-main-thread resource fetches use Resource::kRaw and don't reach // this point, but off-main-thread module fetches might. if (IsMainThread()) { -@@ -1294,7 +1295,9 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, +@@ -1326,7 +1327,9 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, resource = nullptr; } else { resource = MemoryCache::Get()->ResourceForURL( @@ -196,7 +196,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c } if (resource) { policy = DetermineRevalidationPolicy(resource_type, params, *resource, -@@ -1408,6 +1411,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, +@@ -1440,6 +1443,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, if (resource_cache_remote_.is_bound()) { resource_cache_remote_->Contains( params.Url(), @@ -205,7 +205,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c WTF::BindOnce(&ResourceFetcher::OnResourceCacheContainsFinished, WrapWeakPersistent(this), base::TimeTicks::Now(), resource_request.GetRequestDestination())); -@@ -1549,7 +1554,8 @@ Resource* ResourceFetcher::CreateResourceForLoading( +@@ -1581,7 +1586,8 @@ Resource* ResourceFetcher::CreateResourceForLoading( const FetchParameters& params, const ResourceFactory& factory) { const String cache_identifier = @@ -215,7 +215,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c if (!base::FeatureList::IsEnabled( blink::features::kScopeMemoryCachePerContext)) { DCHECK(!IsMainThread() || params.IsStaleRevalidation() || -@@ -2563,10 +2569,13 @@ void ResourceFetcher::UpdateAllImageResourcePriorities() { +@@ -2582,10 +2588,13 @@ void ResourceFetcher::UpdateAllImageResourcePriorities() { to_be_removed.clear(); } @@ -231,7 +231,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c } // Requests that can be satisfied via `archive_` (i.e. MHTML) or -@@ -2579,7 +2588,7 @@ String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { +@@ -2598,7 +2607,7 @@ String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { if (bundle) return bundle->GetCacheIdentifier(); @@ -243,7 +243,7 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.c diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h -@@ -258,7 +258,8 @@ class PLATFORM_EXPORT ResourceFetcher +@@ -261,7 +261,8 @@ class PLATFORM_EXPORT ResourceFetcher uint32_t inflight_keepalive_bytes); blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const; diff --git a/build/patches/Re-introduce-modal-dialog-flag-to-close-all-tabs.patch b/build/patches/Re-introduce-modal-dialog-flag-to-close-all-tabs.patch index f677102a..61631fbc 100644 --- a/build/patches/Re-introduce-modal-dialog-flag-to-close-all-tabs.patch +++ b/build/patches/Re-introduce-modal-dialog-flag-to-close-all-tabs.patch @@ -8,32 +8,30 @@ This reverts commit 614a998c5af5dcd36baffa6d65090c0b8decb03f. License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../tab_management/CloseAllTabsDialog.java | 6 +++++ - .../CloseAllTabsDialogTest.java | 3 +++ - .../CloseAllTabsDialogUnitTest.java | 23 +++++++++++++++++++ - chrome/browser/about_flags.cc | 7 ++++++ - chrome/browser/flag_descriptions.cc | 5 ++++ - chrome/browser/flag_descriptions.h | 3 +++ - .../flags/android/chrome_feature_list.cc | 9 ++++++-- - .../flags/android/chrome_feature_list.h | 1 + - .../browser/flags/ChromeFeatureList.java | 1 + - 9 files changed, 56 insertions(+), 2 deletions(-) + .../browser/tasks/tab_management/CloseAllTabsDialog.java | 6 ++++++ + chrome/browser/about_flags.cc | 7 +++++++ + chrome/browser/flag_descriptions.cc | 5 +++++ + chrome/browser/flag_descriptions.h | 3 +++ + chrome/browser/flags/android/chrome_feature_list.cc | 9 +++++++-- + chrome/browser/flags/android/chrome_feature_list.h | 1 + + .../chromium/chrome/browser/flags/ChromeFeatureList.java | 1 + + 7 files changed, 30 insertions(+), 2 deletions(-) diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java -@@ -9,6 +9,7 @@ import android.content.Context; +@@ -12,6 +12,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.R; + import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.ui.modaldialog.DialogDismissalCause; - import org.chromium.ui.modaldialog.ModalDialogManager; -@@ -30,6 +31,11 @@ public class CloseAllTabsDialog { +@@ -35,6 +36,11 @@ public class CloseAllTabsDialog { public static void show(Context context, - Supplier modalDialogManagerSupplier, Runnable onCloseAll, - boolean isIncognito) { + Supplier modalDialogManagerSupplier, + @NonNull TabModelSelector tabModelSelector, Runnable onCloseAll) { + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CLOSE_ALL_TABS_MODAL_DIALOG)) { + onCloseAll.run(); + return; @@ -41,97 +39,11 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser + assert modalDialogManagerSupplier.hasValue(); final ModalDialogManager manager = modalDialogManagerSupplier.get(); - -diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java ---- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java -+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java -@@ -28,11 +28,13 @@ import org.chromium.base.test.params.ParameterSet; - import org.chromium.base.test.params.ParameterizedRunner; - import org.chromium.base.test.util.CommandLineFlags; - import org.chromium.base.test.util.Restriction; -+import org.chromium.chrome.browser.flags.ChromeFeatureList; - import org.chromium.chrome.browser.flags.ChromeSwitches; - import org.chromium.chrome.browser.tabmodel.TabModelSelector; - import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport; - import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; - import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.chrome.test.util.browser.Features.EnableFeatures; - import org.chromium.content_public.browser.test.util.TestThreadUtils; - import org.chromium.ui.test.util.UiRestriction; - -@@ -44,6 +46,7 @@ import java.util.List; - */ - @RunWith(ParameterizedRunner.class) - @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -+@EnableFeatures({ChromeFeatureList.CLOSE_ALL_TABS_MODAL_DIALOG}) - @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) - public class CloseAllTabsDialogTest { - @ParameterAnnotations.ClassParameter -diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogUnitTest.java ---- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogUnitTest.java -+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogUnitTest.java -@@ -22,8 +22,10 @@ import org.mockito.Mockito; - import org.mockito.MockitoAnnotations; - import org.robolectric.annotation.Config; - -+import org.chromium.base.FeatureList; - import org.chromium.base.test.BaseRobolectricTestRunner; - import org.chromium.base.test.util.HistogramWatcher; -+import org.chromium.chrome.browser.flags.ChromeFeatureList; - import org.chromium.chrome.tab_ui.R; - import org.chromium.ui.modaldialog.DialogDismissalCause; - import org.chromium.ui.modaldialog.ModalDialogManager; -@@ -122,6 +124,7 @@ public class CloseAllTabsDialogUnitTest { - @Test - @SmallTest - public void testDialog() { -+ enableFeature(true); - final boolean isIncognito = false; - CloseAllTabsDialog.show(mContext, this::getModalDialogManager, - () -> { mRunnableCalled = true; }, isIncognito); -@@ -142,6 +145,7 @@ public class CloseAllTabsDialogUnitTest { - @Test - @SmallTest - public void testDismissButton() { -+ enableFeature(true); - final boolean isIncognito = true; - CloseAllTabsDialog.show(mContext, this::getModalDialogManager, - () -> { mRunnableCalled = true; }, isIncognito); -@@ -162,6 +166,7 @@ public class CloseAllTabsDialogUnitTest { - @Test - @SmallTest - public void testDismissNoButton() { -+ enableFeature(true); - final boolean isIncognito = false; - CloseAllTabsDialog.show(mContext, this::getModalDialogManager, - () -> { mRunnableCalled = true; }, isIncognito); -@@ -179,4 +184,22 @@ public class CloseAllTabsDialogUnitTest { - verifyDismissed(); - histograms.assertExpected(); - } -+ -+ @Test -+ @SmallTest -+ public void testDialogInactive() { -+ enableFeature(false); -+ final boolean isIncognito = false; -+ CloseAllTabsDialog.show(mContext, this::getModalDialogManager, -+ () -> { mRunnableCalled = true; }, isIncognito); -+ -+ assertNull(mMockModalDialogManager.getDialogModel()); -+ assertTrue(mRunnableCalled); -+ } -+ -+ private void enableFeature(boolean enable) { -+ FeatureList.TestValues values = new FeatureList.TestValues(); -+ values.addFeatureFlagOverride(ChromeFeatureList.CLOSE_ALL_TABS_MODAL_DIALOG, enable); -+ FeatureList.setTestValues(values); -+ } - } + final boolean isIncognito = tabModelSelector.getCurrentModel().isIncognito(); diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9469,6 +9469,13 @@ const FeatureEntry kFeatureEntries[] = { +@@ -9585,6 +9585,13 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(base::i18n::kLacrosMergeIcuDataFile)}, #endif @@ -148,7 +60,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -3849,6 +3849,11 @@ const char kChimeAndroidSdkDescription[] = +@@ -3903,6 +3903,11 @@ const char kChimeAndroidSdkDescription[] = "Enable Chime SDK to receive push notification."; const char kChimeAndroidSdkName[] = "Use Chime SDK"; @@ -176,16 +88,16 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -170,6 +170,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -173,6 +173,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kBackGestureActivityTabProvider, &kBackGestureRefactorActivityAndroid, &kBackGestureRefactorAndroid, + &kCloseAllTabsModalDialog, &kBackgroundThreadPool, &kBaselineGM3SurfaceColors, - &kCastDeviceFilter, -@@ -493,6 +494,10 @@ BASE_FEATURE(kBaselineGM3SurfaceColors, - "BaselineGM3SurfaceColors", + &kCacheActivityTaskID, +@@ -506,6 +507,10 @@ BASE_FEATURE(kCacheActivityTaskID, + "CacheActivityTaskID", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kCloseAllTabsModalDialog, @@ -195,7 +107,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse // Used in downstream code. BASE_FEATURE(kCastDeviceFilter, "CastDeviceFilter", -@@ -503,8 +508,8 @@ BASE_FEATURE(kClearOmniboxFocusAfterNavigation, +@@ -516,8 +521,8 @@ BASE_FEATURE(kClearOmniboxFocusAfterNavigation, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kCloseTabSuggestions, @@ -209,9 +121,9 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -31,6 +31,7 @@ BASE_DECLARE_FEATURE(kBackGestureRefactorAndroid); - BASE_DECLARE_FEATURE(kBackgroundThreadPool); +@@ -35,6 +35,7 @@ BASE_DECLARE_FEATURE(kBackgroundThreadPool); BASE_DECLARE_FEATURE(kBaselineGM3SurfaceColors); + BASE_DECLARE_FEATURE(kCacheActivityTaskID); BASE_DECLARE_FEATURE(kClearOmniboxFocusAfterNavigation); +BASE_DECLARE_FEATURE(kCloseAllTabsModalDialog); BASE_DECLARE_FEATURE(kCloseTabSuggestions); @@ -220,13 +132,13 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -187,6 +187,7 @@ public abstract class ChromeFeatureList { +@@ -194,6 +194,7 @@ public abstract class ChromeFeatureList { public static final String CCT_RESIZABLE_90_MAXIMUM_HEIGHT = "CCTResizable90MaximumHeight"; public static final String CCT_RESIZABLE_ALLOW_RESIZE_BY_USER_GESTURE = "CCTResizableAllowResizeByUserGesture"; + public static final String CLOSE_ALL_TABS_MODAL_DIALOG = "CloseAllTabsModalDialog"; public static final String CCT_RESIZABLE_FOR_THIRD_PARTIES = "CCTResizableForThirdParties"; public static final String CCT_RESIZABLE_SIDE_SHEET = "CCTResizableSideSheet"; - public static final String CCT_RESIZABLE_SIDE_SHEET_DISCOVER_FEED_SETTINGS = + public static final String CCT_RESIZABLE_SIDE_SHEET_FOR_THIRD_PARTIES = -- 2.25.1 diff --git a/build/patches/Re-introduce-override_build_timestamp.patch b/build/patches/Re-introduce-override_build_timestamp.patch index 3e4b201b..facf841d 100644 --- a/build/patches/Re-introduce-override_build_timestamp.patch +++ b/build/patches/Re-introduce-override_build_timestamp.patch @@ -16,7 +16,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/base/BUILD.gn b/base/BUILD.gn --- a/base/BUILD.gn +++ b/base/BUILD.gn -@@ -4104,8 +4104,13 @@ action("build_date") { +@@ -4068,8 +4068,13 @@ action("build_date") { args = [ rebase_path("$target_gen_dir/generated_build_date.h", root_build_dir), diff --git a/build/patches/Reduce-HTTP-headers-in-DoH-requests-to-bare-minimum.patch b/build/patches/Reduce-HTTP-headers-in-DoH-requests-to-bare-minimum.patch index 56754dd3..3c182c6f 100644 --- a/build/patches/Reduce-HTTP-headers-in-DoH-requests-to-bare-minimum.patch +++ b/build/patches/Reduce-HTTP-headers-in-DoH-requests-to-bare-minimum.patch @@ -4,18 +4,19 @@ Subject: Reduce HTTP headers in DoH requests to bare minimum License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - net/base/load_flags_list.h | 5 +++++ - net/dns/dns_transaction.cc | 2 +- - net/url_request/url_request_http_job.cc | 8 ++++++-- - 3 files changed, 12 insertions(+), 3 deletions(-) + net/base/load_flags_list.h | 6 ++++++ + net/dns/dns_transaction.cc | 2 +- + net/url_request/url_request_http_job.cc | 10 +++++++--- + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h --- a/net/base/load_flags_list.h +++ b/net/base/load_flags_list.h -@@ -103,3 +103,8 @@ LOAD_FLAG(RESTRICTED_PREFETCH, 1 << 15) - // is considered privileged, and therefore this flag must only be set from a - // trusted process. - LOAD_FLAG(CAN_USE_RESTRICTED_PREFETCH, 1 << 16) +@@ -110,3 +110,9 @@ LOAD_FLAG(CAN_USE_SHARED_DICTIONARY, 1 << 17) + // Indicates that CAN_USE_SHARED_DICTIONARY must be disabled after a redirect to + // another origin. + LOAD_FLAG(DISABLE_SHARED_DICTIONARY_AFTER_CROSS_ORIGIN_REDIRECT, 1 << 18) ++ +// This load will not send Accept-Language or User-Agent headers, and not +// advertise brotli encoding. +// Used to comply with IETF (draft) DNS-over-HTTPS: @@ -24,7 +25,7 @@ diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc --- a/net/dns/dns_transaction.cc +++ b/net/dns/dns_transaction.cc -@@ -478,7 +478,7 @@ class DnsHTTPAttempt : public DnsAttempt, public URLRequest::Delegate { +@@ -480,7 +480,7 @@ class DnsHTTPAttempt : public DnsAttempt, public URLRequest::Delegate { // avoid deadlock and enable the use of preconfigured IP addresses. request_->SetSecureDnsPolicy(SecureDnsPolicy::kBootstrap); request_->SetLoadFlags(request_->load_flags() | LOAD_DISABLE_CACHE | @@ -36,7 +37,7 @@ diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc -@@ -351,6 +351,7 @@ void URLRequestHttpJob::OnGotFirstPartySetCacheFilterMatchInfo( +@@ -350,6 +350,7 @@ void URLRequestHttpJob::OnGotFirstPartySetCacheFilterMatchInfo( // fields in the referrer. GURL referrer(request_->referrer()); @@ -44,7 +45,7 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque // Our consumer should have made sure that this is a safe referrer (e.g. via // URLRequestJob::ComputeReferrerForPolicy). if (referrer.is_valid()) { -@@ -358,11 +359,14 @@ void URLRequestHttpJob::OnGotFirstPartySetCacheFilterMatchInfo( +@@ -357,11 +358,14 @@ void URLRequestHttpJob::OnGotFirstPartySetCacheFilterMatchInfo( request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer, referer_value); } @@ -59,12 +60,14 @@ diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_reque AddExtraHeaders(); -@@ -615,9 +619,9 @@ void URLRequestHttpJob::StartTransactionInternal() { +@@ -618,10 +622,10 @@ void URLRequestHttpJob::StartTransactionInternal() { void URLRequestHttpJob::AddExtraHeaders() { request_info_.extra_headers.SetAcceptEncodingIfMissing( request()->url(), request()->accepted_stream_types(), -- request()->context()->enable_brotli()); -+ !(request_info_.load_flags & LOAD_MINIMAL_HEADERS) && request()->context()->enable_brotli()); +- request()->context()->enable_brotli(), +- request()->context()->enable_zstd()); ++ !(request_info_.load_flags & LOAD_MINIMAL_HEADERS) && request()->context()->enable_brotli(), ++ !(request_info_.load_flags & LOAD_MINIMAL_HEADERS) && request()->context()->enable_zstd()); - if (http_user_agent_settings_) { + if (!(request_info_.load_flags & LOAD_MINIMAL_HEADERS) && http_user_agent_settings_) { diff --git a/build/patches/Remove-HTTP-referrals-in-cross-origin-navigation.patch b/build/patches/Remove-HTTP-referrals-in-cross-origin-navigation.patch index 57df2f25..cacb0fad 100644 --- a/build/patches/Remove-HTTP-referrals-in-cross-origin-navigation.patch +++ b/build/patches/Remove-HTTP-referrals-in-cross-origin-navigation.patch @@ -24,12 +24,11 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../strings/android_chrome_strings.grd | 24 +++++ chrome/browser/ui/prefs/pref_watcher.cc | 2 + chrome/browser/ui/prefs/prefs_tab_helper.cc | 2 + - chrome/common/pref_names.cc | 3 + - chrome/common/pref_names.h | 1 + + chrome/common/pref_names.h | 3 + .../renderer_host/navigation_request.cc | 8 ++ .../network/public/cpp/resource_request.h | 2 +- .../renderer_preferences.h | 1 + - 18 files changed, 307 insertions(+), 1 deletion(-) + 17 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 chrome/android/java/res/layout/radio_button_group_referer_policy_preference.xml create mode 100644 chrome/android/java/res/xml/referer_policy_preferences.xml create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/RadioButtonGroupRefererSettings.java @@ -38,7 +37,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -671,6 +671,8 @@ chrome_java_resources = [ +@@ -675,6 +675,8 @@ chrome_java_resources = [ "java/res/xml/incognito_preferences.xml", "java/res/xml/privacy_preferences.xml", "java/res/xml/privacy_preferences_v2.xml", @@ -50,7 +49,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -955,6 +955,8 @@ chrome_java_sources = [ +@@ -964,6 +964,8 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImpl.java", "java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java", "java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java", @@ -180,7 +179,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting private static final String PREF_PRIVACY_SANDBOX = "privacy_sandbox"; private static final String PREF_PROXY_OPTIONS = "proxy"; private static final String PREF_PRIVACY_GUIDE = "privacy_guide"; -@@ -358,6 +360,10 @@ public class PrivacySettings extends PreferenceFragmentCompat +@@ -354,6 +356,10 @@ public class PrivacySettings extends PreferenceFragmentCompat : R.string.text_off); } @@ -372,7 +371,7 @@ new file mode 100644 diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc -@@ -471,6 +471,9 @@ SystemNetworkContextManager::SystemNetworkContextManager( +@@ -520,6 +520,9 @@ SystemNetworkContextManager::SystemNetworkContextManager( base::BindRepeating(&SystemNetworkContextManager::UpdateReferrersEnabled, base::Unretained(this))); @@ -382,7 +381,7 @@ diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/brows pref_change_registrar_.Add( prefs::kExplicitlyAllowedNetworkPorts, base::BindRepeating( -@@ -562,6 +565,7 @@ void SystemNetworkContextManager::RegisterPrefs(PrefRegistrySimple* registry) { +@@ -611,6 +614,7 @@ void SystemNetworkContextManager::RegisterPrefs(PrefRegistrySimple* registry) { // the system NetworkContext, and the per-profile pref values are used for // the profile NetworkContexts. registry->RegisterBooleanPref(prefs::kEnableReferrers, true); @@ -404,7 +403,7 @@ diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/render diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -969,6 +969,30 @@ CHAR_LIMIT guidelines: +@@ -993,6 +993,30 @@ CHAR_LIMIT guidelines: For example, some websites may respond to this request by showing you ads that aren’t based on other websites you’ve visited. Many websites will still collect and use your browsing data — for example to improve security, to provide content, ads and recommendations, and to generate reporting statistics. @@ -438,7 +437,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/chrome/browser/ui/prefs/pref_watcher.cc b/chrome/browser/ui/prefs/pref_watcher.cc --- a/chrome/browser/ui/prefs/pref_watcher.cc +++ b/chrome/browser/ui/prefs/pref_watcher.cc -@@ -84,6 +84,8 @@ PrefWatcher::PrefWatcher(Profile* profile) : profile_(profile) { +@@ -97,6 +97,8 @@ PrefWatcher::PrefWatcher(Profile* profile) : profile_(profile) { renderer_callback); profile_pref_change_registrar_.Add(prefs::kEnableReferrers, renderer_callback); @@ -459,34 +458,23 @@ diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/pre registry->RegisterBooleanPref(prefs::kEnableEncryptedMedia, true); registry->RegisterBooleanPref(prefs::kScrollToTextFragmentEnabled, false); #if BUILDFLAG(IS_ANDROID) -diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc ---- a/chrome/common/pref_names.cc -+++ b/chrome/common/pref_names.cc -@@ -1362,6 +1362,9 @@ const char kEnableHyperlinkAuditing[] = "enable_a_ping"; - // Whether to enable sending referrers. - const char kEnableReferrers[] = "enable_referrers"; - -+// Set referrer policy. -+const char kReferrersPolicy[] = "referrers_policy"; -+ - // Whether to send the DNT header. - const char kEnableDoNotTrack[] = "enable_do_not_track"; - diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h -@@ -415,6 +415,7 @@ extern const char kPinnedTabs[]; - extern const char kDisable3DAPIs[]; - extern const char kEnableHyperlinkAuditing[]; - extern const char kEnableReferrers[]; -+extern const char kReferrersPolicy[]; - extern const char kEnableDoNotTrack[]; - extern const char kEnableEncryptedMedia[]; +@@ -1495,6 +1495,9 @@ inline constexpr char kEnableDoNotTrack[] = "enable_do_not_track"; + inline constexpr char kEnableEncryptedMedia[] = + "webkit.webprefs.encrypted_media_enabled"; ++// Set referrer policy. ++inline constexpr char kReferrersPolicy[] = "referrers_policy"; ++ + // Boolean that specifies whether to import the form data for autofill from the + // default browser on first run. + inline constexpr char kImportAutofillFormData[] = "import_autofill_form_data"; diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc -@@ -390,6 +390,14 @@ void AddAdditionalRequestHeaders( +@@ -391,6 +391,14 @@ void AddAdditionalRequestHeaders( blink::mojom::Referrer(GURL(), network::mojom::ReferrerPolicy::kNever); } @@ -504,7 +492,7 @@ diff --git a/content/browser/renderer_host/navigation_request.cc b/content/brows diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h -@@ -135,7 +135,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { +@@ -144,7 +144,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { std::vector navigation_redirect_chain; GURL referrer; diff --git a/build/patches/Remove-SMS-integration.patch b/build/patches/Remove-SMS-integration.patch index 43bdd785..41565605 100644 --- a/build/patches/Remove-SMS-integration.patch +++ b/build/patches/Remove-SMS-integration.patch @@ -75,8 +75,8 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/sms/Sm - import org.chromium.base.ContextUtils; import org.chromium.base.Log; - import org.chromium.base.annotations.CalledByNative; -@@ -43,17 +40,11 @@ public class SmsProviderGms { + import org.chromium.base.ResettersForTesting; +@@ -44,17 +41,11 @@ public class SmsProviderGms { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public SmsProviderGms(long smsProviderGmsAndroid, @GmsBackend int backend, @@ -95,7 +95,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/sms/Sm if (mBackend == GmsBackend.AUTO || mBackend == GmsBackend.USER_CONSENT) { mUserConsentReceiver = new SmsUserConsentReceiver(this, mContext); } -@@ -85,12 +76,7 @@ public class SmsProviderGms { +@@ -86,12 +77,7 @@ public class SmsProviderGms { @CalledByNative private static SmsProviderGms create(long smsProviderGmsAndroid, @GmsBackend int backend) { Log.d(TAG, "Creating SmsProviderGms"); @@ -109,7 +109,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/sms/Sm } @CalledByNative -@@ -179,13 +165,6 @@ public class SmsProviderGms { +@@ -180,13 +166,6 @@ public class SmsProviderGms { } public Wrappers.SmsRetrieverClientWrapper getClient() { diff --git a/build/patches/Remove-binary-blob-integrations.patch b/build/patches/Remove-binary-blob-integrations.patch index 03c67405..8fa472e1 100644 --- a/build/patches/Remove-binary-blob-integrations.patch +++ b/build/patches/Remove-binary-blob-integrations.patch @@ -54,7 +54,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html chrome/browser/ui/webauthn/sheet_models.cc | 7 +- .../webui/chrome_web_ui_controller_factory.cc | 3 - chrome/browser/webauthn/android/BUILD.gn | 1 - - .../CableAuthenticatorModuleProvider.java | 22 +- + .../CableAuthenticatorModuleProvider.java | 23 +- .../authenticator_request_dialog_model.cc | 4 - chrome/browser/webauthn/cablev2_devices.cc | 3 + chrome/test/android/BUILD.gn | 2 - @@ -66,7 +66,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/gcm_driver/gcm_client_impl.cc | 4 + .../gcm_driver/instance_id/android/BUILD.gn | 3 - .../instance_id/InstanceIDBridge.java | 47 +- - .../media_router/browser/android/BUILD.gn | 9 - + .../media_router/browser/android/BUILD.gn | 11 - .../media_router/BrowserMediaRouter.java | 18 +- .../components/media_router/MediaSink.java | 44 +- .../media_router/MediaStatusBridge.java | 40 +- @@ -89,7 +89,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/signin/public/android/BUILD.gn | 3 - .../signin/AccountRenameChecker.java | 16 - components/webauthn/android/BUILD.gn | 11 - - .../webauthn/AuthenticatorImpl.java | 83 +-- + .../webauthn/AuthenticatorImpl.java | 89 +-- .../webauthn/Fido2ApiCallHelper.java | 58 +- .../push_messaging/push_messaging_manager.cc | 2 +- content/public/android/BUILD.gn | 4 - @@ -102,14 +102,15 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html third_party/android_deps/BUILD.gn | 570 +----------------- .../preconditions/javatests/BUILD.gn | 1 - .../gms/ChromiumPlayServicesAvailability.java | 10 +- + third_party/cardboard/BUILD.gn | 4 - weblayer/browser/java/BUILD.gn | 1 - weblayer/public/java/BUILD.gn | 1 - - 80 files changed, 96 insertions(+), 1978 deletions(-) + 81 files changed, 96 insertions(+), 1991 deletions(-) diff --git a/android_webview/expectations/system_webview_bundle.AndroidManifest.expected b/android_webview/expectations/system_webview_bundle.AndroidManifest.expected --- a/android_webview/expectations/system_webview_bundle.AndroidManifest.expected +++ b/android_webview/expectations/system_webview_bundle.AndroidManifest.expected -@@ -21,10 +21,6 @@ +@@ -22,10 +22,6 @@ android:icon="@$PACKAGE:drawable/icon_webview" android:label="Android System WebView" android:multiArch="true"> @@ -120,7 +121,7 @@ diff --git a/android_webview/expectations/system_webview_bundle.AndroidManifest. # DIFF-ANCHOR: ea1a94af # DIFF-ANCHOR: b7cc06e9 @@ -143,7 +144,7 @@ diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -272,14 +272,6 @@ if (current_toolchain == default_toolchain) { +@@ -280,14 +280,6 @@ if (current_toolchain == default_toolchain) { ":chrome_public_apk_template_resources", ":update_proto_java", ":usage_stats_proto_java", @@ -158,7 +159,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//base:jni_java", "//cc:cc_java", "//cc/mojom:mojom_java", -@@ -582,14 +574,23 @@ if (current_toolchain == default_toolchain) { +@@ -598,14 +590,23 @@ if (current_toolchain == default_toolchain) { "//services/shape_detection:shape_detection_java", "//services/shape_detection/public/mojom:mojom_java", "//skia/public/mojom:mojom_java", @@ -185,7 +186,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/android_media:android_media_java", "//third_party/android_swipe_refresh:android_swipe_refresh_java", -@@ -867,12 +868,6 @@ if (current_toolchain == default_toolchain) { +@@ -883,12 +884,6 @@ if (current_toolchain == default_toolchain) { ":chrome_java", ":chrome_jni_headers", ":delegate_public_impl_java", @@ -198,7 +199,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//base:base_java_test_support", "//base:base_java_test_support_uncommon", "//base:base_junit_test_support", -@@ -1455,13 +1450,6 @@ if (current_toolchain == default_toolchain) { +@@ -1486,13 +1481,6 @@ if (current_toolchain == default_toolchain) { ":chrome_test_util_java", ":critical_persisted_tab_data_flatbuffer_test_v1_java", ":delegate_public_impl_java", @@ -212,7 +213,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//base:base_java", "//base:base_java_test_support", "//base:base_java_test_support_uncommon", -@@ -2352,7 +2340,6 @@ if (current_toolchain == default_toolchain) { +@@ -2408,7 +2396,6 @@ if (current_toolchain == default_toolchain) { ] deps = [ ":chrome_java", @@ -220,7 +221,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//base:base_java", "//base:base_java_test_support", "//base:jni_java", -@@ -2449,7 +2436,6 @@ if (current_toolchain == default_toolchain) { +@@ -2507,7 +2494,6 @@ if (current_toolchain == default_toolchain) { # is in a DFM. android_library("base_module_java") { sources = [ @@ -228,7 +229,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "java/src/org/chromium/chrome/app/TrichromeZygotePreload.java", "java/src/org/chromium/chrome/browser/ChromeBackgroundService.java", "java/src/org/chromium/chrome/browser/ChromeBackupAgent.java", -@@ -2465,8 +2451,6 @@ if (current_toolchain == default_toolchain) { +@@ -2523,8 +2509,6 @@ if (current_toolchain == default_toolchain) { "java/src/org/chromium/chrome/browser/base/SplitCompatBackupAgent.java", "java/src/org/chromium/chrome/browser/base/SplitCompatContentProvider.java", "java/src/org/chromium/chrome/browser/base/SplitCompatCustomTabsService.java", @@ -237,7 +238,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "java/src/org/chromium/chrome/browser/base/SplitCompatIntentService.java", "java/src/org/chromium/chrome/browser/base/SplitCompatJobService.java", "java/src/org/chromium/chrome/browser/base/SplitCompatMinidumpUploadJobService.java", -@@ -2491,17 +2475,11 @@ if (current_toolchain == default_toolchain) { +@@ -2548,17 +2532,11 @@ if (current_toolchain == default_toolchain) { "java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java", "java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java", "java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java", @@ -255,7 +256,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//base:base_java", "//base:jni_java", "//chrome/browser/download/android:file_provider_java", -@@ -2515,7 +2493,6 @@ if (current_toolchain == default_toolchain) { +@@ -2572,7 +2550,6 @@ if (current_toolchain == default_toolchain) { "//components/media_router/browser/android:cast_options_provider_java", "//components/minidump_uploader:minidump_uploader_java", "//components/module_installer/android:module_installer_java", @@ -263,7 +264,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_collection_collection_java", "//ui/android:ui_no_recycler_view_java", -@@ -2534,7 +2511,6 @@ if (current_toolchain == default_toolchain) { +@@ -2591,7 +2568,6 @@ if (current_toolchain == default_toolchain) { # Deps to pull services into base module. # TODO(crbug.com/1126301): Consider moving these to the chrome module to # reduce base dex size. @@ -282,10 +283,10 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java "java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java", "java/src/org/chromium/chrome/browser/ChromeBackupWatcher.java", "java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java", -@@ -979,10 +978,6 @@ chrome_java_sources = [ - "java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProvider.java", +@@ -989,10 +988,6 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/segmentation_platform/ReaderModeActionProvider.java", "java/src/org/chromium/chrome/browser/segmentation_platform/SignalAccumulator.java", + "java/src/org/chromium/chrome/browser/selection/ChromeSelectionDropdownMenuDelegate.java", - "java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerServiceImpl.java", - "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundServiceImpl.java", - "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundTask.java", @@ -308,7 +309,7 @@ diff --git a/chrome/android/features/cablev2_authenticator/BUILD.gn b/chrome/and diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml -@@ -121,21 +121,16 @@ by a child template that "extends" this file. +@@ -121,19 +121,14 @@ by a child template that "extends" this file. @@ -318,8 +319,6 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro - - @@ -330,7 +329,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro -@@ -790,16 +785,6 @@ by a child template that "extends" this file. +@@ -784,16 +779,6 @@ by a child template that "extends" this file. @@ -347,7 +346,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro @@ -374,7 +373,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro -@@ -1036,20 +1001,10 @@ by a child template that "extends" this file. +@@ -1030,20 +995,10 @@ by a child template that "extends" this file. @@ -395,7 +394,7 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro -@@ -1281,12 +1236,6 @@ by a child template that "extends" this file. +@@ -1297,12 +1252,6 @@ by a child template that "extends" this file. {% endif %} @@ -411,16 +410,16 @@ diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/Andro diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java -@@ -7,9 +7,6 @@ package org.chromium.chrome.browser; +@@ -6,9 +6,6 @@ package org.chromium.chrome.browser; + import androidx.annotation.Nullable; - import androidx.annotation.VisibleForTesting; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; - import org.chromium.base.ContextUtils; import org.chromium.base.PackageUtils; - import org.chromium.chrome.browser.customtabs.CustomTabsConnection; + import org.chromium.base.ResettersForTesting; @@ -234,11 +231,7 @@ public abstract class AppHooks { * same as {@link GoogleApiAvailability#isGooglePlayServicesAvailable()}. */ @@ -746,7 +745,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateSta diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java -@@ -129,7 +129,6 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -128,7 +128,6 @@ public class PasswordSettings extends PreferenceFragmentCompat private Preference mLinkPref; private Menu mMenu; @@ -754,7 +753,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage private @ManagePasswordsReferrer int mManagePasswordsReferrer; private HelpAndFeedbackLauncher mHelpAndFeedbackLauncher; private Profile mProfile; -@@ -203,7 +202,6 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -202,7 +201,6 @@ public class PasswordSettings extends PreferenceFragmentCompat @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -762,7 +761,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage computeTrustedVaultBannerState(); } -@@ -307,9 +305,6 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -306,9 +304,6 @@ public class PasswordSettings extends PreferenceFragmentCompat createSavePasswordsSwitch(); createAutoSignInCheckbox(); @@ -772,7 +771,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manage if (mTrustedVaultBannerState == TrustedVaultBannerState.OPTED_IN) { createTrustedVaultBanner(R.string.android_trusted_vault_banner_sub_label_opted_in, -@@ -503,10 +498,6 @@ public class PasswordSettings extends PreferenceFragmentCompat +@@ -502,10 +497,6 @@ public class PasswordSettings extends PreferenceFragmentCompat // by the system. if (getActivity().isFinishing()) { PasswordManagerHandlerProvider.getInstance().removeObserver(this); @@ -825,7 +824,7 @@ diff --git a/chrome/browser/language/android/BUILD.gn b/chrome/browser/language/ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java -@@ -552,12 +552,6 @@ public class AppLanguagePromoDialog { +@@ -546,12 +546,6 @@ public class AppLanguagePromoDialog { mLoadingModal.set(ModalDialogProperties.CUSTOM_VIEW, customView); @@ -838,7 +837,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse boolean isSelectedCurrentUI = AppLocaleUtils.isAppLanguagePref(selectedLanguage.getCode()); if (!isSelectedCurrentUI) { // Only record isTopLanguage if the app language has changed. -@@ -565,23 +559,6 @@ public class AppLanguagePromoDialog { +@@ -559,23 +553,6 @@ public class AppLanguagePromoDialog { } AndroidLanguageMetricsBridge.reportAppLanguagePromptLanguage( selectedLanguage.isSystemDefault() ? "" : selectedLanguage.getCode()); @@ -873,7 +872,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse import org.chromium.chrome.browser.language.R; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar; -@@ -136,11 +135,6 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -135,11 +134,6 @@ public class LanguageSettings extends PreferenceFragmentCompat * translate target language, and detailed translate preferences. */ private void createDetailedPreferences(Bundle savedInstanceState, String rootKey) { @@ -888,7 +887,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn -@@ -97,8 +97,6 @@ android_library("java") { +@@ -99,8 +99,6 @@ android_library("java") { ":android_backend_java_enums", ":java_resources", ":settings_interface_java", @@ -897,7 +896,7 @@ diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/p "//base:base_java", "//base:jni_java", "//build/android:build_java", -@@ -218,8 +216,6 @@ robolectric_binary("password_manager_junit_tests") { +@@ -221,8 +219,6 @@ robolectric_binary("password_manager_junit_tests") { ":public_impl_java", ":settings_interface_java", ":test_support_java", @@ -1077,7 +1076,7 @@ diff --git a/chrome/browser/resources/settings/route.ts b/chrome/browser/resourc diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -367,8 +367,6 @@ static_library("ui") { +@@ -275,8 +275,6 @@ static_library("ui") { "webui/flags/flags_ui.h", "webui/flags/flags_ui_handler.cc", "webui/flags/flags_ui_handler.h", @@ -1086,7 +1085,7 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn "webui/internals/internals_ui.cc", "webui/internals/internals_ui.h", "webui/interstitials/interstitial_ui.cc", -@@ -600,7 +598,6 @@ static_library("ui") { +@@ -520,7 +518,6 @@ static_library("ui") { "//components/feedback/redaction_tool", "//components/find_in_page", "//components/flags_ui", @@ -1097,13 +1096,13 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java -@@ -189,12 +189,8 @@ public class SigninFirstRunMediator +@@ -190,12 +190,8 @@ public class SigninFirstRunMediator boolean isSigninDisabledByPolicy = false; boolean isMetricsReportingDisabledByPolicy = false; if (hasPolicies) { - isSigninDisabledByPolicy = - IdentityServicesProvider.get() -- .getSigninManager(Profile.getLastUsedRegularProfile()) +- .getSigninManager(mDelegate.getProfileSupplier().get()) - .isSigninDisabledByPolicy(); - isMetricsReportingDisabledByPolicy = - !mPrivacyPreferencesManager.isUsageAndCrashReportingPermittedByPolicy(); @@ -1115,7 +1114,7 @@ diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/brows diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc -@@ -192,12 +192,7 @@ bool AuthenticatorMechanismSelectorSheetModel::IsManageDevicesButtonVisible() +@@ -188,12 +188,7 @@ bool AuthenticatorMechanismSelectorSheetModel::IsManageDevicesButtonVisible() const { // If any phones are shown then also show a button that goes to the settings // page to manage them. @@ -1132,7 +1131,7 @@ diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/weba diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc -@@ -42,7 +42,6 @@ +@@ -47,7 +47,6 @@ #include "chrome/browser/ui/webui/download_internals/download_internals_ui.h" #include "chrome/browser/ui/webui/engagement/site_engagement_ui.h" #include "chrome/browser/ui/webui/flags/flags_ui.h" @@ -1140,7 +1139,7 @@ diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrom #include "chrome/browser/ui/webui/internals/internals_ui.h" #include "chrome/browser/ui/webui/interstitials/interstitial_ui.h" #include "chrome/browser/ui/webui/intro/intro_ui.h" -@@ -469,8 +468,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, +@@ -482,8 +481,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; if (url.host_piece() == chrome::kChromeUIFlagsHost) return &NewWebUI; @@ -1172,7 +1171,7 @@ diff --git a/chrome/browser/webauthn/android/java/src/org/chromium/chrome/browse import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.PackageUtils; -@@ -43,7 +41,6 @@ import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFacto +@@ -45,7 +43,6 @@ import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFacto import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions; import org.chromium.chrome.modules.cablev2_authenticator.Cablev2AuthenticatorModule; import org.chromium.components.externalauth.ExternalAuthUtils; @@ -1180,12 +1179,12 @@ diff --git a/chrome/browser/webauthn/android/java/src/org/chromium/chrome/browse import org.chromium.device.DeviceFeatureList; import org.chromium.device.DeviceFeatureMap; -@@ -264,24 +261,7 @@ public class CableAuthenticatorModuleProvider extends Fragment implements OnClic +@@ -284,25 +281,7 @@ public class CableAuthenticatorModuleProvider extends Fragment implements OnClic ok = false; } - if (!ok) { -- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(null); +- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(pointer, null); - return; - } - @@ -1197,25 +1196,26 @@ diff --git a/chrome/browser/webauthn/android/java/src/org/chromium/chrome/browse - Task task = call.run(Fido2ApiCall.METHOD_GET_LINK_INFO, - Fido2ApiCall.TRANSACTION_GET_LINK_INFO, args, result); - task.addOnSuccessListener(linkInfo -> { -- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(linkInfo); +- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation( +- pointer, linkInfo); - }).addOnFailureListener(exception -> { - Log.e(TAG, "Call to get linking information from Play Services failed", exception); -- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(null); +- CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(pointer, null); - }); -+ CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(null); ++ CableAuthenticatorModuleProviderJni.get().onHaveLinkingInformation(pointer, null); } @NativeMethods diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc -@@ -1169,10 +1169,6 @@ void AuthenticatorRequestDialogModel::PopulateMechanisms() { +@@ -1409,10 +1409,6 @@ void AuthenticatorRequestDialogModel::PopulateMechanisms() { if (cable_ui_type_) { switch (*cable_ui_type_) { case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR: - if (base::Contains(transport_availability_.available_transports, - kCable)) { -- include_add_phone_option = true; +- include_add_phone_option = !windows_handles_hybrid; - } break; @@ -1236,7 +1236,7 @@ diff --git a/chrome/browser/webauthn/cablev2_devices.cc b/chrome/browser/webauth diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn -@@ -240,8 +240,6 @@ android_library("chrome_java_integration_test_support") { +@@ -242,8 +242,6 @@ android_library("chrome_java_integration_test_support") { deps = [ ":chrome_java_test_support_common", @@ -1248,7 +1248,7 @@ diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java -@@ -2435,14 +2435,6 @@ public class ExternalNavigationHandler { +@@ -2494,14 +2494,6 @@ public class ExternalNavigationHandler { * @return Whether the given intent is going to open an Instant App. */ private static boolean isIntentToInstantApp(Intent intent) { @@ -1295,8 +1295,8 @@ diff --git a/components/externalauth/android/java/src/org/chromium/components/ex - import org.chromium.base.ContextUtils; import org.chromium.base.Log; - import org.chromium.base.StrictModeContext; -@@ -25,7 +22,6 @@ import org.chromium.base.TraceEvent; + import org.chromium.base.ResettersForTesting; +@@ -26,7 +23,6 @@ import org.chromium.base.TraceEvent; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.components.embedder_support.util.Origin; @@ -1304,7 +1304,7 @@ diff --git a/components/externalauth/android/java/src/org/chromium/components/ex /** * Utility class for external authentication tools. -@@ -171,9 +167,7 @@ public class ExternalAuthUtils { +@@ -172,9 +168,7 @@ public class ExternalAuthUtils { * when it is updating. */ public boolean isGooglePlayServicesMissing(final Context context) { @@ -1315,7 +1315,7 @@ diff --git a/components/externalauth/android/java/src/org/chromium/components/ex } /** -@@ -190,7 +184,6 @@ public class ExternalAuthUtils { +@@ -191,7 +185,6 @@ public class ExternalAuthUtils { public boolean canUseGooglePlayServices(final UserRecoverableErrorHandler errorHandler) { Context context = ContextUtils.getApplicationContext(); final int resultCode = checkGooglePlayServicesAvailable(context); @@ -1401,7 +1401,7 @@ diff --git a/components/gcm_driver/android/java/src/org/chromium/components/gcm_ diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc --- a/components/gcm_driver/gcm_client_impl.cc +++ b/components/gcm_driver/gcm_client_impl.cc -@@ -450,6 +450,7 @@ void GCMClientImpl::StartGCM() { +@@ -448,6 +448,7 @@ void GCMClientImpl::StartGCM() { void GCMClientImpl::InitializeMCSClient() { DCHECK(network_connection_tracker_); @@ -1409,7 +1409,7 @@ diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gc std::vector endpoints; endpoints.push_back(gservices_settings_.GetMCSMainEndpoint()); GURL fallback_endpoint = gservices_settings_.GetMCSFallbackEndpoint(); -@@ -643,6 +644,7 @@ void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, +@@ -641,6 +642,7 @@ void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, int interval_ms) { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK(mcs_client_); @@ -1417,7 +1417,7 @@ diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gc mcs_client_->AddHeartbeatInterval(scope, interval_ms); } -@@ -654,6 +656,7 @@ void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { +@@ -652,6 +654,7 @@ void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { void GCMClientImpl::StartCheckin() { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); @@ -1425,7 +1425,7 @@ diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gc // Make sure no checkin is in progress. if (checkin_request_) -@@ -732,6 +735,7 @@ void GCMClientImpl::SetGServicesSettingsCallback(bool success) { +@@ -730,6 +733,7 @@ void GCMClientImpl::SetGServicesSettingsCallback(bool success) { void GCMClientImpl::SchedulePeriodicCheckin() { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); @@ -1582,10 +1582,19 @@ diff --git a/components/media_router/browser/android/BUILD.gn b/components/media ] } -@@ -146,9 +140,6 @@ robolectric_library("junit") { +@@ -103,7 +97,6 @@ android_library("test_support_java") { + ":java", + ":java_resources", + ":test_jni_headers", +- "$google_play_services_package:google_play_services_cast_java", + "//base:base_java", + "//base:base_java_test_support", + "//base:jni_java", +@@ -147,10 +140,6 @@ robolectric_library("junit") { deps = [ ":java", ":test_support_java", +- "$google_play_services_package:google_play_services_base_java", - "$google_play_services_package:google_play_services_basement_java", - "$google_play_services_package:google_play_services_cast_framework_java", - "$google_play_services_package:google_play_services_cast_java", @@ -1604,8 +1613,8 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo - import org.chromium.base.ContextUtils; import org.chromium.base.Log; - import org.chromium.base.StrictModeContext; -@@ -42,20 +39,7 @@ public class BrowserMediaRouter implements MediaRouteManager { + import org.chromium.base.ResettersForTesting; +@@ -43,20 +40,7 @@ public class BrowserMediaRouter implements MediaRouteManager { new MediaRouteProvider.Factory() { @Override public void addProviders(MediaRouteManager manager) { @@ -2302,7 +2311,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -@@ -345,49 +341,7 @@ public class CafMessageHandler { +@@ -340,49 +336,7 @@ public class CafMessageHandler { final int sequenceNumber) throws JSONException { if (volumeMessage == null) return false; if (!mSessionController.isConnected()) return false; @@ -2353,7 +2362,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo } @VisibleForTesting -@@ -675,19 +629,11 @@ public class CafMessageHandler { +@@ -670,19 +624,11 @@ public class CafMessageHandler { try { // "volume" is a part of "receiver" initialized below. JSONObject jsonVolume = new JSONObject(); @@ -2373,7 +2382,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo jsonReceiver.put("displayStatus", null); jsonReceiver.put("receiverType", "cast"); -@@ -700,25 +646,16 @@ public class CafMessageHandler { +@@ -695,25 +641,16 @@ public class CafMessageHandler { JSONObject jsonMessage = new JSONObject(); jsonMessage.put("sessionId", mSessionController.getSessionId()); @@ -2401,7 +2410,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo return jsonMessage.toString(); } catch (JSONException e) { -@@ -799,32 +736,6 @@ public class CafMessageHandler { +@@ -794,32 +731,6 @@ public class CafMessageHandler { boolean sendStringCastMessage( String message, String namespace, String clientId, int sequenceNumber) { if (!mSessionController.isConnected()) return false; @@ -2740,7 +2749,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafRemotingMediaRouteProvider.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafRemotingMediaRouteProvider.java --- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafRemotingMediaRouteProvider.java +++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafRemotingMediaRouteProvider.java -@@ -70,7 +70,7 @@ public class CafRemotingMediaRouteProvider extends CafBaseMediaRouteProvider { +@@ -69,7 +69,7 @@ public class CafRemotingMediaRouteProvider extends CafBaseMediaRouteProvider { if (!mRoutes.containsKey(routeId)) return null; @@ -2749,7 +2758,7 @@ diff --git a/components/media_router/browser/android/java/src/org/chromium/compo } @Override -@@ -79,7 +79,7 @@ public class CafRemotingMediaRouteProvider extends CafBaseMediaRouteProvider { +@@ -78,7 +78,7 @@ public class CafRemotingMediaRouteProvider extends CafBaseMediaRouteProvider { var controller = sessionController(); // There is no active remote playback media route. @@ -3010,7 +3019,7 @@ diff --git a/components/signin/public/android/BUILD.gn b/components/signin/publi "//base:base_java", "//base:jni_java", "//build/android:build_java", -@@ -176,7 +174,6 @@ robolectric_library("junit") { +@@ -177,7 +175,6 @@ robolectric_library("junit") { deps = [ ":java", ":signin_java_test_support", @@ -3063,10 +3072,10 @@ diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/ "java/src/org/chromium/components/webauthn/InternalAuthenticator.java", "java/src/org/chromium/components/webauthn/WebAuthnBrowserBridge.java", ] -@@ -18,11 +16,7 @@ android_library("java") { - sources = [ +@@ -19,11 +17,7 @@ android_library("java") { "java/src/org/chromium/components/webauthn/AuthenticatorFactory.java", "java/src/org/chromium/components/webauthn/AuthenticatorImpl.java", + "java/src/org/chromium/components/webauthn/CredManMetricsHelper.java", - "java/src/org/chromium/components/webauthn/Fido2Api.java", - "java/src/org/chromium/components/webauthn/Fido2ApiCall.java", "java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java", @@ -3075,7 +3084,7 @@ diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/ "java/src/org/chromium/components/webauthn/GetAssertionResponseCallback.java", "java/src/org/chromium/components/webauthn/GetMatchingCredentialIdsResponseCallback.java", "java/src/org/chromium/components/webauthn/InternalAuthenticator.java", -@@ -33,9 +27,6 @@ android_library("java") { +@@ -34,9 +28,6 @@ android_library("java") { ] deps = [ @@ -3085,7 +3094,7 @@ diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/ "//base:base_java", "//base:jni_java", "//build/android:build_java", -@@ -87,8 +78,6 @@ android_library("test_support_java") { +@@ -89,8 +80,6 @@ android_library("test_support_java") { source_set("android") { sources = [ @@ -3097,7 +3106,7 @@ diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/ diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java -@@ -10,7 +10,6 @@ import android.os.Build; +@@ -12,7 +12,6 @@ import android.os.Build; import android.util.Pair; import org.chromium.base.Callback; @@ -3105,7 +3114,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut import org.chromium.base.metrics.RecordHistogram; import org.chromium.blink.mojom.Authenticator; import org.chromium.blink.mojom.AuthenticatorStatus; -@@ -52,9 +51,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -59,9 +58,6 @@ public final class AuthenticatorImpl implements Authenticator { /** The payment information to be added to the "clientDataJson". */ private PaymentOptions mPayment; @@ -3115,20 +3124,26 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut private MakeCredential_Response mMakeCredentialCallback; private GetAssertion_Response mGetAssertionCallback; // A queue is used to store pending IsUserVerifyingPlatformAuthenticatorAvailable request -@@ -63,9 +59,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -70,15 +66,8 @@ public final class AuthenticatorImpl implements Authenticator { // situation does not matter because all pending requests will return the same value. private Queue> mIsUserVerifyingPlatformAuthenticatorAvailableCallbackQueue = new LinkedList<>(); - private Fido2CredentialRequest mPendingFido2CredentialRequest; -- -- private static Fido2CredentialRequest sFido2CredentialRequestOverrideForTesting; + private Set mUnclosedFido2CredentialRequests = new HashSet<>(); +- // StaticFieldLeak complains that this is a memory leak because +- // `Fido2CredentialRequest` contains a `Context`. But this field is only +- // used in tests so a memory leak is irrelevent. +- @SuppressLint("StaticFieldLeak") +- private static Fido2CredentialRequest sFido2CredentialRequestOverrideForTesting; +- /** * Builds the Authenticator service implementation. -@@ -86,20 +79,6 @@ public final class AuthenticatorImpl implements Authenticator { - + * +@@ -97,21 +86,6 @@ public final class AuthenticatorImpl implements Authenticator { mRenderFrameHost = renderFrameHost; mOrigin = mRenderFrameHost.getLastCommittedOrigin(); + mTopOrigin = topOrigin; - - mGmsCorePackageVersion = PackageUtils.getPackageVersion(GMSCORE_PACKAGE_NAME); - } @@ -3141,12 +3156,13 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut - if (sFido2CredentialRequestOverrideForTesting != null) { - return sFido2CredentialRequestOverrideForTesting; - } -- -- return new Fido2CredentialRequest(mIntentSender); +- Fido2CredentialRequest request = new Fido2CredentialRequest(mIntentSender); +- mUnclosedFido2CredentialRequests.add(request); +- return request; } /** -@@ -129,17 +108,9 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -141,17 +115,9 @@ public final class AuthenticatorImpl implements Authenticator { mMakeCredentialCallback = callback; mIsOperationPending = true; @@ -3156,8 +3172,8 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut - } - mPendingFido2CredentialRequest = getFido2CredentialRequest(); -- mPendingFido2CredentialRequest.handleMakeCredentialRequest(options, mRenderFrameHost, -- mOrigin, +- mPendingFido2CredentialRequest.handleMakeCredentialRequest(mContext, options, +- mRenderFrameHost, /*maybeClientDataHash=*/null, mOrigin, - (status, response) - -> onRegisterResponse(status, response), - status -> onError(status)); @@ -3166,7 +3182,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } @Override -@@ -153,15 +124,8 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -165,16 +131,8 @@ public final class AuthenticatorImpl implements Authenticator { mGetAssertionCallback = callback; mIsOperationPending = true; @@ -3176,15 +3192,16 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut - } - - mPendingFido2CredentialRequest = getFido2CredentialRequest(); -- mPendingFido2CredentialRequest.handleGetAssertionRequest(options, mRenderFrameHost, mOrigin, -- mPayment, +- mPendingFido2CredentialRequest.handleGetAssertionRequest(mContext, options, +- mRenderFrameHost, +- /*maybeClientDataHash=*/null, mOrigin, mTopOrigin, mPayment, - (status, response) -> onSignResponse(status, response), status -> onError(status)); + // Fido2 not supported on Bromite + onError(AuthenticatorStatus.NOT_IMPLEMENTED); } @Override -@@ -173,15 +137,8 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -186,15 +144,8 @@ public final class AuthenticatorImpl implements Authenticator { callback.call(isUvpaa); }; @@ -3195,14 +3212,14 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut - - mIsUserVerifyingPlatformAuthenticatorAvailableCallbackQueue.add(decoratedCallback); - getFido2CredentialRequest().handleIsUserVerifyingPlatformAuthenticatorAvailableRequest( -- mRenderFrameHost, +- mContext, - isUvpaa -> onIsUserVerifyingPlatformAuthenticatorAvailableResponse(isUvpaa)); + decoratedCallback.call(false); + return; } /** -@@ -190,7 +147,7 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -203,7 +154,7 @@ public final class AuthenticatorImpl implements Authenticator { * version. */ public boolean isGetMatchingCredentialIdsSupported() { @@ -3211,7 +3228,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -204,32 +161,13 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -217,32 +168,13 @@ public final class AuthenticatorImpl implements Authenticator { */ public void getMatchingCredentialIds(String relyingPartyId, byte[][] credentialIds, boolean requireThirdPartyPayment, GetMatchingCredentialIdsResponseCallback callback) { @@ -3240,13 +3257,13 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut - // credentials on conditional requests, use IsUVPAA as a proxy for availability. - mIsUserVerifyingPlatformAuthenticatorAvailableCallbackQueue.add(callback); - getFido2CredentialRequest().handleIsUserVerifyingPlatformAuthenticatorAvailableRequest( -- mRenderFrameHost, +- mContext, - isUvpaa -> onIsUserVerifyingPlatformAuthenticatorAvailableResponse(isUvpaa)); + callback.call(false); } @Override -@@ -241,8 +179,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -254,8 +186,6 @@ public final class AuthenticatorImpl implements Authenticator { if (!mIsOperationPending || mGetAssertionCallback == null) { return; } @@ -3255,7 +3272,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -292,7 +228,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -305,7 +235,6 @@ public final class AuthenticatorImpl implements Authenticator { mIsOperationPending = false; mMakeCredentialCallback = null; mGetAssertionCallback = null; @@ -3266,9 +3283,9 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java -@@ -10,10 +10,6 @@ import android.os.Parcel; - - import androidx.annotation.VisibleForTesting; +@@ -8,10 +8,6 @@ import android.app.PendingIntent; + import android.net.Uri; + import android.os.Parcel; -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.OnSuccessListener; @@ -3277,7 +3294,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut import org.chromium.base.ContextUtils; import org.chromium.blink.mojom.PublicKeyCredentialCreationOptions; import org.chromium.blink.mojom.PublicKeyCredentialRequestOptions; -@@ -46,58 +42,6 @@ public class Fido2ApiCallHelper { +@@ -43,58 +39,6 @@ public class Fido2ApiCallHelper { } public boolean arePlayServicesAvailable() { @@ -3366,7 +3383,7 @@ diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn -@@ -3359,10 +3359,6 @@ if (is_android) { +@@ -3376,10 +3376,6 @@ if (is_android) { testonly = true sources = content_java_sources_needing_jni deps = [ @@ -3380,7 +3397,7 @@ diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn diff --git a/device/BUILD.gn b/device/BUILD.gn --- a/device/BUILD.gn +++ b/device/BUILD.gn -@@ -496,9 +496,6 @@ if (is_android) { +@@ -500,9 +500,6 @@ if (is_android) { "gamepad/android/junit/src/org/chromium/device/gamepad/GamepadMappingsTest.java", ] deps = [ @@ -3393,7 +3410,7 @@ diff --git a/device/BUILD.gn b/device/BUILD.gn diff --git a/remoting/android/client_java_tmpl.gni b/remoting/android/client_java_tmpl.gni --- a/remoting/android/client_java_tmpl.gni +++ b/remoting/android/client_java_tmpl.gni -@@ -104,9 +104,6 @@ template("remoting_android_client_java_tmpl") { +@@ -105,9 +105,6 @@ template("remoting_android_client_java_tmpl") { if (defined(invoker.play_services_package)) { deps += [ @@ -3406,7 +3423,7 @@ diff --git a/remoting/android/client_java_tmpl.gni b/remoting/android/client_jav diff --git a/services/BUILD.gn b/services/BUILD.gn --- a/services/BUILD.gn +++ b/services/BUILD.gn -@@ -120,11 +120,6 @@ if (is_android) { +@@ -122,11 +122,6 @@ if (is_android) { "shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java", ] deps = [ @@ -3418,7 +3435,7 @@ diff --git a/services/BUILD.gn b/services/BUILD.gn "//base:base_java", "//base:base_java_test_support", "//base:base_junit_test_support", -@@ -153,10 +148,6 @@ if (is_android) { +@@ -156,10 +151,6 @@ if (is_android) { "shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java", ] deps = [ @@ -3446,7 +3463,7 @@ diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/ diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn --- a/services/shape_detection/BUILD.gn +++ b/services/shape_detection/BUILD.gn -@@ -116,8 +116,6 @@ if (is_android) { +@@ -115,8 +115,6 @@ if (is_android) { ] deps = [ @@ -3482,7 +3499,7 @@ diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD. } # TODO(crbug.com/1366370) Remove this once all depencencies are updated to -@@ -975,212 +966,6 @@ if (!limit_android_deps) { +@@ -978,212 +969,6 @@ if (!limit_android_deps) { ] } @@ -3695,7 +3712,7 @@ diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD. # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. android_aar_prebuilt("com_google_android_material_material_java") { -@@ -1225,62 +1010,6 @@ if (!limit_android_deps) { +@@ -1228,62 +1013,6 @@ if (!limit_android_deps) { ] } @@ -3758,7 +3775,7 @@ diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD. # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. java_prebuilt("com_google_guava_guava_android_java") { -@@ -1614,19 +1343,6 @@ if (!limit_android_deps) { +@@ -1617,19 +1346,6 @@ if (!limit_android_deps) { is_robolectric = true } @@ -3778,7 +3795,7 @@ diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD. # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. java_prebuilt("org_robolectric_utils_java") { jar_path = "libs/org_robolectric_utils/utils-4.10.3.jar" -@@ -2006,290 +1722,6 @@ if (!limit_android_deps) { +@@ -2009,290 +1725,6 @@ if (!limit_android_deps) { deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ] } @@ -4113,6 +4130,20 @@ diff --git a/third_party/android_deps/util/org/chromium/gms/ChromiumPlayServices + return 16; // API_UNAVAILABLE } } +diff --git a/third_party/cardboard/BUILD.gn b/third_party/cardboard/BUILD.gn +--- a/third_party/cardboard/BUILD.gn ++++ b/third_party/cardboard/BUILD.gn +@@ -51,10 +51,6 @@ android_library("cardboard_java") { + deps = [ + ":cardboard_proto_java", + ":cardboard_resources", +- "$google_play_services_package:google_play_services_base_java", +- "$google_play_services_package:google_play_services_basement_java", +- "$google_play_services_package:google_play_services_vision_common_java", +- "$google_play_services_package:google_play_services_vision_java", + "//third_party/android_deps:protobuf_lite_runtime_java", + "//third_party/androidx:androidx_annotation_annotation_jvm_java", + "//third_party/androidx:androidx_appcompat_appcompat_java", diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn --- a/weblayer/browser/java/BUILD.gn +++ b/weblayer/browser/java/BUILD.gn diff --git a/build/patches/Remove-help-menu-item.patch b/build/patches/Remove-help-menu-item.patch index aa2b2e86..88aa35d5 100644 --- a/build/patches/Remove-help-menu-item.patch +++ b/build/patches/Remove-help-menu-item.patch @@ -14,7 +14,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml -@@ -150,9 +150,6 @@ found in the LICENSE file. +@@ -153,9 +153,6 @@ found in the LICENSE file. @@ -27,7 +27,7 @@ diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/re diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java --- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java -@@ -358,9 +358,6 @@ public class KeyboardShortcuts { +@@ -367,9 +367,6 @@ public class KeyboardShortcuts { case KeyEvent.KEYCODE_BUTTON_START: if (currentTab != null && currentTab.canGoForward()) currentTab.goForward(); return true; @@ -40,7 +40,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcu diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java -@@ -2410,16 +2410,6 @@ public abstract class ChromeActivity +@@ -2421,16 +2421,6 @@ public abstract class ChromeActivity final Tab currentTab = getActivityTab(); @@ -60,7 +60,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java -@@ -564,7 +564,7 @@ public abstract class BaseCustomTabActivity extends ChromeActivityIsContextThread()); const String host = Host(); -@@ -250,6 +251,7 @@ void NetworkInformation::ContextDestroyed() { +@@ -248,6 +249,7 @@ void NetworkInformation::ContextDestroyed() { } void NetworkInformation::StartObserving() { @@ -41,7 +41,7 @@ diff --git a/third_party/blink/renderer/modules/netinfo/network_information.cc b if (!IsObserving() && !context_stopped_) { type_ = GetNetworkStateNotifier().ConnectionType(); DCHECK(!connection_observer_handle_); -@@ -260,6 +262,7 @@ void NetworkInformation::StartObserving() { +@@ -258,6 +260,7 @@ void NetworkInformation::StartObserving() { } void NetworkInformation::StopObserving() { diff --git a/build/patches/Remove-segmentation-platform.patch b/build/patches/Remove-segmentation-platform.patch index af583e72..31dd5ac3 100644 --- a/build/patches/Remove-segmentation-platform.patch +++ b/build/patches/Remove-segmentation-platform.patch @@ -56,7 +56,7 @@ diff --git a/components/segmentation_platform/public/features.cc b/components/se BASE_FEATURE(kSegmentationPlatformUkmEngine, "SegmentationPlatformUkmEngine", -@@ -38,11 +38,7 @@ BASE_FEATURE(kSegmentationPlatformDeviceSwitcher, +@@ -42,11 +42,7 @@ BASE_FEATURE(kSegmentationPlatformDeviceSwitcher, BASE_FEATURE(kSegmentationPlatformFeedSegmentFeature, "SegmentationPlatformFeedSegmentFeature", diff --git a/build/patches/Remove-voice-recognition-integration.patch b/build/patches/Remove-voice-recognition-integration.patch index e88a636b..571ed5e3 100644 --- a/build/patches/Remove-voice-recognition-integration.patch +++ b/build/patches/Remove-voice-recognition-integration.patch @@ -26,7 +26,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java -@@ -74,7 +74,6 @@ import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; +@@ -76,7 +76,6 @@ import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.omnibox.OmniboxFocusReason; import org.chromium.chrome.browser.omnibox.OmniboxStub; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; @@ -34,7 +34,7 @@ diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -@@ -532,8 +531,7 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. +@@ -539,8 +538,7 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. // Initialize // Note that isVoiceSearchEnabled will return false in incognito mode. @@ -44,7 +44,7 @@ diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/ updateLensVisibility(); // This is for Instant Start when overview is already visible while the omnibox, Feed -@@ -566,13 +564,6 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. +@@ -573,13 +571,6 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. } }); mPropertyModel.set(VOICE_SEARCH_BUTTON_CLICK_LISTENER, v -> { @@ -58,7 +58,7 @@ diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/ }); mPropertyModel.set(LENS_BUTTON_CLICK_LISTENER, v -> { -@@ -1456,10 +1447,6 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. +@@ -1468,10 +1459,6 @@ class StartSurfaceMediator implements TabSwitcher.TabSwitcherViewObserver, View. // incorrect state if check synchronously. ThreadUtils.postOnUiThread(() -> { if (mOmniboxStub != null) { @@ -129,7 +129,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSess diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java -@@ -59,7 +59,6 @@ import org.chromium.chrome.browser.native_page.ContextMenuManager; +@@ -60,7 +60,6 @@ import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.omnibox.OmniboxFocusReason; import org.chromium.chrome.browser.omnibox.OmniboxStub; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteControllerProvider; @@ -155,7 +155,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. // The timestamp at which the constructor was called. protected final long mConstructedTimeNs; -@@ -234,8 +231,7 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -236,8 +233,7 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide @Override public boolean isVoiceSearchEnabled() { @@ -165,7 +165,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. } @Override -@@ -243,21 +239,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -245,21 +241,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide if (mIsDestroyed) return; FeedReliabilityLogger feedReliabilityLogger = mFeedSurfaceProvider.getReliabilityLogger(); @@ -187,7 +187,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. } @Override -@@ -753,12 +734,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -760,12 +741,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide mOmniboxStub.addUrlFocusChangeListener(feedReliabilityLogger); } } @@ -200,7 +200,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. } @Override -@@ -769,11 +744,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -776,11 +751,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide } } @@ -212,7 +212,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. /** Adds an observer to be notified on most visited tile clicks. */ public void addMostVisitedTileClickObserver(MostVisitedTileClickObserver observer) { mMostVisitedTileClickObservers.addObserver(observer); -@@ -792,9 +762,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -799,9 +769,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide mLastShownTimeNs = System.nanoTime(); RecordUserAction.record("MobileNTPShown"); SuggestionsMetrics.recordSurfaceVisible(); @@ -222,7 +222,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. } /** Records UMA for the NTP being hidden and the time spent on it. */ -@@ -802,7 +769,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -809,7 +776,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide RecordHistogram.recordMediumTimesHistogram("NewTabPage.TimeSpent", (System.nanoTime() - mLastShownTimeNs) / TimeUtils.NANOSECONDS_PER_MILLISECOND); SuggestionsMetrics.recordSurfaceHidden(); @@ -230,7 +230,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage. } /** -@@ -901,9 +867,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide +@@ -907,9 +873,6 @@ public class NewTabPage implements NativePage, InvalidationAwareThumbnailProvide } mFeedSurfaceProvider.destroy(); mTab.getWindowAndroid().removeContextMenuCloseListener(mContextMenuManager); @@ -254,15 +254,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/search/Sear diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java -@@ -53,7 +53,6 @@ import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider; +@@ -54,7 +54,6 @@ import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionsDropdownScrollListener; import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxActionDelegateImpl; - import org.chromium.chrome.browser.omnibox.suggestions.base.HistoryClustersProcessor.OpenHistoryClustersDelegate; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; import org.chromium.chrome.browser.password_manager.PasswordManagerLauncher; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; -@@ -400,14 +399,12 @@ public class SearchActivity extends AsyncInitializationActivity +@@ -403,14 +402,12 @@ public class SearchActivity extends AsyncInitializationActivity // will navigate to Tabbed mode. Investigate whether this can inflate // the tabbed mode layout in the background instead of CCTs. CustomTabsConnection.getInstance().warmup(0); @@ -278,7 +278,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/Se RecordUserAction.record("SearchWidget.WidgetSelected"); getActivityDelegate().onFinishDeferredInitialization(); -@@ -478,8 +475,7 @@ public class SearchActivity extends AsyncInitializationActivity +@@ -481,8 +478,7 @@ public class SearchActivity extends AsyncInitializationActivity if (isFromQuickActionSearchWidget()) { recordQuickActionSearchType(searchType); } @@ -397,15 +397,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/Se diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java -@@ -86,7 +86,6 @@ import org.chromium.chrome.browser.omnibox.OverrideUrlLoadingDelegate; +@@ -91,7 +91,6 @@ import org.chromium.chrome.browser.omnibox.OverrideUrlLoadingDelegate; import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; - import org.chromium.chrome.browser.omnibox.suggestions.base.HistoryClustersProcessor.OpenHistoryClustersDelegate; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.page_info.ChromePageInfo; import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures; -@@ -2122,10 +2121,6 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve +@@ -2154,10 +2153,6 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve return mLocationBar.getOmniboxStub(); } @@ -422,13 +422,13 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi @@ -93,8 +93,6 @@ import org.chromium.chrome.browser.omnibox.OmniboxFocusReason; import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader; import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxActionDelegateImpl; - import org.chromium.chrome.browser.omnibox.suggestions.base.HistoryClustersProcessor.OpenHistoryClustersDelegate; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler.VoiceInteractionSource; import org.chromium.chrome.browser.paint_preview.DemoPaintPreview; import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; import org.chromium.chrome.browser.password_manager.PasswordManagerLauncher; -@@ -281,7 +279,6 @@ public class RootUiCoordinator +@@ -285,7 +283,6 @@ public class RootUiCoordinator protected OneshotSupplierImpl mPromoShownOneshotSupplier = new OneshotSupplierImpl<>(); protected Supplier mStartSurfaceParentTabSupplier; @Nullable @@ -436,7 +436,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi private MediaCaptureOverlayController mCaptureController; private @Nullable ScrollCaptureManager mScrollCaptureManager; protected final ActivityLifecycleDispatcher mActivityLifecycleDispatcher; -@@ -575,9 +572,6 @@ public class RootUiCoordinator +@@ -582,9 +579,6 @@ public class RootUiCoordinator } if (mToolbarManager != null) { @@ -446,7 +446,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi mToolbarManager.destroy(); mToolbarManager = null; } -@@ -1135,19 +1129,11 @@ public class RootUiCoordinator +@@ -1158,19 +1152,11 @@ public class RootUiCoordinator new VoiceToolbarButtonController.VoiceSearchDelegate() { @Override public boolean isVoiceSearchEnabled() { @@ -467,7 +467,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi } }; TranslateToolbarButtonController translateToolbarButtonController = -@@ -1249,13 +1235,6 @@ public class RootUiCoordinator +@@ -1280,13 +1266,6 @@ public class RootUiCoordinator if (!mSupportsAppMenuSupplier.getAsBoolean()) { mToolbarManager.getToolbar().disableMenuButton(); } @@ -484,7 +484,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn -@@ -137,7 +137,6 @@ android_library("java") { +@@ -138,7 +138,6 @@ android_library("java") { "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java", @@ -520,13 +520,13 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java @@ -40,7 +40,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteDelegate; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionsDropdownScrollListener; - import org.chromium.chrome.browser.omnibox.suggestions.base.HistoryClustersProcessor.OpenHistoryClustersDelegate; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor.BookmarkState; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; -@@ -383,13 +382,6 @@ public class LocationBarCoordinator +@@ -384,13 +383,6 @@ public class LocationBarCoordinator return mLocationBarLayout.getSecurityIconView(); } @@ -540,7 +540,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow @Nullable @Override public OmniboxStub getOmniboxStub() { -@@ -660,11 +652,6 @@ public class LocationBarCoordinator +@@ -676,11 +668,6 @@ public class LocationBarCoordinator // End tablet-specific methods. @@ -612,7 +612,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow /* package */ void setLensControllerForTesting(LensController lensController) { mLensController = lensController; } -@@ -570,8 +559,6 @@ class LocationBarMediator +@@ -573,8 +562,6 @@ class LocationBarMediator mUrlCoordinator.setKeyboardVisibility(false, false); RecordUserAction.record("MobileOmniboxVoiceSearch"); @@ -621,7 +621,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow } /** package */ void lensButtonClicked(View view) { -@@ -1023,8 +1010,7 @@ class LocationBarMediator +@@ -1026,8 +1013,7 @@ class LocationBarMediator private boolean shouldShowMicButton() { if (shouldShowDeleteButton()) return false; @@ -631,7 +631,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow return false; } boolean isToolbarMicEnabled = mIsToolbarMicEnabledSupplier.getAsBoolean(); -@@ -1219,7 +1205,6 @@ class LocationBarMediator +@@ -1186,7 +1172,6 @@ class LocationBarMediator // This method needs to be called first as it computes |mBrandedColorScheme|. updateBrandedColorScheme(); @@ -639,7 +639,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow updateLensButtonColors(); } -@@ -1306,16 +1291,6 @@ class LocationBarMediator +@@ -1273,16 +1258,6 @@ class LocationBarMediator } } @@ -656,7 +656,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow @Override public void addUrlFocusChangeListener(UrlFocusChangeListener listener) { mUrlFocusChangeListeners.addObserver(listener); -@@ -1331,29 +1306,10 @@ class LocationBarMediator +@@ -1298,29 +1273,10 @@ class LocationBarMediator return mUrlHasFocus; } @@ -686,7 +686,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow public void setSearchQuery(String query) { if (TextUtils.isEmpty(query)) return; -@@ -1372,21 +1328,9 @@ class LocationBarMediator +@@ -1339,21 +1295,9 @@ class LocationBarMediator mUrlCoordinator.setKeyboardVisibility(true, false); } @@ -781,8 +781,8 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java -@@ -46,7 +46,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderView; - import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderViewBinder; +@@ -46,7 +46,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderViewBinder; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionView; import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionViewBinder; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; @@ -808,8 +808,8 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java @@ -36,7 +36,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.On import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxActionFactoryImpl; - import org.chromium.chrome.browser.omnibox.suggestions.base.HistoryClustersProcessor.OpenHistoryClustersDelegate; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor.BookmarkState; + import org.chromium.chrome.browser.omnibox.suggestions.history_clusters.HistoryClustersProcessor.OpenHistoryClustersDelegate; -import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ShareDelegate; diff --git a/build/patches/Remove-window-name-on-cross-origin-navigation.patch b/build/patches/Remove-window-name-on-cross-origin-navigation.patch index 72b10232..3b3bd790 100644 --- a/build/patches/Remove-window-name-on-cross-origin-navigation.patch +++ b/build/patches/Remove-window-name-on-cross-origin-navigation.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc -@@ -2550,7 +2550,7 @@ void DocumentLoader::CommitNavigation() { +@@ -2573,7 +2573,7 @@ void DocumentLoader::CommitNavigation() { // that the name would be nulled and if the name is accessed after we will // fire a UseCounter. If we decide to move forward with this change, we'd // actually clean the name here. @@ -22,7 +22,7 @@ diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_p frame_->Tree().ExperimentalSetNulledName(); } -@@ -2561,6 +2561,7 @@ void DocumentLoader::CommitNavigation() { +@@ -2584,6 +2584,7 @@ void DocumentLoader::CommitNavigation() { // TODO(shuuran): CrossSiteCrossBrowsingContextGroupSetNulledName will just // record the fact that the name would be nulled and if the name is accessed // after we will fire a UseCounter. diff --git a/build/patches/Restore-Search-Ready-Omnibox-flag.patch b/build/patches/Restore-Search-Ready-Omnibox-flag.patch index 249c261a..88ba8e53 100644 --- a/build/patches/Restore-Search-Ready-Omnibox-flag.patch +++ b/build/patches/Restore-Search-Ready-Omnibox-flag.patch @@ -9,7 +9,7 @@ Disable search-ready omnibox by default License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/about_flags.cc | 3 +++ + chrome/browser/about_flags.cc | 5 +++++ chrome/browser/flag-metadata.json | 5 +++++ chrome/browser/flag_descriptions.cc | 5 +++++ chrome/browser/flag_descriptions.h | 3 +++ @@ -17,25 +17,27 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html chrome/browser/flags/android/chrome_feature_list.h | 1 + .../chrome/browser/flags/ChromeFeatureList.java | 1 + .../suggestions/DropdownItemViewInfoListBuilder.java | 11 +++++++++-- - 8 files changed, 32 insertions(+), 2 deletions(-) + 8 files changed, 34 insertions(+), 2 deletions(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -9346,6 +9346,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -9461,6 +9461,11 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kDesksTemplatesDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kDesksTemplates)}, #endif ++#if BUILDFLAG(IS_ANDROID) + {"enable-search-ready-omnibox", flag_descriptions::kSearchReadyOmniboxName, + flag_descriptions::kSearchReadyOmniboxDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kSearchReadyOmniboxFeature)}, ++#endif {"large-favicon-from-google", flag_descriptions::kLargeFaviconFromGoogleName, diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -3092,6 +3092,11 @@ +@@ -3222,6 +3222,11 @@ // Added feature, for testing. expiry deep in future. "expiry_milestone": 116 }, @@ -50,7 +52,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4258,6 +4258,11 @@ const char kSendTabToSelfV2Description[] = +@@ -4312,6 +4312,11 @@ const char kSendTabToSelfV2Description[] = "Enables new received tab " "UI shown next to the profile icon instead of using system notifications."; @@ -65,7 +67,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2479,6 +2479,9 @@ extern const char kShowScrollableMVTOnNTPAndroidDescription[]; +@@ -2526,6 +2526,9 @@ extern const char kShowScrollableMVTOnNTPAndroidDescription[]; extern const char kSendTabToSelfV2Name[]; extern const char kSendTabToSelfV2Description[]; @@ -78,16 +80,16 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -264,6 +264,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -271,6 +271,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { + &kReaderModeInCCT, &kRecordSuppressionMetrics, - &kReduceToolbarUpdatesForSameDocNavigations, &kReengagementNotification, + &kSearchReadyOmniboxFeature, &kRelatedSearches, &kReportParentalControlSitesChild, &kRequestDesktopSiteDefaults, -@@ -449,6 +450,10 @@ BASE_FEATURE(kAllowNewIncognitoTabIntents, - "AllowNewIncognitoTabIntents", +@@ -458,6 +459,10 @@ BASE_FEATURE(kAvoidSelectedTabFocusOnLayoutDoneShowing, + "AvoidSelectedTabFocusOnLayoutDoneShowing", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kSearchReadyOmniboxFeature, @@ -100,9 +102,9 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -150,6 +150,7 @@ BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsDowngrade); +@@ -158,6 +158,7 @@ BASE_DECLARE_FEATURE(kRequestDesktopSiteOptInSynthetic); + BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsDowngrade); BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsLogging); - BASE_DECLARE_FEATURE(kRequestDesktopSitePerSiteIph); BASE_DECLARE_FEATURE(kRestoreTabsOnFRE); +BASE_DECLARE_FEATURE(kSearchReadyOmniboxFeature); BASE_DECLARE_FEATURE(kSharingHubLinkToggle); @@ -111,7 +113,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -303,6 +303,7 @@ public abstract class ChromeFeatureList { +@@ -308,6 +308,7 @@ public abstract class ChromeFeatureList { "MessagesForAndroidInfrastructure"; public static final String MESSAGES_FOR_ANDROID_PERMISSION_UPDATE = "MessagesForAndroidPermissionUpdate"; @@ -130,7 +132,7 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.omnibox.OmniboxFeatures; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; -@@ -64,6 +65,7 @@ class DropdownItemViewInfoListBuilder { +@@ -56,6 +57,7 @@ class DropdownItemViewInfoListBuilder { @Px private int mDropdownHeight; private OpenHistoryClustersDelegate mOpenHistoryClustersDelegate; @@ -138,20 +140,20 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow DropdownItemViewInfoListBuilder(@NonNull Supplier tabSupplier, BookmarkState bookmarkState, OpenHistoryClustersDelegate openHistoryClustersDelegate) { -@@ -102,8 +104,10 @@ class DropdownItemViewInfoListBuilder { +@@ -92,8 +94,10 @@ class DropdownItemViewInfoListBuilder { mDividerLineProcessor = new DividerLineProcessor(context); } mHeaderProcessor = new HeaderProcessor(context); - registerSuggestionProcessor(new EditUrlSuggestionProcessor( -- context, host, delegate, mFaviconFetcher, mActivityTabSupplier, shareSupplier)); +- context, host, delegate, mImageSupplier, mActivityTabSupplier, shareSupplier)); + mEditUrlSuggestionProcessor = new EditUrlSuggestionProcessor( -+ context, host, delegate, mFaviconFetcher, mActivityTabSupplier, shareSupplier); ++ context, host, delegate, mImageSupplier, mActivityTabSupplier, shareSupplier); + registerSuggestionProcessor(mEditUrlSuggestionProcessor); + registerSuggestionProcessor( - new AnswerSuggestionProcessor(context, host, textProvider, imageFetcherSupplier)); + new AnswerSuggestionProcessor(context, host, textProvider, mImageSupplier)); registerSuggestionProcessor( -@@ -239,6 +243,9 @@ class DropdownItemViewInfoListBuilder { +@@ -202,6 +206,9 @@ class DropdownItemViewInfoListBuilder { /** Signals that native initialization has completed. */ void onNativeInitialized() { mHeaderProcessor.onNativeInitialized(); diff --git a/build/patches/Restore-Simplified-NTP-launch.patch b/build/patches/Restore-Simplified-NTP-launch.patch index f1d95c8c..63c65632 100644 --- a/build/patches/Restore-Simplified-NTP-launch.patch +++ b/build/patches/Restore-Simplified-NTP-launch.patch @@ -30,7 +30,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -566,6 +566,7 @@ chrome_java_resources = [ +@@ -570,6 +570,7 @@ chrome_java_resources = [ "java/res/layout/new_tab_page_incognito.xml", "java/res/layout/new_tab_page_layout.xml", "java/res/layout/new_tab_page_tile_grid_placeholder.xml", @@ -41,7 +41,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -599,6 +599,7 @@ chrome_java_sources = [ +@@ -610,6 +610,7 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollector.java", "java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java", "java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java", @@ -225,7 +225,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageL /** * Whether the tiles shown in the layout have finished loading. * With {@link #mHasShownView}, it's one of the 2 flags used to track initialisation progress. -@@ -227,6 +230,7 @@ public class NewTabPageLayout extends LinearLayout { +@@ -243,6 +246,7 @@ public class NewTabPageLayout extends LinearLayout { initializeMostVisitedTilesCoordinator(profile, lifecycleDispatcher, tileGroupDelegate, touchEnabledDelegate, isScrollableMvtEnabled(), searchProviderIsGoogle); initializeSearchBoxBackground(); @@ -233,7 +233,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageL initializeSearchBoxTextView(); initializeVoiceSearchButton(); initializeLensButton(); -@@ -572,16 +576,22 @@ public class NewTabPageLayout extends LinearLayout { +@@ -605,16 +609,22 @@ public class NewTabPageLayout extends LinearLayout { marginLayoutParams.leftMargin = lateralPaddingsForNTP; marginLayoutParams.rightMargin = lateralPaddingsForNTP; } @@ -257,8 +257,8 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageL + } marginLayoutParams.bottomMargin = getGridMvtBottomMargin(); } - if (mIsNtpAsHomeSurfaceEnabled) { -@@ -884,6 +894,22 @@ public class NewTabPageLayout extends LinearLayout { + +@@ -917,6 +927,22 @@ public class NewTabPageLayout extends LinearLayout { return iphCommandBuilder; } @@ -318,7 +318,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Sug diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5208,6 +5208,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5271,6 +5271,9 @@ const FeatureEntry kFeatureEntries[] = { SINGLE_VALUE_TYPE_AND_VALUE( switches::kForceShowUpdateMenuItemCustomSummary, "Custom Summary")}, @@ -331,7 +331,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4335,6 +4335,9 @@ const char kStartSurfaceWithAccessibilityName[] = +@@ -4394,6 +4394,9 @@ const char kStartSurfaceWithAccessibilityName[] = const char kStartSurfaceWithAccessibilityDescription[] = "Enable Start Surface with Accessibility."; @@ -344,7 +344,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2503,6 +2503,9 @@ extern const char kSlimCompositorDescription[]; +@@ -2553,6 +2553,9 @@ extern const char kSmartZoomDescription[]; extern const char kSmartSuggestionForLargeDownloadsName[]; extern const char kSmartSuggestionForLargeDownloadsDescription[]; @@ -357,7 +357,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -240,6 +240,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -245,6 +245,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kIncognitoReauthenticationForAndroid, &kIncognitoScreenshot, &kInfobarScrollOptimization, @@ -365,7 +365,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &kInstanceSwitcher, &kInstantStart, &kLensCameraAssistedSearch, -@@ -782,6 +783,10 @@ BASE_FEATURE(kInstanceSwitcher, +@@ -800,6 +801,10 @@ BASE_FEATURE(kInstanceSwitcher, "InstanceSwitcher", base::FEATURE_ENABLED_BY_DEFAULT); @@ -379,7 +379,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -121,6 +121,7 @@ BASE_DECLARE_FEATURE(kOmniboxModernizeVisualUpdate); +@@ -129,6 +129,7 @@ BASE_DECLARE_FEATURE(kOmniboxModernizeVisualUpdate); BASE_DECLARE_FEATURE(kOmniboxWarmRecycledViewPool); BASE_DECLARE_FEATURE(kOptimizeGeolocationHeaderGeneration); BASE_DECLARE_FEATURE(kPageAnnotationsService); @@ -390,7 +390,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -301,6 +301,7 @@ public abstract class ChromeFeatureList { +@@ -306,6 +306,7 @@ public abstract class ChromeFeatureList { public static final String LOOKALIKE_NAVIGATION_URL_SUGGESTIONS_UI = "LookalikeUrlNavigationSuggestionsUI"; public static final String MESSAGES_FOR_ANDROID_ADS_BLOCKED = "MessagesForAndroidAdsBlocked"; @@ -413,7 +413,7 @@ diff --git a/components/signin/public/base/signin_switches.cc b/components/signi diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json -@@ -6637,6 +6637,24 @@ +@@ -7276,6 +7276,24 @@ ] } ], diff --git a/build/patches/Restore-adaptive-button-in-top-toolbar-customization.patch b/build/patches/Restore-adaptive-button-in-top-toolbar-customization.patch index 14576f27..9a42f67c 100644 --- a/build/patches/Restore-adaptive-button-in-top-toolbar-customization.patch +++ b/build/patches/Restore-adaptive-button-in-top-toolbar-customization.patch @@ -20,7 +20,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java -@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.signin.services.SigninManager; +@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.sync.SyncServiceFactory; import org.chromium.chrome.browser.sync.settings.ManageSyncSettings; import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils; @@ -28,7 +28,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSe import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor; import org.chromium.chrome.browser.tracing.settings.DeveloperSettings; import org.chromium.components.browser_ui.settings.ChromeBasePreference; -@@ -212,7 +213,9 @@ public class MainSettings extends PreferenceFragmentCompat +@@ -202,7 +203,9 @@ public class MainSettings extends PreferenceFragmentCompat new AdaptiveToolbarStatePredictor(null).recomputeUiState(uiState -> { // We don't show the toolbar shortcut settings page if disabled from finch. @@ -89,7 +89,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButt diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -632,18 +632,12 @@ const FeatureEntry::FeatureParam kAdaptiveButtonCustomization_Share[] = { +@@ -638,18 +638,12 @@ const FeatureEntry::FeatureParam kAdaptiveButtonCustomization_Share[] = { {"default_segment", "share"}, {"show_ui_only_after_ready", "false"}, {"ignore_segmentation_results", "true"}}; @@ -126,7 +126,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java -@@ -239,7 +239,11 @@ public class AdaptiveToolbarButtonController +@@ -238,7 +238,11 @@ public class AdaptiveToolbarButtonController @Override public void onFinishNativeInitialization() { @@ -142,7 +142,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java -@@ -12,8 +12,18 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; +@@ -16,8 +16,18 @@ import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge; /** * A utility class for handling feature flags used by {@link AdaptiveToolbarButtonController}. @@ -161,7 +161,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** Finch default group for new tab variation. */ static final String NEW_TAB = "new-tab"; /** Finch default group for share variation. */ -@@ -26,6 +36,7 @@ public class AdaptiveToolbarFeatures { +@@ -30,6 +40,7 @@ public class AdaptiveToolbarFeatures { private static final String VARIATION_PARAM_DISABLE_UI = "disable_ui"; private static final String VARIATION_PARAM_IGNORE_SEGMENTATION_RESULTS = "ignore_segmentation_results"; @@ -169,7 +169,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow private static final String VARIATION_PARAM_SHOW_UI_ONLY_AFTER_READY = "show_ui_only_after_ready"; @VisibleForTesting -@@ -95,6 +106,21 @@ public class AdaptiveToolbarFeatures { +@@ -100,6 +111,21 @@ public class AdaptiveToolbarFeatures { } } @@ -191,7 +191,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * Returns whether the adaptive toolbar is enabled with segmentation and customization. * -@@ -205,11 +231,48 @@ public class AdaptiveToolbarFeatures { +@@ -220,11 +246,48 @@ public class AdaptiveToolbarFeatures { ChromeFeatureList.CONTEXTUAL_PAGE_ACTIONS, "enable_ui", true); } @@ -260,7 +260,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java -@@ -69,6 +69,21 @@ public class AdaptiveToolbarStatePredictorTest { +@@ -68,6 +68,21 @@ public class AdaptiveToolbarStatePredictorTest { statePredictor.recomputeUiState(verifyResultCallback(expected)); } diff --git a/build/patches/Restore-offline-indicator-v2-flag.patch b/build/patches/Restore-offline-indicator-v2-flag.patch index 028aa2cc..3fffaa18 100644 --- a/build/patches/Restore-offline-indicator-v2-flag.patch +++ b/build/patches/Restore-offline-indicator-v2-flag.patch @@ -51,7 +51,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/in mUpdateOfflineStatusIndicatorDelayedRunnable = () -> { if (sLoggingEnabled) { -@@ -357,4 +361,34 @@ class OfflineDetector +@@ -356,4 +360,34 @@ class OfflineDetector timeNeededAfterConnectionChangeFromOnlineToOffline), timeNeededAfterConnectionChangeFromAirplaneToOffline)); } @@ -89,7 +89,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/in diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java -@@ -848,7 +848,8 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { +@@ -845,7 +845,8 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { private void initStatusIndicatorCoordinator(LayoutManagerImpl layoutManager) { // TODO(crbug.com/1035584): Disable on tablets for now as we need to do one or two extra // things for tablets. @@ -99,7 +99,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab return; } -@@ -870,6 +871,11 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { +@@ -867,6 +868,11 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { mStatusIndicatorCoordinator.addObserver(mStatusIndicatorObserver); mStatusIndicatorCoordinator.addObserver(mStatusBarColorController); @@ -114,7 +114,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -5113,6 +5113,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -5177,6 +5177,9 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kOfflinePagesLivePageSharingName, flag_descriptions::kOfflinePagesLivePageSharingDescription, kOsAndroid, FEATURE_VALUE_TYPE(offline_pages::kOfflinePagesLivePageSharingFeature)}, @@ -127,7 +127,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -5630,6 +5630,11 @@ +@@ -5853,6 +5853,11 @@ "owners": [ "//components/search/OWNERS" ], "expiry_milestone": 118 }, @@ -142,7 +142,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4082,6 +4082,10 @@ const char kNotificationPermissionRationaleBottomSheetDescription[] = +@@ -4146,6 +4146,10 @@ const char kNotificationPermissionRationaleBottomSheetDescription[] = "flow. " "Only works with builds targeting Android T+."; @@ -156,7 +156,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2375,6 +2375,9 @@ extern const char kNetworkServiceInProcessDescription[]; +@@ -2428,6 +2428,9 @@ extern const char kNetworkServiceInProcessDescription[]; extern const char kNotificationPermissionRationaleName[]; extern const char kNotificationPermissionRationaleDescription[]; @@ -169,7 +169,7 @@ diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptio diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc -@@ -249,6 +249,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { +@@ -254,6 +254,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kLensOnQuickActionSearchWidget, &kNotificationPermissionVariant, &kNotificationPermissionBottomSheet, @@ -177,9 +177,9 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse &kPageAnnotationsService, &kPreconnectOnTabCreation, &kInlineUpdateFlow, -@@ -749,6 +750,10 @@ BASE_FEATURE(kDrawEdgeToEdge, +@@ -767,6 +768,10 @@ BASE_FEATURE(kDrawEdgeToEdge, - BASE_FEATURE(kEmptyStates, "EmptyStates", base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kEmptyStates, "EmptyStates", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kOfflineIndicatorV2, + "OfflineIndicatorV2", @@ -191,7 +191,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browse diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h -@@ -112,6 +112,7 @@ BASE_DECLARE_FEATURE(kLanguagesPreference); +@@ -118,6 +118,7 @@ BASE_DECLARE_FEATURE(kLanguagesPreference); BASE_DECLARE_FEATURE(kLensCameraAssistedSearch); BASE_DECLARE_FEATURE(kLensOnQuickActionSearchWidget); BASE_DECLARE_FEATURE(kLocationBarModelOptimizations); @@ -202,7 +202,7 @@ diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java -@@ -313,6 +313,7 @@ public abstract class ChromeFeatureList { +@@ -318,6 +318,7 @@ public abstract class ChromeFeatureList { public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant"; public static final String NOTIFICATION_PERMISSION_BOTTOM_SHEET = "NotificationPermissionBottomSheet"; diff --git a/build/patches/Revert-Delete-block-external-form-redirects.patch b/build/patches/Revert-Delete-block-external-form-redirects.patch index e7fbda98..d78e0645 100644 --- a/build/patches/Revert-Delete-block-external-form-redirects.patch +++ b/build/patches/Revert-Delete-block-external-form-redirects.patch @@ -7,7 +7,7 @@ enables IntentBlockExternalFormRedirectsNoGesture. License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/about_flags.cc | 7 +++++++ + chrome/browser/about_flags.cc | 6 ++++++ chrome/browser/flag-metadata.json | 5 +++++ chrome/browser/flag_descriptions.cc | 6 ++++++ chrome/browser/flag_descriptions.h | 3 +++ @@ -15,20 +15,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../android/external_intents_features.h | 1 + .../ExternalIntentsFeatures.java | 6 ++++++ .../ExternalNavigationHandler.java | 21 +++++++++++++++++++ - 8 files changed, 55 insertions(+), 1 deletion(-) + 8 files changed, 54 insertions(+), 1 deletion(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -243,6 +243,7 @@ - #include "chrome/browser/push_messaging/push_messaging_features.h" - #include "components/browser_ui/photo_picker/android/features.h" - #include "components/content_creation/notes/core/note_features.h" -+#include "components/external_intents/android/external_intents_features.h" - #include "components/translate/content/android/translate_message.h" - #include "ui/android/ui_android_features.h" - #else // BUILDFLAG(IS_ANDROID) -@@ -10022,6 +10023,12 @@ const FeatureEntry kFeatureEntries[] = { +@@ -10089,6 +10089,12 @@ const FeatureEntry kFeatureEntries[] = { #endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) @@ -44,7 +36,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -788,6 +788,11 @@ +@@ -843,6 +843,11 @@ "owners": [ "ioanap", "vsemeniuk@google.com" ], "expiry_milestone": 117 }, @@ -59,7 +51,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4002,6 +4002,12 @@ const char kInstantStartName[] = "Instant start"; +@@ -4054,6 +4054,12 @@ const char kInstantStartName[] = "Instant start"; const char kInstantStartDescription[] = "Show start surface before native library is loaded."; @@ -75,7 +67,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2327,6 +2327,9 @@ extern const char kInstanceSwitcherDescription[]; +@@ -2374,6 +2374,9 @@ extern const char kInstanceSwitcherDescription[]; extern const char kInstantStartName[]; extern const char kInstantStartDescription[]; @@ -91,13 +83,13 @@ diff --git a/components/external_intents/android/external_intents_features.cc b/ @@ -20,7 +20,6 @@ namespace { const base::Feature* kFeaturesExposedToJava[] = { &kExternalNavigationDebugLogs, &kBlockFrameRenavigations, - &kDoNotRequireSpecializedCCTHandler, &kBlockIntentsToSelf}; + &kBlockIntentsToSelf, &kTrustedClientGestureBypass}; - } // namespace // Alphabetical: -@@ -41,7 +40,13 @@ BASE_FEATURE(kBlockIntentsToSelf, - "BlockIntentsToSelf", +@@ -41,7 +40,13 @@ BASE_FEATURE(kTrustedClientGestureBypass, + "TrustedClientGestureBypass", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kIntentBlockExternalFormRedirectsNoGesture, @@ -120,7 +112,7 @@ diff --git a/components/external_intents/android/external_intents_features.h b/c +BASE_DECLARE_FEATURE(kIntentBlockExternalFormRedirectsNoGesture); BASE_DECLARE_FEATURE(kExternalNavigationDebugLogs); BASE_DECLARE_FEATURE(kBlockFrameRenavigations); - BASE_DECLARE_FEATURE(kDoNotRequireSpecializedCCTHandler); + BASE_DECLARE_FEATURE(kBlockIntentsToSelf); diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java @@ -136,11 +128,11 @@ diff --git a/components/external_intents/android/java/src/org/chromium/component + public static final String EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME = "ExternalNavigationDebugLogs"; public static final String BLOCK_FRAME_RENAVIGATIONS_NAME = "BlockFrameRenavigations2"; - public static final String DO_NOT_REQUIRE_SPECIALIZED_CCT_HANDLER_NAME = + public static final String BLOCK_INTENTS_TO_SELF_NAME = "BlockIntentsToSelf"; diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java -@@ -1497,6 +1497,12 @@ public class ExternalNavigationHandler { +@@ -1556,6 +1556,12 @@ public class ExternalNavigationHandler { || ignoreBackForwardNav(params); } @@ -153,7 +145,7 @@ diff --git a/components/external_intents/android/java/src/org/chromium/component private OverrideUrlLoadingResult shouldOverrideUrlLoadingInternal( ExternalNavigationParams params, Intent targetIntent, GURL browserFallbackUrl, MutableBoolean canLaunchExternalFallbackResult) { -@@ -1550,6 +1556,21 @@ public class ExternalNavigationHandler { +@@ -1609,6 +1615,21 @@ public class ExternalNavigationHandler { return OverrideUrlLoadingResult.forNoOverride(); } diff --git a/build/patches/Revert-flags-remove-disable-pull-to-refresh-effect.patch b/build/patches/Revert-flags-remove-disable-pull-to-refresh-effect.patch index c2f365a1..edca9f5e 100644 --- a/build/patches/Revert-flags-remove-disable-pull-to-refresh-effect.patch +++ b/build/patches/Revert-flags-remove-disable-pull-to-refresh-effect.patch @@ -16,21 +16,21 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -4595,6 +4595,10 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kEnableVulkanDescription, - kOsWin | kOsLinux | kOsAndroid, FEATURE_VALUE_TYPE(features::kVulkan)}, +@@ -4670,6 +4670,10 @@ const FeatureEntry kFeatureEntries[] = { + kOsWin | kOsLinux | kOsAndroid | kOsCrOS, + FEATURE_VALUE_TYPE(features::kVulkan)}, #if BUILDFLAG(IS_ANDROID) + {switches::kDisablePullToRefreshEffect, + flag_descriptions::kDisablePullToRefreshEffectName, + flag_descriptions::kDisablePullToRefreshEffectDescription, kOsAndroid, + SINGLE_DISABLE_VALUE_TYPE(switches::kDisablePullToRefreshEffect)}, - {"translate-assist-content", flag_descriptions::kTranslateAssistContentName, - flag_descriptions::kTranslateAssistContentDescription, kOsAndroid, - FEATURE_VALUE_TYPE(language::kTranslateAssistContent)}, + {"translate-message-ui", flag_descriptions::kTranslateMessageUIName, + flag_descriptions::kTranslateMessageUIDescription, kOsAndroid, + FEATURE_VALUE_TYPE(translate::kTranslateMessageUI)}, diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -1650,6 +1650,10 @@ +@@ -1737,6 +1737,10 @@ "yangsharon@google.com", "alexmos@google.com", "creis@google.com" ], "expiry_milestone": 122 }, @@ -44,7 +44,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -4133,6 +4133,10 @@ const char kReadLaterDescription[] = +@@ -4200,6 +4200,10 @@ const char kReadLaterDescription[] = "Allow users to save tabs for later. Enables a new button and menu for " "accessing tabs saved for later."; @@ -58,9 +58,9 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -2410,6 +2410,9 @@ extern const char kQueryTilesSegmentationDescription[]; - extern const char kQueryTilesSwapTrendingName[]; - extern const char kQueryTilesSwapTrendingDescription[]; +@@ -2466,6 +2466,9 @@ extern const char kQueryTilesSwapTrendingDescription[]; + extern const char kReadAloudName[]; + extern const char kReadAloudDescription[]; +extern const char kDisablePullToRefreshEffectName[]; +extern const char kDisablePullToRefreshEffectDescription[]; diff --git a/build/patches/Revert-flags-remove-num-raster-threads.patch b/build/patches/Revert-flags-remove-num-raster-threads.patch index 726e1a88..7b50aee1 100644 --- a/build/patches/Revert-flags-remove-num-raster-threads.patch +++ b/build/patches/Revert-flags-remove-num-raster-threads.patch @@ -6,19 +6,20 @@ This reverts commit 2a51528a1737e9038f7f96f29403032a6a845a25. License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/about_flags.cc | 12 ++++++++++++ + chrome/browser/about_flags.cc | 14 ++++++++++++++ chrome/browser/flag-metadata.json | 4 ++++ chrome/browser/flag_descriptions.cc | 8 ++++++++ chrome/browser/flag_descriptions.h | 7 +++++++ - 4 files changed, 31 insertions(+) + 4 files changed, 33 insertions(+) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -387,6 +387,15 @@ const FeatureEntry::Choice kOverlayStrategiesChoices[] = { +@@ -392,6 +392,17 @@ const FeatureEntry::Choice kOverlayStrategiesChoices[] = { "single-fullscreen,single-on-top,underlay"}, }; ++#if BUILDFLAG(IS_ANDROID) +const FeatureEntry::Choice kNumRasterThreadsChoices[] = { + {flags_ui::kGenericExperimentChoiceDefault, "", ""}, + {flag_descriptions::kNumRasterThreadsOne, cc::switches::kNumRasterThreads, "1"}, @@ -27,11 +28,12 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc + "3"}, + {flag_descriptions::kNumRasterThreadsFour, cc::switches::kNumRasterThreads, + "4"}}; ++#endif + const FeatureEntry::Choice kTouchTextSelectionStrategyChoices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, {flag_descriptions::kTouchSelectionStrategyCharacter, -@@ -4767,6 +4776,9 @@ const FeatureEntry kFeatureEntries[] = { +@@ -4826,6 +4837,9 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(mojo::core::kMojoLinuxChannelSharedMem)}, #endif #if BUILDFLAG(IS_ANDROID) @@ -44,7 +46,7 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json -@@ -5288,6 +5288,10 @@ +@@ -5489,6 +5489,10 @@ "owners": [ "lazzzis", "aishwaryarj"], "expiry_milestone": 118 }, @@ -58,7 +60,7 @@ diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.js diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -2202,6 +2202,14 @@ const char kOmniboxActionsInSuggestDescription[] = +@@ -2244,6 +2244,14 @@ const char kOmniboxActionsInSuggestDescription[] = "Actions in Suggest permits optional Action Chips to be attached to " "Entity suggestions."; @@ -76,7 +78,7 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -1246,6 +1246,13 @@ extern const char kOmitCorsClientCertDescription[]; +@@ -1283,6 +1283,13 @@ extern const char kOmitCorsClientCertDescription[]; extern const char kOmniboxActionsInSuggestName[]; extern const char kOmniboxActionsInSuggestDescription[]; diff --git a/build/patches/Revert-removal-of-execution-context-address-space.patch b/build/patches/Revert-removal-of-execution-context-address-space.patch index 3b51281c..2f3ccc1f 100644 --- a/build/patches/Revert-removal-of-execution-context-address-space.patch +++ b/build/patches/Revert-removal-of-execution-context-address-space.patch @@ -58,7 +58,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -186,7 +186,7 @@ BASE_FEATURE(kBlockInsecurePrivateNetworkRequestsFromPrivate, +@@ -197,7 +197,7 @@ BASE_FEATURE(kBlockInsecurePrivateNetworkRequestsFromPrivate, // - kBlockInsecurePrivateNetworkRequests BASE_FEATURE(kBlockInsecurePrivateNetworkRequestsFromUnknown, "BlockInsecurePrivateNetworkRequestsFromUnknown", @@ -70,7 +70,7 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc -@@ -524,6 +524,15 @@ void ExecutionContext::SetReferrerPolicy( +@@ -516,6 +516,15 @@ void ExecutionContext::SetReferrerPolicy( policy_container_->UpdateReferrerPolicy(referrer_policy); } @@ -175,7 +175,7 @@ diff --git a/third_party/blink/renderer/core/frame/policy_container.h b/third_pa diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc -@@ -8063,6 +8063,40 @@ TEST_F(WebFrameTest, PushStateStartsAndStops) { +@@ -8064,6 +8064,40 @@ TEST_F(WebFrameTest, PushStateStartsAndStops) { EXPECT_EQ(client.StopLoadingCount(), 2); } @@ -231,7 +231,7 @@ diff --git a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_glo diff --git a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc --- a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc -@@ -67,6 +67,7 @@ void InstalledServiceWorkerModuleScriptFetcher::Fetch( +@@ -69,6 +69,7 @@ void InstalledServiceWorkerModuleScriptFetcher::Fetch( global_scope_->Initialize( response_url, response_referrer_policy, @@ -261,7 +261,7 @@ diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_s #include "services/network/public/mojom/referrer_policy.mojom-blink.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/loader/network_utils.h" -@@ -174,7 +175,7 @@ void WorkerModuleScriptFetcher::NotifyClient( +@@ -175,7 +176,7 @@ void WorkerModuleScriptFetcher::NotifyClient( // Step 12.3-12.6 are implemented in Initialize(). global_scope_->Initialize( @@ -786,7 +786,7 @@ diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_imp diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc -@@ -454,6 +454,7 @@ void ServiceWorkerGlobalScope::DidFetchClassicScript( +@@ -455,6 +455,7 @@ void ServiceWorkerGlobalScope::DidFetchClassicScript( // is set, and with the following callback steps given evaluationStatus:" RunClassicScript( classic_script_loader->ResponseURL(), referrer_policy, @@ -794,7 +794,7 @@ diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_gl classic_script_loader->GetContentSecurityPolicy() ? mojo::Clone(classic_script_loader->GetContentSecurityPolicy() ->GetParsedPolicies()) -@@ -467,6 +468,7 @@ void ServiceWorkerGlobalScope::DidFetchClassicScript( +@@ -468,6 +469,7 @@ void ServiceWorkerGlobalScope::DidFetchClassicScript( void ServiceWorkerGlobalScope::Initialize( const KURL& response_url, network::mojom::ReferrerPolicy response_referrer_policy, @@ -802,7 +802,7 @@ diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_gl Vector response_csp, const Vector* response_origin_trial_tokens) { // Step 4.5. "Set workerGlobalScope's url to serviceWorker's script url." -@@ -480,6 +482,9 @@ void ServiceWorkerGlobalScope::Initialize( +@@ -481,6 +483,9 @@ void ServiceWorkerGlobalScope::Initialize( // script resource's referrer policy." SetReferrerPolicy(response_referrer_policy); @@ -812,7 +812,7 @@ diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_gl // This is quoted from the "Content Security Policy" algorithm in the service // workers spec: // "Whenever a user agent invokes Run Service Worker algorithm with a service -@@ -490,6 +495,9 @@ void ServiceWorkerGlobalScope::Initialize( +@@ -491,6 +496,9 @@ void ServiceWorkerGlobalScope::Initialize( // - If serviceWorker's script resource was delivered with a // Content-Security-Policy-Report-Only HTTP header containing the value // policy, the user agent must monitor policy for serviceWorker." @@ -822,7 +822,7 @@ diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_gl InitContentSecurityPolicyFromVector(std::move(response_csp)); BindContentSecurityPolicyToExecutionContext(); -@@ -530,26 +538,27 @@ void ServiceWorkerGlobalScope::LoadAndRunInstalledClassicScript( +@@ -531,26 +539,27 @@ void ServiceWorkerGlobalScope::LoadAndRunInstalledClassicScript( kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy); } diff --git a/build/patches/Samsung-Note-9-SDK27-crazylinker-workaround.patch b/build/patches/Samsung-Note-9-SDK27-crazylinker-workaround.patch index ec0ba7b1..37a071d9 100644 --- a/build/patches/Samsung-Note-9-SDK27-crazylinker-workaround.patch +++ b/build/patches/Samsung-Note-9-SDK27-crazylinker-workaround.patch @@ -11,7 +11,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java -@@ -35,6 +35,7 @@ import org.chromium.build.annotations.MainDex; +@@ -36,6 +36,7 @@ import org.chromium.build.annotations.MainDex; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -19,7 +19,7 @@ diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoade import javax.annotation.concurrent.GuardedBy; -@@ -274,7 +275,21 @@ public class LibraryLoader { +@@ -275,7 +276,21 @@ public class LibraryLoader { */ public void initInAppZygote() { assert !mInitDone; diff --git a/build/patches/Show-site-settings-for-cookies-javascript-and-ads.patch b/build/patches/Show-site-settings-for-cookies-javascript-and-ads.patch index c92af3b4..4ebf0c3a 100644 --- a/build/patches/Show-site-settings-for-cookies-javascript-and-ads.patch +++ b/build/patches/Show-site-settings-for-cookies-javascript-and-ads.patch @@ -13,7 +13,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java -@@ -529,6 +529,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -532,6 +532,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment setUpSoundPreference(preference); } else if (type == ContentSettingsType.JAVASCRIPT) { setUpJavascriptPreference(preference); @@ -22,7 +22,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } else if (type == ContentSettingsType.GEOLOCATION) { setUpLocationPreference(preference); } else if (type == ContentSettingsType.NOTIFICATIONS) { -@@ -888,16 +890,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -889,16 +891,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment private void setUpAdsInformationalBanner() { // Add the informational banner which shows at the top of the UI if ad blocking is // activated on this site. @@ -39,7 +39,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } private SiteSettingsCategory getWarningCategory() { -@@ -1069,17 +1063,35 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -1070,17 +1064,35 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment @Nullable Integer currentValue = mSite.getContentSetting(browserContextHandle, ContentSettingsType.JAVASCRIPT); @@ -81,7 +81,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c /** * Updates the ads list preference based on whether the site is a candidate for blocking. This * has some custom behavior. -@@ -1095,22 +1107,10 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment +@@ -1096,22 +1108,10 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment setupContentSettingsPreference(preference, null, false); return; } @@ -107,7 +107,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java -@@ -204,13 +204,18 @@ public final class Website implements WebsiteEntry { +@@ -205,13 +205,18 @@ public final class Website implements WebsiteEntry { ContentSettingException exception = getContentSettingException(type); if (type == ContentSettingsType.ADS) { diff --git a/build/patches/Site-setting-for-images.patch b/build/patches/Site-setting-for-images.patch index cafa7352..c2398d63 100644 --- a/build/patches/Site-setting-for-images.patch +++ b/build/patches/Site-setting-for-images.patch @@ -259,7 +259,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc -@@ -146,12 +146,8 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, +@@ -145,12 +145,8 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, ContentSettingToValue(CONTENT_SETTING_ALLOW), std::string(), map->IsOffTheRecord())); #else diff --git a/build/patches/Switch-to-fstack-protector-strong.patch b/build/patches/Switch-to-fstack-protector-strong.patch index d49dd769..21e5f8ec 100644 --- a/build/patches/Switch-to-fstack-protector-strong.patch +++ b/build/patches/Switch-to-fstack-protector-strong.patch @@ -19,7 +19,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -361,18 +361,12 @@ config("compiler") { +@@ -360,18 +360,12 @@ config("compiler") { cflags += [ "-fstack-protector" ] } } else if ((is_posix && !is_chromeos && !is_nacl) || is_fuchsia) { diff --git a/build/patches/Timezone-customization.patch b/build/patches/Timezone-customization.patch index 169c07de..3a0cd9ed 100644 --- a/build/patches/Timezone-customization.patch +++ b/build/patches/Timezone-customization.patch @@ -45,7 +45,7 @@ Require: Content-settings-infrastructure.patch diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn -@@ -101,6 +101,7 @@ android_library("java") { +@@ -103,6 +103,7 @@ android_library("java") { "java/src/org/chromium/components/browser_ui/site_settings/WebsitePreference.java", "java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java", "java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java", @@ -53,7 +53,7 @@ diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/b ] resources_package = "org.chromium.components.browser_ui.site_settings" -@@ -267,6 +268,8 @@ android_resources("java_resources") { +@@ -272,6 +273,8 @@ android_resources("java_resources") { "java/res/xml/site_settings_preferences.xml", "java/res/xml/site_settings_preferences_with_categories.xml", "java/res/xml/website_preferences.xml", @@ -379,7 +379,7 @@ new file mode 100755 diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java -@@ -384,6 +384,14 @@ public class WebsitePreferenceBridge { +@@ -412,6 +412,14 @@ public class WebsitePreferenceBridge { return WebsitePreferenceBridgeJni.get().toHostOnlyPattern(pattern); } @@ -394,7 +394,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c @NativeMethods public interface Natives { boolean isNotificationEmbargoedForOrigin( -@@ -448,5 +456,7 @@ public class WebsitePreferenceBridge { +@@ -481,5 +489,7 @@ public class WebsitePreferenceBridge { boolean getLocationAllowedByPolicy(BrowserContextHandle browserContextHandle); String toDomainWildcardPattern(String pattern); String toHostOnlyPattern(String pattern); @@ -557,7 +557,7 @@ new file mode 100644 diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc --- a/components/browser_ui/site_settings/android/website_preference_bridge.cc +++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc -@@ -1020,3 +1020,19 @@ JNI_WebsitePreferenceBridge_ToHostOnlyPattern( +@@ -1103,3 +1103,19 @@ JNI_WebsitePreferenceBridge_ToHostOnlyPattern( ContentSettingsPattern::FromString(pattern_string)); return ConvertUTF8ToJavaString(env, host_only_pattern.ToString()); } @@ -652,7 +652,7 @@ new file mode 100644 diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc --- a/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc -@@ -71,6 +71,8 @@ void PrefProvider::RegisterProfilePrefs( +@@ -72,6 +72,8 @@ void PrefProvider::RegisterProfilePrefs( info->GetPrefRegistrationFlags()); } @@ -661,7 +661,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov // Obsolete prefs ---------------------------------------------------------- // These prefs have been removed, but need to be registered so they can -@@ -142,6 +144,10 @@ PrefProvider::PrefProvider(PrefService* prefs, +@@ -143,6 +145,10 @@ PrefProvider::PrefProvider(PrefService* prefs, event_args->set_number_of_exceptions( num_exceptions); // PrefProvider::PrefProvider. }); @@ -672,7 +672,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov } PrefProvider::~PrefProvider() { -@@ -330,4 +336,14 @@ void PrefProvider::SetClockForTesting(base::Clock* clock) { +@@ -404,4 +410,14 @@ void PrefProvider::SetClockForTesting(base::Clock* clock) { clock_ = clock; } @@ -690,7 +690,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov diff --git a/components/content_settings/core/browser/content_settings_pref_provider.h b/components/content_settings/core/browser/content_settings_pref_provider.h --- a/components/content_settings/core/browser/content_settings_pref_provider.h +++ b/components/content_settings/core/browser/content_settings_pref_provider.h -@@ -69,6 +69,9 @@ class PrefProvider : public UserModifiableProvider { +@@ -78,6 +78,9 @@ class PrefProvider : public UserModifiableProvider { ContentSettingsPref* GetPref(ContentSettingsType type) const; @@ -700,7 +700,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov private: friend class DeadlockCheckerObserver; // For testing. -@@ -106,6 +109,7 @@ class PrefProvider : public UserModifiableProvider { +@@ -123,6 +126,7 @@ class PrefProvider : public UserModifiableProvider { base::ThreadChecker thread_checker_; raw_ptr clock_; @@ -711,10 +711,10 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc -@@ -161,6 +161,11 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, - &(rules->script_rules)); - map->GetSettingsForOneType(ContentSettingsType::POPUPS, - &(rules->popup_redirect_rules)); +@@ -160,6 +160,11 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, + map->GetSettingsForOneType(ContentSettingsType::JAVASCRIPT); + rules->popup_redirect_rules = + map->GetSettingsForOneType(ContentSettingsType::POPUPS); + + // pass custom timezone value to the render process + std::string timezone; @@ -726,7 +726,7 @@ diff --git a/components/content_settings/core/browser/content_settings_utils.cc diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc -@@ -659,6 +659,14 @@ void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) { +@@ -662,6 +662,14 @@ void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) { provider->SetClockForTesting(clock); } @@ -744,7 +744,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h --- a/components/content_settings/core/browser/host_content_settings_map.h +++ b/components/content_settings/core/browser/host_content_settings_map.h -@@ -365,6 +365,9 @@ class HostContentSettingsMap : public content_settings::Observer, +@@ -379,6 +379,9 @@ class HostContentSettingsMap : public content_settings::Observer, allow_invalid_secondary_pattern_for_testing_ = allow; } @@ -775,7 +775,7 @@ diff --git a/components/content_settings/core/common/content_settings.h b/compon diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom --- a/components/content_settings/core/common/content_settings.mojom +++ b/components/content_settings/core/common/content_settings.mojom -@@ -101,4 +101,5 @@ struct RendererContentSettingRules { +@@ -102,4 +102,5 @@ struct RendererContentSettingRules { array popup_redirect_rules; array mixed_content_rules; array auto_dark_content_rules; @@ -784,7 +784,7 @@ diff --git a/components/content_settings/core/common/content_settings.mojom b/co diff --git a/components/content_settings/core/common/content_settings_mojom_traits.cc b/components/content_settings/core/common/content_settings_mojom_traits.cc --- a/components/content_settings/core/common/content_settings_mojom_traits.cc +++ b/components/content_settings/core/common/content_settings_mojom_traits.cc -@@ -172,7 +172,8 @@ bool StructTraitsscript_rules) && data.ReadPopupRedirectRules(&out->popup_redirect_rules) && data.ReadMixedContentRules(&out->mixed_content_rules) && @@ -797,7 +797,7 @@ diff --git a/components/content_settings/core/common/content_settings_mojom_trai diff --git a/components/content_settings/core/common/content_settings_mojom_traits.h b/components/content_settings/core/common/content_settings_mojom_traits.h --- a/components/content_settings/core/common/content_settings_mojom_traits.h +++ b/components/content_settings/core/common/content_settings_mojom_traits.h -@@ -218,6 +218,11 @@ struct StructTraits< +@@ -222,6 +222,11 @@ struct StructTraits< return r.auto_dark_content_rules; } @@ -812,8 +812,8 @@ diff --git a/components/content_settings/core/common/content_settings_mojom_trai diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc --- a/components/content_settings/core/common/pref_names.cc +++ b/components/content_settings/core/common/pref_names.cc -@@ -182,4 +182,7 @@ const char kDesktopSitePeripheralSettingEnabled[] = - const char kDesktopSiteDisplaySettingEnabled[] = "desktop_site.display_setting"; +@@ -216,4 +216,7 @@ const char kDesktopSiteDisplaySettingEnabled[] = "desktop_site.display_setting"; + const char kDesktopSiteWindowSettingEnabled[] = "desktop_site.window_setting"; #endif +const char kContentSettingsCustomTimezone[] = @@ -823,8 +823,8 @@ diff --git a/components/content_settings/core/common/pref_names.cc b/components/ diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h --- a/components/content_settings/core/common/pref_names.h +++ b/components/content_settings/core/common/pref_names.h -@@ -93,6 +93,8 @@ extern const char kDesktopSitePeripheralSettingEnabled[]; - extern const char kDesktopSiteDisplaySettingEnabled[]; +@@ -101,6 +101,8 @@ extern const char kDesktopSiteDisplaySettingEnabled[]; + extern const char kDesktopSiteWindowSettingEnabled[]; #endif +extern const char kContentSettingsCustomTimezone[]; diff --git a/build/patches/Use-4-tile-rows-never-show-logo.patch b/build/patches/Use-4-tile-rows-never-show-logo.patch index 4c2b0788..a42c90ab 100644 --- a/build/patches/Use-4-tile-rows-never-show-logo.patch +++ b/build/patches/Use-4-tile-rows-never-show-logo.patch @@ -22,7 +22,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageL private boolean mSearchProviderIsGoogle; private boolean mShowingNonStandardLogo; -@@ -360,7 +360,7 @@ public class NewTabPageLayout extends LinearLayout { +@@ -381,7 +381,7 @@ public class NewTabPageLayout extends LinearLayout { boolean isScrollableMvtEnabled, boolean searchProviderIsGoogle) { assert mMvTilesContainerLayout != null; @@ -31,7 +31,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageL if (searchProviderIsGoogle && QueryTileUtils.isQueryTilesEnabledOnNTP()) { maxRows = QueryTileSection.getMaxRowsForMostVisitedTiles(getContext()); } -@@ -540,7 +540,7 @@ public class NewTabPageLayout extends LinearLayout { +@@ -567,7 +567,7 @@ public class NewTabPageLayout extends LinearLayout { && mInitialized) { return; } diff --git a/build/patches/Use-64-bit-WebView-processes.patch b/build/patches/Use-64-bit-WebView-processes.patch index e66a0802..52911330 100644 --- a/build/patches/Use-64-bit-WebView-processes.patch +++ b/build/patches/Use-64-bit-WebView-processes.patch @@ -28,7 +28,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/android_webview/nonembedded/java/AndroidManifest.xml b/android_webview/nonembedded/java/AndroidManifest.xml --- a/android_webview/nonembedded/java/AndroidManifest.xml +++ b/android_webview/nonembedded/java/AndroidManifest.xml -@@ -41,9 +41,6 @@ by a child template that "extends" this file. +@@ -38,9 +38,6 @@ by a child template that "extends" this file. android:icon="@{{manifest_package|default('com.android.webview')}}:drawable/icon_webview" android:name="{{ application_name|default('org.chromium.android_webview.nonembedded.WebViewApkApplication') }}" android:multiArch="true" diff --git a/build/patches/User-agent-customization.patch b/build/patches/User-agent-customization.patch index cf6c78cf..b6a11b97 100644 --- a/build/patches/User-agent-customization.patch +++ b/build/patches/User-agent-customization.patch @@ -25,13 +25,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../browser/android/content/content_utils.cc | 28 +++ .../preferences/browser_prefs_android.cc | 7 + .../privacy_preferences_manager_impl.cc | 124 ++++++++++++ - .../preferences/ChromePreferenceKeys.java | 5 + + .../preferences/ChromePreferenceKeys.java | 7 +- .../settings/PrivacyPreferencesManager.java | 8 + .../org/chromium/chrome/browser/tab/Tab.java | 2 + .../browser/tabmodel/TabWindowManager.java | 2 + .../tabmodel/TabWindowManagerImpl.java | 18 ++ .../strings/android_chrome_strings.grd | 35 ++++ - chrome/common/pref_names.cc | 13 ++ chrome/common/pref_names.h | 8 + .../widget/RadioButtonWithEditText.java | 11 + .../embedder_support/user_agent_utils.cc | 8 +- @@ -41,7 +40,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../browser/web_contents/web_contents_impl.cc | 4 + .../framehost/NavigationControllerImpl.java | 3 +- content/renderer/render_thread_impl.cc | 1 - - 31 files changed, 762 insertions(+), 16 deletions(-) + 30 files changed, 749 insertions(+), 18 deletions(-) create mode 100644 chrome/android/java/res/layout/custom_useragent_preferences.xml create mode 100644 chrome/android/java/res/xml/useragent_preferences.xml create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/settings/UserAgentPreferences.java @@ -49,7 +48,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/base/base_switches.cc b/base/base_switches.cc --- a/base/base_switches.cc +++ b/base/base_switches.cc -@@ -174,6 +174,8 @@ const char kForceFieldTrialParams[] = "force-fieldtrial-params"; +@@ -169,6 +169,8 @@ const char kForceFieldTrialParams[] = "force-fieldtrial-params"; extern const char kEnableCrashpad[] = "enable-crashpad"; #endif @@ -61,7 +60,7 @@ diff --git a/base/base_switches.cc b/base/base_switches.cc diff --git a/base/base_switches.h b/base/base_switches.h --- a/base/base_switches.h +++ b/base/base_switches.h -@@ -67,6 +67,8 @@ extern const char kEnableCrashpad[]; +@@ -66,6 +66,8 @@ extern const char kEnableCrashpad[]; extern const char kSchedulerBoostUrgent[]; #endif @@ -73,7 +72,7 @@ diff --git a/base/base_switches.h b/base/base_switches.h diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -671,4 +671,6 @@ chrome_java_resources = [ +@@ -675,4 +675,6 @@ chrome_java_resources = [ "java/res/xml/privacy_preferences_v2.xml", "java/res/xml/search_widget_info.xml", "java/res/xml/tracing_preferences.xml", @@ -83,7 +82,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -928,6 +928,7 @@ chrome_java_sources = [ +@@ -937,6 +937,7 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/payments/ui/DimmingDialog.java", "java/src/org/chromium/chrome/browser/payments/ui/LineItem.java", "java/src/org/chromium/chrome/browser/payments/ui/PaymentAppComparator.java", @@ -205,9 +204,9 @@ new file mode 100644 diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml -@@ -106,6 +106,11 @@ found in the LICENSE file. +@@ -110,6 +110,11 @@ android:key="content_settings" - android:order="18" + android:order="19" android:title="@string/prefs_site_settings"/> + @@ -1046,51 +1047,28 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro General -diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc ---- a/chrome/common/pref_names.cc -+++ b/chrome/common/pref_names.cc -@@ -376,6 +376,19 @@ const char kAllowJavascriptAppleEvents[] = - - #endif - -+#if BUILDFLAG(IS_ANDROID) -+const char kOverrideUserAgentEnabled[] = -+ "override_user_agent_enabled"; -+const char kOverrideUserAgent[] = -+ "override_user_agent"; -+const char kOverrideUserAgentDesktopModeEnabled[] = -+ "override_user_agent_dm_enabled"; -+const char kOverrideUserAgentDesktopMode[] = -+ "override_user_agent_dm"; -+const char kDesktopModeViewportMetaEnabled[] = -+ "dm-viewport-meta-enabled"; -+#endif -+ - // Boolean which specifies whether we should ask the user if we should download - // a file (true) or just download it automatically. - const char kPromptForDownload[] = "download.prompt_for_download"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h -@@ -1246,6 +1246,14 @@ extern const char kDesktopSharingHubEnabled[]; - extern const char kLastWhatsNewVersion[]; - extern const char kHasShownRefreshWhatsNew[]; - #endif +@@ -1825,6 +1825,14 @@ inline constexpr char kNaviOnboardGroup[] = "browser.navi_onboard_group"; + inline constexpr char kHadThreeConsecutiveNotificationPermissionDenies[] = + "profile.content_settings.had_three_consecutive_denies.notifications"; + +#if BUILDFLAG(IS_ANDROID) -+extern const char kOverrideUserAgentEnabled[]; -+extern const char kOverrideUserAgent[]; -+extern const char kOverrideUserAgentDesktopModeEnabled[]; -+extern const char kOverrideUserAgentDesktopMode[]; -+extern const char kDesktopModeViewportMetaEnabled[]; ++inline constexpr char kOverrideUserAgentEnabled[] = "override_user_agent_enabled"; ++inline constexpr char kOverrideUserAgent[] = "override_user_agent"; ++inline constexpr char kOverrideUserAgentDesktopModeEnabled[] = "override_user_agent_dm_enabled"; ++inline constexpr char kOverrideUserAgentDesktopMode[] = "override_user_agent_dm"; ++inline constexpr char kDesktopModeViewportMetaEnabled[] = "dm-viewport-meta-enabled"; +#endif + - - #if !BUILDFLAG(IS_ANDROID) - extern const char kLensRegionSearchEnabled[]; + // Boolean indicating whether to show a promo for the quiet notification + // permission UI. + inline constexpr char kQuietNotificationPermissionShouldShowPromo[] = diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithEditText.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithEditText.java --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithEditText.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithEditText.java -@@ -161,6 +161,17 @@ public class RadioButtonWithEditText extends RadioButtonWithDescription { +@@ -159,6 +159,17 @@ public class RadioButtonWithEditText extends RadioButtonWithDescription { mEditText.setCursorVisible(false); KeyboardVisibilityDelegate.getInstance().hideKeyboard(mEditText); } @@ -1111,18 +1089,18 @@ diff --git a/components/browser_ui/widget/android/java/src/org/chromium/componen diff --git a/components/embedder_support/user_agent_utils.cc b/components/embedder_support/user_agent_utils.cc --- a/components/embedder_support/user_agent_utils.cc +++ b/components/embedder_support/user_agent_utils.cc -@@ -563,6 +563,10 @@ blink::UserAgentMetadata GetUserAgentMetadata(const PrefService* pref_service) { - policy::policy_prefs::kUserAgentClientHintsGREASEUpdateEnabled); - ua_options.force_major_to_minor = GetMajorToMinorFromPrefs(pref_service); - } +@@ -551,6 +551,10 @@ blink::UserAgentMetadata GetUserAgentMetadata() { + + blink::UserAgentMetadata GetUserAgentMetadata(const PrefService* pref_service) { + blink::UserAgentMetadata metadata; + if (base::CommandLine::ForCurrentProcess()->HasSwitch(kUserAgent)) { + //NOTE: metadata is not updated with custom UA information + return metadata; + } - metadata.brand_version_list = GetBrandMajorVersionList( - enable_updated_grease_by_policy, ua_options.force_major_to_minor); - metadata.brand_full_version_list = GetBrandFullVersionList( -@@ -600,7 +604,9 @@ void SetDesktopUserAgentOverride(content::WebContents* web_contents, + + bool enable_updated_grease_by_policy = true; + UserAgentOptions ua_options; +@@ -618,7 +622,9 @@ void SetDesktopUserAgentOverride(content::WebContents* web_contents, blink::UserAgentOverride spoofed_ua; spoofed_ua.ua_string_override = content::BuildUserAgentFromOSAndProduct( @@ -1168,14 +1146,14 @@ diff --git a/content/browser/renderer_host/navigation_controller_android.h b/con diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc -@@ -3722,6 +3722,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( +@@ -3742,6 +3742,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kLacrosUseChromeosProtectedMedia, switches::kLacrosUseChromeosProtectedAv1, #endif + switches::kDesktopModeViewportMetaEnabled, }; - renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, - std::size(kSwitchNames)); + renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames); + diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -1187,7 +1165,7 @@ diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser #include "base/check_op.h" #include "base/command_line.h" #include "base/containers/contains.h" -@@ -2939,6 +2940,9 @@ const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences() { +@@ -2970,6 +2971,9 @@ const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences() { #else prefs.viewport_meta_enabled = false; #endif @@ -1220,7 +1198,7 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/frameh diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc -@@ -922,7 +922,6 @@ void RenderThreadImpl::InitializeRenderer( +@@ -919,7 +919,6 @@ void RenderThreadImpl::InitializeRenderer( const std::vector& cors_exempt_header_list, network::mojom::AttributionSupport attribution_support, blink::mojom::OriginTrialsSettingsPtr origin_trials_settings) { diff --git a/build/patches/Viewport-Protection-Site-Setting.patch b/build/patches/Viewport-Protection-Site-Setting.patch index dd97b00a..52c03c56 100644 --- a/build/patches/Viewport-Protection-Site-Setting.patch +++ b/build/patches/Viewport-Protection-Site-Setting.patch @@ -183,7 +183,7 @@ new file mode 100644 diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1302,7 +1302,7 @@ constexpr base::FeatureParam +@@ -1392,7 +1392,7 @@ constexpr base::FeatureParam BASE_FEATURE(kViewportProtection, "ViewportProtection", @@ -195,7 +195,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc -@@ -2298,6 +2298,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate, +@@ -2274,6 +2274,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate, // var w = window.open() // var not_emulated_screen_info = w.screen bool protection_enabled = base::FeatureList::IsEnabled(features::kViewportProtection); @@ -207,7 +207,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc -@@ -887,6 +887,9 @@ void Page::UpdateAcceleratedCompositingSettings() { +@@ -882,6 +882,9 @@ void Page::UpdateAcceleratedCompositingSettings() { void Page::CalculateEmulatedScreenSetting(LocalFrame* frame, bool force) { bool isEnabled = base::FeatureList::IsEnabled(features::kViewportProtection); diff --git a/build/patches/Viewport-Protection-flag.patch b/build/patches/Viewport-Protection-flag.patch index 84d804e9..150e58f1 100644 --- a/build/patches/Viewport-Protection-flag.patch +++ b/build/patches/Viewport-Protection-flag.patch @@ -28,13 +28,12 @@ The feature is controlled by a feature flag (default enabled) .../blink/renderer/core/input/touch.cc | 17 ++++- third_party/blink/renderer/core/page/page.cc | 76 +++++++++++++++++++ third_party/blink/renderer/core/page/page.h | 7 ++ - .../platform/runtime_enabled_features.json5 | 4 +- - 22 files changed, 253 insertions(+), 21 deletions(-) + 21 files changed, 251 insertions(+), 19 deletions(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc -@@ -10105,6 +10105,11 @@ const FeatureEntry kFeatureEntries[] = { +@@ -10157,6 +10157,11 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(features::kDesktopPWAsAppHomePage)}, #endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) @@ -49,9 +48,9 @@ diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc -@@ -7355,6 +7355,12 @@ const char kPaintPreviewDemoDescription[] = - "previews."; - #endif // ENABLE_PAINT_PREVIEW && BUILDFLAG(IS_ANDROID) +@@ -7539,6 +7539,12 @@ const char kWebXrInternalsDescription[] = + "debug issues with the WebXR Device API."; + #endif // #if defined(ENABLE_VR) +const char kViewportProtectionName[] = "Viewport Protection"; +const char kViewportProtectionDescription[] = @@ -65,22 +64,22 @@ diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descripti diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h -@@ -4252,6 +4252,9 @@ extern const char kPaintPreviewDemoName[]; +@@ -4355,6 +4355,9 @@ extern const char kPaintPreviewDemoName[]; extern const char kPaintPreviewDemoDescription[]; #endif // ENABLE_PAINT_PREVIEW && BUILDFLAG(IS_ANDROID) +extern const char kViewportProtectionName[]; +extern const char kViewportProtectionDescription[]; + - #if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) - extern const char kWebUITabStripFlagId[]; - extern const char kWebUITabStripName[]; + #if BUILDFLAG(ENABLE_VR) + extern const char kWebXrInternalsName[]; + extern const char kWebXrInternalsDescription[]; diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc -@@ -1300,6 +1300,10 @@ constexpr base::FeatureParam - "fledge_extensions_enabled", - /*default_value=*/true}; +@@ -1390,6 +1390,10 @@ constexpr base::FeatureParam + &kPrivateAggregationApi, "fledge_extensions_enabled", + /*default_value=*/true}; +BASE_FEATURE(kViewportProtection, + "ViewportProtection", @@ -92,7 +91,7 @@ diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/fea diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h -@@ -1202,6 +1202,9 @@ BLINK_COMMON_EXPORT bool IsFencedFramesEnabled(); +@@ -1283,6 +1283,9 @@ BLINK_COMMON_EXPORT bool IsFencedFramesEnabled(); BLINK_COMMON_EXPORT bool IsMaxUnthrottledTimeoutNestingLevelEnabled(); @@ -140,7 +139,7 @@ diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/b diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc -@@ -1712,7 +1712,12 @@ ComputedStyleBuilder StyleResolver::InitialStyleBuilderForElement() const { +@@ -1710,7 +1710,12 @@ ComputedStyleBuilder StyleResolver::InitialStyleBuilderForElement() const { ComputedStyleBuilder builder = CreateComputedStyleBuilder(); builder.SetRtlOrdering(GetDocument().VisuallyOrdered() ? EOrder::kVisual : EOrder::kLogical); @@ -226,7 +225,7 @@ diff --git a/third_party/blink/renderer/core/events/pointer_event.h b/third_part diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc -@@ -1040,7 +1040,7 @@ WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) { +@@ -1052,7 +1052,7 @@ WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) { page_popup_ = WebPagePopupImpl::Create( std::move(popup_widget_host), std::move(widget_host), std::move(widget_receiver), this, agent_group_scheduler, @@ -238,7 +237,7 @@ diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_p diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc -@@ -1504,7 +1504,12 @@ int LocalDOMWindow::outerHeight() const { +@@ -1473,7 +1473,12 @@ int LocalDOMWindow::outerHeight() const { if (frame->IsInFencedFrameTree()) { return innerHeight(); } @@ -252,7 +251,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p Page* page = frame->GetPage(); if (!page) return 0; -@@ -1529,7 +1534,12 @@ int LocalDOMWindow::outerWidth() const { +@@ -1498,7 +1503,12 @@ int LocalDOMWindow::outerWidth() const { if (frame->IsInFencedFrameTree()) { return innerWidth(); } @@ -266,7 +265,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p Page* page = frame->GetPage(); if (!page) return 0; -@@ -1722,7 +1732,8 @@ double LocalDOMWindow::devicePixelRatio() const { +@@ -1691,7 +1701,8 @@ double LocalDOMWindow::devicePixelRatio() const { if (!GetFrame()) return 0.0; @@ -276,7 +275,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p } void LocalDOMWindow::scrollBy(double x, double y) const { -@@ -2277,6 +2288,21 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate, +@@ -2253,6 +2264,21 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate, if (!completed_url.IsEmpty() || result.new_window) result.frame->Navigate(frame_request, WebFrameLoadType::kStandard); @@ -298,7 +297,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p // TODO(japhet): window-open-noopener.html?_top and several tests in // html/browsers/windows/browsing-context-names/ appear to require that // the special case target names (_top, _parent, _self) ignore opener -@@ -2333,6 +2359,15 @@ DOMWindow* LocalDOMWindow::openPictureInPictureWindow( +@@ -2309,6 +2335,15 @@ DOMWindow* LocalDOMWindow::openPictureInPictureWindow( DCHECK(result.new_window); result.frame->Navigate(frame_request, WebFrameLoadType::kStandard); @@ -317,8 +316,8 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc -@@ -1423,6 +1423,10 @@ gfx::SizeF LocalFrame::ResizePageRectsKeepingRatio( - return gfx::SizeF(inline_size, block_size); +@@ -1402,6 +1402,10 @@ void LocalFrame::RestoreScrollOffsets() { + saved_scroll_offsets_ = nullptr; } +void LocalFrame::SetPageZoomFactorBaseValue(float factor) { @@ -328,7 +327,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/ void LocalFrame::SetPageZoomFactor(float factor) { SetPageAndTextZoomFactors(factor, text_zoom_factor_); } -@@ -1562,12 +1566,16 @@ device::mojom::blink::DevicePostureType LocalFrame::GetDevicePosture() { +@@ -1542,12 +1546,16 @@ device::mojom::blink::DevicePostureType LocalFrame::GetDevicePosture() { return mojo_handler_->GetDevicePosture(); } @@ -350,7 +349,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/ diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h -@@ -412,13 +412,14 @@ class CORE_EXPORT LocalFrame final +@@ -404,13 +404,14 @@ class CORE_EXPORT LocalFrame final void SetInViewSourceMode(bool = true); void SetPageZoomFactor(float); @@ -367,7 +366,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/b // Informs the local root's document and its local descendant subtree that a // media query value changed. -@@ -1036,6 +1037,7 @@ class CORE_EXPORT LocalFrame final +@@ -1029,6 +1030,7 @@ class CORE_EXPORT LocalFrame final unsigned hidden_ : 1; float page_zoom_factor_; @@ -473,7 +472,7 @@ diff --git a/third_party/blink/renderer/core/frame/screen_metrics_emulator.h b/t diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc -@@ -1714,6 +1714,14 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing( +@@ -1737,6 +1737,14 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing( if (auto* device_emulator = DeviceEmulator()) { device_emulator->UpdateVisualProperties(visual_properties); @@ -563,7 +562,7 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re namespace blink { -@@ -881,7 +885,79 @@ void Page::UpdateAcceleratedCompositingSettings() { +@@ -876,7 +880,79 @@ void Page::UpdateAcceleratedCompositingSettings() { } } @@ -646,7 +645,7 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h -@@ -436,6 +436,9 @@ class CORE_EXPORT Page final : public GarbageCollected, +@@ -439,6 +439,9 @@ class CORE_EXPORT Page final : public GarbageCollected, // place. void UpdateBrowsingContextGroup(const blink::BrowsingContextGroupInfo&); @@ -656,7 +655,7 @@ diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/ren private: friend class ScopedPagePauser; -@@ -579,6 +582,10 @@ class CORE_EXPORT Page final : public GarbageCollected, +@@ -582,6 +585,10 @@ class CORE_EXPORT Page final : public GarbageCollected, // browser side FrameTree has the FrameTree::Type of kFencedFrame. bool is_fenced_frame_tree_ = false; @@ -667,19 +666,5 @@ diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/ren // This tracks the mode that the fenced frame is set to. blink::FencedFrame::DeprecatedFencedFrameMode fenced_frame_mode_ = blink::FencedFrame::DeprecatedFencedFrameMode::kDefault; -diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 ---- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 -+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -1901,8 +1901,8 @@ - // as a speculative site compatibility measure, because web authors may - // assume that screen dimensions match window.innerWidth/innerHeight while - // a page is fullscreen, but that is not always true. crbug.com/1367416 -- name: "FullscreenScreenSizeMatchesDisplay", -- status: "stable", -+ name: "FullscreenScreenSizeMatchesDisplay", // always enabled -+ status: "stable", // in bromite - }, - { - name: "GamepadButtonAxisEvents", -- 2.25.1 diff --git a/build/patches/Welcome-screen.patch b/build/patches/Welcome-screen.patch index fe2ee8ac..a0cd04d7 100644 --- a/build/patches/Welcome-screen.patch +++ b/build/patches/Welcome-screen.patch @@ -27,7 +27,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni -@@ -529,6 +529,7 @@ chrome_java_resources = [ +@@ -532,6 +532,7 @@ chrome_java_resources = [ "java/res/layout/find_in_page.xml", "java/res/layout/find_toolbar.xml", "java/res/layout/fre_tos_privacy_disclaimer.xml", @@ -38,7 +38,7 @@ diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_ja diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni -@@ -626,6 +626,8 @@ chrome_java_sources = [ +@@ -637,6 +637,8 @@ chrome_java_sources = [ "java/src/org/chromium/chrome/browser/firstrun/SyncConsentFirstRunFragment.java", "java/src/org/chromium/chrome/browser/firstrun/TabbedModeFirstRunActivity.java", "java/src/org/chromium/chrome/browser/firstrun/TosDialogBehaviorSharedPrefInvalidator.java", @@ -285,7 +285,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ChildA - appRestrictionInfo.getHasAppRestriction(this::onAppRestrictionDetected); - - accountManagerFacade.getAccounts().then(accounts -> { -- AccountUtils.checkChildAccountStatus(accountManagerFacade, accounts, +- AccountUtils.checkChildAccountStatusLegacy(accountManagerFacade, accounts, - (isChild, account) -> onChildAccountStatusReady(isChild)); - }); } @@ -294,9 +294,9 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ChildA diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java -@@ -30,9 +30,7 @@ import org.chromium.chrome.browser.fonts.FontPreloader; +@@ -29,9 +29,7 @@ import org.chromium.chrome.browser.feature_engagement.TrackerFactory; + import org.chromium.chrome.browser.fonts.FontPreloader; import org.chromium.chrome.browser.metrics.UmaUtils; - import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; -import org.chromium.chrome.browser.signin.SigninCheckerProvider; -import org.chromium.chrome.browser.signin.SigninFirstRunFragment; @@ -305,7 +305,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.metrics.LowEntropySource; -@@ -122,7 +120,7 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa +@@ -121,7 +119,7 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa /** Creates first page and sets up adapter. Should result UI being shown on the screen. */ private void createFirstPage() { BooleanSupplier showWelcomePage = () -> !FirstRunStatus.shouldSkipWelcomePage(); @@ -314,7 +314,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR mFreProgressStates.add(MobileFreProgress.WELCOME_SHOWN); mPagerAdapter = new FirstRunPagerAdapter(FirstRunActivity.this, mPages); mPager.setAdapter(mPagerAdapter); -@@ -144,13 +142,11 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa +@@ -143,13 +141,11 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa // // TODO(b/245912657): explicitly sign in supervised users in {@link // SigninFirstRunMediator#handleContinueWithNative} rather than relying on SigninChecker. @@ -328,7 +328,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR // An optional page to select a default search engine. if (showSearchEnginePromo.getAsBoolean()) { -@@ -159,11 +155,6 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa +@@ -158,11 +154,6 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa mFreProgressStates.add(MobileFreProgress.DEFAULT_SEARCH_ENGINE_SHOWN); } @@ -340,7 +340,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR if (mPagerAdapter != null) { mPagerAdapter.notifyDataSetChanged(); } -@@ -208,10 +199,6 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa +@@ -207,10 +198,6 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa @Override public void triggerLayoutInflation() { @@ -365,7 +365,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java -@@ -32,8 +32,6 @@ import org.chromium.chrome.browser.policy.PolicyServiceFactory; +@@ -33,8 +33,6 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManagerUtils; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.policy.PolicyService; @@ -374,7 +374,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR /** Base class for First Run Experience. */ public abstract class FirstRunActivityBase -@@ -101,9 +99,7 @@ public abstract class FirstRunActivityBase +@@ -104,9 +102,7 @@ public abstract class FirstRunActivityBase @Override @CallSuper public void triggerLayoutInflation() { @@ -388,7 +388,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java -@@ -26,14 +26,9 @@ import org.chromium.chrome.browser.locale.LocaleManager; +@@ -27,14 +27,9 @@ import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.SearchEnginePromoType; @@ -403,7 +403,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR import java.util.List; -@@ -58,38 +53,19 @@ public abstract class FirstRunFlowSequencer { +@@ -65,38 +60,19 @@ public abstract class FirstRunFlowSequencer { /** Returns true if the sync consent promo page should be shown. */ boolean shouldShowSyncConsentPage( Activity activity, List accounts, boolean isChild) { @@ -411,9 +411,9 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR - // Always show the sync consent page for child account. - return true; - } +- assert mProfileSupplier.get() != null; - final IdentityManager identityManager = -- IdentityServicesProvider.get().getIdentityManager( -- Profile.getLastUsedRegularProfile()); +- IdentityServicesProvider.get().getIdentityManager(mProfileSupplier.get()); - if (identityManager.hasPrimaryAccount(ConsentLevel.SYNC) || !isSyncAllowed()) { - // No need to show the sync consent page if users already consented to sync or - // if sync is not allowed. @@ -436,15 +436,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR /** @return true if Sync is allowed for the current user. */ @VisibleForTesting protected boolean isSyncAllowed() { -- SigninManager signinManager = IdentityServicesProvider.get().getSigninManager( -- Profile.getLastUsedRegularProfile()); +- SigninManager signinManager = +- IdentityServicesProvider.get().getSigninManager(mProfileSupplier.get()); - return FirstRunUtils.canAllowSync() && !signinManager.isSigninDisabledByPolicy() - && signinManager.isSigninSupported(/*requireUpdatedPlayServices=*/false); + return false; } } -@@ -133,12 +109,8 @@ public abstract class FirstRunFlowSequencer { +@@ -147,12 +123,8 @@ public abstract class FirstRunFlowSequencer { * method. */ void start() { @@ -459,7 +459,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR } @VisibleForTesting -@@ -163,14 +135,10 @@ public abstract class FirstRunFlowSequencer { +@@ -177,14 +149,10 @@ public abstract class FirstRunFlowSequencer { } private void maybeProcessFreEnvironmentPreNative() { @@ -474,7 +474,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR onFlowIsKnown(freProperties); } -@@ -181,8 +149,8 @@ public abstract class FirstRunFlowSequencer { +@@ -195,8 +163,8 @@ public abstract class FirstRunFlowSequencer { * @param freProperties Resulting FRE properties bundle. */ public void updateFirstRunProperties(Bundle freProperties) { @@ -485,7 +485,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR freProperties.putBoolean( FirstRunActivity.SHOW_SEARCH_ENGINE_PAGE, shouldShowSearchEnginePage()); } -@@ -283,13 +251,17 @@ public abstract class FirstRunFlowSequencer { +@@ -297,13 +265,17 @@ public abstract class FirstRunFlowSequencer { if (!(caller instanceof Activity)) { freIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } @@ -508,7 +508,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java -@@ -18,9 +18,6 @@ import org.chromium.chrome.browser.metrics.UmaSessionStats; +@@ -19,9 +19,6 @@ import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; @@ -518,7 +518,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR /** Provides first run related utility functions. */ public class FirstRunUtils { -@@ -83,16 +80,12 @@ public class FirstRunUtils { +@@ -84,16 +81,12 @@ public class FirstRunUtils { * @return Whether or not sync is allowed on this device. */ static boolean canAllowSync() { @@ -537,7 +537,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstR } @VisibleForTesting -@@ -102,10 +95,7 @@ public class FirstRunUtils { +@@ -103,10 +96,7 @@ public class FirstRunUtils { @VisibleForTesting static boolean hasGoogleAccounts() { @@ -1234,7 +1234,7 @@ new file mode 100644 diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -3157,7 +3157,29 @@ To change this setting, <resetlink>reset sync

<resetlink>reset sync

%1$sGoogle Maps will open in Chrome. By continuing, you agree to the <LINK1>Google Terms of Service</LINK1>, and the <LINK2>Google Chrome and ChromeOS Additional Terms of Service</LINK2>. The <LINK3>Privacy Policy</LINK3> also applies. diff --git a/build/patches/autofill-miscellaneous.patch b/build/patches/autofill-miscellaneous.patch index 3cdab6c4..e112d57e 100644 --- a/build/patches/autofill-miscellaneous.patch +++ b/build/patches/autofill-miscellaneous.patch @@ -12,18 +12,18 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- chrome/browser/prefs/browser_prefs.cc | 6 +-- .../ui/autofill/chrome_autofill_client.cc | 7 +-- - .../core/browser/autofill_download_manager.cc | 49 +++---------------- + .../core/browser/autofill_download_manager.cc | 43 +++---------------- .../core/browser/autofill_download_manager.h | 2 - .../core/browser/browser_autofill_manager.h | 4 +- .../autofill/core/common/autofill_features.cc | 4 +- - .../autofill/core/common/autofill_prefs.cc | 8 +-- + .../autofill/core/common/autofill_prefs.cc | 8 ++-- .../password_generation_frame_helper.cc | 4 -- - 8 files changed, 19 insertions(+), 65 deletions(-) + 8 files changed, 19 insertions(+), 59 deletions(-) diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc -@@ -1138,11 +1138,11 @@ void RegisterProfilePrefsForMigration( +@@ -1198,11 +1198,11 @@ void RegisterProfilePrefsForMigration( PrefRegistry::LOSSY_PREF); // Deprecated 11/2022. @@ -41,7 +41,7 @@ diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browse diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc -@@ -182,12 +182,7 @@ ChromeAutofillClient::GetURLLoaderFactory() { +@@ -188,12 +188,7 @@ ChromeAutofillClient::GetURLLoaderFactory() { } AutofillDownloadManager* ChromeAutofillClient::GetDownloadManager() { @@ -58,8 +58,8 @@ diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/brows diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc -@@ -472,35 +472,6 @@ bool GetUploadPayloadForApi(const AutofillUploadContents& upload, - return upload_request.SerializeToString(payload); +@@ -451,29 +451,6 @@ absl::optional GetUploadPayloadForApi( + return std::move(payload); } -// Gets an API method URL given its type (query or upload), an optional @@ -71,30 +71,24 @@ diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/com -std::string GetAPIMethodUrl(AutofillDownloadManager::RequestType type, - base::StringPiece resource_id, - base::StringPiece method) { -- const char* api_method_url; -- if (type == AutofillDownloadManager::REQUEST_QUERY) { -- if (method == "POST") { -- api_method_url = "/v1/pages:get"; -- } else { -- api_method_url = "/v1/pages"; +- const char* api_method_url = [&] { +- switch (type) { +- case AutofillDownloadManager::REQUEST_QUERY: +- return method == "POST" ? "/v1/pages:get" : "/v1/pages"; +- case AutofillDownloadManager::REQUEST_UPLOAD: +- return "/v1/forms:vote"; - } -- } else if (type == AutofillDownloadManager::REQUEST_UPLOAD) { -- api_method_url = "/v1/forms:vote"; -- } else { -- // This should not be reached, but we never know. -- NOTREACHED() << "Request of type " << type << " is invalid"; -- return ""; -- } +- NOTREACHED_NORETURN(); +- }(); - if (resource_id.empty()) { - return std::string(api_method_url); - } - return base::StrCat({api_method_url, "/", resource_id}); -} -- + // Gets HTTP body payload for API POST request. - bool GetAPIBodyPayload(const std::string& payload, - AutofillDownloadManager::RequestType type, -@@ -539,18 +510,7 @@ bool IsRawMetadataUploadingEnabled(version_info::Channel channel) { + absl::optional GetAPIBodyPayload( +@@ -514,18 +491,7 @@ bool IsRawMetadataUploadingEnabled(version_info::Channel channel) { } std::string GetAPIKeyForUrl(version_info::Channel channel) { @@ -114,7 +108,7 @@ diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/com } } // namespace -@@ -766,6 +726,7 @@ std::tuple AutofillDownloadManager::GetRequestURLAndMethod( +@@ -737,6 +703,7 @@ std::tuple AutofillDownloadManager::GetRequestURLAndMethod( // ID of the resource to add to the API request URL. Nothing will be added if // |resource_id| is empty. std::string resource_id; @@ -122,7 +116,7 @@ diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/com std::string method = "POST"; if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) { -@@ -786,11 +747,15 @@ std::tuple AutofillDownloadManager::GetRequestURLAndMethod( +@@ -757,11 +724,15 @@ std::tuple AutofillDownloadManager::GetRequestURLAndMethod( // Add the query parameter to set the response format to a serialized proto. url = net::AppendQueryParameter(url, "alt", "proto"); @@ -154,8 +148,8 @@ diff --git a/components/autofill/core/browser/autofill_download_manager.h b/comp diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h --- a/components/autofill/core/browser/browser_autofill_manager.h +++ b/components/autofill/core/browser/browser_autofill_manager.h -@@ -784,9 +784,9 @@ class BrowserAutofillManager : public AutofillManager, - credit_card_form_event_logger_; +@@ -768,9 +768,9 @@ class BrowserAutofillManager : public AutofillManager, + autocomplete_unrecognized_fallback_logger_; // Have we logged whether Autofill is enabled for this page load? - bool has_logged_autofill_enabled_ = false; @@ -169,7 +163,7 @@ diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/compo diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc -@@ -718,8 +718,8 @@ BASE_FEATURE(kAutofillLogToTerminal, +@@ -753,8 +753,8 @@ BASE_FEATURE(kAutofillLogToTerminal, // "upload" resources. // i.e., https://other.autofill.server:port/tbproxy/af/ BASE_FEATURE(kAutofillServerCommunication, @@ -183,7 +177,7 @@ diff --git a/components/autofill/core/common/autofill_features.cc b/components/a diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc --- a/components/autofill/core/common/autofill_prefs.cc +++ b/components/autofill/core/common/autofill_prefs.cc -@@ -129,7 +129,7 @@ const char kAutofillPaymentMethodsMandatoryReauthPromoShownCounter[] = +@@ -136,7 +136,7 @@ const char kAutofillUsingVirtualViewStructure[] = void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { // Synced prefs. Used for cross-device choices, e.g., credit card Autofill. registry->RegisterBooleanPref( @@ -192,7 +186,7 @@ diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/auto user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterIntegerPref( prefs::kAutofillLastVersionDeduped, 0, -@@ -141,10 +141,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { +@@ -148,10 +148,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { prefs::kAutofillLastVersionDisusedAddressesDeleted, 0, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( @@ -204,8 +198,8 @@ diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/auto + prefs::kAutofillIBANEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kAutofillPaymentCvcStorageAndFilling, true, -@@ -176,7 +176,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { + prefs::kAutofillPaymentCvcStorage, true, +@@ -182,7 +182,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { // Deprecated prefs registered for migration. registry->RegisterBooleanPref( @@ -213,11 +207,11 @@ diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/auto + prefs::kAutofillEnabledDeprecated, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref(prefs::kAutofillOrphanRowsRemoved, false); - } + diff --git a/components/password_manager/core/browser/password_generation_frame_helper.cc b/components/password_manager/core/browser/password_generation_frame_helper.cc --- a/components/password_manager/core/browser/password_generation_frame_helper.cc +++ b/components/password_manager/core/browser/password_generation_frame_helper.cc -@@ -85,7 +85,6 @@ void PasswordGenerationFrameHelper::ProcessPasswordRequirements( +@@ -101,7 +101,6 @@ void PasswordGenerationFrameHelper::ProcessPasswordRequirements( // In order for password generation to be enabled, we need to make sure: // (1) Password sync is enabled, and // (2) Password saving is enabled @@ -225,7 +219,7 @@ diff --git a/components/password_manager/core/browser/password_generation_frame_ bool PasswordGenerationFrameHelper::IsGenerationEnabled( bool log_debug_data) const { std::unique_ptr logger; -@@ -95,9 +94,6 @@ bool PasswordGenerationFrameHelper::IsGenerationEnabled( +@@ -111,9 +110,6 @@ bool PasswordGenerationFrameHelper::IsGenerationEnabled( } GURL url = driver_->GetLastCommittedURL(); diff --git a/build/patches/bromite-build-utils.patch b/build/patches/bromite-build-utils.patch index de9ba8c3..ca35c875 100644 --- a/build/patches/bromite-build-utils.patch +++ b/build/patches/bromite-build-utils.patch @@ -121,7 +121,7 @@ diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enu diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py -@@ -491,4 +491,27 @@ def ReadSourcesList(sources_list_file_name): +@@ -498,4 +498,27 @@ def ReadSourcesList(sources_list_file_name): Note that this function should not be used to parse response files. """ with open(sources_list_file_name) as f: @@ -394,7 +394,7 @@ new file mode 100644 diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn -@@ -648,6 +648,7 @@ set_defaults("component") { +@@ -652,6 +652,7 @@ set_defaults("component") { configs = default_component_configs } @@ -405,7 +405,7 @@ diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni -@@ -433,7 +433,7 @@ if (enable_java_templates && is_android) { +@@ -429,7 +429,7 @@ if (enable_java_templates && is_android) { # } template("java_cpp_enum") { action_with_pydeps(target_name) { @@ -414,7 +414,7 @@ diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni # The sources aren't compiled so don't check their dependencies. check_includes = false -@@ -444,6 +444,10 @@ if (enable_java_templates && is_android) { +@@ -440,6 +440,10 @@ if (enable_java_templates && is_android) { _rebased_sources = rebase_path(invoker.sources, root_build_dir) args = [ "--srcjar=$_rebased_srcjar_path" ] + _rebased_sources diff --git a/build/patches/build-remove-calling-untrusted-hooks.patch b/build/patches/build-remove-calling-untrusted-hooks.patch index 193252f7..43330299 100644 --- a/build/patches/build-remove-calling-untrusted-hooks.patch +++ b/build/patches/build-remove-calling-untrusted-hooks.patch @@ -7,13 +7,13 @@ sysroot. License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - DEPS | 122 +---------------------------------------------------------- - 1 file changed, 2 insertions(+), 120 deletions(-) + DEPS | 127 +---------------------------------------------------------- + 1 file changed, 2 insertions(+), 125 deletions(-) diff --git a/DEPS b/DEPS --- a/DEPS +++ b/DEPS -@@ -118,7 +118,7 @@ vars = { +@@ -119,7 +119,7 @@ vars = { # Check out and download nacl by default, unless on an arm mac. # This can be disabled e.g. with custom_vars. @@ -22,7 +22,7 @@ diff --git a/DEPS b/DEPS # By default, do not check out src-internal. This can be overridden e.g. with # custom_vars. -@@ -175,7 +175,7 @@ vars = { +@@ -176,7 +176,7 @@ vars = { # platforms, but support for other platforms may be added in the future. 'checkout_openxr' : 'checkout_win or checkout_android', @@ -31,7 +31,7 @@ diff --git a/DEPS b/DEPS # By default bot checkouts the WPR archive files only when this # flag is set True. -@@ -4550,49 +4550,6 @@ hooks = [ +@@ -4595,54 +4595,6 @@ hooks = [ 'sync', '--extract', ], }, @@ -40,6 +40,7 @@ diff --git a/DEPS b/DEPS - 'pattern': '.', - 'condition': 'checkout_linux and checkout_arm', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=arm'], - }, - { @@ -47,6 +48,7 @@ diff --git a/DEPS b/DEPS - 'pattern': '.', - 'condition': 'checkout_linux and checkout_arm64', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=arm64'], - }, - { @@ -54,6 +56,7 @@ diff --git a/DEPS b/DEPS - 'pattern': '.', - 'condition': 'checkout_linux and (checkout_x86 or checkout_x64)', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=x86'], - }, - { @@ -61,6 +64,7 @@ diff --git a/DEPS b/DEPS - 'pattern': '.', - 'condition': 'checkout_linux and checkout_mips', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=mips'], - }, - { @@ -68,20 +72,21 @@ diff --git a/DEPS b/DEPS - 'pattern': '.', - 'condition': 'checkout_linux and checkout_mips64', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=mips64el'], - }, -- - { - 'name': 'sysroot_x64', - 'pattern': '.', - 'condition': 'checkout_linux and checkout_x64', - 'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py', +- '--sysroots-json-path=' + Var('sysroots_json_path'), - '--arch=x64'], - }, { # Case-insensitivity for the Win SDK. Must run before win_toolchain below. 'name': 'ciopfs_linux', -@@ -4743,57 +4700,6 @@ hooks = [ +@@ -4793,57 +4745,6 @@ hooks = [ ], }, @@ -139,7 +144,7 @@ diff --git a/DEPS b/DEPS # Pull rc binaries using checked-in hashes. { 'name': 'rc_win', -@@ -4819,30 +4725,6 @@ hooks = [ +@@ -4869,30 +4770,6 @@ hooks = [ '-s', 'src/build/toolchain/win/rc/mac/rc.sha1', ], }, diff --git a/build/patches/disable-WebView-variations-support.patch b/build/patches/disable-WebView-variations-support.patch index 2e2970b9..6257ddb5 100644 --- a/build/patches/disable-WebView-variations-support.patch +++ b/build/patches/disable-WebView-variations-support.patch @@ -28,7 +28,7 @@ diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewC diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java -@@ -485,10 +485,6 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider { +@@ -488,10 +488,6 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider { } } diff --git a/build/patches/enable-ftrivial-auto-var-init-zero.patch b/build/patches/enable-ftrivial-auto-var-init-zero.patch index b34d604a..fae6ec11 100644 --- a/build/patches/enable-ftrivial-auto-var-init-zero.patch +++ b/build/patches/enable-ftrivial-auto-var-init-zero.patch @@ -11,7 +11,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -382,6 +382,10 @@ config("compiler") { +@@ -381,6 +381,10 @@ config("compiler") { cflags += [ "-fwrapv" ] } diff --git a/build/patches/eyeo-117.0.5938.0-android_api.patch b/build/patches/eyeo-117.0.5938.0-android_api.patch new file mode 100644 index 00000000..4d5c20e6 --- /dev/null +++ b/build/patches/eyeo-117.0.5938.0-android_api.patch @@ -0,0 +1,6282 @@ +From: chromium-sdk +Date: Mon, 21 Aug 2023 18:20:44 +0200 +Subject: eyeo Browser Ad filtering Solution: Android API Module + +Based on Chromium 117.0.5938.0 + +Pre-requisites: eyeo Browser Ad filtering Solution: Base Module +--- + chrome/android/BUILD.gn | 9 + + chrome/browser/BUILD.gn | 14 + + chrome/browser/android/adblock/adblock_jni.cc | 194 +++++++ + chrome/browser/android/adblock/adblock_jni.h | 53 ++ + .../android/adblock/adblock_jni_factory.cc | 72 +++ + .../android/adblock/adblock_jni_factory.h | 50 ++ + .../filtering_configuration_bindings.cc | 250 ++++++++ + .../filtering_configuration_bindings.h | 69 +++ + ...iltering_configuration_bindings_factory.cc | 70 +++ + ...filtering_configuration_bindings_factory.h | 51 ++ + ...source_classification_notifier_bindings.cc | 191 ++++++ + ...esource_classification_notifier_bindings.h | 69 +++ + ...lassification_notifier_bindings_factory.cc | 71 +++ + ...classification_notifier_bindings_factory.h | 52 ++ + ...hrome_browser_main_extra_parts_profiles.cc | 10 + + components/adblock/android/BUILD.gn | 110 ++++ + .../adblock_settings_locales_titles.xml | 98 ++++ + .../adblock/AdblockContentType.java | 62 ++ + .../components/adblock/AdblockController.java | 258 +++++++++ + .../components/adblock/AdblockCounters.java | 101 ++++ + .../adblock/FilteringConfiguration.java | 245 ++++++++ + .../ResourceClassificationNotifier.java | 187 ++++++ + .../adblock/AdblockControllerTest.java | 87 +++ + .../adblock/FilteringConfigurationTest.java | 366 ++++++++++++ + .../ResourceClassificationNotifierTest.java | 143 +++++ + .../adblock/TestAdBlockedObserver.java | 183 ++++++ + .../adblock/TestPagesCircumventionTest.java | 90 +++ + .../components/adblock/TestPagesCspTest.java | 136 +++++ + .../adblock/TestPagesElemhideEmuInvTest.java | 158 +++++ + .../adblock/TestPagesElemhideEmuTest.java | 217 +++++++ + .../adblock/TestPagesElemhideTest.java | 237 ++++++++ + .../adblock/TestPagesExceptionTest.java | 244 ++++++++ + .../adblock/TestPagesFilterTest.java | 329 +++++++++++ + .../adblock/TestPagesHeaderFilterTest.java | 150 +++++ + .../adblock/TestPagesRewriteTest.java | 185 ++++++ + .../adblock/TestPagesSiteKeyTest.java | 82 +++ + .../adblock/TestPagesSnippetsTest.java | 545 ++++++++++++++++++ + .../adblock/TestPagesTestsHelper.java | 255 ++++++++ + .../adblock/TestPagesWebsocketTest.java | 77 +++ + .../adblock/TestVerificationUtils.java | 166 ++++++ + 40 files changed, 5936 insertions(+) + create mode 100644 chrome/browser/android/adblock/adblock_jni.cc + create mode 100644 chrome/browser/android/adblock/adblock_jni.h + create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.cc + create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.h + create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings.cc + create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings.h + create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc + create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.h + create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings.cc + create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings.h + create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc + create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h + create mode 100644 components/adblock/android/BUILD.gn + create mode 100644 components/adblock/android/java/res/values/adblock_settings_locales_titles.xml + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java + +diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn +--- a/chrome/android/BUILD.gn ++++ b/chrome/android/BUILD.gn +@@ -1,6 +1,10 @@ + # Copyright 2014 The Chromium Authors + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//build/android/resource_sizes.gni") + import("//build/config/android/config.gni") +@@ -205,6 +209,7 @@ if (current_toolchain == default_toolchain) { + "//chrome/browser/ui/android/toolbar:java_resources", + "//chrome/browser/ui/android/webid/internal:java_resources", + "//chrome/browser/ui/messages/android:java_resources", ++ "//components/adblock/android:java_resources", + "//components/autofill/android:autofill_java_resources", + "//components/autofill/android:autofill_payments_java_resources", + "//components/blocked_content/android:java_resources", +@@ -432,6 +437,7 @@ if (current_toolchain == default_toolchain) { + "//chrome/browser/webapps/android:java", + "//chrome/browser/webauthn/android:java", + "//chrome/browser/xsurface:java", ++ "//components/adblock/android:adblock_java", + "//components/autofill/android:autofill_java", + "//components/background_task_scheduler:background_task_scheduler_java", + "//components/background_task_scheduler:background_task_scheduler_task_ids_java", +@@ -1641,6 +1647,7 @@ if (current_toolchain == default_toolchain) { + "//chrome/test/android:chrome_java_integration_test_support", + "//chrome/test/android:chrome_java_test_pagecontroller", + "//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java", ++ "//components/adblock/android:adblock_java_tests", + "//components/autofill/android:autofill_features_java", + "//components/autofill/android:autofill_java", + "//components/background_task_scheduler:background_task_scheduler_java", +@@ -1837,6 +1844,7 @@ if (current_toolchain == default_toolchain) { + srcjar_deps = [ "//chrome/browser:tos_dialog_behavior_generated_enum" ] + + data = [ ++ "//chrome/test/data/adblock/", + "//chrome/test/data/android/", + "//chrome/test/data/autofill/", + "//chrome/test/data/background_sync/", +@@ -3597,6 +3605,7 @@ group("jni_headers") { + "//chrome/browser/ui/messages/android:jni_headers", + "//chrome/browser/util:jni_headers", + "//chrome/browser/webauthn/android:jni_headers", ++ "//components/adblock/android:jni_headers", + "//components/content_relationship_verification/android:jni_headers", + "//components/image_fetcher:jni_headers", + "//components/media_router/browser/android:jni_headers", +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -3327,6 +3327,20 @@ static_library("browser") { + "webauthn/android/webauthn_request_delegate_android.cc", + "webauthn/android/webauthn_request_delegate_android.h", + ++ ### Android API module start ++ "android/adblock/adblock_jni.cc", ++ "android/adblock/adblock_jni.h", ++ "android/adblock/adblock_jni_factory.cc", ++ "android/adblock/adblock_jni_factory.h", ++ "android/adblock/filtering_configuration_bindings_factory.cc", ++ "android/adblock/filtering_configuration_bindings_factory.h", ++ "android/adblock/filtering_configuration_bindings.cc", ++ "android/adblock/filtering_configuration_bindings.h", ++ "android/adblock/resource_classification_notifier_bindings_factory.cc", ++ "android/adblock/resource_classification_notifier_bindings_factory.h", ++ "android/adblock/resource_classification_notifier_bindings.cc", ++ "android/adblock/resource_classification_notifier_bindings.h", ++ ### Android API module end + ] + + public_deps += [ +diff --git a/chrome/browser/android/adblock/adblock_jni.cc b/chrome/browser/android/adblock/adblock_jni.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni.cc +@@ -0,0 +1,194 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++#include "chrome/browser/android/adblock/adblock_jni.h" ++ ++#include ++#include ++#include ++ ++#include "base/android/jni_android.h" ++#include "base/android/jni_array.h" ++#include "base/android/jni_string.h" ++#include "base/android/jni_weak_ref.h" ++#include "base/logging.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/profile_manager.h" ++#include "components/adblock/android/jni_headers/AdblockController_jni.h" ++#include "content/public/browser/browser_thread.h" ++ ++using base::android::AttachCurrentThread; ++using base::android::CheckException; ++using base::android::ConvertJavaStringToUTF8; ++using base::android::ConvertUTF8ToJavaString; ++using base::android::GetClass; ++using base::android::JavaParamRef; ++using base::android::JavaRef; ++using base::android::MethodID; ++using base::android::ScopedJavaGlobalRef; ++using base::android::ScopedJavaLocalRef; ++using base::android::ToJavaArrayOfObjects; ++using base::android::ToJavaArrayOfStrings; ++ ++namespace adblock { ++ ++namespace { ++ ++AdblockController* GetController() { ++ if (!g_browser_process || !g_browser_process->profile_manager()) { ++ return nullptr; ++ } ++ return AdblockControllerFactory::GetForBrowserContext( ++ g_browser_process->profile_manager()->GetLastUsedProfile()); ++} ++ ++AdblockJNI* GetJNI() { ++ if (!g_browser_process || !g_browser_process->profile_manager()) { ++ return nullptr; ++ } ++ return AdblockJNIFactory::GetForBrowserContext( ++ g_browser_process->profile_manager()->GetLastUsedProfile()); ++} ++ ++ScopedJavaLocalRef ToJava(JNIEnv* env, ++ ScopedJavaLocalRef& url_class, ++ jmethodID& url_constructor, ++ const std::string& url, ++ const std::string& title, ++ const std::string& version, ++ const std::vector& languages) { ++ ScopedJavaLocalRef url_param( ++ env, env->NewObject(url_class.obj(), url_constructor, ++ ConvertUTF8ToJavaString(env, url).obj())); ++ CheckException(env); ++ return Java_Subscription_Constructor(env, url_param, ++ ConvertUTF8ToJavaString(env, title), ++ ConvertUTF8ToJavaString(env, version), ++ ToJavaArrayOfStrings(env, languages)); ++} ++ ++std::vector> CSubscriptionsToJObjects( ++ JNIEnv* env, ++ const std::vector>& subscriptions) { ++ ScopedJavaLocalRef url_class = GetClass(env, "java/net/URL"); ++ jmethodID url_constructor = MethodID::Get( ++ env, url_class.obj(), "", "(Ljava/lang/String;)V"); ++ std::vector> jobjects; ++ jobjects.reserve(subscriptions.size()); ++ for (auto& sub : subscriptions) { ++ jobjects.push_back(ToJava( ++ env, url_class, url_constructor, sub->GetSourceUrl().spec(), ++ sub->GetTitle(), sub->GetCurrentVersion(), std::vector{})); ++ } ++ return jobjects; ++} ++ ++std::vector> CSubscriptionsToJObjects( ++ JNIEnv* env, ++ std::vector& subscriptions) { ++ ScopedJavaLocalRef url_class = GetClass(env, "java/net/URL"); ++ jmethodID url_constructor = MethodID::Get( ++ env, url_class.obj(), "", "(Ljava/lang/String;)V"); ++ std::vector> jobjects; ++ jobjects.reserve(subscriptions.size()); ++ for (auto& sub : subscriptions) { ++ if (sub.ui_visibility == SubscriptionUiVisibility::Visible) { ++ // The checks here are when one makes f.e. adblock:custom visible ++ DCHECK(sub.url.is_valid()); ++ if (sub.url.is_valid()) { ++ jobjects.push_back(ToJava(env, url_class, url_constructor, ++ sub.url.spec(), sub.title, "", ++ sub.languages)); ++ } ++ } ++ } ++ return jobjects; ++} ++ ++} // namespace ++ ++AdblockJNI::AdblockJNI(SubscriptionService* subscription_service) ++ : subscription_service_(subscription_service) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ if (subscription_service_) { ++ subscription_service_->AddObserver(this); ++ } ++} ++ ++AdblockJNI::~AdblockJNI() { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ if (subscription_service_) { ++ subscription_service_->RemoveObserver(this); ++ } ++} ++ ++void AdblockJNI::Bind(JavaObjectWeakGlobalRef weak_java_controller) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ weak_java_controller_ = weak_java_controller; ++} ++ ++void AdblockJNI::OnSubscriptionInstalled(const GURL& url) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ JNIEnv* env = AttachCurrentThread(); ++ ScopedJavaLocalRef obj = weak_java_controller_.get(env); ++ if (obj.is_null()) { ++ return; ++ } ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ Java_AdblockController_subscriptionUpdatedCallback(env, obj, j_url); ++} ++ ++} // namespace adblock ++ ++static void JNI_AdblockController_Bind( ++ JNIEnv* env, ++ const base::android::JavaParamRef& caller) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) { ++ return; ++ } ++ JavaObjectWeakGlobalRef weak_controller_ref(env, caller); ++ adblock::GetJNI()->Bind(weak_controller_ref); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetInstalledSubscriptions(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) { ++ return ToJavaArrayOfObjects(env, ++ std::vector>{}); ++ } ++ ++ return ToJavaArrayOfObjects( ++ env, adblock::CSubscriptionsToJObjects( ++ env, adblock::GetController()->GetInstalledSubscriptions())); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetRecommendedSubscriptions(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) { ++ return ToJavaArrayOfObjects(env, ++ std::vector>{}); ++ } ++ ++ auto list = adblock::GetController()->GetKnownSubscriptions(); ++ return ToJavaArrayOfObjects(env, ++ adblock::CSubscriptionsToJObjects(env, list)); ++} +diff --git a/chrome/browser/android/adblock/adblock_jni.h b/chrome/browser/android/adblock/adblock_jni.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni.h +@@ -0,0 +1,53 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ ++ ++#include ++ ++#include "base/android/jni_weak_ref.h" ++#include "base/memory/raw_ptr.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/keyed_service/core/keyed_service.h" ++ ++namespace content { ++class BrowserContext; ++} ++ ++namespace adblock { ++ ++class AdblockJNI : public SubscriptionService::SubscriptionObserver, ++ public KeyedService { ++ public: ++ explicit AdblockJNI(SubscriptionService* subscription_service); ++ ~AdblockJNI() override; ++ ++ void Bind(JavaObjectWeakGlobalRef weak_java_controller); ++ // SubscriptionService::SubscriptionObserver ++ void OnSubscriptionInstalled(const GURL& subscription_url) override; ++ ++ private: ++ SEQUENCE_CHECKER(sequence_checker_); ++ raw_ptr subscription_service_; ++ JavaObjectWeakGlobalRef weak_java_controller_; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ +diff --git a/chrome/browser/android/adblock/adblock_jni_factory.cc b/chrome/browser/android/adblock/adblock_jni_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni_factory.cc +@@ -0,0 +1,72 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/android/adblock/adblock_jni.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++AdblockJNI* AdblockJNIFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++AdblockJNIFactory* AdblockJNIFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockJNIFactory::AdblockJNIFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockJNI", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++AdblockJNIFactory::~AdblockJNIFactory() = default; ++ ++KeyedService* AdblockJNIFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new AdblockJNI( ++ SubscriptionServiceFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* AdblockJNIFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++bool AdblockJNIFactory::ServiceIsCreatedWithBrowserContext() const { ++ // This avoids manual instantiation in chrome_browser_main.cc ++ return true; ++} ++ ++bool AdblockJNIFactory::ServiceIsNULLWhileTesting() const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/android/adblock/adblock_jni_factory.h b/chrome/browser/android/adblock/adblock_jni_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni_factory.h +@@ -0,0 +1,50 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class AdblockJNI; ++class AdblockJNIFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ public: ++ static AdblockJNI* GetForBrowserContext(content::BrowserContext* context); ++ static AdblockJNIFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ AdblockJNIFactory(); ++ ~AdblockJNIFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++ bool ServiceIsNULLWhileTesting() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_ +diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings.cc b/chrome/browser/android/adblock/filtering_configuration_bindings.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/filtering_configuration_bindings.cc +@@ -0,0 +1,250 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/android/adblock/filtering_configuration_bindings.h" ++ ++#include ++#include ++ ++#include "base/android/jni_array.h" ++#include "base/android/jni_string.h" ++#include "base/ranges/algorithm.h" ++#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/profiles/profile_manager.h" ++#include "components/adblock/android/jni_headers/FilteringConfiguration_jni.h" ++#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/configuration/persistent_filtering_configuration.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++ ++namespace adblock { ++ ++FilteringConfigurationBindings::FilteringConfigurationBindings( ++ SubscriptionService* subscription_service, ++ PrefService* pref_service) ++ : subscription_service_(subscription_service), ++ pref_service_(pref_service) {} ++ ++FilteringConfigurationBindings::~FilteringConfigurationBindings() { ++ for (auto& pair : bound_counterparts_) { ++ pair.first->RemoveObserver(this); ++ } ++} ++ ++void FilteringConfigurationBindings::Bind( ++ const std::string& configuration_name, ++ JavaObjectWeakGlobalRef filtering_configuration_java) { ++ auto* existing_configuration = ++ GetInstalledConfigurationWithName(configuration_name); ++ if (existing_configuration) { ++ auto existing_binding = bound_counterparts_.find(existing_configuration); ++ if (existing_binding == bound_counterparts_.end()) { ++ // This is the first Java-side counterpart bound to this ++ // FilteringConfiguration. ++ existing_configuration->AddObserver(this); ++ } ++ bound_counterparts_[existing_configuration].push_back( ++ std::move(filtering_configuration_java)); ++ } else { ++ // There is no already-installed FilteringConfiguration with this name. ++ // Create one and bind to it. ++ auto new_filtering_configuration = ++ std::make_unique(pref_service_, ++ configuration_name); ++ new_filtering_configuration->AddObserver(this); ++ bound_counterparts_[new_filtering_configuration.get()].push_back( ++ std::move(filtering_configuration_java)); ++ subscription_service_->InstallFilteringConfiguration( ++ std::move(new_filtering_configuration)); ++ } ++} ++ ++FilteringConfiguration* ++FilteringConfigurationBindings::GetInstalledConfigurationWithName( ++ const std::string& configuration_name) { ++ const auto installed_configurations = ++ subscription_service_->GetInstalledFilteringConfigurations(); ++ auto existing_configuration_it = ++ base::ranges::find(installed_configurations, configuration_name, ++ &FilteringConfiguration::GetName); ++ return existing_configuration_it != installed_configurations.end() ++ ? *existing_configuration_it ++ : nullptr; ++} ++ ++void FilteringConfigurationBindings::OnEnabledStateChanged( ++ FilteringConfiguration* config) { ++ Notify(config, Java_FilteringConfiguration_enabledStateChanged); ++} ++ ++void FilteringConfigurationBindings::OnFilterListsChanged( ++ FilteringConfiguration* config) { ++ Notify(config, Java_FilteringConfiguration_filterListsChanged); ++} ++ ++void FilteringConfigurationBindings::OnAllowedDomainsChanged( ++ FilteringConfiguration* config) { ++ Notify(config, Java_FilteringConfiguration_allowedDomainsChanged); ++} ++ ++void FilteringConfigurationBindings::OnCustomFiltersChanged( ++ FilteringConfiguration* config) { ++ Notify(config, Java_FilteringConfiguration_customFiltersChanged); ++} ++ ++void FilteringConfigurationBindings::Notify( ++ FilteringConfiguration* config, ++ FilteringConfigurationBindings::JavaEventListener event_listener_function) { ++ auto bound_weak_refs = bound_counterparts_.find(config); ++ DCHECK(bound_weak_refs != bound_counterparts_.end()) ++ << "This should never receive notifications from unobserved " ++ "FilteringConfigurations"; ++ JNIEnv* env = base::android::AttachCurrentThread(); ++ for (auto& weak_ref : bound_weak_refs->second) { ++ auto java_counterpart = weak_ref.get(env); ++ if (java_counterpart.is_null()) { ++ continue; // Bound counterpart may have been destroyed on Java side ++ } ++ event_listener_function(env, java_counterpart); ++ } ++} ++ ++} // namespace adblock ++ ++adblock::FilteringConfigurationBindings& GetBindingsFromLastUsedProfile() { ++ auto* bindings = ++ adblock::FilteringConfigurationBindingsFactory::GetForBrowserContext( ++ g_browser_process->profile_manager()->GetLastUsedProfile()); ++ DCHECK(bindings) << "FilteringConfigurationBindings should be non-null even " ++ "in tests, to keep the code simple"; ++ return *bindings; ++} ++ ++adblock::FilteringConfiguration& GetConfigurationWithName( ++ const base::android::JavaParamRef& configuration_name) { ++ auto& bindings = GetBindingsFromLastUsedProfile(); ++ auto* configuration = bindings.GetInstalledConfigurationWithName( ++ base::android::ConvertJavaStringToUTF8(configuration_name)); ++ DCHECK(configuration) ++ << "FilteringConfigurationBindings::Bind should have ensured a " ++ "configuration with this name is installed"; ++ return *configuration; ++} ++ ++static void JNI_FilteringConfiguration_Bind( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& caller) { ++ auto& bindings = GetBindingsFromLastUsedProfile(); ++ JavaObjectWeakGlobalRef weak_configuration_ref(env, caller); ++ auto cpp_name = base::android::ConvertJavaStringToUTF8(configuration_name); ++ bindings.Bind(cpp_name, weak_configuration_ref); ++} ++ ++static jboolean JNI_FilteringConfiguration_IsEnabled( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name) { ++ return GetConfigurationWithName(configuration_name).IsEnabled() ? JNI_TRUE ++ : JNI_FALSE; ++} ++ ++static void JNI_FilteringConfiguration_SetEnabled( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ jboolean j_enabled) { ++ return GetConfigurationWithName(configuration_name) ++ .SetEnabled(j_enabled == JNI_TRUE); ++} ++ ++static void JNI_FilteringConfiguration_AddFilterList( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& url) { ++ GetConfigurationWithName(configuration_name) ++ .AddFilterList(GURL{base::android::ConvertJavaStringToUTF8(url)}); ++} ++ ++static void JNI_FilteringConfiguration_RemoveFilterList( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& url) { ++ GetConfigurationWithName(configuration_name) ++ .RemoveFilterList(GURL{base::android::ConvertJavaStringToUTF8(url)}); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_FilteringConfiguration_GetFilterLists( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name) { ++ // For simplicity, convert GURL to std::string, pass to Java, and convert from ++ // String to URL. Strings are easier to pass through JNI. ++ std::vector urls; ++ base::ranges::transform( ++ GetConfigurationWithName(configuration_name).GetFilterLists(), ++ std::back_inserter(urls), &GURL::spec); ++ return base::android::ToJavaArrayOfStrings(env, urls); ++} ++ ++static void JNI_FilteringConfiguration_AddAllowedDomain( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& allowed_domain) { ++ GetConfigurationWithName(configuration_name) ++ .AddAllowedDomain(base::android::ConvertJavaStringToUTF8(allowed_domain)); ++} ++ ++static void JNI_FilteringConfiguration_RemoveAllowedDomain( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& allowed_domain) { ++ GetConfigurationWithName(configuration_name) ++ .RemoveAllowedDomain(ConvertJavaStringToUTF8(allowed_domain)); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_FilteringConfiguration_GetAllowedDomains( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name) { ++ return base::android::ToJavaArrayOfStrings( ++ env, GetConfigurationWithName(configuration_name).GetAllowedDomains()); ++} ++ ++static void JNI_FilteringConfiguration_AddCustomFilter( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& custom_filter) { ++ GetConfigurationWithName(configuration_name) ++ .AddCustomFilter(ConvertJavaStringToUTF8(custom_filter)); ++} ++ ++static void JNI_FilteringConfiguration_RemoveCustomFilter( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name, ++ const base::android::JavaParamRef& custom_filter) { ++ GetConfigurationWithName(configuration_name) ++ .RemoveCustomFilter( ++ base::android::ConvertJavaStringToUTF8(custom_filter)); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_FilteringConfiguration_GetCustomFilters( ++ JNIEnv* env, ++ const base::android::JavaParamRef& configuration_name) { ++ return base::android::ToJavaArrayOfStrings( ++ env, GetConfigurationWithName(configuration_name).GetCustomFilters()); ++} +diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings.h b/chrome/browser/android/adblock/filtering_configuration_bindings.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/filtering_configuration_bindings.h +@@ -0,0 +1,69 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_H_ ++ ++#include ++#include ++#include ++#include "base/android/jni_weak_ref.h" ++#include "base/memory/raw_ptr.h" ++#include "base/sequence_checker.h" ++#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/keyed_service/core/keyed_service.h" ++#include "components/prefs/pref_service.h" ++ ++namespace adblock { ++ ++class FilteringConfigurationBindings : public KeyedService, ++ public FilteringConfiguration::Observer { ++ public: ++ explicit FilteringConfigurationBindings( ++ SubscriptionService* subscription_service, ++ PrefService* pref_service); ++ ~FilteringConfigurationBindings() override; ++ void Bind(const std::string& configuration_name, ++ JavaObjectWeakGlobalRef filtering_configuration_java); ++ FilteringConfiguration* GetInstalledConfigurationWithName( ++ const std::string& name); ++ ++ // FilteringConfiguration::Observer: ++ void OnEnabledStateChanged(FilteringConfiguration* config) override; ++ void OnFilterListsChanged(FilteringConfiguration* config) override; ++ void OnAllowedDomainsChanged(FilteringConfiguration* config) override; ++ void OnCustomFiltersChanged(FilteringConfiguration* config) override; ++ ++ private: ++ using JavaEventListener = void(JNIEnv* env, ++ const base::android::JavaRef& obj); ++ void Notify(FilteringConfiguration* config, ++ JavaEventListener event_listener_function); ++ SEQUENCE_CHECKER(sequence_checker_); ++ raw_ptr subscription_service_; ++ raw_ptr pref_service_; ++ // There may be multiple Java-side FilteringConfiguration instances ++ // (represented by JavaObjectWeakGlobalRef) that map to a single C++ ++ // FilteringConfiguration. ++ using WeakReferences = std::vector; ++ std::map bound_counterparts_; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_H_ +diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc +@@ -0,0 +1,70 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h" ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/android/adblock/filtering_configuration_bindings.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++ ++namespace adblock { ++ ++// static ++FilteringConfigurationBindings* ++FilteringConfigurationBindingsFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++FilteringConfigurationBindingsFactory* ++FilteringConfigurationBindingsFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++FilteringConfigurationBindingsFactory::FilteringConfigurationBindingsFactory() ++ : BrowserContextKeyedServiceFactory( ++ "FilteringConfigurationBindings", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++FilteringConfigurationBindingsFactory:: ++ ~FilteringConfigurationBindingsFactory() = default; ++ ++KeyedService* FilteringConfigurationBindingsFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new FilteringConfigurationBindings( ++ SubscriptionServiceFactory::GetForBrowserContext(context), ++ Profile::FromBrowserContext(context)->GetPrefs()); ++} ++ ++content::BrowserContext* ++FilteringConfigurationBindingsFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++bool FilteringConfigurationBindingsFactory::ServiceIsCreatedWithBrowserContext() ++ const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h +@@ -0,0 +1,51 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class FilteringConfigurationBindings; ++class FilteringConfigurationBindingsFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ public: ++ static FilteringConfigurationBindings* GetForBrowserContext( ++ content::BrowserContext* context); ++ static FilteringConfigurationBindingsFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ FilteringConfigurationBindingsFactory(); ++ ~FilteringConfigurationBindingsFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_ +diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings.cc b/chrome/browser/android/adblock/resource_classification_notifier_bindings.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings.cc +@@ -0,0 +1,191 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/android/adblock/resource_classification_notifier_bindings.h" ++ ++#include ++#include ++ ++#include "base/android/jni_android.h" ++#include "base/android/jni_array.h" ++#include "base/android/jni_string.h" ++#include "base/ranges/algorithm.h" ++#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h" ++#include "chrome/browser/android/tab_android.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/profiles/profile_manager.h" ++#include "components/adblock/android/jni_headers/ResourceClassificationNotifier_jni.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/common/adblock_utils.h" ++ ++namespace adblock { ++namespace { ++ ++constexpr int kNoId = -1; ++ ++int GetTabId(content::RenderFrameHost* render_frame_host) { ++ auto* web_contents = ++ content::WebContents::FromRenderFrameHost(render_frame_host); ++ if (!web_contents) { ++ return kNoId; ++ } ++ ++ auto* tab = TabAndroid::FromWebContents(web_contents); ++ if (!tab) { ++ return kNoId; ++ } ++ ++ return tab->GetAndroidId(); ++} ++ ++} // namespace ++ ++using base::android::AttachCurrentThread; ++using base::android::CheckException; ++using base::android::ConvertJavaStringToUTF8; ++using base::android::ConvertUTF8ToJavaString; ++using base::android::GetClass; ++using base::android::JavaParamRef; ++using base::android::JavaRef; ++using base::android::MethodID; ++using base::android::ScopedJavaGlobalRef; ++using base::android::ScopedJavaLocalRef; ++using base::android::ToJavaArrayOfObjects; ++using base::android::ToJavaArrayOfStrings; ++ ++ResourceClassificationNotifierBindings::ResourceClassificationNotifierBindings( ++ ResourceClassificationRunner* classification_runner) ++ : classification_runner_(classification_runner) { ++ classification_runner_->AddObserver(this); ++} ++ ++ResourceClassificationNotifierBindings:: ++ ~ResourceClassificationNotifierBindings() { ++ classification_runner_->RemoveObserver(this); ++} ++ ++void ResourceClassificationNotifierBindings::Bind( ++ JavaObjectWeakGlobalRef resource_classifier_java) { ++ bound_counterpart_ = resource_classifier_java; ++} ++ ++void ResourceClassificationNotifierBindings::OnAdMatched( ++ const GURL& url, ++ FilterMatchResult result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ DCHECK(result == FilterMatchResult::kBlockRule || ++ result == FilterMatchResult::kAllowRule); ++ const bool was_blocked = result == FilterMatchResult::kBlockRule; ++ DVLOG(3) << "[eyeo] Ad matched " << url << "(type: " << content_type ++ << (was_blocked ? ", blocked" : ", allowed") << ")"; ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = bound_counterpart_.get(env); ++ if (obj.is_null()) { ++ return; ++ } ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_parents = ++ ToJavaArrayOfStrings(env, adblock::utils::ConvertURLs(parent_frame_urls)); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ ScopedJavaLocalRef j_configuration = ++ ConvertUTF8ToJavaString(env, configuration_name); ++ int tab_id = GetTabId(render_frame_host); ++ Java_ResourceClassificationNotifier_adMatchedCallback( ++ env, obj, j_url, was_blocked, j_parents, j_subscription, j_configuration, ++ static_cast(content_type), tab_id); ++} ++ ++void ResourceClassificationNotifierBindings::OnPageAllowed( ++ const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ DVLOG(3) << "[eyeo] Page allowed " << url; ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = bound_counterpart_.get(env); ++ if (obj.is_null()) { ++ return; ++ } ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ ScopedJavaLocalRef j_configuration = ++ ConvertUTF8ToJavaString(env, configuration_name); ++ int tab_id = GetTabId(render_frame_host); ++ Java_ResourceClassificationNotifier_pageAllowedCallback( ++ env, obj, j_url, j_subscription, j_configuration, tab_id); ++} ++ ++void ResourceClassificationNotifierBindings::OnPopupMatched( ++ const GURL& url, ++ FilterMatchResult result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ DCHECK(result == FilterMatchResult::kBlockRule || ++ result == FilterMatchResult::kAllowRule); ++ const bool was_blocked = result == FilterMatchResult::kBlockRule; ++ DVLOG(3) << "[eyeo] Popup matched " << url ++ << (was_blocked ? ", blocked" : ", allowed"); ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = bound_counterpart_.get(env); ++ if (obj.is_null()) { ++ return; ++ } ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_opener = ++ ConvertUTF8ToJavaString(env, opener_url.spec()); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ ScopedJavaLocalRef j_configuration = ++ ConvertUTF8ToJavaString(env, configuration_name); ++ int tab_id = GetTabId(render_frame_host); ++ Java_ResourceClassificationNotifier_popupMatchedCallback( ++ env, obj, j_url, was_blocked, j_opener, j_subscription, j_configuration, ++ tab_id); ++} ++ ++} // namespace adblock ++ ++static void JNI_ResourceClassificationNotifier_Bind( ++ JNIEnv* env, ++ const base::android::JavaParamRef& caller) { ++ auto* bindings = adblock::ResourceClassificationNotifierBindingsFactory:: ++ GetForBrowserContext(ProfileManager::GetLastUsedProfile()); ++ DCHECK(bindings); ++ ++ bindings->Bind(JavaObjectWeakGlobalRef(env, caller)); ++} +diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings.h b/chrome/browser/android/adblock/resource_classification_notifier_bindings.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings.h +@@ -0,0 +1,69 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_ ++ ++#include ++#include ++#include "base/android/jni_weak_ref.h" ++#include "base/memory/raw_ptr.h" ++#include "base/sequence_checker.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/keyed_service/core/keyed_service.h" ++#include "components/prefs/pref_service.h" ++ ++namespace adblock { ++ ++class ResourceClassificationNotifierBindings ++ : public KeyedService, ++ public ResourceClassificationRunner::Observer { ++ public: ++ explicit ResourceClassificationNotifierBindings( ++ ResourceClassificationRunner* classification_runner); ++ ~ResourceClassificationNotifierBindings() override; ++ ++ void Bind(JavaObjectWeakGlobalRef resource_classifier_java); ++ ++ // ResourceClassificationRunner::Observer ++ void OnAdMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override; ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override; ++ void OnPopupMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override; ++ ++ private: ++ SEQUENCE_CHECKER(sequence_checker_); ++ raw_ptr classification_runner_; ++ JavaObjectWeakGlobalRef bound_counterpart_; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_ +diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc +@@ -0,0 +1,71 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h" ++ ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/android/adblock/resource_classification_notifier_bindings.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++ ++namespace adblock { ++ ++// static ++ResourceClassificationNotifierBindings* ++ResourceClassificationNotifierBindingsFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ResourceClassificationNotifierBindingsFactory* ++ResourceClassificationNotifierBindingsFactory::GetInstance() { ++ static base::NoDestructor ++ instance; ++ return instance.get(); ++} ++ ++ResourceClassificationNotifierBindingsFactory:: ++ ResourceClassificationNotifierBindingsFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ResourceClassificationNotifierBindings", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(ResourceClassificationRunnerFactory::GetInstance()); ++} ++ ++ResourceClassificationNotifierBindingsFactory:: ++ ~ResourceClassificationNotifierBindingsFactory() = default; ++ ++KeyedService* ++ResourceClassificationNotifierBindingsFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ResourceClassificationNotifierBindings( ++ ResourceClassificationRunnerFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* ++ResourceClassificationNotifierBindingsFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++bool ResourceClassificationNotifierBindingsFactory:: ++ ServiceIsCreatedWithBrowserContext() const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h +@@ -0,0 +1,52 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class ResourceClassificationNotifierBindings; ++class ResourceClassificationNotifierBindingsFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ public: ++ static ResourceClassificationNotifierBindings* GetForBrowserContext( ++ content::BrowserContext* context); ++ static ResourceClassificationNotifierBindingsFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor< ++ ResourceClassificationNotifierBindingsFactory>; ++ ResourceClassificationNotifierBindingsFactory(); ++ ~ResourceClassificationNotifierBindingsFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_ +diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc ++++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +@@ -252,6 +252,11 @@ + #include "components/commerce/core/commerce_feature_list.h" + #include "components/commerce/core/proto/merchant_signal_db_content.pb.h" + ++// Android API module start ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" ++#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h" ++#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h" ++// Android API module end + + #else + #include "chrome/browser/accessibility/live_caption/live_caption_controller_factory.h" +@@ -727,6 +732,11 @@ void ChromeBrowserMainExtraPartsProfiles:: + #if BUILDFLAG(IS_ANDROID) + FastCheckoutCapabilitiesFetcherFactory::GetInstance(); + ++ // Android API module start ++ adblock::AdblockJNIFactory::GetInstance(); ++ adblock::FilteringConfigurationBindingsFactory::GetInstance(); ++ adblock::ResourceClassificationNotifierBindingsFactory::GetInstance(); ++ // Android API module end + + #endif + FaviconServiceFactory::GetInstance(); +diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BUILD.gn +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/BUILD.gn +@@ -0,0 +1,110 @@ ++# This file is part of eyeo Chromium SDK, ++# Copyright (C) 2006-present eyeo GmbH ++# eyeo Chromium SDK is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 3 as ++# published by the Free Software Foundation. ++# eyeo Chromium SDK is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# You should have received a copy of the GNU General Public License ++# along with eyeo Chromium SDK. If not, see . ++ ++ ++import("//build/config/android/rules.gni") ++import("//build/config/locales.gni") ++import("//tools/grit/grit_rule.gni") ++ ++android_library("adblock_java") { ++ sources = [ ++ "java/src/org/chromium/components/adblock/AdblockContentType.java", ++ "java/src/org/chromium/components/adblock/AdblockController.java", ++ "java/src/org/chromium/components/adblock/AdblockCounters.java", ++ "java/src/org/chromium/components/adblock/FilteringConfiguration.java", ++ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java", ++ ] ++ ++ ++ deps = [ ++ ":java_resources", ++ ":jni_headers", ++ "//base:base_java", ++ "//base:jni_java", ++ "//build/android:build_java", ++ "//chrome/browser/preferences:java", ++ "//chrome/browser/profiles/android:java", ++ "//components/browser_ui/settings/android:java", ++ "//components/prefs/android:java", ++ "//components/user_prefs/android:java", ++ "//third_party/androidx:androidx_annotation_annotation_java", ++ "//third_party/androidx:androidx_fragment_fragment_java", ++ "//third_party/androidx:androidx_preference_preference_java", ++ ] ++ ++ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] ++ resources_package = "org.chromium.components.adblock" ++} ++ ++generate_jni("jni_headers") { ++ sources = [ ++ "java/src/org/chromium/components/adblock/AdblockController.java", ++ "java/src/org/chromium/components/adblock/FilteringConfiguration.java", ++ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java", ++ ] ++} ++ ++android_resources("java_resources") { ++ sources = [ ++ "java/res/values/adblock_settings_locales_titles.xml", ++ ] ++} ++ ++android_library("adblock_java_tests") { ++ testonly = true ++ ++ sources = [ ++ "javatests/src/org/chromium/components/adblock/AdblockControllerTest.java", ++ "javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java", ++ "javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java", ++ "javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesCspTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java", ++ "javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java", ++ "javatests/src/org/chromium/components/adblock/TestVerificationUtils.java", ++ ] ++ ++ ++ deps = [ ++ ":adblock_java", ++ "//base:base_java", ++ "//base:base_java_test_support", ++ "//chrome/android:chrome_java", ++ "//chrome/browser/flags:java", ++ "//chrome/browser/settings:test_support_java", ++ "//chrome/browser/tab:java", ++ "//chrome/browser/tabmodel:java", ++ "//chrome/test/android:chrome_java_integration_test_support", ++ "//chrome/test/android:chrome_java_test_support_common", ++ "//components/infobars/android:java", ++ "//components/infobars/core:infobar_enums_java", ++ "//components/messages/android/test:test_support_java", ++ "//content/public/android:content_full_java", ++ "//content/public/android:content_main_dex_java", ++ "//content/public/test/android:content_java_test_support", ++ "//net/android:net_java_test_support", ++ "//third_party/androidx:androidx_test_monitor_java", ++ "//third_party/androidx:androidx_test_runner_java", ++ "//third_party/hamcrest:hamcrest_library_java", ++ "//third_party/junit:junit", ++ ] ++} +diff --git a/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml b/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml +@@ -0,0 +1,98 @@ ++ ++ ++ ++ ++ | ++ ++ ++ ++ af|Afrikaans ++ am|ኣማርኛ ++ ar|العربية ++ as|অসমীয়া ++ ast|Asturianu ++ az|Azərbaycan ++ be|Беларуская мова ++ bg|български ++ bn|বাংলা (ভারত) ++ br|ar brezhoneg ++ bs|bosanski ++ ca|català ++ cs|čeština ++ cy|Cymraeg ++ da|dansk ++ de|Deutsch ++ dsb|dolnoserbski ++ el|ελληνικά ++ en|English ++ eo|Esperanto ++ es|español ++ et|eesti keel ++ eu|euskara ++ fa|فارسى ++ fi|suomi ++ fil|Filipino ++ fr|français ++ fy|Frysk ++ gl|Galego ++ gu|ગુજરાતી (ભારત) ++ he|עברית ++ hi|हिन्दी ++ hr|Hrvatski ++ hsb|hornjoserbsce ++ hu|magyar ++ hy|Հայերեն ++ id|Bahasa Indonesia ++ is|Íslenska ++ it|italiano ++ ja|日本語 ++ ka|ქართული ++ kab|Taqbaylit ++ kk|Қазақ тілі ++ kn|ಕನ್ನಡ ++ ko|한국어 ++ lt|lietuvių kalba ++ lv|latviešu valoda ++ mg|Malagasy ++ mk|македонски ++ ml|മലയാളം ++ ms|Melayu ++ nb|norsk ++ nl|Nederlands ++ nn|norsk ++ pa|ਪੰਜਾਬੀ (ਭਾਰਤ) ++ pl|polski ++ pt|português ++ rm|rumantsch ++ ro|română ++ ru|Русский ++ si|සිංහල ++ sk|slovenčina ++ sl|slovenščina ++ sq|shqip ++ sr|српски ++ sv|svenska ++ sw|Kiswahili ++ ta|தமிழ் ++ te|తెలుగు ++ th|ภาษาไทย ++ tr|Türkçe ++ uk|українська ++ ur|اردو ++ uz|o’zbek ++ vi|Tiếng Việt ++ zh|中文 ++ ++ +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java +@@ -0,0 +1,62 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import java.util.HashMap; ++import java.util.Map; ++ ++public enum AdblockContentType { ++ // Note. This has to be kept in sync with c++ enum so some values ++ // are skipped ++ CONTENT_TYPE_OTHER(1 << 0), ++ CONTENT_TYPE_SCRIPT(1 << 1), ++ CONTENT_TYPE_IMAGE(1 << 2), ++ CONTENT_TYPE_STYLESHEET(1 << 3), ++ CONTENT_TYPE_OBJECT(1 << 4), ++ CONTENT_TYPE_SUBDOCUMENT(1 << 5), ++ CONTENT_TYPE_WEBSOCKET(1 << 7), ++ CONTENT_TYPE_WEBRTC(1 << 8), ++ CONTENT_TYPE_PING(1 << 10), ++ CONTENT_TYPE_XMLHTTPREQUEST(1 << 11), ++ CONTENT_TYPE_MEDIA(1 << 14), ++ CONTENT_TYPE_FONT(1 << 15); ++ ++ private final int contentType; ++ ++ private AdblockContentType(int contentType) { ++ this.contentType = contentType; ++ } ++ ++ private static final Map intToContentTypeMap = ++ new HashMap(); ++ ++ static { ++ for (AdblockContentType type : AdblockContentType.values()) { ++ intToContentTypeMap.put(type.contentType, type); ++ } ++ } ++ ++ public static AdblockContentType fromInt(int i) { ++ AdblockContentType type = intToContentTypeMap.get(Integer.valueOf(i)); ++ return type; ++ } ++ ++ public int getValue() { ++ return contentType; ++ } ++} +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java +@@ -0,0 +1,258 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import android.content.Context; ++import android.content.res.Resources; ++import android.util.Log; ++import android.webkit.URLUtil; ++ ++import androidx.annotation.NonNull; ++import androidx.annotation.Nullable; ++import androidx.annotation.UiThread; ++ ++import org.chromium.base.ContextUtils; ++import org.chromium.base.ThreadUtils; ++import org.chromium.base.annotations.CalledByNative; ++import org.chromium.base.annotations.NativeMethods; ++import org.chromium.chrome.browser.preferences.Pref; ++import org.chromium.chrome.browser.profiles.Profile; ++import org.chromium.components.user_prefs.UserPrefs; ++ ++import java.io.UnsupportedEncodingException; ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.concurrent.CopyOnWriteArraySet; ++ ++/** ++ * @brief Main access point for java UI code to control ad filtering. ++ * It calls its native counter part also AdblockController. ++ * It lives in UI thread on the browser process. ++ */ ++public final class AdblockController extends FilteringConfiguration { ++ private static final String TAG = AdblockController.class.getSimpleName(); ++ ++ private static AdblockController sInstance; ++ ++ private URL mAcceptableAds; ++ ++ private AdblockController() { ++ super("adblock"); ++ try { ++ mAcceptableAds = ++ new URL("https://easylist-downloads.adblockplus.org/exceptionrules.txt"); ++ } catch (java.net.MalformedURLException e) { ++ mAcceptableAds = null; ++ } ++ } ++ ++ /** ++ * @return The singleton object. ++ */ ++ public static AdblockController getInstance() { ++ ThreadUtils.assertOnUiThread(); ++ if (sInstance == null) { ++ sInstance = new AdblockController(); ++ AdblockControllerJni.get().bind(sInstance); ++ } ++ return sInstance; ++ } ++ ++ public static class Subscription { ++ private URL mUrl; ++ private String mTitle; ++ private String mVersion = ""; ++ private String[] mLanguages = {}; ++ ++ public Subscription(final URL url, final String title, final String version) { ++ this.mUrl = url; ++ this.mTitle = title; ++ this.mVersion = version; ++ } ++ ++ @CalledByNative("Subscription") ++ public Subscription( ++ final URL url, final String title, final String version, final String[] languages) { ++ this.mUrl = url; ++ this.mTitle = title; ++ this.mVersion = version; ++ this.mLanguages = languages; ++ } ++ ++ public String title() { ++ return mTitle; ++ } ++ ++ public URL url() { ++ return mUrl; ++ } ++ ++ public String version() { ++ return mVersion; ++ } ++ ++ public String[] languages() { ++ return mLanguages; ++ } ++ ++ @Override ++ public boolean equals(final Object object) { ++ if (object == null) return false; ++ if (getClass() != object.getClass()) return false; ++ ++ Subscription other = (Subscription) object; ++ return url().equals(other.url()); ++ } ++ } ++ ++ @UiThread ++ public void setAcceptableAdsEnabled(boolean enabled) { ++ if (enabled) ++ addFilterList(mAcceptableAds); ++ else ++ removeFilterList(mAcceptableAds); ++ } ++ ++ @UiThread ++ public boolean isAcceptableAdsEnabled() { ++ return getFilterLists().contains(mAcceptableAds); ++ } ++ ++ @UiThread ++ public void setMoreOptionsEnabled(boolean enabled) { ++ UserPrefs.get(Profile.getLastUsedRegularProfile()) ++ .setBoolean(Pref.ADBLOCK_MORE_OPTIONS_ENABLED, enabled); ++ } ++ ++ @UiThread ++ public boolean areMoreOptionsEnabled() { ++ return UserPrefs.get(Profile.getLastUsedRegularProfile()) ++ .getBoolean(Pref.ADBLOCK_MORE_OPTIONS_ENABLED); ++ } ++ ++ @UiThread ++ public List getRecommendedSubscriptions(Context context) { ++ final List recommendedSubscriptions = ++ (List) (List) Arrays.asList( ++ AdblockControllerJni.get().getRecommendedSubscriptions()); ++ final Map localeToTitle = getLocaleToTitleMap(context); ++ for (int i = 0; i < recommendedSubscriptions.size(); ++i) { ++ for (final String language : recommendedSubscriptions.get(i).languages()) { ++ final String title = localeToTitle.get(language); ++ if (title != null && !title.isEmpty()) { ++ recommendedSubscriptions.set(i, ++ new Subscription(recommendedSubscriptions.get(i).url(), title, ++ "" /*version*/, recommendedSubscriptions.get(i).languages())); ++ break; ++ } ++ } ++ } ++ return recommendedSubscriptions; ++ } ++ ++ @UiThread ++ public void installSubscription(final URL url) { ++ addFilterList(url); ++ } ++ ++ @UiThread ++ public void uninstallSubscription(final URL url) { ++ removeFilterList(url); ++ } ++ ++ @UiThread ++ public List getInstalledSubscriptions() { ++ return (List) (List) Arrays.asList( ++ AdblockControllerJni.get().getInstalledSubscriptions()); ++ } ++ ++ // TODO(mpawlowski) temporary pass-through, to enable gradual deprecation. ++ public interface AdBlockedObserver extends ResourceClassificationNotifier.AdBlockedObserver {} ++ // TODO(mpawlowski) deprecate and remove, use ResourceClassificationNotifier directly. ++ @UiThread ++ public void addOnAdBlockedObserver( ++ final ResourceClassificationNotifier.AdBlockedObserver observer) { ++ ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(observer); ++ } ++ ++ // TODO(mpawlowski) deprecate and remove, use ResourceClassifier directly. ++ @UiThread ++ public void removeOnAdBlockedObserver( ++ final ResourceClassificationNotifier.AdBlockedObserver observer) { ++ ResourceClassificationNotifier.getInstance().removeOnAdBlockedObserver(observer); ++ } ++ ++ private List transform(String[] urls) { ++ if (urls == null) return null; ++ ++ List result = new ArrayList(); ++ for (String url : urls) { ++ try { ++ result.add(new URL(URLUtil.guessUrl(url))); ++ } catch (MalformedURLException e) { ++ Log.e(TAG, "Error parsing url: " + url); ++ } ++ } ++ ++ return result; ++ } ++ ++ private Map getLocaleToTitleMap(final Context context) { ++ final Resources resources = context.getResources(); ++ final String[] locales = ++ resources.getStringArray(R.array.fragment_adblock_general_locale_title); ++ final String separator = resources.getString(R.string.fragment_adblock_general_separator); ++ final Map localeToTitle = new HashMap<>(locales.length); ++ for (final String localeAndTitlePair : locales) { ++ // in `String.split()` separator is a regexp, but we want to treat it as a string ++ final int separatorIndex = localeAndTitlePair.indexOf(separator); ++ final String locale = localeAndTitlePair.substring(0, separatorIndex); ++ final String title = localeAndTitlePair.substring(separatorIndex + 1); ++ localeToTitle.put(locale, title); ++ } ++ ++ return localeToTitle; ++ } ++ ++ @CalledByNative ++ private void subscriptionUpdatedCallback(final String url) { ++ ThreadUtils.assertOnUiThread(); ++ try { ++ URL subscriptionUrl = new URL(URLUtil.guessUrl(url)); ++ for (final SubscriptionUpdateObserver observer : mSubscriptionUpdateObservers) { ++ observer.onSubscriptionDownloaded(subscriptionUrl); ++ } ++ } catch (MalformedURLException e) { ++ Log.e(TAG, "Error parsing subscription url: " + url); ++ } ++ } ++ ++ @NativeMethods ++ interface Natives { ++ void bind(AdblockController caller); ++ Object[] getInstalledSubscriptions(); ++ Object[] getRecommendedSubscriptions(); ++ } ++} +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java +@@ -0,0 +1,101 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++ ++public class AdblockCounters { ++ /** ++ * Immutable data-class containing an auxiliary information about resource event. ++ */ ++ public static class ResourceInfo { ++ private final String mRequestUrl; ++ private final List mParentFrameUrls; ++ private final String mSubscriptionUrl; ++ private final String mConfigurationName; ++ private final AdblockContentType mAdblockContentType; ++ private final int mTabId; ++ ++ ResourceInfo(final String requestUrl, final List parentFrameUrls, ++ final String subscriptionUrl, final String configurationName, ++ final int adblockContentType, final int tabId) { ++ this.mRequestUrl = requestUrl; ++ this.mParentFrameUrls = parentFrameUrls; ++ this.mSubscriptionUrl = subscriptionUrl; ++ this.mConfigurationName = configurationName; ++ this.mAdblockContentType = AdblockContentType.fromInt(adblockContentType); ++ this.mTabId = tabId; ++ } ++ ++ /** ++ * @return The request which was blocked or allowed. ++ */ ++ public String getRequestUrl() { ++ return mRequestUrl; ++ } ++ ++ /** ++ * @return The parent frames of the mRequestUrl. ++ */ ++ public List getParentFrameUrls() { ++ return mParentFrameUrls; ++ } ++ ++ /** ++ * @return Subscription url for filter done blocking or allowing decision, ++ * empty string otherwise. ++ */ ++ public String getSubscription() { ++ return mSubscriptionUrl; ++ } ++ ++ /** ++ * @return Configuration name containing subscription with matched filer for ++ * blocking or allowing decision, empty string otherwise. ++ */ ++ public String getConfigurationName() { ++ return mConfigurationName; ++ } ++ ++ /** ++ * @return The Adblock content type. See enum ContentType in ++ * components/adblock/types.h ++ */ ++ public AdblockContentType getAdblockContentType() { ++ return mAdblockContentType; ++ } ++ ++ /** ++ * @return The current tab id for the mRequestUrl. -1 means no tab id, likely tab closed ++ * before event arrived. Numbers start from 0. ++ */ ++ public int getTabId() { ++ return mTabId; ++ } ++ ++ @Override ++ public String toString() { ++ return "mRequestUrl: " + mRequestUrl + ", mParentFrameUrls: " ++ + mParentFrameUrls.toString() + ", mSubscriptionUrl:" + mSubscriptionUrl ++ + ", mConfigurationName:" + mConfigurationName + ", mAdblockContentType: " ++ + mAdblockContentType.getValue() + ", mTabId: " + mTabId; ++ } ++ } ++} +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java +@@ -0,0 +1,245 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import android.content.Context; ++import android.content.res.Resources; ++import android.util.Log; ++import android.webkit.URLUtil; ++ ++import androidx.annotation.UiThread; ++ ++import org.chromium.base.ContextUtils; ++import org.chromium.base.ThreadUtils; ++import org.chromium.base.annotations.CalledByNative; ++import org.chromium.base.annotations.NativeMethods; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++ ++/** ++ * @brief Represents an independent configuration of filters, filter lists, ++ * allowed domains and other settings that influence resource filtering and ++ * content blocking. ++ * Multiple Filtering Configurations can co-exist and be controlled separately. ++ * A network resource is blocked if any enabled Filtering Configuration ++ * determines it should be, through its filters. ++ * Elements on websites are hidden according to a superset of element-hiding ++ * selectors from all enabled Filtering Configurations. ++ * Lives on UI thread, not thread-safe. ++ */ ++public class FilteringConfiguration { ++ private static final String TAG = FilteringConfiguration.class.getSimpleName(); ++ ++ private final Set mConfigurationChangeObservers = new HashSet<>(); ++ protected final Set mSubscriptionUpdateObservers = new HashSet<>(); ++ private final String mName; ++ ++ public interface ConfigurationChangeObserver { ++ /** ++ * Triggered when the FilteringConfiguration becomes disabled or enabled. ++ */ ++ @UiThread ++ void onEnabledStateChanged(); ++ ++ /** ++ * Triggered when the collection of installed filter lists changes. ++ */ ++ @UiThread ++ void onFilterListsChanged(); ++ ++ /** ++ * Triggered when the set of allowed domain changes. ++ */ ++ @UiThread ++ void onAllowedDomainsChanged(); ++ ++ /** ++ * Triggered when the set of custom filters changes. ++ */ ++ @UiThread ++ void onCustomFiltersChanged(); ++ } ++ ++ public interface SubscriptionUpdateObserver { ++ @UiThread ++ void onSubscriptionDownloaded(final URL url); ++ } ++ ++ public FilteringConfiguration(String configuration_name) { ++ mName = configuration_name; ++ FilteringConfigurationJni.get().bind(mName, this); ++ } ++ ++ @UiThread ++ public void addObserver(final ConfigurationChangeObserver observer) { ++ mConfigurationChangeObservers.add(observer); ++ } ++ ++ @UiThread ++ public void removeObserver(final ConfigurationChangeObserver observer) { ++ mConfigurationChangeObservers.remove(observer); ++ } ++ ++ @UiThread ++ public void addSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) { ++ mSubscriptionUpdateObservers.add(observer); ++ } ++ ++ @UiThread ++ public void removeSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) { ++ mSubscriptionUpdateObservers.remove(observer); ++ } ++ ++ @UiThread ++ public void setEnabled(boolean enabled) { ++ FilteringConfigurationJni.get().setEnabled(mName, enabled); ++ } ++ ++ @UiThread ++ public boolean isEnabled() { ++ return FilteringConfigurationJni.get().isEnabled(mName); ++ } ++ ++ @UiThread ++ public void addFilterList(final URL url) { ++ FilteringConfigurationJni.get().addFilterList(mName, url.toString()); ++ } ++ ++ @UiThread ++ public void removeFilterList(final URL url) { ++ FilteringConfigurationJni.get().removeFilterList(mName, url.toString()); ++ } ++ ++ @UiThread ++ public List getFilterLists() { ++ List filterListsStr = ++ Arrays.asList(FilteringConfigurationJni.get().getFilterLists(mName)); ++ List filterLists = new ArrayList(); ++ for (String url : filterListsStr) { ++ try { ++ filterLists.add(new URL(url)); ++ } catch (MalformedURLException e) { ++ Log.e(TAG, "Received invalid subscription URL from C++: " + url); ++ } ++ } ++ return filterLists; ++ } ++ ++ @UiThread ++ public void addAllowedDomain(final String domain) { ++ String sanitizedDomain = sanitizeSite(domain); ++ if (sanitizedDomain == null) return; ++ FilteringConfigurationJni.get().addAllowedDomain(mName, sanitizedDomain); ++ } ++ ++ @UiThread ++ public void removeAllowedDomain(final String domain) { ++ String sanitizedDomain = sanitizeSite(domain); ++ if (sanitizedDomain == null) return; ++ FilteringConfigurationJni.get().removeAllowedDomain(mName, sanitizedDomain); ++ } ++ ++ @UiThread ++ public List getAllowedDomains() { ++ List allowedDomains = ++ Arrays.asList(FilteringConfigurationJni.get().getAllowedDomains(mName)); ++ Collections.sort(allowedDomains); ++ return allowedDomains; ++ } ++ ++ @UiThread ++ public void addCustomFilter(final String filter) { ++ FilteringConfigurationJni.get().addCustomFilter(mName, filter); ++ } ++ ++ @UiThread ++ public void removeCustomFilter(final String filter) { ++ FilteringConfigurationJni.get().removeCustomFilter(mName, filter); ++ } ++ ++ @UiThread ++ public List getCustomFilters() { ++ return Arrays.asList(FilteringConfigurationJni.get().getCustomFilters(mName)); ++ } ++ ++ private String sanitizeSite(String site) { ++ // |site| is raw user input. We expect it to be either a domain or a URL. ++ try { ++ URL candidate = new URL(URLUtil.guessUrl(site)); ++ return candidate.getHost(); ++ } catch (java.net.MalformedURLException e) { ++ } ++ // Could not parse |site| as URL or domain. ++ return null; ++ } ++ ++ @CalledByNative ++ private void enabledStateChanged() { ++ ThreadUtils.assertOnUiThread(); ++ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { ++ observer.onEnabledStateChanged(); ++ } ++ } ++ ++ @CalledByNative ++ private void filterListsChanged() { ++ ThreadUtils.assertOnUiThread(); ++ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { ++ observer.onFilterListsChanged(); ++ } ++ } ++ ++ @CalledByNative ++ private void allowedDomainsChanged() { ++ ThreadUtils.assertOnUiThread(); ++ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { ++ observer.onAllowedDomainsChanged(); ++ } ++ } ++ ++ @CalledByNative ++ private void customFiltersChanged() { ++ ThreadUtils.assertOnUiThread(); ++ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { ++ observer.onCustomFiltersChanged(); ++ } ++ } ++ ++ @NativeMethods ++ interface Natives { ++ void bind(String configuration_name, FilteringConfiguration caller); ++ boolean isEnabled(String configuration_name); ++ void setEnabled(String configuration_name, boolean enabled); ++ void addFilterList(String configuration_name, String url); ++ void removeFilterList(String configuration_name, String url); ++ String[] getFilterLists(String configuration_name); ++ void addAllowedDomain(String configuration_name, String domain); ++ void removeAllowedDomain(String configuration_name, String domain); ++ String[] getAllowedDomains(String configuration_name); ++ void addCustomFilter(String configuration_name, String filter); ++ void removeCustomFilter(String configuration_name, String filter); ++ String[] getCustomFilters(String configuration_name); ++ } ++} +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java +@@ -0,0 +1,187 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import android.content.Context; ++import android.content.res.Resources; ++import android.util.Log; ++import android.webkit.URLUtil; ++ ++import androidx.annotation.UiThread; ++ ++import org.chromium.base.ContextUtils; ++import org.chromium.base.ThreadUtils; ++import org.chromium.base.annotations.CalledByNative; ++import org.chromium.base.annotations.NativeMethods; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++ ++/** ++ * @brief Allows observing notifications from ongoing resource classification. ++ * Classification combines filters from all FilteringConfigurations. ++ * Lives on UI thread, not thread-safe. ++ */ ++public final class ResourceClassificationNotifier { ++ private static final String TAG = ResourceClassificationNotifier.class.getSimpleName(); ++ ++ private static ResourceClassificationNotifier sInstance; ++ private final Set mOnAdBlockedObservers = new HashSet<>(); ++ // TODO(mpawlowski) in the future, we can consider adding filter hit ++ // notifications here as well (DPD-1233) ++ ++ public interface AdBlockedObserver { ++ /** ++ * "Ad allowed" event for a request which would be blocked but there ++ * was an allowlisting filter found. ++ * ++ * It should not block the UI thread for too long. ++ * @param info contains auxiliary information about the resource. ++ */ ++ @UiThread ++ void onAdAllowed(AdblockCounters.ResourceInfo info); ++ ++ /** ++ * "Ad blocked" event for a request which was blocked. ++ * ++ * It should not block the UI thread for too long. ++ * @param info contains auxiliary information about the resource. ++ */ ++ @UiThread ++ void onAdBlocked(AdblockCounters.ResourceInfo info); ++ ++ /** ++ * "Page allowed" event for an allowlisted domain (page). ++ * ++ * It should not block the UI thread for too long. ++ * @param info contains auxiliary information about the resource. ++ */ ++ @UiThread ++ void onPageAllowed(AdblockCounters.ResourceInfo info); ++ ++ /** ++ * "Popup allowed" event for a popup which would be blocked but there ++ * was an allowlisting filter found. ++ * ++ * It should not block the UI thread for too long. ++ * @param info contains auxiliary information about the resource. ++ */ ++ @UiThread ++ void onPopupAllowed(AdblockCounters.ResourceInfo info); ++ ++ /** ++ * "Popup blocked" event for a popup which was blocked. ++ * ++ * It should not block the UI thread for too long. ++ * @param info contains auxiliary information about the resource. ++ */ ++ @UiThread ++ void onPopupBlocked(AdblockCounters.ResourceInfo info); ++ } ++ ++ private ResourceClassificationNotifier() { ++ ResourceClassificationNotifierJni.get().bind(this); ++ } ++ ++ public static ResourceClassificationNotifier getInstance() { ++ ThreadUtils.assertOnUiThread(); ++ if (sInstance == null) { ++ sInstance = new ResourceClassificationNotifier(); ++ } ++ return sInstance; ++ } ++ ++ @UiThread ++ public void addOnAdBlockedObserver(final AdBlockedObserver observer) { ++ mOnAdBlockedObservers.add(observer); ++ } ++ ++ @UiThread ++ public void removeOnAdBlockedObserver(final AdBlockedObserver observer) { ++ mOnAdBlockedObservers.remove(observer); ++ } ++ ++ @CalledByNative ++ private void adMatchedCallback(final String requestUrl, boolean wasBlocked, ++ final String[] parentFrameUrls, final String subscriptionUrl, ++ final String configurationName, final int contentType, final int tabId) { ++ ThreadUtils.assertOnUiThread(); ++ final List parentsList = Arrays.asList(parentFrameUrls); ++ final AdblockCounters.ResourceInfo resourceInfo = new AdblockCounters.ResourceInfo( ++ requestUrl, parentsList, subscriptionUrl, configurationName, contentType, tabId); ++ Log.d(TAG, ++ "eyeo: adMatchedCallback() notifies " + mOnAdBlockedObservers.size() ++ + " listeners about " + resourceInfo.toString() ++ + (wasBlocked ? " getting blocked" : " being allowed")); ++ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { ++ if (wasBlocked) { ++ observer.onAdBlocked(resourceInfo); ++ } else { ++ observer.onAdAllowed(resourceInfo); ++ } ++ } ++ } ++ ++ @CalledByNative ++ private void pageAllowedCallback(final String requestUrl, final String subscriptionUrl, ++ final String configurationName, final int tabId) { ++ ThreadUtils.assertOnUiThread(); ++ final AdblockCounters.ResourceInfo resourceInfo = ++ new AdblockCounters.ResourceInfo(requestUrl, new ArrayList(), subscriptionUrl, ++ configurationName, AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId); ++ Log.d(TAG, ++ "eyeo: pageAllowedCallback() notifies " + mOnAdBlockedObservers.size() ++ + " listeners about " + resourceInfo.toString()); ++ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { ++ observer.onPageAllowed(resourceInfo); ++ } ++ } ++ ++ @CalledByNative ++ private void popupMatchedCallback(final String requestUrl, boolean wasBlocked, ++ final String openerUrl, final String subscription, final String configurationName, ++ final int tabId) { ++ ThreadUtils.assertOnUiThread(); ++ final List parentsList = Arrays.asList(openerUrl); ++ final AdblockCounters.ResourceInfo resourceInfo = ++ new AdblockCounters.ResourceInfo(requestUrl, parentsList, subscription, ++ configurationName, AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId); ++ Log.d(TAG, ++ "eyeo: popupMatchedCallback() notifies " + mOnAdBlockedObservers.size() ++ + " listeners about " + resourceInfo.toString() ++ + (wasBlocked ? " getting blocked" : " being allowed")); ++ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { ++ if (wasBlocked) { ++ observer.onPopupBlocked(resourceInfo); ++ } else { ++ observer.onPopupAllowed(resourceInfo); ++ } ++ } ++ } ++ ++ @NativeMethods ++ interface Natives { ++ void bind(ResourceClassificationNotifier caller); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java +@@ -0,0 +1,87 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.base.test.util.IntegrationTest; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.TestThreadUtils; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class AdblockControllerTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private CallbackHelper mHelper = new CallbackHelper(); ++ ++ @Before ++ public void setUp() { ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void addingAllowedDomains() throws TimeoutException { ++ final List allowedDomains = new ArrayList<>(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ AdblockController.getInstance().addAllowedDomain("foobar.com"); ++ AdblockController.getInstance().addAllowedDomain("domain.com/path/to/page.html"); ++ AdblockController.getInstance().addAllowedDomain("domain.com/duplicate.html"); ++ AdblockController.getInstance().addAllowedDomain("https://scheme.com/path.html"); ++ AdblockController.getInstance().addAllowedDomain("gibberish"); ++ allowedDomains.addAll(AdblockController.getInstance().getAllowedDomains()); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ // We expect to see a sorted collection of domains (not URLs) without duplicates. ++ ArrayList expectedAllowedDomains = new ArrayList(); ++ expectedAllowedDomains.add("domain.com"); ++ expectedAllowedDomains.add("foobar.com"); ++ expectedAllowedDomains.add("scheme.com"); ++ expectedAllowedDomains.add("www.gibberish.com"); ++ Assert.assertEquals(expectedAllowedDomains, allowedDomains); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java +@@ -0,0 +1,366 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.InstrumentationRegistry; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.base.test.util.IntegrationTest; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.browser.tab.Tab; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.TestThreadUtils; ++import org.chromium.content_public.common.ContentSwitches; ++import org.chromium.net.test.EmbeddedTestServer; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ++ ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"}) ++public class FilteringConfigurationTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private CallbackHelper mHelper = new CallbackHelper(); ++ public FilteringConfiguration mConfigurationA; ++ public FilteringConfiguration mConfigurationB; ++ private EmbeddedTestServer mTestServer; ++ private String mTestUrl; ++ ++ private class TestConfigurationChangeObserver ++ implements FilteringConfiguration.ConfigurationChangeObserver { ++ public volatile boolean mOnEnabledStateChangedCalled; ++ public volatile boolean mOnFilterListsChanged; ++ public volatile boolean mOnAllowedDomainsChanged; ++ public volatile boolean mOnCustomFiltersChanged; ++ ++ public TestConfigurationChangeObserver() { ++ mOnEnabledStateChangedCalled = false; ++ mOnFilterListsChanged = false; ++ mOnAllowedDomainsChanged = false; ++ mOnCustomFiltersChanged = false; ++ } ++ ++ @Override ++ public void onEnabledStateChanged() { ++ mOnEnabledStateChangedCalled = true; ++ } ++ @Override ++ public void onFilterListsChanged() { ++ mOnFilterListsChanged = true; ++ } ++ ++ @Override ++ public void onAllowedDomainsChanged() { ++ mOnAllowedDomainsChanged = true; ++ } ++ ++ @Override ++ public void onCustomFiltersChanged() { ++ mOnCustomFiltersChanged = true; ++ } ++ } ++ ++ public void loadTestUrl() throws InterruptedException { ++ mActivityTestRule.loadUrl(mTestUrl, 5); ++ } ++ ++ @Before ++ public void setUp() throws TimeoutException { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA = new FilteringConfiguration("a"); ++ mConfigurationB = new FilteringConfiguration("b"); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); ++ mTestUrl = mTestServer.getURLWithHostName( ++ "test.org", "/chrome/test/data/adblock/innermost_frame.html"); ++ } ++ ++ @After ++ public void tearDown() { ++ mTestServer.stopAndDestroyServer(); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void addingAllowedDomains() throws Exception { ++ final List allowedDomainsA = new ArrayList<>(); ++ final List allowedDomainsB = new ArrayList<>(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addAllowedDomain("foobar.com"); ++ mConfigurationA.addAllowedDomain("domain.com/path/to/page.html"); ++ mConfigurationA.addAllowedDomain("domain.com/duplicate.html"); ++ allowedDomainsA.addAll(mConfigurationA.getAllowedDomains()); ++ ++ mConfigurationB.addAllowedDomain("https://scheme.com/path.html"); ++ mConfigurationB.addAllowedDomain("https://second.com"); ++ mConfigurationB.removeAllowedDomain("https://second.com"); ++ mConfigurationB.addAllowedDomain("gibberish"); ++ allowedDomainsB.addAll(mConfigurationB.getAllowedDomains()); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ // We expect to see a sorted collection of domains (not URLs) without duplicates. ++ ArrayList expectedAllowedDomainsA = new ArrayList(); ++ expectedAllowedDomainsA.add("domain.com"); ++ expectedAllowedDomainsA.add("foobar.com"); ++ Assert.assertEquals(expectedAllowedDomainsA, allowedDomainsA); ++ ++ // We expect not to see second.com because it was removed after being added. ++ ArrayList expectedAllowedDomainsB = new ArrayList(); ++ expectedAllowedDomainsB.add("scheme.com"); ++ expectedAllowedDomainsB.add("www.gibberish.com"); ++ Assert.assertEquals(expectedAllowedDomainsB, allowedDomainsB); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void addingCustomFilters() throws Exception { ++ final List customFiltersA = new ArrayList<>(); ++ final List customFiltersB = new ArrayList<>(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addCustomFilter("foobar.com"); ++ mConfigurationA.addCustomFilter("foobar.com"); ++ mConfigurationA.addCustomFilter("abc"); ++ customFiltersA.addAll(mConfigurationA.getCustomFilters()); ++ ++ mConfigurationB.addCustomFilter("https://scheme.com/path.html"); ++ mConfigurationB.addCustomFilter("https://second.com"); ++ mConfigurationB.removeCustomFilter("https://second.com"); ++ customFiltersB.addAll(mConfigurationB.getCustomFilters()); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ // We expect to see a collection of custom filters without duplicates. ++ // The order represents order of addition. ++ ArrayList expectedCustomFiltersA = new ArrayList(); ++ expectedCustomFiltersA.add("foobar.com"); ++ expectedCustomFiltersA.add("abc"); ++ Assert.assertEquals(expectedCustomFiltersA, customFiltersA); ++ ++ // We expect not to see https://second.com because it was removed after being added. ++ ArrayList expectedCustomFiltersB = new ArrayList(); ++ expectedCustomFiltersB.add("https://scheme.com/path.html"); ++ Assert.assertEquals(expectedCustomFiltersB, customFiltersB); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void addingFilterLists() throws Exception { ++ final URL filterList1 = new URL("http://filters.com/list1.txt"); ++ final URL filterList2 = new URL("http://filters.com/list2.txt"); ++ final List filterListsA = new ArrayList(); ++ final List filterListsB = new ArrayList(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addFilterList(filterList1); ++ mConfigurationA.addFilterList(filterList2); ++ mConfigurationA.addFilterList(filterList1); ++ filterListsA.addAll(mConfigurationA.getFilterLists()); ++ ++ mConfigurationB.addFilterList(filterList1); ++ mConfigurationB.addFilterList(filterList2); ++ mConfigurationB.removeFilterList(filterList1); ++ filterListsB.addAll(mConfigurationB.getFilterLists()); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ ArrayList expectedFilterListsA = new ArrayList(); ++ expectedFilterListsA.add(filterList1); ++ expectedFilterListsA.add(filterList2); ++ Assert.assertEquals(expectedFilterListsA, filterListsA); ++ ++ ArrayList expectedFilterListsB = new ArrayList(); ++ expectedFilterListsB.add(filterList2); ++ Assert.assertEquals(expectedFilterListsB, filterListsB); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void aliasedConfigurations() throws Exception { ++ final URL filterList1 = new URL("http://filters.com/list1.txt"); ++ final URL filterList2 = new URL("http://filters.com/list2.txt"); ++ final List filterListsA = new ArrayList(); ++ final List filterListsB = new ArrayList(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ // Create a new FilteringConfiguration with a name of one that ++ // already exist. ++ FilteringConfiguration aliasedConfiguration = new FilteringConfiguration("a"); ++ ++ // We add filter lists only to the original configuration instance. ++ mConfigurationA.addFilterList(filterList1); ++ mConfigurationA.addFilterList(filterList2); ++ ++ // We check what filter lists are present in the original and in the aliased instance. ++ filterListsA.addAll(mConfigurationA.getFilterLists()); ++ filterListsB.addAll(aliasedConfiguration.getFilterLists()); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ ArrayList expectedFilterLists = new ArrayList(); ++ expectedFilterLists.add(filterList1); ++ expectedFilterLists.add(filterList2); ++ Assert.assertEquals(expectedFilterLists, filterListsA); ++ Assert.assertEquals(expectedFilterLists, filterListsB); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void configurationChangeObserverNotified() throws Exception { ++ final URL filterList1 = new URL("http://filters.com/list1.txt"); ++ final TestConfigurationChangeObserver observer = new TestConfigurationChangeObserver(); ++ Assert.assertFalse(observer.mOnEnabledStateChangedCalled); ++ Assert.assertFalse(observer.mOnAllowedDomainsChanged); ++ Assert.assertFalse(observer.mOnCustomFiltersChanged); ++ Assert.assertFalse(observer.mOnFilterListsChanged); ++ ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ // We'll create an aliased instance which will receive notifications triggered by ++ // changes made to the original instance. ++ FilteringConfiguration aliasedConfiguration = new FilteringConfiguration("a"); ++ aliasedConfiguration.addObserver(observer); ++ ++ mConfigurationA.addFilterList(filterList1); ++ mConfigurationA.addAllowedDomain("test.com"); ++ mConfigurationA.addCustomFilter("test.com"); ++ mConfigurationA.setEnabled(false); ++ ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ Assert.assertTrue(observer.mOnEnabledStateChangedCalled); ++ Assert.assertTrue(observer.mOnAllowedDomainsChanged); ++ Assert.assertTrue(observer.mOnCustomFiltersChanged); ++ Assert.assertTrue(observer.mOnFilterListsChanged); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void resourceBlockedByFilter() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addCustomFilter("resource.png"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ TestVerificationUtils.expectResourceBlocked(mActivityTestRule, "subresource"); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void resourceAllowedByFilter() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addCustomFilter("resource.png"); ++ // Allowing filter for the mocked test.org domain that mTestServer hosts. ++ mConfigurationA.addCustomFilter("@@test.org$document"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void resourceAllowedByAllowedDomain() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfigurationA.addCustomFilter("resource.png"); ++ mConfigurationA.addAllowedDomain("test.org"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void resourceBlockedBySecondConfiguration() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ // ConfigurationA allows the resource. ++ // Allowing rules take precedence within a FilteringConfiguration. ++ mConfigurationA.addCustomFilter("resource.png"); ++ mConfigurationA.addAllowedDomain("test.org"); ++ // But ConfigurationB blocks the resource. ++ // Blocking takes precedence across FilteringConfigurations. ++ mConfigurationB.addCustomFilter("resource.png"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ TestVerificationUtils.expectResourceBlocked(mActivityTestRule, "subresource"); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void noBlockingWithoutFilters() throws Exception { ++ loadTestUrl(); ++ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java +@@ -0,0 +1,143 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.InstrumentationRegistry; ++import android.util.Log; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.base.test.util.IntegrationTest; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.browser.tab.Tab; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.TestThreadUtils; ++import org.chromium.content_public.common.ContentSwitches; ++import org.chromium.net.test.EmbeddedTestServer; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ++ ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"}) ++public class ResourceClassificationNotifierTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private CallbackHelper mHelper = new CallbackHelper(); ++ public FilteringConfiguration mConfiguration; ++ public TestAdBlockedObserver mAdBlockedObserver = new TestAdBlockedObserver(); ++ ++ private EmbeddedTestServer mTestServer; ++ private String mTestUrl; ++ ++ public void loadTestUrl() throws InterruptedException { ++ mActivityTestRule.loadUrl(mTestUrl, 5); ++ } ++ ++ @Before ++ public void setUp() throws TimeoutException { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfiguration = new FilteringConfiguration("a"); ++ ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(mAdBlockedObserver); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); ++ mTestUrl = mTestServer.getURLWithHostName( ++ "test.org", "/chrome/test/data/adblock/innermost_frame.html"); ++ } ++ ++ @After ++ public void tearDown() { ++ mTestServer.stopAndDestroyServer(); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void noNotificationWithoutBlocking() throws Exception { ++ loadTestUrl(); ++ ++ Assert.assertTrue(mAdBlockedObserver.blockedInfos.isEmpty()); ++ Assert.assertTrue(mAdBlockedObserver.allowedInfos.isEmpty()); ++ Assert.assertTrue(mAdBlockedObserver.allowedPageInfos.isEmpty()); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void resourceBlockedByFilter() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfiguration.addCustomFilter("resource.png"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ // Observer was notified about the blocking ++ Assert.assertTrue(mAdBlockedObserver.isBlocked("resource.png")); ++ Assert.assertTrue(mAdBlockedObserver.allowedInfos.isEmpty()); ++ Assert.assertTrue(mAdBlockedObserver.allowedPageInfos.isEmpty()); ++ } ++ ++ @Test ++ @IntegrationTest ++ @LargeTest ++ @Feature({"adblock"}) ++ public void pageAllowed() throws Exception { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ mConfiguration.addCustomFilter("resource.png"); ++ mConfiguration.addAllowedDomain("test.org"); ++ mHelper.notifyCalled(); ++ }); ++ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); ++ loadTestUrl(); ++ // Observer was notified about the allowed resource ++ Assert.assertTrue(mAdBlockedObserver.blockedInfos.isEmpty()); ++ Assert.assertTrue(mAdBlockedObserver.isAllowed("resource.png")); ++ ++ // TODO(mpawlowski): The observer could also be notified about the entire domain being ++ // allowed: Assert.assertTrue(mAdBlockedObserver.isPageAllowed("test.org")); However this is ++ // currently broken with multiple FilteringConfigurations (DPD-1729). ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java +@@ -0,0 +1,183 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import org.junit.Assert; ++import org.junit.Rule; ++ ++import java.net.URL; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.CopyOnWriteArrayList; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeoutException; ++ ++public class TestAdBlockedObserver implements ResourceClassificationNotifier.AdBlockedObserver { ++ @Override ++ public void onAdAllowed(AdblockCounters.ResourceInfo info) { ++ allowedInfos.add(info); ++ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); ++ CheckAndCountDownLatch(Decision.ALLOWED, info.getRequestUrl().split("\\?")[0]); ++ } ++ ++ @Override ++ public void onAdBlocked(AdblockCounters.ResourceInfo info) { ++ blockedInfos.add(info); ++ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); ++ CheckAndCountDownLatch(Decision.BLOCKED, info.getRequestUrl().split("\\?")[0]); ++ } ++ ++ @Override ++ public void onPageAllowed(AdblockCounters.ResourceInfo info) { ++ allowedPageInfos.add(info); ++ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); ++ } ++ ++ @Override ++ public void onPopupAllowed(AdblockCounters.ResourceInfo info) { ++ allowedPopupsInfos.add(info); ++ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); ++ } ++ ++ @Override ++ public void onPopupBlocked(AdblockCounters.ResourceInfo info) { ++ blockedPopupsInfos.add(info); ++ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); ++ } ++ ++ public boolean isBlocked(String url) { ++ for (AdblockCounters.ResourceInfo info : blockedInfos) { ++ if (info.getRequestUrl().contains(url)) return true; ++ } ++ ++ return false; ++ } ++ ++ public boolean isPopupBlocked(String url) { ++ for (AdblockCounters.ResourceInfo info : blockedPopupsInfos) { ++ if (info.getRequestUrl().contains(url)) return true; ++ } ++ ++ return false; ++ } ++ ++ public int numBlockedByType(AdblockContentType type) { ++ int result = 0; ++ for (AdblockCounters.ResourceInfo info : blockedInfos) { ++ if (info.getAdblockContentType() == type) ++result; ++ } ++ return result; ++ } ++ ++ public int numBlockedPopups() { ++ int result = 0; ++ for (AdblockCounters.ResourceInfo info : blockedPopupsInfos) { ++ ++result; ++ } ++ return result; ++ } ++ ++ public boolean isAllowed(String url) { ++ for (AdblockCounters.ResourceInfo info : allowedInfos) { ++ if (info.getRequestUrl().contains(url)) return true; ++ } ++ ++ return false; ++ } ++ ++ public boolean isPageAllowed(String url) { ++ for (AdblockCounters.ResourceInfo info : allowedPageInfos) { ++ if (info.getRequestUrl().contains(url)) return true; ++ } ++ ++ return false; ++ } ++ ++ public boolean isPopupAllowed(String url) { ++ for (AdblockCounters.ResourceInfo info : allowedPopupsInfos) { ++ if (info.getRequestUrl().contains(url)) return true; ++ } ++ ++ return false; ++ } ++ ++ public int numAllowedByType(AdblockContentType type) { ++ int result = 0; ++ for (AdblockCounters.ResourceInfo info : allowedInfos) { ++ if (info.getAdblockContentType() == type) ++result; ++ } ++ return result; ++ } ++ ++ public int numAllowedPopups() { ++ int result = 0; ++ for (AdblockCounters.ResourceInfo info : allowedPopupsInfos) { ++ ++result; ++ } ++ return result; ++ } ++ ++ public void setExpectedSubscriptionUrl(URL url) { ++ mTestSubscriptionUrl = url; ++ } ++ ++ private String getExpectedSubscriptionUrl() { ++ if (mTestSubscriptionUrl != null) return mTestSubscriptionUrl.toString(); ++ return "adblock:custom"; ++ } ++ ++ private enum Decision { ALLOWED, BLOCKED } ++ ++ // We either countDown() our latch for every filtered resource if there are no ++ // specific expectations set (expectedAllowed == null && expectedBlocked == null), ++ // or we countDown() only when all expectations have been met so when: ++ // (expectedAllowed.isNullOrEmpty() && expectedBlocked.isNullOrEmpty()). ++ private void CheckAndCountDownLatch(final Decision decision, final String url) { ++ if (countDownLatch != null) { ++ if (expectedBlocked == null && expectedAllowed == null) { ++ countDownLatch.countDown(); ++ } else { ++ if (decision == Decision.BLOCKED) { ++ if (expectedBlocked != null) { ++ expectedBlocked.remove(url); ++ } ++ } else { ++ if (expectedAllowed != null) { ++ expectedAllowed.remove(url); ++ } ++ } ++ boolean expectationsMet = (expectedAllowed == null || expectedAllowed.isEmpty()) ++ && (expectedBlocked == null || expectedBlocked.isEmpty()); ++ if (expectationsMet) { ++ countDownLatch.countDown(); ++ } ++ } ++ } ++ } ++ ++ private URL mTestSubscriptionUrl; ++ List blockedInfos = new CopyOnWriteArrayList<>(); ++ List allowedInfos = new CopyOnWriteArrayList<>(); ++ List allowedPageInfos = new CopyOnWriteArrayList<>(); ++ List blockedPopupsInfos = new CopyOnWriteArrayList<>(); ++ List allowedPopupsInfos = new CopyOnWriteArrayList<>(); ++ CountDownLatch countDownLatch; ++ Set expectedAllowed; ++ Set expectedBlocked; ++}; +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java +@@ -0,0 +1,90 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.DOMUtils; ++import org.chromium.content_public.browser.test.util.JavaScriptUtils; ++ ++import java.lang.Thread; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesCircumventionTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyCircumventionInlineStyleNotImportant() ++ throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT ++ + "inline-style-important"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 2, "div"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyCircumventionAnonymousFrameDocumentWrite() ++ throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT ++ + "anoniframe-documentwrite"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[data-expectedresult='fail']"); ++ String numHidden = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mHelper.getWebContents(), ++ "var hiddenCount = 0;" ++ + "var elements = document.getElementById(\"write\").contentWindow.document.getElementsByTagName(\"span\");" ++ + "for (let i = 0; i < elements.length; ++i) {" ++ + " if (window.getComputedStyle(elements[i]).display == \"none\") ++hiddenCount;" ++ + "}" ++ + "hiddenCount;"); ++ Assert.assertEquals("1", numHidden); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java +@@ -0,0 +1,136 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesCspTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testCspAllSites() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter("*$csp=script-src 'none'"); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_all"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "img[id='all-sites-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testCspSpecificSite() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "img[id='specific-site-fail-1']", IncludeSubframes.NO); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testCspSpecificSiteFrameSrc() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("||%s^$csp=frame-src 'self'", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div[id='sub-frame-error']", IncludeSubframes.NO); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div[id='sub-frame-error-details']", IncludeSubframes.NO); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testCspException() throws TimeoutException, InterruptedException { ++ // Blocking filter: ++ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ // Resource loaded by JS was blocked ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div[id='unblock-javascript'] > img"); ++ ++ // Allowing filter: ++ mHelper.addCustomFilter( ++ String.format("@@||%s^$csp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ // Resource loaded by JS was allowed ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[id='unblock-javascript'] > img"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testCspGenericBlockException() throws TimeoutException, InterruptedException { ++ // Blocking filter: ++ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ // Resource loaded by JS was blocked ++ mHelper.loadUrl( ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div[id='genericblock-javascript'] > img"); ++ ++ // Allowing filter: ++ mHelper.addCustomFilter( ++ String.format("@@||%s^$genericblock", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ // Resource loaded by JS was allowed ++ mHelper.loadUrl( ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[id='genericblock-javascript'] > img"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java +@@ -0,0 +1,158 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesElemhideEmuInvTest { ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT ++ + "element-hiding-emulation-inversion"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotAbpProperties() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#.ehei-properties:not(:-abp-properties(width: 238px))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='basic-not-abp-properties-usage-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotAbpHas() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#.ehei-has:not(:-abp-has(span.ehei-has-not-hide))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='basic-not-abp-has-usage-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotAbpContains() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#.ehei-contains:not(span:-abp-contains(example-content))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='basic-not-abp-contains-usage-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotChained() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#.ehei-chained-parent:not(:-abp-has(> div:-abp-properties(width: 198px)))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, ++ "div[id='chained-extended-selectors-with-not-selector-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotCaseIsensitive() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#?#.ehei-case:not(:-abp-properties(WiDtH: 209px))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, ++ "div[id='case-insensitive-extended-selectors-with-not-selector-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotWildcard() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#?#.ehei-wildcard:not(:-abp-properties(cursor:*))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, ++ "div[id='wildcard-in-extended-selector-combined-with-not-selector-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotRegexAbpProperties() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#.ehei-regex:not(:-abp-properties(/width: 11[1-5]px;/))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-not-abp-properties-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-not-abp-properties-fail-2']"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, ".ehei-regex3"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuNotRegexAbpContains() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#.ehei-contains-regex:not(span:-abp-contains(/example-contentregex\\d/))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='regular-expression-in-not-abp-contains-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='regular-expression-in-not-abp-contains-fail-2']"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 2, ".ehei-contains-regex"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java +@@ -0,0 +1,217 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesElemhideEmuTest { ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding-emulation"; ++ public static final String ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL = ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "element-hiding"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicAbpProperties() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#div:-abp-properties(width: 213px)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='basic-abp-properties-usage-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicAbpHas() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#div:-abp-has(>div>span.ehe-abp-has)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='basic-abp-has-usage-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicHas() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#div:has(>div>span.ehe-has)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ // "Basic :has() usage" are duplicated on testpage. ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "div[id='basic-has-usage-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicAbpContains() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#?#span:-abp-contains(ehe-contains-target)", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='basic-abp-contains-usage-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicXpath() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#span:xpath(//*[@id=\"basic-xpath-usage-fail\"])", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='basic-xpath-usage-fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersBasicHasText() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#span:has-text(ehe-has-text)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "span[id='basic-has-text-usage-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersChainedExtendedSelectors() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#div:-abp-has(> div:-abp-properties(width: 214px))", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='chained-extended-selectors-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersCaseInsensitiveExtendedSelectors() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#div:-abp-properties(WiDtH: 215px)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='case-insensitive-extended-selectors-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersWildcardInExtendedSelector() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#?#div:-abp-properties(cursor:*)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='wildcard-in-extended-selector-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersRegularExpressionInAbpProperties() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#?#div:-abp-properties(/width: 12[1-5]px;/)", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-abp-properties-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-abp-properties-fail-2']"); ++ // "Not a target" div is not hidden, does not match regular expression. ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[class='testcase-examplecontent ehe-regex3']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersRegularExpressionInAbpContains() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#?#div > div:-abp-contains(/ehe-containsregex\\d/)", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-abp-contains-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='regular-expression-in-abp-contains-fail-2']"); ++ } ++ ++ // Exceptions: ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideEmuFiltersException() throws TimeoutException, InterruptedException { ++ // Add a blocking filter, verify element hidden. ++ mHelper.addCustomFilter( ++ String.format("%s##.testcase-ehe", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='exception-usage-pass-1']"); ++ ++ // Add exception filter, verify element no longer hidden. ++ mHelper.addCustomFilter( ++ String.format("%s#@#.testcase-ehe", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[id='exception-usage-pass-1']"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java +@@ -0,0 +1,237 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesElemhideTest { ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String ELEMENT_HIDING_TESTPAGES_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding"; ++ public static final String ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL = ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "elemhide"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersIdSelector() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s###eh-id", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='eh-id']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersIdSelectorDoubleCurlyBraces() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s##div[id='{{eh-id}}']", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='{{eh-id}}']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersClassSelector() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s##.eh-class", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-class']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersDescendantSelector() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##.testcase-area > .eh-descendant", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-descendant']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersSiblingSelector() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s##.testcase-examplecontent + .eh-sibling", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-sibling']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersAttributeSelector1() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##div[height=\"100\"][width=\"100\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='attribute-selector-1-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersAttributeSelector2() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s##div[href=\"http://testcase-attribute.com/\"]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='attribute-selector-2-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersAttributeSelector3() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##div[style=\"width: 200px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='attribute-selector-3-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersStartsWithSelector1() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s##div[href^=\"http://testcase-startswith.com/\"]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='starts-with-selector-1-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersStartsWithSelector2() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##div[style^=\"width: 201px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='starts-with-selector-2-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersEndsWithSelector1() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##div[style$=\"width: 202px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='ends-with-selector-1-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersContains() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s##div[style*=\"width: 203px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='contains-fail-1']"); ++ } ++ ++ // Exceptions: ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersBasicException() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s##.ex-elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/elemhide/basic/*", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); ++ // No exceptions added yet, both objects should be blocked. ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "img[id='basic-usage-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[id='basic-usage-pass-1']"); ++ // Add exception filter and reload. ++ mHelper.addCustomFilter(String.format( ++ "@@%s/en/exceptions/elemhide$elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); ++ // Image should remain blocked, div should be unblocked. ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "img[id='basic-usage-fail-1']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[id='basic-usage-area'] > div[id='basic-usage-pass-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testElemHideFiltersIframeException() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s##.targ-elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/elemhide/iframe/*.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img[id='iframe-fail-1']"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='iframe-pass-1']"); ++ ++ // Add exception filter and reload. ++ mHelper.addCustomFilter(String.format( ++ "@@%s/en/exceptions/elemhide$elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img[id='iframe-fail-1']"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "div[id='iframe-pass-1']"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java +@@ -0,0 +1,244 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.task.PostTask; ++import org.chromium.base.task.TaskTraits; ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.DOMUtils; ++import org.chromium.content_public.browser.test.util.JavaScriptUtils; ++import org.chromium.content_public.common.ContentSwitches; ++ ++import java.lang.Thread; ++import java.util.Arrays; ++import java.util.HashSet; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesExceptionTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyImageExceptions() throws TimeoutException, InterruptedException { ++ final String subdomainImage = String.format( ++ "https://allowed.subdomain.%s/testfiles/image_exception/subdomain.png", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN); ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "image"); ++ Assert.assertEquals(2, mHelper.numAllowed()); ++ Assert.assertEquals(2, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue(mHelper.isAllowed(subdomainImage)); ++ Assert.assertTrue(mHelper.isAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image_exception/image.png")); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 2, "img"); ++ String numImages = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mHelper.getWebContents(), "document.getElementsByTagName(\"img\").length;"); ++ Assert.assertEquals("2", numImages); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ @CommandLineFlags.Add(ContentSwitches.DISABLE_POPUP_BLOCKING) ++ public void testVerifyPopupException() throws TimeoutException, InterruptedException { ++ final String POPUP_TESTACE_URL = ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "popup"; ++ mHelper.loadUrl(POPUP_TESTACE_URL); ++ Assert.assertEquals(1, mHelper.getTabCount()); ++ final CallbackHelper tabsLoadedWaiter = mHelper.getTabsOpenedAndLoadedWaiter(); ++ PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> { ++ try { ++ String numElements = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mHelper.getWebContents(), ++ "var elements = document.getElementsByClassName(\"testcase-trigger\");" ++ + "for (let i = 0; i < elements.length; ++i) {" ++ + " elements[i].click();" ++ + "}" ++ + "elements.length;"); ++ Assert.assertEquals("3", numElements); ++ } catch (TimeoutException e) { ++ Assert.assertEquals("Popups were triggered", "Popups were NOT triggered"); ++ } ++ }); ++ // Wait for three tab loaded events ++ tabsLoadedWaiter.waitForCallback( ++ 0, 3, TestPagesTestsHelper.TEST_TIMEOUT_SEC, TimeUnit.SECONDS); ++ Assert.assertEquals(4, mHelper.getTabCount()); ++ Assert.assertEquals(3, mHelper.numAllowedPopups()); ++ Assert.assertTrue(mHelper.isPopupAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup_exception/link.html")); ++ Assert.assertTrue(mHelper.isPopupAllowed(TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "popup_exception/script-window.html")); ++ Assert.assertTrue(mHelper.isPopupAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup_exception/script-tab.html")); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifySubdocumentException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "subdocument"); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertTrue(mHelper.isAllowed(TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "subdocument_exception/subdocument.html")); ++ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "exception-target"); ++ String numFrames = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mHelper.getWebContents(), "window.frames.length;"); ++ Assert.assertEquals("1", numFrames); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "iframe"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyScriptException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "script"); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertTrue(mHelper.isAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script_exception/script.js")); ++ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "script-target"); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script_exception/image.png")); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyStylesheetException() throws TimeoutException, InterruptedException { ++ final String allowedUrl = TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "stylesheet_exception/stylesheet.cs"; ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(allowedUrl))); ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "stylesheet"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertTrue(mHelper.isAllowed(allowedUrl)); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "stylesheet_exception/image.png")); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img"); ++ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "exception-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyXHRException() throws TimeoutException, InterruptedException { ++ final String allowedUrl = ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest_exception/text.txt"; ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(allowedUrl))); ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertTrue(mHelper.isAllowed(allowedUrl)); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyGenericBlockException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "genericblock"); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "genericblock/specific.png")); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "img[data-expectedresult='pass']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyGenericHideException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "generichide"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[data-expectedresult='pass']"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyDocumentException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document"); ++ Assert.assertTrue(mHelper.isAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "document/image.png")); ++ Assert.assertTrue(mHelper.isPageAllowed( ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document")); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyWebSocketException() throws TimeoutException, InterruptedException { ++ final String wssUrl = ++ String.format("wss://%s/websocket", TestPagesTestsHelper.TESTPAGES_DOMAIN); ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(wssUrl))); ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "websocket"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET)); ++ Assert.assertTrue(mHelper.isAllowed(wssUrl)); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java +@@ -0,0 +1,329 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.task.PostTask; ++import org.chromium.base.task.TaskTraits; ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.browser.tab.Tab; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; ++import org.chromium.content_public.browser.test.util.DOMUtils; ++import org.chromium.content_public.browser.test.util.JavaScriptUtils; ++import org.chromium.content_public.common.ContentSwitches; ++ ++import java.lang.Thread; ++import java.util.Arrays; ++import java.util.HashSet; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesFilterTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testBlockingFilters() throws TimeoutException, InterruptedException { ++ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations( ++ new HashSet<>(Arrays.asList( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/full-path.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "blocking/partial-path/partial-path.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "blocking/wildcard/1/wildcard.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "blocking/wildcard/2/wildcard.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/dynamic.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/subdomain.png")), ++ null); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "blocking"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(6, mHelper.numBlocked()); ++ Assert.assertEquals(6, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 6, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyScriptFilters() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "script"); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script/script.js")); ++ ++ String childCount = ++ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(), ++ "document.getElementById(\"script-target\").childElementCount"); ++ Assert.assertEquals("1", childCount); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyImageFilters() throws TimeoutException, InterruptedException { ++ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations( ++ new HashSet<>(Arrays.asList( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/static/static.png", ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT ++ + "image/dynamic/dynamic.png")), ++ null); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "image"); ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(2, mHelper.numBlocked()); ++ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/static/static.png")); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/dynamic/dynamic.png")); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyStylesheetFilters() throws TimeoutException, InterruptedException { ++ final String blockedUrl = ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "stylesheet/stylesheet.cs"; ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(blockedUrl)), null); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "stylesheet"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals( ++ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET)); ++ Assert.assertTrue(mHelper.isBlocked(blockedUrl)); ++ String value = DOMUtils.getNodeContents(mHelper.getWebContents(), "stylesheet-target"); ++ Assert.assertEquals("Passed. Stylesheet was blocked.", value); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ @CommandLineFlags.Add(ContentSwitches.DISABLE_POPUP_BLOCKING) ++ public void testVerifyPopupFilters() throws TimeoutException, InterruptedException { ++ final String POPUP_TESTACE_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "popup"; ++ mHelper.loadUrl(POPUP_TESTACE_URL); ++ Assert.assertEquals(1, mHelper.getTabCount()); ++ final CallbackHelper tabsOpenedAndClosedWaiter = mHelper.getTabsOpenedAndClosedWaiter(); ++ // Trigger popups which open and close when blocked ++ PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> { ++ try { ++ String numElements = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mHelper.getWebContents(), ++ "var elements = document.getElementsByClassName(\"testcase-trigger\");" ++ + "for (let i = 0; i < elements.length; ++i) {" ++ + " elements[i].click();" ++ + "}" ++ + "elements.length;"); ++ Assert.assertEquals("3", numElements); ++ } catch (TimeoutException e) { ++ Assert.assertEquals("Popups were triggered", "Popups were NOT triggered"); ++ } ++ }); ++ // Wait for three tab open events and three close tabs events ++ tabsOpenedAndClosedWaiter.waitForCallback( ++ 0, 6, TestPagesTestsHelper.TEST_TIMEOUT_SEC, TimeUnit.SECONDS); ++ Assert.assertEquals(3, mHelper.numBlockedPopups()); ++ Assert.assertTrue(mHelper.isPopupBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/link.html")); ++ Assert.assertTrue(mHelper.isPopupBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/script-window.html")); ++ Assert.assertTrue(mHelper.isPopupBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/script-tab.html")); ++ Assert.assertEquals(1, mHelper.getTabCount()); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyXHRFilters() throws TimeoutException, InterruptedException { ++ final String blockedUrl = ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest/text.txt"; ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(blockedUrl)), null); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals( ++ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_XMLHTTPREQUEST)); ++ Assert.assertTrue(mHelper.isBlocked(blockedUrl)); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifySubdocumentFilters() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "subdocument"); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals( ++ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SUBDOCUMENT)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "subdocument/subdocument.html")); ++ // Do not search for iframe within the site's iframes. ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "iframe[data-expectedresult='fail']", IncludeSubframes.NO); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ @DisabledTest(message = "Please enable again when rewrite filters will be supported") ++ public void testVerifyRewrite() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite"); ++ Assert.assertEquals(3, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); ++ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_MEDIA)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/audio.mp3")); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/video.mp4")); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/script.js")); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyMatchCaseFilter() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "match-case"); ++ Assert.assertEquals(2, mHelper.numBlocked()); ++ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyThirdPartyFilter() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "third-party"); ++ Assert.assertEquals(2, mHelper.numBlocked()); ++ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "img[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 2, "img[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyOtherFilter() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "other"); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_OTHER)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "other/image.png")); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyDomainFilter() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "domain"); ++ Assert.assertEquals(2, mHelper.numBlocked()); ++ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "domain/static/target/image.png")); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "domain/dynamic/image.png")); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "img[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyPingFilter() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "ping"); ++ // Ping action not yet triggered ++ Assert.assertEquals(0, mHelper.numBlocked()); ++ final CountDownLatch countDownLatch = new CountDownLatch(1); ++ mHelper.setOnAdMatchedLatch(countDownLatch); ++ // Trigger ping action ++ final Tab tab = ++ mActivityTestRule.getActivity().getTabModelSelectorSupplier().get().getCurrentTab(); ++ JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ tab.getWebContents(), "document.getElementById(\"script-ping-trigger\").click()"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyPingFilterException() throws TimeoutException, InterruptedException { ++ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "ping"); ++ // Ping action not yet triggered ++ Assert.assertEquals(0, mHelper.numAllowed()); ++ final CountDownLatch countDownLatch = new CountDownLatch(1); ++ mHelper.setOnAdMatchedLatch(countDownLatch); ++ // Trigger ping action ++ final Tab tab = ++ mActivityTestRule.getActivity().getTabModelSelectorSupplier().get().getCurrentTab(); ++ JavaScriptUtils.executeJavaScriptAndWaitForResult(tab.getWebContents(), ++ "document.getElementsByClassName(\"testcase-trigger\")[0].click()"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertEquals(0, mHelper.numBlocked()); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java +@@ -0,0 +1,150 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesHeaderFilterTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String HEADER_TESTPAGES_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "header"; ++ public static final String HEADER_EXCEPTIONS_TESTPAGES_URL = ++ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "header"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHeaderFilterScript() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("||%s/testfiles/header/$header=content-type=application/javascript", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); ++ Assert.assertTrue(mHelper.isBlocked(String.format( ++ "https://%s/testfiles/header/script.js", TestPagesTestsHelper.TESTPAGES_DOMAIN))); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, ++ "div#functionproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHeaderFilterImage() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("||%s/testfiles/header/image.png$header=content-type=image/png", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue(mHelper.isBlocked(String.format( ++ "https://%s/testfiles/header/image.png", TestPagesTestsHelper.TESTPAGES_DOMAIN))); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "img[id='image-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHeaderFilterImageAndComma() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("||%s/testfiles/header/image2.png$header=date=\\x2c", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue(mHelper.isBlocked(String.format( ++ "https://%s/testfiles/header/image2.png", TestPagesTestsHelper.TESTPAGES_DOMAIN))); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "img[id='comma-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHeaderFilterStylesheet() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("||%s/testfiles/header/$header=content-type=text/css", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals( ++ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET)); ++ Assert.assertTrue( ++ mHelper.isBlocked(String.format("https://%s/testfiles/header/stylesheet.css", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN))); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHeaderFilterException() throws TimeoutException, InterruptedException { ++ // Add blocking filter, expect blocked image ++ mHelper.addCustomFilter( ++ String.format("||%s/testfiles/header_exception/$header=content-type=image/png", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "img[id='image-header-exception-pass-1']"); ++ ++ // Add exception filter, expect image allowed ++ mHelper.addCustomFilter(String.format( ++ "@@%s/testfiles/header_exception/$header", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); ++ Assert.assertTrue( ++ mHelper.isAllowed(String.format("https://%s/testfiles/header_exception/image.png", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN))); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "img[id='image-header-exception-pass-1']"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java +@@ -0,0 +1,185 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.JavaScriptUtils; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesRewriteTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String REWRITE_TEST_URL = ++ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteScript() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.js$rewrite=abp-resource:blank-js,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "div[id='script-fail-1']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteStylesheet() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.css$rewrite=abp-resource:blank-css,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "stylesheet-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteSubdocument() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.html$rewrite=abp-resource:blank-html,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "subdocument-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteText() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.txt$rewrite=abp-resource:blank-text,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "text-status"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteGif() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/1x1.gif$rewrite=abp-resource:1x1-transparent-gif,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "1x1-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewrite2x2Png() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/2x2.png$rewrite=abp-resource:2x2-transparent-png,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "2x2-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewrite3x2Png() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/3x2.png$rewrite=abp-resource:3x2-transparent-png,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "3x2-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewrite32x32Png() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/32x32.png$rewrite=abp-resource:32x32-transparent-png,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "32x32-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteAudio() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.mp3$rewrite=abp-resource:blank-mp3,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getCurrentTab() ++ .getWebContents(), ++ "document.getElementById('audio-area').lastChild.getAttribute('data-expectedresult')"); ++ Assert.assertEquals("\"pass\"", value); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testRewriteVideo() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/rewrite/*.mp4$rewrite=abp-resource:blank-mp4,domain=%s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrl(REWRITE_TEST_URL); ++ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult( ++ mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getCurrentTab() ++ .getWebContents(), ++ "document.getElementById('video-area').lastChild.getAttribute('data-expectedresult')"); ++ Assert.assertEquals("\"pass\"", value); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java +@@ -0,0 +1,82 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesSiteKeyTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifySitekeyException() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#@#[data-adblockkey]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter( ++ String.format("%s##.testcase-sitekey-eh", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/sitekey/outofframe.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter(String.format( ++ "||%s/testfiles/sitekey/inframe.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.addCustomFilter( ++ "@@$document,sitekey=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANGtTstne7e8MbmDHDiMFkGbcuBgXmiVesGOG3gtYeM1EkrzVhBjGUvKXYE4GLFwqty3v5MuWWbvItUWBTYoVVsCAwEAAQ"); ++ mHelper.loadUrl(TestPagesTestsHelper.SITEKEY_TESTPAGES_TESTCASES_ROOT); ++ Assert.assertEquals(1, mHelper.numBlocked()); ++ Assert.assertTrue(mHelper.isBlocked( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "sitekey/outofframe.png")); ++ Assert.assertEquals(1, mHelper.numAllowed()); ++ Assert.assertTrue(mHelper.isAllowed( ++ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "sitekey/inframe.png")); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java +@@ -0,0 +1,545 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.DisabledTest; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesSnippetsTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ public static final String SNIPPETS_TESTPAGES_TESTCASES_ROOT = ++ TestPagesTestsHelper.TESTPAGES_TESTCASES_ROOT + "snippets/"; ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortCurrentInlineScriptBasic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-current-inline-script console.group", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); ++ // All "Abort" snippets cancel creation of the target div, so it won't be hidden - it will ++ // not exist in DOM. Therefore we verify it's not displayed instead of verifying it's ++ // hidden. ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortCurrentInlineScriptSearch() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#abort-current-inline-script console.info acis-search", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#search-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortCurrentInlineScriptRegex() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#abort-current-inline-script console.warn '/acis-regex[1-2]/'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#regex-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyReadBasic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#abort-on-property-read aoprb", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyReadSubProperty() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#abort-on-property-read aopr.sp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyReadFunctionProperty() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#abort-on-property-read aoprf.fp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, ++ "div#functionproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyWriteBasic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-property-write window.aopwb", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyWriteSubProperty() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-property-write window.aopwsp", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnPropertyWriteFunctionProperty() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#abort-on-property-write aopwf.fp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, ++ "div#functionproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyReadBasic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoiprb", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyReadSubProperty() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr.sp", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyReadMultipleProperties() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr1 aoipr2", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, ++ "div#multipleproperties-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyWriteBasic() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipwb", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyWriteSubProperty() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw.sp", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testAbortOnIframePropertyWriteMultipleProperties() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw1 aoipw2", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, ++ "div#multipleproperties-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsStatic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-static' p[id]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-static-id"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsDynamic() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-dynamic' p[id]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-dynamic-id"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsSearch() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-search' p[id] .target", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#search2-target > p.target"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#search1-target > p[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsRegex() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains /hic-regex-[2-3]/ p[id]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); ++ // "hic-regex-1" does not match regex, should remain displayed. ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "p#hic-regex-1"); ++ ++ // "hic-regex-2" and "hic-regex-2" do match regex, should be hidden. ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-regex-2"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-regex-3"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsFrame() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains hidden span#frame-target", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "span#frame-target"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsAndMatchesStyleStatic() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-contains-and-matches-style hicamss div[id] span.label /./ 'display: inline;'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-and-matches-style"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#static-usage-area > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#static-usage-area > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsAndMatchesStyleDynamic() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-contains-and-matches-style hicamsd div[id] span.label /./ 'display: inline;'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-and-matches-style"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#dynamic-target > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#dynamic-target > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsImage() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-contains-image /^89504e470d0a1a0a0000000d4948445200000064000000640802/ div[shouldhide] div", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-image"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsVisibleTextBasicUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-basic '#parent-basic > .article' '#parent-basic > .article .label'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-visible-text"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#parent-basic > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfContainsVisibleTextContentUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-content '#parent-content > .article' '#parent-content > .article .label'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-visible-text"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#parent-content > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfHasAndMatchesStyleBasicUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-has-and-matches-style a[href=\"#basic-target-ad\"] div[id] span.label /./ 'display: inline;'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-has-and-matches-style"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfHasAndMatchesStyleLegitElements() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-has-and-matches-style a[href=\"#comments-target-ad\"] div[id] span.label ';' /\\\\bdisplay:\\ inline\\;/", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-has-and-matches-style"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#comments-target > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfLabeledBy() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format( ++ "%s#$#hide-if-labelled-by 'Label' '#hilb-target [aria-labelledby]' '#hilb-target'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-labelled-by"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfMatchesXPathBasicStaticUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-matches-xpath //*[@id=\"isnfnv\"]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, ++ "div#basic-static-usage-area > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, ++ "div#basic-static-usage-area > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfMatchesXPathClassUsage() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#hide-if-matches-xpath //*[@class=\"to-be-hidden\"]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#class-usage-area > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#class-usage-area > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfMatchesXPathIdStartsWith() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#hide-if-matches-xpath //div[starts-with(@id,\"fail\")]", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); ++ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, ++ "div#hide-if-id-starts-with-area > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, ++ "div#hide-if-id-starts-with-area > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfShadowContainsBasicUsage() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#hide-if-shadow-contains 'hisc-basic' p", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#basic-target > p[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testHideIfShadowContainsRegexUsage() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#hide-if-shadow-contains '/hisc-regex[1-2]/' div", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 2, "div#regex-target > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#regex-target > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testJsonPrune() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#json-prune 'data-expectedresult jsonprune aria-label'", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "json-prune?delay=100"); ++ // The object does not get hidden, it no longer exists in the DOM. ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#testcase-area > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testOverridePropertyRead() throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#override-property-read overridePropertyRead.fp false", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "override-property-read"); ++ TestVerificationUtils.verifyHiddenCount( ++ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='fail']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testStripFetchQueryParameterBasicUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter(String.format("%s#$#strip-fetch-query-parameter basicBlocked %s", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "strip-fetch-query-parameter"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='pass']"); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testStripFetchQueryParameterOtherUsage() ++ throws TimeoutException, InterruptedException { ++ mHelper.addCustomFilter( ++ String.format("%s#$#strip-fetch-query-parameter otherAllowed2 other-domain", ++ TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ mHelper.loadUrlWaitForContent( ++ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "strip-fetch-query-parameter"); ++ TestVerificationUtils.verifyDisplayedCount( ++ mActivityTestRule, 2, "div#other-target > div[data-expectedresult='pass']"); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java +@@ -0,0 +1,255 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import org.junit.Assert; ++import org.junit.Rule; ++ ++import org.chromium.base.Log; ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.chrome.browser.tab.EmptyTabObserver; ++import org.chromium.chrome.browser.tab.Tab; ++import org.chromium.chrome.browser.tabmodel.TabModelObserver; ++import org.chromium.chrome.browser.tabmodel.TabModelSelector; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.WebContents; ++import org.chromium.content_public.browser.test.util.TestThreadUtils; ++import org.chromium.url.GURL; ++ ++import java.lang.Thread; ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++public class TestPagesTestsHelper { ++ public static final String TESTPAGES_DOMAIN = "abptestpages.org"; ++ public static final String TESTPAGES_BASE_URL = "https://" + TESTPAGES_DOMAIN; ++ public static final String TESTPAGES_TESTCASES_ROOT = TESTPAGES_BASE_URL + "/en/"; ++ public static final String FILTER_TESTPAGES_TESTCASES_ROOT = ++ TESTPAGES_TESTCASES_ROOT + "filters/"; ++ public static final String EXCEPTION_TESTPAGES_TESTCASES_ROOT = ++ TESTPAGES_TESTCASES_ROOT + "exceptions/"; ++ public static final String CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT = ++ TESTPAGES_TESTCASES_ROOT + "circumvention/"; ++ public static final String SITEKEY_TESTPAGES_TESTCASES_ROOT = ++ EXCEPTION_TESTPAGES_TESTCASES_ROOT + "sitekey"; ++ public static final String SNIPPETS_TESTPAGES_TESTCASES_ROOT = ++ TESTPAGES_TESTCASES_ROOT + "snippets/"; ++ public static final String TESTPAGES_RESOURCES_ROOT = TESTPAGES_BASE_URL + "/testfiles/"; ++ public static final String TESTPAGES_SUBSCRIPTION = ++ TESTPAGES_TESTCASES_ROOT + "/abp-testcase-subscription.txt"; ++ ++ public static final int TEST_TIMEOUT_SEC = 30; ++ ++ private URL mTestSubscriptionUrl; ++ private CallbackHelper mHelper = new CallbackHelper(); ++ private TestAdBlockedObserver mObserver = new TestAdBlockedObserver(); ++ private TestSubscriptionUpdatedObserver mSubscriptionUpdateObserver = ++ new TestSubscriptionUpdatedObserver(); ++ private ChromeTabbedActivityTestRule mActivityTestRule; ++ ++ private class TestSubscriptionUpdatedObserver ++ implements AdblockController.SubscriptionUpdateObserver { ++ @Override ++ public void onSubscriptionDownloaded(final URL url) { ++ if (mTestSubscriptionUrl == null) return; ++ if (url.toString().contains(mTestSubscriptionUrl.toString())) { ++ Log.d("TestSubscriptionUpdatedObserver", ++ "Notify subscription updated: " + url.toString()); ++ mHelper.notifyCalled(); ++ } ++ } ++ } ++ ++ public void setUp(final ChromeTabbedActivityTestRule activityRule) { ++ mActivityTestRule = activityRule; ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ AdblockController.getInstance().addOnAdBlockedObserver(mObserver); ++ AdblockController.getInstance().addSubscriptionUpdateObserver( ++ mSubscriptionUpdateObserver); ++ }); ++ } ++ ++ public void addFilterList(final String filterListUrl) { ++ try { ++ mTestSubscriptionUrl = new URL(filterListUrl); ++ mObserver.setExpectedSubscriptionUrl(mTestSubscriptionUrl); ++ } catch (MalformedURLException e) { ++ } ++ Assert.assertNotNull("Test subscription url", mTestSubscriptionUrl); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ AdblockController.getInstance().installSubscription(mTestSubscriptionUrl); ++ }); ++ try { ++ mHelper.waitForCallback(0, 1, TEST_TIMEOUT_SEC, TimeUnit.SECONDS); ++ } catch (TimeoutException e) { ++ Assert.assertEquals( ++ "Test subscription was properly added", "Failed to add test subscription"); ++ } ++ } ++ ++ public void addCustomFilter(final String filter) { ++ TestThreadUtils.runOnUiThreadBlocking( ++ () -> { AdblockController.getInstance().addCustomFilter(filter); }); ++ } ++ ++ public void tearDown() { ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ AdblockController.getInstance().removeSubscriptionUpdateObserver( ++ mSubscriptionUpdateObserver); ++ AdblockController.getInstance().removeOnAdBlockedObserver(mObserver); ++ }); ++ } ++ ++ public CallbackHelper getTabsOpenedAndClosedWaiter() { ++ final CallbackHelper callbackHelper = new CallbackHelper(); ++ final TabModelSelector tabModelSelector = ++ mActivityTestRule.getActivity().getTabModelSelectorSupplier().get(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ tabModelSelector.getCurrentModel().addObserver(new TabModelObserver() { ++ @Override ++ public void onFinishingTabClosure(Tab tab) { ++ // For some reason TabModelObserver#tabRemoved() is not called. ++ // Let's wait a bit to make sure tab is indeed closed. ++ try { ++ Thread.sleep(100); ++ } catch (InterruptedException e) { ++ } ++ callbackHelper.notifyCalled(); ++ } ++ @Override ++ public void didAddTab( ++ Tab tab, int type, int creationState, boolean markedForSelection) { ++ callbackHelper.notifyCalled(); ++ } ++ }); ++ }); ++ return callbackHelper; ++ } ++ ++ public CallbackHelper getTabsOpenedAndLoadedWaiter() { ++ final CallbackHelper callbackHelper = new CallbackHelper(); ++ final TabModelSelector tabModelSelector = ++ mActivityTestRule.getActivity().getTabModelSelectorSupplier().get(); ++ TestThreadUtils.runOnUiThreadBlocking(() -> { ++ tabModelSelector.getCurrentModel().addObserver(new TabModelObserver() { ++ @Override ++ public void didAddTab( ++ Tab tab, int type, int creationState, boolean markedForSelection) { ++ tab.addObserver(new EmptyTabObserver() { ++ @Override ++ public void onPageLoadFinished(Tab tab, GURL url) { ++ callbackHelper.notifyCalled(); ++ } ++ }); ++ } ++ }); ++ }); ++ return callbackHelper; ++ } ++ ++ public WebContents getWebContents() { ++ return mActivityTestRule.getActivity().getCurrentWebContents(); ++ } ++ ++ public int getTabCount() { ++ return mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getTotalTabCount(); ++ } ++ ++ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations ++ public void setOnAdMatchedLatch(final CountDownLatch countDownLatch) { ++ Assert.assertTrue( ++ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0); ++ mObserver.countDownLatch = countDownLatch; ++ } ++ ++ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations ++ public CountDownLatch setOnAdMatchedExpectations( ++ final Set onBlocked, final Set onAllowed) { ++ Assert.assertTrue( ++ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0); ++ mObserver.countDownLatch = new CountDownLatch(1); ++ mObserver.expectedBlocked = onBlocked; ++ mObserver.expectedAllowed = onAllowed; ++ return mObserver.countDownLatch; ++ } ++ ++ public boolean isBlocked(final String url) { ++ return mObserver.isBlocked(url); ++ } ++ ++ public boolean isPopupBlocked(final String url) { ++ return mObserver.isPopupBlocked(url); ++ } ++ ++ public int numBlockedByType(final AdblockContentType type) { ++ return mObserver.numBlockedByType(type); ++ } ++ ++ public int numBlockedPopups() { ++ return mObserver.numBlockedPopups(); ++ } ++ ++ public int numAllowedByType(final AdblockContentType type) { ++ return mObserver.numAllowedByType(type); ++ } ++ ++ public int numAllowedPopups() { ++ return mObserver.numAllowedPopups(); ++ } ++ ++ public boolean isAllowed(final String url) { ++ return mObserver.isAllowed(url); ++ } ++ ++ public boolean isPageAllowed(final String url) { ++ return mObserver.isPageAllowed(url); ++ } ++ ++ public boolean isPopupAllowed(final String url) { ++ return mObserver.isPopupAllowed(url); ++ } ++ ++ public void loadUrl(final String url) throws InterruptedException, TimeoutException { ++ mActivityTestRule.loadUrl(url, TEST_TIMEOUT_SEC); ++ } ++ ++ public void loadUrlWaitForContent(final String url) ++ throws InterruptedException, TimeoutException { ++ loadUrl(url); ++ TestVerificationUtils.verifyCondition(mActivityTestRule, ++ "document.getElementsByClassName('testcase-waiting-content').length == 0"); ++ } ++ ++ public int numBlocked() { ++ return mObserver.blockedInfos.size(); ++ } ++ ++ public int numAllowed() { ++ return mObserver.allowedInfos.size(); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java +@@ -0,0 +1,77 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.filters.LargeTest; ++ ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++ ++import java.util.Arrays; ++import java.util.HashSet; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class TestPagesWebsocketTest { ++ @Rule ++ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); ++ ++ @Before ++ public void setUp() { ++ mHelper.setUp(mActivityTestRule); ++ mHelper.addCustomFilter( ++ String.format("$websocket,domain=%s", TestPagesTestsHelper.TESTPAGES_DOMAIN)); ++ } ++ ++ @After ++ public void tearDown() { ++ mHelper.tearDown(); ++ } ++ ++ @Test ++ @LargeTest ++ @Feature({"adblock"}) ++ public void testVerifyWebsocketFilter() throws TimeoutException, InterruptedException { ++ final String wssUrl = ++ String.format("wss://%s/websocket", TestPagesTestsHelper.TESTPAGES_DOMAIN); ++ final CountDownLatch countDownLatch = ++ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(wssUrl)), null); ++ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "websocket"); ++ // Wait with 10 seconds max timeout ++ countDownLatch.await(10, TimeUnit.SECONDS); ++ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET)); ++ Assert.assertTrue(mHelper.isBlocked(wssUrl)); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java +@@ -0,0 +1,166 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import org.junit.Assert; ++ ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.content_public.browser.test.util.JavaScriptUtils; ++ ++import java.util.concurrent.TimeoutException; ++ ++public class TestVerificationUtils { ++ public enum IncludeSubframes { ++ YES, ++ NO, ++ } ++ ++ private static final String STATUS_OK = "\"OK\""; ++ ++ private static final String MATCHES_HIDDEN_FUNCTION = "let matches = function(element) {" ++ + " return window.getComputedStyle(element).display == \"none\";" ++ + "}"; ++ ++ private static final String MATCHES_DISPLAYED_FUNCTION = "let matches = function(element) {" ++ + " return window.getComputedStyle(element).display != \"none\";" ++ + "}"; ++ ++ private static final String COUNT_ELEMENT_FUNCTION = ++ "let countElements = function(selector, includeSubframes) {" ++ + " let count = 0;" ++ + " for (let element of document.querySelectorAll(selector)) {" ++ + " if (matches(element))" ++ + " ++count;" ++ + " }" ++ + " if (includeSubframes) {" ++ + " for (let frame of document.querySelectorAll(\"iframe\")) {" ++ + " for (let element of frame.contentWindow.document.body.querySelectorAll(selector)) {" ++ + " if (matches(element))" ++ + " ++count;" ++ + " }" ++ + " }" ++ + " }" ++ + " return count;" ++ + "}"; ++ ++ private static final String WAIT_FOR_COUNT_FUNCTION_WRAPPER = "(function () {" ++ + "%s\n" // matches() defintion placeholder ++ + "%s\n" // countElements() defintion placeholder ++ + "%s\n" // WAIT_FUNCTION placeholder which calls countElements() as a predicate ++ + "}());"; ++ ++ // Poll every 100 ms until condition is met or 10 seconds timeout occurs ++ private static final String WAIT_FUNCTION = "let repeat = 100;" ++ + "const id = setInterval(() => {" ++ + " --repeat;" ++ + " if (%s) {" // predicate placeholder ++ + " clearInterval(id);" ++ + " domAutomationController.send('OK');" ++ + " } else if (repeat == 0) {" ++ + " clearInterval(id);" ++ + " domAutomationController.send('Timeout');" ++ + " }" ++ + "}, 100);"; ++ ++ private static void verifyMatchesCount(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final int num, final String matchesFunction, final String selector, ++ IncludeSubframes includeSubframes) throws TimeoutException { ++ final String boolIncludeSubframes = ++ includeSubframes == IncludeSubframes.YES ? "true" : "false"; ++ final String predicate = String.format( ++ "countElements(\"%s\", %s) == %d", selector, boolIncludeSubframes, num); ++ final String waitFunction = String.format(WAIT_FUNCTION, predicate); ++ final String js = String.format(WAIT_FOR_COUNT_FUNCTION_WRAPPER, matchesFunction, ++ COUNT_ELEMENT_FUNCTION, waitFunction); ++ final String result = ++ JavaScriptUtils.runJavascriptWithAsyncResult(mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getCurrentTab() ++ .getWebContents(), ++ js); ++ Assert.assertEquals(STATUS_OK, result); ++ } ++ ++ public static void verifyHiddenCount(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final int num, final String selector) throws TimeoutException { ++ verifyHiddenCount(mActivityTestRule, num, selector, IncludeSubframes.YES); ++ } ++ ++ public static void verifyHiddenCount(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final int num, final String selector, final IncludeSubframes includeSubframes) ++ throws TimeoutException { ++ verifyMatchesCount( ++ mActivityTestRule, num, MATCHES_HIDDEN_FUNCTION, selector, includeSubframes); ++ } ++ ++ public static void verifyDisplayedCount(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final int num, final String selector) throws TimeoutException { ++ verifyDisplayedCount(mActivityTestRule, num, selector, IncludeSubframes.YES); ++ } ++ ++ public static void verifyDisplayedCount(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final int num, final String selector, final IncludeSubframes includeSubframes) ++ throws TimeoutException { ++ verifyMatchesCount( ++ mActivityTestRule, num, MATCHES_DISPLAYED_FUNCTION, selector, includeSubframes); ++ } ++ ++ public static void verifyCondition(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final String predicate) throws TimeoutException { ++ final String waitFunction = String.format(WAIT_FUNCTION, predicate); ++ Assert.assertEquals(STATUS_OK, ++ JavaScriptUtils.runJavascriptWithAsyncResult(mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getCurrentTab() ++ .getWebContents(), ++ waitFunction)); ++ } ++ ++ public static void verifyGreenBackground(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final String elemId) throws TimeoutException { ++ verifyCondition(mActivityTestRule, ++ "window.getComputedStyle(document.getElementById('" + elemId ++ + "')).backgroundColor == 'rgb(13, 199, 75)'"); ++ } ++ ++ // For some cases it is better to rely on page script testing element ++ // rather than invent a specific script to check condition. For example ++ // checks for rewrite filters replaces content proper way. ++ public static void verifySelfTestPass(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final String elemId) throws TimeoutException { ++ verifyCondition(mActivityTestRule, ++ "document.getElementById('" + elemId ++ + "').getAttribute('data-expectedresult') == 'pass'"); ++ } ++ ++ public static void expectResourceBlocked(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final String elemId) throws TimeoutException { ++ verifyCondition(mActivityTestRule, ++ "window.getComputedStyle(document.getElementById('" + elemId ++ + "')).display == 'none'"); ++ } ++ ++ public static void expectResourceShown(final ChromeTabbedActivityTestRule mActivityTestRule, ++ final String elemId) throws TimeoutException { ++ verifyCondition(mActivityTestRule, ++ "window.getComputedStyle(document.getElementById('" + elemId ++ + "')).display == 'inline'"); ++ } ++} +-- +2.25.1 diff --git a/build/patches/eyeo-beta-114.0.5735.53-v1-android_settings.patch b/build/patches/eyeo-117.0.5938.0-android_settings.patch similarity index 93% rename from build/patches/eyeo-beta-114.0.5735.53-v1-android_settings.patch rename to build/patches/eyeo-117.0.5938.0-android_settings.patch index f19a6216..7abac6e0 100644 --- a/build/patches/eyeo-beta-114.0.5735.53-v1-android_settings.patch +++ b/build/patches/eyeo-117.0.5938.0-android_settings.patch @@ -1,13 +1,13 @@ -From: vanilla-chromium-builder -Date: Fri, 26 May 2023 09:20:36 +0000 -Subject: Eyeo Chromium SDK Android Settings UI Patch +From: chromium-sdk +Date: Mon, 21 Aug 2023 18:20:45 +0200 +Subject: eyeo Browser Ad filtering Solution: Android Settings UI Module -Based on Chromium 114.0.5735.53 +Based on Chromium 117.0.5938.0 -Pre-requisites: Eyeo Chromium SDK Base Patch +Pre-requisites: eyeo Browser Ad filtering Solution: Base Module and Android API Module --- - .../android/java/res/xml/main_preferences.xml | 18 +- - components/adblock/android/BUILD.gn | 53 ++++ + .../android/java/res/xml/main_preferences.xml | 14 +- + components/adblock/android/BUILD.gn | 55 ++++ components/adblock/android/README.md | 13 + .../adblock/android/adblock_strings.grd | 238 ++++++++++++++++++ .../fragment_adblock_custom_item_add.png | Bin 0 -> 490 bytes @@ -39,6 +39,9 @@ Pre-requisites: Eyeo Chromium SDK Base Patch .../settings/AdblockFilterListsFragment.java | 54 ++++ .../settings/AdblockMoreOptionsFragment.java | 34 +++ .../settings/AdblockSettingsFragment.java | 137 ++++++++++ + .../adblock/AdblockFilterFragmentTest.java | 73 ++++++ + .../adblock/AdblockPopupInfoBarTest.java | 129 ++++++++++ + .../adblock/AdblockPopupMessageTest.java | 112 +++++++++ .../translations/adblock_strings_af.xtb | 4 + .../translations/adblock_strings_am.xtb | 13 + .../translations/adblock_strings_ar.xtb | 13 + @@ -119,7 +122,7 @@ Pre-requisites: Eyeo Chromium SDK Base Patch .../translations/adblock_strings_zh-HK.xtb | 4 + .../translations/adblock_strings_zh-TW.xtb | 13 + .../translations/adblock_strings_zu.xtb | 4 + - 113 files changed, 2126 insertions(+), 5 deletions(-) + 116 files changed, 2440 insertions(+), 3 deletions(-) create mode 100644 components/adblock/android/README.md create mode 100644 components/adblock/android/adblock_strings.grd create mode 100644 components/adblock/android/java/res/drawable-hdpi/fragment_adblock_custom_item_add.png @@ -151,6 +154,9 @@ Pre-requisites: Eyeo Chromium SDK Base Patch create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsFragment.java create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockMoreOptionsFragment.java create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java create mode 100644 components/adblock/android/translations/adblock_strings_af.xtb create mode 100644 components/adblock/android/translations/adblock_strings_am.xtb create mode 100644 components/adblock/android/translations/adblock_strings_ar.xtb @@ -245,9 +251,9 @@ diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/j --> + - +@@ -114,17 +122,17 @@ found in the LICENSE file. . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.InstrumentationRegistry; ++import androidx.test.rule.ActivityTestRule; ++ ++import androidx.test.filters.SmallTest; ++ ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.Log; ++import org.chromium.base.test.util.ApplicationTestUtils; ++import org.chromium.base.test.util.CallbackHelper; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.browser.settings.SettingsActivityTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.components.adblock.settings.AdblockFilterListsFragment; ++import org.chromium.content_public.browser.test.util.TestThreadUtils; ++ ++import java.net.URL; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class AdblockFilterFragmentTest { ++ @Rule ++ public final ChromeTabbedActivityTestRule mActivityTestRule = ++ new ChromeTabbedActivityTestRule(); ++ @Rule ++ public SettingsActivityTestRule mTestRule = ++ new SettingsActivityTestRule<>(AdblockFilterListsFragment.class); ++ ++ @Before ++ public void setUp() throws Exception { ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ mTestRule.startSettingsActivity(); ++ ApplicationTestUtils.finishActivity(mTestRule.getActivity()); ++ } ++ ++ @Test ++ @SmallTest ++ @Feature({"adblock"}) ++ public void testLanguageFiltersNotEmpty() { ++ mTestRule.startSettingsActivity(); ++ AdblockFilterListsFragment fragment = mTestRule.getFragment(); ++ Assert.assertNotNull(fragment); ++ Assert.assertNotEquals(0, fragment.getListView().getCount()); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java +@@ -0,0 +1,129 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.InstrumentationRegistry; ++import androidx.test.filters.MediumTest; ++ ++import org.hamcrest.Matchers; ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.task.PostTask; ++import org.chromium.base.task.TaskTraits; ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Criteria; ++import org.chromium.base.test.util.CriteriaHelper; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeFeatureList; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.browser.infobar.InfoBarIdentifier; ++import org.chromium.chrome.browser.tabmodel.TabModelSelector; ++import org.chromium.chrome.test.ChromeBrowserTestRule; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.chrome.test.util.browser.Features.DisableFeatures; ++import org.chromium.components.infobars.InfoBar; ++import org.chromium.net.test.EmbeddedTestServer; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++// NOTE: Messages feature had to be disabled when testing infobars ++// https://gitlab.com/eyeo/adblockplus/abpchromium/-/commit/a617caaa5692630f73d967a55d86bf52cc491ad5 ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++@DisableFeatures({ChromeFeatureList.MESSAGES_FOR_ANDROID_INFRASTRUCTURE}) ++public class AdblockPopupInfoBarTest { ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ ++ private static final String POPUP_HTML_PATH = "/chrome/test/data/android/popup_test.html"; ++ ++ private String mPopupHtmlUrl; ++ private EmbeddedTestServer mTestServer; ++ ++ @Before ++ public void setUp() throws Exception { ++ // Create a new temporary instance to ensure the Class is loaded. Otherwise we will get a ++ // ClassNotFoundException when trying to instantiate during startup. ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ ++ PostTask.runOrPostTask( ++ TaskTraits.UI_DEFAULT, () -> Assert.assertTrue(getNumInfobarsShowing() == 0)); ++ ++ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); ++ mPopupHtmlUrl = mTestServer.getURL(POPUP_HTML_PATH); ++ } ++ ++ @After ++ public void tearDown() { ++ mTestServer.stopAndDestroyServer(); ++ } ++ ++ private int getNumInfobarsShowing() { ++ return mActivityTestRule.getInfoBars().size(); ++ } ++ ++ public int getTabCount() { ++ return mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getTotalTabCount(); ++ } ++ ++ @Test ++ @MediumTest ++ @Feature({"adblock"}) ++ public void popUpBlockedInfoBarVisibleWhenAbpEnabled() throws InterruptedException { ++ mActivityTestRule.loadUrl(mPopupHtmlUrl); ++ Assert.assertEquals(1, getTabCount()); ++ CriteriaHelper.pollUiThread(() -> { ++ Criteria.checkThat(getNumInfobarsShowing(), Matchers.is(1)); ++ InfoBar frontInfoBar = mActivityTestRule.getInfoBars().get(0); ++ Criteria.checkThat("Invalid infobar type shown", frontInfoBar.getInfoBarIdentifier(), ++ Matchers.is(InfoBarIdentifier.POPUP_BLOCKED_INFOBAR_DELEGATE_MOBILE)); ++ }); ++ } ++ ++ @Test ++ @MediumTest ++ @CommandLineFlags.Add({"disable-adblock"}) ++ @Feature({"adblock"}) ++ public void popUpBlockedInfoBarVisibleWhenAbpDisabled() { ++ mActivityTestRule.loadUrl(mPopupHtmlUrl); ++ Assert.assertEquals(1, getTabCount()); ++ CriteriaHelper.pollUiThread(() -> { ++ Criteria.checkThat(getNumInfobarsShowing(), Matchers.is(1)); ++ InfoBar frontInfoBar = mActivityTestRule.getInfoBars().get(0); ++ Criteria.checkThat("Invalid infobar type shown", frontInfoBar.getInfoBarIdentifier(), ++ Matchers.is(InfoBarIdentifier.POPUP_BLOCKED_INFOBAR_DELEGATE_MOBILE)); ++ }); ++ } ++} +diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java +new file mode 100644 +--- /dev/null ++++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java +@@ -0,0 +1,112 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++package org.chromium.components.adblock; ++ ++import androidx.test.InstrumentationRegistry; ++import androidx.test.filters.MediumTest; ++ ++import org.hamcrest.Matchers; ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Rule; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++ ++import org.chromium.base.test.util.CommandLineFlags; ++import org.chromium.base.test.util.Criteria; ++import org.chromium.base.test.util.CriteriaHelper; ++import org.chromium.base.test.util.Feature; ++import org.chromium.chrome.browser.flags.ChromeSwitches; ++import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ++import org.chromium.chrome.test.ChromeTabbedActivityTestRule; ++import org.chromium.components.messages.MessagesTestHelper; ++import org.chromium.net.test.EmbeddedTestServer; ++ ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++ ++@RunWith(ChromeJUnit4ClassRunner.class) ++@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) ++public class AdblockPopupMessageTest { ++ @Rule ++ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); ++ ++ private static final String POPUP_HTML_PATH = "/chrome/test/data/android/popup_test.html"; ++ ++ private String mPopupHtmlUrl; ++ private EmbeddedTestServer mTestServer; ++ ++ @Before ++ public void setUp() throws Exception { ++ // Create a new temporary instance to ensure the Class is loaded. Otherwise we will get a ++ // ClassNotFoundException when trying to instantiate during startup. ++ mActivityTestRule.startMainActivityOnBlankPage(); ++ ++ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); ++ mPopupHtmlUrl = mTestServer.getURL(POPUP_HTML_PATH); ++ } ++ ++ @After ++ public void tearDown() { ++ mTestServer.stopAndDestroyServer(); ++ } ++ ++ public int getTabCount() { ++ return mActivityTestRule.getActivity() ++ .getTabModelSelectorSupplier() ++ .get() ++ .getTotalTabCount(); ++ } ++ ++ @Test ++ @MediumTest ++ @Feature({"adblock"}) ++ public void popUpBlockedMessageVisibleWhenAbpEnabled() throws InterruptedException { ++ mActivityTestRule.loadUrl(mPopupHtmlUrl); ++ Assert.assertEquals(1, getTabCount()); ++ ++ CriteriaHelper.pollUiThread(() -> { ++ Criteria.checkThat(MessagesTestHelper.getMessageCount( ++ mActivityTestRule.getActivity().getWindowAndroid()), ++ Matchers.is(1)); ++ }); ++ } ++ ++ @Test ++ @MediumTest ++ @CommandLineFlags.Add({"disable-adblock"}) ++ @Feature({"adblock"}) ++ public void popUpBlockedMessageVisibleWhenAbpDisabled() { ++ mActivityTestRule.loadUrl(mPopupHtmlUrl); ++ Assert.assertEquals(1, getTabCount()); ++ ++ CriteriaHelper.pollUiThread(() -> { ++ Criteria.checkThat(MessagesTestHelper.getMessageCount( ++ mActivityTestRule.getActivity().getWindowAndroid()), ++ Matchers.is(1)); ++ }); ++ } ++} diff --git a/components/adblock/android/translations/adblock_strings_af.xtb b/components/adblock/android/translations/adblock_strings_af.xtb new file mode 100644 --- /dev/null diff --git a/build/patches/eyeo-beta-114.0.5735.53-v1-base.patch b/build/patches/eyeo-117.0.5938.0-base.patch similarity index 84% rename from build/patches/eyeo-beta-114.0.5735.53-v1-base.patch rename to build/patches/eyeo-117.0.5938.0-base.patch index 73899e8d..528d7932 100644 --- a/build/patches/eyeo-beta-114.0.5735.53-v1-base.patch +++ b/build/patches/eyeo-117.0.5938.0-base.patch @@ -1,185 +1,55 @@ -From: vanilla-chromium-builder -Date: Fri, 26 May 2023 09:20:35 +0000 -Subject: Eyeo Chromium SDK Base Patch +From: chromium-sdk +Date: Mon, 21 Aug 2023 18:20:40 +0200 +Subject: eyeo Browser Ad filtering Solution: Base Module -Based on Chromium 114.0.5735.53 +Based on Chromium 117.0.5938.0 --- DEPS | 22 + LICENSE | 15 + README.md | 12 + base/trace_event/builtin_categories.h | 5 + - chrome/android/BUILD.gn | 9 + - chrome/app/chrome_main_delegate.cc | 7 +- - chrome/browser/BUILD.gn | 38 + - chrome/browser/adblock/README.md | 3 + - .../adblock/adblock_content_browser_client.cc | 374 +++ - .../adblock/adblock_content_browser_client.h | 111 + - ...adblock_content_browser_client_unittest.cc | 198 ++ - .../adblock/adblock_controller_factory.cc | 110 + - .../adblock/adblock_controller_factory.h | 52 + - .../adblock_telemetry_service_factory.cc | 127 + - .../adblock_telemetry_service_factory.h | 56 + - ...ontent_security_policy_injector_factory.cc | 69 + - ...content_security_policy_injector_factory.h | 49 + - .../browser/adblock/element_hider_factory.cc | 63 + - .../browser/adblock/element_hider_factory.h | 47 + - .../resource_classification_runner_factory.cc | 71 + - .../resource_classification_runner_factory.h | 49 + - .../browser/adblock/session_stats_factory.cc | 64 + - .../browser/adblock/session_stats_factory.h | 47 + - .../adblock/sitekey_storage_factory.cc | 59 + - .../browser/adblock/sitekey_storage_factory.h | 47 + - ...ubscription_persistent_metadata_factory.cc | 63 + - ...subscription_persistent_metadata_factory.h | 49 + - .../adblock/subscription_service_factory.cc | 216 ++ - .../adblock/subscription_service_factory.h | 63 + - ...lock_content_browser_client_browsertest.cc | 122 + - .../test/adblock_debug_url_browsertest.cc | 301 +++ - .../test/adblock_filter_list_browsertest.cc | 236 ++ - ...ck_filtering_configurations_browsertest.cc | 358 +++ - ...ock_frame_hierarchy_builder_browsertest.cc | 310 +++ - .../test/adblock_multiple_tabs_browsertest.cc | 156 ++ - .../test/adblock_non_ascii_browsertest.cc | 77 + - ...dblock_subscription_service_browsertest.cc | 204 ++ - .../adblock_telemetry_service_browsertest.cc | 256 ++ - .../test/adblock_web_bundle_browsertest.cc | 553 ++++ - chrome/browser/android/adblock/adblock_jni.cc | 211 ++ - chrome/browser/android/adblock/adblock_jni.h | 53 + - .../android/adblock/adblock_jni_factory.cc | 72 + - .../android/adblock/adblock_jni_factory.h | 50 + - .../filtering_configuration_bindings.cc | 250 ++ - .../filtering_configuration_bindings.h | 69 + - ...iltering_configuration_bindings_factory.cc | 70 + - ...filtering_configuration_bindings_factory.h | 51 + - ...source_classification_notifier_bindings.cc | 181 ++ - ...esource_classification_notifier_bindings.h | 66 + - ...lassification_notifier_bindings_factory.cc | 71 + - ...classification_notifier_bindings_factory.h | 52 + - .../client_hints/client_hints_browsertest.cc | 10 +- - chrome/browser/net/errorpage_browsertest.cc | 8 + - ..._page_load_metrics_observer_browsertest.cc | 7 +- - chrome/browser/preferences/BUILD.gn | 5 + - .../prefs/chrome_pref_service_factory.cc | 11 + - ...hrome_browser_main_extra_parts_profiles.cc | 33 + - .../profile_keyed_service_browsertest.cc | 17 +- - .../safe_browsing_blocking_page_test.cc | 8 +- - ...subresource_filter_browser_test_harness.cc | 8 +- - chrome/browser/ui/BUILD.gn | 5 + - chrome/browser/ui/prefs/pref_watcher.cc | 13 + - chrome/browser/ui/tab_helpers.cc | 19 + - chrome/common/BUILD.gn | 3 + - chrome/test/BUILD.gn | 24 + - chrome/test/base/chrome_test_launcher.cc | 7 +- - chrome/test/base/in_process_browser_test.cc | 17 +- - .../filterlist_that_allows_resource.txt | 7 + - .../filterlist_that_blocks_resource.txt | 6 + - .../filterlist_that_hides_resource.txt | 6 + - chrome/test/data/adblock/innermost_frame.html | 20 + - chrome/test/data/adblock/middle_frame.html | 8 + - chrome/test/data/adblock/non-ascii.html | 9 + - chrome/test/data/adblock/outermost_frame.html | 20 + - chrome/test/data/adblock/popup.html | 8 + - chrome/test/data/adblock/popup_opener.html | 8 + - chrome/test/data/adblock/popup_parent.html | 8 + - chrome/test/data/adblock/resource.png | Bin 0 -> 47293 bytes - chrome/test/data/adblock/tab-restore.html | 16 + - chrome/test/data/adblock/wbn/LICENSE | 14 + - .../data/adblock/wbn/blocked_bundle/LICENSE | 14 + - .../fetch_result_1_blocked_bundle.json | 1 + - .../fetch_result_2_blocked_bundle.json | 1 + - .../data/adblock/wbn/by_bundle_file/LICENSE | 14 + - .../fetch_result_2_subresource_loading.json | 1 + - .../green_subresource_loading.css | 1 + - .../green_subresource_loading.png | Bin 0 -> 772 bytes - .../purple_subresource_loading.css | 1 + - .../purple_subresource_loading.png | Bin 0 -> 773 bytes - .../xhr_result_2_subresource_loading.json | 1 + - .../test/data/adblock/wbn/by_resource/LICENSE | 14 + - .../by_resource/blue_subresource_loading.css | 1 + - .../by_resource/blue_subresource_loading.png | Bin 0 -> 773 bytes - .../fetch_result_1_subresource_loading.json | 1 + - .../by_resource/red_subresource_loading.css | 1 + - .../by_resource/red_subresource_loading.png | Bin 0 -> 772 bytes - .../xhr_result_1_subresource_loading.json | 1 + - chrome/test/data/adblock/wbn/by_scope/LICENSE | 14 + - .../fetch_result_3_subresource_loading.json | 1 + - .../by_scope/orange_subresource_loading.css | 1 + - .../by_scope/orange_subresource_loading.png | Bin 0 -> 774 bytes - .../wbn/by_scope/pink_subresource_loading.css | 1 + - .../wbn/by_scope/pink_subresource_loading.png | Bin 0 -> 775 bytes - .../xhr_result_3_subresource_loading.json | 1 + - .../test/data/adblock/wbn/index.html.mustache | 181 ++ - .../wbn/uuid_in_package_by_resource/LICENSE | 14 + - .../index.html.mustache | 45 + - .../skyblue_subresource_loading.css | 1 + - .../skyblue_subresource_loading.png | Bin 0 -> 775 bytes - .../yellowgreen_subresource_loading.css | 1 + - .../yellowgreen_subresource_loading.png | Bin 0 -> 775 bytes - .../wbn/uuid_in_package_by_scope/LICENSE | 14 + - .../index.html.mustache | 42 + - .../navy_subresource_loading.css | 1 + - .../navy_subresource_loading.png | Bin 0 -> 774 bytes - .../orangered_subresource_loading.css | 1 + - .../orangered_subresource_loading.png | Bin 0 -> 774 bytes + build/install-build-deps.py | 10 +- components/BUILD.gn | 15 + - components/adblock/CHANGELOG.md | 593 +++++ + components/adblock/CHANGELOG.md | 611 ++++ components/adblock/LICENSE | 674 +++++ components/adblock/README.md | 80 + - components/adblock/android/BUILD.gn | 112 + - .../adblock_settings_locales_titles.xml | 98 + - .../adblock/AdblockContentType.java | 62 + - .../components/adblock/AdblockController.java | 267 ++ - .../components/adblock/AdblockCounters.java | 86 + - .../adblock/FilteringConfiguration.java | 245 ++ - .../ResourceClassificationNotifier.java | 186 ++ - .../adblock/AdblockControllerTest.java | 87 + - .../adblock/AdblockFilterFragmentTest.java | 73 + - .../adblock/AdblockPopupInfoBarTest.java | 127 + - .../adblock/AdblockPopupMessageTest.java | 110 + - .../adblock/FilteringConfigurationTest.java | 366 +++ - .../ResourceClassificationNotifierTest.java | 143 + - .../adblock/TestAdBlockedObserver.java | 183 ++ - .../adblock/TestPagesCircumventionTest.java | 90 + - .../components/adblock/TestPagesCspTest.java | 136 + - .../adblock/TestPagesElemhideEmuInvTest.java | 158 ++ - .../adblock/TestPagesElemhideEmuTest.java | 217 ++ - .../adblock/TestPagesElemhideTest.java | 237 ++ - .../adblock/TestPagesExceptionTest.java | 229 ++ - .../adblock/TestPagesFilterTest.java | 311 +++ - .../adblock/TestPagesHeaderFilterTest.java | 150 ++ - .../adblock/TestPagesRewriteTest.java | 177 ++ - .../adblock/TestPagesSiteKeyTest.java | 82 + - .../adblock/TestPagesSnippetsTest.java | 545 ++++ - .../adblock/TestPagesTestsHelper.java | 201 ++ - .../adblock/TestPagesWebsocketTest.java | 77 + - .../adblock/TestVerificationUtils.java | 158 ++ components/adblock/content/BUILD.gn | 22 + - components/adblock/content/browser/BUILD.gn | 123 + + components/adblock/content/browser/BUILD.gn | 136 + + .../adblock_controller_factory_base.cc | 87 + + .../browser/adblock_controller_factory_base.h | 50 + .../content/browser/adblock_filter_match.h | 30 + - .../browser/adblock_url_loader_factory.cc | 688 +++++ + .../adblock_telemetry_service_factory_base.cc | 100 + + .../adblock_telemetry_service_factory_base.h | 57 + + .../browser/adblock_url_loader_factory.cc | 746 +++++ .../browser/adblock_url_loader_factory.h | 92 + .../adblock_url_loader_factory_for_test.cc | 372 +++ .../adblock_url_loader_factory_for_test.h | 70 + - .../browser/adblock_webcontents_observer.cc | 122 + - .../browser/adblock_webcontents_observer.h | 75 + + .../browser/adblock_webcontents_observer.cc | 187 ++ + .../browser/adblock_webcontents_observer.h | 85 + .../content_security_policy_injector.h | 61 + .../content_security_policy_injector_impl.cc | 125 + .../content_security_policy_injector_impl.h | 66 + .../adblock/content/browser/element_hider.h | 70 + - .../content/browser/element_hider_impl.cc | 303 +++ - .../content/browser/element_hider_impl.h | 62 + - .../browser/frame_hierarchy_builder.cc | 89 + + .../content/browser/element_hider_impl.cc | 305 ++ + .../content/browser/element_hider_impl.h | 55 + + .../content/browser/element_hider_info.cc | 37 + + .../content/browser/element_hider_info.h | 44 + + .../browser/frame_hierarchy_builder.cc | 117 + .../content/browser/frame_hierarchy_builder.h | 63 + - .../browser/resource_classification_runner.h | 105 + - .../resource_classification_runner_impl.cc | 429 +++ - .../resource_classification_runner_impl.h | 154 ++ - .../content/browser/session_stats_impl.cc | 83 + - .../content/browser/session_stats_impl.h | 68 + - .../test/adblock_url_loader_factory_test.cc | 349 +++ + .../content/browser/frame_opener_info.cc | 37 + + .../content/browser/frame_opener_info.h | 46 + + .../browser/resource_classification_runner.h | 113 + + .../resource_classification_runner_impl.cc | 451 +++ + .../resource_classification_runner_impl.h | 156 ++ + .../content/browser/session_stats_impl.cc | 86 + + .../content/browser/session_stats_impl.h | 71 + + .../subscription_service_factory_base.cc | 225 ++ + .../subscription_service_factory_base.h | 60 + + .../test/adblock_url_loader_factory_test.cc | 399 +++ .../test/adblock_webcontents_observer_test.cc | 159 ++ ...tent_security_policy_injector_impl_test.cc | 177 ++ - .../browser/test/element_hider_impl_test.cc | 347 +++ - .../test/frame_hierarchy_builder_test.cc | 154 ++ + .../browser/test/element_hider_impl_test.cc | 390 +++ + .../test/frame_hierarchy_builder_test.cc | 154 + ...dblock_content_security_policy_injector.cc | 28 + ...adblock_content_security_policy_injector.h | 44 + .../browser/test/mock_element_hider.cc | 26 + @@ -187,31 +57,31 @@ Based on Chromium 114.0.5735.53 .../test/mock_frame_hierarchy_builder.cc | 26 + .../test/mock_frame_hierarchy_builder.h | 49 + .../mock_resource_classification_runner.cc | 49 + - .../mock_resource_classification_runner.h | 96 + - ...esource_classification_runner_impl_test.cc | 387 +++ + .../mock_resource_classification_runner.h | 104 + + ...esource_classification_runner_impl_test.cc | 453 +++ .../browser/test/session_stats_impl_test.cc | 74 + components/adblock/core/BUILD.gn | 175 ++ - .../activeping_telemetry_topic_provider.cc | 242 ++ + .../activeping_telemetry_topic_provider.cc | 243 ++ .../activeping_telemetry_topic_provider.h | 84 + - components/adblock/core/adblock_controller.h | 100 + - .../adblock/core/adblock_controller_impl.cc | 342 +++ - .../adblock/core/adblock_controller_impl.h | 113 + + components/adblock/core/adblock_controller.h | 64 + + .../adblock/core/adblock_controller_impl.cc | 271 ++ + .../adblock/core/adblock_controller_impl.h | 95 + components/adblock/core/adblock_switches.cc | 26 + - components/adblock/core/adblock_switches.h | 30 + + components/adblock/core/adblock_switches.h | 29 + .../adblock/core/adblock_telemetry_service.cc | 244 ++ .../adblock/core/adblock_telemetry_service.h | 107 + components/adblock/core/classifier/BUILD.gn | 76 + .../core/classifier/resource_classifier.cc | 24 + - .../core/classifier/resource_classifier.h | 82 + - .../classifier/resource_classifier_impl.cc | 305 +++ - .../classifier/resource_classifier_impl.h | 59 + + .../core/classifier/resource_classifier.h | 90 + + .../classifier/resource_classifier_impl.cc | 404 +++ + .../classifier/resource_classifier_impl.h | 64 + .../test/mock_resource_classifier.cc | 26 + - .../test/mock_resource_classifier.h | 60 + - .../test/resource_classifier_impl_test.cc | 506 ++++ + .../test/mock_resource_classifier.h | 66 + + .../test/resource_classifier_impl_test.cc | 634 +++++ .../test/resource_classifier_perftest.cc | 235 ++ - components/adblock/core/common/BUILD.gn | 98 + - .../adblock/core/common/adblock_constants.cc | 154 ++ - .../adblock/core/common/adblock_constants.h | 41 + + components/adblock/core/common/BUILD.gn | 110 + + .../adblock/core/common/adblock_constants.cc | 164 ++ + .../adblock/core/common/adblock_constants.h | 48 + .../adblock/core/common/adblock_prefs.cc | 122 + .../adblock/core/common/adblock_prefs.h | 46 + .../adblock/core/common/adblock_utils.cc | 171 ++ @@ -228,10 +98,12 @@ Based on Chromium 114.0.5735.53 components/adblock/core/common/sitekey.h | 29 + .../core/common/test/adblock_utils_test.cc | 43 + .../core/common/test/flatbuffer_data_test.cc | 78 + - .../adblock/core/configuration/BUILD.gn | 57 + + .../adblock/core/configuration/BUILD.gn | 59 + .../configuration/filtering_configuration.h | 90 + - .../persistent_filtering_configuration.cc | 241 ++ - .../persistent_filtering_configuration.h | 81 + + .../filtering_configuration_prefs.cc | 33 + + .../filtering_configuration_prefs.h | 30 + + .../persistent_filtering_configuration.cc | 270 ++ + .../persistent_filtering_configuration.h | 86 + ...persistent_filtering_configuration_test.cc | 240 ++ .../test/fake_filtering_configuration.cc | 114 + .../test/fake_filtering_configuration.h | 66 + @@ -248,7 +120,7 @@ Based on Chromium 114.0.5735.53 .../core/converter/parser/domain_option.h | 59 + .../converter/parser/filter_classifier.cc | 39 + .../core/converter/parser/filter_classifier.h | 46 + - .../adblock/core/converter/parser/metadata.cc | 143 + + .../adblock/core/converter/parser/metadata.cc | 145 + .../adblock/core/converter/parser/metadata.h | 64 + .../core/converter/parser/snippet_filter.cc | 62 + .../core/converter/parser/snippet_filter.h | 46 + @@ -260,23 +132,23 @@ Based on Chromium 114.0.5735.53 .../parser/test/snippet_filter_test.cc | 78 + .../parser/test/snippet_tokenizer_test.cc | 141 + .../parser/test/url_filter_options_test.cc | 255 ++ - .../converter/parser/test/url_filter_test.cc | 149 ++ - .../core/converter/parser/url_filter.cc | 216 ++ + .../converter/parser/test/url_filter_test.cc | 149 + + .../core/converter/parser/url_filter.cc | 218 ++ .../core/converter/parser/url_filter.h | 48 + .../converter/parser/url_filter_options.cc | 263 ++ .../converter/parser/url_filter_options.h | 122 + .../core/converter/serializer/BUILD.gn | 50 + .../serializer/filter_keyword_extractor.cc | 63 + .../serializer/filter_keyword_extractor.h | 59 + - .../serializer/flatbuffer_serializer.cc | 396 +++ + .../serializer/flatbuffer_serializer.cc | 394 +++ .../serializer/flatbuffer_serializer.h | 129 + .../core/converter/serializer/serializer.h | 41 + .../test/filter_keyword_extractor_test.cc | 68 + .../test/flatbuffer_converter_perftest.cc | 64 + - .../test/flatbuffer_converter_test.cc | 2346 +++++++++++++++++ + .../test/flatbuffer_converter_test.cc | 2476 +++++++++++++++++ components/adblock/core/features.cc | 25 + components/adblock/core/features.h | 31 + - .../core/schema/filter_list_schema.fbs | 167 ++ + .../core/schema/filter_list_schema.fbs | 165 ++ components/adblock/core/session_stats.h | 42 + components/adblock/core/sitekey_storage.h | 53 + .../adblock/core/sitekey_storage_impl.cc | 146 + @@ -286,16 +158,16 @@ Based on Chromium 114.0.5735.53 .../core/subscription/domain_splitter.cc | 46 + .../core/subscription/domain_splitter.h | 45 + .../filtering_configuration_maintainer.h | 52 + - ...filtering_configuration_maintainer_impl.cc | 485 ++++ + ...filtering_configuration_maintainer_impl.cc | 489 ++++ .../filtering_configuration_maintainer_impl.h | 119 + .../subscription/installed_subscription.cc | 42 + .../subscription/installed_subscription.h | 138 + - .../installed_subscription_impl.cc | 569 ++++ - .../installed_subscription_impl.h | 150 ++ + .../installed_subscription_impl.cc | 552 ++++ + .../installed_subscription_impl.h | 150 + .../ongoing_subscription_request.h | 50 + .../ongoing_subscription_request_impl.cc | 191 ++ .../ongoing_subscription_request_impl.h | 75 + - .../core/subscription/pattern_matcher.cc | 261 ++ + .../core/subscription/pattern_matcher.cc | 266 ++ .../core/subscription/pattern_matcher.h | 34 + .../preloaded_subscription_provider.h | 56 + .../preloaded_subscription_provider_impl.cc | 121 + @@ -304,30 +176,30 @@ Based on Chromium 114.0.5735.53 .../adblock/core/subscription/regex_matcher.h | 74 + .../adblock/core/subscription/subscription.cc | 24 + .../adblock/core/subscription/subscription.h | 78 + - .../subscription/subscription_collection.h | 95 + - .../subscription_collection_impl.cc | 437 +++ - .../subscription_collection_impl.h | 92 + + .../subscription/subscription_collection.h | 99 + + .../subscription_collection_impl.cc | 353 +++ + .../subscription_collection_impl.h | 97 + .../core/subscription/subscription_config.cc | 320 +++ .../core/subscription/subscription_config.h | 121 + .../subscription/subscription_downloader.h | 66 + .../subscription_downloader_impl.cc | 289 ++ .../subscription_downloader_impl.h | 102 + .../subscription_persistent_metadata.h | 86 + - .../subscription_persistent_metadata_impl.cc | 170 ++ + .../subscription_persistent_metadata_impl.cc | 171 ++ .../subscription_persistent_metadata_impl.h | 62 + .../subscription_persistent_storage.h | 60 + .../subscription_persistent_storage_impl.cc | 229 ++ .../subscription_persistent_storage_impl.h | 80 + - .../core/subscription/subscription_service.h | 79 + - .../subscription/subscription_service_impl.cc | 191 ++ - .../subscription/subscription_service_impl.h | 91 + + .../core/subscription/subscription_service.h | 87 + + .../subscription/subscription_service_impl.cc | 211 ++ + .../subscription/subscription_service_impl.h | 97 + .../core/subscription/subscription_updater.h | 35 + .../subscription/subscription_updater_impl.cc | 65 + .../subscription/subscription_updater_impl.h | 52 + .../subscription/subscription_validator.h | 59 + .../subscription_validator_impl.cc | 145 + .../subscription_validator_impl.h | 53 + - ...ring_configuration_maintainer_impl_test.cc | 846 ++++++ + ...ring_configuration_maintainer_impl_test.cc | 900 ++++++ .../test/installed_subscription_impl_test.cc | 111 + .../test/load_gzipped_test_file.cc | 43 + .../test/load_gzipped_test_file.h | 35 + @@ -340,36 +212,36 @@ Based on Chromium 114.0.5735.53 .../subscription/test/mock_subscription.cc | 36 + .../subscription/test/mock_subscription.h | 51 + .../test/mock_subscription_collection.cc | 26 + - .../test/mock_subscription_collection.h | 96 + + .../test/mock_subscription_collection.h | 102 + .../test/mock_subscription_downloader.cc | 25 + .../test/mock_subscription_downloader.h | 48 + .../mock_subscription_persistent_metadata.cc | 27 + .../mock_subscription_persistent_metadata.h | 76 + .../test/mock_subscription_service.cc | 36 + - .../test/mock_subscription_service.h | 71 + + .../test/mock_subscription_service.h | 75 + .../test/mock_subscription_updater.cc | 25 + .../test/mock_subscription_updater.h | 38 + .../ongoing_subscription_request_impl_test.cc | 337 +++ .../test/pattern_matcher_perftest.cc | 69 + - .../subscription/test/pattern_matcher_test.cc | 340 +++ - ...eloaded_subscription_provider_impl_test.cc | 149 ++ + .../subscription/test/pattern_matcher_test.cc | 351 +++ + ...eloaded_subscription_provider_impl_test.cc | 149 + .../test/regex_matcher_perftest.cc | 83 + - .../test/subscription_collection_impl_test.cc | 1174 +++++++++ + .../test/subscription_collection_impl_test.cc | 1020 +++++++ .../test/subscription_downloader_impl_test.cc | 578 ++++ ...scription_persistent_metadata_impl_test.cc | 213 ++ ...bscription_persistent_storage_impl_test.cc | 342 +++ - .../test/subscription_service_impl_test.cc | 247 ++ + .../test/subscription_service_impl_test.cc | 275 ++ .../test/subscription_updater_impl_test.cc | 98 + .../test/subscription_validator_impl_test.cc | 252 ++ .../test/url_keyword_extractor_test.cc | 74 + .../subscription/url_keyword_extractor.cc | 68 + .../core/subscription/url_keyword_extractor.h | 61 + - ...ctiveping_telemetry_topic_provider_test.cc | 319 +++ - .../core/test/adblock_controller_impl_test.cc | 450 ++++ + ...ctiveping_telemetry_topic_provider_test.cc | 320 +++ + .../core/test/adblock_controller_impl_test.cc | 481 ++++ .../adblock_telemetry_service_unittest.cc | 376 +++ .../core/test/bundled_subscription_test.cc | 49 + .../core/test/mock_adblock_controller.cc | 26 + - .../core/test/mock_adblock_controller.h | 91 + + .../core/test/mock_adblock_controller.h | 71 + .../adblock/core/test/mock_sitekey_storage.cc | 26 + .../adblock/core/test/mock_sitekey_storage.h | 49 + .../core/test/sitekey_storage_impl_test.cc | 155 ++ @@ -395,22 +267,22 @@ Based on Chromium 114.0.5735.53 components/adblock/docs/developer-notes.md | 117 + .../adblock/docs/initialization-sequence.png | Bin 0 -> 129976 bytes .../adblock/docs/initialization-sequence.txt | 27 + - components/adblock/docs/integration-how-to.md | 220 ++ + components/adblock/docs/integration-how-to.md | 216 ++ components/adblock/docs/settings/README.md | 46 + .../docs/settings/user-setting-sequence.png | Bin 0 -> 61104 bytes .../docs/settings/user-setting-sequence.txt | 14 + - components/adblock/features.gni | 44 + + components/adblock/features.gni | 47 + components/resources/BUILD.gn | 9 + components/resources/adblock_resources.grdp | 26 + components/resources/adblocking/.gitignore | 1 + components/resources/adblocking/BUILD.gn | 70 + components/resources/adblocking/LICENSE | 14 + - components/resources/adblocking/anticv.txt.gz | Bin 0 -> 62367 bytes - .../resources/adblocking/easylist.txt.gz | Bin 0 -> 136086 bytes + components/resources/adblocking/anticv.txt.gz | Bin 0 -> 64073 bytes + .../resources/adblocking/easylist.txt.gz | Bin 0 -> 132650 bytes components/resources/adblocking/elemhide.js | 43 + .../adblocking/elemhide_for_selector.jst | 53 + .../resources/adblocking/elemhideemu.jst | 1436 ++++++++++ - .../adblocking/exceptionrules.txt.gz | Bin 0 -> 699295 bytes + .../adblocking/exceptionrules.txt.gz | Bin 0 -> 844912 bytes components/resources/adblocking/update.sh | 33 + components/resources/components_resources.grd | 6 + .../data/adblock/40_regex_patterns.txt.gz | Bin 0 -> 904 bytes @@ -426,7 +298,7 @@ Based on Chromium 114.0.5735.53 .../renderer_host/render_frame_host_impl.cc | 11 +- .../renderer_host/render_frame_host_impl.h | 8 + content/public/browser/render_frame_host.h | 7 + - content/public/common/isolated_world_ids.h | 6 + + content/public/common/isolated_world_ids.h | 8 + content/public/test/fake_local_frame.cc | 7 + content/public/test/fake_local_frame.h | 5 + ...web_request_proxying_url_loader_factory.cc | 5 + @@ -438,137 +310,18 @@ Based on Chromium 114.0.5735.53 .../core/frame/local_frame_mojo_handler.cc | 12 + .../core/frame/local_frame_mojo_handler.h | 5 + .../url_loader/mojo_url_loader_client.cc | 6 +- - .../definitions/adblock_private.d.ts | 191 ++ - .../definitions/eyeo_filtering_private.d.ts | 228 ++ - 436 files changed, 46719 insertions(+), 11 deletions(-) - create mode 100644 chrome/browser/adblock/README.md - create mode 100644 chrome/browser/adblock/adblock_content_browser_client.cc - create mode 100644 chrome/browser/adblock/adblock_content_browser_client.h - create mode 100644 chrome/browser/adblock/adblock_content_browser_client_unittest.cc - create mode 100644 chrome/browser/adblock/adblock_controller_factory.cc - create mode 100644 chrome/browser/adblock/adblock_controller_factory.h - create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.cc - create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.h - create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.cc - create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.h - create mode 100644 chrome/browser/adblock/element_hider_factory.cc - create mode 100644 chrome/browser/adblock/element_hider_factory.h - create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.cc - create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.h - create mode 100644 chrome/browser/adblock/session_stats_factory.cc - create mode 100644 chrome/browser/adblock/session_stats_factory.h - create mode 100644 chrome/browser/adblock/sitekey_storage_factory.cc - create mode 100644 chrome/browser/adblock/sitekey_storage_factory.h - create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.cc - create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.h - create mode 100644 chrome/browser/adblock/subscription_service_factory.cc - create mode 100644 chrome/browser/adblock/subscription_service_factory.h - create mode 100644 chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_debug_url_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_filter_list_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc - create mode 100644 chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc - create mode 100644 chrome/browser/android/adblock/adblock_jni.cc - create mode 100644 chrome/browser/android/adblock/adblock_jni.h - create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.cc - create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.h - create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings.cc - create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings.h - create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc - create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.h - create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings.cc - create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings.h - create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc - create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h - create mode 100644 chrome/test/data/adblock/filterlist_that_allows_resource.txt - create mode 100644 chrome/test/data/adblock/filterlist_that_blocks_resource.txt - create mode 100644 chrome/test/data/adblock/filterlist_that_hides_resource.txt - create mode 100644 chrome/test/data/adblock/innermost_frame.html - create mode 100644 chrome/test/data/adblock/middle_frame.html - create mode 100644 chrome/test/data/adblock/non-ascii.html - create mode 100644 chrome/test/data/adblock/outermost_frame.html - create mode 100644 chrome/test/data/adblock/popup.html - create mode 100644 chrome/test/data/adblock/popup_opener.html - create mode 100644 chrome/test/data/adblock/popup_parent.html - create mode 100644 chrome/test/data/adblock/resource.png - create mode 100644 chrome/test/data/adblock/tab-restore.html - create mode 100644 chrome/test/data/adblock/wbn/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json - create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/purple_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/purple_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/xhr_result_2_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/by_resource/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_resource/fetch_result_1_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/by_resource/red_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_resource/red_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_resource/xhr_result_1_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/by_scope/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_scope/pink_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/by_scope/pink_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json - create mode 100644 chrome/test/data/adblock/wbn/index.html.mustache - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/index.html.mustache - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/LICENSE - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/index.html.mustache - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.png - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.css - create mode 100644 chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.png + tools/gritsettings/resource_ids.spec | 8 + + 307 files changed, 36335 insertions(+), 4 deletions(-) create mode 100644 components/adblock/CHANGELOG.md create mode 100644 components/adblock/LICENSE create mode 100644 components/adblock/README.md - create mode 100644 components/adblock/android/BUILD.gn - create mode 100644 components/adblock/android/java/res/values/adblock_settings_locales_titles.xml - create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java - create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java - create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java - create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java - create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java - create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java create mode 100644 components/adblock/content/BUILD.gn create mode 100644 components/adblock/content/browser/BUILD.gn + create mode 100644 components/adblock/content/browser/adblock_controller_factory_base.cc + create mode 100644 components/adblock/content/browser/adblock_controller_factory_base.h create mode 100644 components/adblock/content/browser/adblock_filter_match.h + create mode 100644 components/adblock/content/browser/adblock_telemetry_service_factory_base.cc + create mode 100644 components/adblock/content/browser/adblock_telemetry_service_factory_base.h create mode 100644 components/adblock/content/browser/adblock_url_loader_factory.cc create mode 100644 components/adblock/content/browser/adblock_url_loader_factory.h create mode 100644 components/adblock/content/browser/adblock_url_loader_factory_for_test.cc @@ -581,13 +334,19 @@ Based on Chromium 114.0.5735.53 create mode 100644 components/adblock/content/browser/element_hider.h create mode 100644 components/adblock/content/browser/element_hider_impl.cc create mode 100644 components/adblock/content/browser/element_hider_impl.h + create mode 100644 components/adblock/content/browser/element_hider_info.cc + create mode 100644 components/adblock/content/browser/element_hider_info.h create mode 100644 components/adblock/content/browser/frame_hierarchy_builder.cc create mode 100644 components/adblock/content/browser/frame_hierarchy_builder.h + create mode 100644 components/adblock/content/browser/frame_opener_info.cc + create mode 100644 components/adblock/content/browser/frame_opener_info.h create mode 100644 components/adblock/content/browser/resource_classification_runner.h create mode 100644 components/adblock/content/browser/resource_classification_runner_impl.cc create mode 100644 components/adblock/content/browser/resource_classification_runner_impl.h create mode 100644 components/adblock/content/browser/session_stats_impl.cc create mode 100644 components/adblock/content/browser/session_stats_impl.h + create mode 100644 components/adblock/content/browser/subscription_service_factory_base.cc + create mode 100644 components/adblock/content/browser/subscription_service_factory_base.h create mode 100644 components/adblock/content/browser/test/adblock_url_loader_factory_test.cc create mode 100644 components/adblock/content/browser/test/adblock_webcontents_observer_test.cc create mode 100644 components/adblock/content/browser/test/content_security_policy_injector_impl_test.cc @@ -643,6 +402,8 @@ Based on Chromium 114.0.5735.53 create mode 100644 components/adblock/core/common/test/flatbuffer_data_test.cc create mode 100644 components/adblock/core/configuration/BUILD.gn create mode 100644 components/adblock/core/configuration/filtering_configuration.h + create mode 100644 components/adblock/core/configuration/filtering_configuration_prefs.cc + create mode 100644 components/adblock/core/configuration/filtering_configuration_prefs.h create mode 100644 components/adblock/core/configuration/persistent_filtering_configuration.cc create mode 100644 components/adblock/core/configuration/persistent_filtering_configuration.h create mode 100644 components/adblock/core/configuration/persistent_filtering_configuration_test.cc @@ -833,13 +594,11 @@ Based on Chromium 114.0.5735.53 create mode 100644 components/test/data/adblock/exceptionrules.txt.gz create mode 100644 components/test/data/adblock/longurl.txt.gz create mode 100644 components/test/data/adblock/random_shuf_100.tsv.sqlite - create mode 100644 tools/typescript/definitions/adblock_private.d.ts - create mode 100644 tools/typescript/definitions/eyeo_filtering_private.d.ts diff --git a/DEPS b/DEPS --- a/DEPS +++ b/DEPS -@@ -181,6 +181,10 @@ vars = { +@@ -182,6 +182,10 @@ vars = { # flag is set True. 'checkout_wpr_archives': False, @@ -850,7 +609,7 @@ diff --git a/DEPS b/DEPS # By default, do not check out WebKit for iOS, as it is not needed unless # running against ToT WebKit rather than system WebKit. This can be overridden # e.g. with custom_vars. -@@ -293,6 +297,8 @@ vars = { +@@ -296,6 +300,8 @@ vars = { 'download_libaom_testdata': False, 'android_git': 'https://android.googlesource.com', @@ -859,19 +618,19 @@ diff --git a/DEPS b/DEPS 'aomedia_git': 'https://aomedia.googlesource.com', 'boringssl_git': 'https://boringssl.googlesource.com', 'chrome_git': 'https://chrome-internal.googlesource.com', -@@ -508,6 +514,11 @@ vars = { +@@ -515,6 +521,11 @@ vars = { # and whatever else without interference from each other. - 'betocore_revision': '45756ea770c41085d5c71156b2c46da0b10117d6', + 'betocore_revision': 'b902b346037ea3f4aadf8177021f6f917b16e648', + # Three lines of non-changing comments so that + # the commit queue can handle CLs rolling feed + # and whatever else without interference from each other. -+ 'eyeo_snippets_revision': 'v0.6.1', ++ 'eyeo_snippets_revision': 'v0.7.0', + # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '055b2e17ae4f0e2c025ad0c7508b01787df17758', -@@ -822,6 +833,10 @@ deps = { + 'libcxx_revision': '84fb809dd6dae36d556dc0bb702c6cc2ce9d4b80', +@@ -841,6 +852,10 @@ deps = { 'condition': 'checkout_android and checkout_src_internal', }, @@ -880,9 +639,9 @@ diff --git a/DEPS b/DEPS + }, + 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '715769197cbe967605f24842ffcfb733d31b40fd', + 'url': Var('chromium_git') + '/website.git' + '@' + 'd1599568a4f463bb9e1bbccd9088f01d8ecafefc', }, -@@ -971,6 +986,13 @@ deps = { +@@ -990,6 +1005,13 @@ deps = { 'dep_type': 'cipd', }, @@ -959,8419 +718,33 @@ diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_ca X("FileSystem") \ X("file_system_provider") \ X("fledge") \ -diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn ---- a/chrome/android/BUILD.gn -+++ b/chrome/android/BUILD.gn -@@ -1,6 +1,10 @@ - # Copyright 2014 The Chromium Authors - # Use of this source code is governed by a BSD-style license that can be - # found in the LICENSE file. +diff --git a/build/install-build-deps.py b/build/install-build-deps.py +--- a/build/install-build-deps.py ++++ b/build/install-build-deps.py +@@ -8,6 +8,14 @@ + # including items requiring sudo privileges. + # See https://chromium.googlesource.com/chromium/src/+/main/docs/linux/build_instructions.md + ++# eyeo Chromium SDK is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. +# -+# This source code is a part of eyeo Chromium SDK. -+# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. -+ - - import("//build/android/resource_sizes.gni") - import("//build/config/android/config.gni") -@@ -205,6 +209,7 @@ if (current_toolchain == default_toolchain) { - "//chrome/browser/ui/android/toolbar:java_resources", - "//chrome/browser/ui/android/webid/internal:java_resources", - "//chrome/browser/ui/messages/android:java_resources", -+ "//components/adblock/android:java_resources", - "//components/autofill/android:autofill_java_resources", - "//components/autofill/android:autofill_payments_java_resources", - "//components/blocked_content/android:java_resources", -@@ -418,6 +423,7 @@ if (current_toolchain == default_toolchain) { - "//chrome/browser/webapps/android:java", - "//chrome/browser/webauthn/android:java", - "//chrome/browser/xsurface:java", -+ "//components/adblock/android:adblock_java", - "//components/autofill/android:autofill_java", - "//components/background_task_scheduler:background_task_scheduler_java", - "//components/background_task_scheduler:background_task_scheduler_task_ids_java", -@@ -1601,6 +1607,7 @@ if (current_toolchain == default_toolchain) { - "//chrome/test/android:chrome_java_integration_test_support", - "//chrome/test/android:chrome_java_test_pagecontroller", - "//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java", -+ "//components/adblock/android:adblock_java_tests", - "//components/autofill/android:autofill_features_java", - "//components/autofill/android:autofill_java", - "//components/background_task_scheduler:background_task_scheduler_java", -@@ -1792,6 +1799,7 @@ if (current_toolchain == default_toolchain) { - srcjar_deps = [ "//chrome/browser:tos_dialog_behavior_generated_enum" ] - - data = [ -+ "//chrome/test/data/adblock/", - "//chrome/test/data/android/", - "//chrome/test/data/autofill/", - "//chrome/test/data/background_sync/", -@@ -3502,6 +3510,7 @@ group("jni_headers") { - "//chrome/browser/ui/messages/android:jni_headers", - "//chrome/browser/util:jni_headers", - "//chrome/browser/webauthn/android:jni_headers", -+ "//components/adblock/android:jni_headers", - "//components/content_relationship_verification/android:jni_headers", - "//components/image_fetcher:jni_headers", - "//components/media_router/browser/android:jni_headers", -diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc ---- a/chrome/app/chrome_main_delegate.cc -+++ b/chrome/app/chrome_main_delegate.cc -@@ -1,6 +1,10 @@ - // Copyright 2012 The Chromium Authors - // Use of this source code is governed by a BSD-style license that can be - // found in the LICENSE file. -+// -+// This source code is a part of eyeo Chromium SDK. -+// Use of this source code is governed by the GPLv3 that can be found in the -+// components/adblock/LICENSE file. - - #include "chrome/app/chrome_main_delegate.h" - -@@ -40,6 +44,7 @@ - #include "base/trace_event/trace_event_impl.h" - #include "build/build_config.h" - #include "build/chromeos_buildflags.h" -+#include "chrome/browser/adblock/adblock_content_browser_client.h" - #include "chrome/browser/buildflags.h" - #include "chrome/browser/chrome_content_browser_client.h" - #include "chrome/browser/chrome_resource_bundle_helper.h" -@@ -1705,7 +1710,7 @@ content::ContentClient* ChromeMainDelegate::CreateContentClient() { - content::ContentBrowserClient* - ChromeMainDelegate::CreateContentBrowserClient() { - chrome_content_browser_client_ = -- std::make_unique(); -+ std::make_unique(); - return chrome_content_browser_client_.get(); - } - -diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn ---- a/chrome/browser/BUILD.gn -+++ b/chrome/browser/BUILD.gn -@@ -1,6 +1,9 @@ - # Copyright 2014 The Chromium Authors - # Use of this source code is governed by a BSD-style license that can be - # found in the LICENSE file. -+# -+# This source code is a part of eyeo Chromium SDK. -+# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. - - import("//base/allocator/allocator.gni") - import("//build/buildflag_header.gni") -@@ -158,6 +161,26 @@ static_library("browser") { - "accessibility/page_colors.h", - "accessibility/page_colors_factory.cc", - "accessibility/page_colors_factory.h", -+ "adblock/adblock_content_browser_client.cc", -+ "adblock/adblock_content_browser_client.h", -+ "adblock/adblock_controller_factory.cc", -+ "adblock/adblock_controller_factory.h", -+ "adblock/adblock_telemetry_service_factory.cc", -+ "adblock/adblock_telemetry_service_factory.h", -+ "adblock/content_security_policy_injector_factory.cc", -+ "adblock/content_security_policy_injector_factory.h", -+ "adblock/element_hider_factory.cc", -+ "adblock/element_hider_factory.h", -+ "adblock/resource_classification_runner_factory.cc", -+ "adblock/resource_classification_runner_factory.h", -+ "adblock/session_stats_factory.cc", -+ "adblock/session_stats_factory.h", -+ "adblock/sitekey_storage_factory.cc", -+ "adblock/sitekey_storage_factory.h", -+ "adblock/subscription_persistent_metadata_factory.cc", -+ "adblock/subscription_persistent_metadata_factory.h", -+ "adblock/subscription_service_factory.cc", -+ "adblock/subscription_service_factory.h", - "after_startup_task_utils.cc", - "after_startup_task_utils.h", - "app_mode/app_mode_utils.cc", -@@ -2063,6 +2086,8 @@ static_library("browser") { - "//chrome/installer/util:with_no_strings", - "//chrome/services/speech/buildflags", - "//chromeos/components/kiosk", -+ "//components/adblock/content:browser", -+ "//components/adblock/core/converter", - "//components/assist_ranker", - "//components/autofill/content/browser", - "//components/autofill/core/browser", -@@ -2586,6 +2611,18 @@ static_library("browser") { - if (is_android) { - sources += [ - "after_startup_task_utils_android.cc", -+ "android/adblock/adblock_jni.cc", -+ "android/adblock/adblock_jni.h", -+ "android/adblock/adblock_jni_factory.cc", -+ "android/adblock/adblock_jni_factory.h", -+ "android/adblock/filtering_configuration_bindings_factory.cc", -+ "android/adblock/filtering_configuration_bindings_factory.h", -+ "android/adblock/filtering_configuration_bindings.cc", -+ "android/adblock/filtering_configuration_bindings.h", -+ "android/adblock/resource_classification_notifier_bindings_factory.cc", -+ "android/adblock/resource_classification_notifier_bindings_factory.h", -+ "android/adblock/resource_classification_notifier_bindings.cc", -+ "android/adblock/resource_classification_notifier_bindings.h", - "android/android_theme_resources.h", - "android/autocomplete/tab_matcher_android.cc", - "android/autocomplete/tab_matcher_android.h", -@@ -3265,6 +3302,7 @@ static_library("browser") { - "webauthn/android/webauthn_request_delegate_android.cc", - "webauthn/android/webauthn_request_delegate_android.h", - ] -+ - public_deps += [ - "//chrome/android/features/dev_ui:buildflags", - "//components/image_fetcher/core", -diff --git a/chrome/browser/adblock/README.md b/chrome/browser/adblock/README.md -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/README.md -@@ -0,0 +1,3 @@ -+This folder contains the OS-agnostic, Chrome-specific source code of eyeo Chromium SDK. -+ -+For the full documentation, refer to [components/adblock](/components/adblock). -diff --git a/chrome/browser/adblock/adblock_content_browser_client.cc b/chrome/browser/adblock/adblock_content_browser_client.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_content_browser_client.cc -@@ -0,0 +1,374 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_content_browser_client.h" -+ -+#include "base/containers/unique_ptr_adapters.h" -+#include "base/ranges/algorithm.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/content_security_policy_injector_factory.h" -+#include "chrome/browser/adblock/element_hider_factory.h" -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/adblock/sitekey_storage_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser_navigator_params.h" -+#include "components/adblock/content/browser/adblock_url_loader_factory.h" -+#include "components/adblock/content/browser/resource_classification_runner.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_prefs.h" -+#include "components/adblock/core/configuration/filtering_configuration.h" -+#include "components/adblock/core/subscription/subscription_service.h" -+#include "components/embedder_support/user_agent_utils.h" -+#include "components/prefs/pref_service.h" -+#include "content/public/browser/browser_task_traits.h" -+#include "content/public/browser/browser_thread.h" -+#include "content/public/browser/render_frame_host.h" -+#include "content/public/browser/render_process_host.h" -+#include "content/public/browser/render_view_host.h" -+#include "content/public/browser/web_contents.h" -+#include "mojo/public/cpp/bindings/self_owned_receiver.h" -+#include "services/network/public/mojom/websocket.mojom.h" -+#include "services/service_manager/public/cpp/binder_registry.h" -+#include "third_party/blink/public/common/loader/url_loader_throttle.h" -+ -+#ifdef EYEO_INTERCEPT_DEBUG_URL -+#include "components/adblock/content/browser/adblock_url_loader_factory_for_test.h" -+#endif -+ -+#if BUILDFLAG(ENABLE_EXTENSIONS) -+#include "chrome/browser/extensions/extension_util.h" -+#endif -+ -+namespace { -+ -+bool IsFilteringNeeded(content::RenderFrameHost* frame) { -+ if (frame) { -+ auto* profile = -+ Profile::FromBrowserContext(frame->GetProcess()->GetBrowserContext()); -+ if (profile) { -+ // Filtering may be needed if there's at least one enabled -+ // FilteringConfiguration. -+ return base::ranges::any_of( -+ adblock::SubscriptionServiceFactory::GetForBrowserContext(profile) -+ ->GetInstalledFilteringConfigurations(), -+ &adblock::FilteringConfiguration::IsEnabled); -+ } -+ } -+ return false; -+} -+ -+// Owns all of the AdblockURLLoaderFactory for a given Profile. -+class AdblockContextData : public base::SupportsUserData::Data { -+ public: -+ AdblockContextData(const AdblockContextData&) = delete; -+ AdblockContextData& operator=(const AdblockContextData&) = delete; -+ ~AdblockContextData() override = default; -+ -+ static void StartProxying( -+ Profile* profile, -+ content::RenderFrameHost* frame, -+ int render_process_id, -+ mojo::PendingReceiver receiver, -+ mojo::PendingRemote target_factory, -+ bool use_test_loader) { -+ const void* const kAdblockContextUserDataKey = &kAdblockContextUserDataKey; -+ auto* self = static_cast( -+ profile->GetUserData(kAdblockContextUserDataKey)); -+ if (!self) { -+ self = new AdblockContextData(); -+ profile->SetUserData(kAdblockContextUserDataKey, base::WrapUnique(self)); -+ } -+ auto* browser_context = -+ content::WebContents::FromRenderFrameHost(frame)->GetBrowserContext(); -+ adblock::AdblockURLLoaderFactoryConfig config{ -+ adblock::SubscriptionServiceFactory::GetForBrowserContext( -+ browser_context), -+ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser_context), -+ adblock::ElementHiderFactory::GetForBrowserContext(browser_context), -+ adblock::SitekeyStorageFactory::GetForBrowserContext(browser_context), -+ adblock::ContentSecurityPolicyInjectorFactory::GetForBrowserContext( -+ browser_context)}; -+#ifdef EYEO_INTERCEPT_DEBUG_URL -+ if (use_test_loader) { -+ auto proxy = std::make_unique( -+ std::move(config), -+ content::GlobalRenderFrameHostId(render_process_id, -+ frame->GetRoutingID()), -+ std::move(receiver), std::move(target_factory), -+ embedder_support::GetUserAgent(), -+ base::BindOnce(&AdblockContextData::RemoveProxy, -+ self->weak_factory_.GetWeakPtr()), -+ adblock::AdblockControllerFactory::GetForBrowserContext( -+ Profile::FromBrowserContext( -+ frame->GetProcess()->GetBrowserContext()))); -+ self->proxies_.emplace(std::move(proxy)); -+ return; -+ } -+#endif -+ auto proxy = std::make_unique( -+ std::move(config), -+ content::GlobalRenderFrameHostId(render_process_id, -+ frame->GetRoutingID()), -+ std::move(receiver), std::move(target_factory), -+ embedder_support::GetUserAgent(), -+ base::BindOnce(&AdblockContextData::RemoveProxy, -+ self->weak_factory_.GetWeakPtr())); -+ self->proxies_.emplace(std::move(proxy)); -+ } -+ -+ private: -+ void RemoveProxy(adblock::AdblockURLLoaderFactory* proxy) { -+ auto it = proxies_.find(proxy); -+ DCHECK(it != proxies_.end()); -+ proxies_.erase(it); -+ } -+ -+ AdblockContextData() = default; -+ -+ std::set, -+ base::UniquePtrComparator> -+ proxies_; -+ -+ base::WeakPtrFactory weak_factory_{this}; -+}; -+ -+} // namespace -+ -+AdblockContentBrowserClient::AdblockContentBrowserClient() = default; -+ -+AdblockContentBrowserClient::~AdblockContentBrowserClient() = default; -+ -+#if BUILDFLAG(ENABLE_EXTENSIONS) -+// static -+bool AdblockContentBrowserClient::force_adblock_proxy_for_testing_ = false; -+ -+// static -+void AdblockContentBrowserClient::ForceAdblockProxyForTesting() { -+ force_adblock_proxy_for_testing_ = true; -+} -+#endif -+ -+bool AdblockContentBrowserClient::CanCreateWindow( -+ content::RenderFrameHost* opener, -+ const GURL& opener_url, -+ const GURL& opener_top_level_frame_url, -+ const url::Origin& source_origin, -+ content::mojom::WindowContainerType container_type, -+ const GURL& target_url, -+ const content::Referrer& referrer, -+ const std::string& frame_name, -+ WindowOpenDisposition disposition, -+ const blink::mojom::WindowFeatures& features, -+ bool user_gesture, -+ bool opener_suppressed, -+ bool* no_javascript_access) { -+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -+ DCHECK(opener); -+ -+ if (IsFilteringNeeded(opener)) { -+ content::WebContents* web_contents = -+ content::WebContents::FromRenderFrameHost(opener); -+ auto* subscription_service = -+ adblock::SubscriptionServiceFactory::GetForBrowserContext( -+ web_contents->GetBrowserContext()); -+ -+ GURL popup_url(target_url); -+ web_contents->GetPrimaryMainFrame()->GetProcess()->FilterURL(false, -+ &popup_url); -+ auto* classification_runner = -+ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( -+ web_contents->GetBrowserContext()); -+ const auto popup_blocking_decision = -+ classification_runner->ShouldBlockPopup( -+ subscription_service->GetCurrentSnapshot(), popup_url, opener); -+ if (popup_blocking_decision == adblock::FilterMatchResult::kAllowRule) { -+ return true; -+ } -+ if (popup_blocking_decision == adblock::FilterMatchResult::kBlockRule) { -+ return false; -+ } -+ // Otherwise, if eyeo adblocking is disabled or there is no rule that -+ // explicitly allows or blocks a popup, fall back on Chromium's built-in -+ // popup blocker. -+ DCHECK(popup_blocking_decision == adblock::FilterMatchResult::kDisabled || -+ popup_blocking_decision == adblock::FilterMatchResult::kNoRule); -+ } -+ -+ return ChromeContentBrowserClient::CanCreateWindow( -+ opener, opener_url, opener_top_level_frame_url, source_origin, -+ container_type, target_url, referrer, frame_name, disposition, features, -+ user_gesture, opener_suppressed, no_javascript_access); -+} -+ -+bool AdblockContentBrowserClient::WillInterceptWebSocket( -+ content::RenderFrameHost* frame) { -+ if (IsFilteringNeeded(frame)) { -+ return true; -+ } -+ -+ return ChromeContentBrowserClient::WillInterceptWebSocket(frame); -+} -+ -+void AdblockContentBrowserClient::CreateWebSocket( -+ content::RenderFrameHost* frame, -+ WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client) { -+ if (IsFilteringNeeded(frame)) { -+ CreateWebSocketInternal(frame->GetGlobalId(), std::move(factory), url, -+ site_for_cookies, user_agent, -+ std::move(handshake_client)); -+ } else { -+ DCHECK(ChromeContentBrowserClient::WillInterceptWebSocket(frame)); -+ ChromeContentBrowserClient::CreateWebSocket(frame, std::move(factory), url, -+ site_for_cookies, user_agent, -+ std::move(handshake_client)); -+ } -+} -+ -+void AdblockContentBrowserClient::CreateWebSocketInternal( -+ content::GlobalRenderFrameHostId render_frame_host_id, -+ WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client) { -+ auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); -+ if (!frame) { -+ return; -+ } -+ auto* browser_context = frame->GetProcess()->GetBrowserContext(); -+ auto* subscription_service = -+ adblock::SubscriptionServiceFactory::GetForBrowserContext( -+ browser_context); -+ auto* classification_runner = -+ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser_context); -+ classification_runner->CheckRequestFilterMatchForWebSocket( -+ subscription_service->GetCurrentSnapshot(), url, render_frame_host_id, -+ base::BindOnce( -+ &AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted, -+ weak_factory_.GetWeakPtr(), render_frame_host_id, std::move(factory), -+ url, site_for_cookies, user_agent, std::move(handshake_client))); -+} -+ -+void AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted( -+ content::GlobalRenderFrameHostId render_frame_host_id, -+ ChromeContentBrowserClient::WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client, -+ adblock::FilterMatchResult result) { -+ auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); -+ if (!frame) { -+ return; -+ } -+ const bool has_blocking_filter = -+ result == adblock::FilterMatchResult::kBlockRule; -+ if (!has_blocking_filter) { -+ VLOG(1) << "[eyeo] Web socket allowed for " << url; -+ if (ChromeContentBrowserClient::WillInterceptWebSocket(frame)) { -+ ChromeContentBrowserClient::CreateWebSocket( -+ frame, std::move(factory), url, site_for_cookies, user_agent, -+ std::move(handshake_client)); -+ return; -+ } -+ -+ std::vector headers; -+ if (user_agent) { -+ headers.push_back(network::mojom::HttpHeader::New( -+ net::HttpRequestHeaders::kUserAgent, *user_agent)); -+ } -+ std::move(factory).Run(url, std::move(headers), std::move(handshake_client), -+ mojo::NullRemote(), mojo::NullRemote()); -+ } -+ -+ VLOG(1) << "[eyeo] Web socket blocked for " << url; -+} -+ -+bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( -+ content::BrowserContext* browser_context, -+ content::RenderFrameHost* frame, -+ int render_process_id, -+ URLLoaderFactoryType type, -+ const url::Origin& request_initiator, -+ absl::optional navigation_id, -+ ukm::SourceIdObj ukm_source_id, -+ mojo::PendingReceiver* factory_receiver, -+ mojo::PendingRemote* -+ header_client, -+ bool* bypass_redirect_checks, -+ bool* disable_secure_dns, -+ network::mojom::URLLoaderFactoryOverridePtr* factory_override, -+ scoped_refptr navigation_response_task_runner) { -+ // Create Chromium proxy first as WebRequestProxyingURLLoaderFactory logic -+ // depends on being first proxy -+ bool use_chrome_proxy = -+ ChromeContentBrowserClient::WillCreateURLLoaderFactory( -+ browser_context, frame, render_process_id, type, request_initiator, -+ navigation_id, ukm_source_id, factory_receiver, header_client, -+ bypass_redirect_checks, disable_secure_dns, factory_override, -+ navigation_response_task_runner); -+ auto* profile = frame ? Profile::FromBrowserContext( -+ frame->GetProcess()->GetBrowserContext()) -+ : nullptr; -+ -+#if BUILDFLAG(ENABLE_EXTENSIONS) -+ if (!force_adblock_proxy_for_testing_ && -+ request_initiator.scheme() == extensions::kExtensionScheme) { -+ VLOG(1) << "[eyeo] Do not use adblock proxy for extensions requests " -+ "[extension id:" -+ << request_initiator.host() << "]."; -+ return use_chrome_proxy; -+ } -+#endif -+ -+ bool use_adblock_proxy = -+ (type == URLLoaderFactoryType::kDocumentSubResource || -+ type == URLLoaderFactoryType::kNavigation) && -+ IsFilteringNeeded(frame); -+ -+ bool use_test_loader = false; -+#ifdef EYEO_INTERCEPT_DEBUG_URL -+ content::WebContents* wc = content::WebContents::FromRenderFrameHost(frame); -+ use_test_loader = -+ (type == -+ content::ContentBrowserClient::URLLoaderFactoryType::kNavigation) && -+ wc->GetVisibleURL().is_valid() && -+ wc->GetVisibleURL().host() == -+ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; -+ use_adblock_proxy |= use_test_loader; -+#endif -+ -+ if (use_adblock_proxy) { -+ auto proxied_receiver = std::move(*factory_receiver); -+ mojo::PendingRemote target_factory_remote; -+ *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver(); -+ AdblockContextData::StartProxying( -+ profile, frame, render_process_id, std::move(proxied_receiver), -+ std::move(target_factory_remote), use_test_loader); -+ } -+ return use_adblock_proxy || use_chrome_proxy; -+} -diff --git a/chrome/browser/adblock/adblock_content_browser_client.h b/chrome/browser/adblock/adblock_content_browser_client.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_content_browser_client.h -@@ -0,0 +1,111 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ -+#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ -+ -+#include "build/buildflag.h" -+#include "chrome/browser/chrome_content_browser_client.h" -+ -+namespace adblock { -+enum class FilterMatchResult; -+} // namespace adblock -+ -+/** -+ * @brief Intercepts network and UI events to inject ad-filtering. -+ * Provides ad-filtering implementations of URLLoaderThrottles. -+ * Binds a mojo connection between Renderer processes and the -+ * Browser-process-based ResourceClassificationRunner. -+ * Lives in browser process UI thread. -+ */ -+class AdblockContentBrowserClient : public ChromeContentBrowserClient { -+ public: -+ AdblockContentBrowserClient(); -+ ~AdblockContentBrowserClient() override; -+ -+#if BUILDFLAG(ENABLE_EXTENSIONS) -+ // Enable ad filtering also for requests initiated by extensions. -+ // This allows implementing extension-driven browser tests. -+ // In production code, requests from extensions are not blocked. -+ static void ForceAdblockProxyForTesting(); -+#endif -+ -+ bool CanCreateWindow(content::RenderFrameHost* opener, -+ const GURL& opener_url, -+ const GURL& opener_top_level_frame_url, -+ const url::Origin& source_origin, -+ content::mojom::WindowContainerType container_type, -+ const GURL& target_url, -+ const content::Referrer& referrer, -+ const std::string& frame_name, -+ WindowOpenDisposition disposition, -+ const blink::mojom::WindowFeatures& features, -+ bool user_gesture, -+ bool opener_suppressed, -+ bool* no_javascript_access) override; -+ bool WillInterceptWebSocket(content::RenderFrameHost* frame) override; -+ void CreateWebSocket( -+ content::RenderFrameHost* frame, -+ WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client) override; -+ bool WillCreateURLLoaderFactory( -+ content::BrowserContext* browser_context, -+ content::RenderFrameHost* frame, -+ int render_process_id, -+ URLLoaderFactoryType type, -+ const url::Origin& request_initiator, -+ absl::optional navigation_id, -+ ukm::SourceIdObj ukm_source_id, -+ mojo::PendingReceiver* factory_receiver, -+ mojo::PendingRemote* -+ header_client, -+ bool* bypass_redirect_checks, -+ bool* disable_secure_dns, -+ network::mojom::URLLoaderFactoryOverridePtr* factory_override, -+ scoped_refptr navigation_response_task_runner) override; -+ -+ private: -+ void CreateWebSocketInternal( -+ content::GlobalRenderFrameHostId render_frame_host_id, -+ WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client); -+ void OnWebSocketFilterCheckCompleted( -+ content::GlobalRenderFrameHostId render_frame_host_id, -+ ChromeContentBrowserClient::WebSocketFactory factory, -+ const GURL& url, -+ const net::SiteForCookies& site_for_cookies, -+ const absl::optional& user_agent, -+ mojo::PendingRemote -+ handshake_client, -+ adblock::FilterMatchResult result); -+ -+ base::WeakPtrFactory weak_factory_{this}; -+ -+#if BUILDFLAG(ENABLE_EXTENSIONS) -+ static bool force_adblock_proxy_for_testing_; -+#endif -+}; -+ -+#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ -diff --git a/chrome/browser/adblock/adblock_content_browser_client_unittest.cc b/chrome/browser/adblock/adblock_content_browser_client_unittest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_content_browser_client_unittest.cc -@@ -0,0 +1,198 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_content_browser_client.h" -+ -+#include "base/callback_list.h" -+#include "base/memory/raw_ptr.h" -+#include "base/run_loop.h" -+#include "base/test/gmock_move_support.h" -+#include "base/test/mock_callback.h" -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/test/base/chrome_render_view_host_test_harness.h" -+#include "components/adblock/content/browser/test/mock_resource_classification_runner.h" -+#include "components/adblock/core/common/adblock_prefs.h" -+#include "components/adblock/core/common/content_type.h" -+#include "components/adblock/core/subscription/installed_subscription.h" -+#include "components/adblock/core/subscription/subscription_service.h" -+#include "components/adblock/core/subscription/test/mock_subscription_collection.h" -+#include "components/adblock/core/subscription/test/mock_subscription_service.h" -+#include "components/adblock/core/test/mock_adblock_controller.h" -+#include "components/keyed_service/core/keyed_service.h" -+#include "content/public/browser/content_browser_client.h" -+#include "content/public/test/mock_render_process_host.h" -+#include "content/public/test/test_renderer_host.h" -+#include "gmock/gmock.h" -+#include "services/network/public/mojom/network_context.mojom.h" -+#include "services/network/public/mojom/websocket.mojom.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+using testing::_; -+using testing::Return; -+ -+namespace adblock { -+ -+class AdblockContentBrowserClientUnitTest -+ : public ChromeRenderViewHostTestHarness { -+ public: -+ TestingProfile::TestingFactories GetTestingFactories() const override { -+ return {std::make_pair( -+ SubscriptionServiceFactory::GetInstance(), -+ base::BindRepeating([](content::BrowserContext* bc) -+ -> std::unique_ptr { -+ return std::make_unique(); -+ })), -+ std::make_pair( -+ ResourceClassificationRunnerFactory::GetInstance(), -+ base::BindRepeating([](content::BrowserContext* bc) -+ -> std::unique_ptr { -+ return std::make_unique(); -+ }))}; -+ } -+ -+ void SetUp() override { -+ RenderViewHostTestHarness::SetUp(); -+ -+ subscription_service_ = static_cast( -+ SubscriptionServiceFactory::GetForBrowserContext(profile())); -+ resource_classification_runner_ = -+ static_cast( -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ profile())); -+ } -+ -+ raw_ptr subscription_service_; -+ raw_ptr resource_classification_runner_; -+}; -+ -+TEST_F(AdblockContentBrowserClientUnitTest, -+ WillInterceptWebSocketWhenFilteringEnabled) { -+ AdblockContentBrowserClient content_client; -+ subscription_service_->WillRequireFiltering(true); -+ EXPECT_TRUE(content_client.WillInterceptWebSocket(main_rfh())); -+} -+ -+TEST_F(AdblockContentBrowserClientUnitTest, -+ WillNotInterceptWebSocketWhenFilteringDisabled) { -+ AdblockContentBrowserClient content_client; -+ subscription_service_->WillRequireFiltering(false); -+ EXPECT_FALSE(content_client.WillInterceptWebSocket(main_rfh())); -+} -+ -+TEST_F(AdblockContentBrowserClientUnitTest, -+ RenderFrameHostDiesBeforeClassificationFinished) { -+ const auto kSocketUrl = GURL("wss://domain.com/test"); -+ subscription_service_->WillRequireFiltering(true); -+ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { -+ SubscriptionService::Snapshot snapshot; -+ snapshot.push_back(std::make_unique()); -+ return snapshot; -+ }); -+ CheckFilterMatchCallback classification_callback; -+ EXPECT_CALL(*resource_classification_runner_, -+ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, -+ main_rfh()->GetGlobalId(), _)) -+ .WillOnce(MoveArg<3>(&classification_callback)); -+ -+ AdblockContentBrowserClient content_client; -+ base::MockCallback -+ web_socket_factory; -+ // The web_socket_factory callback will never be called because the -+ // associated RenderFrameHost will be dead. -+ EXPECT_CALL(web_socket_factory, Run(_, _, _, _, _)).Times(0); -+ -+ const net::SiteForCookies site_for_cookies; -+ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), -+ kSocketUrl, site_for_cookies, absl::nullopt, -+ {}); -+ // Tab is closed. -+ DeleteContents(); -+ -+ // Classification finishes now. It will not trigger a call to -+ // |web_socket_factory| because the RFH is dead. -+ std::move(classification_callback).Run(FilterMatchResult::kBlockRule); -+ -+ task_environment()->RunUntilIdle(); -+} -+ -+TEST_F(AdblockContentBrowserClientUnitTest, WebSocketAllowed) { -+ subscription_service_->WillRequireFiltering(true); -+ const auto kSocketUrl = GURL("wss://domain.com/test"); -+ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { -+ SubscriptionService::Snapshot snapshot; -+ snapshot.push_back(std::make_unique()); -+ return snapshot; -+ }); -+ CheckFilterMatchCallback classification_callback; -+ EXPECT_CALL(*resource_classification_runner_, -+ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, -+ main_rfh()->GetGlobalId(), _)) -+ .WillOnce(MoveArg<3>(&classification_callback)); -+ -+ AdblockContentBrowserClient content_client; -+ base::MockCallback -+ web_socket_factory; -+ // The web_socket_factory callback will be called to let the web socket -+ // continue connecting. -+ EXPECT_CALL(web_socket_factory, Run(kSocketUrl, _, _, _, _)); -+ -+ const net::SiteForCookies site_for_cookies; -+ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), -+ kSocketUrl, site_for_cookies, absl::nullopt, -+ {}); -+ -+ // Classification finishes now. It will trigger a call to |web_socket_factory| -+ std::move(classification_callback).Run(FilterMatchResult::kAllowRule); -+ -+ task_environment()->RunUntilIdle(); -+} -+ -+TEST_F(AdblockContentBrowserClientUnitTest, WebSocketBlocked) { -+ subscription_service_->WillRequireFiltering(true); -+ const auto kSocketUrl = GURL("wss://domain.com/test"); -+ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { -+ SubscriptionService::Snapshot snapshot; -+ snapshot.push_back(std::make_unique()); -+ return snapshot; -+ }); -+ CheckFilterMatchCallback classification_callback; -+ EXPECT_CALL(*resource_classification_runner_, -+ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, -+ main_rfh()->GetGlobalId(), _)) -+ .WillOnce(MoveArg<3>(&classification_callback)); -+ -+ AdblockContentBrowserClient content_client; -+ base::MockCallback -+ web_socket_factory; -+ // The web_socket_factory callback will not be called as to disallow -+ // connection. -+ EXPECT_CALL(web_socket_factory, Run(kSocketUrl, _, _, _, _)).Times(0); -+ -+ const net::SiteForCookies site_for_cookies; -+ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), -+ kSocketUrl, site_for_cookies, absl::nullopt, -+ {}); -+ -+ // Classification finishes now. -+ std::move(classification_callback).Run(FilterMatchResult::kBlockRule); -+ -+ task_environment()->RunUntilIdle(); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/adblock_controller_factory.cc b/chrome/browser/adblock/adblock_controller_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_controller_factory.cc -@@ -0,0 +1,110 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+ -+#include -+ -+#include "base/command_line.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/browser_process.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/core/adblock_controller_impl.h" -+#include "components/adblock/core/adblock_switches.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/adblock/core/common/adblock_prefs.h" -+#include "components/adblock/core/configuration/persistent_filtering_configuration.h" -+#include "components/adblock/core/subscription/subscription_config.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "components/pref_registry/pref_registry_syncable.h" -+#include "components/version_info/version_info.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+AdblockController* AdblockControllerFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+AdblockControllerFactory* AdblockControllerFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+AdblockControllerFactory::AdblockControllerFactory() -+ : BrowserContextKeyedServiceFactory( -+ "AdblockController", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(SubscriptionServiceFactory::GetInstance()); -+} -+ -+AdblockControllerFactory::~AdblockControllerFactory() = default; -+ -+KeyedService* AdblockControllerFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); -+ auto adblock_filtering_configuration = -+ std::make_unique( -+ prefs, kAdblockFilteringConfigurationName); -+ -+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( -+ adblock::switches::kDisableAcceptableAds)) { -+ adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); -+ } -+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( -+ switches::kDisableAdblock)) { -+ adblock_filtering_configuration->SetEnabled(false); -+ } -+ -+ auto* subscription_service = -+ SubscriptionServiceFactory::GetForBrowserContext(context); -+ auto controller = std::make_unique( -+ adblock_filtering_configuration.get(), subscription_service, -+ g_browser_process->GetApplicationLocale(), -+ config::GetKnownSubscriptions()); -+ controller->RunFirstRunLogic(prefs); -+ controller->MigrateLegacyPrefs(prefs); -+ -+ subscription_service->InstallFilteringConfiguration( -+ std::move(adblock_filtering_configuration)); -+ -+ return controller.release(); -+} -+ -+content::BrowserContext* AdblockControllerFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+void AdblockControllerFactory::RegisterProfilePrefs( -+ user_prefs::PrefRegistrySyncable* registry) { -+ adblock::prefs::RegisterProfilePrefs(registry); -+} -+ -+bool AdblockControllerFactory::ServiceIsNULLWhileTesting() const { -+ return true; -+} -+ -+bool AdblockControllerFactory::ServiceIsCreatedWithBrowserContext() const { -+ return true; -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/adblock_controller_factory.h b/chrome/browser/adblock/adblock_controller_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_controller_factory.h -@@ -0,0 +1,52 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class AdblockController; -+class AdblockControllerFactory : public BrowserContextKeyedServiceFactory { -+ public: -+ static AdblockController* GetForBrowserContext( -+ content::BrowserContext* context); -+ static AdblockControllerFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ AdblockControllerFactory(); -+ ~AdblockControllerFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+ void RegisterProfilePrefs( -+ user_prefs::PrefRegistrySyncable* registry) override; -+ bool ServiceIsNULLWhileTesting() const override; -+ bool ServiceIsCreatedWithBrowserContext() const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ -diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.cc b/chrome/browser/adblock/adblock_telemetry_service_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_telemetry_service_factory.cc -@@ -0,0 +1,127 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" -+ -+#include -+ -+#include "base/no_destructor.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/common/pref_names.h" -+#include "components/adblock/core/activeping_telemetry_topic_provider.h" -+#include "components/adblock/core/adblock_telemetry_service.h" -+#include "components/adblock/core/common/adblock_utils.h" -+#include "components/adblock/core/configuration/filtering_configuration.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/storage_partition.h" -+ -+namespace adblock { -+namespace { -+std::optional g_check_interval_for_testing; -+std::optional g_initial_delay_for_testing; -+ -+base::TimeDelta GetInitialDelay() { -+ static base::TimeDelta kInitialDelay = -+ g_initial_delay_for_testing ? g_initial_delay_for_testing.value() -+ : base::Seconds(30); -+ return kInitialDelay; -+} -+ -+base::TimeDelta GetCheckInterval() { -+ static base::TimeDelta kCheckInterval = -+ g_check_interval_for_testing ? g_check_interval_for_testing.value() -+ : base::Minutes(5); -+ return kCheckInterval; -+} -+ -+} // namespace -+ -+// static -+AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile( -+ Profile* profile) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(profile, true)); -+} -+// static -+AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory() -+ : BrowserContextKeyedServiceFactory( -+ "AdblockTelemetryService", -+ BrowserContextDependencyManager::GetInstance()) { -+ // AdblockController creates Adblock Filtering Configuration required by -+ // AdblockTelemetryService -+ DependsOn(AdblockControllerFactory::GetInstance()); -+} -+ -+AdblockTelemetryServiceFactory::~AdblockTelemetryServiceFactory() = default; -+ -+KeyedService* AdblockTelemetryServiceFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ // Need to use a URLLoaderFactory specific to the browser context, not from -+ // system_network_context_manager(), because the required Accept-Language -+ // header depends on user's language settings and is not present in requests -+ // made from the System network context. -+ scoped_refptr url_loader_factory = -+ context->GetDefaultStoragePartition() -+ ->GetURLLoaderFactoryForBrowserProcess(); -+ auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); -+ auto service = std::make_unique( -+ SubscriptionServiceFactory::GetForBrowserContext(context) -+ ->GetAdblockFilteringConfiguration(), -+ url_loader_factory, GetInitialDelay(), GetCheckInterval()); -+ service->AddTopicProvider(std::make_unique( -+ utils::GetAppInfo(), prefs, -+ AdblockControllerFactory::GetForBrowserContext(context), -+ ActivepingTelemetryTopicProvider::DefaultBaseUrl(), -+ ActivepingTelemetryTopicProvider::DefaultAuthToken())); -+ -+ if (url_loader_factory) { -+ service->Start(); -+ } -+ -+ return service.release(); -+} -+ -+content::BrowserContext* AdblockTelemetryServiceFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+bool AdblockTelemetryServiceFactory::ServiceIsNULLWhileTesting() const { -+ return true; -+} -+ -+bool AdblockTelemetryServiceFactory::ServiceIsCreatedWithBrowserContext() -+ const { -+ return true; -+} -+ -+void AdblockTelemetryServiceFactory::SetCheckAndDelayIntervalsForTesting( -+ base::TimeDelta check_interval, -+ base::TimeDelta initial_delay) { -+ g_check_interval_for_testing = check_interval; -+ g_initial_delay_for_testing = initial_delay; -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.h b/chrome/browser/adblock/adblock_telemetry_service_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/adblock_telemetry_service_factory.h -@@ -0,0 +1,56 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "base/time/time.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+ -+class Profile; -+ -+namespace adblock { -+class AdblockTelemetryService; -+class AdblockTelemetryServiceFactory -+ : public BrowserContextKeyedServiceFactory { -+ public: -+ static AdblockTelemetryService* GetForProfile(Profile* profile); -+ static AdblockTelemetryServiceFactory* GetInstance(); -+ -+ // Sets the initial delay and interval checks required for browser tests. -+ // Must be called before BuildServiceInstanceFor(). -+ void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval, -+ base::TimeDelta initial_delay); -+ -+ private: -+ friend class base::NoDestructor; -+ AdblockTelemetryServiceFactory(); -+ ~AdblockTelemetryServiceFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+ bool ServiceIsNULLWhileTesting() const override; -+ bool ServiceIsCreatedWithBrowserContext() const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ -diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.cc b/chrome/browser/adblock/content_security_policy_injector_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/content_security_policy_injector_factory.cc -@@ -0,0 +1,69 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/content_security_policy_injector_factory.h" -+ -+#include -+ -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/content/browser/content_security_policy_injector_impl.h" -+#include "components/adblock/content/browser/frame_hierarchy_builder.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+ContentSecurityPolicyInjector* -+ContentSecurityPolicyInjectorFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+ContentSecurityPolicyInjectorFactory* -+ContentSecurityPolicyInjectorFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+ContentSecurityPolicyInjectorFactory::ContentSecurityPolicyInjectorFactory() -+ : BrowserContextKeyedServiceFactory( -+ "ContentSecurityPolicyInjector", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(SubscriptionServiceFactory::GetInstance()); -+} -+ -+ContentSecurityPolicyInjectorFactory::~ContentSecurityPolicyInjectorFactory() = -+ default; -+ -+KeyedService* ContentSecurityPolicyInjectorFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new ContentSecurityPolicyInjectorImpl( -+ SubscriptionServiceFactory::GetForBrowserContext(context), -+ std::make_unique()); -+} -+ -+content::BrowserContext* -+ContentSecurityPolicyInjectorFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.h b/chrome/browser/adblock/content_security_policy_injector_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/content_security_policy_injector_factory.h -@@ -0,0 +1,49 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class ContentSecurityPolicyInjector; -+class ContentSecurityPolicyInjectorFactory -+ : public BrowserContextKeyedServiceFactory { -+ public: -+ static ContentSecurityPolicyInjector* GetForBrowserContext( -+ content::BrowserContext* context); -+ static ContentSecurityPolicyInjectorFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ ContentSecurityPolicyInjectorFactory(); -+ ~ContentSecurityPolicyInjectorFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ -diff --git a/chrome/browser/adblock/element_hider_factory.cc b/chrome/browser/adblock/element_hider_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/element_hider_factory.cc -@@ -0,0 +1,63 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/element_hider_factory.h" -+ -+#include -+ -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/content/browser/element_hider_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+ElementHider* ElementHiderFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+ElementHiderFactory* ElementHiderFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+ElementHiderFactory::ElementHiderFactory() -+ : BrowserContextKeyedServiceFactory( -+ "ElementHider", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(adblock::SubscriptionServiceFactory::GetInstance()); -+} -+ -+ElementHiderFactory::~ElementHiderFactory() = default; -+ -+KeyedService* ElementHiderFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new ElementHiderImpl( -+ adblock::SubscriptionServiceFactory::GetForBrowserContext(context)); -+} -+ -+content::BrowserContext* ElementHiderFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/element_hider_factory.h b/chrome/browser/adblock/element_hider_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/element_hider_factory.h -@@ -0,0 +1,47 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class ElementHider; -+class ElementHiderFactory : public BrowserContextKeyedServiceFactory { -+ public: -+ static ElementHider* GetForBrowserContext(content::BrowserContext* context); -+ static ElementHiderFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ ElementHiderFactory(); -+ ~ElementHiderFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ -diff --git a/chrome/browser/adblock/resource_classification_runner_factory.cc b/chrome/browser/adblock/resource_classification_runner_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/resource_classification_runner_factory.cc -@@ -0,0 +1,71 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+ -+#include -+ -+#include "chrome/browser/adblock/sitekey_storage_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/content/browser/frame_hierarchy_builder.h" -+#include "components/adblock/content/browser/resource_classification_runner_impl.h" -+#include "components/adblock/core/classifier/resource_classifier_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+ResourceClassificationRunner* -+ResourceClassificationRunnerFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+ResourceClassificationRunnerFactory* -+ResourceClassificationRunnerFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+ResourceClassificationRunnerFactory::ResourceClassificationRunnerFactory() -+ : BrowserContextKeyedServiceFactory( -+ "ResourceClassificationRunner", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(SitekeyStorageFactory::GetInstance()); -+} -+ -+ResourceClassificationRunnerFactory::~ResourceClassificationRunnerFactory() = -+ default; -+ -+KeyedService* ResourceClassificationRunnerFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new ResourceClassificationRunnerImpl( -+ base::MakeRefCounted(), -+ std::make_unique(), -+ SitekeyStorageFactory::GetForBrowserContext(context)); -+} -+ -+content::BrowserContext* -+ResourceClassificationRunnerFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/resource_classification_runner_factory.h b/chrome/browser/adblock/resource_classification_runner_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/resource_classification_runner_factory.h -@@ -0,0 +1,49 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class ResourceClassificationRunner; -+class ResourceClassificationRunnerFactory -+ : public BrowserContextKeyedServiceFactory { -+ public: -+ static ResourceClassificationRunner* GetForBrowserContext( -+ content::BrowserContext* context); -+ static ResourceClassificationRunnerFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ ResourceClassificationRunnerFactory(); -+ ~ResourceClassificationRunnerFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ -diff --git a/chrome/browser/adblock/session_stats_factory.cc b/chrome/browser/adblock/session_stats_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/session_stats_factory.cc -@@ -0,0 +1,64 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/session_stats_factory.h" -+ -+#include -+ -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/content/browser/session_stats_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+SessionStats* SessionStatsFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+ -+// static -+SessionStatsFactory* SessionStatsFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+SessionStatsFactory::SessionStatsFactory() -+ : BrowserContextKeyedServiceFactory( -+ "SessionStats", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(ResourceClassificationRunnerFactory::GetInstance()); -+} -+ -+SessionStatsFactory::~SessionStatsFactory() = default; -+ -+KeyedService* SessionStatsFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new SessionStatsImpl( -+ ResourceClassificationRunnerFactory::GetForBrowserContext(context)); -+} -+ -+content::BrowserContext* SessionStatsFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/session_stats_factory.h b/chrome/browser/adblock/session_stats_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/session_stats_factory.h -@@ -0,0 +1,47 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class SessionStats; -+class SessionStatsFactory : public BrowserContextKeyedServiceFactory { -+ public: -+ static SessionStats* GetForBrowserContext(content::BrowserContext* context); -+ static SessionStatsFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ SessionStatsFactory(); -+ ~SessionStatsFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ -diff --git a/chrome/browser/adblock/sitekey_storage_factory.cc b/chrome/browser/adblock/sitekey_storage_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/sitekey_storage_factory.cc -@@ -0,0 +1,59 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/sitekey_storage_factory.h" -+ -+#include -+ -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/core/sitekey_storage_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+SitekeyStorage* SitekeyStorageFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+SitekeyStorageFactory* SitekeyStorageFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+SitekeyStorageFactory::SitekeyStorageFactory() -+ : BrowserContextKeyedServiceFactory( -+ "SitekeyStorage", -+ BrowserContextDependencyManager::GetInstance()) {} -+ -+SitekeyStorageFactory::~SitekeyStorageFactory() = default; -+ -+KeyedService* SitekeyStorageFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new SitekeyStorageImpl(); -+} -+ -+content::BrowserContext* SitekeyStorageFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/sitekey_storage_factory.h b/chrome/browser/adblock/sitekey_storage_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/sitekey_storage_factory.h -@@ -0,0 +1,47 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class SitekeyStorage; -+class SitekeyStorageFactory : public BrowserContextKeyedServiceFactory { -+ public: -+ static SitekeyStorage* GetForBrowserContext(content::BrowserContext* context); -+ static SitekeyStorageFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ SitekeyStorageFactory(); -+ ~SitekeyStorageFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ -diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.cc b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc -@@ -0,0 +1,63 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" -+ -+#include -+ -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/core/subscription/subscription_persistent_metadata_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+// static -+SubscriptionPersistentMetadata* -+SubscriptionPersistentMetadataFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+SubscriptionPersistentMetadataFactory* -+SubscriptionPersistentMetadataFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+SubscriptionPersistentMetadataFactory::SubscriptionPersistentMetadataFactory() -+ : BrowserContextKeyedServiceFactory( -+ "AdblockSubscriptionPersistentMetadata", -+ BrowserContextDependencyManager::GetInstance()) {} -+SubscriptionPersistentMetadataFactory:: -+ ~SubscriptionPersistentMetadataFactory() = default; -+ -+KeyedService* SubscriptionPersistentMetadataFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new SubscriptionPersistentMetadataImpl( -+ Profile::FromBrowserContext(context)->GetPrefs()); -+} -+ -+content::BrowserContext* -+SubscriptionPersistentMetadataFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.h b/chrome/browser/adblock/subscription_persistent_metadata_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.h -@@ -0,0 +1,49 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class SubscriptionPersistentMetadata; -+class SubscriptionPersistentMetadataFactory -+ : public BrowserContextKeyedServiceFactory { -+ public: -+ static SubscriptionPersistentMetadata* GetForBrowserContext( -+ content::BrowserContext* context); -+ static SubscriptionPersistentMetadataFactory* GetInstance(); -+ -+ private: -+ friend class base::NoDestructor; -+ SubscriptionPersistentMetadataFactory(); -+ ~SubscriptionPersistentMetadataFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ -diff --git a/chrome/browser/adblock/subscription_service_factory.cc b/chrome/browser/adblock/subscription_service_factory.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/subscription_service_factory.cc -@@ -0,0 +1,216 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/subscription_service_factory.h" -+ -+#include -+#include -+#include -+ -+#include "base/files/file_util.h" -+#include "base/functional/bind.h" -+#include "base/task/thread_pool.h" -+#include "base/trace_event/trace_event.h" -+#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" -+#include "chrome/browser/profiles/incognito_helpers.h" -+#include "chrome/browser/profiles/profile.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/adblock/core/configuration/persistent_filtering_configuration.h" -+#include "components/adblock/core/converter/flatbuffer_converter.h" -+#include "components/adblock/core/subscription/filtering_configuration_maintainer_impl.h" -+#include "components/adblock/core/subscription/installed_subscription_impl.h" -+#include "components/adblock/core/subscription/ongoing_subscription_request_impl.h" -+#include "components/adblock/core/subscription/preloaded_subscription_provider_impl.h" -+#include "components/adblock/core/subscription/subscription_config.h" -+#include "components/adblock/core/subscription/subscription_downloader_impl.h" -+#include "components/adblock/core/subscription/subscription_persistent_storage_impl.h" -+#include "components/adblock/core/subscription/subscription_service_impl.h" -+#include "components/adblock/core/subscription/subscription_updater.h" -+#include "components/adblock/core/subscription/subscription_updater_impl.h" -+#include "components/adblock/core/subscription/subscription_validator_impl.h" -+#include "components/keyed_service/content/browser_context_dependency_manager.h" -+#include "components/pref_registry/pref_registry_syncable.h" -+#include "components/prefs/pref_service.h" -+#include "content/public/browser/browser_context.h" -+#include "content/public/browser/storage_partition.h" -+ -+namespace adblock { -+namespace { -+ -+std::optional g_update_check_interval_for_testing; -+std::optional g_update_initial_delay_for_testing; -+ -+base::TimeDelta GetUpdateInitialDelay() { -+ static base::TimeDelta kInitialDelay = -+ g_update_initial_delay_for_testing -+ ? g_update_initial_delay_for_testing.value() -+ : base::Seconds(30); -+ return kInitialDelay; -+} -+ -+base::TimeDelta GetUpdateCheckInterval() { -+ static base::TimeDelta kCheckInterval = -+ g_update_check_interval_for_testing -+ ? g_update_check_interval_for_testing.value() -+ : base::Hours(1); -+ return kCheckInterval; -+} -+ -+constexpr net::BackoffEntry::Policy kRetryBackoffPolicy = { -+ 0, // Number of initial errors to ignore. -+ 5000, // Initial delay in ms. -+ 2.0, // Factor by which the waiting time will be multiplied. -+ 0.2, // Fuzzing percentage. -+ 60 * 60 * 1000, // Maximum delay in ms. -+ -1, // Never discard the entry. -+ false, // Use initial delay. -+}; -+ -+std::unique_ptr MakeOngoingSubscriptionRequest( -+ scoped_refptr url_loader_factory) { -+ return std::make_unique(&kRetryBackoffPolicy, -+ url_loader_factory); -+} -+ -+ConversionResult ConvertFilterFile(const GURL& subscription_url, -+ const base::FilePath& path) { -+ TRACE_EVENT1("eyeo", "ConvertFileToFlatbuffer", "url", -+ subscription_url.spec()); -+ ConversionResult result; -+ std::ifstream input_stream(path.AsUTF8Unsafe()); -+ if (!input_stream.is_open() || !input_stream.good()) { -+ result = ConversionError("Could not open filter file"); -+ } else { -+ result = FlatbufferConverter::Convert( -+ input_stream, subscription_url, -+ config::AllowPrivilegedFilters(subscription_url)); -+ } -+ base::DeleteFile(path); -+ return result; -+} -+ -+std::unique_ptr MakeSubscriptionUpdater() { -+ return std::make_unique(GetUpdateInitialDelay(), -+ GetUpdateCheckInterval()); -+} -+ -+std::unique_ptr -+MakeFilterConfigurationMaintainer( -+ content::BrowserContext* context, -+ FilteringConfiguration* configuration, -+ FilteringConfigurationMaintainerImpl::SubscriptionUpdatedCallback -+ observer) { -+ auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); -+ auto main_thread_task_runner = base::SequencedTaskRunner::GetCurrentDefault(); -+ auto* persistent_metadata = -+ SubscriptionPersistentMetadataFactory::GetForBrowserContext(context); -+ scoped_refptr url_loader_factory = -+ context->GetDefaultStoragePartition() -+ ->GetURLLoaderFactoryForBrowserProcess(); -+ -+ const std::string storage_dir = configuration->GetName() + "_subscriptions"; -+ -+ auto storage = std::make_unique( -+ context->GetPath().AppendASCII(storage_dir), -+ std::make_unique(prefs, -+ CurrentSchemaVersion()), -+ persistent_metadata); -+ -+ ConversionExecutors* conversion_executors = -+ SubscriptionServiceFactory::GetInstance(); -+ -+ auto downloader = std::make_unique( -+ utils::GetAppInfo(), -+ base::BindRepeating(&MakeOngoingSubscriptionRequest, url_loader_factory), -+ conversion_executors, persistent_metadata); -+ -+ auto maintainer = std::make_unique( -+ configuration, std::move(storage), std::move(downloader), -+ std::make_unique(), -+ MakeSubscriptionUpdater(), conversion_executors, persistent_metadata, -+ observer); -+ maintainer->InitializeStorage(); -+ return maintainer; -+} -+ -+} // namespace -+ -+scoped_refptr -+SubscriptionServiceFactory::ConvertCustomFilters( -+ const std::vector& filters) const { -+ auto raw_data = -+ FlatbufferConverter::Convert(filters, CustomFiltersUrl(), true); -+ return base::MakeRefCounted( -+ std::move(raw_data), Subscription::InstallationState::Installed, -+ base::Time()); -+} -+ -+void SubscriptionServiceFactory::ConvertFilterListFile( -+ const GURL& subscription_url, -+ const base::FilePath& path, -+ base::OnceCallback result_callback) const { -+ base::ThreadPool::PostTaskAndReplyWithResult( -+ FROM_HERE, {base::MayBlock()}, -+ base::BindOnce(&ConvertFilterFile, subscription_url, path), -+ std::move(result_callback)); -+} -+ -+// static -+SubscriptionService* SubscriptionServiceFactory::GetForBrowserContext( -+ content::BrowserContext* context) { -+ return static_cast( -+ GetInstance()->GetServiceForBrowserContext(context, true)); -+} -+// static -+SubscriptionServiceFactory* SubscriptionServiceFactory::GetInstance() { -+ static base::NoDestructor instance; -+ return instance.get(); -+} -+ -+SubscriptionServiceFactory::SubscriptionServiceFactory() -+ : BrowserContextKeyedServiceFactory( -+ "AdblockSubscriptionService", -+ BrowserContextDependencyManager::GetInstance()) { -+ DependsOn(SubscriptionPersistentMetadataFactory::GetInstance()); -+} -+SubscriptionServiceFactory::~SubscriptionServiceFactory() = default; -+ -+KeyedService* SubscriptionServiceFactory::BuildServiceInstanceFor( -+ content::BrowserContext* context) const { -+ return new SubscriptionServiceImpl( -+ base::BindRepeating(&MakeFilterConfigurationMaintainer, context)); -+} -+ -+content::BrowserContext* SubscriptionServiceFactory::GetBrowserContextToUse( -+ content::BrowserContext* context) const { -+ return chrome::GetBrowserContextRedirectedInIncognito(context); -+} -+ -+void SubscriptionServiceFactory::RegisterProfilePrefs( -+ user_prefs::PrefRegistrySyncable* registry) { -+ adblock::PersistentFilteringConfiguration::RegisterProfilePrefs(registry); -+} -+ -+// static -+void SubscriptionServiceFactory::SetUpdateCheckAndDelayIntervalsForTesting( -+ base::TimeDelta check_interval, -+ base::TimeDelta initial_delay) { -+ g_update_check_interval_for_testing = check_interval; -+ g_update_initial_delay_for_testing = initial_delay; -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/subscription_service_factory.h b/chrome/browser/adblock/subscription_service_factory.h -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/subscription_service_factory.h -@@ -0,0 +1,63 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ -+#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ -+ -+#include "base/no_destructor.h" -+#include "components/adblock/core/subscription/conversion_executors.h" -+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -+#include "content/public/browser/browser_context.h" -+ -+namespace adblock { -+ -+class SubscriptionService; -+class SubscriptionServiceFactory : public BrowserContextKeyedServiceFactory, -+ public ConversionExecutors { -+ public: -+ static SubscriptionService* GetForBrowserContext( -+ content::BrowserContext* context); -+ static SubscriptionServiceFactory* GetInstance(); -+ static void SetUpdateCheckAndDelayIntervalsForTesting( -+ base::TimeDelta check_interval, -+ base::TimeDelta initial_delay); -+ -+ // ConversionExecutors: -+ scoped_refptr ConvertCustomFilters( -+ const std::vector& filters) const override; -+ void ConvertFilterListFile( -+ const GURL& subscription_url, -+ const base::FilePath& path, -+ base::OnceCallback) const override; -+ -+ private: -+ friend class base::NoDestructor; -+ SubscriptionServiceFactory(); -+ ~SubscriptionServiceFactory() override; -+ -+ // BrowserContextKeyedServiceFactory: -+ KeyedService* BuildServiceInstanceFor( -+ content::BrowserContext* context) const override; -+ content::BrowserContext* GetBrowserContextToUse( -+ content::BrowserContext* context) const override; -+ void RegisterProfilePrefs( -+ user_prefs::PrefRegistrySyncable* registry) override; -+}; -+ -+} // namespace adblock -+ -+#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ -diff --git a/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc b/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc -@@ -0,0 +1,122 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_content_browser_client.h" -+ -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/browser/ui/browser_commands.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/adblock/core/common/adblock_prefs.h" -+#include "components/adblock/core/subscription/subscription_service.h" -+#include "components/adblock/core/subscription/test/mock_subscription_service.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+#include "net/test/spawned_test_server/spawned_test_server.h" -+#include "net/test/test_data_directory.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+namespace adblock { -+ -+class AdblockContentBrowserClientBrowserTest : public InProcessBrowserTest { -+ public: -+ void SetUpOnMainThread() override { -+ watcher_ = std::make_unique( -+ browser()->tab_strip_model()->GetActiveWebContents(), u"PASS"); -+ watcher_->AlsoWaitForTitle(u"FAIL"); -+ embedded_test_server()->ServeFilesFromSourceDirectory( -+ net::GetWebSocketTestDataDirectory()); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ } -+ -+ void TearDownOnMainThread() override { watcher_.reset(); } -+ -+ void NavigateToHTTP(const std::string& path) { -+ // Visit a HTTPS page for testing. -+ GURL::Replacements replacements; -+ replacements.SetSchemeStr("http"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), ws_server_.GetURL(path).ReplaceComponents(replacements))); -+ } -+ -+ std::string WaitAndGetTitle() { -+ return base::UTF16ToUTF8(watcher_->WaitAndGetTitle()); -+ } -+ -+ net::SpawnedTestServer ws_server_{net::SpawnedTestServer::TYPE_WS, -+ net::GetWebSocketTestDataDirectory()}; -+ -+ private: -+ std::unique_ptr watcher_; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, -+ WebSocketConnectionNotInterrupted) { -+ // Launch a WebSocket server. -+ ASSERT_TRUE(ws_server_.Start()); -+ -+ // Disable ad-filtering. -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()) -+ ->SetAdblockEnabled(false); -+ -+ NavigateToHTTP("split_packet_check.html"); -+ -+ // WebSocket connected. -+ EXPECT_EQ("PASS", WaitAndGetTitle()); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, -+ WebSocketConnectionInterruptedButNotBlocked) { -+ // Launch a WebSocket server. -+ ASSERT_TRUE(ws_server_.Start()); -+ -+ // Enable ad-filtering. -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()) -+ ->SetAdblockEnabled(true); -+ -+ NavigateToHTTP("split_packet_check.html"); -+ -+ // WebSocket connected, there were no blocking filters. -+ EXPECT_EQ("PASS", WaitAndGetTitle()); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, -+ WebSocketConnectionInterruptedAndBlocked) { -+ // Launch a WebSocket server. -+ ASSERT_TRUE(ws_server_.Start()); -+ -+ // Intercept WebSocket and block connection via a filter. -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->SetAdblockEnabled(true); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ controller->AddCustomFilter({"*$websocket"}); -+ -+ NavigateToHTTP("split_packet_check.html"); -+ -+ // WebSocket did not connect. -+ EXPECT_EQ("FAIL", WaitAndGetTitle()); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc b/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc -@@ -0,0 +1,301 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include -+ -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/content/browser/adblock_url_loader_factory_for_test.h" -+#include "content/public/test/browser_test.h" -+#include "testing/gmock/include/gmock/gmock.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+using testing::_; -+using testing::HasSubstr; -+using testing::Mock; -+using testing::Return; -+using testing::StartsWith; -+ -+namespace adblock { -+ -+class AdblockDebugUrlTest : public InProcessBrowserTest { -+ public: -+ AdblockDebugUrlTest() {} -+ ~AdblockDebugUrlTest() override = default; -+ AdblockDebugUrlTest(const AdblockDebugUrlTest&) = delete; -+ AdblockDebugUrlTest& operator=(const AdblockDebugUrlTest&) = delete; -+ -+ protected: -+ std::string ExecuteScriptAndExtractString(const std::string& js_code) const { -+ content::WebContents* web_contents = -+ browser()->tab_strip_model()->GetActiveWebContents(); -+ return content::EvalJs(web_contents->GetPrimaryMainFrame(), js_code) -+ .ExtractString(); -+ } -+ -+ const std::string kReadPageBodyScript = -+ "document.getElementsByTagName('body')[0].firstChild.innerHTML"; -+ -+ const std::string kAdblockDebugUrl = -+ "http://" + -+ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestInvalidUrls) { -+ GURL no_command1(kAdblockDebugUrl); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), no_command1)); -+ ASSERT_EQ("INVALID_COMMAND", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL no_command2(kAdblockDebugUrl + "/"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), no_command2)); -+ ASSERT_EQ("INVALID_COMMAND", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL invalid_command_url(kAdblockDebugUrl + "/some_invalid_command"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_command_url)); -+ ASSERT_EQ("INVALID_COMMAND", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL invalid_topic(kAdblockDebugUrl + "/filter/add/%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_topic)); -+ ASSERT_EQ("INVALID_COMMAND", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL invalid_command(kAdblockDebugUrl + "/filters/ad/%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_command)); -+ ASSERT_EQ("INVALID_COMMAND", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestFilterCommands) { -+ GURL clear_filters_url(kAdblockDebugUrl + "/filters/clear"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL list_filters_url(kAdblockDebugUrl + "/filters/list"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ std::string expected_no_filters = "OK"; -+ ASSERT_EQ(expected_no_filters, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL add_filters_url(kAdblockDebugUrl + -+ "/filters/add/%2FadsPlugin%2F%2A%0A%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); -+ ASSERT_THAT(response, StartsWith("OK\n\n")); -+ ASSERT_THAT(response, HasSubstr("adsPlugin/*")); -+ ASSERT_THAT(response, HasSubstr("adsponsor.")); -+ -+ GURL remove_filter_url(kAdblockDebugUrl + "/filters/remove/%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_filter_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ std::string expected_one_filter = "OK\n\n/adsPlugin/*\n"; -+ ASSERT_EQ(expected_one_filter, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ ASSERT_EQ(expected_no_filters, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestDomainCommands) { -+ GURL clear_domains_url(kAdblockDebugUrl + "/domains/clear"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_domains_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL list_domains_url(kAdblockDebugUrl + "/domains/list"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); -+ std::string expected_no_domains = "OK"; -+ ASSERT_EQ(expected_no_domains, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL add_domain_url(kAdblockDebugUrl + -+ "/domains/add/example.com%0Adomain.org"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_domain_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); -+ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); -+ ASSERT_THAT(response, StartsWith("OK\n\n")); -+ ASSERT_THAT(response, HasSubstr("example.com")); -+ ASSERT_THAT(response, HasSubstr("domain.org")); -+ -+ GURL remove_domain_url(kAdblockDebugUrl + "/domains/remove/example.com"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_domain_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); -+ std::string expected_one_domain = "OK\n\ndomain.org\n"; -+ ASSERT_EQ(expected_one_domain, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_domains_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); -+ ASSERT_EQ(expected_no_domains, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestSubscriptionCommands) { -+ GURL clear_subscriptions_url(kAdblockDebugUrl + "/subscriptions/clear"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_subscriptions_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL list_subscriptions_url(kAdblockDebugUrl + "/subscriptions/list"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); -+ std::string expected_no_subscriptions = "OK"; -+ ASSERT_EQ(expected_no_subscriptions, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL add_subscription_url(kAdblockDebugUrl + -+ "/subscriptions/add/" -+ "https%3A%2F%2Fexample.com%2Flist1.txt%0Ahttps%3A%" -+ "2F%2Fwww.domain.org%2Flist2.txt"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_subscription_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); -+ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); -+ ASSERT_THAT(response, StartsWith("OK\n\n")); -+ ASSERT_THAT(response, HasSubstr("https://example.com/list1.txt")); -+ ASSERT_THAT(response, HasSubstr("https://www.domain.org/list2.txt")); -+ -+ GURL remove_subscription_url( -+ kAdblockDebugUrl + -+ "/subscriptions/remove/https%3A%2F%2Fwww.domain.org%2Flist2.txt"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_subscription_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); -+ std::string expected_one_subscription = -+ "OK\n\nhttps://example.com/list1.txt\n"; -+ ASSERT_EQ(expected_one_subscription, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_subscriptions_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); -+ ASSERT_EQ(expected_no_subscriptions, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestEnableAdblockCommands) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ -+ GURL enable_adblock__url(kAdblockDebugUrl + "/adblock/enable"); -+ GURL disable_adblock_url(kAdblockDebugUrl + "/adblock/disable"); -+ GURL adblock_state_url(kAdblockDebugUrl + "/adblock/state"); -+ -+ ASSERT_TRUE(controller->IsAdblockEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); -+ ASSERT_EQ("OK\n\nenabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), disable_adblock_url)); -+ ASSERT_FALSE(controller->IsAdblockEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); -+ ASSERT_EQ("OK\n\ndisabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), enable_adblock__url)); -+ ASSERT_TRUE(controller->IsAdblockEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); -+ ASSERT_EQ("OK\n\nenabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestEnableAACommands) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ -+ GURL enable_aa_url(kAdblockDebugUrl + "/aa/enable"); -+ GURL disable_aa_url(kAdblockDebugUrl + "/aa/disable"); -+ GURL aa_state_url(kAdblockDebugUrl + "/aa/state"); -+ -+ ASSERT_TRUE(controller->IsAcceptableAdsEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); -+ ASSERT_EQ("OK\n\nenabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), disable_aa_url)); -+ ASSERT_FALSE(controller->IsAcceptableAdsEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); -+ ASSERT_EQ("OK\n\ndisabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), enable_aa_url)); -+ ASSERT_TRUE(controller->IsAcceptableAdsEnabled()); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); -+ ASSERT_EQ("OK\n\nenabled", -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestFilterCommandsInOldFormat) { -+ GURL clear_filters_url(kAdblockDebugUrl + "/filters/clear"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL list_filters_url(kAdblockDebugUrl + "/filters/list"); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ std::string expected_no_filters = "OK"; -+ ASSERT_EQ(expected_no_filters, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ GURL add_filters_url(kAdblockDebugUrl + -+ "/add?payload=%2FadsPlugin%2F%2A%0A%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); -+ ASSERT_THAT(response, StartsWith("OK\n\n")); -+ ASSERT_THAT(response, HasSubstr("adsPlugin/*")); -+ ASSERT_THAT(response, HasSubstr("adsponsor.")); -+ -+ GURL remove_filter_url(kAdblockDebugUrl + "/remove?payload=%2Fadsponsor."); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_filter_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ std::string expected_one_filter = "OK\n\n/adsPlugin/*\n"; -+ ASSERT_EQ(expected_one_filter, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); -+ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); -+ ASSERT_EQ(expected_no_filters, -+ ExecuteScriptAndExtractString(kReadPageBodyScript)); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc b/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc -@@ -0,0 +1,236 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "base/environment.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "components/adblock/core/adblock_switches.h" -+#include "components/adblock/core/subscription/subscription_config.h" -+#include "components/version_info/version_info.h" -+#include "content/public/browser/browser_task_traits.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+ -+namespace adblock { -+ -+class AdblockFilterListDownloadTestBase : public InProcessBrowserTest { -+ public: -+ AdblockFilterListDownloadTestBase() -+ : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} -+ // We need to set server and request handler asap -+ void SetUpInProcessBrowserTestFixture() override { -+ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); -+ host_resolver()->AddRule("easylist-downloads.adblockplus.org", "127.0.0.1"); -+ https_server_.RegisterRequestHandler( -+ base::BindRepeating(&AdblockFilterListDownloadTestBase::RequestHandler, -+ base::Unretained(this))); -+ net::EmbeddedTestServer::ServerCertificateConfig cert_config; -+ cert_config.dns_names = {"easylist-downloads.adblockplus.org"}; -+ https_server_.SetSSLConfig(cert_config); -+ ASSERT_TRUE(https_server_.Start()); -+ SetFilterListServerPortForTesting(https_server_.port()); -+ } -+ -+ void CheckRequestParams(const net::test_server::HttpRequest& request, -+ std::string expected_disabled_value) { -+ std::string os; -+ base::ReplaceChars(version_info::GetOSType(), base::kWhitespaceASCII, "", -+ &os); -+ EXPECT_TRUE(request.relative_url.find("addonName=eyeo-chromium-sdk") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("addonVersion=1.0") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("platformVersion=1.0") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("platform=" + os) != -+ std::string::npos); -+ if (RunsOnEyeoCI()) { -+ // Those two checks below require "eyeo_application_name" and -+ // "eyeo_application_version" to be set as gn gen args. -+ EXPECT_TRUE( -+ request.relative_url.find("application=app_name_from_ci_config") != -+ std::string::npos) -+ << "Did you set \"eyeo_application_name\" gn gen arg?"; -+ EXPECT_TRUE(request.relative_url.find( -+ "applicationVersion=app_version_from_ci_config") != -+ std::string::npos) -+ << "Did you set \"eyeo_application_version\" gn gen arg?"; -+ } -+ EXPECT_TRUE( -+ request.relative_url.find("disabled=" + expected_disabled_value) != -+ std::string::npos); -+ } -+ -+ virtual std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) { -+ if (request.method == net::test_server::HttpMethod::METHOD_GET && -+ (base::StartsWith(request.relative_url, "/abp-filters-anti-cv.txt") || -+ base::StartsWith(request.relative_url, "/easylist.txt") || -+ base::StartsWith(request.relative_url, "/exceptionrules.txt"))) { -+ CheckRequestParams(request, "false"); -+ default_lists_.insert(request.relative_url.substr( -+ 1, request.relative_url.find_first_of("?") - 1)); -+ } -+ -+ // Unhandled requests result in the Embedded test server sending a 404. -+ return nullptr; -+ } -+ -+ void CloseBrowserFromAnyThread() { -+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING}) -+ ->PostTask( -+ FROM_HERE, -+ base::BindOnce( -+ &AdblockFilterListDownloadTestBase::CloseBrowserAsynchronously, -+ base::Unretained(this), browser())); -+ } -+ -+ bool RunsOnEyeoCI() { -+ auto env = base::Environment::Create(); -+ std::string value; -+ env->GetVar("CI_PROJECT_NAME", &value); -+ return value == "chromium-sdk"; -+ } -+ -+ protected: -+ net::EmbeddedTestServer https_server_; -+ std::set default_lists_; -+}; -+ -+class AdblockEnabledFilterListDownloadTest -+ : public AdblockFilterListDownloadTestBase { -+ public: -+ std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) override { -+ auto return_value = -+ AdblockFilterListDownloadTestBase::RequestHandler(request); -+ // If we get all expected requests we simply finish the test by closing -+ // the browser, otherwise test will fail with a timeout. -+ if (default_lists_.size() == 3) { -+ CloseBrowserFromAnyThread(); -+ } -+ -+ return return_value; -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockEnabledFilterListDownloadTest, -+ TestInitialDownloads) { -+ RunUntilBrowserProcessQuits(); -+} -+ -+class AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest -+ : public AdblockFilterListDownloadTestBase { -+ public: -+ AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest() { -+ const auto testing_interval = base::Seconds(1); -+ SubscriptionServiceFactory::SetUpdateCheckAndDelayIntervalsForTesting( -+ testing_interval, testing_interval); -+ } -+ -+ std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) override { -+ // If we get expected HEAD request we simply finish the test by closing -+ // the browser, otherwise test will fail with a timeout. -+ if (request.method == net::test_server::HttpMethod::METHOD_HEAD && -+ base::StartsWith(request.relative_url, "/exceptionrules.txt")) { -+ CheckRequestParams(request, "true"); -+ CloseBrowserFromAnyThread(); -+ } -+ -+ return nullptr; -+ } -+ -+ void SetUpCommandLine(base::CommandLine* command_line) override { -+ command_line->AppendSwitch(adblock::switches::kDisableAcceptableAds); -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F( -+ AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest, -+ TestInitialDownloads) { -+ RunUntilBrowserProcessQuits(); -+} -+ -+class AdblockDisabledFilterListDownloadTest -+ : public AdblockFilterListDownloadTestBase { -+ public: -+ void SetUpCommandLine(base::CommandLine* command_line) override { -+ command_line->AppendSwitch(adblock::switches::kDisableAdblock); -+ } -+ -+ void VerifyNoDownloads() { -+ ASSERT_EQ(0u, default_lists_.size()); -+ CloseBrowserFromAnyThread(); -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockDisabledFilterListDownloadTest, -+ TestInitialDownloads) { -+ // This test assumes that inital downloads (for adblock enabled) will happen -+ // within 10 seconds. When tested locally it always happens within 3 seconds. -+ base::OneShotTimer timer; -+ timer.Start( -+ FROM_HERE, base::Seconds(10), -+ base::BindOnce(&AdblockDisabledFilterListDownloadTest::VerifyNoDownloads, -+ base::Unretained(this))); -+ RunUntilBrowserProcessQuits(); -+} -+ -+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -+class AdblockPtLocaleFilterListDownloadTest -+ : public AdblockFilterListDownloadTestBase { -+ public: -+ AdblockPtLocaleFilterListDownloadTest() -+ : AdblockFilterListDownloadTestBase() { -+ setenv("LANGUAGE", "pt_PT", 1); -+ } -+ -+ std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) override { -+ EXPECT_FALSE(base::StartsWith(request.relative_url, "/easylist.txt")); -+ if (request.method == net::test_server::HttpMethod::METHOD_GET && -+ (base::StartsWith(request.relative_url, "/abp-filters-anti-cv.txt") || -+ base::StartsWith(request.relative_url, -+ "/easylistportuguese+easylist.txt") || -+ base::StartsWith(request.relative_url, "/exceptionrules.txt"))) { -+ CheckRequestParams(request, "false"); -+ default_lists_.insert(request.relative_url.substr( -+ 1, request.relative_url.find_first_of("?") - 1)); -+ } -+ -+ // If we get all expected requests we simply finish the test by closing -+ // the browser, otherwise test will fail with a timeout. -+ if (default_lists_.size() == 3) { -+ CloseBrowserFromAnyThread(); -+ } -+ -+ // Unhandled requests result in the Embedded test server sending a 404. -+ return nullptr; -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockPtLocaleFilterListDownloadTest, -+ TestInitialDownloads) { -+ RunUntilBrowserProcessQuits(); -+} -+#endif -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc b/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc -@@ -0,0 +1,358 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include -+#include "base/memory/raw_ptr.h" -+#include "base/ranges/algorithm.h" -+#include "base/run_loop.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/adblock/core/configuration/filtering_configuration.h" -+#include "components/adblock/core/configuration/persistent_filtering_configuration.h" -+#include "components/adblock/core/subscription/subscription_service.h" -+#include "components/version_info/version_info.h" -+#include "content/public/browser/browser_task_traits.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "gmock/gmock.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+#include "url/gurl.h" -+ -+namespace adblock { -+ -+class SubscriptionInstalledWaiter -+ : public SubscriptionService::SubscriptionObserver { -+ public: -+ explicit SubscriptionInstalledWaiter( -+ SubscriptionService* subscription_service) -+ : subscription_service_(subscription_service) { -+ subscription_service_->AddObserver(this); -+ } -+ -+ ~SubscriptionInstalledWaiter() override { -+ subscription_service_->RemoveObserver(this); -+ } -+ -+ void WaitUntilSubscriptionsInstalled(std::vector subscriptions) { -+ awaited_subscriptions_ = std::move(subscriptions); -+ run_loop_.Run(); -+ } -+ -+ void OnSubscriptionInstalled(const GURL& subscription_url) override { -+ awaited_subscriptions_.erase( -+ base::ranges::remove(awaited_subscriptions_, subscription_url), -+ awaited_subscriptions_.end()); -+ if (awaited_subscriptions_.empty()) { -+ run_loop_.Quit(); -+ } -+ } -+ -+ protected: -+ raw_ptr subscription_service_; -+ base::RunLoop run_loop_; -+ std::vector awaited_subscriptions_; -+}; -+ -+class AdblockFilteringConfigurationBrowserTest : public InProcessBrowserTest { -+ public: -+ void SetUpInProcessBrowserTestFixture() override { -+ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); -+ host_resolver()->AddRule("*", "127.0.0.1"); -+ embedded_test_server()->ServeFilesFromSourceDirectory( -+ "chrome/test/data/adblock"); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ } -+ -+ void SetUpOnMainThread() override { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ } -+ -+ GURL BlockingFilterListUrl() { -+ return embedded_test_server()->GetURL( -+ "/filterlist_that_blocks_resource.txt"); -+ } -+ -+ GURL ElementHidingFilterListUrl() { -+ return embedded_test_server()->GetURL( -+ "/filterlist_that_hides_resource.txt"); -+ } -+ -+ GURL AllowingFilterListUrl() { -+ return embedded_test_server()->GetURL( -+ "/filterlist_that_allows_resource.txt"); -+ } -+ -+ GURL GetPageUrl() { -+ return embedded_test_server()->GetURL("test.org", "/innermost_frame.html"); -+ } -+ -+ void NavigateToPage() { -+ ASSERT_TRUE(NavigateToURL( -+ browser()->tab_strip_model()->GetActiveWebContents(), GetPageUrl())); -+ } -+ -+ std::unique_ptr MakeConfiguration( -+ std::string name) { -+ return std::make_unique( -+ browser()->profile()->GetPrefs(), name); -+ } -+ -+ void InstallFilteringConfiguration( -+ std::unique_ptr configuration) { -+ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) -+ ->InstallFilteringConfiguration(std::move(configuration)); -+ } -+ -+ void WaitUntilSubscriptionsInstalled(std::vector subscriptions) { -+ SubscriptionInstalledWaiter waiter( -+ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile())); -+ waiter.WaitUntilSubscriptionsInstalled(std::move(subscriptions)); -+ } -+ -+ std::string GetResourcesComputedStyle() { -+ const std::string javascript = -+ "window.getComputedStyle(document.getElementById('subresource'))." -+ "display"; -+ return content::EvalJs(browser() -+ ->tab_strip_model() -+ ->GetActiveWebContents() -+ ->GetPrimaryMainFrame(), -+ javascript) -+ .ExtractString(); -+ } -+ -+ void ExpectResourceBlocked() { -+ EXPECT_EQ("none", GetResourcesComputedStyle()); -+ } -+ -+ void ExpectResourceShown() { -+ EXPECT_EQ("inline", GetResourcesComputedStyle()); -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ NoBlockingByDefault) { -+ auto configuration = MakeConfiguration("config"); -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ResourceBlockedByFilteringConfigurationsList) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddFilterList(BlockingFilterListUrl()); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl()}); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ResourceHiddenByFilteringConfigurationsList) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddFilterList(ElementHidingFilterListUrl()); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ WaitUntilSubscriptionsInstalled({ElementHidingFilterListUrl()}); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ResourceAllowedByFilteringConfigurationsList) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddFilterList(BlockingFilterListUrl()); -+ configuration->AddFilterList(ElementHidingFilterListUrl()); -+ configuration->AddFilterList(AllowingFilterListUrl()); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl(), -+ AllowingFilterListUrl(), -+ ElementHidingFilterListUrl()}); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ BlockingTakesPrecedenceBetweenConfigurations) { -+ auto blocking_configuration = MakeConfiguration("blocking"); -+ blocking_configuration->AddFilterList(BlockingFilterListUrl()); -+ -+ auto allowing_configuration = MakeConfiguration("allowing"); -+ allowing_configuration->AddFilterList(AllowingFilterListUrl()); -+ -+ InstallFilteringConfiguration(std::move(blocking_configuration)); -+ InstallFilteringConfiguration(std::move(allowing_configuration)); -+ -+ WaitUntilSubscriptionsInstalled( -+ {BlockingFilterListUrl(), AllowingFilterListUrl()}); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ElementBlockedByCustomFilter) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddCustomFilter("*resource.png"); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ElementAllowedByCustomFilter) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddCustomFilter("*resource.png"); -+ configuration->AddCustomFilter("@@*resource.png"); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ElementAllowedByAllowedDomain) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddCustomFilter("*resource.png"); -+ configuration->AddAllowedDomain(GetPageUrl().host()); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ PRE_CustomFiltersPersist) { -+ auto configuration = MakeConfiguration("persistent"); -+ // This custom filter will survive browser restart. -+ configuration->AddCustomFilter("*resource.png"); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ CustomFiltersPersist) { -+ auto configuration = MakeConfiguration("persistent"); -+ EXPECT_THAT(configuration->GetCustomFilters(), -+ testing::UnorderedElementsAre("*resource.png")); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ DisabledConfigurationDoesNotBlock) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->AddCustomFilter("*resource.png"); -+ configuration->SetEnabled(false); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ConfigurationCanBeUsedAfterInstalling) { -+ auto configuration = MakeConfiguration("config"); -+ auto* configuration_ptr = configuration.get(); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ configuration_ptr->AddCustomFilter("*resource.png"); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ ConfigurationCanBeDisabledAfterInstalling) { -+ auto configuration = MakeConfiguration("config"); -+ auto* configuration_ptr = configuration.get(); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ configuration_ptr->AddCustomFilter("*resource.png"); -+ configuration_ptr->SetEnabled(false); -+ -+ NavigateToPage(); -+ ExpectResourceShown(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ SubscriptionsDownloadedAfterConfigurationEnabled) { -+ auto configuration = MakeConfiguration("config"); -+ configuration->SetEnabled(false); -+ configuration->AddFilterList(BlockingFilterListUrl()); -+ configuration->AddFilterList(ElementHidingFilterListUrl()); -+ configuration->AddFilterList(AllowingFilterListUrl()); -+ auto* configuration_ptr = configuration.get(); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ configuration_ptr->SetEnabled(true); -+ -+ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl(), -+ AllowingFilterListUrl(), -+ ElementHidingFilterListUrl()}); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ PRE_DownloadedSubscriptionsPersistOnDisk) { -+ auto configuration = MakeConfiguration("config"); -+ // This filter list setting will survive browser restart. -+ configuration->AddFilterList(BlockingFilterListUrl()); -+ -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ // This downloaded subscription won't need to be re-downloaded after restart. -+ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl()}); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, -+ DownloadedSubscriptionsPersistOnDisk) { -+ auto configuration = MakeConfiguration("config"); -+ InstallFilteringConfiguration(std::move(configuration)); -+ -+ NavigateToPage(); -+ ExpectResourceBlocked(); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc b/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc -@@ -0,0 +1,310 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include -+ -+#include "base/ranges/algorithm.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/content/browser/adblock_filter_match.h" -+#include "components/adblock/content/browser/frame_hierarchy_builder.h" -+#include "components/adblock/content/browser/resource_classification_runner.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/blocked_content/popup_blocker_tab_helper.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+namespace adblock { -+ -+class ResourceClassificationRunnerObserver -+ : public ResourceClassificationRunner::Observer { -+ public: -+ ~ResourceClassificationRunnerObserver() override { -+ VerifyNoUnexpectedNotifications(); -+ } -+ // ResourceClassificationRunner::Observer: -+ void OnAdMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const std::vector& parent_frame_urls, -+ ContentType content_type, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ if (match_result == FilterMatchResult::kAllowRule) { -+ allowed_ads_notifications.push_back(url); -+ } else { -+ blocked_ads_notifications.push_back(url); -+ } -+ } -+ -+ void OnPageAllowed(const GURL& url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ allowed_pages_notifications.push_back(url); -+ } -+ -+ void OnPopupMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const GURL& opener_url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ if (match_result == FilterMatchResult::kAllowRule) { -+ allowed_popups_notifications.push_back(url); -+ } else { -+ blocked_popups_notifications.push_back(url); -+ } -+ } -+ -+ void VerifyNotificationSent(base::StringPiece path, std::vector& list) { -+ auto it = base::ranges::find(list, path, &GURL::ExtractFileName); -+ ASSERT_FALSE(it == list.end()) << "Path " << path << " not on list"; -+ // Remove expected notifications so that we can verify there are no -+ // unexpected notifications left by the end of each test. -+ list.erase(it); -+ } -+ -+ void VerifyNoUnexpectedNotifications() { -+ EXPECT_TRUE(blocked_ads_notifications.empty()); -+ EXPECT_TRUE(allowed_ads_notifications.empty()); -+ EXPECT_TRUE(blocked_popups_notifications.empty()); -+ EXPECT_TRUE(allowed_popups_notifications.empty()); -+ EXPECT_TRUE(allowed_pages_notifications.empty()); -+ } -+ -+ std::vector blocked_ads_notifications; -+ std::vector allowed_ads_notifications; -+ std::vector blocked_popups_notifications; -+ std::vector allowed_popups_notifications; -+ std::vector allowed_pages_notifications; -+}; -+ -+// Simulated setup: -+// http://outer.com/outermost_frame.html -+// has an iframe: http://middle.com/middle_frame.html -+// has an iframe: http://inner.com/innermost_frame.html -+// has a subresource http://inner.com/resource.png -+// -+// All of these files are in chrome/test/data/adblock. Cross-domain distribution -+// is simulated via SetupCrossSiteRedirector. -+// innermost_frame.html reports whether resource.png is visible via -+// window.top.postMessage to outermost_frame.html, which stores a global -+// subresource_visible JS variable. -+class AdblockFrameHierarchyBrowserTest : public InProcessBrowserTest { -+ public: -+ void SetUpOnMainThread() override { -+ InProcessBrowserTest::SetUpOnMainThread(); -+ host_resolver()->AddRule("*", "127.0.0.1"); -+ embedded_test_server()->ServeFilesFromSourceDirectory( -+ "chrome/test/data/adblock"); -+ content::SetupCrossSiteRedirector(embedded_test_server()); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ auto* classification_runner = -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser()->profile()); -+ classification_runner->AddObserver(&observer); -+ } -+ -+ void TearDownOnMainThread() override { -+ auto* classification_runner = -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser()->profile()); -+ classification_runner->RemoveObserver(&observer); -+ InProcessBrowserTest::TearDownOnMainThread(); -+ } -+ -+ void SetFilters(std::vector filters) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ for (auto& filter : filters) { -+ controller->AddCustomFilter(filter); -+ } -+ } -+ -+ void NavigateToOutermostFrame() { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), embedded_test_server()->GetURL( -+ "/cross-site/outer.com/outermost_frame.html"))); -+ } -+ -+ void NavigateToPopupParentFrame() { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), embedded_test_server()->GetURL( -+ "/cross-site/outer.com/popup_parent.html"))); -+ } -+ -+ void VerifyTargetResourceShown(bool expected_shown) { -+ EXPECT_EQ( -+ expected_shown, -+ content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), -+ "subresource_visible === true")); -+ } -+ -+ int NumberOfOpenTabs() { return browser()->tab_strip_model()->GetTabCount(); } -+ -+ ResourceClassificationRunnerObserver observer; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ SubresourceShownWithNoFilters) { -+ SetFilters({}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(true); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, SubresourceBlocked) { -+ SetFilters({"/resource.png"}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(false); -+ observer.VerifyNotificationSent("resource.png", -+ observer.blocked_ads_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ SubresourceAllowedViaInnerFrame) { -+ SetFilters({"/resource.png", "@@||inner.com^$document"}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(true); -+ observer.VerifyNotificationSent("resource.png", -+ observer.allowed_ads_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ SubresourceAllowedViaMiddleFrame) { -+ SetFilters({"/resource.png", "@@||middle.com^$document"}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(true); -+ observer.VerifyNotificationSent("resource.png", -+ observer.allowed_ads_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ SubresourceAllowedViaOutermostFrame) { -+ SetFilters({"/resource.png", "@@||outer.com^$document"}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(true); -+ observer.VerifyNotificationSent("resource.png", -+ observer.allowed_ads_notifications); -+ observer.VerifyNotificationSent("outermost_frame.html", -+ observer.allowed_pages_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ SubresourceBlockedWhenInvalidAllowRule) { -+ SetFilters({"/resource.png", "@@||bogus.com^$document"}); -+ NavigateToOutermostFrame(); -+ VerifyTargetResourceShown(false); -+ observer.VerifyNotificationSent("resource.png", -+ observer.blocked_ads_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ PopupHandledByChromiumWithoutFilters) { -+ // Without any popup-specific filters, blocking popups is handed over to -+ // Chromium, which has it's own heuristics that are not based on filters. -+ SetFilters({}); -+ NavigateToPopupParentFrame(); -+ // The popup was not opened: -+ EXPECT_EQ(1, NumberOfOpenTabs()); -+ // Because Chromium's built-in popup blocker stopped it: -+ EXPECT_EQ(1u, blocked_content::PopupBlockerTabHelper::FromWebContents( -+ browser()->tab_strip_model()->GetActiveWebContents()) -+ ->GetBlockedPopupsCount()); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, PopupBlockedByFilter) { -+ SetFilters({"popup.html$popup"}); -+ NavigateToPopupParentFrame(); -+ EXPECT_EQ(1, NumberOfOpenTabs()); -+ // Observer was notified about blocked popup: -+ observer.VerifyNotificationSent("popup.html", -+ observer.blocked_popups_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, PopupAllowedByFilter) { -+ SetFilters({"popup.html$popup", "@@popup.html$popup"}); -+ NavigateToPopupParentFrame(); -+ // Popup was allowed to open in a new tab -+ EXPECT_EQ(2, NumberOfOpenTabs()); -+ observer.VerifyNotificationSent("popup.html", -+ observer.allowed_popups_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ PopupAllowedByDomainSpecificFilter) { -+ // The frame that wants to open the popup is hosted on middle.com. -+ // The $popup allow rule applies to that frame. -+ SetFilters({"popup.html$popup", "@@popup.html$popup,domain=middle.com"}); -+ NavigateToPopupParentFrame(); -+ // Popup was allowed to open in a new tab -+ EXPECT_EQ(2, NumberOfOpenTabs()); -+ observer.VerifyNotificationSent("popup.html", -+ observer.allowed_popups_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ PopupNotAllowedByDomainSpecificFilter) { -+ // The frame that wants to open the popup is hosted on middle.com. -+ // The $popup allow rule does not apply because it is specific to outer.com. -+ // outer.com is not the frame that is opening the popup. -+ SetFilters({"popup.html$popup", "@@popup.html$popup,domain=outer.com"}); -+ NavigateToPopupParentFrame(); -+ EXPECT_EQ(1, NumberOfOpenTabs()); -+ // Observer was notified about blocked popup: -+ observer.VerifyNotificationSent("popup.html", -+ observer.blocked_popups_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ PopupAllowedByParentDocument) { -+ // The outermost frame has a blanket allowing rule of $document type. -+ SetFilters({"popup.html$popup", "@@||outer.com^$document,domain=outer.com"}); -+ NavigateToPopupParentFrame(); -+ // Popup was allowed to open in a new tab -+ EXPECT_EQ(2, NumberOfOpenTabs()); -+ observer.VerifyNotificationSent("popup.html", -+ observer.allowed_popups_notifications); -+ observer.VerifyNotificationSent("popup_parent.html", -+ observer.allowed_pages_notifications); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, -+ PopupAllowedByIntermediateParentDocument) { -+ // The middle frame has a blanket allowing rule of $document type. -+ SetFilters( -+ {"popup.html$popup", "@@||middle.com^$document,domain=middle.com"}); -+ NavigateToPopupParentFrame(); -+ // Popup was allowed to open in a new tab -+ EXPECT_EQ(2, NumberOfOpenTabs()); -+ observer.VerifyNotificationSent("popup.html", -+ observer.allowed_popups_notifications); -+ observer.VerifyNotificationSent("popup.html", -+ observer.allowed_pages_notifications); -+} -+ -+// More tests can be added / parametrized, e.g.: -+// - elemhide blocking filters (in conjunction with $elemhide allow rules) -+// - $subdocument-based allow rules -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc b/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc -@@ -0,0 +1,156 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/browser/ui/browser_list.h" -+#include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/content/browser/resource_classification_runner.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/sessions/content/session_tab_helper.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+ -+namespace adblock { -+ -+class AdblockMultipleTabsBrowserTest -+ : public InProcessBrowserTest, -+ public ResourceClassificationRunner::Observer { -+ public: -+ void SetUpOnMainThread() override { -+ host_resolver()->AddRule(kTestDomain, "127.0.0.1"); -+ embedded_test_server()->ServeFilesFromSourceDirectory( -+ "chrome/test/data/adblock"); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser()->profile()) -+ ->AddObserver(this); -+ SetFilters({"blocked.png", "allowed.png", "@@allowed.png"}); -+ } -+ -+ void TearDownInProcessBrowserTestFixture() override { -+ ASSERT_EQ(kTabsCount, static_cast(tabs_with_blocked_resource_.size())); -+ ASSERT_EQ(kTabsCount, static_cast(tabs_with_allowed_resource_.size())); -+ } -+ -+ void SetFilters(std::vector filters) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ for (auto& filter : filters) { -+ controller->AddCustomFilter(filter); -+ } -+ } -+ -+ void RestoreTabs(Browser* browser) { -+ content::DOMMessageQueue queue; -+ RecentTabsSubMenuModel menu(nullptr, browser); -+ menu.ExecuteCommand(menu.GetFirstRecentTabsCommandId(), 0); -+ for (int i = 0; i < kTabsCount; ++i) { -+ std::string message; -+ EXPECT_TRUE(queue.WaitForMessage(&message)); -+ EXPECT_EQ("\"READY\"", message); -+ } -+ } -+ -+ // ResourceClassificationRunner::Observer: -+ void OnAdMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const std::vector& parent_frame_urls, -+ ContentType content_type, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ const content::WebContents* wc = -+ content::WebContents::FromRenderFrameHost(render_frame_host); -+ if (match_result == FilterMatchResult::kBlockRule && -+ url.path() == "/blocked.png") { -+ tabs_with_blocked_resource_.insert( -+ sessions::SessionTabHelper::IdForTab(wc).id()); -+ } else if (match_result == FilterMatchResult::kAllowRule && -+ url.path() == "/allowed.png") { -+ tabs_with_allowed_resource_.insert( -+ sessions::SessionTabHelper::IdForTab(wc).id()); -+ } -+ } -+ -+ void OnPageAllowed(const GURL& url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override {} -+ -+ void OnPopupMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const GURL& opener_url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override {} -+ -+ protected: -+ const int kTabsCount = 4; -+ const char* kTestDomain = "example.com"; -+ std::set tabs_with_blocked_resource_; -+ std::set tabs_with_allowed_resource_; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockMultipleTabsBrowserTest, PRE_OpenManyTabs) { -+ // Load page in already opened tab -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), -+ embedded_test_server()->GetURL(kTestDomain, "/tab-restore.html"))); -+ // Open more tabs -+ for (int i = 0; i < kTabsCount - 1; ++i) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( -+ browser(), -+ embedded_test_server()->GetURL(kTestDomain, "/tab-restore.html"), -+ WindowOpenDisposition::NEW_FOREGROUND_TAB, -+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); -+ } -+ EXPECT_EQ(kTabsCount, browser()->tab_strip_model()->count()); -+ EXPECT_EQ(kTabsCount, static_cast(tabs_with_blocked_resource_.size())); -+ EXPECT_EQ(kTabsCount, static_cast(tabs_with_allowed_resource_.size())); -+ -+ // Open a new browser instance -+ ui_test_utils::NavigateToURLWithDisposition( -+ browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::NEW_WINDOW, -+ ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER); -+ BrowserList* active_browser_list = BrowserList::GetInstance(); -+ EXPECT_EQ(2u, active_browser_list->size()); -+ -+ // Close the 1st browser and clear tabs test data -+ CloseBrowserSynchronously(browser()); -+ EXPECT_EQ(1u, active_browser_list->size()); -+ tabs_with_blocked_resource_.clear(); -+ tabs_with_allowed_resource_.clear(); -+ -+ Browser* browser = active_browser_list->get(0); -+ // Restore tabs from1 st browser instance (already closed) in 2nd instance -+ RestoreTabs(browser); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockMultipleTabsBrowserTest, OpenManyTabs) { -+ ASSERT_EQ(0u, tabs_with_blocked_resource_.size()); -+ ASSERT_EQ(0u, tabs_with_allowed_resource_.size()); -+ // Restore tabs from previous session (previous test) -+ RestoreTabs(browser()); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc b/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc -@@ -0,0 +1,77 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+namespace adblock { -+ -+class AdblockNonASCIIBrowserTest : public InProcessBrowserTest { -+ public: -+ void SetUpOnMainThread() override { -+ host_resolver()->AddRule("xn----dtbfdbwspgnceulm.xn--p1ai", "127.0.0.1"); -+ embedded_test_server()->ServeFilesFromSourceDirectory( -+ "chrome/test/data/adblock"); -+ content::SetupCrossSiteRedirector(embedded_test_server()); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ } -+ -+ void SetFilters(std::vector filters) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ for (auto& filter : filters) { -+ controller->AddCustomFilter(filter); -+ } -+ } -+ -+ std::string ExecuteScriptAndExtractString(const std::string& js_code) const { -+ content::WebContents* web_contents = -+ browser()->tab_strip_model()->GetActiveWebContents(); -+ return content::EvalJs(web_contents->GetPrimaryMainFrame(), js_code) -+ .ExtractString(); -+ } -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockNonASCIIBrowserTest, BlockNonASCII) { -+ static constexpr char kCheckVisibility[] = -+ R"(getComputedStyle(document.getElementsByClassName("форум")[0]).display)"; -+ -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), -+ embedded_test_server()->GetURL("форум-трейдеров.рф", "/non-ascii.html"))); -+ EXPECT_EQ("block", ExecuteScriptAndExtractString(kCheckVisibility)); -+ -+ SetFilters({"xn----dtbfdbwspgnceulm.xn--p1ai##.форум"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL( -+ browser(), -+ embedded_test_server()->GetURL("форум-трейдеров.рф", "/non-ascii.html"))); -+ -+ EXPECT_EQ("none", ExecuteScriptAndExtractString(kCheckVisibility)); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc b/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc -@@ -0,0 +1,204 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "base/files/file_util.h" -+#include "base/files/scoped_temp_dir.h" -+#include "base/ranges/algorithm.h" -+#include "base/run_loop.h" -+#include "base/strings/string_split.h" -+#include "base/test/bind.h" -+#include "base/threading/thread_restrictions.h" -+#include "base/time/time.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" -+#include "chrome/browser/adblock/subscription_service_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/subscription/subscription_config.h" -+#include "components/adblock/core/subscription/subscription_service.h" -+#include "components/version_info/version_info.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/http/http_request_headers.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+ -+namespace adblock { -+ -+class AdblockSubscriptionServiceBrowserTest -+ : public InProcessBrowserTest, -+ public SubscriptionService::SubscriptionObserver { -+ public: -+ AdblockSubscriptionServiceBrowserTest() { -+ SubscriptionServiceFactory::SetUpdateCheckAndDelayIntervalsForTesting( -+ base::Seconds(1), base::Seconds(1)); -+ } -+ void SetUpOnMainThread() override { -+ InProcessBrowserTest::SetUpOnMainThread(); -+ https_server_ = std::make_unique( -+ net::EmbeddedTestServer::TYPE_HTTPS); -+ https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK); -+ } -+ -+ bool RequestHeadersContainAcceptLanguage( -+ const net::test_server::HttpRequest& request) { -+ const auto accept_language_it = -+ request.headers.find(net::HttpRequestHeaders::kAcceptLanguage); -+ return accept_language_it != request.headers.end() && -+ !accept_language_it->second.empty(); -+ } -+ -+ bool RequestHeadersContainAcceptEncodingBrotli( -+ const net::test_server::HttpRequest& request) { -+ const auto accept_encoding_it = -+ request.headers.find(net::HttpRequestHeaders::kAcceptEncoding); -+ if (accept_encoding_it == request.headers.end()) { -+ return false; -+ } -+ const auto split_encodings = -+ base::SplitString(accept_encoding_it->second, ",", -+ base::WhitespaceHandling::TRIM_WHITESPACE, -+ base::SplitResult::SPLIT_WANT_NONEMPTY); -+ return base::ranges::find(split_encodings, "br") != split_encodings.end(); -+ } -+ -+ std::unique_ptr -+ HandleSubscriptionUpdateRequestWithUrlCheck( -+ std::string expected_url_part, -+ const net::test_server::HttpRequest& request) { -+ static const char kSubscriptionHeader[] = -+ "[Adblock Plus 2.0]\n" -+ "! Checksum: X5A8vtJDBW2a9EgS9glqbg\n" -+ "! Version: 202202061935\n" -+ "! Last modified: 06 Feb 2022 19:35 UTC\n" -+ "! Expires: 1 days (update frequency)\n\n"; -+ if (base::StartsWith(request.relative_url, kSubscription, -+ base::CompareCase::SENSITIVE) && -+ !request_already_handled_) { -+ request_already_handled_ = true; -+ EXPECT_TRUE(RequestHeadersContainAcceptLanguage(request)); -+ EXPECT_TRUE(RequestHeadersContainAcceptEncodingBrotli(request)); -+ std::string os; -+ base::ReplaceChars(version_info::GetOSType(), base::kWhitespaceASCII, "", -+ &os); -+ EXPECT_TRUE(request.relative_url.find(expected_url_part) != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("addonName=eyeo-chromium-sdk") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("addonVersion=1.0") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("platformVersion=1.0") != -+ std::string::npos); -+ EXPECT_TRUE(request.relative_url.find("platform=" + os) != -+ std::string::npos); -+ auto http_response = -+ std::make_unique(); -+ http_response->set_code(net::HTTP_OK); -+ http_response->set_content(kSubscriptionHeader); -+ http_response->set_content_type("text/plain"); -+ return std::move(http_response); -+ } -+ -+ // Unhandled requests result in the Embedded test server sending a 404. -+ return nullptr; -+ } -+ -+ void ExpectFilterListRequestMadeWithLastVersion(std::string last_version) { -+ https_server_->RegisterRequestHandler( -+ base::BindRepeating(&AdblockSubscriptionServiceBrowserTest:: -+ HandleSubscriptionUpdateRequestWithUrlCheck, -+ base::Unretained(this), last_version)); -+ ASSERT_TRUE(https_server_->Start(kPort)); -+ } -+ -+ // adblock::SubscriptionService::SubscriptionObserver -+ void OnSubscriptionInstalled(const GURL& url) override { -+ if (base::StartsWith(url.spec(), -+ https_server_->GetURL(kSubscription).spec())) { -+ // In order to ensure next run requests an update, mark the subscription -+ // as almost expired. -+ SubscriptionPersistentMetadataFactory::GetForBrowserContext( -+ browser()->profile()) -+ ->SetExpirationInterval(url, base::Milliseconds(1)); -+ CloseBrowserAsynchronously(browser()); -+ } -+ } -+ -+ std::unique_ptr https_server_; -+ bool request_already_handled_ = false; -+ static const std::string kSubscription; -+ // Port is hardcoded so the server url is the same across tests -+ static const int kPort = 65432; -+}; -+ -+const std::string AdblockSubscriptionServiceBrowserTest::kSubscription = -+ "/subscription.txt"; -+ -+IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, PRE_LastVersion) { -+ ExpectFilterListRequestMadeWithLastVersion("&lastVersion=0&"); -+ // Downloading a filter list and setting its expiry time to almost zero, so -+ // the next run will have to update it ASAP. -+ -+ auto* subscription_service = -+ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()); -+ subscription_service->AddObserver(this); -+ // Using a custom subscription URL here because before test sets -+ // up the server then SubscriptionService already started fetching default -+ // subscriptions. -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->InstallSubscription(https_server_->GetURL(kSubscription)); -+ // Wait until subscription is downloaded and stored. -+ RunUntilBrowserProcessQuits(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, LastVersion) { -+ ExpectFilterListRequestMadeWithLastVersion("&lastVersion=202202061935&"); -+ auto* subscription_service = -+ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()); -+ subscription_service->AddObserver(this); -+ // Wait for subscription update to trigger a network request. -+ RunUntilBrowserProcessQuits(); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, -+ FilterFileDeletedAfterConversion) { -+ base::ScopedAllowBlockingForTesting allow_blocking; -+ ConversionExecutors* conversion_executors = -+ SubscriptionServiceFactory::GetInstance(); -+ DCHECK(conversion_executors); -+ base::ScopedTempDir temp_dir; -+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); -+ const auto filter_list_path = temp_dir.GetPath().AppendASCII("easylist.txt"); -+ std::vector filter_list_contents = { -+ "[\"Adblock Plus 2.0\"]\n", "invalid file"}; -+ for (const auto& file_content : filter_list_contents) { -+ base::WriteFile(filter_list_path, file_content); -+ ASSERT_TRUE(base::PathExists(filter_list_path)); -+ base::RunLoop run_loop; -+ conversion_executors->ConvertFilterListFile( -+ DefaultSubscriptionUrl(), filter_list_path, -+ base::BindLambdaForTesting( -+ [&run_loop](ConversionResult result) { run_loop.Quit(); })); -+ run_loop.Run(); -+ ASSERT_FALSE(base::PathExists(filter_list_path)); -+ } -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc b/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc -@@ -0,0 +1,256 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include "base/json/json_reader.h" -+#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "components/adblock/core/activeping_telemetry_topic_provider.h" -+#include "content/public/browser/browser_task_traits.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+ -+namespace adblock { -+ -+class AdblockTelemetryServiceBrowserTestBase : public InProcessBrowserTest { -+ public: -+ // We need to set server and request handler asap -+ void SetUpInProcessBrowserTestFixture() override { -+ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); -+ host_resolver()->AddRule( -+ ActivepingTelemetryTopicProvider::DefaultBaseUrl().host(), "127.0.0.1"); -+ http_server_.RegisterRequestHandler(base::BindRepeating( -+ &AdblockTelemetryServiceBrowserTestBase::RequestHandler, -+ base::Unretained(this))); -+ ASSERT_TRUE(http_server_.Start()); -+ ActivepingTelemetryTopicProvider::SetHttpPortForTesting( -+ http_server_.port()); -+ auto testing_interval = base::Seconds(2); -+ ActivepingTelemetryTopicProvider::SetIntervalsForTesting(testing_interval); -+ AdblockTelemetryServiceFactory::GetInstance() -+ ->SetCheckAndDelayIntervalsForTesting(testing_interval, -+ testing_interval); -+ } -+ -+ base::Value* GetFirstPing(absl::optional& parsed) { -+ return GetPayload(parsed)->Find("first_ping"); -+ } -+ -+ base::Value* GetLastPing(absl::optional& parsed) { -+ return GetPayload(parsed)->Find("last_ping"); -+ } -+ -+ base::Value* GetLastPingTag(absl::optional& parsed) { -+ return GetPayload(parsed)->Find("last_ping_tag"); -+ } -+ -+ base::Value* GetPreviousLastPing(absl::optional& parsed) { -+ return GetPayload(parsed)->Find("previous_last_ping"); -+ } -+ -+ void CloseBrowserFromAnyThread() { -+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING}) -+ ->PostTask(FROM_HERE, -+ base::BindOnce(&AdblockTelemetryServiceBrowserTestBase:: -+ CloseBrowserAsynchronously, -+ base::Unretained(this), browser())); -+ } -+ -+ std::unique_ptr CreateResponse( -+ const std::string& token) { -+ auto http_response = -+ std::make_unique(); -+ http_response->set_code(net::HTTP_OK); -+ http_response->set_content("{\"token\": \"" + token + "\"}"); -+ http_response->set_content_type("text/plain"); -+ return std::move(http_response); -+ } -+ -+ virtual std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) = 0; -+ -+ private: -+ base::Value::Dict* GetPayload(absl::optional& parsed) { -+ EXPECT_TRUE(parsed && parsed->is_dict()); -+ base::Value::Dict* parsed_dict = parsed->GetIfDict(); -+ EXPECT_TRUE(parsed_dict); -+ base::Value::Dict* payload = parsed_dict->FindDict("payload"); -+ EXPECT_TRUE(payload); -+ return payload; -+ } -+ -+ net::EmbeddedTestServer http_server_; -+}; -+ -+// Test three initial pings each after startup and each fails for the 1st time -+class AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest -+ : public AdblockTelemetryServiceBrowserTestBase { -+ public: -+ std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) override { -+ EXPECT_TRUE(base::StartsWith(request.relative_url, -+ "/topic/eyeochromium_activeping/version/1")); -+ EXPECT_TRUE(request.has_content); -+ absl::optional parsed = -+ base::JSONReader::Read(request.content); -+ base::Value* first_ping = GetFirstPing(parsed); -+ base::Value* last_ping = GetLastPing(parsed); -+ base::Value* previous_last_ping = GetPreviousLastPing(parsed); -+ -+ if (expected_first_ping_.empty()) { -+ EXPECT_FALSE(first_ping); -+ } else { -+ EXPECT_EQ(expected_first_ping_, *first_ping); -+ } -+ -+ if (expected_last_ping_.empty()) { -+ EXPECT_FALSE(last_ping); -+ } else { -+ EXPECT_EQ(expected_last_ping_, *last_ping); -+ } -+ -+ if (expected_previous_last_ping_.empty()) { -+ EXPECT_FALSE(previous_last_ping); -+ } else { -+ EXPECT_EQ(expected_previous_last_ping_, *previous_last_ping); -+ } -+ -+ if (!attempt_++) { -+ // Force retry by 404 response but 1st save last_ping_tag if any -+ base::Value* last_ping_tag = GetLastPingTag(parsed); -+ if (last_ping_tag) { -+ previous_last_ping_tag_ = last_ping_tag->GetString(); -+ } -+ return nullptr; -+ } -+ -+ // Verifies that retried ping has the same last_ping_tag -+ if (!previous_last_ping_tag_.empty()) { -+ base::Value* last_ping_tag = GetLastPingTag(parsed); -+ EXPECT_EQ(previous_last_ping_tag_, *last_ping_tag); -+ } -+ -+ // If we get expected telemetry ping with retry we simply finish the test -+ // by closing the browser, otherwise test will fail with a timeout. -+ CloseBrowserFromAnyThread(); -+ -+ // This will be still processed before CloseBrowserFromAnyThread() applies -+ return CreateResponse(server_response_); -+ } -+ -+ void TearDownInProcessBrowserTestFixture() override { -+ // Make sure we called RequestHandler exactly twice: 1st ping failed, 2nd -+ // was successful -+ EXPECT_EQ(2, attempt_); -+ } -+ -+ protected: -+ std::string server_response_; -+ std::string expected_first_ping_; -+ std::string expected_last_ping_; -+ std::string expected_previous_last_ping_; -+ -+ private: -+ int attempt_ = 0; -+ std::string previous_last_ping_tag_ = ""; -+}; -+ -+IN_PROC_BROWSER_TEST_F( -+ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, -+ PRE_PRE_TestPing) { -+ // Sets the ping to be returned by the server and checked in the next test -+ server_response_ = "11111"; -+ RunUntilBrowserProcessQuits(); -+} -+ -+IN_PROC_BROWSER_TEST_F( -+ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, -+ PRE_TestPing) { -+ // Sets the ping to be returned by the server and checked in the next test -+ server_response_ = "22222"; -+ expected_first_ping_ = expected_last_ping_ = "11111"; -+ RunUntilBrowserProcessQuits(); -+} -+ -+IN_PROC_BROWSER_TEST_F( -+ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, -+ TestPing) { -+ expected_first_ping_ = "11111"; -+ expected_last_ping_ = "22222"; -+ expected_previous_last_ping_ = "11111"; -+ RunUntilBrowserProcessQuits(); -+} -+ -+// Test three inital pings -+class AdblockTelemetryServiceSubsequentPingsBrowserTest -+ : public AdblockTelemetryServiceBrowserTestBase { -+ public: -+ std::unique_ptr RequestHandler( -+ const net::test_server::HttpRequest& request) override { -+ EXPECT_TRUE(base::StartsWith(request.relative_url, -+ "/topic/eyeochromium_activeping/version/1")); -+ EXPECT_TRUE(request.has_content); -+ absl::optional parsed = -+ base::JSONReader::Read(request.content); -+ base::Value* first_ping = GetFirstPing(parsed); -+ base::Value* last_ping = GetLastPing(parsed); -+ base::Value* previous_last_ping = GetPreviousLastPing(parsed); -+ -+ if (count_ == 1) { -+ // No ping payload in the very 1st ping -+ EXPECT_FALSE(first_ping); -+ EXPECT_FALSE(last_ping); -+ } else if (count_ == 2) { -+ // For 2nd ping `first_ping` == `last_ping` -+ EXPECT_EQ(first_ping_, *first_ping); -+ EXPECT_EQ(first_ping_, *last_ping); -+ } else if (count_ == 3) { -+ // From 3rd ping onward `first_ping` != `last_ping` and we also get -+ // `previous_last_ping` -+ EXPECT_EQ(first_ping_, *first_ping); -+ EXPECT_EQ(second_ping_, *last_ping); -+ EXPECT_EQ(first_ping_, *previous_last_ping); -+ } -+ -+ // If we get three expected telemetry pings we simply finish the test by -+ // closing the browser, otherwise test will fail with a timeout. -+ if (count_ == 3) { -+ CloseBrowserFromAnyThread(); -+ return nullptr; -+ } -+ return CreateResponse(count_++ == 1 ? first_ping_ : second_ping_); -+ } -+ -+ void TearDownInProcessBrowserTestFixture() override { -+ // Make sure we called RequestHandler exactly three times -+ EXPECT_EQ(3, count_); -+ } -+ -+ private: -+ const std::string first_ping_ = "11111"; -+ const std::string second_ping_ = "22222"; -+ int count_ = 1; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockTelemetryServiceSubsequentPingsBrowserTest, -+ TestPing) { -+ RunUntilBrowserProcessQuits(); -+} -+ -+} // namespace adblock -diff --git a/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc b/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc -@@ -0,0 +1,553 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+#include -+#include -+#include "base/files/file_path.h" -+#include "base/files/file_util.h" -+#include "base/files/scoped_temp_dir.h" -+#include "base/functional/bind.h" -+#include "base/path_service.h" -+#include "base/strings/string_util.h" -+#include "chrome/browser/adblock/adblock_controller_factory.h" -+#include "chrome/browser/adblock/resource_classification_runner_factory.h" -+#include "chrome/browser/profiles/profile.h" -+#include "chrome/browser/ui/browser.h" -+#include "chrome/test/base/in_process_browser_test.h" -+#include "chrome/test/base/ui_test_utils.h" -+#include "components/adblock/content/browser/resource_classification_runner.h" -+#include "components/adblock/core/adblock_controller.h" -+#include "components/adblock/core/common/adblock_constants.h" -+#include "components/web_package/web_bundle_builder.h" -+#include "content/public/common/content_switches.h" -+#include "content/public/test/browser_test.h" -+#include "content/public/test/browser_test_utils.h" -+#include "net/dns/mock_host_resolver.h" -+#include "net/test/embedded_test_server/embedded_test_server.h" -+#include "net/test/embedded_test_server/request_handler_util.h" -+#include "testing/gtest/include/gtest/gtest.h" -+ -+namespace adblock { -+ -+class AdblockWebBundleBrowserTest -+ : public InProcessBrowserTest, -+ public ResourceClassificationRunner::Observer { -+ public: -+ void SetUpOnMainThread() override { -+ InProcessBrowserTest::SetUpOnMainThread(); -+ host_resolver()->AddRule("*", "127.0.0.1"); -+ embedded_test_server()->RegisterDefaultHandler( -+ base::BindRepeating(&AdblockWebBundleBrowserTest::HandleFileRequest, -+ base::Unretained(this))); -+ ASSERT_TRUE(embedded_test_server()->Start()); -+ PrepareTempDirWithContent(); -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser()->profile()) -+ ->AddObserver(this); -+ } -+ -+ void TearDownOnMainThread() override { -+ ResourceClassificationRunnerFactory::GetForBrowserContext( -+ browser()->profile()) -+ ->RemoveObserver(this); -+ InProcessBrowserTest::TearDownOnMainThread(); -+ } -+ -+ void PrepareTempDirWithContent() { -+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); -+ CreateIndexFiles(); -+ CreateByResourceWebBundle(); -+ CreateByBundleFileWebBundle(); -+ CreateByScopeFileWebBundle(); -+ CreateUuidInPackageByResourceWebBundle(); -+ CreateUuidInPackageByScopeWebBundle(); -+ } -+ -+ std::string GetFileContentFromTestDir( -+ base::FilePath::StringType relative_path) { -+ base::FilePath root; -+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root)); -+ root = root.AppendASCII("chrome/test/data/adblock/wbn"); -+ std::string content; -+ CHECK(base::ReadFileToString(root.Append(relative_path), &content)); -+ return content; -+ } -+ -+ std::string GetFileContentFromTempDir(base::StringPiece relative_path) { -+ std::string content; -+ CHECK(base::ReadFileToString(temp_dir_.GetPath().AppendASCII(relative_path), -+ &content)); -+ return content; -+ } -+ -+ // In order for an html file to use absolute URLs in 'src' attributes to -+ // resources hosted by the embedded_test_server(), we need to replace -+ // {{{baseUrl}}} with the server's URL. It changes for every run. -+ std::string GetHtmlContentWithReplacements( -+ base::FilePath::StringType relative_path) { -+ std::string content = GetFileContentFromTestDir(relative_path); -+ auto url = embedded_test_server()->GetURL("example.org", "/").spec(); -+ url.pop_back(); -+ base::ReplaceSubstringsAfterOffset(&content, 0, "{{{baseUrl}}}", url); -+ return content; -+ } -+ -+ void SetUpCommandLine(base::CommandLine* command_line) override { -+ // This is needed to accesss cross origin iframes data -+ command_line->AppendSwitch(switches::kDisableWebSecurity); -+ InProcessBrowserTest::SetUpCommandLine(command_line); -+ } -+ -+ void CreateByResourceWebBundle() { -+ web_package::WebBundleBuilder builder; -+ builder.AddExchange("by_resource/blue_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/blue_subresource_loading.css"))); -+ builder.AddExchange("by_resource/blue_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/blue_subresource_loading.png"))); -+ builder.AddExchange("by_resource/red_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/red_subresource_loading.css"))); -+ builder.AddExchange("by_resource/red_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/red_subresource_loading.png"))); -+ builder.AddExchange( -+ "by_resource/xhr_result_1_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/xhr_result_1_subresource_loading.json"))); -+ builder.AddExchange( -+ "by_resource/fetch_result_1_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_resource/fetch_result_1_subresource_loading.json"))); -+ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); -+ const auto binary_data = builder.CreateBundle(); -+ ASSERT_TRUE(base::WriteFile( -+ temp_dir_.GetPath().AppendASCII("by_resource.wbn"), binary_data)); -+ } -+ -+ void CreateByBundleFileWebBundle() { -+ web_package::WebBundleBuilder builder; -+ builder.AddExchange("by_bundle_file/green_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/green_subresource_loading.css"))); -+ builder.AddExchange("by_bundle_file/green_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/green_subresource_loading.png"))); -+ builder.AddExchange("by_bundle_file/purple_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/purple_subresource_loading.css"))); -+ builder.AddExchange("by_bundle_file/purple_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/purple_subresource_loading.png"))); -+ builder.AddExchange( -+ "by_bundle_file/xhr_result_2_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/xhr_result_2_subresource_loading.json"))); -+ builder.AddExchange( -+ "by_bundle_file/fetch_result_2_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_bundle_file/fetch_result_2_subresource_loading.json"))); -+ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); -+ const auto binary_data = builder.CreateBundle(); -+ ASSERT_TRUE(base::WriteFile( -+ temp_dir_.GetPath().AppendASCII("by_bundle_file.wbn"), binary_data)); -+ } -+ -+ void CreateByScopeFileWebBundle() { -+ web_package::WebBundleBuilder builder; -+ builder.AddExchange("by_scope/orange_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/orange_subresource_loading.css"))); -+ builder.AddExchange("by_scope/orange_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/orange_subresource_loading.png"))); -+ builder.AddExchange("by_scope/pink_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/pink_subresource_loading.css"))); -+ builder.AddExchange("by_scope/pink_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/pink_subresource_loading.png"))); -+ builder.AddExchange( -+ "by_scope/xhr_result_3_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/xhr_result_3_subresource_loading.json"))); -+ builder.AddExchange( -+ "by_scope/fetch_result_3_subresource_loading.json", -+ {{":status", "200"}, {"content-type", "application/json"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "by_scope/fetch_result_3_subresource_loading.json"))); -+ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); -+ const auto binary_data = builder.CreateBundle(); -+ ASSERT_TRUE(base::WriteFile(temp_dir_.GetPath().AppendASCII("by_scope.wbn"), -+ binary_data)); -+ } -+ -+ void CreateUuidInPackageByResourceWebBundle() { -+ web_package::WebBundleBuilder builder; -+ builder.AddExchange( -+ "uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae", -+ {{":status", "200"}, {"content-type", "text/html"}}, -+ GetFileContentFromTempDir("uuid_in_package_by_resource_index.html")); -+ builder.AddExchange( -+ "uuid_in_package_by_resource/skyblue_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_resource/skyblue_subresource_loading.css"))); -+ builder.AddExchange( -+ "uuid_in_package_by_resource/skyblue_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_resource/skyblue_subresource_loading.png"))); -+ builder.AddExchange( -+ "uuid_in_package_by_resource/yellowgreen_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir( -+ FILE_PATH_LITERAL("uuid_in_package_by_resource/" -+ "yellowgreen_subresource_loading.css"))); -+ builder.AddExchange( -+ "uuid_in_package_by_resource/yellowgreen_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir( -+ FILE_PATH_LITERAL("uuid_in_package_by_resource/" -+ "yellowgreen_subresource_loading.png"))); -+ builder.AddPrimaryURL( -+ "uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae"); -+ const auto binary_data = builder.CreateBundle(); -+ ASSERT_TRUE(base::WriteFile( -+ temp_dir_.GetPath().AppendASCII("uuid_in_package_by_resource.wbn"), -+ binary_data)); -+ } -+ -+ void CreateUuidInPackageByScopeWebBundle() { -+ web_package::WebBundleBuilder builder; -+ builder.AddExchange( -+ "uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ad", -+ {{":status", "200"}, {"content-type", "text/html"}}, -+ GetFileContentFromTempDir("uuid_in_package_by_scope_index.html")); -+ builder.AddExchange( -+ "uuid_in_package_by_scope/navy_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_scope/navy_subresource_loading.css"))); -+ builder.AddExchange( -+ "uuid_in_package_by_scope/navy_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_scope/navy_subresource_loading.png"))); -+ builder.AddExchange( -+ "uuid_in_package_by_scope/orangered_subresource_loading.css", -+ {{":status", "200"}, {"content-type", "text/css"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_scope/orangered_subresource_loading.css"))); -+ builder.AddExchange( -+ "uuid_in_package_by_scope/orangered_subresource_loading.png", -+ {{":status", "200"}, {"content-type", "image/png"}}, -+ GetFileContentFromTestDir(FILE_PATH_LITERAL( -+ "uuid_in_package_by_scope/orangered_subresource_loading.png"))); -+ builder.AddPrimaryURL( -+ "uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ad"); -+ const auto binary_data = builder.CreateBundle(); -+ ASSERT_TRUE(base::WriteFile( -+ temp_dir_.GetPath().AppendASCII("uuid_in_package_by_scope.wbn"), -+ binary_data)); -+ } -+ -+ void CreateIndexFiles() { -+ auto html = GetHtmlContentWithReplacements( -+ FILE_PATH_LITERAL("index.html.mustache")); -+ ASSERT_TRUE( -+ base::WriteFile(temp_dir_.GetPath().AppendASCII("index.html"), html)); -+ html = GetHtmlContentWithReplacements( -+ FILE_PATH_LITERAL("uuid_in_package_by_resource/index.html.mustache")); -+ ASSERT_TRUE(base::WriteFile(temp_dir_.GetPath().AppendASCII( -+ "uuid_in_package_by_resource_index.html"), -+ html)); -+ html = GetHtmlContentWithReplacements( -+ FILE_PATH_LITERAL("uuid_in_package_by_scope/index.html.mustache")); -+ ASSERT_TRUE(base::WriteFile( -+ temp_dir_.GetPath().AppendASCII("uuid_in_package_by_scope_index.html"), -+ html)); -+ } -+ -+ std::unique_ptr HandleFileRequest( -+ const net::test_server::HttpRequest& request) { -+ auto response = -+ net::test_server::HandleFileRequest(temp_dir_.GetPath(), request); -+ if (response) { -+ auto* basic = -+ static_cast(response.get()); -+ if (temp_dir_.GetPath() -+ .AppendASCII(request.GetURL().path().substr(1)) -+ .MatchesExtension(FILE_PATH_LITERAL(".wbn"))) { -+ basic->set_content_type("application/webbundle"); -+ } -+ basic->AddCustomHeader("X-Content-Type-Options", "nosniff"); -+ } -+ return response; -+ } -+ -+ GURL GetUrl() { -+ return embedded_test_server()->GetURL("example.org", "/index.html"); -+ } -+ -+ void SetFilters(std::vector filters) { -+ auto* controller = -+ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); -+ controller->RemoveCustomFilter(kAllowlistEverythingFilter); -+ for (auto& filter : filters) { -+ controller->AddCustomFilter(filter); -+ } -+ } -+ -+ bool EvaluateJs(std::string value) { -+ return content::EvalJs(browser() -+ ->tab_strip_model() -+ ->GetActiveWebContents() -+ ->GetPrimaryMainFrame(), -+ value) -+ .ExtractBool(); -+ } -+ -+ // 2nd argument allows to specify iframe instead of a main document -+ bool IsImageLoaded(std::string selector, -+ std::string document_node = "document") { -+ return EvaluateJs( -+ "(function(){ node = (" + document_node + ").querySelector('" + -+ selector + -+ "'); return node.complete && node.naturalHeight !== 0; })()"); -+ } -+ -+ bool IsCssBlocked(std::string selector) { -+ // On the test page, a box with this |id| is grey if element-specific CSS -+ // was blocked. Grey is the default color for divs, and gets overridden -+ // to element-specific colors by blockable CSS files. -+ return EvaluateJs( -+ "(function(){ return " -+ "window.getComputedStyle(document.querySelector('" + -+ selector + "')).backgroundColor == 'rgb(128, 128, 128)'; })()"); -+ } -+ -+ // Waits until the textContent of the selected item stops being "Pending" and -+ // returns whatever it's final value is. -+ // This asynchronous wait is because scripts that change the textContent may -+ // execute with a delay. -+ std::string GetSelectorTextContent(std::string selector) { -+ return content::EvalJs(browser() -+ ->tab_strip_model() -+ ->GetActiveWebContents() -+ ->GetPrimaryMainFrame(), -+ R"( -+ (async function (selector) { -+ return new Promise(resolve => { -+ if (!document.querySelector(selector).textContent.includes('Pending')) { -+ return resolve(document.querySelector(selector).textContent); -+ } -+ -+ const observer = new MutationObserver(mutations => { -+ if (!document.querySelector(selector).textContent.includes('Pending')) { -+ resolve(document.querySelector(selector).textContent); -+ observer.disconnect(); -+ } -+ }); -+ -+ observer.observe(document.body, { -+ childList: true, -+ subtree: true -+ }); -+ }); -+})(' )" + selector + "');") -+ .ExtractString(); -+ } -+ -+ bool IsXhrOrFetchRequestBlocked(std::string selector) { -+ return GetSelectorTextContent(selector).find("Error") != std::string::npos; -+ } -+ -+ bool IsXhrOrFetchRequestAllowed(std::string selector) { -+ return GetSelectorTextContent(selector).find("succeeded") != -+ std::string::npos; -+ } -+ -+ // ResourceClassificationRunner::Observer: -+ void OnAdMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const std::vector& parent_frame_urls, -+ ContentType content_type, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ if (match_result == FilterMatchResult::kBlockRule) { -+ blocked_ads_notifications_.push_back(url); -+ } -+ } -+ -+ void OnPageAllowed(const GURL& url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override {} -+ -+ void OnPopupMatched(const GURL& url, -+ FilterMatchResult match_result, -+ const GURL& opener_url, -+ content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override {} -+ -+ base::ScopedTempDir temp_dir_; -+ std::vector blocked_ads_notifications_; -+}; -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockImageByResource) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_image_selector = -+ R"(img[src="by_resource/blue_subresource_loading.png"])"; -+ const auto* other_image_selector = -+ R"(img[src="by_resource/red_subresource_loading.png"])"; -+ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector)); -+ SetFilters({"/blue_subresource_loading.png"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockCssByResource) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsCssBlocked("div.blue")); -+ SetFilters({"blue_subresource_loading.css"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_TRUE(IsCssBlocked("div.blue")); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockXhrByResource) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_selector = "code#xhr_result_by_resource"; -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed(blocked_selector)); -+ SetFilters({"/xhr_result_1_subresource_loading.json"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_TRUE(IsXhrOrFetchRequestBlocked(blocked_selector)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockFetchByResource) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_selector = "code#fetch_result_by_resource"; -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed(blocked_selector)); -+ SetFilters({"/fetch_result_1_subresource_loading.json"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_TRUE(IsXhrOrFetchRequestBlocked(blocked_selector)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockByBundle) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_image_selector = -+ R"(img[src="by_bundle_file/green_subresource_loading.png"])"; -+ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_FALSE(IsCssBlocked("div.green")); -+ EXPECT_FALSE(IsCssBlocked("div.purple")); -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#xhr_result_by_bundle_file")); -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#fetch_result_by_bundle_file")); -+ -+ SetFilters({"by_bundle_file.wbn$webbundle"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_TRUE(IsCssBlocked("div.green")); -+ EXPECT_TRUE(IsCssBlocked("div.purple")); -+ EXPECT_THAT(blocked_ads_notifications_, -+ testing::Contains(embedded_test_server()->GetURL( -+ "example.org", "/by_bundle_file.wbn"))); -+ // FIXME the following two expectations fail because the state of the requests -+ // is "pending" rather than allowed or blocked: DPD-1887 -+ // EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#xhr_result_by_bundle_file")); -+ // EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#fetch_result_by_bundle_file")); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockByScope) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_image_selector = -+ R"(img[src="by_scope/orange_subresource_loading.png"])"; -+ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_FALSE(IsCssBlocked("div.orange")); -+ EXPECT_FALSE(IsCssBlocked("div.pink")); -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#xhr_result_by_scope")); -+ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#fetch_result_by_scope")); -+ -+ SetFilters({"by_scope/"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); -+ EXPECT_TRUE(IsCssBlocked("div.orange")); -+ EXPECT_TRUE(IsCssBlocked("div.pink")); -+ EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#xhr_result_by_scope")); -+ EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#fetch_result_by_scope")); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, OpaqueIframeByResource) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_image_selector = -+ R"(img[src$="uuid_in_package_by_resource/skyblue_subresource_loading.png"])"; -+ const auto* other_image_selector = -+ R"(img[src$="uuid_in_package_by_resource/yellowgreen_subresource_loading.png"])"; -+ const auto* iframe_selector = -+ R"(document.querySelector('iframe[src="uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae"]').contentDocument)"; -+ EXPECT_TRUE(IsImageLoaded(blocked_image_selector, iframe_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector, iframe_selector)); -+ SetFilters({"uuid_in_package_by_resource/skyblue_subresource_loading.png"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsImageLoaded(blocked_image_selector, iframe_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector, iframe_selector)); -+} -+ -+IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, OpaqueIframeByScope) { -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ const auto* blocked_image_selector = -+ R"(img[src$="uuid_in_package_by_scope/navy_subresource_loading.png"])"; -+ const auto* other_image_selector = -+ R"(img[src$="uuid_in_package_by_scope/orangered_subresource_loading.png"])"; -+ const auto* iframe_selector = -+ R"(document.querySelector('iframe[src="uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ad"]').contentDocument)"; -+ EXPECT_TRUE(IsImageLoaded(blocked_image_selector, iframe_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector, iframe_selector)); -+ SetFilters({"uuid_in_package_by_scope/navy_subresource_loading.png"}); -+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); -+ EXPECT_FALSE(IsImageLoaded(blocked_image_selector, iframe_selector)); -+ EXPECT_TRUE(IsImageLoaded(other_image_selector, iframe_selector)); -+} -+ -+// TODO: -+// - Mixed origins -+// - Signed bundles. including case of navigation between signed and unsigned -+// content. -+// - If you block the whole bundle, all resources requests to components -+// declared in -+ -+ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/chrome/test/data/adblock/middle_frame.html b/chrome/test/data/adblock/middle_frame.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/middle_frame.html -@@ -0,0 +1,8 @@ -+ -+ -+ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/chrome/test/data/adblock/non-ascii.html b/chrome/test/data/adblock/non-ascii.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/non-ascii.html -@@ -0,0 +1,9 @@ -+ -+ -+ -+ -+ -+ -+

Should be shidden
-+ -+ -diff --git a/chrome/test/data/adblock/outermost_frame.html b/chrome/test/data/adblock/outermost_frame.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/outermost_frame.html -@@ -0,0 +1,20 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/chrome/test/data/adblock/popup.html b/chrome/test/data/adblock/popup.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/popup.html -@@ -0,0 +1,8 @@ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/chrome/test/data/adblock/popup_opener.html b/chrome/test/data/adblock/popup_opener.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/popup_opener.html -@@ -0,0 +1,8 @@ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/chrome/test/data/adblock/popup_parent.html b/chrome/test/data/adblock/popup_parent.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/popup_parent.html -@@ -0,0 +1,8 @@ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/chrome/test/data/adblock/resource.png b/chrome/test/data/adblock/resource.png -new file mode 100644 -index 0000000000000000000000000000000000000000..39f3630072b2677debf4aac66b20096852453a7f -GIT binary patch -literal 47293 -zcmeFZWl&z-k|>M?3&Ab8L(m6zcXxMp*Py}O-Q6u{aCevBP67cE9D>8Q$$QS3ckZ1# -z_nWG@|Au;~diGx3y?V8GFN$ylIq`S!IPhR#VDBU)M3lh5z?*?zGFWKfjc_SC2N)Pu -zg{O*!i;|%`k%N=HnWc>>k;_L1QzBCjOEWMqkJZTx^ZHCqw~!ZO3_XZBK@CKsWcTg8 -zhmXBpdnsR;Ps$IewUZAWo|W89=bq;T -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 -z*apMuKnvugUmYLvJi~U2+-j80_;uecizG( -zaA(gs_I&NP3p;L3vwcP|+oQNU)sRcG@;DY3O{iKqvifdq~+h|q-O=H$7>R(-_V-hURX+AeJ_MdnrA3xwjWyE*8E>_fGH0V5swObbhj -z9dz<(DMAE^j34Jo!krmb>Yk*uvV%?PiTPbD$2yY$WqUk!`V});4%SiFGTl@qT2?f! -z1e+k%lK_0#yYVY0e>?SL%wq0YnXm1ElqeNnDx=v6f)nypI8ju;ED&UeDc%~~^mL89 -z&t}Zsfqagy)8CwaGJ__(tVLk?CcL>8@7}^t^CzG4wCPi$wCZ3kOl>u&?-5zc+lE2LLLkE -zg(2%jtQGS0zT09%(`hIbf!a|xMM2@~9SOs}-A9}$G{lxb=F7lbD<}CL^ko@x`%PUA -zGnebBXv=wWwRIqL`VkfG6+#G-WNhH|0rt9|;Bb=b`E6WlK7+^b-8+;Lh=V22KlWaPGacuo<9uJhqwc6yknnqiW7`W5mGY67`KmO=Y$_U=Z{x2 -zso2s+K1Z|#DJxbF#ML3gkp*Uc@JgBu^5QlfCQfAY$44Ze(nY~Qs@+a4W+E9%J_<;n -z3OY+-g?HCOM$L3Y34I@Obnz9pUnE*jgeCyvmdrvXCra%r-zUk)xiKyA9%QD4Y%pc< -z5@;XA(q%Ev#l{@Swg46yJ=hR4x^452k7P2Vy3Mkp1u3JKyqVNhOLvVuMAcFjmWFp0 -zL@bB+P8kwQ$y#5j-&VAUDRd2SBO5DS!Rkh_k`SP;$&C@KzNBbw6-X=w*bTWNB4N*D -zXb?Jl!B6I4GjK~6-%=1Nyd69g1pSIi5faUttS==7AFLDE;skRs7#b`NOb*jT;1^h; -zLi4An{xV5Omt@%J<=Saw3Q5@9WQ2x8ZJGRry|`u%*$Vc}aP}F|^1S&ZEK-YlT$duR -zu?aLxIeDYdI=89S25I%#yRW?W#s&-V+hM9YD+78F@l}zD2(jco;_P`uicbBmqtCxF -zkx-*)g|k}O?GW+?+wEbgjm*H8n$xgN@QG`|IF;_91;>#;iKjH4h+c6ihms$x#r`(A -zKX-2-FH{GCW9lWlXM~L8)#6ElP5w^OCS2V~fDn`rARP&nB+8Q)d9#iT-#^R~#8({; -z7Mwqm!)sK6AH8_M5P?@LTN*fC=q`urXuQaciAoftOG<&C8LCfYV4-3LehC(V@r}q? -z=VnfdXZM97d@^s3Ikf*sahA& -zM>2vG#E)1_3f%8{N}&3V%Su1+^bNS+nGGJ0G0i6?2{>MGjw}k+Y`bbg5+&0>?9K?fLkd=E9_mgMpjqqR&ctafcO7hlw9RVpN3?Ro(l(T8}ohd-Mq!29K(E;a8*kW$=8KyB^55@ -zN-M-J4~1HY{jR<@bQ@~b{HRL1%zdC%TyJVt_`Og>?s&zVIyDWjbb)ZiJ-0IT$n>d_ -zMKBZ>L+P-ZN?rRrs1?{8OH(UrDDg3Tn!!AT60Vr8pcQ7Ev3WiRxdmuh&m~Z_G^*10 -zp#qERWR;;-W6n4ZdAc274)*lMYE5{8D<%`**Dp?H+L#7tu@5IHi{ -z$-&fHS&85RaTH6*O!Na!4MfvK=37KFYajIJ2&_cR(helgOr;^r)3rnJQd7;N+pb&i -z+jY47DJUiGdXX9A##r{=m@T#NuVO|xv?14l!*hYgR`Uo2sxp`1%tCBpJh21}!9e_~#xJVd3~-!*hA~NMd=~Bq9eZ0lQ;ffjOAX%C -z-lQFtF=Q$aJ)x*@*Z_Hkb0c)l7Bf2~eqKM0Up_|nzWF_Qvup=@9>nw9sqkCHCks_9 -zb-4FuqKj5uEm<>V)kVb|$0*Wh`xHCjXxcCvV8I*yv^05#;IW8G^zbk21C)h*e#i3Ve@g -zAlKR8s2BTQ?Z{7K(i_*cBVCIifA$lU1lU=SPa~D&9nlLXzEYOfffVl&?a!KwB*VOL -z3uuUV{5L$G8+D}+^#nEju`KPCr#%uY)uzE#eBBRt#wwP}N+VvA>1`9(Vd1fu4Nc9+OC){gTQgs9YB%{P#lul8%-a)0lEUEgk23S9~cnNd#kc -z19QW&1UG%;{0&1G0jDsH6QQmW+4xUn8(*iXOv+3A2H|;OtGJPA7Zruv#peswez*|& -zd}6rq_IwI~qc6-e4mW|SW6B8eveNWd18=}J(#SkOi(x!@i+{?vPEc@NGiWJ>bRXEJ -zb&WT+V{=aj%bS;M90xl?A()w0@!~a8A#EW$1s{aqV6`~y-e^Au@^kQ7IJMsI1w+z` -zLHOoLwY|e -zmj8gDMHz}QD7)H0T+?+~yh81cri@(Hjh7qxl?R_ddCbuli&YG!vK{AkR!??aADt#A9_#WF$((Y5_l6aLhNS=}?O9uNGqv+|80YLnAwVL6Y73QiOCs{|1f -z`8^6aoGdA>l;l@++G4m=5S--CFM8cgGeW^w&4v<=SmTTqI6-zL^ao}v9r1nDTT|OE -z7FAyzTHn|l2`L$2T8nY1$G=%9B}Vn7%G82sP(Y1)hn4_>VmOE0)wNyz@L_IkbwhZb -zuW#uTB5IgbR#S8v5#6Ur1$XP{jlx^D>pSe=00zx93ry*qgdk|9yeJ6Sx-{sET(x5~ -zhMkg>s5*?#VdBHi=A-uaO+u$wICT&c5II!Zbf=qnv$G8B7#aleMkKt{xaL9XHLFyj -zCc!Jg8{)(;bW;lK#*;Z?HCXPxJUU9AqHDw`@Yd4=qf+UK( -zw91^C!CZj$ZIpR%#m^@TCkaTsfW3Epb9Z)_uPN-pL5v+hAi9IHh4Wb*{|M*$C(g}J -z99Qc)WR`nAF@Dj$DJ6WJGOJmcZg~>MkRLueF~_~?)v_Ysm<*&5J3JN&MarrVG1bo@ -z^o{p|lMptVCp&1_F>m|A*|&GK)DX)bu#s7JK;YU2B*|fq>6YUThX(WYBJGHuO9`Q; -z4pRb3hvJ+B#PW~C^=5n{%Py{{Aw%I$ew0r-%g_~Q^Gi!y^>xZcIzBzFbsOWH*xw6& -zeYt$AINjd<0IIDOgDr)H6(og)|2ee>X7yP<@w^iK0(gV^+D+6LFx*MI -zars=D$QX`asnPR=$}qHCL9JJBGg!zz(8mN=_x8pPRs=>i)F9Rb5Z!|B?(Y{JkdQw! -zd}s_i-)fms1b-F_E;n1^$g@g`m!k->u~UWZDu6+`B918=knxd2S3bkjzd1X< -zrk`r)n114fPU;v1%N5`mcj+hDB+A)rbeVb>FjPxG-*w()45XKM9C2OQW1kWYed1xZ -zF`2s@Ff__v?sbA`NXSQ(M;S&}E%f$VG!4GQG;dNeuJ*dX3b|MvV_LFABn=m(6$}D< -z&zhv@FY1$=4>*bJ100gy*Yn8l38Sjeq{9#u3dEegXZ*Jt)tYHp4v9i=c@Kll{9>QB -z>1V3ee&5vDvde$!VRk5PdRl-6T}pa(Ru9H}>b2e8ZL1#j>e)j?{y0Z2>{J9M>z5DK -zkvq%2_bFdH&u{X$x+!)ZhDcbq*zQxHutB55%1?sRljC2YCPE{-|6enO{ -z$dQ)7HHwC;441LJExno9-!|&l>Xl!ljLS$rWZfVC$a@yWaLS$*e -zOQOyy3zBsZHnp&n@N_a&_LNgG_Ov$UG$G;VgXi(!0tncex)>69*xJ}Rb9wNR{GrPQ -ze1Cn-Ktl8f#KoGIL_=1ANZ8)Vl!%3%g&ssF>S5`|M8XG8#N%XQ#-$`8_74)k6EBH{ -zi;Dvn1B1J}JH0zIy}gq;10yFVCj*Fyfr*I@fS_~!Xy;<+L1*Vo`by$28X~67#!i+F -zE|&IoM6WarjqF`rcu7crb)tU|2Ud+mJ%E@0*x>c~4|!)769!4(fdx1Z0KmWm0&&oR -znCO@|8UBtBtjfy%3){~5A5sM5$>3q=z`#fkVz9OScNoqtqHh1T-+zeVtODF-F({cj -z+q*g$n~J)b+PRSaeNzV;SLeU)>FR9y`sxqgHYR2a08@W<{yUDiq^!cfa9+h|ZfWcA -z2jdm`?~o?O|AKRHb+Y*bV`9u;YGY~(FyahQX8d>XueWah!uWURd0qM67;&*Q`#*rc -zuKaJ{0C)c}@qdc<59@!_z$IdD?E1>1qzEs`>+!fu?2Ro=xc+=KWMnsG0Wq7>v9Ys& -z=vde}ndyu;nN8>nO<363m<>5t7+K8zMoQAo*~QS#*z}bYK%CwZpkrvv&dADX%1md% -z%EV5`!fI$l$H~HBOb23NWi>JaF|o0lu>6gLyptv1IEFTV=jxS|2|$XS%?t#P;-oWW -z<6r_v8MD%HG6F0a1Iz%#KxXV9lRu=hQ>tl -z%Kx^aVrgrt>|*#THAXfj7FH$>5F-a8BZ!5C{ojDpOr4wor+6jG2%=|V`m)2l)=Hy{LjLx8o3lKJxpyhL;&h`f1$E4bNnx>ntxkm;{1!~t4_H9NdQ_g -zeDy>{m|3Ul%Y-;lA+yC%x -zAwzS9KaV^N{~7TAMoHPi-res1ADw>#{TCHMCl_~nCu?~pc_S-RW0(J&&VK~_FG@;4 -zTy=JF`Y8E-In@6G$Mcu1O8~g`P9Oiazp|<0Ur&DpKO4(Gq9P*t6L0|I{Y(7LhHj>R -znHC_&zm|+G4DHNKfyn+3xBlmQ%m2U!*o+xLAY%|49gB&PAsq_`$e50U)0l~l*^JG^ -zjEU9M$Q1OKg8xO`+1|{>-O$NY&>XMXx6s0w7qcbrzGjz3aA>mUtb}|L_ -zw6J&iOUO2s|Df?l~V17`E -zkv{{>9-xh+#YO&1A;9j0+x>uVa1Iih&R}4eG*{=+>NF@Om6zv1IRtmMPjK=not8S205vm=kJzVY9|+usl9(29KX1@860 -z65{`4H0W&@S%d&`kaYI+4;nCP@YC?zWC3&!0*}p~*J2_c!VS=%1X~n@ClFe|=fiWI -zOG-*ktZi(HT3gd&Vh}?@LPkbM4d+W_Cvtcn;A@xKRg2Q!$x@+?7ArK|8%y@SuGBYue!Pn%mzI`BgbHUoBiKAHmNG6yl5BRfLr)ex@s54H$M(yHn4#g$ -zmrlLY8xhHf*OPMO8k#{9oE{#oyl(&dcum~Pi~H&6iEI~z=e=3Pg%0{&`>5mEtfeWJ -zkFm|xQV4(A_H@^+=<_baGeqjRYxUAkAHAfqKO(rqusBhnW?h__>8a6eUv4l*vbC*- -zqI@!GtwP`D`Y_?FnD&!|a$YQCQiddbfBT#-XUiAek7F{LeRJga%T`RU0rI6K$ueM4 -zQ`&hLMM~wH#=|k^N0qhpwrgznKAi`q$&bGfq&n@)QuY*+e)QQf6Iru>1(CubvR$7~ -zG#AQwmkn6%X2uR -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 -zOxom>x{+IRdWWf)hA5FBvYueE-x$ieSTz; -zzRjdbHKCpO>cJmwfh{V@gc0G`Vf(4tOUvR2k2qc;J~ek5tLyB|Ys%bpYVCUWNN|>I -zMS6I7#|D(Q*R7M8rzO=*!L18=b{hP#1>UK*zHFq -z`4HJ}l(p2RfKpxvXiAlUvAlFr8o(xtu&s?v)!q=UeNl07aBu_s?e{j$B+rfA>PHBV -zC^E@D8)rl3y@DcTs3+lpzCuD;6W1gv
V{U7J}H&pS9gNnf6`j0RaKZ -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 -z_xh_{^QnFR-q`n-=O;QC!P!OqvS)*_FI6= -zhNb_xSUImk13&#hMy>CexXKLwA?6Ci!Zfuz7j$_v9;&!iHYren9RcCr($dc8 -za9ybe`1crUG(yKtSkc8Ct9%3JzloiA-Pmf%cu6}kRkNRe!Q^@;>b}zjg3)EC-y?Kx -z*Rz()&}Db2Oad93PHPI`%bC80UUwKUqJCU*_ByzV&Ry)j+vuJu7NMO;@`D8;@cvXG -z$Chl}Qgm%?Xh;aO_y0%JS%yW`eQjI?1(XH>=@#kk5a|ZVp*x4}R#Lj8OF+82JBA*5 -zKspB;x{-R%^S`e53m@T}!#;bj`@Vl`9ntk>N&El)U5J4Q| -z?{+6C_;A)MiVsk=fVeJ+snHp -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 -zH6%qI4}Gvk7dKwyo4iqogAvH -zzG^1Ra!*dK`g-r(r7pGFQ9MOBkH7iQJS*SS|IN^jx{`5VORle1Ef(vt#xsz3%+66& -zU!y0e)qRdF1G>@%+JRdHZrtQ2TdX*IY~(6mI{ycZRa7)?&QSh4$txv*Qzys*7~S$_ -zVt~qKHtcBmDoh33LdaT%K!WVbC2${jE7|UuepX4U5+enG%Zm!>Wm1x^2x83_UNK -zF^?+4=E(Ae%KR!z`X(%X%|Ua{TI*g?!=4T1fRM%HmmHIdPTflGLavl+3=+bhaf9i;H)1|_XDJU~;&i=C$4>VA4a}M@6 -zy=b41)O5ZEVa1lJW{nt!BnFB38)b=$`6tRTBn(lY#%FE|AS{UAhA*}HQanEdQ*dw! -zORh%yiFWz$O0`a6t$faYr$OMWBiJ1BnOz!C@9nW}(|-iUgR!0otHH~?MuB$(TGcx8 -z4zVbY&u#x8V9pw^O?_@+3^M=i0X(@4^DgK?XOK^27;`g*rY1m|5&Z8K&Jfy0{>hTm -zLqTuZ1S>6lCM5|(csCz|l;}vKXl!UJ2xxve)kP(2M{xVoy!9R1!l`KEKIMa(2c*zA2#X7aWvY_@lw+X2m-JPcvCiYZ7 -zod|HByP(8w9;=&k3e*fq#$Jg#q?F)?G$ -zchsS-JJvMw76L2h5k7}n+n+=N=?h}p%7mYe-<7u<;6>FEH9qWls+>0)J@X2A9?_7i -zbbZ8DlBRKQ4m0d_SPqyUJt`NKhYbY5dx5|gSInj -zSr#%M6^84yfF$dwx2WuQ(pypJY|McR58kQ8kZ#uTIfOL82 -ze;^R1pjxD!=I>R-FPN59_SggYV`^v?ZhFxGy-bYC?GbEX9k;Etn%R5(BsECc>-T;L -zCT(@~1jyNtbXNe})BCVHmyR@|qrAD$!f;g)sKLtvqpgLVZF}kMYV=}4`f-3ZvH!By -zEji$dMIZNv6KH5napYY%<5kAV>>B>d_EEx@Bkq#b(RjXfnTUNi#%~_`vJjr-P{6=g -z`cq!e-=#CcIWSGeXb}p)0ZFO5#wJR=;SLJ2MKjT_`v%n63p&t)pAHS@xdnN9yMn{h -z0pg>%?ORYsG}rlx9PYjw@wqE!%TfJUX|BQez%9}9^@$iD9kZ!&%LaJxlK?a_T2w?&OhPh^Fz-m`)sV|@XlY1nVbQzoksf!-f2mA6^D9SR -zDjhZC1K_3C6Mq_UJu?Z^P3-vv`#r)tT=y$3hO>ZM@07B#87_8lfZNX*Ck3iGL4?K9(yT(YBd}p99)O4w=Vfu1 -z9E7x4%B8E5yf2Iiv7WEdE`3CdI?lL$5_ofDDn+Zjj>xi&Q=%~utX+3>al!3j%E8A0 -z!v&`TM7X)#W~11;h5?G{i;4;seP@bd`$0B&CcyF20xLfz4KV4V%E~0o(B_i#-wSZ_ -zh6XY!7LCa_Ek7kZMT@fmDb4_R#*BMkV2$H5Q1eggWSMg+aaQItFzRCHut+mT)|WDl -zSU!!v5@u!cSqx*Vh`~-nS2c|P-v9KZa70r}TlzC- -zutGv~kcB@Hc`4mvfw@dlb2H|V?BP6b9q7oqT`3k7H*~;+kUUCm$>B?h9EemT(wfX6 -zR5g=T8IUO*=m~l~l=~_^YtFA-UwZ`Hw6E6!t$nd%BBOv*FM0bq)Iss&Pgd#l4*}jy -zByx68pDE|BGWPeec{%2Bm5z%l?1{h127<=UrX4F%b`KuEBE)!u1vI_guoS0+xW$bb -zcPE-b{8x^fZ>sf~ -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 -zM;LqdYJuW!K4tjl -z_}fxbRjs-S04+i+ehA;^L9D>e?2P!_>xEl{{CBB-(JKA*$-?rzgb~dlx>UBj0|LxR -zHFLj3HQ$2WLsG;*jt0?J7)zZ121xDh53FklU?sF08yo$LOG_hCjRMj?Q+{SAlEe;q -ze!+_rjvFD_NV{SBvB{j%`vmA*dpf3g-lSOUvS+$L1g~^-WqZ39YrmtN3`vqy<3AQ| -zvWNft==HuH&tlb-QJq$sp}wRtr+&bWp>8-bmOe-nOJoFpDM;G>a9~FDJ?Bp+1OD`Y -zl-O<4G+x~$%Ix_?Z}yQ%B)NZK#R;^)b@b%NO6mK~@9GCm&@WWzNYmm9+M6k2>pzIH -zMN)4s7E?qLzKCO<#y-cp@g1=i6jAp!^s^z!{dc&2aa8S>P#7ho`cqrDu4qW`X1^r39OlDMaxzf -z1ED&4N@);d?^D{st#fc*|PB5kJ?abatl! -zK#R1;A$8(ew?*U+19MGX?k8Z*%fPD^Fd^T!NolpM_bIY3agdCghmV6pSW%4+%^O-l -zk;xn}5G)!*9x7t?;rd8yIPhtoO7sj8_}NTiRn25#Z_h{cxjC0!KzOuj(qH)U)?v;4 -zLRXjA&Jd=&UTxvVGHLvV9R*-D;WYzq$=xnjgDn}jQi-lv7n=ARUXtOy|3C>QP -zC~j)v<4g6`RG7(*bF!4s$B%>ftHx&ad>0$pM&2X-q{B#sKEez0DeD4kn6Sb;W`y_$ -zhs|Rp%`QW<0)>gcB)@j?j!CrKxL{0gkame)~km9 -zQ6h;L%)fm!>>!5<2;JM;IBdk~IqodMjZA9-zilceq{wbW!!nOrqT$@6kiynl@;LZy -zSSfRqTSN0%py;!})7I>B6x`!-OO4K<+h_1YDDgTf-9%55y&pLn`PE#LY9*LmI7M2` -zLU3=sfN@6c#t2gZ8HxN4o^#b&4fdGJFagiMu%g9fF8PxUTHl*PO8^)9k5&L03&0S* -zt}~3|mhD*XnxenG2A>Cb3&x+>{;SBAfF|t=#3NXDMv?hY%+88dG){7=JRYWqzARF9 -zJkdl7hE+1kL)E~mB0WiZ?JZz;5+(xPJO;QljS@EH{!LAQH1dghFJ`6UM(Emq&`vn3P@FRa7*^J6`#x-Iee3_agpz#DO+7O>y`TW2pn -z1Ak7iUv6sU)R=YMq_tH`l*1?fmxa81)4q9q -zeC-kC_AI!2XTv;f7emdj%ujx2uZ@+i-;_b!JYSU_H|o4p#qXzkx%QTSaJ^7B6vCtJ -zu%q&{AN;TkJBBaWuQJpP*lV-U0Pz#mF1RaXcM%>VbpMZ -zQiuhk`c5~+dIV*UCPJtrDr{0=L|V`FXRNpTA%FbudaIvO_U@3?Z*~RZ)KqN#{pyFJ -z-15TYaA3UDR+$n>EBH~Dz_Vfd=1%#O(lZ#yVRi9h9?oP$fdGsaYVVzpQ%d^IuK)ID -z5)I$1$FQv+O)Kt){vvNfrohuD&x_;s6W}my_5F&6<_uxsQ)R%v+w<&(&a!!KUNNpT -zIHSGn_R;FTFfaOH(K^ugU7eHu>j5>259G}Iy%vkDC`)w{HKI_JP#ySxTB{6z+J1dU -z>fAmQj^7DofzB*1j{%iJ3jm-+jhLU?M@Vj^YMN&H-mczsKl=ltctER$W1~%fJ}~_~ -zq<0;zlcoJdtw8NP@#{dd^CcOi*C%_tkCupp30BsRfPrx;;ZAwgxphQX&6Aw?FCmWMO4n+l>7$DIb1#Otp -zXq$4+iT^4T7)Hiy)bvB_d66PvY*)amyMagSJ%rxL|klcJvTq(1zC0|s6YT^m)J%#)NSjgOusXLid=IKyu@sl1X3)Y -zdAKr%E~3wxnp2P6YUB+4!G4F^Xa$x;3;G5vuc>KFxtrifY38f3@Dy7X48PsP>QVvb -zBvCx>%LFDU(mx9)$b!4l7H+e&E|ln#v`K}%PO+Zu-Wm09@EmuTa@590x?u|HzWc1! -zOq9)vd+94X5GP8grtvxs8pWU)Vc#Ud2gbaNz34Zx2l7{f;}*-;dG$Zd-Re;PiJ-?= -z?32k;MZQuXNG;kN=EQX^Q`oF}QvEvGb5oSy*x&#rn4FYsUZ -zit~lLmonD@9sb*yKP%`xu_7pop4LCY{;<2(Vkf%o`QwqncCF%$=#yYAPj!P0jRVT^ -z$IQu}&M(IdXd(6bu5u`LsSQrN>KamNl*DJV(^@M2%mZGG{cHZ=i>-Ei3aPA}SMQ8& -z`<{SW-cu{W9`k?0>cYB!9_RC0vu?AAJ|9-26*pzsqaUF*?Z3}0xL3`c6)yLcWO2{# -zI%VZ~Ld|*mo%M&l0^f!}9Q|zI40Jou94PqiD(Dy+-cK$G+n`N45LR+G$w1IRz#WMU -zGf9dZoC$?I)8lPC<&z{YnGykk?zjDfk|tYN5(80v{~DBt6U$|oNLy>J2DE+CW4c|% -zXQk1Xe~=COMvca$n}9i6$mu`(I#B?lciZA@3-bvgvj(LI+<9a+nsFW)Ad3jGwp02= -z@`ml?&>YrFMbI#Zi*cVod)5Gfx*N#TCFKgY;el{lfyc!?AF5(Ic_hF+uCCXP_D^Fi -z;E^~V&QL3rAO&3RxLpO6-rWAm`q)Bhv-9A4?Ujq0z~`HFV0?sYl{~n9S?|Kr-Q9n0 -z{rPcy`W&?8VSbtFr(;QJ -zU|jLbjCy8fWk5#s*7sq;$S<0tsw+{I!RdO47uR%Y3v(tNoy~r^|NEL6LF2qS-Z^!) -zrN&?r8RoUp>3EZaE-|%!t>sIeO+NY(zv+#LRLt6L$1LFZX}KGoD&i<9_hF|JDtdqD8+dE9{!xu&=Z|J( -z76LVfHX^O5KX20}rFl@zDEXJE(8iVb>20Ux#4zYB%w1qgXi|k@RUBvGX&QJt!O=GD9QKKf&V3aD!QN}@MQi~;Q!>^F0F#VQ9d`rW)NefjQv -zA)t2J-amzC4_$o9ic3wN@em_nN&fxaNrd(+HWt~zTPN0=NaG#}31LYWa0b$9@M05L -z+r#--CGhfz1>{v<3HVa}M*L%Ia$JvPe8+4b<189WCP}%IY!i#}A%}6Jty)pO*L`YC -zu*pR0gL#UnDI+wh{oa{0Rj67o6n4Lt@CWC_(vVEM(jLMNCii`M(QlS+Hj_g@|5vB0 -z2A~4fo)8eRes<^yX_7^H(}HE!ouko4W%FuJ-m&4+Ki6D%4wm1~z&{V~Jr4gw-DTL} -z(tVd@7!dL7Oh)OtaumMV2imchbI(@_u$&lBaZP#7&u%{f=_?gi3e!IaiN}99*FRiLHsak@3&FGW@ -z8KKp=tDck1M&j7k74KYON_Gj7sV6{4^n3Q8TaG>{s+@e8c@StZyJ!}>?Zp}{{@7v) -zdN=K=ALwS@`!>1%bhA|W9dVxwi+t~UwN7&UYWer|?_#&>Tmut}4Ueg(iFS|pDx@{n -zA1+iuxM%ko^s}$q-l+c^ePfr}MEagp9Uo`RuMOJccI|`WkxhE#g%j?Tk={g|or~L)5x^w!A{@ -zXC6`k;0xFv4Fx6XtIw_xFm^GV-1jg#)K`X@bo)0mJnYKrr`)wQaeMz5&e2={J8lb9 -zr`)c|6*-e9U6z$#zsml4XItenU`K@LO!3CeGo|98-x85!{%Q`42YRzSj+P+xY#rmS -zdQCH{Fcn^-o+dCLrwV+mh~09Y-Kl=OsL~uG8I-Jf<}vmiO(-g!C|T10HumZ^W6F`y(NPwa)(;r~{mNEA_laUG$6jx*2!q -z$Ecx4`{J6K|LGNluFFEUM<`?M#20q@Jh#tKg#W^w;SWwg$h7x6=IT2M0=nZCQlwK@K;wy0?`$fn2R%sX>A$+& -zT)Nbhhj-p%)!9QFnvNDHuCsj?+fQEjKT1R^{T{Zwz*nGiTODxL@5#3L>kSs{LcDDO -zzIK(KEfbM1E8))q{0Y*-W3#}U7Z&~bg{&^P{%86#OSo8~ZAorT1FOvyW&sKhX+{0j -z*K;#V)M5eVC@BAifL$TcGJetq@Z6o3lgA=tkl;rF5&7S=HND)%#L@dV3{HFqjqXOZ -zS*=YoliD3Q(=P*oP`0ol8FgV0JLICgqIwuNDzo7CTVj)3pP$~wf8XfVhHR;q8!j`8 -zcm1kww!=sMjxh$u!Su0O|(g8;N_ly)!gdu72J3R5qy=rfJT -z+B38^pMUI1@8V?W2r8)vV!jf_scDnY5kvviHXiz$v-=LOPVx?NHsHw{vw!9%qQynS -zLkmZJ9V~NYE>!7W&YR8&+n -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

7cOc&DF@xl^-3}B(kApb -z`7sOiU(VM2n3FyYN0QCw{@CU~VaPoQ{_ZCjRoLxp#J<|FPdrk?jZ;319Wmp*NJJI} -zsppTCVBV2Qpktoxo5K)(d6Jd6^C}sAnC{)*xCG>KTJ07tWMioL2Q5x?XCpPwR9X|u -z{?vH7muk2;DpN1--K%$**MuOYL~^l+E&liKv6lZMO7Lc14;8rptXF#4WRg5#`Y6FC -ze0Sz$aeQP+=RGP^FU@p-e+394rT^Y2i8&dGIY`g|wK%@iPEh!}CJPQ8-ifj7V6Ygs -zw7No2od2O2ATikparU@t>2M?duf4N;i?R#Xz6A;hBGM_{J(7bwG}0XcLzfIlr-C3M -zEj2Vq!_c50-OW&gbax{S67J>ue%k-T=HTE99K*ftT5Da`d7i(bwl<(pI@zDQh%7(Z -zYi6h|HU8v>r)O$aH#lA>Q>T`nPb;$P#z@tZ70>xKeJI#b&SfA%{l@%i>7yTFcj!EtKI{HHB#azJREico%6-`Z<| -z0L5YY7y7bHd=Ul5xh~|0eaau^I8QD=vVn2n{-7marQNZkhjdFqCW1m`9uy)^k-2!w -zzca%z^KJRW`1<@8oM0k65v-n|Tp~L4-4-pv#W(0BZb;arOmnmJIP>qes&D&H8P)_R -zoZ;#?>6jIqk};-AuEX;KO*q=&l8;!iIjj{fR7V*m}XC=Fk2J+!hb70(k^?PdDJdFZ*k^KR5(Zb_+?XIeP&y7MGRS4lhiMzUl7g1MgRp+- -zxicUPq#qWR^p#{>JDmZ^_5yuY;rwpu<;a3+s_)ss#*^w|89PIs`3p&wah&mF$-N-1 -zqpS5d1oVG`vL)2fqpmm-_)o61cg#%5?buB_{@8qR90?!ZrCmxm@+53T1|SuBH!C=n -zBm>MvN!R(Ni=gY-vI52{qg1z)3io<}1rM-_=t-7Hnm5Q}&#>?C`1`xtIN2JUomwzn1(_AFLTLT9ad0@+hz -zPubB8c^XmWpG84hA8Prwr&LZVQ4jI)q2~C+rA;Wt^XRYPLAEVJq?8A;T$JbE -zVMjls{tSg+9S9w&vl$R#uLJ8#Qe$M53a{pWMdbnkVx_phoRa$ENy(MbacLHg5ESTK -zD%Av9={;(~9!>K6WGXx -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 -zBQXTJ8WHx9l|F{Y�ECN!%-TBQwoYFsV*9D@||TI@CMShZDOmxz{Iuk^cE{_hFzU -zJ$$w?En!k%#eI6%HI>9{ziD&JRK?ET-!{JN?D(d9Og4YxyH0{bfGwgP=esF!*}Z#s -z&^OW&T5UY1Co1p>WvY3W5;^3qb^W2+y!0>E<6wWCw47v4E|IVOMY&a88gnHk -z+Su00naRs;v<|hYAg%v*-SEe#;SU@9dZjvxaNHloOjBXY8yL-3E8*O)&&M@YomM)r -zK#fsuL5$T3v-np)OM91nOWh|s^4m+pr~wgGb#>hCY*u%-XU^}S5|cl0JWr$jG9z~Z -z1RNRW$k6WBe6HDi@tK(nFRH@Al-chxfg42A^%RyA3hn+lzJlhMzqr}76JPiHyA&dw -zqd7kL_~-2g3f{CUP%lEVWAI-%CPY!4ErvGqy#=Y_(R(;Y7PWT8Ix{ -zKk+EPXqrN%z$$$X^!b%XaLjX%4)M%F1ukscB??H-bZzWK?i(-D8^u%^3@yBn&-L{p -z|FDXaEq89fZc1%yYkOr}eS6o;w(HZ-(12pj@C*RbbY>vv`zmIQeod@$do3*^5Qs00 -zqPj=aVgP%(eze-tkm9fTMz1j*Z8gPf-Km&7JdJQ+@Ryc+qWGnZmSKhW@w-vbZX6oUlIig -z`ZY)QwA_l-KRZ*?HRup*J}2_MKA0^+mfR%V|8ZSvd~EG^ClnG*ZEjkesmwlOi>qat -zdJc;xe#oP&7TNwbXB(bj!DY-+-@AcR%F3w9r2DjNML2O%&22S|H6*jBr5LQVCnj|M -zh2m3tZ_xr;4!7Mm6vBi(h~hU2#FEdSti`ETnfKrkga+P}hkI1&8fw+LdCUOVwZeozrfxf#qfh@7-!j_Ko1=zk8nkqWH2eAvRJ_*&N3dHK565Ay835>J-* -zz56jXJ>3VQT2O%dQ&?L1@t$W>UY@1iLb^U7yvyx_2nA0+N$|>qj#BYVRp@!&uGu0D>`@6HEHr097RVNpm$*GpVJ} -zwlGDOt6+pju=Vroq51V8yz8*scTzc3!P4`O-0;b*-<@u35n-lY3*tTWm}sN6Hba}% -zHiaovI&3*cUFH0l<5|`lal?g>{qD++mXtQIn{I5T&kna23Lr)3bOQ -z@bI38o+S-Ii-hxe*4jAbb;uP}w -zHk=96bV&=)Z_Lf<|1qv==bUjsu0JjQlg9fup^s7?&H4n*DQ2nJpht7$rd#~PL0H1( -zco7htDfcOJ4Xsq@7yTCcU6-!qP31YS!Zxq+!QnBi_F*(S812yEP-|M9raw&+X5`pa -zRzLQ~-&Q6MTtIoca9fSEMq`#D?u1{P$K;i+V8_xFD))D5fCDxq!BoscNtv~o4qG@l -z$U3wTF9-<;lw1`uQW5Z5!35LK3-HL?`Aeug!{dKV%>?0n!yqEVLCqZ3r;ztM;g8RT -zBag>{Au;FM&a+A5VWf8P*3M3LRn_tRrMhXuX70B0HYta6Q&JyqA0H5W`Y$o~^!%KU -zhvz>I;<#t`ofe4G=dHRdYgb+MoTluj?1|wMl8Na-l9qYuc(wf6{`scag+L*;e9`}o -zQ;QHWaXVhXsW(3{GiYvn%?1{pq~v7ldhcn(adA1JXtgJ>B7l={u6cWVPt}4? -z6BB#-?AZ(KAOJvL%N>yY5QyM{_2Sx*X9#8azezE*}(Gsnn(RmjV| -zls43GZz%oQ7!OrK%}q36)Xpl)$YA{X^=o{5yu$OyOaMOh56GvBgvUF`V$}=~yUv35 -zZuR{9{N6%SDoCe&jvdr%Rm~C>kj)aL-JK`H+*yLh7t-NBu-?A!zIt-CwYO&h)RZMg -z4G7Bt#QjT#UWTc%@oxqsk+K(i^9_mMBPv1qd~ire-@5an*Wkswrt|Y#+nz -z?X9ba2O5p;=!;_}qoib@j#m7UhtL0|WBDcilYhdbf0orsGmL+{@}eTF^2y?RqMs7K -zCj7@RWhF87OGEE$Eyj?mmLpjS#4iImS$=J8;=%$9jEjtlijfj82Z{WC5co5qM28)i -z`vKb(;MS7C(hrA(E4R2f9MC}k1`04LJFTk4o_(O1Vqdi+fD^a}Rm@_3V5W|4$R1^h -zkq-^dzUHfdd_YJf!8S8uQdsR>lS5KZt<97)Z_c@d2?&${=Pz -z-M~N*{03O?ahHz3bUL|~9%u4`hU2%0|Di?oG*DSRSzTQXl%$o+!hiAN1z1ji)@-P3 -zPUork5)DZ_8iKCDU)J*g}DiQdxqG*@GO0#8Y19 -zdmKE+3jtx!U=CJ7L+y^QP9J(sPMWzt(%y#N3SIc<6cZKy3Ija){QO`5-8m-J1uq(X -zbC}EKP?uTd98M!c79+z{XNc{z*Qc>M_ZheCIV|W`pq6f5=2>=30=E&kDF5yrf>8WO -z+2oWII`T+x-^%A{tmCpPGVGO=y?h8Bn4j|wZ0zhu*SFwp5FZWJqdPl0;5t8g;D3CH -z7+Ckl@WlOcPyeOMkXy~=D}r~D0m_E`_ewZ}VYWXKwl~Lqw2UVdv0xWzg?U1U#>WXO -z^-4ZuG=FtvOQ1_vNeqW6gk-Z6BE1(v_XxhWz(|$z1;Er+@X!VL|Gd8OC5x{Z78ebo%?f -zB0}jryO0j`*ZCy+V9JM5KZBLmQtH9VNdSJi8Ne3TB_lL=5`1CXn@ZOilBS`Bt6eVJ -zU%wF$z$HI?GC6g&;vCv;n|haGrOEo0i!h3WEif5|&wqQV?eAU`us`>SJ;FF3gIQe)Fe7%uT -KkuH-o3HTopq;ALn - -literal 0 -HcmV?d00001 - -diff --git a/chrome/test/data/adblock/tab-restore.html b/chrome/test/data/adblock/tab-restore.html -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/tab-restore.html -@@ -0,0 +1,16 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/chrome/test/data/adblock/wbn/LICENSE b/chrome/test/data/adblock/wbn/LICENSE -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/LICENSE -@@ -0,0 +1,14 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE b/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE -@@ -0,0 +1,14 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json -@@ -0,0 +1 @@ -+{ "method": "fetch", "result": 1 } -diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json -@@ -0,0 +1 @@ -+{ "method": "fetch", "result": 2 } -diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE b/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE -@@ -0,0 +1,14 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json b/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json -@@ -0,0 +1 @@ -+{ "method": "fetch", "result": 2 } -diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css -@@ -0,0 +1 @@ -+.green { background-color: green } -diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..2040a0a2b2cd006f3ade7be290ff37ad8fd0452e -GIT binary patch -literal 772 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm. -diff --git a/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css -@@ -0,0 +1 @@ -+.blue { background-color: blue } -diff --git a/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..7a0773bec90118a4a83069ee0900449dcc511a49 -GIT binary patch -literal 773 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLmZZ}T. -diff --git a/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json b/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json -@@ -0,0 +1 @@ -+{ "method": "fetch", "result": 3 } -diff --git a/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css -@@ -0,0 +1 @@ -+.orange { background-color: orange } -diff --git a/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..348f1275fa97592546d48a3f5a339625c231ba2e -GIT binary patch -literal 774 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLmkF2lAmzQji)bo59o7&t;ucLK6V>Gl+EDj>gTe~DWM4fjk(;R - -literal 0 -HcmV?d00001 - -diff --git a/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json b/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json -@@ -0,0 +1 @@ -+{ "method": "xhr", "result": 3 } -diff --git a/chrome/test/data/adblock/wbn/index.html.mustache b/chrome/test/data/adblock/wbn/index.html.mustache -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/index.html.mustache -@@ -0,0 +1,181 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+

Chromium Web bundles test

-+ -+

Identified by resource

-+ -+
    -+
  • Resources in by_resource.wbn -+
      -+
    • Shows blue box with by_resource/blue_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_resource/blue_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows red box with by_resource/red_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_resource/red_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows xhr result for by_resource/xhr_result_1_subresource_loading.json: -+
      Pending
    • -+
    • Shows fetch result for by_resource/fetch_result_1_subresource_loading.json: -+
      Pending
    • -+
    -+
  • -+
-+ -+

Identified by bundle file

-+ -+
    -+
  • Resources in by_bundle_file.wbn (Please click here to check fetch behavior with blocked bundle) -+
      -+
    • Shows green box with by_bundle_file/green_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_bundle_file/green_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows purple box with by_bundle_file/purple_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_bundle_file/purple_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows xhr result for by_bundle_file/xhr_result_2_subresource_loading.json: -+
      Pending
    • -+
    • Shows fetch result for by_bundle_file/fetch_result_2_subresource_loading.json: -+
      Pending
    • -+
    -+
  • -+
-+ -+

Identified by scope

-+ -+
    -+
  • Resources in by_scope.wbn -+
      -+
    • Shows orange box with by_scope/orange_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_scope/orange_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows pink box with by_scope/pink_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows by_scope/pink_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows xhr result for by_scope/xhr_result_3_subresource_loading.json: -+
      Pending
    • -+
    • Shows fetch result for by_scope/fetch_result_3_subresource_loading.json: -+
      Pending
    • -+
    -+
  • -+
-+ -+
-+ -+ -+ -+
-+ -+ -+ -+

-+To navigate to {{{navigation_to_unsigned_bundles_baseUrl}}} within a bundle file, download the bundle file by clicking here. -+

-+ -+ -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/LICENSE b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/LICENSE -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/LICENSE -@@ -0,0 +1,14 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/index.html.mustache b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/index.html.mustache -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/index.html.mustache -@@ -0,0 +1,45 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+

Identified by resource inside opaque origin iframe

-+ -+
    -+
  • Resources in uuid_in_package_by_resource.wbn -+
      -+
    • Shows skyblue box with uuid_in_package_by_resource/skyblue_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows uuid_in_package_by_resource/skyblue_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows yellowgreen box with uuid_in_package_by_resource/yellowgreen_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows uuid_in_package_by_resource/yellowgreen_subresource_loading.png, nothing after the png blocked: -+
    • -+
    -+
  • -+
-+ -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.css b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.css -@@ -0,0 +1 @@ -+.skyblue { background-color: skyblue } -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.png b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/skyblue_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..5782a6730fbcb5269ec3f9d1f5c95afb5db2f4f3 -GIT binary patch -literal 775 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLmUHx3vIVCg!08Q%O6aWAK - -literal 0 -HcmV?d00001 - -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.css b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.css -@@ -0,0 +1 @@ -+.yellowgreen { background-color: yellowgreen } -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.png b/chrome/test/data/adblock/wbn/uuid_in_package_by_resource/yellowgreen_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..f2ee8b50a76d1132bf27f405160bf108cc0e5638 -GIT binary patch -literal 775 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm. -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/index.html.mustache b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/index.html.mustache -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/index.html.mustache -@@ -0,0 +1,42 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+

Identified by scope inside opaque origin iframe

-+ -+
    -+
  • Resources in uuid_in_package_by_scope.wbn -+
      -+
    • Shows navy box with uuid_in_package_by_scope/navy_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows uuid_in_package_by_scope/navy_subresource_loading.png, nothing after the png blocked: -+
    • -+
    • Shows orangered box with uuid_in_package_by_scope/orangered_subresource_loading.css, grey box after the css blocked: -+
    • -+
    • Shows uuid_in_package_by_scope/orangered_subresource_loading.png, nothing after the png blocked: -+
    • -+
    -+
  • -+
-+ -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.css b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.css -@@ -0,0 +1 @@ -+.navy { background-color: navy } -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.png b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/navy_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..b8d64acdf745dd8b1be84346efd7ff03bf4fece4 -GIT binary patch -literal 774 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm4zn0Nj2SZ76wWd%k!&zw -no{+|HX;g4DKn6T9Y~inKX8vt0{5ukuuo*mE{an^LB{Ts5mg3#x - -literal 0 -HcmV?d00001 - -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.css b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.css -new file mode 100644 ---- /dev/null -+++ b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.css -@@ -0,0 +1 @@ -+.orangered { background-color: orangered } -diff --git a/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.png b/chrome/test/data/adblock/wbn/uuid_in_package_by_scope/orangered_subresource_loading.png -new file mode 100644 -index 0000000000000000000000000000000000000000..a95dd790854750625abfaee3c8342c58883c464c -GIT binary patch -literal 774 -zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm``tAF - -literal 0 -HcmV?d00001 - ++# You should have received a copy of the GNU General Public License ++# along with eyeo Chromium SDK. If not, see . ++ + import argparse + import functools + import os +@@ -533,7 +541,7 @@ def backwards_compatible_list(options): + "msttcorefonts", + "python-dev", + "python-setuptools", +- "snapcraft", ++ #"snapcraft", + "ttf-dejavu-core", + "ttf-indic-fonts", + "ttf-kochi-gothic", diff --git a/components/BUILD.gn b/components/BUILD.gn --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -9385,7 +758,7 @@ diff --git a/components/BUILD.gn b/components/BUILD.gn import("//base/debug/debug.gni") import("//build/config/chrome_build.gni") -@@ -125,6 +128,14 @@ test("components_unittests") { +@@ -124,6 +127,14 @@ test("components_unittests") { deps = [ "//base", @@ -9400,7 +773,7 @@ diff --git a/components/BUILD.gn b/components/BUILD.gn "//components/aggregation_service:unit_tests", "//components/apdu:unit_tests", "//components/assist_ranker:unit_tests", -@@ -336,6 +347,7 @@ test("components_unittests") { +@@ -338,6 +349,7 @@ test("components_unittests") { if (use_blink) { deps += [ @@ -9408,7 +781,7 @@ diff --git a/components/BUILD.gn b/components/BUILD.gn "//components/autofill/content/browser:unit_tests", "//components/autofill/content/renderer:unit_tests", "//components/autofill/core/common/mojom:unit_tests", -@@ -1061,6 +1073,9 @@ if (use_blink) { +@@ -1067,6 +1079,9 @@ if (use_blink) { deps = [ "//base", @@ -9422,9 +795,27 @@ diff --git a/components/adblock/CHANGELOG.md b/components/adblock/CHANGELOG.md new file mode 100644 --- /dev/null +++ b/components/adblock/CHANGELOG.md -@@ -0,0 +1,593 @@ +@@ -0,0 +1,611 @@ +# Release Notes + ++## eyeo Chromium SDK 116.0 ++* Updated to Chromium 116.0.5845.78 ++* Added webview support (DPD-2036) ++* Added gn gen argument to disable eyeo filtering for first run (DPD-2063) ++* Added chrome://adblock-internals status page (DPD-1708) ++* Removed deprecated APIs from AdblockController (DPD-2060) ++* Improved blocking of popups (DPD-1977) ++* Fix bug that injects CSS/JS multiple times for the same document (DPD-1773) ++ ++## eyeo Chromium SDK 115.0 ++* Updated to Chromium 115.0.5790.98 ++* Fixed bug with not allowlisting frames with 'about:blank...' urls (DPD-1946) ++* Fixed bug with logging telemetry authentication token in release builds (DPD-1951) ++* Fixed several problems with rewrite filters and refactored code (DPD-1657) ++* Fixed bug with handling domain matching filters with empty url pattern (DPD-1978) ++* Updated extensions JavaScript API and Java API by adding FilteringConfiguration name to blocked/allowed notifications (DPD-1909) ++* Updated snippets library version from v0.6.1 to v0.7.0 (DPD-1974) ++ +## eyeo Chromium SDK 114.0 +* Updated to Chromium 114.0.5735.53 +* Fixed bug of gn gen build settings for "eyeo_application_name" and "eyeo_application_version" being ignored (DPD-1937) @@ -10761,7 +2152,7 @@ new file mode 100644 + +Differences across versions are listed in [the changelog](components/adblock/CHANGELOG.md). + -+You can also use our [interdiff script](/tools/adblock/interdiff.py) to compare two git revision ranges. You can find more information in the [integration how-to](docs/integration-how-to.md). ++You can also use our [interdiff script](tools/adblock/generate_interdiffs.sh) to compare two git revision ranges. You can find more information in the [integration how-to](docs/integration-how-to.md). + + +## For eyeo Chromium SDK contributors @@ -10781,5059 +2172,6 @@ new file mode 100644 +You can find how our implementation maps to Chromium's design in the [design overview](docs/design-overview.md). + +General information for developers, like options for logging, testing, etc, can be found in the [developer notes](docs/developer-notes.md). -diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BUILD.gn -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/BUILD.gn -@@ -0,0 +1,112 @@ -+# This file is part of eyeo Chromium SDK, -+# Copyright (C) 2006-present eyeo GmbH -+# eyeo Chromium SDK is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License version 3 as -+# published by the Free Software Foundation. -+# eyeo Chromium SDK is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# You should have received a copy of the GNU General Public License -+# along with eyeo Chromium SDK. If not, see . -+ -+ -+import("//build/config/android/rules.gni") -+import("//build/config/locales.gni") -+import("//tools/grit/grit_rule.gni") -+ -+android_library("adblock_java") { -+ sources = [ -+ "java/src/org/chromium/components/adblock/AdblockContentType.java", -+ "java/src/org/chromium/components/adblock/AdblockController.java", -+ "java/src/org/chromium/components/adblock/AdblockCounters.java", -+ "java/src/org/chromium/components/adblock/FilteringConfiguration.java", -+ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java", -+ ] -+ -+ -+ deps = [ -+ ":java_resources", -+ ":jni_headers", -+ "//base:base_java", -+ "//base:jni_java", -+ "//build/android:build_java", -+ "//chrome/browser/preferences:java", -+ "//chrome/browser/profiles/android:java", -+ "//components/browser_ui/settings/android:java", -+ "//components/prefs/android:java", -+ "//components/user_prefs/android:java", -+ "//third_party/androidx:androidx_annotation_annotation_java", -+ "//third_party/androidx:androidx_fragment_fragment_java", -+ "//third_party/androidx:androidx_preference_preference_java", -+ ] -+ -+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] -+ resources_package = "org.chromium.components.adblock" -+} -+ -+generate_jni("jni_headers") { -+ sources = [ -+ "java/src/org/chromium/components/adblock/AdblockController.java", -+ "java/src/org/chromium/components/adblock/FilteringConfiguration.java", -+ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java", -+ ] -+} -+ -+android_resources("java_resources") { -+ sources = [ -+ "java/res/values/adblock_settings_locales_titles.xml", -+ ] -+} -+ -+android_library("adblock_java_tests") { -+ testonly = true -+ -+ sources = [ -+ "javatests/src/org/chromium/components/adblock/AdblockControllerTest.java", -+ "javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java", -+ "javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java", -+ "javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java", -+ "javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java", -+ "javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesCspTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java", -+ "javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java", -+ "javatests/src/org/chromium/components/adblock/TestVerificationUtils.java", -+ ] -+ -+ -+ deps = [ -+ ":adblock_java", -+ "//base:base_java", -+ "//base:base_java_test_support", -+ "//chrome/android:chrome_java", -+ "//chrome/browser/flags:java", -+ "//chrome/browser/settings:test_support_java", -+ "//chrome/browser/tab:java", -+ "//chrome/browser/tabmodel:java", -+ "//chrome/test/android:chrome_java_integration_test_support", -+ "//chrome/test/android:chrome_java_test_support_common", -+ "//components/infobars/android:java", -+ "//components/infobars/core:infobar_enums_java", -+ "//components/messages/android/test:test_support_java", -+ "//content/public/android:content_full_java", -+ "//content/public/android:content_main_dex_java", -+ "//content/public/test/android:content_java_test_support", -+ "//net/android:net_java_test_support", -+ "//third_party/androidx:androidx_test_monitor_java", -+ "//third_party/androidx:androidx_test_runner_java", -+ "//third_party/hamcrest:hamcrest_library_java", -+ "//third_party/junit:junit", -+ ] -+} -diff --git a/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml b/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/res/values/adblock_settings_locales_titles.xml -@@ -0,0 +1,98 @@ -+ -+ -+ -+ -+ | -+ -+ -+ -+ af|Afrikaans -+ am|ኣማርኛ -+ ar|العربية -+ as|অসমীয়া -+ ast|Asturianu -+ az|Azərbaycan -+ be|Беларуская мова -+ bg|български -+ bn|বাংলা (ভারত) -+ br|ar brezhoneg -+ bs|bosanski -+ ca|català -+ cs|čeština -+ cy|Cymraeg -+ da|dansk -+ de|Deutsch -+ dsb|dolnoserbski -+ el|ελληνικά -+ en|English -+ eo|Esperanto -+ es|español -+ et|eesti keel -+ eu|euskara -+ fa|فارسى -+ fi|suomi -+ fil|Filipino -+ fr|français -+ fy|Frysk -+ gl|Galego -+ gu|ગુજરાતી (ભારત) -+ he|עברית -+ hi|हिन्दी -+ hr|Hrvatski -+ hsb|hornjoserbsce -+ hu|magyar -+ hy|Հայերեն -+ id|Bahasa Indonesia -+ is|Íslenska -+ it|italiano -+ ja|日本語 -+ ka|ქართული -+ kab|Taqbaylit -+ kk|Қазақ тілі -+ kn|ಕನ್ನಡ -+ ko|한국어 -+ lt|lietuvių kalba -+ lv|latviešu valoda -+ mg|Malagasy -+ mk|македонски -+ ml|മലയാളം -+ ms|Melayu -+ nb|norsk -+ nl|Nederlands -+ nn|norsk -+ pa|ਪੰਜਾਬੀ (ਭਾਰਤ) -+ pl|polski -+ pt|português -+ rm|rumantsch -+ ro|română -+ ru|Русский -+ si|සිංහල -+ sk|slovenčina -+ sl|slovenščina -+ sq|shqip -+ sr|српски -+ sv|svenska -+ sw|Kiswahili -+ ta|தமிழ் -+ te|తెలుగు -+ th|ภาษาไทย -+ tr|Türkçe -+ uk|українська -+ ur|اردو -+ uz|o’zbek -+ vi|Tiếng Việt -+ zh|中文 -+ -+ -diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java -@@ -0,0 +1,62 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import java.util.HashMap; -+import java.util.Map; -+ -+public enum AdblockContentType { -+ // Note. This has to be kept in sync with c++ enum so some values -+ // are skipped -+ CONTENT_TYPE_OTHER(1 << 0), -+ CONTENT_TYPE_SCRIPT(1 << 1), -+ CONTENT_TYPE_IMAGE(1 << 2), -+ CONTENT_TYPE_STYLESHEET(1 << 3), -+ CONTENT_TYPE_OBJECT(1 << 4), -+ CONTENT_TYPE_SUBDOCUMENT(1 << 5), -+ CONTENT_TYPE_WEBSOCKET(1 << 7), -+ CONTENT_TYPE_WEBRTC(1 << 8), -+ CONTENT_TYPE_PING(1 << 10), -+ CONTENT_TYPE_XMLHTTPREQUEST(1 << 11), -+ CONTENT_TYPE_MEDIA(1 << 14), -+ CONTENT_TYPE_FONT(1 << 15); -+ -+ private final int contentType; -+ -+ private AdblockContentType(int contentType) { -+ this.contentType = contentType; -+ } -+ -+ private static final Map intToContentTypeMap = -+ new HashMap(); -+ -+ static { -+ for (AdblockContentType type : AdblockContentType.values()) { -+ intToContentTypeMap.put(type.contentType, type); -+ } -+ } -+ -+ public static AdblockContentType fromInt(int i) { -+ AdblockContentType type = intToContentTypeMap.get(Integer.valueOf(i)); -+ return type; -+ } -+ -+ public int getValue() { -+ return contentType; -+ } -+} -diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java -@@ -0,0 +1,267 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import android.content.Context; -+import android.content.res.Resources; -+import android.util.Log; -+import android.webkit.URLUtil; -+ -+import androidx.annotation.NonNull; -+import androidx.annotation.Nullable; -+import androidx.annotation.UiThread; -+ -+import org.chromium.base.ContextUtils; -+import org.chromium.base.ThreadUtils; -+import org.chromium.base.annotations.CalledByNative; -+import org.chromium.base.annotations.NativeMethods; -+import org.chromium.chrome.browser.preferences.Pref; -+import org.chromium.chrome.browser.profiles.Profile; -+import org.chromium.components.user_prefs.UserPrefs; -+ -+import java.io.UnsupportedEncodingException; -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.concurrent.CopyOnWriteArraySet; -+ -+/** -+ * @brief Main access point for java UI code to control ad filtering. -+ * It calls its native counter part also AdblockController. -+ * It lives in UI thread on the browser process. -+ */ -+public final class AdblockController extends FilteringConfiguration { -+ private static final String TAG = AdblockController.class.getSimpleName(); -+ -+ private static AdblockController sInstance; -+ -+ private URL mAcceptableAds; -+ -+ private AdblockController() { -+ super("adblock"); -+ try { -+ mAcceptableAds = -+ new URL("https://easylist-downloads.adblockplus.org/exceptionrules.txt"); -+ } catch (java.net.MalformedURLException e) { -+ mAcceptableAds = null; -+ } -+ } -+ -+ /** -+ * @return The singleton object. -+ */ -+ public static AdblockController getInstance() { -+ ThreadUtils.assertOnUiThread(); -+ if (sInstance == null) { -+ sInstance = new AdblockController(); -+ AdblockControllerJni.get().bind(sInstance); -+ } -+ return sInstance; -+ } -+ -+ public static class Subscription { -+ private URL mUrl; -+ private String mTitle; -+ private String mVersion = ""; -+ private String[] mLanguages = {}; -+ -+ public Subscription(final URL url, final String title, final String version) { -+ this.mUrl = url; -+ this.mTitle = title; -+ this.mVersion = version; -+ } -+ -+ @CalledByNative("Subscription") -+ public Subscription( -+ final URL url, final String title, final String version, final String[] languages) { -+ this.mUrl = url; -+ this.mTitle = title; -+ this.mVersion = version; -+ this.mLanguages = languages; -+ } -+ -+ public String title() { -+ return mTitle; -+ } -+ -+ public URL url() { -+ return mUrl; -+ } -+ -+ public String version() { -+ return mVersion; -+ } -+ -+ public String[] languages() { -+ return mLanguages; -+ } -+ -+ @Override -+ public boolean equals(final Object object) { -+ if (object == null) return false; -+ if (getClass() != object.getClass()) return false; -+ -+ Subscription other = (Subscription) object; -+ return url().equals(other.url()); -+ } -+ } -+ -+ @UiThread -+ public void setAcceptableAdsEnabled(boolean enabled) { -+ if (enabled) -+ addFilterList(mAcceptableAds); -+ else -+ removeFilterList(mAcceptableAds); -+ } -+ -+ @UiThread -+ public boolean isAcceptableAdsEnabled() { -+ return getFilterLists().contains(mAcceptableAds); -+ } -+ -+ @UiThread -+ public void setMoreOptionsEnabled(boolean enabled) { -+ UserPrefs.get(Profile.getLastUsedRegularProfile()) -+ .setBoolean(Pref.ADBLOCK_MORE_OPTIONS_ENABLED, enabled); -+ } -+ -+ @UiThread -+ public boolean areMoreOptionsEnabled() { -+ return UserPrefs.get(Profile.getLastUsedRegularProfile()) -+ .getBoolean(Pref.ADBLOCK_MORE_OPTIONS_ENABLED); -+ } -+ -+ @UiThread -+ public List getRecommendedSubscriptions(Context context) { -+ final List recommendedSubscriptions = -+ (List) (List) Arrays.asList( -+ AdblockControllerJni.get().getRecommendedSubscriptions()); -+ final Map localeToTitle = getLocaleToTitleMap(context); -+ for (int i = 0; i < recommendedSubscriptions.size(); ++i) { -+ for (final String language : recommendedSubscriptions.get(i).languages()) { -+ final String title = localeToTitle.get(language); -+ if (title != null && !title.isEmpty()) { -+ recommendedSubscriptions.set(i, -+ new Subscription(recommendedSubscriptions.get(i).url(), title, -+ "" /*version*/, recommendedSubscriptions.get(i).languages())); -+ break; -+ } -+ } -+ } -+ return recommendedSubscriptions; -+ } -+ -+ // Deprecated, to be removed in version 115 -+ // [deprecated="Use Subscription.version() instead"] -+ @UiThread -+ public String getSelectedSubscriptionVersion(final Subscription subscription) { -+ return AdblockControllerJni.get().getSelectedSubscriptionVersion( -+ subscription.url().toString()); -+ } -+ -+ @UiThread -+ public void installSubscription(final URL url) { -+ addFilterList(url); -+ } -+ -+ @UiThread -+ public void uninstallSubscription(final URL url) { -+ removeFilterList(url); -+ } -+ -+ @UiThread -+ public List getInstalledSubscriptions() { -+ return (List) (List) Arrays.asList( -+ AdblockControllerJni.get().getInstalledSubscriptions()); -+ } -+ -+ // TODO(mpawlowski) temporary pass-through, to enable gradual deprecation. -+ public interface AdBlockedObserver extends ResourceClassificationNotifier.AdBlockedObserver {} -+ // TODO(mpawlowski) deprecate and remove, use ResourceClassificationNotifier directly. -+ @UiThread -+ public void addOnAdBlockedObserver( -+ final ResourceClassificationNotifier.AdBlockedObserver observer) { -+ ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(observer); -+ } -+ -+ // TODO(mpawlowski) deprecate and remove, use ResourceClassifier directly. -+ @UiThread -+ public void removeOnAdBlockedObserver( -+ final ResourceClassificationNotifier.AdBlockedObserver observer) { -+ ResourceClassificationNotifier.getInstance().removeOnAdBlockedObserver(observer); -+ } -+ -+ private List transform(String[] urls) { -+ if (urls == null) return null; -+ -+ List result = new ArrayList(); -+ for (String url : urls) { -+ try { -+ result.add(new URL(URLUtil.guessUrl(url))); -+ } catch (MalformedURLException e) { -+ Log.e(TAG, "Error parsing url: " + url); -+ } -+ } -+ -+ return result; -+ } -+ -+ private Map getLocaleToTitleMap(final Context context) { -+ final Resources resources = context.getResources(); -+ final String[] locales = -+ resources.getStringArray(R.array.fragment_adblock_general_locale_title); -+ final String separator = resources.getString(R.string.fragment_adblock_general_separator); -+ final Map localeToTitle = new HashMap<>(locales.length); -+ for (final String localeAndTitlePair : locales) { -+ // in `String.split()` separator is a regexp, but we want to treat it as a string -+ final int separatorIndex = localeAndTitlePair.indexOf(separator); -+ final String locale = localeAndTitlePair.substring(0, separatorIndex); -+ final String title = localeAndTitlePair.substring(separatorIndex + 1); -+ localeToTitle.put(locale, title); -+ } -+ -+ return localeToTitle; -+ } -+ -+ @CalledByNative -+ private void subscriptionUpdatedCallback(final String url) { -+ ThreadUtils.assertOnUiThread(); -+ try { -+ URL subscriptionUrl = new URL(URLUtil.guessUrl(url)); -+ for (final SubscriptionUpdateObserver observer : mSubscriptionUpdateObservers) { -+ observer.onSubscriptionDownloaded(subscriptionUrl); -+ } -+ } catch (MalformedURLException e) { -+ Log.e(TAG, "Error parsing subscription url: " + url); -+ } -+ } -+ -+ @NativeMethods -+ interface Natives { -+ void bind(AdblockController caller); -+ Object[] getInstalledSubscriptions(); -+ Object[] getRecommendedSubscriptions(); -+ String getSelectedSubscriptionVersion(String subscription); -+ } -+} -diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java -@@ -0,0 +1,86 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+ -+public class AdblockCounters { -+ /** -+ * Immutable data-class containing an auxiliary information about resource event. -+ */ -+ public static class ResourceInfo { -+ private final String mRequestUrl; -+ private final List mParentFrameUrls; -+ private final String mSubscriptionUrl; -+ private final AdblockContentType mAdblockContentType; -+ private final int mTabId; -+ -+ ResourceInfo(final String requestUrl, final List parentFrameUrls, -+ final String subscriptionUrl, final int adblockContentType, final int tabId) { -+ this.mRequestUrl = requestUrl; -+ this.mParentFrameUrls = parentFrameUrls; -+ this.mSubscriptionUrl = subscriptionUrl; -+ this.mAdblockContentType = AdblockContentType.fromInt(adblockContentType); -+ this.mTabId = tabId; -+ } -+ -+ /** -+ * @return The request which was blocked or allowed. -+ */ -+ public String getRequestUrl() { -+ return mRequestUrl; -+ } -+ -+ /** -+ * @return The parent frames of the mRequestUrl. -+ */ -+ public List getParentFrameUrls() { -+ return mParentFrameUrls; -+ } -+ -+ public String getSubscription() { -+ return mSubscriptionUrl; -+ } -+ -+ /** -+ * @return The Adblock content type. See enum ContentType in -+ * components/adblock/types.h -+ */ -+ public AdblockContentType getAdblockContentType() { -+ return mAdblockContentType; -+ } -+ -+ /** -+ * @return The current tab id for the mRequestUrl. -1 means no tab id, likely tab closed -+ * before event arrived. Numbers start from 0. -+ */ -+ public int getTabId() { -+ return mTabId; -+ } -+ -+ @Override -+ public String toString() { -+ return "mRequestUrl: " + mRequestUrl + ", mParentFrameUrls: " -+ + mParentFrameUrls.toString() + ", mSubscriptionUrl:" + mSubscriptionUrl -+ + ", mAdblockContentType: " + mAdblockContentType.getValue() -+ + ", mTabId: " + mTabId; -+ } -+ } -+} -diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java -@@ -0,0 +1,245 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import android.content.Context; -+import android.content.res.Resources; -+import android.util.Log; -+import android.webkit.URLUtil; -+ -+import androidx.annotation.UiThread; -+ -+import org.chromium.base.ContextUtils; -+import org.chromium.base.ThreadUtils; -+import org.chromium.base.annotations.CalledByNative; -+import org.chromium.base.annotations.NativeMethods; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+ -+/** -+ * @brief Represents an independent configuration of filters, filter lists, -+ * allowed domains and other settings that influence resource filtering and -+ * content blocking. -+ * Multiple Filtering Configurations can co-exist and be controlled separately. -+ * A network resource is blocked if any enabled Filtering Configuration -+ * determines it should be, through its filters. -+ * Elements on websites are hidden according to a superset of element-hiding -+ * selectors from all enabled Filtering Configurations. -+ * Lives on UI thread, not thread-safe. -+ */ -+public class FilteringConfiguration { -+ private static final String TAG = FilteringConfiguration.class.getSimpleName(); -+ -+ private final Set mConfigurationChangeObservers = new HashSet<>(); -+ protected final Set mSubscriptionUpdateObservers = new HashSet<>(); -+ private final String mName; -+ -+ public interface ConfigurationChangeObserver { -+ /** -+ * Triggered when the FilteringConfiguration becomes disabled or enabled. -+ */ -+ @UiThread -+ void onEnabledStateChanged(); -+ -+ /** -+ * Triggered when the collection of installed filter lists changes. -+ */ -+ @UiThread -+ void onFilterListsChanged(); -+ -+ /** -+ * Triggered when the set of allowed domain changes. -+ */ -+ @UiThread -+ void onAllowedDomainsChanged(); -+ -+ /** -+ * Triggered when the set of custom filters changes. -+ */ -+ @UiThread -+ void onCustomFiltersChanged(); -+ } -+ -+ public interface SubscriptionUpdateObserver { -+ @UiThread -+ void onSubscriptionDownloaded(final URL url); -+ } -+ -+ public FilteringConfiguration(String configuration_name) { -+ mName = configuration_name; -+ FilteringConfigurationJni.get().bind(mName, this); -+ } -+ -+ @UiThread -+ public void addObserver(final ConfigurationChangeObserver observer) { -+ mConfigurationChangeObservers.add(observer); -+ } -+ -+ @UiThread -+ public void removeObserver(final ConfigurationChangeObserver observer) { -+ mConfigurationChangeObservers.remove(observer); -+ } -+ -+ @UiThread -+ public void addSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) { -+ mSubscriptionUpdateObservers.add(observer); -+ } -+ -+ @UiThread -+ public void removeSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) { -+ mSubscriptionUpdateObservers.remove(observer); -+ } -+ -+ @UiThread -+ public void setEnabled(boolean enabled) { -+ FilteringConfigurationJni.get().setEnabled(mName, enabled); -+ } -+ -+ @UiThread -+ public boolean isEnabled() { -+ return FilteringConfigurationJni.get().isEnabled(mName); -+ } -+ -+ @UiThread -+ public void addFilterList(final URL url) { -+ FilteringConfigurationJni.get().addFilterList(mName, url.toString()); -+ } -+ -+ @UiThread -+ public void removeFilterList(final URL url) { -+ FilteringConfigurationJni.get().removeFilterList(mName, url.toString()); -+ } -+ -+ @UiThread -+ public List getFilterLists() { -+ List filterListsStr = -+ Arrays.asList(FilteringConfigurationJni.get().getFilterLists(mName)); -+ List filterLists = new ArrayList(); -+ for (String url : filterListsStr) { -+ try { -+ filterLists.add(new URL(url)); -+ } catch (MalformedURLException e) { -+ Log.e(TAG, "Received invalid subscription URL from C++: " + url); -+ } -+ } -+ return filterLists; -+ } -+ -+ @UiThread -+ public void addAllowedDomain(final String domain) { -+ String sanitizedDomain = sanitizeSite(domain); -+ if (sanitizedDomain == null) return; -+ FilteringConfigurationJni.get().addAllowedDomain(mName, sanitizedDomain); -+ } -+ -+ @UiThread -+ public void removeAllowedDomain(final String domain) { -+ String sanitizedDomain = sanitizeSite(domain); -+ if (sanitizedDomain == null) return; -+ FilteringConfigurationJni.get().removeAllowedDomain(mName, sanitizedDomain); -+ } -+ -+ @UiThread -+ public List getAllowedDomains() { -+ List allowedDomains = -+ Arrays.asList(FilteringConfigurationJni.get().getAllowedDomains(mName)); -+ Collections.sort(allowedDomains); -+ return allowedDomains; -+ } -+ -+ @UiThread -+ public void addCustomFilter(final String filter) { -+ FilteringConfigurationJni.get().addCustomFilter(mName, filter); -+ } -+ -+ @UiThread -+ public void removeCustomFilter(final String filter) { -+ FilteringConfigurationJni.get().removeCustomFilter(mName, filter); -+ } -+ -+ @UiThread -+ public List getCustomFilters() { -+ return Arrays.asList(FilteringConfigurationJni.get().getCustomFilters(mName)); -+ } -+ -+ private String sanitizeSite(String site) { -+ // |site| is raw user input. We expect it to be either a domain or a URL. -+ try { -+ URL candidate = new URL(URLUtil.guessUrl(site)); -+ return candidate.getHost(); -+ } catch (java.net.MalformedURLException e) { -+ } -+ // Could not parse |site| as URL or domain. -+ return null; -+ } -+ -+ @CalledByNative -+ private void enabledStateChanged() { -+ ThreadUtils.assertOnUiThread(); -+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { -+ observer.onEnabledStateChanged(); -+ } -+ } -+ -+ @CalledByNative -+ private void filterListsChanged() { -+ ThreadUtils.assertOnUiThread(); -+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { -+ observer.onFilterListsChanged(); -+ } -+ } -+ -+ @CalledByNative -+ private void allowedDomainsChanged() { -+ ThreadUtils.assertOnUiThread(); -+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { -+ observer.onAllowedDomainsChanged(); -+ } -+ } -+ -+ @CalledByNative -+ private void customFiltersChanged() { -+ ThreadUtils.assertOnUiThread(); -+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) { -+ observer.onCustomFiltersChanged(); -+ } -+ } -+ -+ @NativeMethods -+ interface Natives { -+ void bind(String configuration_name, FilteringConfiguration caller); -+ boolean isEnabled(String configuration_name); -+ void setEnabled(String configuration_name, boolean enabled); -+ void addFilterList(String configuration_name, String url); -+ void removeFilterList(String configuration_name, String url); -+ String[] getFilterLists(String configuration_name); -+ void addAllowedDomain(String configuration_name, String domain); -+ void removeAllowedDomain(String configuration_name, String domain); -+ String[] getAllowedDomains(String configuration_name); -+ void addCustomFilter(String configuration_name, String filter); -+ void removeCustomFilter(String configuration_name, String filter); -+ String[] getCustomFilters(String configuration_name); -+ } -+} -diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java -@@ -0,0 +1,186 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import android.content.Context; -+import android.content.res.Resources; -+import android.util.Log; -+import android.webkit.URLUtil; -+ -+import androidx.annotation.UiThread; -+ -+import org.chromium.base.ContextUtils; -+import org.chromium.base.ThreadUtils; -+import org.chromium.base.annotations.CalledByNative; -+import org.chromium.base.annotations.NativeMethods; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+ -+/** -+ * @brief Allows observing notifications from ongoing resource classification. -+ * Classification combines filters from all FilteringConfigurations. -+ * Lives on UI thread, not thread-safe. -+ */ -+public final class ResourceClassificationNotifier { -+ private static final String TAG = ResourceClassificationNotifier.class.getSimpleName(); -+ -+ private static ResourceClassificationNotifier sInstance; -+ private final Set mOnAdBlockedObservers = new HashSet<>(); -+ // TODO(mpawlowski) in the future, we can consider adding filter hit -+ // notifications here as well (DPD-1233) -+ -+ public interface AdBlockedObserver { -+ /** -+ * "Ad allowed" event for a request which would be blocked but there -+ * was an allowlisting filter found. -+ * -+ * It should not block the UI thread for too long. -+ * @param info contains auxiliary information about the resource. -+ */ -+ @UiThread -+ void onAdAllowed(AdblockCounters.ResourceInfo info); -+ -+ /** -+ * "Ad blocked" event for a request which was blocked. -+ * -+ * It should not block the UI thread for too long. -+ * @param info contains auxiliary information about the resource. -+ */ -+ @UiThread -+ void onAdBlocked(AdblockCounters.ResourceInfo info); -+ -+ /** -+ * "Page allowed" event for an allowlisted domain (page). -+ * -+ * It should not block the UI thread for too long. -+ * @param info contains auxiliary information about the resource. -+ */ -+ @UiThread -+ void onPageAllowed(AdblockCounters.ResourceInfo info); -+ -+ /** -+ * "Popup allowed" event for a popup which would be blocked but there -+ * was an allowlisting filter found. -+ * -+ * It should not block the UI thread for too long. -+ * @param info contains auxiliary information about the resource. -+ */ -+ @UiThread -+ void onPopupAllowed(AdblockCounters.ResourceInfo info); -+ -+ /** -+ * "Popup blocked" event for a popup which was blocked. -+ * -+ * It should not block the UI thread for too long. -+ * @param info contains auxiliary information about the resource. -+ */ -+ @UiThread -+ void onPopupBlocked(AdblockCounters.ResourceInfo info); -+ } -+ -+ private ResourceClassificationNotifier() { -+ ResourceClassificationNotifierJni.get().bind(this); -+ } -+ -+ public static ResourceClassificationNotifier getInstance() { -+ ThreadUtils.assertOnUiThread(); -+ if (sInstance == null) { -+ sInstance = new ResourceClassificationNotifier(); -+ } -+ return sInstance; -+ } -+ -+ @UiThread -+ public void addOnAdBlockedObserver(final AdBlockedObserver observer) { -+ mOnAdBlockedObservers.add(observer); -+ } -+ -+ @UiThread -+ public void removeOnAdBlockedObserver(final AdBlockedObserver observer) { -+ mOnAdBlockedObservers.remove(observer); -+ } -+ -+ @CalledByNative -+ private void adMatchedCallback(final String requestUrl, boolean wasBlocked, -+ final String[] parentFrameUrls, final String subscriptionUrl, final int contentType, -+ final int tabId) { -+ ThreadUtils.assertOnUiThread(); -+ final List parentsList = Arrays.asList(parentFrameUrls); -+ final AdblockCounters.ResourceInfo resourceInfo = new AdblockCounters.ResourceInfo( -+ requestUrl, parentsList, subscriptionUrl, contentType, tabId); -+ Log.d(TAG, -+ "eyeo: adMatchedCallback() notifies " + mOnAdBlockedObservers.size() -+ + " listeners about " + resourceInfo.toString() -+ + (wasBlocked ? " getting blocked" : " being allowed")); -+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { -+ if (wasBlocked) { -+ observer.onAdBlocked(resourceInfo); -+ } else { -+ observer.onAdAllowed(resourceInfo); -+ } -+ } -+ } -+ -+ @CalledByNative -+ private void pageAllowedCallback( -+ final String requestUrl, final String subscriptionUrl, final int tabId) { -+ ThreadUtils.assertOnUiThread(); -+ final AdblockCounters.ResourceInfo resourceInfo = -+ new AdblockCounters.ResourceInfo(requestUrl, new ArrayList(), subscriptionUrl, -+ AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId); -+ Log.d(TAG, -+ "eyeo: pageAllowedCallback() notifies " + mOnAdBlockedObservers.size() -+ + " listeners about " + resourceInfo.toString()); -+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { -+ observer.onPageAllowed(resourceInfo); -+ } -+ } -+ -+ @CalledByNative -+ private void popupMatchedCallback(final String requestUrl, boolean wasBlocked, -+ final String openerUrl, final String subscription, final int tabId) { -+ ThreadUtils.assertOnUiThread(); -+ final List parentsList = Arrays.asList(openerUrl); -+ final AdblockCounters.ResourceInfo resourceInfo = -+ new AdblockCounters.ResourceInfo(requestUrl, parentsList, subscription, -+ AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId); -+ Log.d(TAG, -+ "eyeo: popupMatchedCallback() notifies " + mOnAdBlockedObservers.size() -+ + " listeners about " + resourceInfo.toString() -+ + (wasBlocked ? " getting blocked" : " being allowed")); -+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) { -+ if (wasBlocked) { -+ observer.onPopupBlocked(resourceInfo); -+ } else { -+ observer.onPopupAllowed(resourceInfo); -+ } -+ } -+ } -+ -+ @NativeMethods -+ interface Natives { -+ void bind(ResourceClassificationNotifier caller); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java -@@ -0,0 +1,87 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CallbackHelper; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.base.test.util.IntegrationTest; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class AdblockControllerTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private CallbackHelper mHelper = new CallbackHelper(); -+ -+ @Before -+ public void setUp() { -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void addingAllowedDomains() throws TimeoutException { -+ final List allowedDomains = new ArrayList<>(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ AdblockController.getInstance().addAllowedDomain("foobar.com"); -+ AdblockController.getInstance().addAllowedDomain("domain.com/path/to/page.html"); -+ AdblockController.getInstance().addAllowedDomain("domain.com/duplicate.html"); -+ AdblockController.getInstance().addAllowedDomain("https://scheme.com/path.html"); -+ AdblockController.getInstance().addAllowedDomain("gibberish"); -+ allowedDomains.addAll(AdblockController.getInstance().getAllowedDomains()); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ // We expect to see a sorted collection of domains (not URLs) without duplicates. -+ ArrayList expectedAllowedDomains = new ArrayList(); -+ expectedAllowedDomains.add("domain.com"); -+ expectedAllowedDomains.add("foobar.com"); -+ expectedAllowedDomains.add("scheme.com"); -+ expectedAllowedDomains.add("www.gibberish.com"); -+ Assert.assertEquals(expectedAllowedDomains, allowedDomains); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java -@@ -0,0 +1,73 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.InstrumentationRegistry; -+import androidx.test.rule.ActivityTestRule; -+ -+import androidx.test.filters.SmallTest; -+ -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.Log; -+import org.chromium.base.test.util.ApplicationTestUtils; -+import org.chromium.base.test.util.CallbackHelper; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.settings.SettingsActivityTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.components.adblock.settings.AdblockFilterListsFragment; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+ -+import java.net.URL; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class AdblockFilterFragmentTest { -+ @Rule -+ public final ChromeTabbedActivityTestRule mActivityTestRule = -+ new ChromeTabbedActivityTestRule(); -+ @Rule -+ public SettingsActivityTestRule mTestRule = -+ new SettingsActivityTestRule<>(AdblockFilterListsFragment.class); -+ -+ @Before -+ public void setUp() throws Exception { -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ mTestRule.startSettingsActivity(); -+ ApplicationTestUtils.finishActivity(mTestRule.getActivity()); -+ } -+ -+ @Test -+ @SmallTest -+ @Feature({"adblock"}) -+ public void testLanguageFiltersNotEmpty() { -+ mTestRule.startSettingsActivity(); -+ AdblockFilterListsFragment fragment = mTestRule.getFragment(); -+ Assert.assertNotNull(fragment); -+ Assert.assertNotEquals(0, fragment.getListView().getCount()); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java -@@ -0,0 +1,127 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.InstrumentationRegistry; -+ -+import androidx.test.filters.MediumTest; -+ -+import org.hamcrest.Matchers; -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.task.PostTask; -+import org.chromium.base.task.TaskTraits; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Criteria; -+import org.chromium.base.test.util.CriteriaHelper; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeFeatureList; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.infobar.InfoBarIdentifier; -+import org.chromium.chrome.browser.tabmodel.TabModelSelector; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.chrome.test.util.browser.Features.DisableFeatures; -+import org.chromium.components.infobars.InfoBar; -+import org.chromium.net.test.EmbeddedTestServer; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+// NOTE: Messages feature had to be disabled when testing infobars -+// https://gitlab.com/eyeo/adblockplus/abpchromium/-/commit/a617caaa5692630f73d967a55d86bf52cc491ad5 -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+@DisableFeatures({ChromeFeatureList.MESSAGES_FOR_ANDROID_INFRASTRUCTURE}) -+public class AdblockPopupInfoBarTest { -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ -+ private static final String POPUP_HTML_PATH = "/chrome/test/data/android/popup_test.html"; -+ -+ private String mPopupHtmlUrl; -+ private EmbeddedTestServer mTestServer; -+ -+ @Before -+ public void setUp() throws Exception { -+ // Create a new temporary instance to ensure the Class is loaded. Otherwise we will get a -+ // ClassNotFoundException when trying to instantiate during startup. -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ -+ PostTask.runOrPostTask( -+ TaskTraits.UI_DEFAULT, () -> Assert.assertTrue(getNumInfobarsShowing() == 0)); -+ -+ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); -+ mPopupHtmlUrl = mTestServer.getURL(POPUP_HTML_PATH); -+ } -+ -+ @After -+ public void tearDown() { -+ mTestServer.stopAndDestroyServer(); -+ } -+ -+ private int getNumInfobarsShowing() { -+ return mActivityTestRule.getInfoBars().size(); -+ } -+ -+ public int getTabCount() { -+ return mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount(); -+ } -+ -+ @Test -+ @MediumTest -+ @Feature({"adblock"}) -+ public void popUpBlockedInfoBarVisibleWhenAbpEnabled() throws InterruptedException { -+ mActivityTestRule.loadUrl(mPopupHtmlUrl); -+ Assert.assertEquals(1, getTabCount()); -+ CriteriaHelper.pollUiThread(() -> { -+ Criteria.checkThat(getNumInfobarsShowing(), Matchers.is(1)); -+ InfoBar frontInfoBar = mActivityTestRule.getInfoBars().get(0); -+ Criteria.checkThat("Invalid infobar type shown", frontInfoBar.getInfoBarIdentifier(), -+ Matchers.is(InfoBarIdentifier.POPUP_BLOCKED_INFOBAR_DELEGATE_MOBILE)); -+ }); -+ } -+ -+ @Test -+ @MediumTest -+ @CommandLineFlags.Add({"disable-adblock"}) -+ @Feature({"adblock"}) -+ public void popUpBlockedInfoBarVisibleWhenAbpDisabled() { -+ mActivityTestRule.loadUrl(mPopupHtmlUrl); -+ Assert.assertEquals(1, getTabCount()); -+ CriteriaHelper.pollUiThread(() -> { -+ Criteria.checkThat(getNumInfobarsShowing(), Matchers.is(1)); -+ InfoBar frontInfoBar = mActivityTestRule.getInfoBars().get(0); -+ Criteria.checkThat("Invalid infobar type shown", frontInfoBar.getInfoBarIdentifier(), -+ Matchers.is(InfoBarIdentifier.POPUP_BLOCKED_INFOBAR_DELEGATE_MOBILE)); -+ }); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java -@@ -0,0 +1,110 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.InstrumentationRegistry; -+ -+import androidx.test.filters.MediumTest; -+ -+import org.hamcrest.Matchers; -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Criteria; -+import org.chromium.base.test.util.CriteriaHelper; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.components.messages.MessagesTestHelper; -+import org.chromium.net.test.EmbeddedTestServer; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class AdblockPopupMessageTest { -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ -+ private static final String POPUP_HTML_PATH = "/chrome/test/data/android/popup_test.html"; -+ -+ private String mPopupHtmlUrl; -+ private EmbeddedTestServer mTestServer; -+ -+ @Before -+ public void setUp() throws Exception { -+ // Create a new temporary instance to ensure the Class is loaded. Otherwise we will get a -+ // ClassNotFoundException when trying to instantiate during startup. -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ -+ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); -+ mPopupHtmlUrl = mTestServer.getURL(POPUP_HTML_PATH); -+ } -+ -+ @After -+ public void tearDown() { -+ mTestServer.stopAndDestroyServer(); -+ } -+ -+ public int getTabCount() { -+ return mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount(); -+ } -+ -+ @Test -+ @MediumTest -+ @Feature({"adblock"}) -+ public void popUpBlockedMessageVisibleWhenAbpEnabled() throws InterruptedException { -+ mActivityTestRule.loadUrl(mPopupHtmlUrl); -+ Assert.assertEquals(1, getTabCount()); -+ -+ CriteriaHelper.pollUiThread(() -> { -+ Criteria.checkThat(MessagesTestHelper.getMessageCount( -+ mActivityTestRule.getActivity().getWindowAndroid()), -+ Matchers.is(1)); -+ }); -+ } -+ -+ @Test -+ @MediumTest -+ @CommandLineFlags.Add({"disable-adblock"}) -+ @Feature({"adblock"}) -+ public void popUpBlockedMessageVisibleWhenAbpDisabled() { -+ mActivityTestRule.loadUrl(mPopupHtmlUrl); -+ Assert.assertEquals(1, getTabCount()); -+ -+ CriteriaHelper.pollUiThread(() -> { -+ Criteria.checkThat(MessagesTestHelper.getMessageCount( -+ mActivityTestRule.getActivity().getWindowAndroid()), -+ Matchers.is(1)); -+ }); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/FilteringConfigurationTest.java -@@ -0,0 +1,366 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.InstrumentationRegistry; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CallbackHelper; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.base.test.util.IntegrationTest; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+import org.chromium.content_public.common.ContentSwitches; -+import org.chromium.net.test.EmbeddedTestServer; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, -+ ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"}) -+public class FilteringConfigurationTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private CallbackHelper mHelper = new CallbackHelper(); -+ public FilteringConfiguration mConfigurationA; -+ public FilteringConfiguration mConfigurationB; -+ private EmbeddedTestServer mTestServer; -+ private String mTestUrl; -+ -+ private class TestConfigurationChangeObserver -+ implements FilteringConfiguration.ConfigurationChangeObserver { -+ public volatile boolean mOnEnabledStateChangedCalled; -+ public volatile boolean mOnFilterListsChanged; -+ public volatile boolean mOnAllowedDomainsChanged; -+ public volatile boolean mOnCustomFiltersChanged; -+ -+ public TestConfigurationChangeObserver() { -+ mOnEnabledStateChangedCalled = false; -+ mOnFilterListsChanged = false; -+ mOnAllowedDomainsChanged = false; -+ mOnCustomFiltersChanged = false; -+ } -+ -+ @Override -+ public void onEnabledStateChanged() { -+ mOnEnabledStateChangedCalled = true; -+ } -+ @Override -+ public void onFilterListsChanged() { -+ mOnFilterListsChanged = true; -+ } -+ -+ @Override -+ public void onAllowedDomainsChanged() { -+ mOnAllowedDomainsChanged = true; -+ } -+ -+ @Override -+ public void onCustomFiltersChanged() { -+ mOnCustomFiltersChanged = true; -+ } -+ } -+ -+ public void loadTestUrl() throws InterruptedException { -+ mActivityTestRule.loadUrl(mTestUrl, 5); -+ } -+ -+ @Before -+ public void setUp() throws TimeoutException { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA = new FilteringConfiguration("a"); -+ mConfigurationB = new FilteringConfiguration("b"); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); -+ mTestUrl = mTestServer.getURLWithHostName( -+ "test.org", "/chrome/test/data/adblock/innermost_frame.html"); -+ } -+ -+ @After -+ public void tearDown() { -+ mTestServer.stopAndDestroyServer(); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void addingAllowedDomains() throws Exception { -+ final List allowedDomainsA = new ArrayList<>(); -+ final List allowedDomainsB = new ArrayList<>(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addAllowedDomain("foobar.com"); -+ mConfigurationA.addAllowedDomain("domain.com/path/to/page.html"); -+ mConfigurationA.addAllowedDomain("domain.com/duplicate.html"); -+ allowedDomainsA.addAll(mConfigurationA.getAllowedDomains()); -+ -+ mConfigurationB.addAllowedDomain("https://scheme.com/path.html"); -+ mConfigurationB.addAllowedDomain("https://second.com"); -+ mConfigurationB.removeAllowedDomain("https://second.com"); -+ mConfigurationB.addAllowedDomain("gibberish"); -+ allowedDomainsB.addAll(mConfigurationB.getAllowedDomains()); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ // We expect to see a sorted collection of domains (not URLs) without duplicates. -+ ArrayList expectedAllowedDomainsA = new ArrayList(); -+ expectedAllowedDomainsA.add("domain.com"); -+ expectedAllowedDomainsA.add("foobar.com"); -+ Assert.assertEquals(expectedAllowedDomainsA, allowedDomainsA); -+ -+ // We expect not to see second.com because it was removed after being added. -+ ArrayList expectedAllowedDomainsB = new ArrayList(); -+ expectedAllowedDomainsB.add("scheme.com"); -+ expectedAllowedDomainsB.add("www.gibberish.com"); -+ Assert.assertEquals(expectedAllowedDomainsB, allowedDomainsB); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void addingCustomFilters() throws Exception { -+ final List customFiltersA = new ArrayList<>(); -+ final List customFiltersB = new ArrayList<>(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addCustomFilter("foobar.com"); -+ mConfigurationA.addCustomFilter("foobar.com"); -+ mConfigurationA.addCustomFilter("abc"); -+ customFiltersA.addAll(mConfigurationA.getCustomFilters()); -+ -+ mConfigurationB.addCustomFilter("https://scheme.com/path.html"); -+ mConfigurationB.addCustomFilter("https://second.com"); -+ mConfigurationB.removeCustomFilter("https://second.com"); -+ customFiltersB.addAll(mConfigurationB.getCustomFilters()); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ // We expect to see a collection of custom filters without duplicates. -+ // The order represents order of addition. -+ ArrayList expectedCustomFiltersA = new ArrayList(); -+ expectedCustomFiltersA.add("foobar.com"); -+ expectedCustomFiltersA.add("abc"); -+ Assert.assertEquals(expectedCustomFiltersA, customFiltersA); -+ -+ // We expect not to see https://second.com because it was removed after being added. -+ ArrayList expectedCustomFiltersB = new ArrayList(); -+ expectedCustomFiltersB.add("https://scheme.com/path.html"); -+ Assert.assertEquals(expectedCustomFiltersB, customFiltersB); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void addingFilterLists() throws Exception { -+ final URL filterList1 = new URL("http://filters.com/list1.txt"); -+ final URL filterList2 = new URL("http://filters.com/list2.txt"); -+ final List filterListsA = new ArrayList(); -+ final List filterListsB = new ArrayList(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addFilterList(filterList1); -+ mConfigurationA.addFilterList(filterList2); -+ mConfigurationA.addFilterList(filterList1); -+ filterListsA.addAll(mConfigurationA.getFilterLists()); -+ -+ mConfigurationB.addFilterList(filterList1); -+ mConfigurationB.addFilterList(filterList2); -+ mConfigurationB.removeFilterList(filterList1); -+ filterListsB.addAll(mConfigurationB.getFilterLists()); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ ArrayList expectedFilterListsA = new ArrayList(); -+ expectedFilterListsA.add(filterList1); -+ expectedFilterListsA.add(filterList2); -+ Assert.assertEquals(expectedFilterListsA, filterListsA); -+ -+ ArrayList expectedFilterListsB = new ArrayList(); -+ expectedFilterListsB.add(filterList2); -+ Assert.assertEquals(expectedFilterListsB, filterListsB); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void aliasedConfigurations() throws Exception { -+ final URL filterList1 = new URL("http://filters.com/list1.txt"); -+ final URL filterList2 = new URL("http://filters.com/list2.txt"); -+ final List filterListsA = new ArrayList(); -+ final List filterListsB = new ArrayList(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ // Create a new FilteringConfiguration with a name of one that -+ // already exist. -+ FilteringConfiguration aliasedConfiguration = new FilteringConfiguration("a"); -+ -+ // We add filter lists only to the original configuration instance. -+ mConfigurationA.addFilterList(filterList1); -+ mConfigurationA.addFilterList(filterList2); -+ -+ // We check what filter lists are present in the original and in the aliased instance. -+ filterListsA.addAll(mConfigurationA.getFilterLists()); -+ filterListsB.addAll(aliasedConfiguration.getFilterLists()); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ ArrayList expectedFilterLists = new ArrayList(); -+ expectedFilterLists.add(filterList1); -+ expectedFilterLists.add(filterList2); -+ Assert.assertEquals(expectedFilterLists, filterListsA); -+ Assert.assertEquals(expectedFilterLists, filterListsB); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void configurationChangeObserverNotified() throws Exception { -+ final URL filterList1 = new URL("http://filters.com/list1.txt"); -+ final TestConfigurationChangeObserver observer = new TestConfigurationChangeObserver(); -+ Assert.assertFalse(observer.mOnEnabledStateChangedCalled); -+ Assert.assertFalse(observer.mOnAllowedDomainsChanged); -+ Assert.assertFalse(observer.mOnCustomFiltersChanged); -+ Assert.assertFalse(observer.mOnFilterListsChanged); -+ -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ // We'll create an aliased instance which will receive notifications triggered by -+ // changes made to the original instance. -+ FilteringConfiguration aliasedConfiguration = new FilteringConfiguration("a"); -+ aliasedConfiguration.addObserver(observer); -+ -+ mConfigurationA.addFilterList(filterList1); -+ mConfigurationA.addAllowedDomain("test.com"); -+ mConfigurationA.addCustomFilter("test.com"); -+ mConfigurationA.setEnabled(false); -+ -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ Assert.assertTrue(observer.mOnEnabledStateChangedCalled); -+ Assert.assertTrue(observer.mOnAllowedDomainsChanged); -+ Assert.assertTrue(observer.mOnCustomFiltersChanged); -+ Assert.assertTrue(observer.mOnFilterListsChanged); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void resourceBlockedByFilter() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addCustomFilter("resource.png"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ TestVerificationUtils.expectResourceBlocked(mActivityTestRule, "subresource"); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void resourceAllowedByFilter() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addCustomFilter("resource.png"); -+ // Allowing filter for the mocked test.org domain that mTestServer hosts. -+ mConfigurationA.addCustomFilter("@@test.org$document"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void resourceAllowedByAllowedDomain() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfigurationA.addCustomFilter("resource.png"); -+ mConfigurationA.addAllowedDomain("test.org"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void resourceBlockedBySecondConfiguration() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ // ConfigurationA allows the resource. -+ // Allowing rules take precedence within a FilteringConfiguration. -+ mConfigurationA.addCustomFilter("resource.png"); -+ mConfigurationA.addAllowedDomain("test.org"); -+ // But ConfigurationB blocks the resource. -+ // Blocking takes precedence across FilteringConfigurations. -+ mConfigurationB.addCustomFilter("resource.png"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ TestVerificationUtils.expectResourceBlocked(mActivityTestRule, "subresource"); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void noBlockingWithoutFilters() throws Exception { -+ loadTestUrl(); -+ TestVerificationUtils.expectResourceShown(mActivityTestRule, "subresource"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/ResourceClassificationNotifierTest.java -@@ -0,0 +1,143 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.InstrumentationRegistry; -+import android.util.Log; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CallbackHelper; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.base.test.util.IntegrationTest; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+import org.chromium.content_public.common.ContentSwitches; -+import org.chromium.net.test.EmbeddedTestServer; -+ -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, -+ ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"}) -+public class ResourceClassificationNotifierTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private CallbackHelper mHelper = new CallbackHelper(); -+ public FilteringConfiguration mConfiguration; -+ public TestAdBlockedObserver mAdBlockedObserver = new TestAdBlockedObserver(); -+ -+ private EmbeddedTestServer mTestServer; -+ private String mTestUrl; -+ -+ public void loadTestUrl() throws InterruptedException { -+ mActivityTestRule.loadUrl(mTestUrl, 5); -+ } -+ -+ @Before -+ public void setUp() throws TimeoutException { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfiguration = new FilteringConfiguration("a"); -+ ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(mAdBlockedObserver); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); -+ mTestUrl = mTestServer.getURLWithHostName( -+ "test.org", "/chrome/test/data/adblock/innermost_frame.html"); -+ } -+ -+ @After -+ public void tearDown() { -+ mTestServer.stopAndDestroyServer(); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void noNotificationWithoutBlocking() throws Exception { -+ loadTestUrl(); -+ -+ Assert.assertTrue(mAdBlockedObserver.blockedInfos.isEmpty()); -+ Assert.assertTrue(mAdBlockedObserver.allowedInfos.isEmpty()); -+ Assert.assertTrue(mAdBlockedObserver.allowedPageInfos.isEmpty()); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void resourceBlockedByFilter() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfiguration.addCustomFilter("resource.png"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ // Observer was notified about the blocking -+ Assert.assertTrue(mAdBlockedObserver.isBlocked("resource.png")); -+ Assert.assertTrue(mAdBlockedObserver.allowedInfos.isEmpty()); -+ Assert.assertTrue(mAdBlockedObserver.allowedPageInfos.isEmpty()); -+ } -+ -+ @Test -+ @IntegrationTest -+ @LargeTest -+ @Feature({"adblock"}) -+ public void pageAllowed() throws Exception { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ mConfiguration.addCustomFilter("resource.png"); -+ mConfiguration.addAllowedDomain("test.org"); -+ mHelper.notifyCalled(); -+ }); -+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS); -+ loadTestUrl(); -+ // Observer was notified about the allowed resource -+ Assert.assertTrue(mAdBlockedObserver.blockedInfos.isEmpty()); -+ Assert.assertTrue(mAdBlockedObserver.isAllowed("resource.png")); -+ -+ // TODO(mpawlowski): The observer could also be notified about the entire domain being -+ // allowed: Assert.assertTrue(mAdBlockedObserver.isPageAllowed("test.org")); However this is -+ // currently broken with multiple FilteringConfigurations (DPD-1729). -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java -@@ -0,0 +1,183 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import org.junit.Assert; -+import org.junit.Rule; -+ -+import java.net.URL; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.CopyOnWriteArrayList; -+import java.util.concurrent.CountDownLatch; -+import java.util.concurrent.TimeoutException; -+ -+public class TestAdBlockedObserver implements ResourceClassificationNotifier.AdBlockedObserver { -+ @Override -+ public void onAdAllowed(AdblockCounters.ResourceInfo info) { -+ allowedInfos.add(info); -+ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); -+ CheckAndCountDownLatch(Decision.ALLOWED, info.getRequestUrl().split("\\?")[0]); -+ } -+ -+ @Override -+ public void onAdBlocked(AdblockCounters.ResourceInfo info) { -+ blockedInfos.add(info); -+ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); -+ CheckAndCountDownLatch(Decision.BLOCKED, info.getRequestUrl().split("\\?")[0]); -+ } -+ -+ @Override -+ public void onPageAllowed(AdblockCounters.ResourceInfo info) { -+ allowedPageInfos.add(info); -+ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); -+ } -+ -+ @Override -+ public void onPopupAllowed(AdblockCounters.ResourceInfo info) { -+ allowedPopupsInfos.add(info); -+ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); -+ } -+ -+ @Override -+ public void onPopupBlocked(AdblockCounters.ResourceInfo info) { -+ blockedPopupsInfos.add(info); -+ Assert.assertTrue(info.getSubscription().equals(getExpectedSubscriptionUrl())); -+ } -+ -+ public boolean isBlocked(String url) { -+ for (AdblockCounters.ResourceInfo info : blockedInfos) { -+ if (info.getRequestUrl().contains(url)) return true; -+ } -+ -+ return false; -+ } -+ -+ public boolean isPopupBlocked(String url) { -+ for (AdblockCounters.ResourceInfo info : blockedPopupsInfos) { -+ if (info.getRequestUrl().contains(url)) return true; -+ } -+ -+ return false; -+ } -+ -+ public int numBlockedByType(AdblockContentType type) { -+ int result = 0; -+ for (AdblockCounters.ResourceInfo info : blockedInfos) { -+ if (info.getAdblockContentType() == type) ++result; -+ } -+ return result; -+ } -+ -+ public int numBlockedPopups() { -+ int result = 0; -+ for (AdblockCounters.ResourceInfo info : blockedPopupsInfos) { -+ ++result; -+ } -+ return result; -+ } -+ -+ public boolean isAllowed(String url) { -+ for (AdblockCounters.ResourceInfo info : allowedInfos) { -+ if (info.getRequestUrl().contains(url)) return true; -+ } -+ -+ return false; -+ } -+ -+ public boolean isPageAllowed(String url) { -+ for (AdblockCounters.ResourceInfo info : allowedPageInfos) { -+ if (info.getRequestUrl().contains(url)) return true; -+ } -+ -+ return false; -+ } -+ -+ public boolean isPopupAllowed(String url) { -+ for (AdblockCounters.ResourceInfo info : allowedPopupsInfos) { -+ if (info.getRequestUrl().contains(url)) return true; -+ } -+ -+ return false; -+ } -+ -+ public int numAllowedByType(AdblockContentType type) { -+ int result = 0; -+ for (AdblockCounters.ResourceInfo info : allowedInfos) { -+ if (info.getAdblockContentType() == type) ++result; -+ } -+ return result; -+ } -+ -+ public int numAllowedPopups() { -+ int result = 0; -+ for (AdblockCounters.ResourceInfo info : allowedPopupsInfos) { -+ ++result; -+ } -+ return result; -+ } -+ -+ public void setExpectedSubscriptionUrl(URL url) { -+ mTestSubscriptionUrl = url; -+ } -+ -+ private String getExpectedSubscriptionUrl() { -+ if (mTestSubscriptionUrl != null) return mTestSubscriptionUrl.toString(); -+ return "adblock:custom"; -+ } -+ -+ private enum Decision { ALLOWED, BLOCKED } -+ -+ // We either countDown() our latch for every filtered resource if there are no -+ // specific expectations set (expectedAllowed == null && expectedBlocked == null), -+ // or we countDown() only when all expectations have been met so when: -+ // (expectedAllowed.isNullOrEmpty() && expectedBlocked.isNullOrEmpty()). -+ private void CheckAndCountDownLatch(final Decision decision, final String url) { -+ if (countDownLatch != null) { -+ if (expectedBlocked == null && expectedAllowed == null) { -+ countDownLatch.countDown(); -+ } else { -+ if (decision == Decision.BLOCKED) { -+ if (expectedBlocked != null) { -+ expectedBlocked.remove(url); -+ } -+ } else { -+ if (expectedAllowed != null) { -+ expectedAllowed.remove(url); -+ } -+ } -+ boolean expectationsMet = (expectedAllowed == null || expectedAllowed.isEmpty()) -+ && (expectedBlocked == null || expectedBlocked.isEmpty()); -+ if (expectationsMet) { -+ countDownLatch.countDown(); -+ } -+ } -+ } -+ } -+ -+ private URL mTestSubscriptionUrl; -+ List blockedInfos = new CopyOnWriteArrayList<>(); -+ List allowedInfos = new CopyOnWriteArrayList<>(); -+ List allowedPageInfos = new CopyOnWriteArrayList<>(); -+ List blockedPopupsInfos = new CopyOnWriteArrayList<>(); -+ List allowedPopupsInfos = new CopyOnWriteArrayList<>(); -+ CountDownLatch countDownLatch; -+ Set expectedAllowed; -+ Set expectedBlocked; -+}; -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java -@@ -0,0 +1,90 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.DOMUtils; -+import org.chromium.content_public.browser.test.util.JavaScriptUtils; -+ -+import java.lang.Thread; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesCircumventionTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyCircumventionInlineStyleNotImportant() -+ throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT -+ + "inline-style-important"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 2, "div"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyCircumventionAnonymousFrameDocumentWrite() -+ throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT -+ + "anoniframe-documentwrite"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[data-expectedresult='fail']"); -+ String numHidden = JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ mHelper.getWebContents(), -+ "var hiddenCount = 0;" -+ + "var elements = document.getElementById(\"write\").contentWindow.document.getElementsByTagName(\"span\");" -+ + "for (let i = 0; i < elements.length; ++i) {" -+ + " if (window.getComputedStyle(elements[i]).display == \"none\") ++hiddenCount;" -+ + "}" -+ + "hiddenCount;"); -+ Assert.assertEquals("1", numHidden); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java -@@ -0,0 +1,136 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesCspTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testCspAllSites() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter("*$csp=script-src 'none'"); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_all"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "img[id='all-sites-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testCspSpecificSite() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "img[id='specific-site-fail-1']", IncludeSubframes.NO); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testCspSpecificSiteFrameSrc() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("||%s^$csp=frame-src 'self'", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div[id='sub-frame-error']", IncludeSubframes.NO); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div[id='sub-frame-error-details']", IncludeSubframes.NO); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testCspException() throws TimeoutException, InterruptedException { -+ // Blocking filter: -+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ // Resource loaded by JS was blocked -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div[id='unblock-javascript'] > img"); -+ -+ // Allowing filter: -+ mHelper.addCustomFilter( -+ String.format("@@||%s^$csp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ // Resource loaded by JS was allowed -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[id='unblock-javascript'] > img"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testCspGenericBlockException() throws TimeoutException, InterruptedException { -+ // Blocking filter: -+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ // Resource loaded by JS was blocked -+ mHelper.loadUrl( -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div[id='genericblock-javascript'] > img"); -+ -+ // Allowing filter: -+ mHelper.addCustomFilter( -+ String.format("@@||%s^$genericblock", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ // Resource loaded by JS was allowed -+ mHelper.loadUrl( -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[id='genericblock-javascript'] > img"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java -@@ -0,0 +1,158 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesElemhideEmuInvTest { -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT -+ + "element-hiding-emulation-inversion"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotAbpProperties() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#.ehei-properties:not(:-abp-properties(width: 238px))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='basic-not-abp-properties-usage-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotAbpHas() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#.ehei-has:not(:-abp-has(span.ehei-has-not-hide))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='basic-not-abp-has-usage-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotAbpContains() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#.ehei-contains:not(span:-abp-contains(example-content))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='basic-not-abp-contains-usage-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotChained() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#.ehei-chained-parent:not(:-abp-has(> div:-abp-properties(width: 198px)))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, -+ "div[id='chained-extended-selectors-with-not-selector-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotCaseIsensitive() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#?#.ehei-case:not(:-abp-properties(WiDtH: 209px))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, -+ "div[id='case-insensitive-extended-selectors-with-not-selector-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotWildcard() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#?#.ehei-wildcard:not(:-abp-properties(cursor:*))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, -+ "div[id='wildcard-in-extended-selector-combined-with-not-selector-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotRegexAbpProperties() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#.ehei-regex:not(:-abp-properties(/width: 11[1-5]px;/))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-not-abp-properties-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-not-abp-properties-fail-2']"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, ".ehei-regex3"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuNotRegexAbpContains() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#.ehei-contains-regex:not(span:-abp-contains(/example-contentregex\\d/))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='regular-expression-in-not-abp-contains-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='regular-expression-in-not-abp-contains-fail-2']"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 2, ".ehei-contains-regex"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java -@@ -0,0 +1,217 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesElemhideEmuTest { -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding-emulation"; -+ public static final String ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL = -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "element-hiding"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicAbpProperties() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#div:-abp-properties(width: 213px)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='basic-abp-properties-usage-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicAbpHas() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#div:-abp-has(>div>span.ehe-abp-has)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='basic-abp-has-usage-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicHas() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#div:has(>div>span.ehe-has)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ // "Basic :has() usage" are duplicated on testpage. -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "div[id='basic-has-usage-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicAbpContains() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#?#span:-abp-contains(ehe-contains-target)", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='basic-abp-contains-usage-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicXpath() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#span:xpath(//*[@id=\"basic-xpath-usage-fail\"])", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='basic-xpath-usage-fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersBasicHasText() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#span:has-text(ehe-has-text)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "span[id='basic-has-text-usage-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersChainedExtendedSelectors() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#div:-abp-has(> div:-abp-properties(width: 214px))", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='chained-extended-selectors-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersCaseInsensitiveExtendedSelectors() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#div:-abp-properties(WiDtH: 215px)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='case-insensitive-extended-selectors-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersWildcardInExtendedSelector() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#?#div:-abp-properties(cursor:*)", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='wildcard-in-extended-selector-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersRegularExpressionInAbpProperties() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#?#div:-abp-properties(/width: 12[1-5]px;/)", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-abp-properties-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-abp-properties-fail-2']"); -+ // "Not a target" div is not hidden, does not match regular expression. -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[class='testcase-examplecontent ehe-regex3']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersRegularExpressionInAbpContains() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#?#div > div:-abp-contains(/ehe-containsregex\\d/)", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-abp-contains-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='regular-expression-in-abp-contains-fail-2']"); -+ } -+ -+ // Exceptions: -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideEmuFiltersException() throws TimeoutException, InterruptedException { -+ // Add a blocking filter, verify element hidden. -+ mHelper.addCustomFilter( -+ String.format("%s##.testcase-ehe", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='exception-usage-pass-1']"); -+ -+ // Add exception filter, verify element no longer hidden. -+ mHelper.addCustomFilter( -+ String.format("%s#@#.testcase-ehe", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[id='exception-usage-pass-1']"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java -@@ -0,0 +1,237 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesElemhideTest { -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String ELEMENT_HIDING_TESTPAGES_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding"; -+ public static final String ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL = -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "elemhide"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersIdSelector() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s###eh-id", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='eh-id']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersIdSelectorDoubleCurlyBraces() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s##div[id='{{eh-id}}']", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='{{eh-id}}']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersClassSelector() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s##.eh-class", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-class']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersDescendantSelector() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##.testcase-area > .eh-descendant", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-descendant']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersSiblingSelector() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s##.testcase-examplecontent + .eh-sibling", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[class='eh-sibling']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersAttributeSelector1() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##div[height=\"100\"][width=\"100\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='attribute-selector-1-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersAttributeSelector2() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s##div[href=\"http://testcase-attribute.com/\"]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='attribute-selector-2-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersAttributeSelector3() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##div[style=\"width: 200px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='attribute-selector-3-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersStartsWithSelector1() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s##div[href^=\"http://testcase-startswith.com/\"]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='starts-with-selector-1-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersStartsWithSelector2() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##div[style^=\"width: 201px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='starts-with-selector-2-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersEndsWithSelector1() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##div[style$=\"width: 202px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='ends-with-selector-1-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersContains() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s##div[style*=\"width: 203px;\"]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='contains-fail-1']"); -+ } -+ -+ // Exceptions: -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersBasicException() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s##.ex-elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/elemhide/basic/*", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); -+ // No exceptions added yet, both objects should be blocked. -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "img[id='basic-usage-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[id='basic-usage-pass-1']"); -+ // Add exception filter and reload. -+ mHelper.addCustomFilter(String.format( -+ "@@%s/en/exceptions/elemhide$elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); -+ // Image should remain blocked, div should be unblocked. -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "img[id='basic-usage-fail-1']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[id='basic-usage-area'] > div[id='basic-usage-pass-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testElemHideFiltersIframeException() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s##.targ-elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/elemhide/iframe/*.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img[id='iframe-fail-1']"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div[id='iframe-pass-1']"); -+ -+ // Add exception filter and reload. -+ mHelper.addCustomFilter(String.format( -+ "@@%s/en/exceptions/elemhide$elemhide", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img[id='iframe-fail-1']"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "div[id='iframe-pass-1']"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java -@@ -0,0 +1,229 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.DOMUtils; -+import org.chromium.content_public.browser.test.util.JavaScriptUtils; -+ -+import java.lang.Thread; -+import java.util.Arrays; -+import java.util.HashSet; -+import java.util.concurrent.CountDownLatch; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesExceptionTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyImageExceptions() throws TimeoutException, InterruptedException { -+ final String subdomainImage = String.format( -+ "https://allowed.subdomain.%s/testfiles/image_exception/subdomain.png", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN); -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "image"); -+ Assert.assertEquals(2, mHelper.numAllowed()); -+ Assert.assertEquals(2, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue(mHelper.isAllowed(subdomainImage)); -+ Assert.assertTrue(mHelper.isAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image_exception/image.png")); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 2, "img"); -+ String numImages = JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ mHelper.getWebContents(), "document.getElementsByTagName(\"img\").length;"); -+ Assert.assertEquals("2", numImages); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyPopupException() throws TimeoutException, InterruptedException { -+ final String POPUP_TESTACE_URL = -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "popup"; -+ mHelper.loadUrl(POPUP_TESTACE_URL); -+ Assert.assertEquals(1, mHelper.getTabCount()); -+ String numElements = -+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(), -+ "var elements = document.getElementsByClassName(\"testcase-trigger\");" -+ + "for (let i = 0; i < elements.length; ++i) {" -+ + " elements[i].click();" -+ + "}" -+ + "elements.length;"); -+ Assert.assertEquals("3", numElements); -+ Assert.assertEquals(4, mHelper.getTabCount()); -+ Assert.assertEquals(3, mHelper.numAllowedPopups()); -+ Assert.assertTrue(mHelper.isPopupAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup_exception/link.html")); -+ Assert.assertTrue(mHelper.isPopupAllowed(TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "popup_exception/script-window.html")); -+ Assert.assertTrue(mHelper.isPopupAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup_exception/script-tab.html")); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifySubdocumentException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "subdocument"); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertTrue(mHelper.isAllowed(TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "subdocument_exception/subdocument.html")); -+ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "exception-target"); -+ String numFrames = JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ mHelper.getWebContents(), "window.frames.length;"); -+ Assert.assertEquals("1", numFrames); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "iframe"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyScriptException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "script"); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertTrue(mHelper.isAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script_exception/script.js")); -+ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "script-target"); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script_exception/image.png")); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyStylesheetException() throws TimeoutException, InterruptedException { -+ final String allowedUrl = TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "stylesheet_exception/stylesheet.cs"; -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(allowedUrl))); -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "stylesheet"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertTrue(mHelper.isAllowed(allowedUrl)); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "stylesheet_exception/image.png")); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img"); -+ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "exception-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyXHRException() throws TimeoutException, InterruptedException { -+ final String allowedUrl = -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest_exception/text.txt"; -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(allowedUrl))); -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertTrue(mHelper.isAllowed(allowedUrl)); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyGenericBlockException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "genericblock"); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "genericblock/specific.png")); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "img[data-expectedresult='pass']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyGenericHideException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "generichide"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[data-expectedresult='pass']"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyDocumentException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document"); -+ Assert.assertTrue(mHelper.isAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "document/image.png")); -+ Assert.assertTrue(mHelper.isPageAllowed( -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document")); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyWebSocketException() throws TimeoutException, InterruptedException { -+ final String wssUrl = -+ String.format("wss://%s/websocket", TestPagesTestsHelper.TESTPAGES_DOMAIN); -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(Arrays.asList(wssUrl))); -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "websocket"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET)); -+ Assert.assertTrue(mHelper.isAllowed(wssUrl)); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java -@@ -0,0 +1,311 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; -+import org.chromium.content_public.browser.test.util.DOMUtils; -+import org.chromium.content_public.browser.test.util.JavaScriptUtils; -+ -+import java.lang.Thread; -+import java.util.Arrays; -+import java.util.HashSet; -+import java.util.concurrent.CountDownLatch; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesFilterTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ mHelper.addFilterList(TestPagesTestsHelper.TESTPAGES_SUBSCRIPTION); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testBlockingFilters() throws TimeoutException, InterruptedException { -+ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations( -+ new HashSet<>(Arrays.asList( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/full-path.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "blocking/partial-path/partial-path.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "blocking/wildcard/1/wildcard.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "blocking/wildcard/2/wildcard.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/dynamic.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "blocking/subdomain.png")), -+ null); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "blocking"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(6, mHelper.numBlocked()); -+ Assert.assertEquals(6, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 6, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyScriptFilters() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "script"); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "script/script.js")); -+ -+ String childCount = -+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(), -+ "document.getElementById(\"script-target\").childElementCount"); -+ Assert.assertEquals("1", childCount); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyImageFilters() throws TimeoutException, InterruptedException { -+ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations( -+ new HashSet<>(Arrays.asList( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/static/static.png", -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT -+ + "image/dynamic/dynamic.png")), -+ null); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "image"); -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(2, mHelper.numBlocked()); -+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/static/static.png")); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "image/dynamic/dynamic.png")); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyStylesheetFilters() throws TimeoutException, InterruptedException { -+ final String blockedUrl = -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "stylesheet/stylesheet.cs"; -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(blockedUrl)), null); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "stylesheet"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals( -+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET)); -+ Assert.assertTrue(mHelper.isBlocked(blockedUrl)); -+ String value = DOMUtils.getNodeContents(mHelper.getWebContents(), "stylesheet-target"); -+ Assert.assertEquals("Passed. Stylesheet was blocked.", value); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyPopupFilters() throws TimeoutException, InterruptedException { -+ final String POPUP_TESTACE_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "popup"; -+ mHelper.loadUrl(POPUP_TESTACE_URL); -+ Assert.assertEquals(1, mHelper.getTabCount()); -+ String numElements = -+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(), -+ "var elements = document.getElementsByClassName(\"testcase-trigger\");" -+ + "for (let i = 0; i < elements.length; ++i) {" -+ + " elements[i].click();" -+ + "}" -+ + "elements.length;"); -+ Assert.assertEquals("3", numElements); -+ Assert.assertEquals(3, mHelper.numBlockedPopups()); -+ Assert.assertTrue(mHelper.isPopupBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/link.html")); -+ Assert.assertTrue(mHelper.isPopupBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/script-window.html")); -+ Assert.assertTrue(mHelper.isPopupBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "popup/script-tab.html")); -+ Assert.assertEquals(1, mHelper.getTabCount()); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyXHRFilters() throws TimeoutException, InterruptedException { -+ final String blockedUrl = -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest/text.txt"; -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(blockedUrl)), null); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals( -+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_XMLHTTPREQUEST)); -+ Assert.assertTrue(mHelper.isBlocked(blockedUrl)); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifySubdocumentFilters() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "subdocument"); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals( -+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SUBDOCUMENT)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "subdocument/subdocument.html")); -+ // Do not search for iframe within the site's iframes. -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "iframe[data-expectedresult='fail']", IncludeSubframes.NO); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ @DisabledTest(message = "Please enable again when rewrite filters will be supported") -+ public void testVerifyRewrite() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite"); -+ Assert.assertEquals(3, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); -+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_MEDIA)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/audio.mp3")); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/video.mp4")); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "rewrite/script.js")); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyMatchCaseFilter() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "match-case"); -+ Assert.assertEquals(2, mHelper.numBlocked()); -+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyThirdPartyFilter() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "third-party"); -+ Assert.assertEquals(2, mHelper.numBlocked()); -+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "img[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 2, "img[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyOtherFilter() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "other"); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_OTHER)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "other/image.png")); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyDomainFilter() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "domain"); -+ Assert.assertEquals(2, mHelper.numBlocked()); -+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "domain/static/target/image.png")); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "domain/dynamic/image.png")); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "img[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyPingFilter() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "ping"); -+ // Ping action not yet triggered -+ Assert.assertEquals(0, mHelper.numBlocked()); -+ final CountDownLatch countDownLatch = new CountDownLatch(1); -+ mHelper.setOnAdMatchedLatch(countDownLatch); -+ // Trigger ping action -+ final Tab tab = mActivityTestRule.getActivity().getActivityTab(); -+ JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ tab.getWebContents(), "document.getElementById(\"script-ping-trigger\").click()"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyPingFilterException() throws TimeoutException, InterruptedException { -+ mHelper.loadUrl(TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "ping"); -+ // Ping action not yet triggered -+ Assert.assertEquals(0, mHelper.numAllowed()); -+ final CountDownLatch countDownLatch = new CountDownLatch(1); -+ mHelper.setOnAdMatchedLatch(countDownLatch); -+ // Trigger ping action -+ final Tab tab = mActivityTestRule.getActivity().getActivityTab(); -+ JavaScriptUtils.executeJavaScriptAndWaitForResult(tab.getWebContents(), -+ "document.getElementsByClassName(\"testcase-trigger\")[0].click()"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertEquals(0, mHelper.numBlocked()); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java -@@ -0,0 +1,150 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.components.adblock.TestVerificationUtils.IncludeSubframes; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesHeaderFilterTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String HEADER_TESTPAGES_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "header"; -+ public static final String HEADER_EXCEPTIONS_TESTPAGES_URL = -+ TestPagesTestsHelper.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "header"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHeaderFilterScript() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("||%s/testfiles/header/$header=content-type=application/javascript", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT)); -+ Assert.assertTrue(mHelper.isBlocked(String.format( -+ "https://%s/testfiles/header/script.js", TestPagesTestsHelper.TESTPAGES_DOMAIN))); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, -+ "div#functionproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHeaderFilterImage() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("||%s/testfiles/header/image.png$header=content-type=image/png", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue(mHelper.isBlocked(String.format( -+ "https://%s/testfiles/header/image.png", TestPagesTestsHelper.TESTPAGES_DOMAIN))); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "img[id='image-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHeaderFilterImageAndComma() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("||%s/testfiles/header/image2.png$header=date=\\x2c", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue(mHelper.isBlocked(String.format( -+ "https://%s/testfiles/header/image2.png", TestPagesTestsHelper.TESTPAGES_DOMAIN))); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "img[id='comma-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHeaderFilterStylesheet() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("||%s/testfiles/header/$header=content-type=text/css", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals( -+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET)); -+ Assert.assertTrue( -+ mHelper.isBlocked(String.format("https://%s/testfiles/header/stylesheet.css", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN))); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHeaderFilterException() throws TimeoutException, InterruptedException { -+ // Add blocking filter, expect blocked image -+ mHelper.addCustomFilter( -+ String.format("||%s/testfiles/header_exception/$header=content-type=image/png", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "img[id='image-header-exception-pass-1']"); -+ -+ // Add exception filter, expect image allowed -+ mHelper.addCustomFilter(String.format( -+ "@@%s/testfiles/header_exception/$header", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE)); -+ Assert.assertTrue( -+ mHelper.isAllowed(String.format("https://%s/testfiles/header_exception/image.png", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN))); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "img[id='image-header-exception-pass-1']"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java -@@ -0,0 +1,177 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.JavaScriptUtils; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesRewriteTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String REWRITE_TEST_URL = -+ TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteScript() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.js$rewrite=abp-resource:blank-js,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, "div[id='script-fail-1']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteStylesheet() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.css$rewrite=abp-resource:blank-css,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifyGreenBackground(mActivityTestRule, "stylesheet-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteSubdocument() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.html$rewrite=abp-resource:blank-html,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "subdocument-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteText() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.txt$rewrite=abp-resource:blank-text,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "text-status"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteGif() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/1x1.gif$rewrite=abp-resource:1x1-transparent-gif,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "1x1-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewrite2x2Png() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/2x2.png$rewrite=abp-resource:2x2-transparent-png,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "2x2-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewrite3x2Png() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/3x2.png$rewrite=abp-resource:3x2-transparent-png,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "3x2-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewrite32x32Png() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/32x32.png$rewrite=abp-resource:32x32-transparent-png,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ TestVerificationUtils.verifySelfTestPass(mActivityTestRule, "32x32-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteAudio() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.mp3$rewrite=abp-resource:blank-mp3,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ mActivityTestRule.getActivity().getActivityTab().getWebContents(), -+ "document.getElementById('audio-area').lastChild.getAttribute('data-expectedresult')"); -+ Assert.assertEquals("\"pass\"", value); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testRewriteVideo() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/rewrite/*.mp4$rewrite=abp-resource:blank-mp4,domain=%s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrl(REWRITE_TEST_URL); -+ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult( -+ mActivityTestRule.getActivity().getActivityTab().getWebContents(), -+ "document.getElementById('video-area').lastChild.getAttribute('data-expectedresult')"); -+ Assert.assertEquals("\"pass\"", value); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java -@@ -0,0 +1,82 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesSiteKeyTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifySitekeyException() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#@#[data-adblockkey]", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter( -+ String.format("%s##.testcase-sitekey-eh", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/sitekey/outofframe.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter(String.format( -+ "||%s/testfiles/sitekey/inframe.png", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.addCustomFilter( -+ "@@$document,sitekey=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANGtTstne7e8MbmDHDiMFkGbcuBgXmiVesGOG3gtYeM1EkrzVhBjGUvKXYE4GLFwqty3v5MuWWbvItUWBTYoVVsCAwEAAQ"); -+ mHelper.loadUrl(TestPagesTestsHelper.SITEKEY_TESTPAGES_TESTCASES_ROOT); -+ Assert.assertEquals(1, mHelper.numBlocked()); -+ Assert.assertTrue(mHelper.isBlocked( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "sitekey/outofframe.png")); -+ Assert.assertEquals(1, mHelper.numAllowed()); -+ Assert.assertTrue(mHelper.isAllowed( -+ TestPagesTestsHelper.TESTPAGES_RESOURCES_ROOT + "sitekey/inframe.png")); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "img"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "div"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java -@@ -0,0 +1,545 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.DisabledTest; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesSnippetsTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ public static final String SNIPPETS_TESTPAGES_TESTCASES_ROOT = -+ TestPagesTestsHelper.TESTPAGES_TESTCASES_ROOT + "snippets/"; -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortCurrentInlineScriptBasic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-current-inline-script console.group", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); -+ // All "Abort" snippets cancel creation of the target div, so it won't be hidden - it will -+ // not exist in DOM. Therefore we verify it's not displayed instead of verifying it's -+ // hidden. -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortCurrentInlineScriptSearch() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#abort-current-inline-script console.info acis-search", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#search-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortCurrentInlineScriptRegex() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#abort-current-inline-script console.warn '/acis-regex[1-2]/'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-current-inline-script"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#regex-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyReadBasic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#abort-on-property-read aoprb", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyReadSubProperty() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#abort-on-property-read aopr.sp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyReadFunctionProperty() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#abort-on-property-read aoprf.fp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, -+ "div#functionproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyWriteBasic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-property-write window.aopwb", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyWriteSubProperty() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-property-write window.aopwsp", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnPropertyWriteFunctionProperty() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#abort-on-property-write aopwf.fp", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, -+ "div#functionproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyReadBasic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoiprb", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyReadSubProperty() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr.sp", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyReadMultipleProperties() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr1 aoipr2", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-read"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, -+ "div#multipleproperties-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyWriteBasic() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipwb", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyWriteSubProperty() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw.sp", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#subproperty-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testAbortOnIframePropertyWriteMultipleProperties() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw1 aoipw2", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-iframe-property-write"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 0, -+ "div#multipleproperties-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsStatic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-static' p[id]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-static-id"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsDynamic() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-dynamic' p[id]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-dynamic-id"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsSearch() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-search' p[id] .target", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#search2-target > p.target"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#search1-target > p[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsRegex() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains /hic-regex-[2-3]/ p[id]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); -+ // "hic-regex-1" does not match regex, should remain displayed. -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, "p#hic-regex-1"); -+ -+ // "hic-regex-2" and "hic-regex-2" do match regex, should be hidden. -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-regex-2"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "p#hic-regex-3"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsFrame() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains hidden span#frame-target", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, "span#frame-target"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsAndMatchesStyleStatic() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-contains-and-matches-style hicamss div[id] span.label /./ 'display: inline;'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-and-matches-style"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#static-usage-area > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#static-usage-area > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsAndMatchesStyleDynamic() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-contains-and-matches-style hicamsd div[id] span.label /./ 'display: inline;'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-and-matches-style"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#dynamic-target > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#dynamic-target > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsImage() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-contains-image /^89504e470d0a1a0a0000000d4948445200000064000000640802/ div[shouldhide] div", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-image"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsVisibleTextBasicUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-basic '#parent-basic > .article' '#parent-basic > .article .label'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-visible-text"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#parent-basic > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfContainsVisibleTextContentUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-content '#parent-content > .article' '#parent-content > .article .label'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-visible-text"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#parent-content > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfHasAndMatchesStyleBasicUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-has-and-matches-style a[href=\"#basic-target-ad\"] div[id] span.label /./ 'display: inline;'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-has-and-matches-style"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfHasAndMatchesStyleLegitElements() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-has-and-matches-style a[href=\"#comments-target-ad\"] div[id] span.label ';' /\\\\bdisplay:\\ inline\\;/", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-has-and-matches-style"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#comments-target > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfLabeledBy() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format( -+ "%s#$#hide-if-labelled-by 'Label' '#hilb-target [aria-labelledby]' '#hilb-target'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-labelled-by"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfMatchesXPathBasicStaticUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-matches-xpath //*[@id=\"isnfnv\"]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, -+ "div#basic-static-usage-area > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, -+ "div#basic-static-usage-area > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfMatchesXPathClassUsage() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#hide-if-matches-xpath //*[@class=\"to-be-hidden\"]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#class-usage-area > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#class-usage-area > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfMatchesXPathIdStartsWith() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#hide-if-matches-xpath //div[starts-with(@id,\"fail\")]", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath"); -+ TestVerificationUtils.verifyHiddenCount(mActivityTestRule, 1, -+ "div#hide-if-id-starts-with-area > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount(mActivityTestRule, 1, -+ "div#hide-if-id-starts-with-area > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfShadowContainsBasicUsage() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#hide-if-shadow-contains 'hisc-basic' p", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#basic-target > p[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testHideIfShadowContainsRegexUsage() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#hide-if-shadow-contains '/hisc-regex[1-2]/' div", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 2, "div#regex-target > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#regex-target > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testJsonPrune() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#json-prune 'data-expectedresult jsonprune aria-label'", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "json-prune?delay=100"); -+ // The object does not get hidden, it no longer exists in the DOM. -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#testcase-area > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testOverridePropertyRead() throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#override-property-read overridePropertyRead.fp false", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent(SNIPPETS_TESTPAGES_TESTCASES_ROOT + "override-property-read"); -+ TestVerificationUtils.verifyHiddenCount( -+ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='fail']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testStripFetchQueryParameterBasicUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter(String.format("%s#$#strip-fetch-query-parameter basicBlocked %s", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN, TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "strip-fetch-query-parameter"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 0, "div#basic-target > div[data-expectedresult='fail']"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 1, "div#basic-target > div[data-expectedresult='pass']"); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testStripFetchQueryParameterOtherUsage() -+ throws TimeoutException, InterruptedException { -+ mHelper.addCustomFilter( -+ String.format("%s#$#strip-fetch-query-parameter otherAllowed2 other-domain", -+ TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ mHelper.loadUrlWaitForContent( -+ SNIPPETS_TESTPAGES_TESTCASES_ROOT + "strip-fetch-query-parameter"); -+ TestVerificationUtils.verifyDisplayedCount( -+ mActivityTestRule, 2, "div#other-target > div[data-expectedresult='pass']"); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java -@@ -0,0 +1,201 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import org.junit.Assert; -+import org.junit.Rule; -+ -+import org.chromium.base.Log; -+import org.chromium.base.test.util.CallbackHelper; -+import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.WebContents; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+ -+import java.lang.Thread; -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.CountDownLatch; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+public class TestPagesTestsHelper { -+ public static final String TESTPAGES_DOMAIN = "abptestpages.org"; -+ public static final String TESTPAGES_BASE_URL = "https://" + TESTPAGES_DOMAIN; -+ public static final String TESTPAGES_TESTCASES_ROOT = TESTPAGES_BASE_URL + "/en/"; -+ public static final String FILTER_TESTPAGES_TESTCASES_ROOT = -+ TESTPAGES_TESTCASES_ROOT + "filters/"; -+ public static final String EXCEPTION_TESTPAGES_TESTCASES_ROOT = -+ TESTPAGES_TESTCASES_ROOT + "exceptions/"; -+ public static final String CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT = -+ TESTPAGES_TESTCASES_ROOT + "circumvention/"; -+ public static final String SITEKEY_TESTPAGES_TESTCASES_ROOT = -+ EXCEPTION_TESTPAGES_TESTCASES_ROOT + "sitekey"; -+ public static final String SNIPPETS_TESTPAGES_TESTCASES_ROOT = -+ TESTPAGES_TESTCASES_ROOT + "snippets/"; -+ public static final String TESTPAGES_RESOURCES_ROOT = TESTPAGES_BASE_URL + "/testfiles/"; -+ public static final String TESTPAGES_SUBSCRIPTION = -+ TESTPAGES_TESTCASES_ROOT + "/abp-testcase-subscription.txt"; -+ -+ private static final int TEST_TIMEOUT_SEC = 30; -+ -+ private URL mTestSubscriptionUrl; -+ private CallbackHelper mHelper = new CallbackHelper(); -+ private TestAdBlockedObserver mObserver = new TestAdBlockedObserver(); -+ private TestSubscriptionUpdatedObserver mSubscriptionUpdateObserver = -+ new TestSubscriptionUpdatedObserver(); -+ private ChromeTabbedActivityTestRule mActivityTestRule; -+ -+ private class TestSubscriptionUpdatedObserver -+ implements AdblockController.SubscriptionUpdateObserver { -+ @Override -+ public void onSubscriptionDownloaded(final URL url) { -+ if (mTestSubscriptionUrl == null) return; -+ if (url.toString().contains(mTestSubscriptionUrl.toString())) { -+ Log.d("TestSubscriptionUpdatedObserver", -+ "Notify subscription updated: " + url.toString()); -+ mHelper.notifyCalled(); -+ } -+ } -+ } -+ -+ public void setUp(final ChromeTabbedActivityTestRule activityRule) { -+ mActivityTestRule = activityRule; -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ AdblockController.getInstance().addOnAdBlockedObserver(mObserver); -+ AdblockController.getInstance().addSubscriptionUpdateObserver( -+ mSubscriptionUpdateObserver); -+ }); -+ } -+ -+ public void addFilterList(final String filterListUrl) { -+ try { -+ mTestSubscriptionUrl = new URL(filterListUrl); -+ mObserver.setExpectedSubscriptionUrl(mTestSubscriptionUrl); -+ } catch (MalformedURLException e) { -+ } -+ Assert.assertNotNull("Test subscription url", mTestSubscriptionUrl); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ AdblockController.getInstance().installSubscription(mTestSubscriptionUrl); -+ }); -+ try { -+ mHelper.waitForCallback(0, 1, TEST_TIMEOUT_SEC, TimeUnit.SECONDS); -+ } catch (TimeoutException e) { -+ Assert.assertEquals( -+ "Test subscription was properly added", "Failed to add test subscription"); -+ } -+ } -+ -+ public void addCustomFilter(final String filter) { -+ TestThreadUtils.runOnUiThreadBlocking( -+ () -> { AdblockController.getInstance().addCustomFilter(filter); }); -+ } -+ -+ public void tearDown() { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ AdblockController.getInstance().removeSubscriptionUpdateObserver( -+ mSubscriptionUpdateObserver); -+ AdblockController.getInstance().removeOnAdBlockedObserver(mObserver); -+ }); -+ } -+ -+ public WebContents getWebContents() { -+ return mActivityTestRule.getActivity().getCurrentWebContents(); -+ } -+ -+ public int getTabCount() { -+ return mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount(); -+ } -+ -+ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations -+ public void setOnAdMatchedLatch(final CountDownLatch countDownLatch) { -+ Assert.assertTrue( -+ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0); -+ mObserver.countDownLatch = countDownLatch; -+ } -+ -+ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations -+ public CountDownLatch setOnAdMatchedExpectations( -+ final Set onBlocked, final Set onAllowed) { -+ Assert.assertTrue( -+ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0); -+ mObserver.countDownLatch = new CountDownLatch(1); -+ mObserver.expectedBlocked = onBlocked; -+ mObserver.expectedAllowed = onAllowed; -+ return mObserver.countDownLatch; -+ } -+ -+ public boolean isBlocked(final String url) { -+ return mObserver.isBlocked(url); -+ } -+ -+ public boolean isPopupBlocked(final String url) { -+ return mObserver.isPopupBlocked(url); -+ } -+ -+ public int numBlockedByType(final AdblockContentType type) { -+ return mObserver.numBlockedByType(type); -+ } -+ -+ public int numBlockedPopups() { -+ return mObserver.numBlockedPopups(); -+ } -+ -+ public int numAllowedByType(final AdblockContentType type) { -+ return mObserver.numAllowedByType(type); -+ } -+ -+ public int numAllowedPopups() { -+ return mObserver.numAllowedPopups(); -+ } -+ -+ public boolean isAllowed(final String url) { -+ return mObserver.isAllowed(url); -+ } -+ -+ public boolean isPageAllowed(final String url) { -+ return mObserver.isPageAllowed(url); -+ } -+ -+ public boolean isPopupAllowed(final String url) { -+ return mObserver.isPopupAllowed(url); -+ } -+ -+ public void loadUrl(final String url) throws InterruptedException, TimeoutException { -+ mActivityTestRule.loadUrl(url, TEST_TIMEOUT_SEC); -+ } -+ -+ public void loadUrlWaitForContent(final String url) -+ throws InterruptedException, TimeoutException { -+ loadUrl(url); -+ TestVerificationUtils.verifyCondition(mActivityTestRule, -+ "document.getElementsByClassName('testcase-waiting-content').length == 0"); -+ } -+ -+ public int numBlocked() { -+ return mObserver.blockedInfos.size(); -+ } -+ -+ public int numAllowed() { -+ return mObserver.allowedInfos.size(); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java -@@ -0,0 +1,77 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import androidx.test.filters.LargeTest; -+ -+import org.junit.After; -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.test.ChromeBrowserTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+ -+import java.util.Arrays; -+import java.util.HashSet; -+import java.util.concurrent.CountDownLatch; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class TestPagesWebsocketTest { -+ @Rule -+ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); -+ @Rule -+ public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); -+ private TestPagesTestsHelper mHelper = new TestPagesTestsHelper(); -+ -+ @Before -+ public void setUp() { -+ mHelper.setUp(mActivityTestRule); -+ mHelper.addCustomFilter( -+ String.format("$websocket,domain=%s", TestPagesTestsHelper.TESTPAGES_DOMAIN)); -+ } -+ -+ @After -+ public void tearDown() { -+ mHelper.tearDown(); -+ } -+ -+ @Test -+ @LargeTest -+ @Feature({"adblock"}) -+ public void testVerifyWebsocketFilter() throws TimeoutException, InterruptedException { -+ final String wssUrl = -+ String.format("wss://%s/websocket", TestPagesTestsHelper.TESTPAGES_DOMAIN); -+ final CountDownLatch countDownLatch = -+ mHelper.setOnAdMatchedExpectations(new HashSet<>(Arrays.asList(wssUrl)), null); -+ mHelper.loadUrl(TestPagesTestsHelper.FILTER_TESTPAGES_TESTCASES_ROOT + "websocket"); -+ // Wait with 10 seconds max timeout -+ countDownLatch.await(10, TimeUnit.SECONDS); -+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET)); -+ Assert.assertTrue(mHelper.isBlocked(wssUrl)); -+ } -+} -diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java -new file mode 100644 ---- /dev/null -+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java -@@ -0,0 +1,158 @@ -+/* -+ * This file is part of eyeo Chromium SDK, -+ * Copyright (C) 2006-present eyeo GmbH -+ * -+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 3 as -+ * published by the Free Software Foundation. -+ * -+ * eyeo Chromium SDK is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with eyeo Chromium SDK. If not, see . -+ */ -+ -+package org.chromium.components.adblock; -+ -+import org.junit.Assert; -+ -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.content_public.browser.test.util.JavaScriptUtils; -+ -+import java.util.concurrent.TimeoutException; -+ -+public class TestVerificationUtils { -+ public enum IncludeSubframes { -+ YES, -+ NO, -+ } -+ -+ private static final String STATUS_OK = "\"OK\""; -+ -+ private static final String MATCHES_HIDDEN_FUNCTION = "let matches = function(element) {" -+ + " return window.getComputedStyle(element).display == \"none\";" -+ + "}"; -+ -+ private static final String MATCHES_DISPLAYED_FUNCTION = "let matches = function(element) {" -+ + " return window.getComputedStyle(element).display != \"none\";" -+ + "}"; -+ -+ private static final String COUNT_ELEMENT_FUNCTION = -+ "let countElements = function(selector, includeSubframes) {" -+ + " let count = 0;" -+ + " for (let element of document.querySelectorAll(selector)) {" -+ + " if (matches(element))" -+ + " ++count;" -+ + " }" -+ + " if (includeSubframes) {" -+ + " for (let frame of document.querySelectorAll(\"iframe\")) {" -+ + " for (let element of frame.contentWindow.document.body.querySelectorAll(selector)) {" -+ + " if (matches(element))" -+ + " ++count;" -+ + " }" -+ + " }" -+ + " }" -+ + " return count;" -+ + "}"; -+ -+ private static final String WAIT_FOR_COUNT_FUNCTION_WRAPPER = "(function () {" -+ + "%s\n" // matches() defintion placeholder -+ + "%s\n" // countElements() defintion placeholder -+ + "%s\n" // WAIT_FUNCTION placeholder which calls countElements() as a predicate -+ + "}());"; -+ -+ // Poll every 100 ms until condition is met or 10 seconds timeout occurs -+ private static final String WAIT_FUNCTION = "let repeat = 100;" -+ + "const id = setInterval(() => {" -+ + " --repeat;" -+ + " if (%s) {" // predicate placeholder -+ + " clearInterval(id);" -+ + " domAutomationController.send('OK');" -+ + " } else if (repeat == 0) {" -+ + " clearInterval(id);" -+ + " domAutomationController.send('Timeout');" -+ + " }" -+ + "}, 100);"; -+ -+ private static void verifyMatchesCount(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final int num, final String matchesFunction, final String selector, -+ IncludeSubframes includeSubframes) throws TimeoutException { -+ final String boolIncludeSubframes = -+ includeSubframes == IncludeSubframes.YES ? "true" : "false"; -+ final String predicate = String.format( -+ "countElements(\"%s\", %s) == %d", selector, boolIncludeSubframes, num); -+ final String waitFunction = String.format(WAIT_FUNCTION, predicate); -+ final String js = String.format(WAIT_FOR_COUNT_FUNCTION_WRAPPER, matchesFunction, -+ COUNT_ELEMENT_FUNCTION, waitFunction); -+ final String result = JavaScriptUtils.runJavascriptWithAsyncResult( -+ mActivityTestRule.getActivity().getActivityTab().getWebContents(), js); -+ Assert.assertEquals(STATUS_OK, result); -+ } -+ -+ public static void verifyHiddenCount(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final int num, final String selector) throws TimeoutException { -+ verifyHiddenCount(mActivityTestRule, num, selector, IncludeSubframes.YES); -+ } -+ -+ public static void verifyHiddenCount(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final int num, final String selector, final IncludeSubframes includeSubframes) -+ throws TimeoutException { -+ verifyMatchesCount( -+ mActivityTestRule, num, MATCHES_HIDDEN_FUNCTION, selector, includeSubframes); -+ } -+ -+ public static void verifyDisplayedCount(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final int num, final String selector) throws TimeoutException { -+ verifyDisplayedCount(mActivityTestRule, num, selector, IncludeSubframes.YES); -+ } -+ -+ public static void verifyDisplayedCount(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final int num, final String selector, final IncludeSubframes includeSubframes) -+ throws TimeoutException { -+ verifyMatchesCount( -+ mActivityTestRule, num, MATCHES_DISPLAYED_FUNCTION, selector, includeSubframes); -+ } -+ -+ public static void verifyCondition(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final String predicate) throws TimeoutException { -+ final String waitFunction = String.format(WAIT_FUNCTION, predicate); -+ Assert.assertEquals(STATUS_OK, -+ JavaScriptUtils.runJavascriptWithAsyncResult( -+ mActivityTestRule.getActivity().getActivityTab().getWebContents(), -+ waitFunction)); -+ } -+ -+ public static void verifyGreenBackground(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final String elemId) throws TimeoutException { -+ verifyCondition(mActivityTestRule, -+ "window.getComputedStyle(document.getElementById('" + elemId -+ + "')).backgroundColor == 'rgb(13, 199, 75)'"); -+ } -+ -+ // For some cases it is better to rely on page script testing element -+ // rather than invent a specific script to check condition. For example -+ // checks for rewrite filters replaces content proper way. -+ public static void verifySelfTestPass(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final String elemId) throws TimeoutException { -+ verifyCondition(mActivityTestRule, -+ "document.getElementById('" + elemId -+ + "').getAttribute('data-expectedresult') == 'pass'"); -+ } -+ -+ public static void expectResourceBlocked(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final String elemId) throws TimeoutException { -+ verifyCondition(mActivityTestRule, -+ "window.getComputedStyle(document.getElementById('" + elemId -+ + "')).display == 'none'"); -+ } -+ -+ public static void expectResourceShown(final ChromeTabbedActivityTestRule mActivityTestRule, -+ final String elemId) throws TimeoutException { -+ verifyCondition(mActivityTestRule, -+ "window.getComputedStyle(document.getElementById('" + elemId -+ + "')).display == 'inline'"); -+ } -+} diff --git a/components/adblock/content/BUILD.gn b/components/adblock/content/BUILD.gn new file mode 100644 --- /dev/null @@ -15865,7 +2203,7 @@ diff --git a/components/adblock/content/browser/BUILD.gn b/components/adblock/co new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/BUILD.gn -@@ -0,0 +1,123 @@ +@@ -0,0 +1,136 @@ +# +# This file is part of eyeo Chromium SDK, +# Copyright (C) 2006-present eyeo GmbH @@ -15899,7 +2237,11 @@ new file mode 100644 + "//components/adblock/content:*", + ] + sources = [ ++ "adblock_controller_factory_base.cc", ++ "adblock_controller_factory_base.h", + "adblock_filter_match.h", ++ "adblock_telemetry_service_factory_base.cc", ++ "adblock_telemetry_service_factory_base.h", + "adblock_url_loader_factory.cc", + "adblock_url_loader_factory.h", + "adblock_webcontents_observer.cc", @@ -15910,13 +2252,20 @@ new file mode 100644 + "element_hider.h", + "element_hider_impl.cc", + "element_hider_impl.h", ++ "element_hider_info.cc", ++ "element_hider_info.h", + "frame_hierarchy_builder.cc", + "frame_hierarchy_builder.h", ++ "frame_opener_info.cc", ++ "frame_opener_info.h", + "resource_classification_runner.h", + "resource_classification_runner_impl.cc", + "resource_classification_runner_impl.h", + "session_stats_impl.cc", + "session_stats_impl.h", ++ "subscription_service_factory_base.cc", ++ "subscription_service_factory_base.h", ++ + ] + + if (eyeo_intercept_debug_url) { @@ -15928,6 +2277,8 @@ new file mode 100644 + + deps = [ + "//base", ++ "//components/adblock/core/converter:converter", ++ "//components/keyed_service/content:content", + "//components/resources:components_resources_grit", + "//url:url", + ] @@ -15989,6 +2340,153 @@ new file mode 100644 + ":test_support", + ] +} +diff --git a/components/adblock/content/browser/adblock_controller_factory_base.cc b/components/adblock/content/browser/adblock_controller_factory_base.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/adblock_controller_factory_base.cc +@@ -0,0 +1,87 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/content/browser/adblock_controller_factory_base.h" ++ ++#include ++ ++#include "base/command_line.h" ++#include "components/adblock/core/adblock_controller_impl.h" ++#include "components/adblock/core/adblock_switches.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/configuration/persistent_filtering_configuration.h" ++#include "components/adblock/core/subscription/subscription_config.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/pref_registry/pref_registry_syncable.h" ++#include "components/version_info/version_info.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++AdblockControllerFactoryBase::~AdblockControllerFactoryBase() = default; ++ ++AdblockControllerFactoryBase::AdblockControllerFactoryBase() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockController", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++KeyedService* AdblockControllerFactoryBase::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ auto* prefs = GetPrefs(context); ++ auto adblock_filtering_configuration = ++ std::make_unique( ++ prefs, kAdblockFilteringConfigurationName); ++ ++ if (base::CommandLine::ForCurrentProcess()->HasSwitch( ++ adblock::switches::kDisableAcceptableAds)) { ++ adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); ++ } ++ if (base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kDisableAdblock) || ++ base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kDisableEyeoFiltering)) { ++ adblock_filtering_configuration->SetEnabled(false); ++ } ++ ++ auto* subscription_service = GetSubscriptionService(context); ++ auto controller = std::make_unique( ++ adblock_filtering_configuration.get(), subscription_service, GetLocale(), ++ config::GetKnownSubscriptions()); ++ controller->RunFirstRunLogic(prefs); ++ controller->MigrateLegacyPrefs(prefs); ++ ++ subscription_service->InstallFilteringConfiguration( ++ std::move(adblock_filtering_configuration)); ++ ++ return controller.release(); ++} ++ ++void AdblockControllerFactoryBase::RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) { ++ adblock::common::prefs::RegisterProfilePrefs(registry); ++} ++ ++bool AdblockControllerFactoryBase::ServiceIsNULLWhileTesting() const { ++ return true; ++} ++ ++bool AdblockControllerFactoryBase::ServiceIsCreatedWithBrowserContext() const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/components/adblock/content/browser/adblock_controller_factory_base.h b/components/adblock/content/browser/adblock_controller_factory_base.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/adblock_controller_factory_base.h +@@ -0,0 +1,50 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_CONTROLLER_FACTORY_BASE_H_ ++#define COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_CONTROLLER_FACTORY_BASE_H_ ++ ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SubscriptionService; ++class AdblockControllerFactoryBase : public BrowserContextKeyedServiceFactory { ++ protected: ++ virtual PrefService* GetPrefs(content::BrowserContext* context) const = 0; ++ virtual const std::string& GetLocale() const = 0; ++ virtual SubscriptionService* GetSubscriptionService( ++ content::BrowserContext* context) const = 0; ++ AdblockControllerFactoryBase(); ++ ~AdblockControllerFactoryBase() override; ++ ++ private: ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ void RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) override; ++ bool ServiceIsNULLWhileTesting() const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_CONTROLLER_FACTORY_BASE_H_ diff --git a/components/adblock/content/browser/adblock_filter_match.h b/components/adblock/content/browser/adblock_filter_match.h new file mode 100644 --- /dev/null @@ -16024,11 +2522,178 @@ new file mode 100644 +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_FILTER_MATCH_H_ +diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc +@@ -0,0 +1,100 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/content/browser/adblock_telemetry_service_factory_base.h" ++ ++#include ++ ++#include "components/adblock/core/activeping_telemetry_topic_provider.h" ++#include "components/adblock/core/adblock_telemetry_service.h" ++#include "components/adblock/core/common/adblock_utils.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "content/public/browser/browser_context.h" ++#include "content/public/browser/storage_partition.h" ++ ++namespace adblock { ++namespace { ++ ++std::optional g_check_interval_for_testing; ++std::optional g_initial_delay_for_testing; ++ ++base::TimeDelta GetInitialDelay() { ++ static base::TimeDelta kInitialDelay = ++ g_initial_delay_for_testing ? g_initial_delay_for_testing.value() ++ : base::Seconds(30); ++ return kInitialDelay; ++} ++ ++base::TimeDelta GetCheckInterval() { ++ static base::TimeDelta kCheckInterval = ++ g_check_interval_for_testing ? g_check_interval_for_testing.value() ++ : base::Minutes(5); ++ return kCheckInterval; ++} ++ ++} // namespace ++ ++AdblockTelemetryServiceFactoryBase::AdblockTelemetryServiceFactoryBase() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockTelemetryService", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++AdblockTelemetryServiceFactoryBase::~AdblockTelemetryServiceFactoryBase() = ++ default; ++ ++KeyedService* AdblockTelemetryServiceFactoryBase::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ // Need to use a URLLoaderFactory specific to the browser context, not from ++ // system_network_context_manager(), because the required Accept-Language ++ // header depends on user's language settings and is not present in requests ++ // made from the System network context. ++ scoped_refptr url_loader_factory = ++ context->GetDefaultStoragePartition() ++ ->GetURLLoaderFactoryForBrowserProcess(); ++ auto* prefs = GetPrefs(context); ++ auto service = std::make_unique( ++ GetSubscriptionService(context)->GetAdblockFilteringConfiguration(), ++ url_loader_factory, GetInitialDelay(), GetCheckInterval()); ++ service->AddTopicProvider(std::make_unique( ++ utils::GetAppInfo(), prefs, GetAdblockController(context), ++ ActivepingTelemetryTopicProvider::DefaultBaseUrl(), ++ ActivepingTelemetryTopicProvider::DefaultAuthToken())); ++ ++ if (url_loader_factory) { ++ service->Start(); ++ } ++ ++ return service.release(); ++} ++ ++bool AdblockTelemetryServiceFactoryBase::ServiceIsNULLWhileTesting() const { ++ return true; ++} ++ ++bool AdblockTelemetryServiceFactoryBase::ServiceIsCreatedWithBrowserContext() ++ const { ++ return true; ++} ++ ++void AdblockTelemetryServiceFactoryBase::SetCheckAndDelayIntervalsForTesting( ++ base::TimeDelta check_interval, ++ base::TimeDelta initial_delay) { ++ g_check_interval_for_testing = check_interval; ++ g_initial_delay_for_testing = initial_delay; ++} ++ ++} // namespace adblock +diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.h b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h +@@ -0,0 +1,57 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_TELEMETRY_SERVICE_FACTORY_BASE_H_ ++#define COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_TELEMETRY_SERVICE_FACTORY_BASE_H_ ++ ++#include "base/time/time.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "components/prefs/pref_service.h" ++ ++namespace adblock { ++ ++class AdblockController; ++class SubscriptionService; ++class AdblockTelemetryServiceFactoryBase ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ // Sets the initial delay and interval checks required for browser tests. ++ // Must be called before BuildServiceInstanceFor(). ++ void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval, ++ base::TimeDelta initial_delay); ++ ++ protected: ++ virtual PrefService* GetPrefs(content::BrowserContext* context) const = 0; ++ virtual AdblockController* GetAdblockController( ++ content::BrowserContext* context) const = 0; ++ virtual SubscriptionService* GetSubscriptionService( ++ content::BrowserContext* context) const = 0; ++ AdblockTelemetryServiceFactoryBase(); ++ ~AdblockTelemetryServiceFactoryBase() override; ++ ++ private: ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ bool ServiceIsNULLWhileTesting() const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_ADBLOCK_TELEMETRY_SERVICE_FACTORY_BASE_H_ diff --git a/components/adblock/content/browser/adblock_url_loader_factory.cc b/components/adblock/content/browser/adblock_url_loader_factory.cc new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/adblock_url_loader_factory.cc -@@ -0,0 +1,688 @@ +@@ -0,0 +1,746 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -16053,6 +2718,7 @@ new file mode 100644 +#include "base/supports_user_data.h" +#include "components/adblock/content/browser/content_security_policy_injector.h" +#include "components/adblock/content/browser/element_hider.h" ++#include "components/adblock/content/browser/frame_opener_info.h" +#include "components/adblock/content/browser/resource_classification_runner.h" +#include "components/adblock/core/features.h" +#include "components/adblock/core/sitekey_storage.h" @@ -16060,6 +2726,7 @@ new file mode 100644 +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" ++#include "content/public/browser/web_contents.h" +#include "net/base/url_util.h" +#include "net/http/http_status_code.h" +#include "net/http/http_util.h" @@ -16130,10 +2797,10 @@ new file mode 100644 + return ContentType::WebBundle; + case network::mojom::RequestDestination::kReport: + case network::mojom::RequestDestination::kAudioWorklet: ++ case network::mojom::RequestDestination::kDictionary: + case network::mojom::RequestDestination::kManifest: + case network::mojom::RequestDestination::kPaintWorklet: + case network::mojom::RequestDestination::kWebIdentity: -+ case network::mojom::RequestDestination::kDictionary: + return ContentType::Other; + } + NOTREACHED(); @@ -16379,11 +3046,39 @@ new file mode 100644 + + auto subscription_service = factory_->config_.subscription_service; + if (is_document_request_) { -+ factory_->config_.resource_classifier->CheckDocumentAllowlisted( -+ subscription_service->GetCurrentSnapshot(), request_url_, -+ factory_->host_id_); -+ PostFilterMatchCallbackToUI(std::move(callback), -+ FilterMatchResult::kNoRule); ++ auto* host = content::RenderFrameHost::FromID(factory_->host_id_); ++ auto* wc = content::WebContents::FromRenderFrameHost(host); ++ DCHECK(wc); ++ auto* info = FrameOpenerInfo::FromWebContents(wc); ++ // We could use WebContents::HasLiveOriginalOpenerChain() to recognize a ++ // popup here. The problem is that its companion method ++ // WebContents::GetFirstWebContentsInLiveOriginalOpenerChain() returns not a ++ // direct opener of a popup (which can be an embedded iframe) but the main ++ // frame of the page which opened popup which is not enough for correct ++ // allowlisting. Because of that we need to track an opener via ++ // content::WebContentsUserData (see ++ // AdblockWebContentObserver::DidOpenRequestedURL()), so for ++ // consistency we everywhere check content::WebContentsUserData to find out ++ // whether a request is a popup or to obtain its opener. ++ bool is_popup = info && content::RenderFrameHost::FromID(info->GetOpener()); ++ if (is_popup) { ++ factory_->config_.resource_classifier->CheckPopupFilterMatch( ++ subscription_service->GetCurrentSnapshot(), request_url_, ++ factory_->host_id_, ++ base::BindOnce( ++ &AdblockURLLoaderFactory::InProgressRequest:: ++ OnRequestUrlClassified, ++ weak_factory_.GetWeakPtr(), ++ base::BindOnce(&AdblockURLLoaderFactory::InProgressRequest:: ++ PostFilterMatchCallbackToUI, ++ weak_factory_.GetWeakPtr(), std::move(callback)))); ++ } else { ++ factory_->config_.resource_classifier->CheckDocumentAllowlisted( ++ subscription_service->GetCurrentSnapshot(), request_url_, ++ factory_->host_id_); ++ PostFilterMatchCallbackToUI(std::move(callback), ++ FilterMatchResult::kNoRule); ++ } + } else { + factory_->config_.resource_classifier->CheckRequestFilterMatch( + subscription_service->GetCurrentSnapshot(), request_url_, @@ -16440,10 +3135,19 @@ new file mode 100644 + FilterMatchResult result) { + if (result == FilterMatchResult::kBlockRule) { + if (factory_->CheckHostValid()) { -+ ElementHider* element_hider = factory_->config_.element_hider; -+ if (element_hider->IsElementTypeHideable(adblock_resource_type_)) { -+ element_hider->HideBlockedElement( -+ request_url_, content::RenderFrameHost::FromID(factory_->host_id_)); ++ if (is_document_request_) { ++ // This path means we classified popup ++ auto* wc = content::WebContents::FromRenderFrameHost( ++ content::RenderFrameHost::FromID(factory_->host_id_)); ++ DCHECK(wc); ++ wc->ClosePage(); ++ } else { ++ ElementHider* element_hider = factory_->config_.element_hider; ++ if (element_hider->IsElementTypeHideable(adblock_resource_type_)) { ++ element_hider->HideBlockedElement( ++ request_url_, ++ content::RenderFrameHost::FromID(factory_->host_id_)); ++ } + } + } + } @@ -16509,7 +3213,19 @@ new file mode 100644 +void AdblockURLLoaderFactory::InProgressRequest::OnReceiveRedirect( + const net::RedirectInfo& redirect_info, + network::mojom::URLResponseHeadPtr head) { ++ VLOG(1) ++ << "[eyeo] AdblockURLLoaderFactory::InProgressRequest::OnReceiveRedirect " ++ "from " ++ << request_url_ << " to " << redirect_info.new_url; + request_url_ = redirect_info.new_url; ++ if (net::IsLocalhost(request_url_) || (!request_url_.SchemeIsHTTPOrHTTPS() && ++ !request_url_.SchemeIsWSOrWSS())) { ++ VLOG(1) ++ << "[eyeo] Ignoring URL (local url or unsupported scheme), allowing " ++ "load."; ++ target_client_->OnReceiveRedirect(redirect_info, std::move(head)); ++ return; ++ } + CheckFilterMatch(base::BindOnce( + &InProgressRequest::OnRedirectFilterMatchResult, + weak_factory_.GetWeakPtr(), redirect_info, std::move(head))); @@ -16526,6 +3242,13 @@ new file mode 100644 + return; + } + if (result == FilterMatchResult::kBlockRule) { ++ if (is_document_request_ && factory_->CheckHostValid()) { ++ // This path means we classified popup ++ auto* wc = content::WebContents::FromRenderFrameHost( ++ content::RenderFrameHost::FromID(factory_->host_id_)); ++ DCHECK(wc); ++ wc->ClosePage(); ++ } + OnRequestError(net::ERR_BLOCKED_BY_ADMINISTRATOR); + return; + } @@ -17270,7 +3993,7 @@ diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/adblock_webcontents_observer.cc -@@ -0,0 +1,122 @@ +@@ -0,0 +1,187 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -17291,12 +4014,46 @@ new file mode 100644 +#include "components/adblock/content/browser/adblock_webcontents_observer.h" + +#include "base/trace_event/trace_event.h" ++#include "components/adblock/content/browser/frame_opener_info.h" +#include "components/adblock/core/common/sitekey.h" +#include "components/adblock/core/subscription/subscription_service.h" +#include "content/public/browser/navigation_handle.h" +#include "net/base/url_util.h" +#include "third_party/blink/public/common/frame/frame_owner_element_type.h" + ++namespace { ++const char* WindowOpenDispositionToString(WindowOpenDisposition value) { ++ switch (value) { ++ case WindowOpenDisposition::UNKNOWN: ++ return "UNKNOWN"; ++ case WindowOpenDisposition::CURRENT_TAB: ++ return "CURRENT_TAB"; ++ case WindowOpenDisposition::SINGLETON_TAB: ++ return "SINGLETON_TAB"; ++ case WindowOpenDisposition::NEW_FOREGROUND_TAB: ++ return "NEW_FOREGROUND_TAB"; ++ case WindowOpenDisposition::NEW_BACKGROUND_TAB: ++ return "NEW_BACKGROUND_TAB"; ++ case WindowOpenDisposition::NEW_POPUP: ++ return "NEW_POPUP"; ++ case WindowOpenDisposition::NEW_WINDOW: ++ return "NEW_WINDOW"; ++ case WindowOpenDisposition::SAVE_TO_DISK: ++ return "SAVE_TO_DISK"; ++ case WindowOpenDisposition::OFF_THE_RECORD: ++ return "OFF_THE_RECORD"; ++ case WindowOpenDisposition::IGNORE_ACTION: ++ return "IGNORE_ACTION"; ++ case WindowOpenDisposition::SWITCH_TO_TAB: ++ return "SWITCH_TO_TAB"; ++ case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: ++ return "NEW_PICTURE_IN_PICTURE"; ++ default: ++ return ""; ++ } ++} ++} // namespace ++ +void TraceHandleLoadComplete( + content::RenderFrameHost* frame_host, + const adblock::ElementHider::ElemhideInjectionData&) { @@ -17320,11 +4077,36 @@ new file mode 100644 + +AdblockWebContentObserver::~AdblockWebContentObserver() = default; + ++void AdblockWebContentObserver::DidOpenRequestedURL( ++ content::WebContents* new_contents, ++ content::RenderFrameHost* source_render_frame_host, ++ const GURL& url, ++ const content::Referrer& referrer, ++ WindowOpenDisposition disposition, ++ ui::PageTransition transition, ++ bool started_from_context_menu, ++ bool renderer_initiated) { ++ if (!IsAdblockEnabled()) { ++ return; ++ } ++ VLOG(1) << "[eyeo] DidOpenRequestedURL: URL=" << url ++ << ", disposition=" << WindowOpenDispositionToString(disposition) ++ << ", renderer_initiated=" << renderer_initiated; ++ if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || ++ disposition == WindowOpenDisposition::NEW_POPUP) { ++ // WindowOpenDisposition::NEW_WINDOW is excluded as it is set when user ++ // opens a link in a new window from context menu. ++ // We use content::WebContentsUserData instead of content::DocumentUserData ++ // because the latter is reset when there is a client side redirection. ++ adblock::FrameOpenerInfo::CreateForWebContents(new_contents); ++ auto* info = adblock::FrameOpenerInfo::FromWebContents(new_contents); ++ info->SetOpener(source_render_frame_host->GetGlobalId()); ++ } ++} ++ +void AdblockWebContentObserver::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { -+ if (base::ranges::none_of( -+ subscription_service_->GetInstalledFilteringConfigurations(), -+ &adblock::FilteringConfiguration::IsEnabled)) { ++ if (!IsAdblockEnabled()) { + return; + } + const GURL& url = navigation_handle->GetURL(); @@ -17392,12 +4174,18 @@ new file mode 100644 + base::BindOnce(&TraceHandleLoadComplete, frame_host)); +} + ++bool AdblockWebContentObserver::IsAdblockEnabled() const { ++ return base::ranges::any_of( ++ subscription_service_->GetInstalledFilteringConfigurations(), ++ &adblock::FilteringConfiguration::IsEnabled); ++} ++ +WEB_CONTENTS_USER_DATA_KEY_IMPL(AdblockWebContentObserver); diff --git a/components/adblock/content/browser/adblock_webcontents_observer.h b/components/adblock/content/browser/adblock_webcontents_observer.h new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/adblock_webcontents_observer.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,85 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -17459,9 +4247,19 @@ new file mode 100644 + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + ++ void DidOpenRequestedURL(content::WebContents* new_contents, ++ content::RenderFrameHost* source_render_frame_host, ++ const GURL& url, ++ const content::Referrer& referrer, ++ WindowOpenDisposition disposition, ++ ui::PageTransition transition, ++ bool started_from_context_menu, ++ bool renderer_initiated) override; ++ + private: + explicit AdblockWebContentObserver(content::WebContents* web_contents); + void HandleOnLoad(content::RenderFrameHost* render_frame_host); ++ bool IsAdblockEnabled() const; + + friend class content::WebContentsUserData; + WEB_CONTENTS_USER_DATA_KEY_DECL(); @@ -17819,7 +4617,7 @@ diff --git a/components/adblock/content/browser/element_hider_impl.cc b/componen new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/element_hider_impl.cc -@@ -0,0 +1,303 @@ +@@ -0,0 +1,305 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -17849,6 +4647,7 @@ new file mode 100644 +#include "base/strings/utf_string_conversions.h" +#include "base/task/thread_pool.h" +#include "base/trace_event/trace_event.h" ++#include "components/adblock/content/browser/element_hider_info.h" +#include "components/adblock/core/subscription/subscription_service.h" +#include "components/grit/components_resources.h" +#include "content/public/browser/browser_thread.h" @@ -18014,6 +4813,14 @@ new file mode 100644 + std::move(on_finished).Run(std::move(input)); + return; + } ++ auto* info = ElementHiderInfo::GetOrCreateForCurrentDocument(frame_host); ++ if (info->IsElementHidingDone()) { ++ std::move(on_finished).Run(ElementHider::ElemhideInjectionData{}); ++ return; ++ } else { ++ info->SetElementHidingDone(); ++ } ++ + if (!input.stylesheet.empty()) { + frame_host->InsertAbpElemhideStylesheet(input.stylesheet); + DVLOG(1) << "[eyeo] Element hiding - inserted stylesheet in frame" @@ -18026,7 +4833,7 @@ new file mode 100644 + content::RenderFrameHost::JavaScriptResultCallback(), + content::ISOLATED_WORLD_ID_ADBLOCK); + -+ DVLOG(1) << "[eyeo] Element hiding emulation - called JS in frame" ++ DVLOG(1) << "[eyeo] Element hiding emulation - executed JS in frame" + << " '" << frame_host->GetFrameName() << "'"; + } + @@ -18039,7 +4846,7 @@ new file mode 100644 + content::RenderFrameHost::JavaScriptResultCallback(), + content::ISOLATED_WORLD_ID_ADBLOCK); + -+ DVLOG(1) << "[eyeo] Snippet - called JS in frame" ++ DVLOG(1) << "[eyeo] Snippet - executed JS in frame" + << " '" << frame_host->GetFrameName() << "'"; + } + @@ -18059,10 +4866,19 @@ new file mode 100644 + content::RenderFrameHost* render_frame_host, + SiteKey sitekey, + base::OnceCallback on_finished) { -+ ApplyElementHidingEmulationInternal( -+ std::move(url), std::move(frame_hierarchy), -+ render_frame_host->GetGlobalId(), std::move(sitekey), -+ std::move(on_finished)); ++ auto* info = ElementHiderInfo::GetForCurrentDocument(render_frame_host); ++ if (info && info->IsElementHidingDone()) { ++ std::move(on_finished).Run(ElementHider::ElemhideInjectionData{}); ++ return; ++ } ++ base::ThreadPool::PostTaskAndReplyWithResult( ++ FROM_HERE, {}, ++ base::BindOnce(&PrepareElemhideEmulationData, ++ subscription_service_->GetCurrentSnapshot(), ++ std::move(url), std::move(frame_hierarchy), ++ std::move(sitekey)), ++ base::BindOnce(&InsertUserCSSAndApplyElemHidingEmuJS, ++ render_frame_host->GetGlobalId(), std::move(on_finished))); +} + +bool ElementHiderImpl::IsElementTypeHideable( @@ -18102,24 +4918,8 @@ new file mode 100644 + content::RenderFrameHost::JavaScriptResultCallback(), + content::ISOLATED_WORLD_ID_ADBLOCK); + -+ VLOG(1) << "[eyeo] Element hiding - called JS: " << js; -+} -+ -+void ElementHiderImpl::ApplyElementHidingEmulationInternal( -+ GURL url, -+ std::vector frame_hierarchy, -+ content::GlobalRenderFrameHostId frame_host_id, -+ SiteKey sitekey, -+ base::OnceCallback -+ on_finished) { -+ base::ThreadPool::PostTaskAndReplyWithResult( -+ FROM_HERE, {}, -+ base::BindOnce(&PrepareElemhideEmulationData, -+ subscription_service_->GetCurrentSnapshot(), -+ std::move(url), std::move(frame_hierarchy), -+ std::move(sitekey)), -+ base::BindOnce(&InsertUserCSSAndApplyElemHidingEmuJS, frame_host_id, -+ std::move(on_finished))); ++ DVLOG(1) << "[eyeo] Element hiding - executed JS in frame" ++ << " '" << render_frame_host->GetFrameName() << "'"; +} + +} // namespace adblock @@ -18127,7 +4927,7 @@ diff --git a/components/adblock/content/browser/element_hider_impl.h b/component new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/element_hider_impl.h -@@ -0,0 +1,62 @@ +@@ -0,0 +1,55 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -18176,13 +4976,6 @@ new file mode 100644 + content::RenderFrameHost* render_frame_host) final; + + private: -+ void ApplyElementHidingEmulationInternal( -+ GURL url, -+ std::vector frame_hierarchy, -+ content::GlobalRenderFrameHostId frame_host_id, -+ SiteKey sitekey, -+ base::OnceCallback -+ on_finished); + raw_ptr subscription_service_; + base::WeakPtrFactory weak_ptr_factory_{this}; +}; @@ -18190,11 +4983,102 @@ new file mode 100644 +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_ELEMENT_HIDER_IMPL_H_ +diff --git a/components/adblock/content/browser/element_hider_info.cc b/components/adblock/content/browser/element_hider_info.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/element_hider_info.cc +@@ -0,0 +1,37 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/content/browser/element_hider_info.h" ++ ++namespace adblock { ++ ++DOCUMENT_USER_DATA_KEY_IMPL(ElementHiderInfo); ++ ++ElementHiderInfo::ElementHiderInfo(content::RenderFrameHost* rfh) ++ : content::DocumentUserData(rfh) {} ++ ++ElementHiderInfo::~ElementHiderInfo() = default; ++ ++bool ElementHiderInfo::IsElementHidingDone() const { ++ return element_hining_done_; ++} ++ ++void ElementHiderInfo::SetElementHidingDone() { ++ element_hining_done_ = true; ++} ++ ++} // namespace adblock +diff --git a/components/adblock/content/browser/element_hider_info.h b/components/adblock/content/browser/element_hider_info.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/element_hider_info.h +@@ -0,0 +1,44 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CONTENT_BROWSER_ELEMENT_HIDER_INFO_H_ ++#define COMPONENTS_ADBLOCK_CONTENT_BROWSER_ELEMENT_HIDER_INFO_H_ ++ ++#include "content/public/browser/document_user_data.h" ++ ++namespace adblock { ++ ++class ElementHiderInfo final ++ : public content::DocumentUserData { ++ public: ++ ~ElementHiderInfo() final; ++ ++ bool IsElementHidingDone() const; ++ void SetElementHidingDone(); ++ ++ private: ++ explicit ElementHiderInfo(content::RenderFrameHost* rfh); ++ ++ bool element_hining_done_ = false; ++ ++ friend DocumentUserData; ++ DOCUMENT_USER_DATA_KEY_DECL(); ++}; ++ ++} // namespace adblock ++ ++#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_ELEMENT_HIDER_INFO_H_ diff --git a/components/adblock/content/browser/frame_hierarchy_builder.cc b/components/adblock/content/browser/frame_hierarchy_builder.cc new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/frame_hierarchy_builder.cc -@@ -0,0 +1,89 @@ +@@ -0,0 +1,117 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -18218,6 +5102,7 @@ new file mode 100644 +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" ++#include "content/public/common/url_constants.h" +#include "services/network/public/mojom/network_context.mojom-forward.h" +#include "url/gurl.h" + @@ -18225,8 +5110,35 @@ new file mode 100644 + +namespace { + ++// Do not use GURL::IsAboutBlank for frame hierarchy, it returns true for valid ++// src like `about:blank?eyeo=true` ++bool IsExactlyAboutBlank(const GURL url) { ++ static const base::StringPiece kAboutBlankUrl = "about:blank"; ++ return url == kAboutBlankUrl; ++} ++ +bool IsValidForFrameHierarchy(const GURL& url) { -+ return !url.is_empty() && !url.IsAboutBlank(); ++ return !url.is_empty() && !IsExactlyAboutBlank(url) && ++ url != content::kBlockedURL; ++} ++ ++// Basically calling `GetAsReferrer()` on url strips elements that are not ++// supposed to be sent as HTTP referrer: username, password and ref fragment, ++// and this is what we want for frame hierarchy urls. ++// But for urls like `about:blank?eyeo=true` calling `GetAsReferrer()` returns ++// an empty url which excludes it from frame hierarchy, so for `about:blank...` ++// we fallback to `GetLastCommittedURL()`. ++GURL GetUrlAsReferrer(const content::RenderFrameHost* frame_host) { ++ auto last_commited_referrer = ++ frame_host->GetLastCommittedURL().GetAsReferrer(); ++ if (last_commited_referrer.is_empty()) { ++ auto last_commited_url = frame_host->GetLastCommittedURL(); ++ if (last_commited_url.IsAboutBlank() && ++ IsValidForFrameHierarchy(last_commited_url)) { ++ last_commited_referrer = last_commited_url; ++ } ++ } ++ return last_commited_referrer; +} + +} // namespace @@ -18249,8 +5161,7 @@ new file mode 100644 + + std::vector referrers_chain; + for (auto* iter = host; iter; iter = iter->GetParent()) { -+ auto last_commited_referrer = iter->GetLastCommittedURL().GetAsReferrer(); -+ ++ auto last_commited_referrer = GetUrlAsReferrer(iter); + if (IsValidForFrameHierarchy(last_commited_referrer)) { + VLOG(2) << "[eyeo] FrameHierarchy item: " + << last_commited_referrer.spec(); @@ -18266,17 +5177,18 @@ new file mode 100644 + content::WebContents* web_contents) const { + GURL url = frame_host->GetLastCommittedURL(); + // Anonymous frames have "about:blank" source so we use a parent frame URL -+ if (url.IsAboutBlank()) { ++ // Do not use GURL::IsExactlyAboutBlank (DPD-1946). ++ if (IsExactlyAboutBlank(url)) { + for (auto* parent = frame_host->GetParent(); parent; + parent = parent->GetParent()) { + GURL parent_url = parent->GetLastCommittedURL(); -+ if (!parent_url.spec().empty() && !parent_url.IsAboutBlank()) { ++ if (!parent_url.spec().empty() && !IsExactlyAboutBlank(parent_url)) { + url = parent_url; + break; + } + } + // If we still cannot find parent url let's use top level navigation url -+ if (url.IsAboutBlank()) { ++ if (IsExactlyAboutBlank(url)) { + url = web_contents->GetLastCommittedURL(); + } + } @@ -18352,11 +5264,104 @@ new file mode 100644 +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_FRAME_HIERARCHY_BUILDER_H_ +diff --git a/components/adblock/content/browser/frame_opener_info.cc b/components/adblock/content/browser/frame_opener_info.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/frame_opener_info.cc +@@ -0,0 +1,37 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/content/browser/frame_opener_info.h" ++ ++namespace adblock { ++ ++WEB_CONTENTS_USER_DATA_KEY_IMPL(FrameOpenerInfo); ++ ++FrameOpenerInfo::FrameOpenerInfo(content::WebContents* contents) ++ : content::WebContentsUserData(*contents) {} ++ ++FrameOpenerInfo::~FrameOpenerInfo() = default; ++ ++content::GlobalRenderFrameHostId FrameOpenerInfo::GetOpener() const { ++ return render_frame_host_id_; ++} ++void FrameOpenerInfo::SetOpener( ++ content::GlobalRenderFrameHostId render_frame_host_id) { ++ render_frame_host_id_ = render_frame_host_id; ++} ++ ++} // namespace adblock +diff --git a/components/adblock/content/browser/frame_opener_info.h b/components/adblock/content/browser/frame_opener_info.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/frame_opener_info.h +@@ -0,0 +1,46 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CONTENT_BROWSER_FRAME_OPENER_INFO_H_ ++#define COMPONENTS_ADBLOCK_CONTENT_BROWSER_FRAME_OPENER_INFO_H_ ++ ++#include "content/public/browser/global_routing_id.h" ++#include "content/public/browser/web_contents_user_data.h" ++ ++namespace adblock { ++ ++class FrameOpenerInfo final ++ : public content::WebContentsUserData { ++ public: ++ ~FrameOpenerInfo() final; ++ ++ content::GlobalRenderFrameHostId GetOpener() const; ++ void SetOpener(content::GlobalRenderFrameHostId render_frame_host_id); ++ ++ private: ++ explicit FrameOpenerInfo(content::WebContents* contents); ++ ++ content::GlobalRenderFrameHostId render_frame_host_id_ = ++ content::GlobalRenderFrameHostId{MSG_ROUTING_NONE, MSG_ROUTING_NONE}; ++ ++ friend WebContentsUserData; ++ WEB_CONTENTS_USER_DATA_KEY_DECL(); ++}; ++ ++} // namespace adblock ++ ++#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_FRAME_OPENER_INFO_H_ diff --git a/components/adblock/content/browser/resource_classification_runner.h b/components/adblock/content/browser/resource_classification_runner.h new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/resource_classification_runner.h -@@ -0,0 +1,105 @@ +@@ -0,0 +1,113 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -18411,15 +5416,18 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) = 0; ++ const GURL& subscription, ++ const std::string& configuration_name) = 0; + virtual void OnPageAllowed(const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) = 0; ++ const GURL& subscription, ++ const std::string& configuration_name) = 0; + virtual void OnPopupMatched(const GURL& url, + FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) = 0; ++ const GURL& subscription, ++ const std::string& configuration_name) = 0; + }; + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; @@ -18429,6 +5437,11 @@ new file mode 100644 + const SubscriptionService::Snapshot& subscription_collections, + const GURL& popup_url, + content::RenderFrameHost* render_frame_host) = 0; ++ virtual void CheckPopupFilterMatch( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& popup_url, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback) = 0; + virtual void CheckRequestFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, @@ -18466,7 +5479,7 @@ diff --git a/components/adblock/content/browser/resource_classification_runner_i new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/resource_classification_runner_impl.cc -@@ -0,0 +1,429 @@ +@@ -0,0 +1,451 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -18490,10 +5503,12 @@ new file mode 100644 +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "base/trace_event/trace_event.h" ++#include "components/adblock/content/browser/frame_opener_info.h" +#include "components/adblock/core/common/adblock_utils.h" +#include "components/adblock/core/common/sitekey.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" ++#include "content/public/browser/web_contents.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace adblock { @@ -18501,59 +5516,6 @@ new file mode 100644 +using ClassificationDecision = + ResourceClassifier::ClassificationResult::Decision; + -+namespace { -+ -+absl::optional HasRewriteHelper( -+ const SubscriptionService::Snapshot subscription_collections, -+ const GURL& request_url, -+ const std::vector& frame_hierarchy) { -+ absl::optional rewrite_url = absl::nullopt; -+ for (const auto& collection : subscription_collections) { -+ rewrite_url = collection->GetRewriteUrl(request_url, frame_hierarchy); -+ if (rewrite_url) { -+ break; -+ } -+ } -+ return rewrite_url; -+} -+ -+absl::optional CheckDocumentAllowlistedHelper( -+ const SubscriptionService::Snapshot subscription_collections, -+ const GURL& request_url) { -+ absl::optional subscription_url = absl::nullopt; -+ // We check if page is allowlisted in every configuration but on success -+ // return any matching subscription from any configuration -+ for (const auto& collection : subscription_collections) { -+ subscription_url = collection->FindBySpecialFilter( -+ SpecialFilterType::Document, request_url, std::vector(), -+ SiteKey()); -+ if (!subscription_url) { -+ return absl::nullopt; -+ } -+ } -+ return subscription_url; -+} -+ -+} // namespace -+ -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult:: -+ CheckResourceFilterMatchResult(FilterMatchResult status, -+ const GURL& subscription) -+ : status(status), subscription(subscription) {} -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult:: -+ ~CheckResourceFilterMatchResult() = default; -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult:: -+ CheckResourceFilterMatchResult(const CheckResourceFilterMatchResult&) = -+ default; -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult& -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult::operator=( -+ const CheckResourceFilterMatchResult&) = default; -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult:: -+ CheckResourceFilterMatchResult(CheckResourceFilterMatchResult&&) = default; -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult& -+ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult::operator=( -+ CheckResourceFilterMatchResult&&) = default; -+ +ResourceClassificationRunnerImpl::ResourceClassificationRunnerImpl( + scoped_refptr resource_classifier, + std::unique_ptr frame_hierarchy_builder, @@ -18575,11 +5537,50 @@ new file mode 100644 + observers_.RemoveObserver(observer); +} + ++void ResourceClassificationRunnerImpl::OnCheckPopupFilterMatchComplete( ++ const GURL& popup_url, ++ const std::vector& frame_hierarchy, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ absl::optional callback, ++ const ResourceClassifier::ClassificationResult& classification_result) { ++ if (classification_result.decision != ClassificationDecision::Ignored) { ++ FilterMatchResult result = ++ classification_result.decision == ClassificationDecision::Allowed ++ ? FilterMatchResult::kAllowRule ++ : FilterMatchResult::kBlockRule; ++ if (callback) { ++ std::move(*callback).Run(result); ++ } ++ auto* frame_host = content::RenderFrameHost::FromID(render_frame_host_id); ++ if (frame_host) { ++ const auto& opener_url = ++ frame_hierarchy.empty() ? GURL() : frame_hierarchy.front(); ++ if (result == FilterMatchResult::kBlockRule) { ++ VLOG(1) << "[eyeo] Prevented loading of pop-up " << popup_url.spec() ++ << ", opener: " << opener_url.spec(); ++ } else { ++ VLOG(1) << "[eyeo] Pop-up allowed " << popup_url.spec() ++ << ", opener: " << opener_url.spec(); ++ } ++ for (auto& observer : observers_) { ++ observer.OnPopupMatched( ++ popup_url, result, opener_url, frame_host, ++ classification_result.decisive_subscription, ++ classification_result.decisive_configuration_name); ++ } ++ } ++ } else if (callback) { ++ std::move(*callback).Run(FilterMatchResult::kNoRule); ++ } ++} ++ ++ +FilterMatchResult ResourceClassificationRunnerImpl::ShouldBlockPopup( + const SubscriptionService::Snapshot& subscription_collections, + const GURL& popup_url, + content::RenderFrameHost* frame_host) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DVLOG(1) << "[eyeo] ShouldBlockPopup for " << popup_url.spec(); + DCHECK(frame_host); + TRACE_EVENT1("eyeo", "ResourceClassificationRunnerImpl::ShouldBlockPopup", + "popup_url", popup_url.spec()); @@ -18594,22 +5595,57 @@ new file mode 100644 + if (classification_result.decision == ClassificationDecision::Ignored) { + return FilterMatchResult::kNoRule; + } -+ const FilterMatchResult result = -+ classification_result.decision == ClassificationDecision::Allowed -+ ? FilterMatchResult::kAllowRule -+ : FilterMatchResult::kBlockRule; -+ if (result == FilterMatchResult::kBlockRule) { -+ VLOG(1) << "[eyeo] Prevented loading of pop-up " << popup_url.spec(); -+ } else { -+ VLOG(1) << "[eyeo] Pop-up allowed " << popup_url.spec(); ++ OnCheckPopupFilterMatchComplete(popup_url, frame_hierarchy, ++ frame_host->GetGlobalId(), absl::nullopt, ++ classification_result); ++ return classification_result.decision == ClassificationDecision::Allowed ++ ? FilterMatchResult::kAllowRule ++ : FilterMatchResult::kBlockRule; ++} ++ ++void ResourceClassificationRunnerImpl::CheckPopupFilterMatch( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& popup_url, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DVLOG(1) << "[eyeo] CheckPopupFilterMatch for " << popup_url.spec(); ++ auto* frame_host = content::RenderFrameHost::FromID(render_frame_host_id); ++ if (!frame_host) { ++ // Host has died, likely because this is a deferred execution. It does not ++ // matter anymore whether the resource is blocked, the page is gone. ++ VLOG(1) << "[eyeo] CheckPopupFilterMatch for " << popup_url.spec() ++ << " no frame host!"; ++ std::move(callback).Run(FilterMatchResult::kNoRule); ++ return; + } -+ const auto& opener_url = -+ frame_hierarchy.empty() ? GURL() : frame_hierarchy.front(); -+ for (auto& observer : observers_) { -+ observer.OnPopupMatched(popup_url, result, opener_url, frame_host, -+ classification_result.decisive_subscription); ++ ++ auto* wc = content::WebContents::FromRenderFrameHost(frame_host); ++ DCHECK(wc); ++ auto* info = FrameOpenerInfo::FromWebContents(wc); ++ DCHECK(info); ++ auto* frame_host_opener = content::RenderFrameHost::FromID(info->GetOpener()); ++ if (!frame_host_opener) { ++ // We are unable to check allowlisting ++ VLOG(1) << "[eyeo] CheckPopupFilterMatch for " << popup_url.spec() ++ << " no frame host for opener!"; ++ std::move(callback).Run(FilterMatchResult::kNoRule); ++ return; + } -+ return result; ++ ++ const auto frame_hierarchy = ++ frame_hierarchy_builder_->BuildFrameHierarchy(frame_host_opener); ++ auto sitekey = sitekey_storage_->FindSiteKeyForAnyUrl(frame_hierarchy); ++ ++ base::ThreadPool::PostTaskAndReplyWithResult( ++ FROM_HERE, {}, ++ base::BindOnce(&ResourceClassifier::ClassifyPopup, resource_classifier_, ++ std::move(subscription_collections), popup_url, ++ frame_hierarchy, sitekey ? sitekey->second : SiteKey()), ++ base::BindOnce( ++ &ResourceClassificationRunnerImpl::OnCheckPopupFilterMatchComplete, ++ weak_ptr_factory_.GetWeakPtr(), popup_url, frame_hierarchy, ++ render_frame_host_id, std::move(callback))); +} + +void ResourceClassificationRunnerImpl::CheckRequestFilterMatchForWebSocket( @@ -18619,9 +5655,9 @@ new file mode 100644 + CheckFilterMatchCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(request_url.SchemeIsWSOrWSS()); -+ CheckRequestFilterMatchImpl(std::move(subscription_collections), request_url, -+ ContentType::Websocket, render_frame_host_id, -+ std::move(callback)); ++ CheckRequestFilterMatch(std::move(subscription_collections), request_url, ++ ContentType::Websocket, render_frame_host_id, ++ std::move(callback)); +} + +void ResourceClassificationRunnerImpl::CheckDocumentAllowlisted( @@ -18632,7 +5668,7 @@ new file mode 100644 + DVLOG(1) << "[eyeo] Main document. Passing it through: " << request_url; + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {}, -+ base::BindOnce(&CheckDocumentAllowlistedHelper, ++ base::BindOnce(&CheckDocumentAllowlistedInternal, + std::move(subscription_collections), request_url), + base::BindOnce( + &ResourceClassificationRunnerImpl::ProcessDocumentAllowlistedResponse, @@ -18642,14 +5678,15 @@ new file mode 100644 +void ResourceClassificationRunnerImpl::ProcessDocumentAllowlistedResponse( + const GURL request_url, + content::GlobalRenderFrameHostId render_frame_host_id, -+ absl::optional allowing_subscription) { ++ CheckResourceFilterMatchResult result) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::RenderFrameHost* host = + content::RenderFrameHost::FromID(render_frame_host_id); -+ if (allowing_subscription && host) { ++ if (result.status == FilterMatchResult::kAllowRule && host) { + VLOG(1) << "[eyeo] Calling OnPageAllowed() for " << request_url; + for (auto& observer : observers_) { -+ observer.OnPageAllowed(request_url, host, allowing_subscription.value()); ++ observer.OnPageAllowed(request_url, host, result.subscription, ++ result.configuration_name); + } + } +} @@ -18658,36 +5695,6 @@ new file mode 100644 + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, + ContentType adblock_resource_type, -+ content::GlobalRenderFrameHostId render_frame_host_id, -+ CheckFilterMatchCallback callback) { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ DCHECK(!request_url.SchemeIsWSOrWSS()) -+ << "Use CheckRequestFilterMatchForWebSocket()"; -+ -+ content::RenderFrameHost* host = -+ frame_hierarchy_builder_->FindRenderFrameHost(render_frame_host_id); -+ if (!host) { -+ // We're unable to verify if the resource is allowed or blocked without a -+ // frame hierarchy, so err on the side of safety and allow the load. -+ // This happens for Ping-type requests, for reasons unknown. -+ VLOG(1) << "[eyeo] Unable to build frame hierarchy for " << request_url -+ << " \t: process id " << render_frame_host_id.child_id -+ << ", render frame id " << render_frame_host_id.frame_routing_id -+ << ", adblock_resource_type " << adblock_resource_type -+ << ": Allowing load"; -+ std::move(callback).Run(FilterMatchResult::kNoRule); -+ return; -+ } -+ -+ CheckRequestFilterMatchImpl(std::move(subscription_collections), request_url, -+ adblock_resource_type, host->GetGlobalId(), -+ std::move(callback)); -+} -+ -+void ResourceClassificationRunnerImpl::CheckRequestFilterMatchImpl( -+ SubscriptionService::Snapshot subscription_collections, -+ const GURL& request_url, -+ ContentType adblock_resource_type, + content::GlobalRenderFrameHostId frame_host_id, + CheckFilterMatchCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -18751,19 +5758,21 @@ new file mode 100644 + + if (classification_result.decision == ClassificationDecision::Allowed) { + VLOG(1) << "[eyeo] Document allowed due to allowing filter " << request_url; -+ return CheckResourceFilterMatchResult( ++ return CheckResourceFilterMatchResult{ + FilterMatchResult::kAllowRule, -+ {classification_result.decisive_subscription}); ++ classification_result.decisive_subscription, ++ classification_result.decisive_configuration_name}; + } + + if (classification_result.decision == ClassificationDecision::Blocked) { + VLOG(1) << "[eyeo] Document blocked " << request_url; -+ return CheckResourceFilterMatchResult( ++ return CheckResourceFilterMatchResult{ + FilterMatchResult::kBlockRule, -+ {classification_result.decisive_subscription}); ++ classification_result.decisive_subscription, ++ classification_result.decisive_configuration_name}; + } + -+ return CheckResourceFilterMatchResult(FilterMatchResult::kNoRule, {}); ++ return CheckResourceFilterMatchResult{FilterMatchResult::kNoRule, {}, {}}; +} + +void ResourceClassificationRunnerImpl::OnCheckResourceFilterMatchComplete( @@ -18785,7 +5794,7 @@ new file mode 100644 + result.status == FilterMatchResult::kBlockRule) { + NotifyAdMatched(request_url, result.status, frame_hierarchy, + adblock_resource_type, render_frame_host, -+ result.subscription); ++ result.subscription, result.configuration_name); + } + } +} @@ -18796,17 +5805,40 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) { ++ const GURL& subscription, ++ const std::string& configuration_name) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + VLOG(1) << "[eyeo] NotifyAdMatched() called for " << url; + + for (auto& observer : observers_) { + observer.OnAdMatched(url, result, parent_frame_urls, + static_cast(content_type), -+ render_frame_host, {subscription}); ++ render_frame_host, subscription, configuration_name); + } +} + ++// static ++ResourceClassificationRunnerImpl::CheckResourceFilterMatchResult ++ResourceClassificationRunnerImpl::CheckDocumentAllowlistedInternal( ++ const SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url) { ++ CheckResourceFilterMatchResult result{FilterMatchResult::kNoRule, {}, {}}; ++ // It is required for all configurations to have an allowing Document filter ++ // to consider a page allowlisted. ++ for (const auto& collection : subscription_collections) { ++ auto subscription_url = collection->FindBySpecialFilter( ++ SpecialFilterType::Document, request_url, std::vector(), ++ SiteKey()); ++ if (!subscription_url) { ++ return {FilterMatchResult::kNoRule, {}, {}}; ++ } else { ++ result = {FilterMatchResult::kAllowRule, subscription_url.value(), ++ collection->GetFilteringConfigurationName()}; ++ } ++ } ++ return result; ++} ++ +void ResourceClassificationRunnerImpl::CheckResponseFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& response_url, @@ -18856,19 +5888,21 @@ new file mode 100644 + if (classification_result.decision == ClassificationDecision::Allowed) { + VLOG(1) << "[eyeo] Document allowed due to allowing filter " + << response_url; -+ return CheckResourceFilterMatchResult( ++ return CheckResourceFilterMatchResult{ + FilterMatchResult::kAllowRule, -+ {classification_result.decisive_subscription}); ++ classification_result.decisive_subscription, ++ classification_result.decisive_configuration_name}; + } + + if (classification_result.decision == ClassificationDecision::Blocked) { + VLOG(1) << "[eyeo] Document blocked " << response_url; -+ return CheckResourceFilterMatchResult( ++ return CheckResourceFilterMatchResult{ + FilterMatchResult::kBlockRule, -+ {classification_result.decisive_subscription}); ++ classification_result.decisive_subscription, ++ classification_result.decisive_configuration_name}; + } + -+ return CheckResourceFilterMatchResult(FilterMatchResult::kNoRule, {}); ++ return CheckResourceFilterMatchResult{FilterMatchResult::kNoRule, {}, {}}; +} + +void ResourceClassificationRunnerImpl::CheckRewriteFilterMatch( @@ -18890,8 +5924,9 @@ new file mode 100644 + frame_hierarchy_builder_->BuildFrameHierarchy(host); + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {}, -+ base::BindOnce(&HasRewriteHelper, std::move(subscription_collections), -+ request_url, frame_hierarchy), ++ base::BindOnce(&ResourceClassifier::CheckRewrite, resource_classifier_, ++ std::move(subscription_collections), request_url, ++ frame_hierarchy), + std::move(callback)); +} + @@ -18900,7 +5935,7 @@ diff --git a/components/adblock/content/browser/resource_classification_runner_i new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/resource_classification_runner_impl.h -@@ -0,0 +1,154 @@ +@@ -0,0 +1,156 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -18950,6 +5985,11 @@ new file mode 100644 + const SubscriptionService::Snapshot& subscription_collections, + const GURL& popup_url, + content::RenderFrameHost* render_frame_host) final; ++ void CheckPopupFilterMatch( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& popup_url, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback) final; + void CheckRequestFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, @@ -18980,25 +6020,10 @@ new file mode 100644 + base::OnceCallback&)> result) final; + + private: -+ void CheckRequestFilterMatchImpl( -+ SubscriptionService::Snapshot subscription_collections, -+ const GURL& request_url, -+ ContentType adblock_type, -+ content::GlobalRenderFrameHostId frame_host_id, -+ CheckFilterMatchCallback cb); -+ + struct CheckResourceFilterMatchResult { -+ CheckResourceFilterMatchResult(FilterMatchResult status, -+ const GURL& subscription); -+ ~CheckResourceFilterMatchResult(); -+ CheckResourceFilterMatchResult(const CheckResourceFilterMatchResult&); -+ CheckResourceFilterMatchResult& operator=( -+ const CheckResourceFilterMatchResult&); -+ CheckResourceFilterMatchResult(CheckResourceFilterMatchResult&&); -+ CheckResourceFilterMatchResult& operator=(CheckResourceFilterMatchResult&&); -+ + FilterMatchResult status; + GURL subscription; ++ std::string configuration_name; + }; + + static CheckResourceFilterMatchResult CheckRequestFilterMatchInternal( @@ -19017,6 +6042,13 @@ new file mode 100644 + CheckFilterMatchCallback callback, + const CheckResourceFilterMatchResult result); + ++ void OnCheckPopupFilterMatchComplete( ++ const GURL& popup_url, ++ const std::vector& frame_hierarchy, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ absl::optional callback, ++ const ResourceClassifier::ClassificationResult& result); ++ + static CheckResourceFilterMatchResult CheckResponseFilterMatchInternal( + const scoped_refptr resource_classifier, + SubscriptionService::Snapshot subscription_collections, @@ -19030,7 +6062,8 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription); ++ const GURL& subscription, ++ const std::string& configuration_name); + + void PostFilterMatchCallbackToUI(CheckFilterMatchCallback callback, + FilterMatchResult result); @@ -19039,10 +6072,14 @@ new file mode 100644 + base::OnceCallback&)> callback, + absl::optional url); + ++ static CheckResourceFilterMatchResult CheckDocumentAllowlistedInternal( ++ const SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url); ++ + void ProcessDocumentAllowlistedResponse( + const GURL request_url, + content::GlobalRenderFrameHostId render_frame_host_id, -+ absl::optional allowing_subscription); ++ CheckResourceFilterMatchResult result); + + SEQUENCE_CHECKER(sequence_checker_); + scoped_refptr resource_classifier_; @@ -19059,7 +6096,7 @@ diff --git a/components/adblock/content/browser/session_stats_impl.cc b/componen new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/session_stats_impl.cc -@@ -0,0 +1,83 @@ +@@ -0,0 +1,86 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -19110,14 +6147,16 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) { ++ const GURL& subscription, ++ const std::string& configuration_name) { + OnMatchedInternal(match_result, subscription); +} + +void SessionStatsImpl::OnPageAllowed( + const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) { ++ const GURL& subscription, ++ const std::string& configuration_name) { + OnMatchedInternal(FilterMatchResult::kAllowRule, subscription); +} + @@ -19126,7 +6165,8 @@ new file mode 100644 + FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) { ++ const GURL& subscription, ++ const std::string& configuration_name) { + OnMatchedInternal(match_result, subscription); +} + @@ -19147,7 +6187,7 @@ diff --git a/components/adblock/content/browser/session_stats_impl.h b/component new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/session_stats_impl.h -@@ -0,0 +1,68 @@ +@@ -0,0 +1,71 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -19193,15 +6233,18 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) final; ++ const GURL& subscription, ++ const std::string& configuration_name) final; + void OnPageAllowed(const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) final; ++ const GURL& subscription, ++ const std::string& configuration_name) final; + void OnPopupMatched(const GURL& url, + FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) final; ++ const GURL& subscription, ++ const std::string& configuration_name) final; + + private: + void OnMatchedInternal(FilterMatchResult match_result, @@ -19216,11 +6259,306 @@ new file mode 100644 +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_SESSION_STATS_IMPL_H_ +diff --git a/components/adblock/content/browser/subscription_service_factory_base.cc b/components/adblock/content/browser/subscription_service_factory_base.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/subscription_service_factory_base.cc +@@ -0,0 +1,225 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/content/browser/subscription_service_factory_base.h" ++ ++#include ++#include ++#include ++ ++#include "base/command_line.h" ++#include "base/files/file_util.h" ++#include "base/functional/bind.h" ++#include "base/task/thread_pool.h" ++#include "base/trace_event/trace_event.h" ++#include "components/adblock/core/adblock_switches.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/adblock/core/configuration/persistent_filtering_configuration.h" ++#include "components/adblock/core/converter/flatbuffer_converter.h" ++#include "components/adblock/core/subscription/filtering_configuration_maintainer_impl.h" ++#include "components/adblock/core/subscription/installed_subscription_impl.h" ++#include "components/adblock/core/subscription/ongoing_subscription_request_impl.h" ++#include "components/adblock/core/subscription/preloaded_subscription_provider_impl.h" ++#include "components/adblock/core/subscription/subscription_config.h" ++#include "components/adblock/core/subscription/subscription_downloader_impl.h" ++#include "components/adblock/core/subscription/subscription_persistent_storage_impl.h" ++#include "components/adblock/core/subscription/subscription_service_impl.h" ++#include "components/adblock/core/subscription/subscription_updater.h" ++#include "components/adblock/core/subscription/subscription_updater_impl.h" ++#include "components/adblock/core/subscription/subscription_validator_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "components/pref_registry/pref_registry_syncable.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_context.h" ++#include "content/public/browser/storage_partition.h" ++ ++namespace adblock { ++namespace { ++ ++std::optional g_update_check_interval_for_testing; ++std::optional g_update_initial_delay_for_testing; ++ ++base::TimeDelta GetUpdateInitialDelay() { ++ static base::TimeDelta kInitialDelay = ++ g_update_initial_delay_for_testing ++ ? g_update_initial_delay_for_testing.value() ++ : base::Seconds(30); ++ return kInitialDelay; ++} ++ ++base::TimeDelta GetUpdateCheckInterval() { ++ static base::TimeDelta kCheckInterval = ++ g_update_check_interval_for_testing ++ ? g_update_check_interval_for_testing.value() ++ : base::Hours(1); ++ return kCheckInterval; ++} ++ ++constexpr net::BackoffEntry::Policy kRetryBackoffPolicy = { ++ 0, // Number of initial errors to ignore. ++ 5000, // Initial delay in ms. ++ 2.0, // Factor by which the waiting time will be multiplied. ++ 0.2, // Fuzzing percentage. ++ 60 * 60 * 1000, // Maximum delay in ms. ++ -1, // Never discard the entry. ++ false, // Use initial delay. ++}; ++ ++std::unique_ptr MakeOngoingSubscriptionRequest( ++ scoped_refptr url_loader_factory) { ++ return std::make_unique(&kRetryBackoffPolicy, ++ url_loader_factory); ++} ++ ++ConversionResult ConvertFilterFile(const GURL& subscription_url, ++ const base::FilePath& path) { ++ TRACE_EVENT1("eyeo", "ConvertFileToFlatbuffer", "url", ++ subscription_url.spec()); ++ ConversionResult result; ++ std::ifstream input_stream(path.AsUTF8Unsafe()); ++ if (!input_stream.is_open() || !input_stream.good()) { ++ result = ConversionError("Could not open filter file"); ++ } else { ++ result = FlatbufferConverter::Convert( ++ input_stream, subscription_url, ++ config::AllowPrivilegedFilters(subscription_url)); ++ } ++ base::DeleteFile(path); ++ return result; ++} ++ ++std::unique_ptr MakeSubscriptionUpdater() { ++ return std::make_unique(GetUpdateInitialDelay(), ++ GetUpdateCheckInterval()); ++} ++ ++std::unique_ptr ++MakeFilterConfigurationMaintainer( ++ content::BrowserContext* context, ++ PrefService* prefs, ++ SubscriptionPersistentMetadata* persistent_metadata, ++ const ConversionExecutors* conversion_executors, ++ FilteringConfiguration* configuration, ++ FilteringConfigurationMaintainerImpl::SubscriptionUpdatedCallback ++ observer) { ++ auto main_thread_task_runner = base::SequencedTaskRunner::GetCurrentDefault(); ++ scoped_refptr url_loader_factory = ++ context->GetDefaultStoragePartition() ++ ->GetURLLoaderFactoryForBrowserProcess(); ++ ++ const std::string storage_dir = configuration->GetName() + "_subscriptions"; ++ ++ auto storage = std::make_unique( ++ context->GetPath().AppendASCII(storage_dir), ++ std::make_unique(prefs, ++ CurrentSchemaVersion()), ++ persistent_metadata); ++ ++ auto downloader = std::make_unique( ++ utils::GetAppInfo(), ++ base::BindRepeating(&MakeOngoingSubscriptionRequest, url_loader_factory), ++ const_cast(conversion_executors), ++ persistent_metadata); ++ ++ auto maintainer = std::make_unique( ++ configuration, std::move(storage), std::move(downloader), ++ std::make_unique(), ++ MakeSubscriptionUpdater(), ++ const_cast(conversion_executors), ++ persistent_metadata, observer); ++ maintainer->InitializeStorage(); ++ return maintainer; ++} ++ ++void CleanupPersistedConfiguration(PrefService* prefs, ++ FilteringConfiguration* configuration) { ++ PersistentFilteringConfiguration::RemovePersistedData( ++ prefs, configuration->GetName()); ++} ++ ++} // namespace ++ ++SubscriptionServiceFactoryBase::SubscriptionServiceFactoryBase() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockSubscriptionService", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++SubscriptionServiceFactoryBase::~SubscriptionServiceFactoryBase() = default; ++ ++KeyedService* SubscriptionServiceFactoryBase::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ auto* prefs = GetPrefs(context); ++ auto* subscription_service = new SubscriptionServiceImpl( ++ base::BindRepeating(&MakeFilterConfigurationMaintainer, context, ++ GetPrefs(context), ++ GetSubscriptionPersistentMetadata(context), ++ static_cast(this)), ++ base::BindRepeating(&CleanupPersistedConfiguration, prefs)); ++ auto persisted_configs = ++ PersistentFilteringConfiguration::GetPersistedConfigurations(prefs); ++ bool start_disabled = base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kDisableEyeoFiltering); ++ for (auto& persisted_configuration : persisted_configs) { ++ if (persisted_configuration->GetName() == ++ kAdblockFilteringConfigurationName) { ++ // "adblock" configuration is taken care by ++ // AdblockController(Factory) ++ continue; ++ } ++ if (start_disabled) { ++ persisted_configuration->SetEnabled(false); ++ } ++ subscription_service->InstallFilteringConfiguration( ++ std::move(persisted_configuration)); ++ } ++ return subscription_service; ++} ++ ++scoped_refptr ++SubscriptionServiceFactoryBase::ConvertCustomFilters( ++ const std::vector& filters) const { ++ auto raw_data = ++ FlatbufferConverter::Convert(filters, CustomFiltersUrl(), true); ++ return base::MakeRefCounted( ++ std::move(raw_data), Subscription::InstallationState::Installed, ++ base::Time()); ++} ++ ++void SubscriptionServiceFactoryBase::ConvertFilterListFile( ++ const GURL& subscription_url, ++ const base::FilePath& path, ++ base::OnceCallback result_callback) const { ++ base::ThreadPool::PostTaskAndReplyWithResult( ++ FROM_HERE, {base::MayBlock()}, ++ base::BindOnce(&ConvertFilterFile, subscription_url, path), ++ std::move(result_callback)); ++} ++ ++void SubscriptionServiceFactoryBase::RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) { ++ adblock::PersistentFilteringConfiguration::RegisterProfilePrefs(registry); ++} ++ ++// static ++void SubscriptionServiceFactoryBase::SetUpdateCheckAndDelayIntervalsForTesting( ++ base::TimeDelta check_interval, ++ base::TimeDelta initial_delay) { ++ g_update_check_interval_for_testing = check_interval; ++ g_update_initial_delay_for_testing = initial_delay; ++} ++ ++} // namespace adblock +diff --git a/components/adblock/content/browser/subscription_service_factory_base.h b/components/adblock/content/browser/subscription_service_factory_base.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/content/browser/subscription_service_factory_base.h +@@ -0,0 +1,60 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CONTENT_BROWSER_SUBSCRIPTION_SERVICE_FACTORY_BASE_H_ ++#define COMPONENTS_ADBLOCK_CONTENT_BROWSER_SUBSCRIPTION_SERVICE_FACTORY_BASE_H_ ++ ++#include "components/adblock/core/subscription/conversion_executors.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SubscriptionPersistentMetadata; ++class SubscriptionServiceFactoryBase : public BrowserContextKeyedServiceFactory, ++ public ConversionExecutors { ++ public: ++ static void SetUpdateCheckAndDelayIntervalsForTesting( ++ base::TimeDelta check_interval, ++ base::TimeDelta initial_delay); ++ ++ // ConversionExecutors: ++ scoped_refptr ConvertCustomFilters( ++ const std::vector& filters) const override; ++ void ConvertFilterListFile( ++ const GURL& subscription_url, ++ const base::FilePath& path, ++ base::OnceCallback) const override; ++ ++ protected: ++ virtual PrefService* GetPrefs(content::BrowserContext* context) const = 0; ++ virtual SubscriptionPersistentMetadata* GetSubscriptionPersistentMetadata( ++ content::BrowserContext* context) const = 0; ++ SubscriptionServiceFactoryBase(); ++ ~SubscriptionServiceFactoryBase() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ void RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) override; ++}; ++ ++} // namespace adblock ++ ++#endif // COMPONENTS_ADBLOCK_CONTENT_BROWSER_SUBSCRIPTION_SERVICE_FACTORY_BASE_H_ diff --git a/components/adblock/content/browser/test/adblock_url_loader_factory_test.cc b/components/adblock/content/browser/test/adblock_url_loader_factory_test.cc new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/test/adblock_url_loader_factory_test.cc -@@ -0,0 +1,349 @@ +@@ -0,0 +1,399 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -19244,6 +6582,7 @@ new file mode 100644 +#include "base/functional/callback_helpers.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" ++#include "components/adblock/content/browser/frame_opener_info.h" +#include "components/adblock/content/browser/test/mock_adblock_content_security_policy_injector.h" +#include "components/adblock/content/browser/test/mock_element_hider.h" +#include "components/adblock/content/browser/test/mock_resource_classification_runner.h" @@ -19251,7 +6590,8 @@ new file mode 100644 +#include "components/adblock/core/subscription/test/mock_subscription_collection.h" +#include "components/adblock/core/subscription/test/mock_subscription_service.h" +#include "components/adblock/core/test/mock_sitekey_storage.h" -+#include "content/public/test/browser_task_environment.h" ++#include "content/public/browser/web_contents.h" ++#include "content/public/test/test_renderer_host.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "services/network/public/cpp/simple_url_loader.h" @@ -19298,7 +6638,7 @@ new file mode 100644 + network::mojom::RequestDestination::kFrame; +}; + -+class AdblockURLLoaderFactoryTest : public testing::Test { ++class AdblockURLLoaderFactoryTest : public content::RenderViewHostTestHarness { + public: + AdblockURLLoaderFactoryTest() : test_factory_receiver_(&test_factory_) {} + @@ -19323,7 +6663,8 @@ new file mode 100644 + adblock::AdblockURLLoaderFactoryConfig{ + &subscription_service_, &resource_classifier_, &element_hider_, + &sitekey_storage_, &csp_injector_}, -+ content::GlobalRenderFrameHostId{}, std::move(factory_request), ++ web_contents()->GetPrimaryMainFrame()->GetGlobalId(), ++ std::move(factory_request), + test_factory_receiver_.BindNewPipeAndPassRemote(), kTestUserAgent, + base::BindOnce(&AdblockURLLoaderFactoryTest::OnDisconnect, + base::Unretained(this))); @@ -19378,6 +6719,24 @@ new file mode 100644 + }); + } + ++ void InitializePopupFlow() { ++ flow.destination = network::mojom::RequestDestination::kDocument; ++ adblock::FrameOpenerInfo::CreateForWebContents(web_contents()); ++ auto* info = adblock::FrameOpenerInfo::FromWebContents(web_contents()); ++ info->SetOpener(main_rfh()->GetGlobalId()); ++ ExpectCheckRewrite(); ++ EXPECT_CALL(resource_classifier_, ++ CheckDocumentAllowlisted(testing::_, flow.url, testing::_)) ++ .Times(0); ++ EXPECT_CALL( ++ resource_classifier_, ++ CheckPopupFilterMatch(testing::_, flow.url, testing::_, testing::_)) ++ .WillOnce([&](auto, const GURL&, content::GlobalRenderFrameHostId, ++ adblock::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(flow.request_match); ++ }); ++ } ++ + void ExpectRequestAllowed(HostState state = HostState::Alive) { + EXPECT_CALL(resource_classifier_, + CheckResponseFilterMatch(testing::_, flow.url, testing::_, @@ -19390,6 +6749,18 @@ new file mode 100644 + }); + } + ++ void ExpectPopupAllowed(HostState state = HostState::Alive) { ++ EXPECT_CALL(resource_classifier_, ++ CheckResponseFilterMatch(testing::_, flow.url, testing::_, ++ testing::_, testing::_, testing::_)) ++ .WillOnce([&, state](auto, const GURL&, adblock::ContentType, ++ content::GlobalRenderFrameHostId, const auto&, ++ adblock::CheckFilterMatchCallback cb) { ++ adblock_factory_->ApplyState(state); ++ std::move(cb).Run(flow.response_match); ++ }); ++ } ++ + void ExpectRequestBlockedOrNotHeppened() { + // if request was not processed or blocked, response processing should not + // take place. @@ -19439,7 +6810,6 @@ new file mode 100644 + .Times(0); + } + -+ content::BrowserTaskEnvironment task_environment_; + std::unique_ptr loader_; + std::unique_ptr adblock_factory_; + network::TestURLLoaderFactory test_factory_; @@ -19521,6 +6891,24 @@ new file mode 100644 + EXPECT_EQ(net::OK, loader_->NetError()); +} + ++TEST_F(AdblockURLLoaderFactoryTest, PopupNavigation) { ++ InitializePopupFlow(); ++ ExpectRequestAllowed(); ++ ExpectResponseAllowed(); ++ ExpectElemhideSkipped(); ++ StartRequest(); ++ EXPECT_EQ(net::OK, loader_->NetError()); ++} ++ ++TEST_F(AdblockURLLoaderFactoryTest, FrameDiesWhilePopupNavigation) { ++ InitializePopupFlow(); ++ ExpectRequestAllowed(HostState::Dead); ++ ExpectResponseBlockedOrNotHappened(); ++ ExpectElemhideSkipped(); ++ StartRequest(); ++ EXPECT_EQ(net::OK, loader_->NetError()); ++} ++ +TEST_F(AdblockURLLoaderFactoryTest, FrameDiesWhileRewriteCheck) { + ExpectCheckRewrite(HostState::Dead); + EXPECT_CALL(resource_classifier_, @@ -19920,7 +7308,7 @@ diff --git a/components/adblock/content/browser/test/element_hider_impl_test.cc new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/test/element_hider_impl_test.cc -@@ -0,0 +1,347 @@ +@@ -0,0 +1,390 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -20267,6 +7655,49 @@ new file mode 100644 + })); +} + ++TEST_F(AdblockElementHiderImplTest, SecondInjectionSkipped) { ++ std::vector selectors{"a", "b"}; ++ std::vector emu_selectors; ++ ++ EXPECT_CALL(sub_service_, GetCurrentSnapshot()) ++ .WillRepeatedly([this, selectors, emu_selectors]() { ++ auto collection = std::make_unique(); ++ EXPECT_CALL(*collection, ++ FindBySpecialFilter(SpecialFilterType::Document, kUrl, ++ kFrameHierarchy, kSitekey)) ++ .WillOnce(testing::Return(absl::nullopt)); ++ EXPECT_CALL(*collection, ++ FindBySpecialFilter(SpecialFilterType::Elemhide, kUrl, ++ kFrameHierarchy, kSitekey)) ++ .WillOnce(testing::Return(absl::nullopt)); ++ EXPECT_CALL(*collection, ++ GetElementHideSelectors(kUrl, kFrameHierarchy, kSitekey)) ++ .WillOnce(testing::Return(selectors)); ++ EXPECT_CALL(*collection, GetElementHideEmulationSelectors(kUrl)) ++ .WillOnce(testing::Return(emu_selectors)); ++ SubscriptionService::Snapshot snapshot; ++ snapshot.push_back(std::move(collection)); ++ return snapshot; ++ }); ++ ++ ElementHiderImpl element_hide(&sub_service_); ++ element_hide.ApplyElementHidingEmulationOnPage( ++ kUrl, kFrameHierarchy, main_rfh(), kSitekey, ++ base::BindLambdaForTesting( ++ [&](const ElementHider::ElemhideInjectionData& data) { ++ EXPECT_EQ(data.stylesheet, "a, b {display: none !important;}\n"); ++ })); ++ task_environment()->RunUntilIdle(); ++ ++ element_hide.ApplyElementHidingEmulationOnPage( ++ kUrl, kFrameHierarchy, main_rfh(), kSitekey, ++ base::BindLambdaForTesting( ++ [&](const ElementHider::ElemhideInjectionData& data) { ++ EXPECT_EQ(data.stylesheet, ""); ++ })); ++ task_environment()->RunUntilIdle(); ++} ++ +} // namespace adblock diff --git a/components/adblock/content/browser/test/frame_hierarchy_builder_test.cc b/components/adblock/content/browser/test/frame_hierarchy_builder_test.cc new file mode 100644 @@ -20734,7 +8165,7 @@ new file mode 100644 + const GURL& subscription) { + for (auto& observer : observers_) { + observer.OnAdMatched(url, result, parent_frame_urls, content_type, -+ render_frame_host, subscription); ++ render_frame_host, subscription, ""); + } +} + @@ -20743,7 +8174,7 @@ diff --git a/components/adblock/content/browser/test/mock_resource_classificatio new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/test/mock_resource_classification_runner.h -@@ -0,0 +1,96 @@ +@@ -0,0 +1,104 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -20785,7 +8216,7 @@ new file mode 100644 + content::RenderFrameHost* render_frame_host, + const GURL& subscription); + -+ MOCK_METHOD((FilterMatchResult), ++ MOCK_METHOD(FilterMatchResult, + ShouldBlockPopup, + (const SubscriptionService::Snapshot&, + const GURL&, @@ -20793,6 +8224,14 @@ new file mode 100644 + (override)); + + MOCK_METHOD(void, ++ CheckPopupFilterMatch, ++ (SubscriptionService::Snapshot, ++ const GURL&, ++ content::GlobalRenderFrameHostId, ++ CheckFilterMatchCallback), ++ (override)); ++ ++ MOCK_METHOD(void, + CheckRequestFilterMatch, + (const SubscriptionService::Snapshot, + const GURL&, @@ -20844,7 +8283,7 @@ diff --git a/components/adblock/content/browser/test/resource_classification_run new file mode 100644 --- /dev/null +++ b/components/adblock/content/browser/test/resource_classification_runner_impl_test.cc -@@ -0,0 +1,387 @@ +@@ -0,0 +1,453 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -20871,6 +8310,7 @@ new file mode 100644 +#include "base/functional/callback_forward.h" +#include "base/test/bind.h" +#include "base/test/mock_callback.h" ++#include "components/adblock/content/browser/frame_opener_info.h" +#include "components/adblock/content/browser/test/mock_frame_hierarchy_builder.h" +#include "components/adblock/core/classifier/test/mock_resource_classifier.h" +#include "components/adblock/core/common/sitekey.h" @@ -20899,13 +8339,15 @@ new file mode 100644 + const std::vector& parent_frame_urls, + ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription), ++ const GURL& subscription, ++ const std::string& configuration_name), + (override)); + MOCK_METHOD(void, + OnPageAllowed, + (const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription), ++ const GURL& subscription, ++ const std::string& configuration_name), + (override)); + MOCK_METHOD(void, + OnPopupMatched, @@ -20913,7 +8355,8 @@ new file mode 100644 + FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription), ++ const GURL& subscription, ++ const std::string& configuration_name), + (override)); +}; + @@ -20946,9 +8389,6 @@ new file mode 100644 + } + + void FrameHierarchyWillBeBuilt() { -+ EXPECT_CALL(*mock_frame_hierarchy_builder_, -+ FindRenderFrameHost(main_rfh()->GetGlobalId())) -+ .WillOnce(testing::Return(main_rfh())); + EXPECT_CALL(*mock_frame_hierarchy_builder_, BuildFrameHierarchy(main_rfh())) + .WillOnce(Return(kFrameHierarchy)); + } @@ -20960,7 +8400,14 @@ new file mode 100644 + *mock_resource_classifier_, + ClassifyRequest(_, url, kFrameHierarchy, content_type, kSitekey)) + .WillOnce(testing::Return(ResourceClassifier::ClassificationResult{ -+ decision, kSubscriptionUrl})); ++ decision, kSubscriptionUrl, kConfigurationName})); ++ } ++ ++ void ClassifierReturnsPopupClassification(GURL popup_url, Decision decision) { ++ EXPECT_CALL(*mock_resource_classifier_, ++ ClassifyPopup(_, popup_url, _, kSitekey)) ++ .WillOnce(testing::Return(ResourceClassifier::ClassificationResult{ ++ decision, kSubscriptionUrl, kConfigurationName})); + } + + void ClassifierReturnsResponseClassification( @@ -20970,7 +8417,7 @@ new file mode 100644 + EXPECT_CALL(*mock_resource_classifier_, + ClassifyResponse(_, url, kFrameHierarchy, _, headers)) + .WillOnce(testing::Return(ResourceClassifier::ClassificationResult{ -+ decision, kSubscriptionUrl})); ++ decision, kSubscriptionUrl, kConfigurationName})); + } + + void AdMatchedWillBeNotified(GURL url, @@ -20978,7 +8425,14 @@ new file mode 100644 + FilterMatchResult result) { + EXPECT_CALL(mock_observer_, + OnAdMatched(url, result, kFrameHierarchy, content_type, -+ main_rfh(), kSubscriptionUrl)); ++ main_rfh(), kSubscriptionUrl, kConfigurationName)); ++ } ++ ++ void PopupMatchedWillBeNotified(GURL popup_url, FilterMatchResult result) { ++ EXPECT_CALL( ++ mock_observer_, ++ OnPopupMatched(popup_url, result, kFrameHierarchy.front(), main_rfh(), ++ kSubscriptionUrl, kConfigurationName)); + } + + MockObserver mock_observer_; @@ -20994,6 +8448,7 @@ new file mode 100644 + const std::vector kFrameHierarchy{GURL{"https://test.com/"}}; + const SiteKey kSitekey{"key"}; + const GURL kSubscriptionUrl{"https://easylist.com/list.txt"}; ++ const std::string kConfigurationName{"test_configuration"}; +}; + +TEST_F(AdblockResourceClassificationRunnerImplTest, CheckGurlSpecNormalizes) { @@ -21051,27 +8506,21 @@ new file mode 100644 + +TEST_F(AdblockResourceClassificationRunnerImplTest, + CheckRequestFilterMatch_RenderFrameHostNotFound) { -+ // FrameHierarchyBuilder will be unable to find a RFH for the provided IDs. -+ EXPECT_CALL(*mock_frame_hierarchy_builder_, -+ FindRenderFrameHost(main_rfh()->GetGlobalId())) -+ .WillOnce(testing::Return(nullptr)); -+ -+ // The final callback will be called with kNoRule result, because -+ // we aren't able to query filters without a frame hierarchy. Frame hierarchy -+ // is necessary ex. to establish allowlisting. + base::MockCallback callback; + EXPECT_CALL(callback, Run(FilterMatchResult::kNoRule)); + + classification_runner_->CheckRequestFilterMatch( + std::move(*mock_snapshot_), kUrl, ContentType::Image, -+ main_rfh()->GetGlobalId(), callback.Get()); ++ content::GlobalRenderFrameHostId(MSG_ROUTING_NONE, MSG_ROUTING_NONE), ++ callback.Get()); + + task_environment()->RunUntilIdle(); +} + +TEST_F(AdblockResourceClassificationRunnerImplTest, + CheckRequestFilterMatch_AllowlistedMainframeInOneConfig) { -+ EXPECT_CALL(mock_observer_, OnPageAllowed(kUrl, main_rfh(), kSubscriptionUrl)) ++ EXPECT_CALL(mock_observer_, OnPageAllowed(kUrl, main_rfh(), kSubscriptionUrl, ++ kConfigurationName)) + .Times(0); + + // In default config page is not allowlisted... @@ -21096,8 +8545,9 @@ new file mode 100644 + +TEST_F(AdblockResourceClassificationRunnerImplTest, + CheckRequestFilterMatch_AllowlistedMainframeInTwoConfigs) { -+ EXPECT_CALL(mock_observer_, -+ OnPageAllowed(kUrl, main_rfh(), kSubscriptionUrl)); ++ std::string other_coniguration = "other"; ++ EXPECT_CALL(mock_observer_, OnPageAllowed(kUrl, main_rfh(), kSubscriptionUrl, ++ other_coniguration)); + + EXPECT_CALL(*mock_subscription_collection_, + FindBySpecialFilter(SpecialFilterType::Document, kUrl, @@ -21109,6 +8559,10 @@ new file mode 100644 + FindBySpecialFilter(SpecialFilterType::Document, kUrl, + std::vector(), SiteKey())) + .WillOnce(testing::Return(absl::optional{kSubscriptionUrl})); ++ EXPECT_CALL(*collection, GetFilteringConfigurationName()) ++ .WillRepeatedly(testing::ReturnRef(other_coniguration)); ++ EXPECT_CALL(*mock_subscription_collection_, GetFilteringConfigurationName()) ++ .WillRepeatedly(testing::ReturnRef(kConfigurationName)); + mock_snapshot_->push_back(std::move(collection)); + + classification_runner_->CheckDocumentAllowlisted( @@ -21139,7 +8593,8 @@ new file mode 100644 + // Observer will be notified with null RFH. + EXPECT_CALL(mock_observer_, + OnAdMatched(kUrl, FilterMatchResult::kBlockRule, kFrameHierarchy, -+ ContentType::Image, nullptr, kSubscriptionUrl)) ++ ContentType::Image, nullptr, kSubscriptionUrl, ++ kConfigurationName)) + .Times(0); + + task_environment()->RunUntilIdle(); @@ -21149,15 +8604,12 @@ new file mode 100644 + CheckResponseFilterMatch_NoRenderFrameHost) { + base::MockCallback callback; + -+ EXPECT_CALL(*mock_frame_hierarchy_builder_, -+ FindRenderFrameHost(main_rfh()->GetGlobalId())) -+ .WillOnce(Return(nullptr)); -+ + EXPECT_CALL(callback, Run(FilterMatchResult::kNoRule)); + + classification_runner_->CheckResponseFilterMatch( + std::move(*mock_snapshot_), kUrl, ContentType::Image, -+ main_rfh()->GetGlobalId(), {}, callback.Get()); ++ content::GlobalRenderFrameHostId(MSG_ROUTING_NONE, MSG_ROUTING_NONE), {}, ++ callback.Get()); + + task_environment()->RunUntilIdle(); +} @@ -21182,7 +8634,7 @@ new file mode 100644 + EXPECT_CALL(callback, Run(FilterMatchResult::kBlockRule)); + EXPECT_CALL(mock_observer_, + OnAdMatched(kUrl, FilterMatchResult::kBlockRule, kFrameHierarchy, -+ _, _, kSubscriptionUrl)); ++ _, _, kSubscriptionUrl, kConfigurationName)); + task_environment()->RunUntilIdle(); +} + @@ -21206,7 +8658,7 @@ new file mode 100644 + EXPECT_CALL(callback, Run(FilterMatchResult::kAllowRule)); + EXPECT_CALL(mock_observer_, + OnAdMatched(kUrl, FilterMatchResult::kAllowRule, kFrameHierarchy, -+ _, _, kSubscriptionUrl)); ++ _, _, kSubscriptionUrl, kConfigurationName)); + task_environment()->RunUntilIdle(); +} + @@ -21231,6 +8683,59 @@ new file mode 100644 + task_environment()->RunUntilIdle(); +} + ++TEST_F(AdblockResourceClassificationRunnerImplTest, ++ CheckPopupFilterMatch_ValidParameters) { ++ // Set opener pointing to valid RFH ++ adblock::FrameOpenerInfo::CreateForWebContents(web_contents()); ++ auto* info = adblock::FrameOpenerInfo::FromWebContents(web_contents()); ++ info->SetOpener(main_rfh()->GetGlobalId()); ++ ++ FrameHierarchyWillBeBuilt(); ++ SiteKeyWillBePresent(kFrameHierarchy, kSitekey); ++ ++ ClassifierReturnsPopupClassification(kUrl, Decision::Blocked); ++ ++ // The final callback will be called with kBlockRule result. ++ base::MockCallback callback; ++ EXPECT_CALL(callback, Run(FilterMatchResult::kBlockRule)); ++ ++ PopupMatchedWillBeNotified(kUrl, FilterMatchResult::kBlockRule); ++ ++ classification_runner_->CheckPopupFilterMatch(std::move(*mock_snapshot_), ++ kUrl, main_rfh()->GetGlobalId(), ++ callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockResourceClassificationRunnerImplTest, ++ CheckPopupFilterMatch_RenderFrameHostNotFound) { ++ base::MockCallback callback; ++ EXPECT_CALL(callback, Run(FilterMatchResult::kNoRule)); ++ ++ classification_runner_->CheckPopupFilterMatch( ++ std::move(*mock_snapshot_), kUrl, ++ content::GlobalRenderFrameHostId(MSG_ROUTING_NONE, MSG_ROUTING_NONE), ++ callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockResourceClassificationRunnerImplTest, ++ CheckPopupFilterMatch_RenderFrameHostNotFoundForOpener) { ++ // Set opener pointing to invalid RFH ++ adblock::FrameOpenerInfo::CreateForWebContents(web_contents()); ++ ++ base::MockCallback callback; ++ EXPECT_CALL(callback, Run(FilterMatchResult::kNoRule)); ++ ++ classification_runner_->CheckPopupFilterMatch(std::move(*mock_snapshot_), ++ kUrl, main_rfh()->GetGlobalId(), ++ callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ +} // namespace adblock diff --git a/components/adblock/content/browser/test/session_stats_impl_test.cc b/components/adblock/content/browser/test/session_stats_impl_test.cc new file mode 100644 @@ -21495,7 +9000,7 @@ diff --git a/components/adblock/core/activeping_telemetry_topic_provider.cc b/co new file mode 100644 --- /dev/null +++ b/components/adblock/core/activeping_telemetry_topic_provider.cc -@@ -0,0 +1,242 @@ +@@ -0,0 +1,243 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -21515,11 +9020,11 @@ new file mode 100644 + +#include "components/adblock/core/activeping_telemetry_topic_provider.h" + -+#include "base/guid.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/system/sys_info.h" +#include "base/time/time.h" ++#include "base/uuid.h" +#include "components/adblock/core/common/adblock_prefs.h" + +namespace adblock { @@ -21557,10 +9062,10 @@ new file mode 100644 +void AppendStringIfPresent(PrefService* pref_service, + const std::string& pref_name, + base::StringPiece payload_key, -+ base::Value& payload) { ++ base::Value::Dict& payload) { + auto str = pref_service->GetString(pref_name); + if (!str.empty()) { -+ payload.SetStringKey(payload_key, std::move(str)); ++ payload.Set(payload_key, std::move(str)); + } +} +} // namespace @@ -21594,8 +9099,8 @@ new file mode 100644 +// static +std::string ActivepingTelemetryTopicProvider::DefaultAuthToken() { +#if defined(EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN) -+ VLOG(1) << "[eyeo] Using " << EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN -+ << " as Telemetry authentication token"; ++ DVLOG(1) << "[eyeo] Using " << EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN ++ << " as Telemetry authentication token"; + return EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN; +#else + LOG(WARNING) @@ -21615,29 +9120,28 @@ new file mode 100644 +} + +void ActivepingTelemetryTopicProvider::GetPayload(PayloadCallback callback) { -+ base::Value payload(base::Value::Type::DICT); -+ payload.SetStringKey("addon_name", "eyeo-chromium-sdk"); -+ payload.SetStringKey("addon_version", "2.0.0"); -+ payload.SetStringKey("application", app_info_.name); -+ payload.SetStringKey("application_version", app_info_.version); -+ payload.SetBoolKey("aa_active", -+ adblock_controller_->IsAcceptableAdsEnabled()); -+ payload.SetStringKey("platform", base::SysInfo::OperatingSystemName()); -+ payload.SetStringKey("platform_version", -+ base::SysInfo::OperatingSystemVersion()); ++ base::Value::Dict payload; ++ payload.Set("addon_name", "eyeo-chromium-sdk"); ++ payload.Set("addon_version", "2.0.0"); ++ payload.Set("application", app_info_.name); ++ payload.Set("application_version", app_info_.version); ++ payload.Set("aa_active", adblock_controller_->IsAcceptableAdsEnabled()); ++ payload.Set("platform", base::SysInfo::OperatingSystemName()); ++ payload.Set("platform_version", base::SysInfo::OperatingSystemVersion()); + // Server requires the following parameters to either have a correct, + // non-empty value, or not be present at all. We shall not send empty strings. -+ AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTag, ++ AppendStringIfPresent(pref_service_, common::prefs::kTelemetryLastPingTag, + "last_ping_tag", payload); -+ AppendStringIfPresent(pref_service_, prefs::kTelemetryFirstPingTime, ++ AppendStringIfPresent(pref_service_, common::prefs::kTelemetryFirstPingTime, + "first_ping", payload); -+ AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTime, ++ AppendStringIfPresent(pref_service_, common::prefs::kTelemetryLastPingTime, + "last_ping", payload); -+ AppendStringIfPresent(pref_service_, prefs::kTelemetryPreviousLastPingTime, ++ AppendStringIfPresent(pref_service_, ++ common::prefs::kTelemetryPreviousLastPingTime, + "previous_last_ping", payload); + -+ base::Value root(base::Value::Type::DICT); -+ root.SetKey("payload", std::move(payload)); ++ base::Value::Dict root; ++ root.Set("payload", std::move(payload)); + std::string serialized; + // The only way JSONWriter::Write() can return fail is then the Value + // contains lists or dicts that are too deep (200 levels). We just built the @@ -21649,7 +9153,7 @@ new file mode 100644 + +base::Time ActivepingTelemetryTopicProvider::GetTimeOfNextRequest() const { + const auto next_ping_time = -+ pref_service_->GetTime(prefs::kTelemetryNextPingTime); ++ pref_service_->GetTime(common::prefs::kTelemetryNextPingTime); + // Next ping time may be unset if this is a first run. Next request should + // happen ASAP. + if (next_ping_time.is_null()) { @@ -21668,15 +9172,15 @@ new file mode 100644 + } + + VLOG(1) << "[eyeo] Response from Telemetry server: " << *response_content; -+ auto parsed = base::JSONReader::Read(*response_content); -+ if (!parsed || !parsed->is_dict()) { ++ auto parsed = base::JSONReader::ReadDict(*response_content); ++ if (!parsed) { + VLOG(1) + << "[eyeo] Telemetry ping failed, response could not be parsed as JSON"; + ScheduleNextPing(GetRetryPingInterval()); + return; + } + -+ auto* error_message = parsed->FindStringKey("error"); ++ auto* error_message = parsed->FindString("error"); + if (error_message) { + VLOG(1) << "[eyeo] Telemetry ping failed, error message: " + << *error_message; @@ -21688,7 +9192,7 @@ new file mode 100644 + // should be the server time of when the ping was handled, possibly truncated + // for anonymity. We don't parse it or interpret it, just send it back with + // next ping. -+ auto* ping_response_time = parsed->FindStringKey("token"); ++ auto* ping_response_time = parsed->FindString("token"); + if (!ping_response_time) { + VLOG(1) << "[eyeo] Telemetry ping failed, response did not contain a last " + "ping / token value"; @@ -21702,26 +9206,28 @@ new file mode 100644 +} + +void ActivepingTelemetryTopicProvider::ScheduleNextPing(base::TimeDelta delay) { -+ pref_service_->SetTime(prefs::kTelemetryNextPingTime, ++ pref_service_->SetTime(common::prefs::kTelemetryNextPingTime, + base::Time::Now() + delay); +} + +void ActivepingTelemetryTopicProvider::UpdatePrefs( + const std::string& ping_response_time) { + // First ping is only set once per client. -+ if (pref_service_->GetString(prefs::kTelemetryFirstPingTime).empty()) { -+ pref_service_->SetString(prefs::kTelemetryFirstPingTime, ++ if (pref_service_->GetString(common::prefs::kTelemetryFirstPingTime) ++ .empty()) { ++ pref_service_->SetString(common::prefs::kTelemetryFirstPingTime, + ping_response_time); + } + // Previous-to-last becomes last, last becomes current. + pref_service_->SetString( -+ prefs::kTelemetryPreviousLastPingTime, -+ pref_service_->GetString(prefs::kTelemetryLastPingTime)); -+ pref_service_->SetString(prefs::kTelemetryLastPingTime, ping_response_time); ++ common::prefs::kTelemetryPreviousLastPingTime, ++ pref_service_->GetString(common::prefs::kTelemetryLastPingTime)); ++ pref_service_->SetString(common::prefs::kTelemetryLastPingTime, ++ ping_response_time); + // Generate a new random tag that wil be sent along with ping times in the + // next request. -+ const auto tag = base::GUID::GenerateRandomV4(); -+ pref_service_->SetString(prefs::kTelemetryLastPingTag, ++ const auto tag = base::Uuid::GenerateRandomV4(); ++ pref_service_->SetString(common::prefs::kTelemetryLastPingTag, + tag.AsLowercaseString()); +} + @@ -21831,7 +9337,7 @@ diff --git a/components/adblock/core/adblock_controller.h b/components/adblock/c new file mode 100644 --- /dev/null +++ b/components/adblock/core/adblock_controller.h -@@ -0,0 +1,100 @@ +@@ -0,0 +1,64 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -21870,22 +9376,8 @@ new file mode 100644 + */ +class AdblockController : public KeyedService { + public: -+ // Deprecated, to be removed in version 115 -+ // [deprecated="Use FilteringConfiguration::Observer instead"] -+ class Observer : public base::CheckedObserver { -+ public: -+ virtual void OnSubscriptionUpdated(const GURL& url) {} -+ virtual void OnEnabledStateChanged() {} -+ }; + ~AdblockController() override = default; + -+ // Deprecated, to be removed in version 115 -+ // [deprecated="Use FilteringConfiguration::AddObserver instead"] -+ virtual void AddObserver(Observer* observer) = 0; -+ // Deprecated, to be removed in version 115 -+ // [deprecated="Use FilteringConfiguration::RemoveObserver instead"] -+ virtual void RemoveObserver(Observer* observer) = 0; -+ + virtual void SetAdblockEnabled(bool enabled) = 0; + virtual bool IsAdblockEnabled() const = 0; + virtual void SetAcceptableAdsEnabled(bool enabled) = 0; @@ -21905,28 +9397,6 @@ new file mode 100644 + virtual std::vector GetCustomFilters() const = 0; + + virtual std::vector GetKnownSubscriptions() const = 0; -+ -+ // Deprecated, SelectBuiltInSubscription will be removed in version 115 -+ // Use InstallSubscription(const GURL& url) instead. -+ virtual void SelectBuiltInSubscription(const GURL& url) = 0; -+ // Deprecated, UnselectBuiltInSubscription will be removed in version 115 -+ // Use UninstallSubscription(const GURL& url) instead. -+ virtual void UnselectBuiltInSubscription(const GURL& url) = 0; -+ // Deprecated, GetSelectedBuiltInSubscriptions will be removed in version 115 -+ // Use GetInstalledSubscriptions() instead. -+ virtual std::vector> -+ GetSelectedBuiltInSubscriptions() const = 0; -+ -+ // Deprecated, AddCustomSubscription will be removed in version 115 -+ // Use InstallSubscription(const GURL& url) instead. -+ virtual void AddCustomSubscription(const GURL& url) = 0; -+ // Deprecated, RemoveCustomSubscription will be removed in version 115 -+ // Use UninstallSubscription(const GURL& url) instead. -+ virtual void RemoveCustomSubscription(const GURL& url) = 0; -+ // Deprecated, GetCustomSubscriptions will be removed in version 115 -+ // Use GetInstalledSubscriptions() instead. -+ virtual std::vector> GetCustomSubscriptions() -+ const = 0; +}; + +} // namespace adblock @@ -21936,7 +9406,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb new file mode 100644 --- /dev/null +++ b/components/adblock/core/adblock_controller_impl.cc -@@ -0,0 +1,342 @@ +@@ -0,0 +1,271 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -21986,15 +9456,6 @@ new file mode 100644 + +namespace { + -+bool IsKnownSubscription( -+ const std::vector& known_subscriptions, -+ const GURL& url) { -+ return base::ranges::any_of(known_subscriptions, -+ [&](const auto& known_subscription) { -+ return known_subscription.url == url; -+ }); -+} -+ +template +std::vector MigrateItemsFromList(PrefService* pref_service, + const std::string& pref_name) { @@ -22032,7 +9493,6 @@ new file mode 100644 + subscription_service_(subscription_service), + language_(language::ExtractBaseLanguage(locale)), + known_subscriptions_(std::move(known_subscriptions)) { -+ subscription_service_->AddObserver(this); + // language::ExtractBaseLanguage is pretty basic, if it doesn't return + // something that looks like a valid language, fallback to English and use the + // default EasyList. @@ -22041,26 +9501,10 @@ new file mode 100644 + } +} + -+AdblockControllerImpl::~AdblockControllerImpl() { -+ subscription_service_->RemoveObserver(this); -+} -+ -+void AdblockControllerImpl::AddObserver(AdblockController::Observer* observer) { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ observers_.AddObserver(observer); -+} -+ -+void AdblockControllerImpl::RemoveObserver( -+ AdblockController::Observer* observer) { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ observers_.RemoveObserver(observer); -+} ++AdblockControllerImpl::~AdblockControllerImpl() = default; + +void AdblockControllerImpl::SetAdblockEnabled(bool enabled) { + adblock_filtering_configuration_->SetEnabled(enabled); -+ for (auto& observer : observers_) { -+ observer.OnEnabledStateChanged(); -+ } +} + +bool AdblockControllerImpl::IsAdblockEnabled() const { @@ -22089,55 +9533,11 @@ new file mode 100644 + adblock_filtering_configuration_->RemoveFilterList(url); +} + -+void AdblockControllerImpl::SelectBuiltInSubscription(const GURL& url) { -+ InstallSubscription(url); -+} -+ -+void AdblockControllerImpl::UnselectBuiltInSubscription(const GURL& url) { -+ UninstallSubscription(url); -+} -+ -+void AdblockControllerImpl::AddCustomSubscription(const GURL& url) { -+ InstallSubscription(url); -+} -+ -+void AdblockControllerImpl::RemoveCustomSubscription(const GURL& url) { -+ UninstallSubscription(url); -+} -+ +std::vector> +AdblockControllerImpl::GetInstalledSubscriptions() const { + return GetSubscriptionsThatMatchConfiguration(); +} + -+std::vector> -+AdblockControllerImpl::GetSelectedBuiltInSubscriptions() const { -+ auto selected = GetInstalledSubscriptions(); -+ std::vector known = GetKnownSubscriptions(); -+ selected.erase(base::ranges::remove_if(selected, -+ [&](const auto& subscription) { -+ return !IsKnownSubscription( -+ known, -+ subscription->GetSourceUrl()); -+ }), -+ selected.end()); -+ return selected; -+} -+ -+std::vector> -+AdblockControllerImpl::GetCustomSubscriptions() const { -+ auto selected = GetInstalledSubscriptions(); -+ std::vector known = GetKnownSubscriptions(); -+ selected.erase(base::ranges::remove_if(selected, -+ [&](const auto& subscription) { -+ return IsKnownSubscription( -+ known, -+ subscription->GetSourceUrl()); -+ }), -+ selected.end()); -+ return selected; -+} -+ +void AdblockControllerImpl::AddAllowedDomain(const std::string& domain) { + adblock_filtering_configuration_->AddAllowedDomain(domain); +} @@ -22167,17 +9567,11 @@ new file mode 100644 + return known_subscriptions_; +} + -+void AdblockControllerImpl::OnSubscriptionInstalled( -+ const GURL& subscription_url) { -+ for (auto& observer : observers_) { -+ observer.OnSubscriptionUpdated(subscription_url); -+ } -+} -+ +void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) { + // If the state of installed subscriptions in SubscriptionService is different + // than the state in prefs, prefs take precedence. -+ if (pref_service->GetBoolean(prefs::kInstallFirstStartSubscriptions)) { ++ if (pref_service->GetBoolean( ++ common::prefs::kInstallFirstStartSubscriptions)) { + // On first run, install additional subscriptions. + for (const auto& cur : known_subscriptions_) { + if (cur.first_run == SubscriptionFirstRunBehavior::Subscribe) { @@ -22192,47 +9586,52 @@ new file mode 100644 + } + } + ++ if (IsEyeoFilteringDisabledByDefault()) { ++ SetAdblockEnabled(false); ++ } ++ + InstallLanguageBasedRecommendedSubscriptions(); -+ pref_service->SetBoolean(prefs::kInstallFirstStartSubscriptions, false); ++ pref_service->SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ false); + } +} + +void AdblockControllerImpl::MigrateLegacyPrefs(PrefService* pref_service) { -+ if (auto aa_value = MigrateBoolFromPrefs(pref_service, -+ prefs::kEnableAcceptableAdsLegacy)) { ++ if (auto aa_value = MigrateBoolFromPrefs( ++ pref_service, common::prefs::kEnableAcceptableAdsLegacy)) { + SetAcceptableAdsEnabled(*aa_value); + VLOG(1) << "[eyeo] Migrated kEnableAcceptableAdsLegacy pref"; + } + -+ if (auto enable_value = -+ MigrateBoolFromPrefs(pref_service, prefs::kEnableAdblockLegacy)) { ++ if (auto enable_value = MigrateBoolFromPrefs( ++ pref_service, common::prefs::kEnableAdblockLegacy)) { + SetAdblockEnabled(*enable_value); + VLOG(1) << "[eyeo] Migrated kEnableAdblockLegacy pref"; + } + + for (const auto& url : MigrateItemsFromList( -+ pref_service, prefs::kAdblockCustomSubscriptionsLegacy)) { ++ pref_service, common::prefs::kAdblockCustomSubscriptionsLegacy)) { + adblock_filtering_configuration_->AddFilterList(url); + VLOG(1) << "[eyeo] Migrated " << url + << " from kAdblockCustomSubscriptionsLegacy pref"; + } + + for (const auto& url : MigrateItemsFromList( -+ pref_service, prefs::kAdblockSubscriptionsLegacy)) { ++ pref_service, common::prefs::kAdblockSubscriptionsLegacy)) { + adblock_filtering_configuration_->AddFilterList(url); + VLOG(1) << "[eyeo] Migrated " << url + << " from kAdblockSubscriptionsLegacy pref"; + } + + for (const auto& domain : MigrateItemsFromList( -+ pref_service, prefs::kAdblockAllowedDomainsLegacy)) { ++ pref_service, common::prefs::kAdblockAllowedDomainsLegacy)) { + adblock_filtering_configuration_->AddAllowedDomain(domain); + VLOG(1) << "[eyeo] Migrated " << domain + << " from kAdblockAllowedDomainsLegacy pref"; + } + + for (const auto& filter : MigrateItemsFromList( -+ pref_service, prefs::kAdblockCustomFiltersLegacy)) { ++ pref_service, common::prefs::kAdblockCustomFiltersLegacy)) { + adblock_filtering_configuration_->AddCustomFilter(filter); + VLOG(1) << "[eyeo] Migrated " << filter + << " from kAdblockCustomFiltersLegacy pref"; @@ -22283,7 +9682,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.h b/components/adbl new file mode 100644 --- /dev/null +++ b/components/adblock/core/adblock_controller_impl.h -@@ -0,0 +1,113 @@ +@@ -0,0 +1,95 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -22326,8 +9725,7 @@ new file mode 100644 + * FilteringConfiguration as the backend for all the state set via the + * interface. + */ -+class AdblockControllerImpl : public AdblockController, -+ public SubscriptionService::SubscriptionObserver { ++class AdblockControllerImpl : public AdblockController { + public: + AdblockControllerImpl(FilteringConfiguration* adblock_filtering_configuration, + SubscriptionService* subscription_service, @@ -22340,24 +9738,11 @@ new file mode 100644 + AdblockControllerImpl(AdblockControllerImpl&&) = delete; + AdblockControllerImpl& operator=(AdblockControllerImpl&&) = delete; + -+ void AddObserver(AdblockController::Observer* observer) override; -+ void RemoveObserver(AdblockController::Observer* observer) override; -+ + void SetAdblockEnabled(bool enabled) override; + bool IsAdblockEnabled() const override; + void SetAcceptableAdsEnabled(bool enabled) override; + bool IsAcceptableAdsEnabled() const override; + -+ void SelectBuiltInSubscription(const GURL& url) override; -+ void UnselectBuiltInSubscription(const GURL& url) override; -+ std::vector> GetSelectedBuiltInSubscriptions() -+ const override; -+ -+ void AddCustomSubscription(const GURL& url) override; -+ void RemoveCustomSubscription(const GURL& url) override; -+ std::vector> GetCustomSubscriptions() -+ const override; -+ + void InstallSubscription(const GURL& url) override; + void UninstallSubscription(const GURL& url) override; + std::vector> GetInstalledSubscriptions() @@ -22373,9 +9758,6 @@ new file mode 100644 + + std::vector GetKnownSubscriptions() const override; + -+ // SubscriptionObserver: -+ void OnSubscriptionInstalled(const GURL& subscription_url) override; -+ + void RunFirstRunLogic(PrefService* pref_service); + void MigrateLegacyPrefs(PrefService* pref_service); + @@ -22390,7 +9772,6 @@ new file mode 100644 + raw_ptr subscription_service_; + std::string language_; + std::vector known_subscriptions_; -+ base::ObserverList observers_; + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + @@ -22425,14 +9806,14 @@ new file mode 100644 + +const char kDisableAcceptableAds[] = "disable-aa"; +const char kDisableAdblock[] = "disable-adblock"; -+const char kDisableWebUiCompatibility[] = "disable-webui-compatibility"; ++const char kDisableEyeoFiltering[] = "disable-eyeo-filtering"; + +} // namespace adblock::switches diff --git a/components/adblock/core/adblock_switches.h b/components/adblock/core/adblock_switches.h new file mode 100644 --- /dev/null +++ b/components/adblock/core/adblock_switches.h -@@ -0,0 +1,30 @@ +@@ -0,0 +1,29 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -22457,8 +9838,7 @@ new file mode 100644 + +extern const char kDisableAcceptableAds[]; +extern const char kDisableAdblock[]; -+// TODO(mpawlowski) remove in 111, when this becomes standard: -+extern const char kDisableWebUiCompatibility[]; ++extern const char kDisableEyeoFiltering[]; + +} // namespace adblock::switches + @@ -22938,7 +10318,7 @@ diff --git a/components/adblock/core/classifier/resource_classifier.h b/componen new file mode 100644 --- /dev/null +++ b/components/adblock/core/classifier/resource_classifier.h -@@ -0,0 +1,82 @@ +@@ -0,0 +1,90 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -22990,6 +10370,9 @@ new file mode 100644 + // If decision is Blocked or Allowed, |decisive_subscription| has the URL of + // the subscription that had the decisive filter. + GURL decisive_subscription; ++ // If decision is Blocked or Allowed, |decisive_configuration_name| has the ++ // name of the FilteringConfiguration that contain matched filter. ++ std::string decisive_configuration_name; + }; + + virtual ClassificationResult ClassifyRequest( @@ -23013,6 +10396,11 @@ new file mode 100644 + const scoped_refptr& response_headers) + const = 0; + ++ virtual absl::optional CheckRewrite( ++ const SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const std::vector& frame_hierarchy) const = 0; ++ + protected: + friend class base::RefCountedThreadSafe; + virtual ~ResourceClassifier(); @@ -23025,7 +10413,7 @@ diff --git a/components/adblock/core/classifier/resource_classifier_impl.cc b/co new file mode 100644 --- /dev/null +++ b/components/adblock/core/classifier/resource_classifier_impl.cc -@@ -0,0 +1,305 @@ +@@ -0,0 +1,404 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -23098,7 +10486,8 @@ new file mode 100644 + FilterCategory::Blocking); + if (!subscription_with_blocking_filter_it) { + // Found no blocking filters in any of the subscriptions. -+ return ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Ignored, {}, {}}; + } + // Found a blocking filter but perhaps one of the subscriptions has an + // allowing filter to override it? @@ -23107,8 +10496,10 @@ new file mode 100644 + content_type, sitekey); + if (subscription_with_allowing_filter_it) { + // Found an overriding allowing filter: -+ return ClassificationResult{ClassificationResult::Decision::Allowed, -+ *subscription_with_allowing_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Allowed, ++ *subscription_with_allowing_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; + } + // Last chance to avoid blocking: maybe there is a GENERICBLOCK filter and we + // should re-search for domain-specific filters only? @@ -23126,17 +10517,21 @@ new file mode 100644 + // it. + return ClassificationResult{ + ClassificationResult::Decision::Blocked, -+ *subscription_with_domain_specific_blocking_filter_it}; ++ *subscription_with_domain_specific_blocking_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; + } else { + // There were no domain-specific blocking filters, our first match must + // have been a generic filter. -+ return ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Ignored, {}, {}}; + } + } + // There was no GENERICBLOCK filter available, so the original blocking result + // is valid. -+ return ClassificationResult{ClassificationResult::Decision::Blocked, -+ *subscription_with_blocking_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Blocked, ++ *subscription_with_blocking_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; +} + +ClassificationResult ClassifyPopupWithSingleCollection( @@ -23151,7 +10546,8 @@ new file mode 100644 + popup_url, opener_frame_hierarchy, sitekey, FilterCategory::Blocking); + if (!subscription_with_blocking_filter_it) { + // Found no blocking filters in any of the subscriptions. -+ return ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Ignored, {}, {}}; + } + // Found a blocking filter but perhaps one of the subscriptions has an + // allowing filter to override it? @@ -23160,8 +10556,10 @@ new file mode 100644 + popup_url, opener_frame_hierarchy, sitekey, FilterCategory::Allowing); + if (subscription_with_allowing_filter_it) { + // Found an overriding allowing filter: -+ return ClassificationResult{ClassificationResult::Decision::Allowed, -+ *subscription_with_allowing_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Allowed, ++ *subscription_with_allowing_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; + } + const auto subscription_with_document_allowing_filter_it = + subscription_collection.FindBySpecialFilter( @@ -23169,21 +10567,26 @@ new file mode 100644 + sitekey); + if (subscription_with_document_allowing_filter_it) { + // Found an overriding document allowing filter for the frame hierarchy: -+ return ClassificationResult{ClassificationResult::Decision::Allowed, -+ *subscription_with_document_allowing_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Allowed, ++ *subscription_with_document_allowing_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; + } + // There is no overriding allowing filter, the popup should be blocked. -+ return ClassificationResult{ClassificationResult::Decision::Blocked, -+ *subscription_with_blocking_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Blocked, ++ *subscription_with_blocking_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; +} + +ClassificationResult CheckHeaderFiltersMatchResponseHeaders( ++ const SubscriptionCollection& subscription_collection, + const GURL request_url, + const std::vector frame_hierarchy, + const scoped_refptr& headers, + std::set blocking_filters, + std::set allowing_filters) { -+ ClassificationResult result{ClassificationResult::Decision::Ignored, {}}; ++ ClassificationResult result{ClassificationResult::Decision::Ignored, {}, {}}; + + for (const auto& filter : blocking_filters) { + auto key_value = @@ -23196,10 +10599,12 @@ new file mode 100644 + if (auto allow_rule = IsHeaderFilterOverruled(filter.header_filter, + allowing_filters)) { + result = {ClassificationResult::Decision::Allowed, -+ allow_rule->subscription_url}; ++ allow_rule->subscription_url, ++ subscription_collection.GetFilteringConfigurationName()}; + } else { -+ return ClassificationResult{ClassificationResult::Decision::Blocked, -+ filter.subscription_url}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Blocked, filter.subscription_url, ++ subscription_collection.GetFilteringConfigurationName()}; + } + } + } else { @@ -23208,10 +10613,12 @@ new file mode 100644 + if (auto allow_rule = IsHeaderFilterOverruled(filter.header_filter, + allowing_filters)) { + result = {ClassificationResult::Decision::Allowed, -+ allow_rule->subscription_url}; ++ allow_rule->subscription_url, ++ subscription_collection.GetFilteringConfigurationName()}; + } else { -+ return ClassificationResult{ClassificationResult::Decision::Blocked, -+ filter.subscription_url}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Blocked, filter.subscription_url, ++ subscription_collection.GetFilteringConfigurationName()}; + } + } + } @@ -23228,17 +10635,20 @@ new file mode 100644 + auto blocking_filters = subscription_collection.GetHeaderFilters( + request_url, frame_hierarchy, content_type, FilterCategory::Blocking); + if (blocking_filters.empty()) { -+ return ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Ignored, {}, {}}; + } + -+ // If blocking filters found, check first if filters are not overuled ++ // If blocking filters found, check first if filters are not overruled + const auto subscription_with_allowing_document_filter_it = + subscription_collection.FindBySpecialFilter( + SpecialFilterType::Document, request_url, frame_hierarchy, SiteKey()); + if (subscription_with_allowing_document_filter_it) { + // Found no blocking filters in any of the subscriptions. -+ return ClassificationResult{ClassificationResult::Decision::Allowed, -+ *subscription_with_allowing_document_filter_it}; ++ return ClassificationResult{ ++ ClassificationResult::Decision::Allowed, ++ *subscription_with_allowing_document_filter_it, ++ subscription_collection.GetFilteringConfigurationName()}; + } + + if (subscription_collection.FindBySpecialFilter( @@ -23251,7 +10661,7 @@ new file mode 100644 + FilterCategory::DomainSpecificBlocking); + + return CheckHeaderFiltersMatchResponseHeaders( -+ request_url, frame_hierarchy, response_headers, ++ subscription_collection, request_url, frame_hierarchy, response_headers, + std::move(blocking_filters), {}); + } + // If no special filters found, get allowing filters and check which filters @@ -23259,10 +10669,73 @@ new file mode 100644 + auto allowing_filters = subscription_collection.GetHeaderFilters( + request_url, frame_hierarchy, content_type, FilterCategory::Allowing); + return CheckHeaderFiltersMatchResponseHeaders( -+ request_url, frame_hierarchy, response_headers, ++ subscription_collection, request_url, frame_hierarchy, response_headers, + std::move(blocking_filters), std::move(allowing_filters)); +} + ++absl::optional CheckRewriteWithSingleCollection( ++ const SubscriptionCollection& subscription_collection, ++ const GURL& request_url, ++ const std::vector& frame_hierarchy) { ++ auto blocking_rewrites = subscription_collection.GetRewriteFilters( ++ request_url, frame_hierarchy, FilterCategory::Blocking); ++ if (blocking_rewrites.empty()) { ++ return absl::nullopt; ++ } ++ ++ // If blocking filters are found, check first if blocking filters are not ++ // overruled completely. ++ const auto subscription_with_allowing_document_filter_it = ++ subscription_collection.FindBySpecialFilter( ++ SpecialFilterType::Document, request_url, frame_hierarchy, SiteKey()); ++ if (subscription_with_allowing_document_filter_it) { ++ return absl::nullopt; ++ } ++ ++ if (subscription_collection.FindBySpecialFilter( ++ SpecialFilterType::Genericblock, request_url, frame_hierarchy, ++ SiteKey())) { ++ // If genericblock filter is found, searched for blocking domain-specific ++ // filters. ++ blocking_rewrites = subscription_collection.GetRewriteFilters( ++ request_url, frame_hierarchy, FilterCategory::DomainSpecificBlocking); ++ ++ if (blocking_rewrites.empty()) { ++ return absl::nullopt; ++ } ++ } ++ ++ // Check if blocking filters are not overruled by allowing ones. ++ auto allowing_rewrites = subscription_collection.GetRewriteFilters( ++ request_url, frame_hierarchy, FilterCategory::Allowing); ++ if (allowing_rewrites.empty()) { ++ // Any filter will do, take the 1st one. ++ return absl::optional(GURL{*blocking_rewrites.begin()}); ++ } ++ ++ // Change set to vector to call algorithm ++ std::vector blocking_rewrites_v(blocking_rewrites.begin(), ++ blocking_rewrites.end()); ++ // Remove blocking filters overruled by allowing filters. ++ blocking_rewrites_v.erase( ++ base::ranges::remove_if( ++ blocking_rewrites_v, ++ [&allowing_rewrites](const auto blocking_rewrite) { ++ return base::ranges::find_if( ++ allowing_rewrites, [&](const auto& allowing_rewrite) { ++ return blocking_rewrite == allowing_rewrite; ++ }) != allowing_rewrites.end(); ++ }), ++ blocking_rewrites_v.end()); ++ ++ if (blocking_rewrites_v.empty()) { ++ return absl::nullopt; ++ } ++ ++ // Any filter will do, take the 1st one. ++ return absl::optional(GURL{*blocking_rewrites_v.begin()}); ++} ++ +} // namespace + +ResourceClassifierImpl::~ResourceClassifierImpl() = default; @@ -23274,7 +10747,7 @@ new file mode 100644 + ContentType content_type, + const SiteKey& sitekey) const { + auto classification = -+ ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ ClassificationResult{ClassificationResult::Decision::Ignored, {}, {}}; + for (const auto& collection : subscription_collections) { + auto result = ClassifyRequestWithSingleCollection( + *collection, request_url, frame_hierarchy, content_type, sitekey); @@ -23294,7 +10767,7 @@ new file mode 100644 + const std::vector& opener_frame_hierarchy, + const SiteKey& sitekey) const { + auto classification = -+ ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ ClassificationResult{ClassificationResult::Decision::Ignored, {}, {}}; + for (const auto& collection : subscription_collections) { + auto result = ClassifyPopupWithSingleCollection( + *collection, popup_url, opener_frame_hierarchy, sitekey); @@ -23315,7 +10788,7 @@ new file mode 100644 + ContentType content_type, + const scoped_refptr& response_headers) const { + auto classification = -+ ClassificationResult{ClassificationResult::Decision::Ignored, {}}; ++ ClassificationResult{ClassificationResult::Decision::Ignored, {}, {}}; + for (const auto& collection : subscription_collections) { + auto result = ClassifyResponseWithSingleCollection( + *collection, request_url, frame_hierarchy, content_type, @@ -23330,12 +10803,26 @@ new file mode 100644 + return classification; +} + ++absl::optional ResourceClassifierImpl::CheckRewrite( ++ const SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const std::vector& frame_hierarchy) const { ++ for (const auto& collection : subscription_collections) { ++ auto result = CheckRewriteWithSingleCollection(*collection, request_url, ++ frame_hierarchy); ++ if (result) { ++ return result; ++ } ++ } ++ return absl::nullopt; ++} ++ +} // namespace adblock diff --git a/components/adblock/core/classifier/resource_classifier_impl.h b/components/adblock/core/classifier/resource_classifier_impl.h new file mode 100644 --- /dev/null +++ b/components/adblock/core/classifier/resource_classifier_impl.h -@@ -0,0 +1,59 @@ +@@ -0,0 +1,64 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -23387,6 +10874,11 @@ new file mode 100644 + const scoped_refptr& response_headers) + const final; + ++ absl::optional CheckRewrite( ++ const SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const std::vector& frame_hierarchy) const final; ++ + protected: + friend class base::RefCountedThreadSafe; + ~ResourceClassifierImpl() override; @@ -23430,7 +10922,7 @@ diff --git a/components/adblock/core/classifier/test/mock_resource_classifier.h new file mode 100644 --- /dev/null +++ b/components/adblock/core/classifier/test/mock_resource_classifier.h -@@ -0,0 +1,60 @@ +@@ -0,0 +1,66 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -23483,6 +10975,12 @@ new file mode 100644 + ContentType, + const scoped_refptr&), + (override, const)); ++ MOCK_METHOD(absl::optional, ++ CheckRewrite, ++ (const SubscriptionService::Snapshot, ++ const GURL&, ++ const std::vector&), ++ (override, const)); + + protected: + ~MockResourceClassifier() override; @@ -23495,7 +10993,7 @@ diff --git a/components/adblock/core/classifier/test/resource_classifier_impl_te new file mode 100644 --- /dev/null +++ b/components/adblock/core/classifier/test/resource_classifier_impl_test.cc -@@ -0,0 +1,506 @@ +@@ -0,0 +1,634 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -23539,6 +11037,8 @@ new file mode 100644 + mock_subscription_collection_ = new MockSubscriptionCollection(); + mock_snapshot_ = std::make_unique(); + mock_snapshot_->emplace_back(mock_subscription_collection_); ++ EXPECT_CALL(*mock_subscription_collection_, GetFilteringConfigurationName()) ++ .WillRepeatedly(testing::ReturnRef(kConfigurationName)); + } + + void FindBySubresourceFilterReturns(const absl::optional& return_value, @@ -23580,6 +11080,13 @@ new file mode 100644 + .Times(0); + } + ++ void GetRewriteFiltersReturns(const std::set& return_value, ++ FilterCategory category) { ++ EXPECT_CALL(*mock_subscription_collection_, ++ GetRewriteFilters(_, _, category)) ++ .WillOnce(Return(return_value)); ++ } ++ + void AssertFindBySpecialFilterNotCalled(SpecialFilterType type) { + EXPECT_CALL(*mock_subscription_collection_, + FindBySpecialFilter(type, _, _, _)) @@ -23622,6 +11129,7 @@ new file mode 100644 + {"blocking_filter", kSourceUrl}}; + const std::set kDomainSpecificHeaderFilters = { + {"domain_specific_filter", kSourceUrl}}; ++ const std::string kConfigurationName = "test_configuration"; + raw_ptr mock_subscription_collection_; + std::unique_ptr mock_snapshot_; + scoped_refptr classifier_; @@ -23637,11 +11145,12 @@ new file mode 100644 + AssertFindBySubresourceFilterNotCalled( + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Ignored); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, BlockingFilterFound) { @@ -23659,11 +11168,12 @@ new file mode 100644 + AssertFindBySubresourceFilterNotCalled( + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, BlockingAndAllowingFilterFound) { @@ -23680,11 +11190,12 @@ new file mode 100644 + AssertFindBySubresourceFilterNotCalled( + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Allowed); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Allowed); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, GenericBlockSearch) { @@ -23701,11 +11212,12 @@ new file mode 100644 + AssertFindBySubresourceFilterNotCalled( + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, DomainSpecificNotFound) { @@ -23725,11 +11237,12 @@ new file mode 100644 + FindBySubresourceFilterReturns(absl::nullopt, + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Ignored); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, DomainSpecificFound) { @@ -23749,22 +11262,23 @@ new file mode 100644 + FindBySubresourceFilterReturns(absl::optional(kSourceUrl), + FilterCategory::DomainSpecificBlocking); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, PopupNoHasFilters) { + FindByPopupFilterReturns(absl::nullopt, FilterCategory::Blocking); + AssertFindByPopupFilterNotCalled(FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyPopup(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kSitekey) -+ .decision, -+ Decision::Ignored); ++ auto result = classifier_->ClassifyPopup( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, PopupHasBlockingFilter) { @@ -23772,11 +11286,11 @@ new file mode 100644 + FilterCategory::Blocking); + FindByPopupFilterReturns(absl::nullopt, FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyPopup(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = classifier_->ClassifyPopup( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, PopupHasAllowingFilter) { @@ -23785,22 +11299,23 @@ new file mode 100644 + FindByPopupFilterReturns(absl::optional(kSourceUrl), + FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyPopup(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kSitekey) -+ .decision, -+ Decision::Allowed); ++ auto result = classifier_->ClassifyPopup( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Allowed); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, NoBlockingHeaderFilters) { + GetHeaderFiltersReturns({}, FilterCategory::Blocking); + AssertGetHeaderFiltersNotCalled(FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, {}) -+ .decision, -+ Decision::Ignored); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, {}); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23813,11 +11328,12 @@ new file mode 100644 + AssertGetHeaderFiltersNotCalled(FilterCategory::DomainSpecificBlocking); + AssertGetHeaderFiltersNotCalled(FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, {}) -+ .decision, -+ Decision::Allowed); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, {}); ++ EXPECT_EQ(result.decision, Decision::Allowed); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23829,11 +11345,12 @@ new file mode 100644 + GetHeaderFiltersReturns({}, FilterCategory::DomainSpecificBlocking); + AssertGetHeaderFiltersNotCalled(FilterCategory::Allowing); + -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, {}) -+ .decision, -+ Decision::Ignored); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, {}); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23848,11 +11365,12 @@ new file mode 100644 + + auto headers = CreateResponseHeaders("not_matching"); + CHECK(headers); -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, headers) -+ .decision, -+ Decision::Ignored); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, headers); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23868,11 +11386,12 @@ new file mode 100644 + auto headers = CreateResponseHeaders( + kDomainSpecificHeaderFilters.begin()->header_filter); + CHECK(headers); -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, headers) -+ .decision, -+ Decision::Blocked); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, headers); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, BlockingHeaderFiltersNoMatch) { @@ -23884,11 +11403,12 @@ new file mode 100644 + + auto headers = CreateResponseHeaders("no_match"); + CHECK(headers); -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, headers) -+ .decision, -+ Decision::Ignored); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, headers); ++ EXPECT_EQ(result.decision, Decision::Ignored); ++ EXPECT_EQ(result.decisive_configuration_name, ""); ++ EXPECT_EQ(result.decisive_subscription, GURL()); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23902,11 +11422,12 @@ new file mode 100644 + auto headers = + CreateResponseHeaders(kBlockingHeaderFilters.begin()->header_filter); + CHECK(headers); -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, headers) -+ .decision, -+ Decision::Blocked); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, headers); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23920,11 +11441,12 @@ new file mode 100644 + auto headers = + CreateResponseHeaders(kAllowingHeaderFilters.begin()->header_filter); + CHECK(headers); -+ EXPECT_EQ(classifier_ -+ ->ClassifyResponse(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, headers) -+ .decision, -+ Decision::Allowed); ++ auto result = classifier_->ClassifyResponse( ++ std::move(*mock_snapshot_), kResourceAddress, {kParentAddress}, ++ kContentType, headers); ++ EXPECT_EQ(result.decision, Decision::Allowed); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23935,23 +11457,28 @@ new file mode 100644 + FindByAllowFilterReturns(absl::optional(kSourceUrl)); + + // Other configuration has blocking filter ++ std::string other_coniguration = "other"; ++ GURL other_source{"https://subscription.com/other.txt"}; + auto mock_subscription_collection = + std::make_unique(); + EXPECT_CALL(*mock_subscription_collection, + FindBySubresourceFilter(_, _, _, _, FilterCategory::Blocking)) -+ .WillOnce(Return(kSourceUrl)); ++ .WillOnce(Return(absl::optional(other_source))); + EXPECT_CALL(*mock_subscription_collection, FindByAllowFilter(_, _, _, _)) + .WillOnce(Return(absl::nullopt)); + EXPECT_CALL(*mock_subscription_collection, + FindBySpecialFilter(SpecialFilterType::Genericblock, _, _, _)) + .WillOnce(Return(absl::nullopt)); ++ EXPECT_CALL(*mock_subscription_collection, GetFilteringConfigurationName()) ++ .WillRepeatedly(testing::ReturnRef(other_coniguration)); + + mock_snapshot_->push_back(std::move(mock_subscription_collection)); -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, other_coniguration); ++ EXPECT_EQ(result.decisive_subscription, other_source); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23970,11 +11497,12 @@ new file mode 100644 + .Times(0); + + mock_snapshot_->push_back(std::move(mock_subscription_collection)); -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Blocked); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Blocked); ++ EXPECT_EQ(result.decisive_configuration_name, kConfigurationName); ++ EXPECT_EQ(result.decisive_subscription, kSourceUrl); +} + +TEST_F(AdblockResourceClassifierImplTest, @@ -23985,20 +11513,118 @@ new file mode 100644 + FindByAllowFilterReturns(absl::optional(kSourceUrl)); + + // Other configuration has also allowing filter ++ std::string other_coniguration = "other"; ++ GURL other_source{"https://subscription.com/other.txt"}; + MockSubscriptionCollection* mock_subscription_collection = + new MockSubscriptionCollection(); + EXPECT_CALL(*mock_subscription_collection, + FindBySubresourceFilter(_, _, _, _, FilterCategory::Blocking)) -+ .WillOnce(Return(kSourceUrl)); ++ .WillOnce(Return(other_source)); + EXPECT_CALL(*mock_subscription_collection, FindByAllowFilter(_, _, _, _)) -+ .WillOnce(Return(absl::optional(kSourceUrl))); ++ .WillOnce(Return(absl::optional(other_source))); ++ EXPECT_CALL(*mock_subscription_collection, GetFilteringConfigurationName()) ++ .WillRepeatedly(testing::ReturnRef(other_coniguration)); + + mock_snapshot_->emplace_back(mock_subscription_collection); -+ EXPECT_EQ(classifier_ -+ ->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, -+ {kParentAddress}, kContentType, kSitekey) -+ .decision, -+ Decision::Allowed); ++ auto result = ++ classifier_->ClassifyRequest(std::move(*mock_snapshot_), kResourceAddress, ++ {kParentAddress}, kContentType, kSitekey); ++ EXPECT_EQ(result.decision, Decision::Allowed); ++ EXPECT_EQ(result.decisive_configuration_name, other_coniguration); ++ EXPECT_EQ(result.decisive_subscription, other_source); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, RewriteFilterNotFound) { ++ // There are no blocking filters found. ++ GetRewriteFiltersReturns({}, FilterCategory::Blocking); ++ ++ // Since there are no blocking filters, no need to check allow filters. ++ AssertFindBySpecialFilterNotCalled(SpecialFilterType::Document); ++ AssertFindBySpecialFilterNotCalled(SpecialFilterType::Genericblock); ++ ++ // Empty result means no redirect necessary. ++ EXPECT_FALSE(classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, RewriteFilterFound) { ++ base::StringPiece redirect = "about::blank"; ++ ++ GetRewriteFiltersReturns({redirect}, FilterCategory::Blocking); ++ GetRewriteFiltersReturns({}, FilterCategory::Allowing); ++ ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Document); ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Genericblock); ++ ++ EXPECT_EQ(GURL{redirect}, ++ classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, RewriteFilterDomainSpecificFound) { ++ GetRewriteFiltersReturns({"about::blank/generic"}, FilterCategory::Blocking); ++ GetRewriteFiltersReturns({}, FilterCategory::Allowing); ++ ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Document); ++ FindBySpecialFilterReturns(absl::optional(kSourceUrl), ++ SpecialFilterType::Genericblock); ++ GetRewriteFiltersReturns({"about::blank/domain_specific"}, ++ FilterCategory::DomainSpecificBlocking); ++ ++ EXPECT_EQ(absl::optional{GURL("about::blank/domain_specific")}, ++ classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, ++ RewriteBlockingFilterOverruledViaDocumentAllowingRule) { ++ GetRewriteFiltersReturns({"about::blank"}, FilterCategory::Blocking); ++ ++ FindBySpecialFilterReturns(absl::optional(kSourceUrl), ++ SpecialFilterType::Document); ++ AssertFindBySpecialFilterNotCalled(SpecialFilterType::Genericblock); ++ ++ // Empty result means no redirect necessary. ++ EXPECT_FALSE(classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, ++ RewriteBlockingFilterOverruledViaOtherRewriteFilter) { ++ GetRewriteFiltersReturns({"about::blank"}, FilterCategory::Blocking); ++ ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Document); ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Genericblock); ++ ++ GetRewriteFiltersReturns({"about::blank_not_matching", "about::blank"}, ++ FilterCategory::Allowing); ++ ++ // Empty result means no redirect necessary. ++ EXPECT_FALSE(classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); ++} ++ ++TEST_F(AdblockResourceClassifierImplTest, ++ TwoConfigs_RewriteFilterFound_OtherConfigNotChecked) { ++ // Default configuration has blocking rewrite filter. ++ base::StringPiece redirect = "about::blank"; ++ ++ GetRewriteFiltersReturns({redirect}, FilterCategory::Blocking); ++ GetRewriteFiltersReturns({}, FilterCategory::Allowing); ++ ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Document); ++ FindBySpecialFilterReturns(absl::nullopt, SpecialFilterType::Genericblock); ++ ++ // Other configuration should not be called ++ auto mock_subscription_collection = ++ std::make_unique(); ++ EXPECT_CALL(*mock_subscription_collection, GetRewriteFilters(_, _, _)) ++ .Times(0); ++ ++ mock_snapshot_->push_back(std::move(mock_subscription_collection)); ++ EXPECT_EQ(GURL{redirect}, ++ classifier_->CheckRewrite(std::move(*mock_snapshot_), ++ kResourceAddress, {kParentAddress})); +} + +} // namespace adblock @@ -24065,7 +11691,7 @@ new file mode 100644 + absl::get>(converter_result)), + Subscription::InstallationState::Installed, base::Time())); + } -+ return std::make_unique(state); ++ return std::make_unique(state, ""); + } + + static std::string ReadFromTestData(const std::string& file_name) { @@ -24246,7 +11872,7 @@ diff --git a/components/adblock/core/common/BUILD.gn b/components/adblock/core/c new file mode 100644 --- /dev/null +++ b/components/adblock/core/common/BUILD.gn -@@ -0,0 +1,98 @@ +@@ -0,0 +1,110 @@ +# +# This file is part of eyeo Chromium SDK, +# Copyright (C) 2006-present eyeo GmbH @@ -24265,7 +11891,19 @@ new file mode 100644 + +import("//components/adblock/features.gni") + ++config("eyeo_filtering_config") { ++ defines = [] ++ ++ if (eyeo_disable_filtering_by_default) { ++ defines += [ "EYEO_DISABLE_FILTERING_BY_DEFAULT=true" ] ++ } else { ++ defines += [ "EYEO_DISABLE_FILTERING_BY_DEFAULT=false" ] ++ } ++} ++ +source_set("common") { ++ configs += [ ":eyeo_filtering_config" ] ++ + sources = [ + "adblock_constants.cc", + "adblock_constants.h", @@ -24349,7 +11987,7 @@ diff --git a/components/adblock/core/common/adblock_constants.cc b/components/ad new file mode 100644 --- /dev/null +++ b/components/adblock/core/common/adblock_constants.cc -@@ -0,0 +1,154 @@ +@@ -0,0 +1,164 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -24503,12 +12141,22 @@ new file mode 100644 + } +} + ++bool g_eyeo_disable_filtering_by_default = EYEO_DISABLE_FILTERING_BY_DEFAULT; ++ ++bool IsEyeoFilteringDisabledByDefault() { ++ return g_eyeo_disable_filtering_by_default; ++} ++ ++base::AutoReset OverrideEyeoFilteringDisabledByDefault(bool val) { ++ return base::AutoReset(&g_eyeo_disable_filtering_by_default, val); ++} ++ +} // namespace adblock diff --git a/components/adblock/core/common/adblock_constants.h b/components/adblock/core/common/adblock_constants.h new file mode 100644 --- /dev/null +++ b/components/adblock/core/common/adblock_constants.h -@@ -0,0 +1,41 @@ +@@ -0,0 +1,48 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -24529,6 +12177,7 @@ new file mode 100644 +#ifndef COMPONENTS_ADBLOCK_CORE_COMMON_ADBLOCK_CONSTANTS_H_ +#define COMPONENTS_ADBLOCK_CORE_COMMON_ADBLOCK_CONSTANTS_H_ + ++#include "base/auto_reset.h" +#include "base/strings/string_piece.h" +#include "url/gurl.h" + @@ -24547,6 +12196,12 @@ new file mode 100644 +const GURL& CustomFiltersUrl(); +base::StringPiece RewriteUrl(flat::AbpResource type); + ++bool IsEyeoFilteringDisabledByDefault(); ++ ++// Override result of IsEyeoFilteringDisabledByDefault() for the ++// duration of the returned AutoReset's lifetime. Used for testing. ++base::AutoReset OverrideEyeoFilteringDisabledByDefault(bool val); ++ +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CORE_COMMON_ADBLOCK_CONSTANTS_H_ @@ -24577,7 +12232,7 @@ new file mode 100644 +#include "base/logging.h" +#include "components/prefs/pref_registry_simple.h" + -+namespace adblock::prefs { ++namespace adblock::common::prefs { + +// Whether to block ads +const char kEnableAdblockLegacy[] = "adblock.enable"; @@ -24676,7 +12331,7 @@ new file mode 100644 + VLOG(3) << "[eyeo] Registered prefs"; +} + -+} // namespace adblock::prefs ++} // namespace adblock::common::prefs diff --git a/components/adblock/core/common/adblock_prefs.h b/components/adblock/core/common/adblock_prefs.h new file mode 100644 --- /dev/null @@ -24704,7 +12359,7 @@ new file mode 100644 + +class PrefRegistrySimple; + -+namespace adblock::prefs { ++namespace adblock::common::prefs { + +extern const char kEnableAdblockLegacy[]; +extern const char kEnableAcceptableAdsLegacy[]; @@ -24725,7 +12380,7 @@ new file mode 100644 + +void RegisterProfilePrefs(PrefRegistrySimple* registry); + -+} // namespace adblock::prefs ++} // namespace adblock::common::prefs + +#endif // COMPONENTS_ADBLOCK_CORE_COMMON_ADBLOCK_PREFS_H_ diff --git a/components/adblock/core/common/adblock_utils.cc b/components/adblock/core/common/adblock_utils.cc @@ -25687,7 +13342,7 @@ diff --git a/components/adblock/core/configuration/BUILD.gn b/components/adblock new file mode 100644 --- /dev/null +++ b/components/adblock/core/configuration/BUILD.gn -@@ -0,0 +1,57 @@ +@@ -0,0 +1,59 @@ +# +# This file is part of eyeo Chromium SDK, +# Copyright (C) 2006-present eyeo GmbH @@ -25706,6 +13361,8 @@ new file mode 100644 + +source_set("configuration") { + sources = [ ++ "filtering_configuration_prefs.cc", ++ "filtering_configuration_prefs.h", + "filtering_configuration.h", + "persistent_filtering_configuration.cc", + "persistent_filtering_configuration.h", @@ -25840,11 +13497,84 @@ new file mode 100644 +} // namespace adblock + +#endif // COMPONENTS_ADBLOCK_CORE_CONFIGURATION_FILTERING_CONFIGURATION_H_ +diff --git a/components/adblock/core/configuration/filtering_configuration_prefs.cc b/components/adblock/core/configuration/filtering_configuration_prefs.cc +new file mode 100644 +--- /dev/null ++++ b/components/adblock/core/configuration/filtering_configuration_prefs.cc +@@ -0,0 +1,33 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "components/adblock/core/configuration/filtering_configuration_prefs.h" ++ ++#include "base/logging.h" ++#include "components/prefs/pref_registry_simple.h" ++ ++namespace adblock::filtering_configuration::prefs { ++ ++const char kConfigurationsPrefsPath[] = "filtering.configurations"; ++ ++void RegisterProfilePrefs(PrefRegistrySimple* registry) { ++ registry->RegisterDictionaryPref(kConfigurationsPrefsPath); ++ ++ VLOG(3) << "[eyeo] Registered prefs"; ++} ++ ++} // namespace adblock::filtering_configuration::prefs +diff --git a/components/adblock/core/configuration/filtering_configuration_prefs.h b/components/adblock/core/configuration/filtering_configuration_prefs.h +new file mode 100644 +--- /dev/null ++++ b/components/adblock/core/configuration/filtering_configuration_prefs.h +@@ -0,0 +1,30 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef COMPONENTS_ADBLOCK_CORE_CONFIGURATION_FILTERING_CONFIGURATION_PREFS_H_ ++#define COMPONENTS_ADBLOCK_CORE_CONFIGURATION_FILTERING_CONFIGURATION_PREFS_H_ ++class PrefRegistrySimple; ++ ++namespace adblock::filtering_configuration::prefs { ++ ++extern const char kConfigurationsPrefsPath[]; ++ ++void RegisterProfilePrefs(PrefRegistrySimple* registry); ++ ++} // namespace adblock::filtering_configuration::prefs ++ ++#endif // COMPONENTS_ADBLOCK_CORE_CONFIGURATION_FILTERING_CONFIGURATION_PREFS_H_ diff --git a/components/adblock/core/configuration/persistent_filtering_configuration.cc b/components/adblock/core/configuration/persistent_filtering_configuration.cc new file mode 100644 --- /dev/null +++ b/components/adblock/core/configuration/persistent_filtering_configuration.cc -@@ -0,0 +1,241 @@ +@@ -0,0 +1,270 @@ + +/* + * This file is part of eyeo Chromium SDK, @@ -25869,57 +13599,57 @@ new file mode 100644 + +#include "base/strings/string_piece_forward.h" +#include "base/strings/string_util.h" ++#include "components/adblock/core/configuration/filtering_configuration_prefs.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" + ++#include "base/logging.h" ++ +namespace adblock { +namespace { + -+constexpr auto kConfigurationsPrefsPath = -+ base::StringPiece("filtering.configurations"); +constexpr auto kEnabledKey = base::StringPiece("enabled"); +constexpr auto kDomainsKey = base::StringPiece("domains"); +constexpr auto kCustomFiltersKey = base::StringPiece("filters"); +constexpr auto kFilterListsKey = base::StringPiece("subscriptions"); + -+base::Value ReadFromPrefs(PrefService* pref_service, -+ base::StringPiece configuration_name) { ++base::Value::Dict ReadFromPrefs(PrefService* pref_service, ++ base::StringPiece configuration_name) { + const auto& all_configurations = -+ pref_service->GetValue(kConfigurationsPrefsPath); -+ DCHECK(all_configurations.is_dict()); -+ const auto* this_config = -+ all_configurations.GetIfDict()->FindDict(configuration_name); ++ pref_service ++ ->GetValue(filtering_configuration::prefs::kConfigurationsPrefsPath) ++ .GetDict(); ++ const auto* this_config = all_configurations.FindDict(configuration_name); + if (this_config) { -+ return base::Value(this_config->Clone()); ++ return base::Value::Dict(this_config->Clone()); + } -+ return base::Value{base::Value::Type::DICT}; ++ return base::Value::Dict(); +} + -+void StoreToPrefs(const base::Value& configuration, ++void StoreToPrefs(const base::Value::Dict& configuration, + PrefService* pref_service, + base::StringPiece configuration_name) { + // ScopedDictPrefUpdate requires an std::string for some reason: -+ static std::string kConfigurationsPrefsPathString(kConfigurationsPrefsPath); ++ static std::string kConfigurationsPrefsPathString( ++ filtering_configuration::prefs::kConfigurationsPrefsPath); + ScopedDictPrefUpdate update(pref_service, kConfigurationsPrefsPathString); + update.Get().Set(configuration_name, configuration.Clone()); +} + -+void SetDefaultValuesIfNeeded(base::Value& configuration) { -+ DCHECK(configuration.is_dict()); -+ auto& dict = configuration.GetDict(); -+ if (!dict.FindBool(kEnabledKey)) { -+ dict.Set(kEnabledKey, true); ++void SetDefaultValuesIfNeeded(base::Value::Dict& configuration) { ++ if (!configuration.FindBool(kEnabledKey)) { ++ configuration.Set(kEnabledKey, true); + } -+ dict.EnsureList(kDomainsKey); -+ dict.EnsureList(kCustomFiltersKey); -+ dict.EnsureList(kFilterListsKey); ++ configuration.EnsureList(kDomainsKey); ++ configuration.EnsureList(kCustomFiltersKey); ++ configuration.EnsureList(kFilterListsKey); +} + -+bool AppendToList(base::Value& configuration, ++bool AppendToList(base::Value::Dict& configuration, + base::StringPiece key, + const std::string& value) { -+ DCHECK(configuration.GetDict().FindList(key)); // see SetDefaultValuesIfNeeded(). -+ base::Value::List* list = configuration.GetDict().FindList(key); ++ DCHECK(configuration.FindList(key)); // see SetDefaultValuesIfNeeded(). ++ auto* list = configuration.FindList(key); + if (base::ranges::find(*list, base::Value(value)) != list->end()) { + // value already exists in the list. + return false; @@ -25928,11 +13658,11 @@ new file mode 100644 + return true; +} + -+bool RemoveFromList(base::Value& configuration, ++bool RemoveFromList(base::Value::Dict& configuration, + base::StringPiece key, + const std::string& value) { -+ DCHECK(configuration.GetDict().FindList(key)); // see SetDefaultValuesIfNeeded(). -+ base::Value::List* list = configuration.GetDict().FindList(key); ++ DCHECK(configuration.FindList(key)); // see SetDefaultValuesIfNeeded(). ++ auto* list = configuration.FindList(key); + auto it = base::ranges::find(*list, base::Value(value)); + if (it == list->end()) { + // value was not on the list. @@ -25943,10 +13673,10 @@ new file mode 100644 +} + +template -+std::vector GetFromList(const base::Value& configuration, ++std::vector GetFromList(const base::Value::Dict& configuration, + base::StringPiece key) { -+ DCHECK(configuration.GetDict().FindList(key)); // see SetDefaultValuesIfNeeded(). -+ const base::Value::List* list = configuration.GetDict().FindList(key); ++ DCHECK(configuration.FindList(key)); // see SetDefaultValuesIfNeeded(). ++ const auto* list = configuration.FindList(key); + std::vector result; + for (const auto& value : *list) { + if (value.is_string()) { @@ -25965,6 +13695,7 @@ new file mode 100644 + name_(std::move(name)), + dictionary_(ReadFromPrefs(pref_service_, name_)) { + SetDefaultValuesIfNeeded(dictionary_); ++ PersistToPrefs(); +} + +PersistentFilteringConfiguration::~PersistentFilteringConfiguration() = default; @@ -25984,13 +13715,13 @@ new file mode 100644 + if (IsEnabled() == enabled) { + return; + } -+ dictionary_.GetDict().Set(kEnabledKey, enabled); ++ dictionary_.Set(kEnabledKey, enabled); + PersistToPrefs(); + NotifyEnabledStateChanged(); +} + +bool PersistentFilteringConfiguration::IsEnabled() const { -+ const auto pref_value = dictionary_.GetDict().FindBool(kEnabledKey); ++ const auto pref_value = dictionary_.FindBool(kEnabledKey); + DCHECK(pref_value); + return *pref_value; +} @@ -26082,7 +13813,35 @@ new file mode 100644 +// static +void PersistentFilteringConfiguration::RegisterProfilePrefs( + PrefRegistrySimple* registry) { -+ registry->RegisterDictionaryPref(std::string(kConfigurationsPrefsPath)); ++ registry->RegisterDictionaryPref( ++ std::string(filtering_configuration::prefs::kConfigurationsPrefsPath)); ++} ++ ++// static ++std::vector> ++PersistentFilteringConfiguration::GetPersistedConfigurations( ++ PrefService* pref_service) { ++ std::vector> configs; ++ const auto& all_configurations = ++ pref_service ++ ->GetValue(filtering_configuration::prefs::kConfigurationsPrefsPath) ++ .GetDict(); ++ for (auto it = all_configurations.begin(); it != all_configurations.end(); ++ ++it) { ++ configs.push_back(std::make_unique( ++ pref_service, (it->first))); ++ } ++ return configs; ++} ++ ++// static ++void PersistentFilteringConfiguration::RemovePersistedData( ++ PrefService* pref_service, ++ const std::string& name) { ++ static std::string kConfigurationsPrefsPathString( ++ filtering_configuration::prefs::kConfigurationsPrefsPath); ++ ScopedDictPrefUpdate update(pref_service, kConfigurationsPrefsPathString); ++ update.Get().Remove(name); +} + +} // namespace adblock @@ -26090,7 +13849,7 @@ diff --git a/components/adblock/core/configuration/persistent_filtering_configur new file mode 100644 --- /dev/null +++ b/components/adblock/core/configuration/persistent_filtering_configuration.h -@@ -0,0 +1,81 @@ +@@ -0,0 +1,86 @@ + +/* + * This file is part of eyeo Chromium SDK, @@ -26156,6 +13915,11 @@ new file mode 100644 + + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + ++ static std::vector> ++ GetPersistedConfigurations(PrefService* pref_service); ++ static void RemovePersistedData(PrefService* pref_service, ++ const std::string& name); ++ + private: + void PersistToPrefs(); + void NotifyEnabledStateChanged(); @@ -26166,7 +13930,7 @@ new file mode 100644 + raw_ptr pref_service_; + std::string name_; + base::ObserverList observers_; -+ base::Value dictionary_; ++ base::Value::Dict dictionary_; +}; + +} // namespace adblock @@ -27615,7 +15379,7 @@ diff --git a/components/adblock/core/converter/parser/metadata.cc b/components/a new file mode 100644 --- /dev/null +++ b/components/adblock/core/converter/parser/metadata.cc -@@ -0,0 +1,143 @@ +@@ -0,0 +1,145 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -27636,6 +15400,7 @@ new file mode 100644 +#include "components/adblock/core/converter/parser/metadata.h" + +#include "base/logging.h" ++#include "base/ranges/algorithm.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "third_party/re2/src/re2/re2.h" @@ -27753,9 +15518,10 @@ new file mode 100644 + << kDefaultExpirationInterval.InDays() << " days."; + return kDefaultExpirationInterval; + } -+ return std::clamp(expiration_unit == "h" ? base::Hours(expiration_time) -+ : base::Days(expiration_time), -+ kMinExpirationInterval, kMaxExpirationInterval); ++ return base::ranges::clamp(expiration_unit == "h" ++ ? base::Hours(expiration_time) ++ : base::Days(expiration_time), ++ kMinExpirationInterval, kMaxExpirationInterval); +} + +} // namespace adblock @@ -29290,7 +17056,7 @@ diff --git a/components/adblock/core/converter/parser/url_filter.cc b/components new file mode 100644 --- /dev/null +++ b/components/adblock/core/converter/parser/url_filter.cc -@@ -0,0 +1,216 @@ +@@ -0,0 +1,218 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -29443,12 +17209,6 @@ new file mode 100644 + } + + if (options.has_value() && options->Rewrite().has_value()) { -+ if (options->Domains().GetIncludeDomains().empty()) { -+ VLOG(1) << "[eyeo] Rewrite filter must be restricted to at least one " -+ "domain using the domain filter option"; -+ return {}; -+ } -+ + if (options->ThirdParty() == + UrlFilterOptions::ThirdPartyOption::ThirdPartyOnly) { + VLOG(1) << "[eyeo] Rewrite filter must not be used together with the " @@ -29462,6 +17222,14 @@ new file mode 100644 + "or start with a domain anchor double pipe (||)"; + return {}; + } ++ ++ if (options->Domains().GetIncludeDomains().empty() && ++ options->ThirdParty() == UrlFilterOptions::ThirdPartyOption::Ignore) { ++ VLOG(1) << "[eyeo] Rewrite filter must be restricted to at least one " ++ "domain using the domain filter option or have ~third-party " ++ "option"; ++ return {}; ++ } + } + + if (IsGenericFilterIsNotSpecificEnough(filter_str, options)) { @@ -30146,7 +17914,7 @@ diff --git a/components/adblock/core/converter/serializer/flatbuffer_serializer. new file mode 100644 --- /dev/null +++ b/components/adblock/core/converter/serializer/flatbuffer_serializer.cc -@@ -0,0 +1,396 @@ +@@ -0,0 +1,394 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -30241,7 +18009,6 @@ new file mode 100644 + ? builder_.CreateString(content_filter.selector.data(), + content_filter.selector.size()) + : builder_.CreateString(EscapeSelector(content_filter.selector)), -+ CreateVectorOfSharedStrings(content_filter.domains.GetIncludeDomains()), + CreateVectorOfSharedStrings(content_filter.domains.GetExcludeDomains())); + + // Insert the filter under the correct index. @@ -30282,7 +18049,6 @@ new file mode 100644 + + auto offset = flat::CreateSnippetFilter( + builder_, {}, -+ CreateVectorOfSharedStrings(snippet_filter.domains.GetIncludeDomains()), + CreateVectorOfSharedStrings(snippet_filter.domains.GetExcludeDomains()), + builder_.CreateVector(offsets)); + AddSnippetFilterForDomains( @@ -30869,7 +18635,7 @@ diff --git a/components/adblock/core/converter/test/flatbuffer_converter_test.cc new file mode 100644 --- /dev/null +++ b/components/adblock/core/converter/test/flatbuffer_converter_test.cc -@@ -0,0 +1,2346 @@ +@@ -0,0 +1,2476 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -31465,8 +19231,6 @@ new file mode 100644 + EXPECT_EQ(entry->domain()->str(), "test.com"); + + auto* snippet = entry->filter()->Get(0); -+ ASSERT_EQ(snippet->include_domains()->size(), 1u); -+ EXPECT_EQ(snippet->include_domains()->Get(0)->str(), "test.com"); + ASSERT_EQ(snippet->exclude_domains()->size(), 1u); + EXPECT_EQ(snippet->exclude_domains()->Get(0)->str(), "other.test.com"); + EXPECT_EQ(snippet->script()->size(), 1u); @@ -31486,7 +19250,6 @@ new file mode 100644 + auto* entry = index.index_->snippet()->Get(0); + ASSERT_EQ(entry->filter()->size(), 1u); + auto* snippet = entry->filter()->Get(0); -+ ASSERT_EQ(snippet->include_domains()->size(), 1u); + + auto* call = snippet->script()->Get(0); + EXPECT_EQ(call->command()->str(), "log"); @@ -32778,23 +20541,73 @@ new file mode 100644 + EXPECT_TRUE(results.empty()); +} + -+TEST_F(AdblockFlatbufferConverterTest, RewriteValid) { ++TEST_F(AdblockFlatbufferConverterTest, RewriteEmpty) { ++ auto subscriptions = ConvertAndLoadRules(R"( ++ ||adform.net/banners/scripts/adx.js$domain=adform.net,rewrite= ++ ||adform.net/banners/scripts/adx.js$domain=adform.net,rewrite ++ )"); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.js"), ++ "adform.net", FilterCategory::Blocking) ++ .empty()); ++} ++ ++TEST_F(AdblockFlatbufferConverterTest, RewriteDomain) { + auto subscriptions = ConvertAndLoadRules(R"( + ||adform.net/banners/scripts/adx.css$domain=delfi.lt,rewrite=abp-resource:blank-css + )"); -+ EXPECT_EQ(subscriptions->FindRewriteFilter( -+ GURL("https://adform.net/banners/scripts/adx.css"), "delfi.lt", -+ FilterCategory::Blocking), ++ EXPECT_EQ(*subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "delfi.lt", FilterCategory::Blocking) ++ .begin(), ++ "data:text/css,"); ++ EXPECT_EQ(*subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "delfi.lt", FilterCategory::DomainSpecificBlocking) ++ .begin(), + "data:text/css,"); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteFirstParty) { + auto subscriptions = ConvertAndLoadRules(R"( ++ ||adform.net/banners/scripts/adx.css$rewrite=abp-resource:blank-css,~third-party ++ )"); ++ EXPECT_EQ(*subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "adform.net", FilterCategory::Blocking) ++ .begin(), ++ "data:text/css,"); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "adform.net", FilterCategory::DomainSpecificBlocking) ++ .empty()); ++} ++ ++TEST_F(AdblockFlatbufferConverterTest, RewriteFirstPartyDomainNotMatching) { ++ auto subscriptions = ConvertAndLoadRules(R"( ++ ||adform.net/banners/scripts/adx.css$rewrite=abp-resource:blank-css,~third-party ++ )"); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "example.com", FilterCategory::Blocking) ++ .empty()); ++} ++ ++TEST_F(AdblockFlatbufferConverterTest, RewriteFirstPartyAndDomain) { ++ auto subscriptions = ConvertAndLoadRules(R"( + ||adform.net/banners/scripts/adx.js$domain=adform.net,rewrite=abp-resource:blank-js,~third-party + )"); -+ EXPECT_EQ(subscriptions->FindRewriteFilter( -+ GURL("https://adform.net/banners/scripts/adx.js"), "adform.net", -+ FilterCategory::Blocking), ++ EXPECT_EQ(*subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.js"), ++ "adform.net", FilterCategory::Blocking) ++ .begin(), + "data:application/javascript,"); +} + @@ -32802,18 +20615,22 @@ new file mode 100644 + auto subscriptions = ConvertAndLoadRules(R"( + ||adform.net/banners/scripts/adx.js$domain=delfi.lt,rewrite=abp-resource:blank-xxx + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://adform.net/banners/scripts/adx.js"), "delfi.lt", -+ FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.js"), ++ "delfi.lt", FilterCategory::Blocking) ++ .empty()); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteWrongScheme) { + auto subscriptions = ConvertAndLoadRules(R"( + ||adform.net/banners/scripts/adx.js$domain=delfi.lt,rewrite=about::blank + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://adform.net/banners/scripts/adx.js"), "delfi.lt", -+ FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.js"), ++ "delfi.lt", FilterCategory::Blocking) ++ .empty()); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteStar) { @@ -32821,9 +20638,11 @@ new file mode 100644 + *$domain=delfi.lt,rewrite=abp-resource:blank-html + )"); + EXPECT_EQ( -+ subscriptions->FindRewriteFilter( -+ GURL("https://adform.net/banners/scripts/adx.html"), "delfi.lt", -+ FilterCategory::Blocking), ++ *subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.html"), "delfi.lt", ++ FilterCategory::Blocking) ++ .begin(), + "data:text/html,"); +} + @@ -32831,32 +20650,52 @@ new file mode 100644 + auto subscriptions = ConvertAndLoadRules(R"( + *test.com$domain=delfi.lt,rewrite=abp-resource:blank-html + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://test.com/ad.html"), "delfi.lt", FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters(GURL("https://test.com/ad.html"), ++ "delfi.lt", FilterCategory::Blocking) ++ .empty()); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteStrict) { + auto subscriptions = ConvertAndLoadRules(R"( + test.com$domain=delfi.lt,rewrite=abp-resource:blank-html + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://test.com/ad.html"), "delfi.lt", FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters(GURL("https://test.com/ad.html"), ++ "delfi.lt", FilterCategory::Blocking) ++ .empty()); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteNoDomain) { + auto subscriptions = ConvertAndLoadRules(R"( + ||test.com$rewrite=abp-resource:blank-html + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://test.com/ad.html"), "test.com", FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters(GURL("https://test.com/ad.html"), ++ "test.com", FilterCategory::Blocking) ++ .empty()); +} + +TEST_F(AdblockFlatbufferConverterTest, RewriteExcludeDomain) { + auto subscriptions = ConvertAndLoadRules(R"( + ||test.com$domain=~delfi.lt,rewrite=abp-resource:blank-html + )"); -+ EXPECT_FALSE(subscriptions->FindRewriteFilter( -+ GURL("https://test.com/ad.html"), "test.com", FilterCategory::Blocking)); ++ EXPECT_TRUE(subscriptions ++ ->FindRewriteFilters(GURL("https://test.com/ad.html"), ++ "test.com", FilterCategory::Blocking) ++ .empty()); ++} ++ ++TEST_F(AdblockFlatbufferConverterTest, RewriteAllowedFilter) { ++ auto subscriptions = ConvertAndLoadRules(R"( ++ @@||adform.net/banners/scripts/adx.css$domain=delfi.lt,rewrite=abp-resource:blank-css ++ )"); ++ EXPECT_EQ(*subscriptions ++ ->FindRewriteFilters( ++ GURL("https://adform.net/banners/scripts/adx.css"), ++ "delfi.lt", FilterCategory::Allowing) ++ .begin(), ++ "data:text/css,"); +} + +TEST_F(AdblockFlatbufferConverterTest, HeaderFilterIgnoredForNonpriviledged) { @@ -33209,7 +21048,64 @@ new file mode 100644 +TEST_F(AdblockFlatbufferConverterTest, InvalidFilterDoesNotCrashParser) { + auto subscription = ConvertAndLoadRules(R"( + || ++ | + )"); ++ // Filters are too short and were rejected by parser. ++ EXPECT_FALSE(subscription->HasUrlFilter( ++ GURL("http://example.com/content.jpg"), "example.com", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++} ++ ++// See DPD-1978 ++TEST_F(AdblockFlatbufferConverterTest, DomainSpecificSinglePipe) { ++ auto subscription = ConvertAndLoadRules(R"( ++ |$domain=example.com ++ )"); ++ EXPECT_TRUE(subscription->HasUrlFilter(GURL("http://example.com/content.jpg"), ++ "example.com", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++ EXPECT_FALSE(subscription->HasUrlFilter( ++ GURL("http://example.com/content.jpg"), "example.net", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++} ++ ++// See DPD-1978 ++TEST_F(AdblockFlatbufferConverterTest, DomainSpecificSinglePipeWithWildcard) { ++ auto subscription = ConvertAndLoadRules(R"( ++ |*$domain=example.com ++ )"); ++ EXPECT_TRUE(subscription->HasUrlFilter(GURL("http://example.com/content.jpg"), ++ "example.com", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++ EXPECT_FALSE(subscription->HasUrlFilter( ++ GURL("http://example.com/content.jpg"), "example.net", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++} ++ ++// See DPD-1978 ++TEST_F(AdblockFlatbufferConverterTest, DomainSpecificDoublePipe) { ++ auto subscription = ConvertAndLoadRules(R"( ++ ||$domain=example.com ++ )"); ++ EXPECT_TRUE(subscription->HasUrlFilter(GURL("http://example.com/content.jpg"), ++ "example.com", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++ EXPECT_FALSE(subscription->HasUrlFilter( ++ GURL("http://example.com/content.jpg"), "example.net", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++} ++ ++// See DPD-1978 ++TEST_F(AdblockFlatbufferConverterTest, DomainSpecificDoublePipeWithWildcard) { ++ auto subscription = ConvertAndLoadRules(R"( ++ ||*$domain=example.com ++ )"); ++ EXPECT_TRUE(subscription->HasUrlFilter(GURL("http://example.com/content.jpg"), ++ "example.com", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); ++ EXPECT_FALSE(subscription->HasUrlFilter( ++ GURL("http://example.com/content.jpg"), "example.net", ContentType::Image, ++ SiteKey(), FilterCategory::Blocking)); +} + +// TODO(mpawlowski) support multiple CSP filters per URL + frame hierarchy: @@ -33286,7 +21182,7 @@ diff --git a/components/adblock/core/schema/filter_list_schema.fbs b/components/ new file mode 100644 --- /dev/null +++ b/components/adblock/core/schema/filter_list_schema.fbs -@@ -0,0 +1,167 @@ +@@ -0,0 +1,165 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -33377,7 +21273,6 @@ new file mode 100644 +table ElemHideFilter { + filter_text: string; + selector: string (required); -+ include_domains: [string]; + exclude_domains: [string]; +} + @@ -33388,7 +21283,6 @@ new file mode 100644 + +table SnippetFilter { + filter_text: string; -+ include_domains: [string]; + exclude_domains: [string]; + script: [SnippetFunctionCall]; +} @@ -34174,7 +22068,7 @@ diff --git a/components/adblock/core/subscription/filtering_configuration_mainta new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc -@@ -0,0 +1,485 @@ +@@ -0,0 +1,489 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -34271,7 +22165,8 @@ new file mode 100644 + std::back_inserter(state)); + VLOG(2) << "[eyeo] FilteringConfiguration " << configuration_->GetName() + << " produces " << state.size() << " subscriptions for Snapshot"; -+ return std::make_unique(state); ++ return std::make_unique( ++ state, configuration_->GetName()); +} + +std::vector> @@ -34354,6 +22249,9 @@ new file mode 100644 + auto demanded_subscriptions = configuration_->GetFilterLists(); + base::ranges::sort(installed_subscriptions); + base::ranges::sort(demanded_subscriptions); ++ installed_subscriptions.erase(std::unique(installed_subscriptions.begin(), ++ installed_subscriptions.end()), ++ installed_subscriptions.end()); + // Unneeded subscriptions is the difference between the two: + std::vector unneeded_subscriptions; + base::ranges::set_difference(installed_subscriptions, demanded_subscriptions, @@ -34939,8 +22837,8 @@ new file mode 100644 + const std::string& document_domain, + FilterCategory category, + std::set& results) const = 0; -+ // Find an URL to rewrite if any for specific request -+ virtual absl::optional FindRewriteFilter( ++ // Find all rewrite filters matching category. ++ virtual std::set FindRewriteFilters( + const GURL& url, + const std::string& document_domain, + FilterCategory category) const = 0; @@ -34978,7 +22876,7 @@ diff --git a/components/adblock/core/subscription/installed_subscription_impl.cc new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/installed_subscription_impl.cc -@@ -0,0 +1,569 @@ +@@ -0,0 +1,552 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -35152,27 +23050,19 @@ new file mode 100644 + } +} + -+absl::optional InstalledSubscriptionImpl::FindRewriteFilter( ++std::set InstalledSubscriptionImpl::FindRewriteFilters( + const GURL& url, + const std::string& document_domain, + FilterCategory category) const { -+ auto filters = FindInternal(category != FilterCategory::Allowing -+ ? index_->url_rewrite_block() -+ : index_->url_rewrite_allow(), -+ url, absl::nullopt, document_domain, "", category, -+ FindStrategy::FindFirst); -+ if (filters.empty()) { -+ return absl::nullopt; ++ std::set result; ++ for (auto* filter : FindInternal(category != FilterCategory::Allowing ++ ? index_->url_rewrite_block() ++ : index_->url_rewrite_allow(), ++ url, absl::nullopt, document_domain, "", ++ category, FindStrategy::FindAll)) { ++ result.insert(RewriteUrl(filter->rewrite()->replace_with())); + } -+ const auto* filter = filters[0]; -+ DCHECK(category == FilterCategory::Allowing || filter->rewrite()) -+ << "Blocking rewrite filter must contain payload"; -+ if (filter->rewrite()) { -+ auto new_url = RewriteUrl(filter->rewrite()->replace_with()); -+ DCHECK(!new_url.empty()); -+ return new_url; -+ } -+ return absl::nullopt; ++ return result; +} + +void InstalledSubscriptionImpl::FindHeaderFilters( @@ -35233,14 +23123,6 @@ new file mode 100644 + + std::vector selectors; + for (auto* filter : *category->filter()) { -+ const bool filter_allowed_by_includes = -+ // No include domains, filter is generic: -+ filter->include_domains()->size() == 0 || -+ // Or include domains contain |domain| or one of its subdomains: -+ DomainOnList(domain, filter->include_domains()); -+ if (!filter_allowed_by_includes) { -+ continue; -+ } + const bool filter_disallowed_by_excludes = + // Some exclusions apply on this domain: + filter->exclude_domains()->size() > 0 && @@ -35522,8 +23404,7 @@ new file mode 100644 + } + + for (const auto* cur : (*idx->filter())) { -+ if (IsActiveOnDomain(document_domain, cur->include_domains(), -+ cur->exclude_domains())) { ++ if (IsActiveOnDomain(document_domain, nullptr, cur->exclude_domains())) { + for (const auto* line : (*cur->script())) { + InstalledSubscription::Snippet obj; + obj.command = base::StringPiece(line->command()->c_str(), @@ -35620,7 +23501,7 @@ new file mode 100644 + const std::string& document_domain, + FilterCategory category, + std::set& results) const final; -+ absl::optional FindRewriteFilter( ++ std::set FindRewriteFilters( + const GURL& url, + const std::string& document_domain, + FilterCategory category) const final; @@ -36038,7 +23919,7 @@ diff --git a/components/adblock/core/subscription/pattern_matcher.cc b/component new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/pattern_matcher.cc -@@ -0,0 +1,261 @@ +@@ -0,0 +1,266 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -36277,10 +24158,15 @@ new file mode 100644 + { + // If the next token is *, we discard the start-from-host anchor, behave + // as if the filter started from * -+ auto wildcard_tokenizer = tokenizer; -+ const auto wildcard_token = wildcard_tokenizer.NextToken(); -+ if (wildcard_token == "*") { -+ return FindNextTokenInInput(input, wildcard_tokenizer, 0).has_value(); ++ auto empty_or_wildcard_tokenizer = tokenizer; ++ const auto token = empty_or_wildcard_tokenizer.NextToken(); ++ if (token == "*") { ++ return FindNextTokenInInput(input, empty_or_wildcard_tokenizer, 0) ++ .has_value(); ++ } ++ // If the next token is empty we have a filter "||" matching any domain. ++ if (token.empty()) { ++ return true; + } + } + const auto skipped_characters = FindNextTokenInInput(input, tokenizer, 0); @@ -36946,7 +24832,7 @@ diff --git a/components/adblock/core/subscription/subscription_collection.h b/co new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_collection.h -@@ -0,0 +1,95 @@ +@@ -0,0 +1,99 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -36991,6 +24877,9 @@ new file mode 100644 + public: + virtual ~SubscriptionCollection() = default; + ++ // Name of the FilteringConfiguration this collection represents ++ virtual const std::string& GetFilteringConfigurationName() const = 0; ++ + virtual absl::optional FindBySubresourceFilter( + const GURL& request_url, + const std::vector& frame_hierarchy, @@ -37028,9 +24917,10 @@ new file mode 100644 + const GURL& request_url, + const std::vector& frame_hierarchy) const = 0; + -+ virtual absl::optional GetRewriteUrl( ++ virtual std::set GetRewriteFilters( + const GURL& request_url, -+ const std::vector& frame_hierarchy) const = 0; ++ const std::vector& frame_hierarchy, ++ FilterCategory category) const = 0; + + virtual std::set GetHeaderFilters( + const GURL& request_url, @@ -37046,7 +24936,7 @@ diff --git a/components/adblock/core/subscription/subscription_collection_impl.c new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_collection_impl.cc -@@ -0,0 +1,437 @@ +@@ -0,0 +1,353 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -37102,53 +24992,6 @@ new file mode 100644 + return final_selectors; +} + -+using GenericGetter = absl::optional ( -+ InstalledSubscription::*)(const GURL&, -+ const std::string&, -+ FilterCategory) const; -+ -+bool IsFilterOverruled(base::StringPiece blocking, -+ const InstalledSubscription& subscription, -+ const GURL& request_url, -+ const std::string& request_domain, -+ GenericGetter getter) { -+ auto allowing = (subscription.*getter)(request_url, request_domain, -+ FilterCategory::Allowing); -+ if (!allowing) { -+ return false; -+ } -+ return allowing->empty() || *allowing == blocking; -+} -+ -+bool GenericHasAllowingFilter(const InstalledSubscription& subscription, -+ const base::StringPiece blocking, -+ const GURL& request_url, -+ const std::vector& frame_hierarchy, -+ GenericGetter getter) { -+ const auto request_domain = DocumentDomain(request_url, frame_hierarchy); -+ // There may exist an allowing rule for this request and its immediate -+ // parent frame. We also check for document-wide allowing filters. -+ if (IsFilterOverruled(blocking, subscription, request_url, request_domain, -+ getter) || -+ subscription.HasSpecialFilter(SpecialFilterType::Document, request_url, -+ request_domain, SiteKey())) { -+ return true; -+ } -+ // For parent frames, we only match document-wide allowing filters. Parent -+ // frames' allowing rules don't propagate to child frames. -+ for (auto it = frame_hierarchy.begin(); it < frame_hierarchy.end(); ++it) { -+ const GURL& current_url = *it; -+ const std::string& current_domain = std::next(it) != frame_hierarchy.end() -+ ? std::next(it)->host() -+ : current_url.host(); -+ if (subscription.HasSpecialFilter(SpecialFilterType::Document, current_url, -+ current_domain, SiteKey())) { -+ return true; -+ } -+ } -+ return false; -+} -+ +bool SubscriptionContainsSpecialFilter( + const scoped_refptr subscription, + SpecialFilterType filter_type, @@ -37201,61 +25044,14 @@ new file mode 100644 + frame_hierarchy, sitekey); +} + -+absl::optional GenericFindFilter( -+ const std::vector>& subscriptions, -+ const GURL& request_url, -+ const std::vector& frame_hierarchy, -+ GenericGetter getter) { -+ for (const auto& subscription : subscriptions) { -+ // Is there a blocking filter in this subscription? -+ const auto blocking = (*subscription.*getter)( -+ request_url, DocumentDomain(request_url, frame_hierarchy), -+ FilterCategory::Blocking); -+ if (!blocking) { -+ // There are no blocking filters in this subscription, check next one. -+ continue; -+ } -+ // There may be an allowing rule for the entire document or an allowing // -+ // filter in one of the subscriptions: -+ if (base::ranges::any_of(subscriptions, [&](const auto& sub) { -+ return GenericHasAllowingFilter(*sub, *blocking, request_url, -+ frame_hierarchy, getter); -+ })) { -+ continue; -+ } -+ // Last chance to avoid blocking: maybe there is a Genericblock filter and -+ // we should re-search for domain-specific filters only? -+ if (base::ranges::any_of(subscriptions, [&](const auto& sub) { -+ return HasSpecialFilter(sub, SpecialFilterType::Genericblock, -+ request_url, frame_hierarchy, SiteKey()); -+ })) { -+ // This is a relatively rare case - we should have searched for -+ // domain-specific filters only. -+ const auto domain_specific_blocking = (*subscription.*getter)( -+ request_url, DocumentDomain(request_url, frame_hierarchy), -+ FilterCategory::DomainSpecificBlocking); -+ if (domain_specific_blocking) { -+ // There is a domain-specific blocking filter. No point in -+ // searching for a domain-specific allowing filter, since the -+ // previous search for non-specific allowing filters would have found -+ // it. -+ return domain_specific_blocking; -+ } else { -+ // There are no domain-specific blocking filters in this -+ // subscription. -+ continue; -+ } -+ } -+ return blocking; -+ } -+ return absl::nullopt; -+} -+ +} // namespace + +SubscriptionCollectionImpl::SubscriptionCollectionImpl( -+ std::vector> current_state) -+ : subscriptions_(std::move(current_state)) {} ++ std::vector> current_state, ++ const std::string& configuration_name) ++ : subscriptions_(std::move(current_state)), ++ configuration_name_(configuration_name) {} ++ +SubscriptionCollectionImpl::~SubscriptionCollectionImpl() = default; +SubscriptionCollectionImpl::SubscriptionCollectionImpl( + const SubscriptionCollectionImpl&) = default; @@ -37266,6 +25062,11 @@ new file mode 100644 +SubscriptionCollectionImpl& SubscriptionCollectionImpl::operator=( + SubscriptionCollectionImpl&&) = default; + ++const std::string& SubscriptionCollectionImpl::GetFilteringConfigurationName() ++ const { ++ return configuration_name_; ++} ++ +absl::optional SubscriptionCollectionImpl::FindBySubresourceFilter( + const GURL& request_url, + const std::vector& frame_hierarchy, @@ -37404,7 +25205,7 @@ new file mode 100644 + return {}; + } + -+ // If blocking filters found, check if can be overuled by allowing filters. ++ // If blocking filters found, check if can be overruled by allowing filters. + for (const auto& subscription : subscriptions_) { + // There may exist an allowing rule for this request and its immediate + // parent frame. We also check for document-wide allowing filters. @@ -37417,7 +25218,7 @@ new file mode 100644 + FilterCategory::Allowing, allowing_filters); + } + -+ // Remove overrulled filters ++ // Remove overruled filters. + for (const auto& a_f : allowing_filters) { + if (a_f.empty()) { + return {}; @@ -37461,12 +25262,17 @@ new file mode 100644 + return blocking_filters; +} + -+absl::optional SubscriptionCollectionImpl::GetRewriteUrl( ++std::set SubscriptionCollectionImpl::GetRewriteFilters( + const GURL& request_url, -+ const std::vector& frame_hierarchy) const { -+ auto result = GenericFindFilter(subscriptions_, request_url, frame_hierarchy, -+ &InstalledSubscription::FindRewriteFilter); -+ return result ? absl::optional(GURL(*result)) : absl::nullopt; ++ const std::vector& frame_hierarchy, ++ FilterCategory category) const { ++ std::set result; ++ for (const auto& subscription : subscriptions_) { ++ const auto filters = subscription->FindRewriteFilters( ++ request_url, DocumentDomain(request_url, frame_hierarchy), category); ++ result.insert(filters.begin(), filters.end()); ++ } ++ return result; +} + +std::set SubscriptionCollectionImpl::GetHeaderFilters( @@ -37488,7 +25294,7 @@ diff --git a/components/adblock/core/subscription/subscription_collection_impl.h new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_collection_impl.h -@@ -0,0 +1,92 @@ +@@ -0,0 +1,97 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -37520,13 +25326,16 @@ new file mode 100644 +class SubscriptionCollectionImpl final : public SubscriptionCollection { + public: + explicit SubscriptionCollectionImpl( -+ std::vector> current_state); ++ std::vector> current_state, ++ const std::string& configuration_name); + ~SubscriptionCollectionImpl() final; + SubscriptionCollectionImpl(const SubscriptionCollectionImpl&); + SubscriptionCollectionImpl(SubscriptionCollectionImpl&&); + SubscriptionCollectionImpl& operator=(const SubscriptionCollectionImpl&); + SubscriptionCollectionImpl& operator=(SubscriptionCollectionImpl&&); + ++ const std::string& GetFilteringConfigurationName() const final; ++ + absl::optional FindBySubresourceFilter( + const GURL& request_url, + const std::vector& frame_hierarchy, @@ -37564,9 +25373,10 @@ new file mode 100644 + std::set GetCspInjections( + const GURL& request_url, + const std::vector& frame_hierarchy) const final; -+ absl::optional GetRewriteUrl( ++ std::set GetRewriteFilters( + const GURL& request_url, -+ const std::vector& frame_hierarchy) const final; ++ const std::vector& frame_hierarchy, ++ FilterCategory category) const final; + + std::set GetHeaderFilters( + const GURL& request_url, @@ -37576,6 +25386,7 @@ new file mode 100644 + + private: + std::vector> subscriptions_; ++ std::string configuration_name_; +}; + +} // namespace adblock @@ -38599,7 +26410,7 @@ diff --git a/components/adblock/core/subscription/subscription_persistent_metada new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_persistent_metadata_impl.cc -@@ -0,0 +1,170 @@ +@@ -0,0 +1,171 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -38745,11 +26556,12 @@ new file mode 100644 + subscription.Set(kErrorCountKey, pair.second.error_count); + dict.Set(pair.first.spec(), std::move(subscription)); + } -+ prefs_->SetDict(prefs::kSubscriptionMetadata, std::move(dict)); ++ prefs_->SetDict(common::prefs::kSubscriptionMetadata, std::move(dict)); +} + +void SubscriptionPersistentMetadataImpl::LoadFromPrefs() { -+ const base::Value& dict = prefs_->GetValue(prefs::kSubscriptionMetadata); ++ const base::Value& dict = ++ prefs_->GetValue(common::prefs::kSubscriptionMetadata); + DCHECK(dict.is_dict()); + for (const auto dict_item : dict.GetDict()) { + Metadata subscription; @@ -39225,7 +27037,7 @@ diff --git a/components/adblock/core/subscription/subscription_service.h b/compo new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_service.h -@@ -0,0 +1,79 @@ +@@ -0,0 +1,87 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -39247,6 +27059,7 @@ new file mode 100644 +#define COMPONENTS_ADBLOCK_CORE_SUBSCRIPTION_SUBSCRIPTION_SERVICE_H_ + +#include ++#include +#include + +#include "base/functional/callback.h" @@ -39285,6 +27098,13 @@ new file mode 100644 + // lists as needed. + virtual void InstallFilteringConfiguration( + std::unique_ptr configuration) = 0; ++ // Removes configuration from the list of known configurations and reset its ++ // all persistent data. Use it only when configuration is no longer needed, ++ // otherwise prefer to disable configuration via FilteringConfiguration API. ++ // IMPORTANT: After calling this method any pointer pointing to uninstalled ++ // configuration becomes invalid. ++ virtual void UninstallFilteringConfiguration( ++ const std::string& configuration_name) = 0; + // Returns a list of FilteringConfigurations previously installed via + // InstallFilteringConfiguration. + virtual std::vector @@ -39309,7 +27129,7 @@ diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_service_impl.cc -@@ -0,0 +1,191 @@ +@@ -0,0 +1,211 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -39344,7 +27164,7 @@ new file mode 100644 +#include "base/trace_event/trace_event.h" +#include "components/adblock/core/common/adblock_constants.h" +#include "components/adblock/core/common/adblock_utils.h" -+#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/configuration/filtering_configuration_prefs.h" +#include "components/adblock/core/subscription/filtering_configuration_maintainer.h" +#include "components/adblock/core/subscription/subscription_collection.h" +#include "components/adblock/core/subscription/subscription_service.h" @@ -39373,8 +27193,10 @@ new file mode 100644 +}; + +SubscriptionServiceImpl::SubscriptionServiceImpl( -+ FilteringConfigurationMaintainerFactory maintainer_factory) -+ : maintainer_factory_(std::move(maintainer_factory)) {} ++ FilteringConfigurationMaintainerFactory maintainer_factory, ++ FilteringConfigurationCleaner configuration_cleaner) ++ : maintainer_factory_(std::move(maintainer_factory)), ++ configuration_cleaner_(std::move(configuration_cleaner)) {} + +SubscriptionServiceImpl::~SubscriptionServiceImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -39425,6 +27247,24 @@ new file mode 100644 + } +} + ++void SubscriptionServiceImpl::UninstallFilteringConfiguration( ++ const std::string& configuration_name) { ++ VLOG(1) << "[eyeo] FilteringConfiguration uninstalled: " ++ << configuration_name; ++ auto it = base::ranges::find_if(maintainers_, [&](const auto& entry) { ++ return entry.first.get()->GetName() == configuration_name; ++ }); ++ if (it == maintainers_.end()) { ++ LOG(WARNING) << "[eyeo] Trying to uninstall not installed configuration " ++ << configuration_name; ++ return; ++ } ++ it->first->RemoveObserver(this); ++ it->second.reset(); ++ configuration_cleaner_.Run(it->first.get()); ++ maintainers_.erase(it); ++} ++ +std::vector +SubscriptionServiceImpl::GetInstalledFilteringConfigurations() { + std::vector result; @@ -39505,7 +27345,7 @@ diff --git a/components/adblock/core/subscription/subscription_service_impl.h b/ new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/subscription_service_impl.h -@@ -0,0 +1,91 @@ +@@ -0,0 +1,97 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -39560,8 +27400,11 @@ new file mode 100644 + base::RepeatingCallback( + FilteringConfiguration* configuration, + SubscriptionUpdatedCallback observer)>; ++ using FilteringConfigurationCleaner = ++ base::RepeatingCallback; + explicit SubscriptionServiceImpl( -+ FilteringConfigurationMaintainerFactory maintainer_factory); ++ FilteringConfigurationMaintainerFactory maintainer_factory, ++ FilteringConfigurationCleaner configuration_cleaner); + ~SubscriptionServiceImpl() final; + + // SubscriptionService: @@ -39569,6 +27412,8 @@ new file mode 100644 + FilteringConfiguration* configuration) const final; + void InstallFilteringConfiguration( + std::unique_ptr configuration) final; ++ void UninstallFilteringConfiguration( ++ const std::string& configuration_name) final; + std::vector GetInstalledFilteringConfigurations() + final; + FilteringConfiguration* GetAdblockFilteringConfiguration() const final; @@ -39586,6 +27431,7 @@ new file mode 100644 + + SEQUENCE_CHECKER(sequence_checker_); + FilteringConfigurationMaintainerFactory maintainer_factory_; ++ FilteringConfigurationCleaner configuration_cleaner_; + using MaintainersCollection = + std::map, + std::unique_ptr>; @@ -39879,15 +27725,15 @@ new file mode 100644 +void ClearSignaturesIfSchemaVersionChanged( + PrefService* pref_service, + const std::string& current_schema_version) { -+ if (pref_service->GetString(prefs::kLastUsedSchemaVersion) != ++ if (pref_service->GetString(common::prefs::kLastUsedSchemaVersion) != + current_schema_version) { -+ if (!pref_service->FindPreference(prefs::kSubscriptionSignatures) ++ if (!pref_service->FindPreference(common::prefs::kSubscriptionSignatures) + ->IsDefaultValue()) { + LOG(INFO) << "[eyeo] Schema version has changed, invalidating stored " + "subscriptions."; -+ pref_service->ClearPref(prefs::kSubscriptionSignatures); ++ pref_service->ClearPref(common::prefs::kSubscriptionSignatures); + } -+ pref_service->SetString(prefs::kLastUsedSchemaVersion, ++ pref_service->SetString(common::prefs::kLastUsedSchemaVersion, + current_schema_version); + } +} @@ -39938,7 +27784,7 @@ new file mode 100644 +SubscriptionValidatorImpl::IsSignatureValid() const { + return base::BindRepeating( + &IsSignatureValidInternal, -+ pref_service_->GetDict(prefs::kSubscriptionSignatures).Clone()); ++ pref_service_->GetDict(common::prefs::kSubscriptionSignatures).Clone()); +} + +SubscriptionValidator::StoreTrustedSignatureThreadSafeCallback @@ -39964,7 +27810,7 @@ new file mode 100644 + std::string signature, + const base::FilePath& path) { + ScopedDictPrefUpdate pref_update(pref_service_, -+ prefs::kSubscriptionSignatures); ++ common::prefs::kSubscriptionSignatures); + const auto key = path.BaseName().AsUTF8Unsafe(); + pref_update->Set(key, base::Value(signature)); +} @@ -39972,7 +27818,7 @@ new file mode 100644 +void SubscriptionValidatorImpl::RemoveStoredSignatureInMainThread( + const base::FilePath& path) { + ScopedDictPrefUpdate pref_update(pref_service_, -+ prefs::kSubscriptionSignatures); ++ common::prefs::kSubscriptionSignatures); + const auto key = path.BaseName().AsUTF8Unsafe(); + pref_update->Remove(key); +} @@ -40040,7 +27886,7 @@ diff --git a/components/adblock/core/subscription/test/filtering_configuration_m new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/filtering_configuration_maintainer_impl_test.cc -@@ -0,0 +1,846 @@ +@@ -0,0 +1,900 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -40175,11 +28021,11 @@ new file mode 100644 + const std::string& document_domain, + FilterCategory category, + std::set& results) const final {} -+ absl::optional FindRewriteFilter( ++ std::set FindRewriteFilters( + const GURL& url, + const std::string& document_domain, + FilterCategory category) const final { -+ return absl::nullopt; ++ return {}; + } + void FindHeaderFilters(const GURL& url, + ContentType type, @@ -40490,6 +28336,60 @@ new file mode 100644 +} + +TEST_F(AdblockFilteringConfigurationMaintainerImplTest, ++ CallOnFilterListsChangedDuringUpgradeExistingSubscriptions) { ++ InitializeTesteeWithNoSubscriptions(); ++ auto expired_subscription = ++ base::MakeRefCounted("expired_subscription"); ++ auto young_subscription = ++ base::MakeRefCounted("young_subscription"); ++ AddSubscription(expired_subscription); ++ AddSubscription(young_subscription); ++ ++ // Pretend one of the subscriptions expired. ++ EXPECT_CALL(persistent_metadata_, ++ IsExpired(expired_subscription->GetSourceUrl())) ++ .WillRepeatedly(testing::Return(true)); ++ EXPECT_CALL(persistent_metadata_, ++ IsExpired(young_subscription->GetSourceUrl())) ++ .WillRepeatedly(testing::Return(false)); ++ // Even though Acceptable Ads is not installed, its expiration will be checked ++ // to make a HEAD request if needed. ++ EXPECT_CALL(persistent_metadata_, IsExpired(AcceptableAdsUrl())) ++ .WillRepeatedly(testing::Return(false)); ++ ++ // Expect that the expired subscription will be re-downloaded and call ++ // OnFilterListsChanged during update ++ EXPECT_CALL(*downloader_, ++ StartDownload(expired_subscription->GetSourceUrl(), ++ SubscriptionDownloader::RetryPolicy::DoNotRetry, ++ testing::_)) ++ .WillOnce(testing::DoAll( ++ [&]() { ++ testee_->OnFilterListsChanged(filtering_configuration_.get()); ++ }, ++ base::test::RunOnceCallback<2>(std::make_unique()))); ++ ++ // The young subscription will not be re-downloaded. ++ EXPECT_CALL(*downloader_, StartDownload(young_subscription->GetSourceUrl(), ++ testing::_, testing::_)) ++ .Times(0); ++ ++ run_update_check_callback_.Run(); ++ ++ // In a second run, even though |expired_subscription| might be marked as ++ // expired by persistent_metadata_, there will be no new download since one is ++ // already under way. ++ EXPECT_CALL(*downloader_, StartDownload(expired_subscription->GetSourceUrl(), ++ testing::_, testing::_)) ++ .Times(0); ++ run_update_check_callback_.Run(); ++ ++ // After OnFilterListsChanged, check if number of subscriptions is unchanged ++ // (DPD-2015) ++ EXPECT_EQ(2u, testee_->GetCurrentSubscriptions().size()); ++} ++ ++TEST_F(AdblockFilteringConfigurationMaintainerImplTest, + UpdatePingStoresAAversion) { + InitializeTesteeWithNoSubscriptions(); + // Once the update check runs, even though Acceptable Ads is not installed, @@ -41356,8 +29256,8 @@ new file mode 100644 + FilterCategory category, + std::set& results), + (override, const)); -+ MOCK_METHOD(absl::optional, -+ FindRewriteFilter, ++ MOCK_METHOD(std::set, ++ FindRewriteFilters, + (const GURL& url, + const std::string& document_domain, + FilterCategory category), @@ -41523,7 +29423,7 @@ diff --git a/components/adblock/core/subscription/test/mock_subscription_collect new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/mock_subscription_collection.h -@@ -0,0 +1,96 @@ +@@ -0,0 +1,102 @@ + +/* + * This file is part of eyeo Chromium SDK, @@ -41557,6 +29457,10 @@ new file mode 100644 + public: + MockSubscriptionCollection(); + ~MockSubscriptionCollection() override; ++ MOCK_METHOD(const std::string&, ++ GetFilteringConfigurationName, ++ (), ++ (const, override)); + MOCK_METHOD(absl::optional, + FindBySubresourceFilter, + (const GURL& frame_url, @@ -41604,9 +29508,11 @@ new file mode 100644 + GetCspInjections, + (const GURL& frame_url, const std::vector& frame_hierarchy), + (const, override)); -+ MOCK_METHOD(absl::optional, -+ GetRewriteUrl, -+ (const GURL& frame_url, const std::vector& frame_hierarchy), ++ MOCK_METHOD(std::set, ++ GetRewriteFilters, ++ (const GURL& frame_url, ++ const std::vector& frame_hierarchy, ++ FilterCategory blocking_filter_category), + (const, override)); + MOCK_METHOD(std::set, + GetHeaderFilters, @@ -41861,7 +29767,7 @@ diff --git a/components/adblock/core/subscription/test/mock_subscription_service new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/mock_subscription_service.h -@@ -0,0 +1,71 @@ +@@ -0,0 +1,75 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -41908,6 +29814,10 @@ new file mode 100644 + InstallFilteringConfiguration, + (std::unique_ptr configuration), + (override)); ++ MOCK_METHOD(void, ++ UninstallFilteringConfiguration, ++ (const std::string& configuration_name), ++ (override)); + MOCK_METHOD(std::vector, + GetInstalledFilteringConfigurations, + (), @@ -42426,7 +30336,7 @@ diff --git a/components/adblock/core/subscription/test/pattern_matcher_test.cc b new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/pattern_matcher_test.cc -@@ -0,0 +1,340 @@ +@@ -0,0 +1,351 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -42766,6 +30676,17 @@ new file mode 100644 + EXPECT_FALSE(DoesPatternMatchUrl(deep_pattern, long_url)); +} + ++TEST(AdblockPatternMatcherTest, EmptyDoublePipe) { ++ const auto pattern = base::StringPiece("||"); ++ EXPECT_TRUE(DoesPatternMatchUrl(pattern, GURL("https://url.com"))); ++} ++ ++TEST(AdblockPatternMatcherTest, EmptySinglePipe) { ++ const auto pattern = base::StringPiece("|"); ++ EXPECT_TRUE(DoesPatternMatchUrl(pattern, GURL("https://url.com"))); ++} ++ ++ +} // namespace adblock diff --git a/components/adblock/core/subscription/test/preloaded_subscription_provider_impl_test.cc b/components/adblock/core/subscription/test/preloaded_subscription_provider_impl_test.cc new file mode 100644 @@ -43013,7 +30934,7 @@ diff --git a/components/adblock/core/subscription/test/subscription_collection_i new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/subscription_collection_impl_test.cc -@@ -0,0 +1,1174 @@ +@@ -0,0 +1,1020 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -43098,7 +31019,7 @@ new file mode 100644 + EXPECT_CALL(*sub1, GetSourceUrl()).WillRepeatedly(Return(kSourceUrl)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + EXPECT_TRUE(!!collection.FindBySubresourceFilter( + kImageAddress, frame_hierarchy, ContentType::Image, kSitekey, + FilterCategory::Blocking)); @@ -43145,7 +31066,7 @@ new file mode 100644 + "ad_content"}; + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + auto actual_selectors = + collection.GetElementHideSelectors(kParentAddress, {}, kSitekey); + std::sort(actual_selectors.begin(), actual_selectors.end()); @@ -43178,7 +31099,7 @@ new file mode 100644 + std::vector expected_selectors{"a", "d", "e"}; + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + auto actual_selectors = + collection.GetElementHideEmulationSelectors(kParentAddress); + std::sort(actual_selectors.begin(), actual_selectors.end()); @@ -43196,7 +31117,7 @@ new file mode 100644 + .WillOnce(Return(std::vector{snippet})); + + SubscriptionCollectionImpl collection( -+ std::vector>{subscription}); ++ std::vector>{subscription}, {}); + auto snippets = collection.GenerateSnippets(kParentAddress, {}); + EXPECT_EQ("say", snippets.front().GetList().front().GetString()); + EXPECT_EQ("Hello", snippets.front().GetList().back().GetString()); @@ -43219,7 +31140,7 @@ new file mode 100644 + .WillOnce(Return(true)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_TRUE(!!collection.FindBySpecialFilter( + SpecialFilterType::Document, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43244,7 +31165,7 @@ new file mode 100644 + .WillOnce(Return(false)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_FALSE(!!collection.FindBySpecialFilter( + SpecialFilterType::Document, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43265,7 +31186,7 @@ new file mode 100644 + .WillOnce(Return(true)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_TRUE(!!collection.FindBySpecialFilter( + SpecialFilterType::Elemhide, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43291,7 +31212,7 @@ new file mode 100644 + .WillOnce(Return(false)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_FALSE(!!collection.FindBySpecialFilter( + SpecialFilterType::Elemhide, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43314,7 +31235,7 @@ new file mode 100644 + .WillOnce(Return(true)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_TRUE(collection.FindBySpecialFilter( + SpecialFilterType::Genericblock, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43341,7 +31262,7 @@ new file mode 100644 + .WillOnce(Return(false)); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + EXPECT_FALSE(collection.FindBySpecialFilter( + SpecialFilterType::Genericblock, kSourceUrl, {kParentAddress}, kSitekey)); +} @@ -43365,7 +31286,7 @@ new file mode 100644 + .Times(0); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + + // Empty result means no CSP injection necessary. + EXPECT_TRUE( @@ -43430,7 +31351,7 @@ new file mode 100644 + // filters, the string returned by first subscription becomes the CSP + // injection. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + + std::set filters = + collection.GetCspInjections(kImageAddress, {kParentAddress}); @@ -43497,7 +31418,7 @@ new file mode 100644 + // filters, the string returned by first subscription becomes the CSP + // injection. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + + std::set filters = + collection.GetCspInjections(kImageAddress, {kParentAddress}); @@ -43565,7 +31486,7 @@ new file mode 100644 + // filters, the string returned by first subscription becomes the CSP + // injection. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + + std::set filters = + collection.GetCspInjections(kImageAddress, {kParentAddress}); @@ -43597,7 +31518,7 @@ new file mode 100644 + + // The allowing Document filter overrules the blocking CSP filter. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); @@ -43645,7 +31566,7 @@ new file mode 100644 + + // The allowing CSP filter overrules the blocking CSP filter. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_TRUE(results.empty()); @@ -43696,7 +31617,7 @@ new file mode 100644 + + // The allowing CSP filter overrules the blocking CSP filter. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_THAT(results, testing::UnorderedElementsAre("first")); @@ -43754,7 +31675,7 @@ new file mode 100644 + + // The allowing CSP filter overrules the blocking CSP filter. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_TRUE(results.empty()); @@ -43800,7 +31721,7 @@ new file mode 100644 + + // The allowing CSP filter overrules the blocking CSP filter. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_TRUE(results.empty()); @@ -43851,7 +31772,7 @@ new file mode 100644 + // The blocking CSP filter was NOT overruled by an allowing CSP filter because + // the payloads did not match. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); @@ -43926,7 +31847,7 @@ new file mode 100644 + + // Finally, no CSP filter found. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_THAT(results, testing::UnorderedElementsAre("domain-block")); @@ -43980,7 +31901,7 @@ new file mode 100644 + + // Finally, no CSP filter found. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); ++ std::vector>{sub1}, {}); + std::set results = + collection.GetCspInjections(kImageAddress, {kParentAddress}); + EXPECT_TRUE(results.empty()); @@ -43991,200 +31912,46 @@ new file mode 100644 + auto sub2 = base::MakeRefCounted(); + + // There are no blocking filters found. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return(absl::nullopt)); -+ EXPECT_CALL(*sub2, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return(absl::nullopt)); ++ EXPECT_CALL(*sub1, FindRewriteFilters(kImageAddress, kParentAddress.host(), ++ FilterCategory::Blocking)) ++ .WillOnce(Return(std::set{})); ++ EXPECT_CALL(*sub2, FindRewriteFilters(kImageAddress, kParentAddress.host(), ++ FilterCategory::Blocking)) ++ .WillOnce(Return(std::set{})); + + // Since there are no blocking filters, no need to check allow filters. + EXPECT_CALL(*sub1, HasSpecialFilter(_, _, _, _)).Times(0); + EXPECT_CALL(*sub2, HasSpecialFilter(_, _, _, _)).Times(0); -+ EXPECT_CALL(*sub1, FindRewriteFilter(_, _, FilterCategory::Allowing)) -+ .Times(0); -+ EXPECT_CALL(*sub2, FindRewriteFilter(_, _, FilterCategory::Allowing)) -+ .Times(0); + + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); ++ std::vector>{sub1, sub2}, {}); + + // Empty result means no redirect necessary. -+ EXPECT_EQ(collection.GetRewriteUrl(kImageAddress, {kParentAddress}), -+ absl::nullopt); ++ EXPECT_THAT(collection.GetRewriteFilters(kImageAddress, {kParentAddress}, ++ FilterCategory::Blocking), ++ testing::UnorderedElementsAre()); +} + -+TEST_F(AdblockSubscriptionCollectionImplTest, RewriteBlockingFilterFound) { ++TEST_F(AdblockSubscriptionCollectionImplTest, RewriteBlockingFiltersFound) { + auto sub1 = base::MakeRefCounted(); + auto sub2 = base::MakeRefCounted(); -+ constexpr const char* redirect = "about::blank"; ++ constexpr const char* redirect1 = "about::blank/1"; ++ constexpr const char* redirect2 = "about::blank/2"; + -+ // First subscription contains a blocking filter. Second is not queried -+ // because we only return the first found blocking filter. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return(redirect)); -+ EXPECT_CALL(*sub2, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .Times(0); -+ -+ // Since a blocking filter is found, implementation will try to find allowing -+ // rules. -+ -+ // Neither subscription contains a document-wide allowing rule. -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Document, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Document, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Document, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Document, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ -+ // Neither subscription contains an allowing rule. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Allowing)) -+ .WillOnce(Return(absl::nullopt)); -+ EXPECT_CALL(*sub2, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Allowing)) -+ .WillOnce(Return(absl::nullopt)); -+ -+ // Neither subscription contains a GenericBlock rule that would require -+ // searching for domain-specific-only blocking filters. -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); ++ EXPECT_CALL(*sub1, FindRewriteFilters(kImageAddress, kParentAddress.host(), ++ FilterCategory::Blocking)) ++ .WillOnce(Return(std::set{redirect1})); ++ EXPECT_CALL(*sub2, FindRewriteFilters(kImageAddress, kParentAddress.host(), ++ FilterCategory::Blocking)) ++ .WillOnce(Return(std::set{redirect2})); + + // In presence of a blocking filters and absence of any allowing filters, + // the string returned by first subscription becomes the redirect. + SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); -+ EXPECT_EQ(collection.GetRewriteUrl(kImageAddress, {kParentAddress}), -+ GURL(redirect)); -+} -+ -+TEST_F(AdblockSubscriptionCollectionImplTest, -+ RewriteBlockingFilterOverruledViaDocumentAllowingRule) { -+ auto sub1 = base::MakeRefCounted(); -+ -+ // Subscription contains a blocking filter. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return("block")); -+ -+ // Since a blocking filter is found, implementation will try to find allowing -+ // rules. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Allowing)) -+ .WillOnce(Return(absl::nullopt)); -+ -+ // A document-wide allowing rule exists. -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Document, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(true)); -+ -+ // No need to query GenericBlock rules since the blocking filter was -+ // overruled already. -+ EXPECT_CALL(*sub1, HasSpecialFilter(SpecialFilterType::Genericblock, _, _, _)) -+ .Times(0); -+ -+ // The allowing Document filter overrules the blocking filter. -+ SubscriptionCollectionImpl collection( -+ std::vector>{sub1}); -+ EXPECT_EQ(collection.GetRewriteUrl(kImageAddress, {kParentAddress}), -+ absl::nullopt); -+} -+ -+TEST_F(AdblockSubscriptionCollectionImplTest, GenericBlockRewriteFilter) { -+ auto sub1 = base::MakeRefCounted(); -+ auto sub2 = base::MakeRefCounted(); -+ -+ // First subscription contains a blocking filter. Second does not. -+ // Both are consulted, because the first subscription's blocking filter -+ // gets overruled as not domain-specific. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return("block")); -+ EXPECT_CALL(*sub2, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Blocking)) -+ .WillOnce(Return(absl::nullopt)); -+ -+ // Neither subscription contains a document-wide allowing rule. -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Document, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Document, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Document, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Document, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ -+ // Neither subscription contains an allowing rule. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Allowing)) -+ .WillOnce(Return(absl::nullopt)); -+ EXPECT_CALL(*sub2, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::Allowing)) -+ .WillOnce(Return(absl::nullopt)); -+ -+ // Second subscription contains a genericblock rule. -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub1, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kImageAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(*sub2, -+ HasSpecialFilter(SpecialFilterType::Genericblock, kParentAddress, -+ kParentAddress.host(), SiteKey())) -+ .WillOnce(Return(true)); -+ -+ // Search is retried but now for domain-specific filters only. No matches. -+ EXPECT_CALL(*sub1, FindRewriteFilter(kImageAddress, kParentAddress.host(), -+ FilterCategory::DomainSpecificBlocking)) -+ .WillOnce(Return(absl::nullopt)); -+ -+ // Finally, no filter found. -+ SubscriptionCollectionImpl collection( -+ std::vector>{sub1, sub2}); -+ EXPECT_EQ(collection.GetRewriteUrl(kImageAddress, {kParentAddress}), -+ absl::nullopt); ++ std::vector>{sub1, sub2}, {}); ++ EXPECT_THAT(collection.GetRewriteFilters(kImageAddress, {kParentAddress}, ++ FilterCategory::Blocking), ++ testing::UnorderedElementsAre(GURL(redirect1), GURL(redirect2))); +} + +} // namespace adblock @@ -44813,7 +32580,7 @@ new file mode 100644 + : public testing::TestWithParam { + public: + AdblockSubscriptionPersistentMetadataImplTest() { -+ prefs::RegisterProfilePrefs(prefs_.registry()); ++ common::prefs::RegisterProfilePrefs(prefs_.registry()); + metadata_ = std::make_unique(&prefs_); + } + @@ -45340,7 +33107,7 @@ diff --git a/components/adblock/core/subscription/test/subscription_service_impl new file mode 100644 --- /dev/null +++ b/components/adblock/core/subscription/test/subscription_service_impl_test.cc -@@ -0,0 +1,247 @@ +@@ -0,0 +1,275 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -45366,6 +33133,8 @@ new file mode 100644 +#include "base/memory/scoped_refptr.h" +#include "base/ranges/algorithm.h" +#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/configuration/filtering_configuration_prefs.h" ++#include "components/adblock/core/configuration/persistent_filtering_configuration.h" +#include "components/adblock/core/configuration/test/fake_filtering_configuration.h" +#include "components/adblock/core/subscription/filtering_configuration_maintainer.h" +#include "components/adblock/core/subscription/subscription_collection.h" @@ -45402,9 +33171,13 @@ new file mode 100644 + }; + + AdblockSubscriptionServiceImplTest() -+ : testee_(base::BindRepeating( -+ &AdblockSubscriptionServiceImplTest::MockMakeMaintainer, -+ base::Unretained(this))) {} ++ : testee_( ++ base::BindRepeating( ++ &AdblockSubscriptionServiceImplTest::MockMakeMaintainer, ++ base::Unretained(this)), ++ base::BindRepeating( ++ &AdblockSubscriptionServiceImplTest::MockCleanupConfiguration, ++ base::Unretained(this))) {} + + std::unique_ptr MockMakeMaintainer( + FilteringConfiguration* configuration, @@ -45415,7 +33188,12 @@ new file mode 100644 + return maintainer; + } + ++ void MockCleanupConfiguration(FilteringConfiguration* configuration) { ++ cleaned_configs_.push_back(configuration->GetName()); ++ } ++ + std::vector maintainer_factory_calls_; ++ std::vector cleaned_configs_; + MockSubscriptionObserver observer_; + SubscriptionServiceImpl testee_; +}; @@ -45451,6 +33229,23 @@ new file mode 100644 +} + +TEST_F(AdblockSubscriptionServiceImplTest, ++ UninstallingConfigurationRemovesData) { ++ auto config = std::make_unique(); ++ auto config_name = config->GetName(); ++ auto* config_bare_ptr = config.get(); ++ // Install and confirm. ++ testee_.InstallFilteringConfiguration(std::move(config)); ++ EXPECT_EQ(testee_.GetInstalledFilteringConfigurations(), ++ std::vector{config_bare_ptr}); ++ ASSERT_EQ(0u, cleaned_configs_.size()); ++ // Uninstall and confirm. ++ testee_.UninstallFilteringConfiguration(config_name); ++ EXPECT_TRUE(testee_.GetInstalledFilteringConfigurations().empty()); ++ ASSERT_EQ(1u, cleaned_configs_.size()); ++ EXPECT_EQ(cleaned_configs_[0], config_name); ++} ++ ++TEST_F(AdblockSubscriptionServiceImplTest, + EnablingConfigurationCreatesMaintainer) { + auto config = std::make_unique(); + auto* config_bare_ptr = config.get(); @@ -45734,7 +33529,7 @@ new file mode 100644 +class AdblockSubscriptionValidatorImplTest : public testing::Test { + public: + void SetUp() override { -+ prefs::RegisterProfilePrefs(pref_service_.registry()); ++ common::prefs::RegisterProfilePrefs(pref_service_.registry()); + } + + std::unique_ptr MakeValidator( @@ -45807,7 +33602,7 @@ new file mode 100644 + + // Simulate a schema version change by storing a kLastUsedSchemaVersion + // different than the current one. -+ pref_service_.SetString(prefs::kLastUsedSchemaVersion, "000"); ++ pref_service_.SetString(common::prefs::kLastUsedSchemaVersion, "000"); + + // Recreate the validator. + validator = MakeValidator(CurrentSchemaVersion()); @@ -45833,7 +33628,7 @@ new file mode 100644 + // "Key" interprets dict["x.fb"]="hash" as {"x.fb":"hash"} - the dot is part + // of the key name + const base::Value::Dict& pref = -+ pref_service_.GetDict(prefs::kSubscriptionSignatures); ++ pref_service_.GetDict(common::prefs::kSubscriptionSignatures); + ASSERT_TRUE(pref.FindString("x.fb")); + EXPECT_EQ(*pref.FindString("x.fb"), + base::Base64Encode(crypto::SHA256Hash( @@ -46170,7 +33965,7 @@ diff --git a/components/adblock/core/test/activeping_telemetry_topic_provider_te new file mode 100644 --- /dev/null +++ b/components/adblock/core/test/activeping_telemetry_topic_provider_test.cc -@@ -0,0 +1,319 @@ +@@ -0,0 +1,320 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -46192,12 +33987,12 @@ new file mode 100644 + +#include + -+#include "base/guid.h" +#include "base/json/json_reader.h" +#include "base/strings/string_piece_forward.h" +#include "base/system/sys_info.h" +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" ++#include "base/uuid.h" +#include "components/adblock/core/common/adblock_prefs.h" +#include "components/adblock/core/test/mock_adblock_controller.h" +#include "components/prefs/pref_value_store.h" @@ -46216,7 +34011,7 @@ new file mode 100644 + app_info_.name = "MyApp"; + app_info_.version = "1234"; + app_info_.client_os = "UNUSED"; // base/sys_info.h used instead. -+ prefs::RegisterProfilePrefs(pref_service_.registry()); ++ common::prefs::RegisterProfilePrefs(pref_service_.registry()); + EXPECT_CALL(controller_, IsAcceptableAdsEnabled()) + .WillRepeatedly(testing::Return(AcceptableAdsEnabled())); + RecreateProvider(); @@ -46254,18 +34049,18 @@ new file mode 100644 + void ExpectPayloadContainsValue(const std::string& json, + std::string key, + base::Value expected_value) { -+ auto root = base::JSONReader::Read(json); ++ auto root = base::JSONReader::ReadDict(json); + ASSERT_TRUE(root) << "JSON is invalid"; -+ auto* value = root->FindPath("payload." + key); ++ auto* value = root->FindByDottedPath("payload." + key); + ASSERT_TRUE(value); + EXPECT_EQ(*value, expected_value); + } + + void ExpectPayloadDoesNotContainValue(const std::string& json, + std::string key) { -+ auto value = base::JSONReader::Read(json); ++ auto value = base::JSONReader::ReadDict(json); + ASSERT_TRUE(value) << "JSON is invalid"; -+ EXPECT_FALSE(value->FindPath("payload." + key)); ++ EXPECT_FALSE(value->FindByDottedPath("payload." + key)); + } + + void ExpectPayloadContainsRequiredStaticValues(const std::string& json) { @@ -46286,12 +34081,13 @@ new file mode 100644 + } + + void ExpectLastPingTagValid(const std::string& json, -+ base::GUID* parsed_tag = nullptr) { -+ auto root = base::JSONReader::Read(json); ++ base::Uuid* parsed_tag = nullptr) { ++ auto root = base::JSONReader::ReadDict(json); + ASSERT_TRUE(root); -+ const std::string* tag = root->FindStringPath("payload.last_ping_tag"); ++ const std::string* tag = ++ root->FindStringByDottedPath("payload.last_ping_tag"); + ASSERT_TRUE(tag); -+ const auto uuid = base::GUID::ParseLowercase(*tag); ++ const auto uuid = base::Uuid::ParseLowercase(*tag); + EXPECT_TRUE(uuid.is_valid()); + if (parsed_tag) { + *parsed_tag = uuid; @@ -46417,7 +34213,7 @@ new file mode 100644 + std::make_unique(R"({"token":"Monday"})")); + + // Store first last_ping_tag to compare against the next one: -+ base::GUID first_response_uuid; ++ base::Uuid first_response_uuid; + ExpectLastPingTagValid(GetPayload(), &first_response_uuid); + + // Next ping after normal delay, since the previous one succeeded: @@ -46439,7 +34235,7 @@ new file mode 100644 + base::Value("Monday")); + ExpectPayloadContainsValue(payload, "first_ping", base::Value("Monday")); + -+ base::GUID second_response_uuid; ++ base::Uuid second_response_uuid; + ExpectLastPingTagValid(payload, &second_response_uuid); + + // Different tag was generated: @@ -46494,7 +34290,7 @@ diff --git a/components/adblock/core/test/adblock_controller_impl_test.cc b/comp new file mode 100644 --- /dev/null +++ b/components/adblock/core/test/adblock_controller_impl_test.cc -@@ -0,0 +1,450 @@ +@@ -0,0 +1,481 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -46585,11 +34381,11 @@ new file mode 100644 +class AdblockControllerImplTest : public testing::Test { + public: + AdblockControllerImplTest() { -+ prefs::RegisterProfilePrefs(pref_service_.registry()); ++ common::prefs::RegisterProfilePrefs(pref_service_.registry()); + RecreateController(); -+ custom_subscriptions_pref_.Init(prefs::kAdblockCustomSubscriptionsLegacy, -+ &pref_service_); -+ subscriptions_pref_.Init(prefs::kAdblockSubscriptionsLegacy, ++ custom_subscriptions_pref_.Init( ++ common::prefs::kAdblockCustomSubscriptionsLegacy, &pref_service_); ++ subscriptions_pref_.Init(common::prefs::kAdblockSubscriptionsLegacy, + &pref_service_); + } + @@ -46704,7 +34500,7 @@ new file mode 100644 +} + +TEST_F(AdblockControllerImplTest, EnableAcceptableAdsfPrefMigrated) { -+ pref_service_.SetBoolean(prefs::kEnableAcceptableAdsLegacy, false); ++ pref_service_.SetBoolean(common::prefs::kEnableAcceptableAdsLegacy, false); + // Acceptable Ads is not installed (and even removed, if it was installed + // before) as old profile had it disabled. + ExpectRemoval(AcceptableAdsUrl()); @@ -46715,7 +34511,7 @@ new file mode 100644 + RecreateController(); + testee_->MigrateLegacyPrefs(&pref_service_); + -+ pref_service_.SetBoolean(prefs::kEnableAcceptableAdsLegacy, true); ++ pref_service_.SetBoolean(common::prefs::kEnableAcceptableAdsLegacy, true); + // Acceptable Ads is installed but only once. + ExpectInstallationTriggered(AcceptableAdsUrl()); + RecreateController(); @@ -46728,7 +34524,7 @@ new file mode 100644 + +TEST_F(AdblockControllerImplTest, EnabledStatePrefMigrated) { + // Pref is migrated once. -+ pref_service_.SetBoolean(prefs::kEnableAdblockLegacy, false); ++ pref_service_.SetBoolean(common::prefs::kEnableAdblockLegacy, false); + EXPECT_CALL(filtering_configuration_, SetEnabled(false)); + RecreateController(); + testee_->MigrateLegacyPrefs(&pref_service_); @@ -46737,7 +34533,7 @@ new file mode 100644 + testee_->MigrateLegacyPrefs(&pref_service_); + + // Works for true value as well. -+ pref_service_.SetBoolean(prefs::kEnableAdblockLegacy, true); ++ pref_service_.SetBoolean(common::prefs::kEnableAdblockLegacy, true); + EXPECT_CALL(filtering_configuration_, SetEnabled(true)); + RecreateController(); + testee_->MigrateLegacyPrefs(&pref_service_); @@ -46746,6 +34542,30 @@ new file mode 100644 + testee_->MigrateLegacyPrefs(&pref_service_); +} + ++TEST_F(AdblockControllerImplTest, DisableEyeoFilteringPrefAppliedOnFirstRun) { ++ { ++ auto flag_not_set = OverrideEyeoFilteringDisabledByDefault(false); ++ // Check normal 1st run. ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); ++ EXPECT_CALL(filtering_configuration_, SetEnabled(_)).Times(0); ++ testee_->RunFirstRunLogic(&pref_service_); ++ } ++ ++ // Confirm disabled on 1st run when flag is set. ++ { ++ auto flag_set = OverrideEyeoFilteringDisabledByDefault(true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); ++ EXPECT_CALL(filtering_configuration_, SetEnabled(false)); ++ testee_->RunFirstRunLogic(&pref_service_); ++ ++ // Assure it happens once during 1st run only. ++ EXPECT_CALL(filtering_configuration_, SetEnabled(_)).Times(0); ++ testee_->RunFirstRunLogic(&pref_service_); ++ } ++} ++ +TEST_F(AdblockControllerImplTest, EnablingAcceptableAdsInstallsSubscription) { + // Initially, AA is not installed. + EXPECT_CALL(filtering_configuration_, GetFilterLists()) @@ -46810,7 +34630,8 @@ new file mode 100644 +TEST_F(AdblockControllerImplTest, + InstallLanguageBasedRecommendationAndAntiCvOnFirstRun) { + // Default prefs state indicates a first run situation. -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + // Since there aren't any pre-existing subscriptions migrated, we will install + // a language-based recommendation. + ExpectInstallationTriggered(kRecommendedSubscription); @@ -46825,7 +34646,8 @@ new file mode 100644 + +TEST_F(AdblockControllerImplTest, + InstallDefaultRecommendationForNonMatchingLanguage) { -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + // Since the language does not have a language-specific recommendation, we + // install a default list. + ExpectInstallationTriggered(DefaultSubscriptionUrl()); @@ -46848,7 +34670,8 @@ new file mode 100644 + "easylistgermany+easylist.txt"}; + subscriptions_pref_.SetValue({kMigratedSubscription.spec()}); + -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + ExpectInstallationTriggered(kMigratedSubscription); + ExpectInstallationTriggered(kRecommendedSubscription); + ExpectInstallationTriggered(AntiCVUrl()); @@ -46860,7 +34683,8 @@ new file mode 100644 +} + +TEST_F(AdblockControllerImplTest, AADefaultOffFirstRun) { -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + const std::vector recommendations = { + {AcceptableAdsUrl(), + "AA", @@ -46874,7 +34698,8 @@ new file mode 100644 +} + +TEST_F(AdblockControllerImplTest, AADefaultOnFirstRun) { -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + const std::vector recommendations = { + {AcceptableAdsUrl(), + "AA", @@ -46889,7 +34714,8 @@ new file mode 100644 + +TEST_F(AdblockControllerImplTest, + NoInstallationWhenDefaultSubscriptionIgnored) { -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + const std::vector recommendations = { + {DefaultSubscriptionUrl(), + "EasyList", @@ -46903,7 +34729,8 @@ new file mode 100644 +} + +TEST_F(AdblockControllerImplTest, SeveralLanguageSpecificSubscriptions) { -+ pref_service_.SetBoolean(prefs::kInstallFirstStartSubscriptions, true); ++ pref_service_.SetBoolean(common::prefs::kInstallFirstStartSubscriptions, ++ true); + const auto kEnglishUrl1 = GURL("https://english.com/filter1.txt"); + const auto kEnglishUrl2 = GURL("https://english.com/filter2.txt"); + const auto kGermanUrl1 = GURL("https://german.com/filter1.txt"); @@ -47415,7 +35242,7 @@ diff --git a/components/adblock/core/test/mock_adblock_controller.h b/components new file mode 100644 --- /dev/null +++ b/components/adblock/core/test/mock_adblock_controller.h -@@ -0,0 +1,91 @@ +@@ -0,0 +1,71 @@ +/* + * This file is part of eyeo Chromium SDK, + * Copyright (C) 2006-present eyeo GmbH @@ -47450,30 +35277,10 @@ new file mode 100644 + MockAdblockController(); + ~MockAdblockController() override; + -+ MOCK_METHOD(void, -+ AddObserver, -+ (AdblockController::Observer * observer), -+ (override)); -+ MOCK_METHOD(void, -+ RemoveObserver, -+ (AdblockController::Observer * observer), -+ (override)); + MOCK_METHOD(void, SetAdblockEnabled, (bool enabled), (override)); + MOCK_METHOD(bool, IsAdblockEnabled, (), (const, override)); + MOCK_METHOD(void, SetAcceptableAdsEnabled, (bool enabled), (override)); + MOCK_METHOD(bool, IsAcceptableAdsEnabled, (), (const, override)); -+ MOCK_METHOD(void, SelectBuiltInSubscription, (const GURL& url), (override)); -+ MOCK_METHOD(void, UnselectBuiltInSubscription, (const GURL& url), (override)); -+ MOCK_METHOD(std::vector>, -+ GetSelectedBuiltInSubscriptions, -+ (), -+ (const, override)); -+ MOCK_METHOD(void, AddCustomSubscription, (const GURL& url), (override)); -+ MOCK_METHOD(void, RemoveCustomSubscription, (const GURL& url), (override)); -+ MOCK_METHOD(std::vector>, -+ GetCustomSubscriptions, -+ (), -+ (const, override)); + MOCK_METHOD(void, InstallSubscription, (const GURL& url), (override)); + MOCK_METHOD(void, UninstallSubscription, (const GURL& url), (override)); + MOCK_METHOD(std::vector>, @@ -57475,7 +45282,7 @@ diff --git a/components/adblock/docs/integration-how-to.md b/components/adblock/ new file mode 100644 --- /dev/null +++ b/components/adblock/docs/integration-how-to.md -@@ -0,0 +1,220 @@ +@@ -0,0 +1,216 @@ +# Integration how-to guides + +This section provides guidance (including code snippets) on setting up ad-filtering in your browser. @@ -57689,13 +45496,9 @@ new file mode 100644 + +Differences across versions are listed in [the changelog](components/adblock/CHANGELOG.md). + -+You can also use our [interdiff script](/tools/adblock/interdiff.py) to compare two git revision ranges. ++You can also use our [interdiff script](tools/adblock/generate_interdiffs.sh) to compare two git revision ranges. + -+The script requires the patchutils package to be available. -+* On Mac it is available via `brew install patchutils` -+* On Linux you can use your package manager, for example `sudo apt install patchutils` -+ -+To get a combined patch, execute the script to obtain the changes introduced by eyeo Chromium SDK compared to vanilla Chromium in the old branch, and the same for the new new branch. You can obtain the necessary hashes for the revision ranges from release announcements. To get help on how to use the script, run `./interdiff.py --help`. ++To get a combined patch, execute the script to obtain the changes introduced by eyeo Chromium SDK compared to vanilla Chromium in the old branch, and the same for the new new branch. You can obtain the necessary hashes for the revision ranges from release announcements. To get help on how to use the script, run `./generate_interdiffs.sh --help`. diff --git a/components/adblock/docs/settings/README.md b/components/adblock/docs/settings/README.md new file mode 100644 --- /dev/null @@ -58765,7 +46568,7 @@ diff --git a/components/adblock/features.gni b/components/adblock/features.gni new file mode 100644 --- /dev/null +++ b/components/adblock/features.gni -@@ -0,0 +1,44 @@ +@@ -0,0 +1,47 @@ +# +# This file is part of eyeo Chromium SDK, +# Copyright (C) 2006-present eyeo GmbH @@ -58809,6 +46612,9 @@ new file mode 100644 + # in order to allow installing/removing/listing filter lists via navigating to + # special URLs. This is used for internal automated testing (see DPD-1407). + eyeo_intercept_debug_url = false ++ ++ # If true then eyeo filtering is disabled by default (applies to 1st run scenario). ++ eyeo_disable_filtering_by_default = false +} diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn --- a/components/resources/BUILD.gn @@ -58969,3837 +46775,3803 @@ new file mode 100644 +// along with eyeo Chromium SDK. If not, see . diff --git a/components/resources/adblocking/anticv.txt.gz b/components/resources/adblocking/anticv.txt.gz new file mode 100644 -index 0000000000000000000000000000000000000000..2cd20f69f932cb0fed185ea59287ec4219f2f92b +index 0000000000000000000000000000000000000000..a9c8d47aada08f8fed54b1c4ed152f91049d5061 GIT binary patch -literal 62367 -zcmV(tKKkDsYSbwmOL*_>+PY&%r{e`^w%f~;Tz4;@3 -z>RrBx_tp1rJ_OL^Ba@1Y^w2)oJ9xDBS2H -z0KP$}ZJ$d&Peu#|h}0$&u;8g5=ai>G*XF6MV1C;tim9%xL&l}8CGjKp{Lm&T1u$dV -zmt1q7#5PwdXUZN5Y0nTkSB5fx%}LAvmMvK(qy_+!atwTe`TxlEFS&PvmG&Db(jIYA -zapUj&(chB-lME2)2^knPc6WE}C14JTBp&yBdaSVvbbR;v?AUswq8=Ar{PE!jfAy%# -zRLIyDXz6TshzHAYMCxQxWK8ObBN?GK(ZYLfFMhlPf-&Gs8Zenjp6Y{Ty$lG-d_mcV -z)7Qr$$wUf_TG{oK1t3$F(nM085X7}rPHHs$TuOlB@HFNra}=;I1KAKD2+-W~0hne# -z#SCk9--Bv2MG5FzoCOn)DUG1(GSDz-YCLVqdUPFWv;_Kgjz2n2zkgyO;T2;PA-Bp& -zQ%P7;PMK~h*Uz$?0kfq22I5;Gxg?Q6peTVLNTEqedLvHRS7f1D@Y83O$3V|SnlfMa -za@F;P6hikvQUjFZby0#XR(0)4G$RfS -z6L>|7)dYlcYLO`PK=uwE1A>>T5aP#q)+16kl?7o1vL5JB&rh2obU{GLXA;%Y;S{ps -zw<;hjt%_(>VxW6d8}ZE4KrkwCi%o7YC)k -zMQ>voNKzGz-VecI$06+zzb=9hS4GpMk@vP?|2C0NNE(nH0Xrj9NJ3iR2nL8>#o!+p -zineMKk+-VN3cjxFT?Ef4l9dc+YKpXKL)xks`q$NAo;H=lYmJhu)lGr@Xlj~_TNR$E -zriPrZD@H|{TG`E1P$FBkT#NQsk3q|%-5^rhs@5wimjouVT}Og8)q07h77{L7RqnUD -zqSQ9EghVXQS`8WZ+gO4_s@khiUi<5W_@OQuIMj0^j5?3tUmqA;_#!iP6p~A>8@5kK -z91{ojIoSNPpk%VHyHXWuhXprU_~A -zF5wvOr@z{VYo@q<2DA0efHW@8n0||A227BXGZur-AmmXT+px*KBLVlVmdzr`YQqU0 -z0tNd3Td)EM5LJ{8$+IVq!Jb}{1Wg`^1QyV8nv(GfijSfyjLSmv4Xu4q0&gY&2eM&p -zAYf~{)=yqS|7)CdFOLHvIZ0c7dgWFHF{6Y-xWU0--ozzYHK`xMD8=Tcd#zU%FLuwbnjm`H=?(WE -z*)Qx~vh&dIP+!5#-@MQ0)k32ddXljo68Ck2;bqC4xmUxT2=Pj`}Vh^AKh24&fKFP -z&)oe3%TK|vOM_Lbdh~S9?s%?bDvz~#5p%oexrClbfv%>s4jw&zvW6j1O#jG+1Yo=m -z!B|=(l>B?Jw%P3s5O|nr28@|pFB%YtllZK*J;wi6_5-^L0hHx~u_%0sYXP~gk3K?{ -zprdbwt_gl9@+uM;jswg;D-g(v -z6ehv8vtzZowz{7^PT-j+J$5yjyPE%7@Jvtko!q21_=*0{Za&5Y`AgsGLMR^MUxJmvsfD2Rt -z8f{PEKmX8+*kt@7x^^!cJA}e7HYTY1u&2Y1 -z3*rDpK9rzjN_hmle7o4Su_vl(t}ePZY-Q)1ej03H>sHxdHhO4FN|@$DF_@qVxCGWd -z*ouJwOnQPy3hPUFo;dr_%S8gj$3c5hs% -z`Ai+8^AbqAhOx7Akn>QoA$;i@=6Dh!XE5_~h;Rx$K(w5iT>!9VLjxlN?W2Q2dS)m> -zS;Q1@#fy1FtYWU+vit6~%Drkg?2eNdGxX+^0)s+hhPxEDZJrKlkX9em0-|ENTfo|$ -z8@AYAF_W(wlnHy6f;xh8@@ada>r1d;3DJYkYP!8@`j2hUc6C=d@x -zJj4?iLchL*84i85dud*~_zPA#H>Nuw32X>vI|7!)Y`kFHYdb|rv2C&aC&pN%Ljx`m -zpV<|aWMuXQ&;ZPGU3ITmv1?pm?#QqlTuZQwjJi^Ln?|P4F(bblN2Lgs@R$n}YUAh> -zX8RS|*G;3+!_-|G9BmwtPNieV<*xE)Nix{xH;q>zI)M;D%$o2W_6=i{aUak9Xwyj6 -zo56EJhumYqVBU4~faUKr-iJHcUMXMfX( -zU{J2~BxaydZlO|cfeK%y;GvaH!egaCL2eiN+to|jca*Nia5R}@ki$)iBCzu -z3a50_*fcv;le5|=N+!Wy<#d}g??U)dAij<1GA5NsNzAXrh@`|RvzC1fM=G2^1Ok#c -zmB+gzd)#FHB%>V9RlHm?bo?+0SNG}+g%;Hm)^timl8O=3@j&L&whp7rFZV7otL@1`l8%;b8ZHAA8Y2MKO=&(p)7Yrfo({8%9iPMoim` -zm{yCPmW-GdjF^^;n9eX_S}|f;GGbaX!g`Qn7E)!-y}}Cq-{0+jR(;Z2Of7B}wdvHS -zX%8<_J0#>@gB$~@a -zc||!q3D52ak`FS_?fq3b|Bd1{ZSMio+E`l;{3JWW6Y;@)lEenV8N96rd?*Kd^CoKf -z(x#hTL37>#TK*tbdY-`d8|!Iv1V3%g?WgUt_i02V5fRgDtPPNqD3-C5Ul~yKY5uf1 -z?4MRgJ6w>0r9gQVy=TLPB -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 -zfDU)=*49>6f9KZX@Uc<~j(@6k)>j -z>rh-p_0Ha2IYB^KnJhdYE|jHtl*}mC(z$lmTQAkfwnp}N -zUm6FvG-VE4yA!m{W_QCe+|wjgU3T!$;GWteR?N{rQN?ZCV9Xtwa%N^1-)7y7iF -zE%YmT~k{$iQ^Y*H$0I%v}Id+f;9v2Br@ydT7@#bcnRjeDpD -zz(i7}no-j@w7)X8jC#@Hr%F@F1JVdH#l){SUZ*?89FUrsi;w3iDZ`s7EQegpjaoNX -zb%>*SeWiXnj{$@huy~fTQFC4iMBUI-tj+V$-uLH{LMTS0bi{bR>D==Ool64i{HCnW -zC1rcB<3^1{%qMXV^x4rko=@_=TPWO)70f4f$UNZPoKp7(7-e&Ao3@$Cu3SCgTM6Dy -zGnW)5>|R&qBAIz-&lS_hZqI!Pw@94d5^HhU7t>eAbYgqQfkj4DFayVDy?cs6MY+gsHy$2be -zW8&C65Abak-`v{la+c4hPt%QM(Us|4uJ#hSHJ2ndV;;%%<75=_IkiFVw35A*Ych+@ -zF+sc)1{=DUMXPVjsMM6y%}5qNG)1C1jQaiWuQb~t=BRXM4Ty6$7@oCT-a9dM59|1* -zK2td(RHi$Ui1Dvet)vdmOH9nWGi11Hd}>M>%Cwt*TStAgAtKE=D4g5I<8Smyetd3; -zhB7a@|J1$gE>hB&$(qEqoOSkIN%S!kB<}{ -zvc?!#^_qo<>3KIR?8M&o<^smd06B11EGy2kuYbhil7EuzC`($1?6DRt2;DCb$X$ST&RfJcWSfhdV$g_fvIW}G*s9^ -z?KX`N_ZH~6NS*K4O1r`*iY|8`&!}AO5cylVi2K4z6XxJgdHB7_yfp^wOSr^vh^N1o -zX%dx2|pdI^I+O(yZy~PfTIy^r#Hxw^Utb1Gm1>Vxc -z#n!HFO=dpv5e_r6XgHwdze_gwwAIe3i=CIK1L(StM^kEUmjd}P*KrE1_>6tAZ;oB% -zGTp6hucyOXmlL9?rQ#Y1-60<`7#I~VS4_^}x?N7o`vILo4)L`1_*x+biGESyu!KvI -z6UGv>28PAKfoAff%ZtK9FZaNOM41hUmxp2ScvUr-h$-xCD}24+&Gw6!k)q1Db+rAv2fagcNEypI<**l -z8JG~F%LlV6(bR1@>$N9`GgjuOYLKAClu)}DsTr*CCdSpEee6?dv0-35!R$2vyJ)nbOO>P|byj -zG4`DPfNSs*RcS@58#hP;FjHJ4^8g6SRVa)_E^ccq+oY$apEQ6iC-KV;0uS -z1AEc>R=MBp0;5NtWgU?OF>mL)Q$~?$g|41z!}Nz}v)?mHdluPO%W0nm10=zWEi`0~ -z*yx)LKknvAbLCDV>EeyOwK4!_MT?JpNLOr~|IzqB5K7q-Jji$-yKpTnT74woymX9C -zG)|Ro&|vIB$J4qP!X+(=S2gS_Th0Tr@z -ziE>L>Fk3umM~n%fF}B?g1Y{Y!ke$_WaljU~yK3VioqF`8o0xe5qUo$)_OAkY4LqGG -z`xwCd{i+9J+*25x4O -ziy%DSjSApNBOm6N!uXrp+p7!ghz(U&4lq_6&Sd)=xJ?;?tLtV|-mNX(C1VET4)VoY -z%ah;Z=M66g&LNQZ9lZG94B~+8u}~A_?W`^E78_x1YHUHzNJCcSx|7`SE9wKM(8l`Es`m8Uu;pDwgY2E$*COoektU38vQmV%WGY{c!C -z;NdA4V2gOFtwBjmBIqCGV0bL}0H=qnDYlP+BKF7trvpM0Iq7uGeU=HPH(A9zYK@ks -z4z*?Oo)s}8YU9Iyd*>%9{7Lvr;7^(74E{L$MW=Von-hZ(@YliT)3d%627dAp`~&}= -zoA|{1G5E{PyYs%o-+}oiA(DRA5UI}iDms1Om1FY>4IPPj7a{)iKYsB({C@fVN6p$2 -zG;taK#cS4s+ralRw%3-hwHk_yoWn!K)7#X{ek((w(o19J{t{>}Ba1S<^?#!CxR4%L -z`-9ue&afbh*3!d6J-K3M$Tn^)gh@h*=G)&wtqsbALq`kVE_gP=n?FIfgKnvX44jz( -z%fQa3Ibgg}5x%-*GFn^P+*#nc8kwxl>9yJbRih-dvoQz$n^<-_ct2BQyW@nZGsw-w -z0Hm)WEnfGqxJ>pg&MWDDsm*N)YeySi6TJB`7AG)b;8jXy#9YP@1dG!x6-Nn;Rb>s` -zOew}}rJy;i!!e3ZMn{7US5~*S$qGQG<2Y;?E&4?a9-uyn299Z1qq)o467lJJv$-pu%~ -zfBfkm)rdU9lH^cPQm_Vn@7pFjP_r~mZXyPv)D -z*`HPty~?s4WT)Cs{yD3D{u&cOs#~;zfA-0H&mRBq*(ZPU?D0>YJ^uLF5u -ze}>>E?>>9{WBc&Iv&TQGeEHy-KRjKm6jo&wu*) -z$6x&M7w>=mcQb^Y`kP*i*vADNT%OR^PSMuygXN{#+Nu@p^^GlDkU(9abz=EUs?b2F -z>C7W4FY}1{%sdL00JWd}tmo$^q6(DwP%rbL4Bi6yU+}=BJyR{68VYI -z?qJP>IYq!g=AuncpvPE>SDx@(zsfUq%wv$8{Cur9Iahkk23)!ite-twT8O+y+6q$E -zd>}ABDuoOr10~2IXYTE5Uc0d{0)>d{Z58q?DPSbmVgW7+3=KFi)|M&|8J=j_lo_sW -zFXTmw-_$Cw(E(>h-ve}5!M7#wH8Ynpjbs61u-1J36>qd#-W<5p7hMdytgq+>Mal)N -zt-$C38*E@K#Za%GnYZS2zyb~!y@ANMsr9TF;%R!f<&ix*;oayykI}pw`IV`I_QkKy -z`8b0@BAN8IceFSGZS7c4i`4tFEtPJadXMuH&^CfA)0=W|Cb=!3Ua3?aX&B~ODl>L6 -zQeB~;Hh2Jx&UJ= -z(@KNSOp3P;9FkL}+wfNHtc2@Zn_CN*X}4&do$v3x`Rez~C1!p&_B;o-|6vz2{9xvN -zWi)`3!J`^o8HGgFUlAQtJ#+k=%VH^ -zG~b;SRkTEOxKS=Qn>zs6tnD3sZr0nov9SR94P;7{eq?DcA4g12jBCZd(Biyf)F6uk -zhO^U!ku_>eqvO5&>c?^fX{_LNqZ8RVrz^mK2o(Xxb#1i;v}3+#ZySk+0cAKGHin~< -z`r77NDfnwQ!7&0euk3afVLOh6y)PnJ90{AcBeGbz#ND^OoW?&yn8<46#|XlkZe-q# -zc+^OEUSEs3Y6<9PM)@9qn+{k{ -zh2hHjCZ^Y0;PksA23mnDSI|bpk3~$<)+1s!I&4(twNbX+M#6erS8OA--vW!r>nRNhAz?U))B6m|imLF`bu9pe6)^~Q0(OWor -zf%YD0;#P%&u}+_{*gR)3q|wjdxwmoCtp?C*M1k|bk}Ts>TBBuQ!c4LBU$5;>^A -zsR+viD(p%bqhxY$HuDmXBBGKa;+EuG`DGQjUxrkut&_|hALC3UV1a2sCkyfcIEX$5 -z%r?j*_E9YkV~9#e6AoUK6hp8rd!qO^F8KUr0D`En?8Jul!_~i=*4%0A3qM -z*!2b!v6a5Azw3p#LXnAm5|w$>V$44$DRCuwwKQw&R> -z=#w6X$0D=c8dYI+z$8?QwfvkA6-qkc>*ztGXIIoq^`3$qAT|9Kg;^OBS8HEHI2k|` -z5&=9$B=VxfgW@HSxKEF^b^&(_@UKj-&Z91;raTS`ylq`$k4Fr8seX1N7*$a3 -zY*P*)l4^n@IdZ@;1AmG+c#yj1A*k6nGH?R_8CxA`ZsE1U&^N(T3{V^f*z0!M4OxRS;;SWE;96?r1?tm7U{G^*#t_&W%Gf;Bv}Oy8y>eUuFcK3gwK#Q -z^fe1sHC-!Geb-?Lq9%54w_RBgTKUMsuzYTdxUVX2b8V*+tYUDJiCqqb%D|O2@Qf7D -zaz#F3w$Z>Y_3aXnDP~%Q$FX!8AEi0Kp#jA_@cSgau`=dR+Sqe2_4>dX0f=eE7!J(L -z_#y(`+BVOH>Uz|wyyL4ZMCh@wk_MfI5dHKLQ?cEskpYQwiFnx)0Y*v7K2OT8WE<0G -z9OrgjUamE5Myd-2DQ)3RZ8D50(2X1?MF*JdH?v0Qg;$8*YL(bRrBYhAtym6@WXq7KTTP=nqV0p#669d$kqOYygJlc6 -z-(Cr*z8(O0%##MN -zqxv%G@lgqmfG?1?1l!CE{REi~=DJgn=SPJAD*>#()S6@=+N)NthR{f0m@5Zp*9klz -zfI{3P5aJVVM&~wBk)q#Uely^$Tn-Wgg1O_WV2oR+1(}2;Wd=|7uk52>6C*vea{>%f -zOY8dP4U0T>6H#F+56b2Wc`wvZR@BK(2SvaYIjk;1ZB)Hc;IIoJO{` -zQV32&SI_&}=@@j0f;R4v)*z@_TC6J}YF(>pY5ak))PrTmn$8H6LlNG$#5=s=WRvU! -zp16@L={X#S!0{9McL+V7I1o!iynMS5`qTzN7@!Kg5b&=APWyYNr#%xw$w2z8>Lj`{ -zsDgAPWm2gK4Llgx%n%c1BWIy#IL)aC(TZO^RG^Ga4WMJn*xWm#)xALxN%~Q%ZVMe#yJt&|BtH;)KYzvLE!Y;S=H|Iy^$BdDyYSI7 -z7y=C}fSwT-UAPvR8Rul)lbMl~k$JxMa?G?OS1XFE4>RdOvX!)EJImSSgGh>8*-*Q- -z`@l6l&zpM07s$qFrawde^Z3Zf^L1|(x_hQ+=mv1ZJ>x`1MtFF*dw96V@KkMj7|I=H -zfq^LvJBD8O&z*qFKr70;=%1lww>5A06P={WOOP5WV!RGg92|thLZT^cgnlRu*mnj7QB7UI3etd=Jz=Je -zn5rs*h7p;|QruBCVmLE~si#Rrol6d2m^QQk`cZDWYUa%cX;+%f9fdWcq|hsGl3@hQ -z6wZXe`Xt&hSgm`(6#~DtdB_QU4sA4&s(UU*dq&c_&z5B@)77|?RI2?k3lf?vGCTj$ -zWS7Q%G>-H22}ud;{@SR8QPyQeN}=DhC0qtP-E+rDv}gvFF>F!tx|36-r&vw4V|eaf -z+K~7?*2b1f;?4OpP!|=zt85Krz8R!Xz{Jux6{pli%|ELNkBfNr0de2f?&d~h%F=%0 -zv=}Rj8K`wu%O2FdE>Fk>k$|hPbmzKk^@#E+!g3rS6IH>#u)_6h+bdFAIba~pa&cl7 -zS_0*gHY`odX2V`9mvT&#On;}7z^G)O)kNuOv1VQFQ8MZ2P2 -z<4n~n1_sNG)AH*f%dC(?Nedl$p#hTtWT&gVuI-rSETDFKRyE -zO587NCxVkS8K?)YnHFCaYm~1Ec -zB=^&l_c|vC9@K^Tq9QbV0u%sR!&8U=L{Hk)CEFQTl$c^fUn=mZV@!;i6V9s|;<(w8WNkk6hJE)eEFityU -z@UsBNpUn}ruVFEn^fDVv#G+Zk5HbTFo>Nn~nN+VIyflaQJo^<36lPI^lm -zqs-U$-%GgQK!Hb^P$ZqR0lROD=#-`9UbqEz>Ra3Sz{|!!Wui%g6JLV^;|MHj9{<{l -zt_JL>hd>UF>C8qz-~tvYe}456$}B_Lc;qH7l$e24#*)Qc*DXCr9KM3#Cq|5Q)+2|{ -zX9LjLpZ$>r6Q>*19%C7i#hEFhegzofKhyq;F_GsXG!>=P1B_GgdYpX|Xq7;WASnl` -z>07mL84R_>4aR%v4s0Ckj~%T@Vu^=#Gsf^az*G#VOlQ`nX#f@r0K)w)wUfHAtI7r -z9V_f$8zLo=?>XoI7pzx;Gm$r|-eh7>O>ehjglhW(BWq75%EdP9Q4qGwG%P -zcB~SH93Gg0#PUE71I~^jFa7{QJ=v(@M9xW96j>TV!MZp7DhhgRF(k4L5w6P0?af`4 -zms5*=ZRIK|_2k$!jiDiC#$6k$B2(5)mzaNNdNReKW7Q5Ue^?&IvT8x25C|)qO>vwd -z0+uxuwB4spxCbYNeZq_WK%}`d_5w1C%jsi;5e;#?sc{prC?fHcmJ(>QN3EP5Wg$;- -z1lx&srgFl7P`u=7S5!)r-iC-m&5ZNx%byRj@ -ziEY^&?)ec-n$8_a(+(vYQEco2Q@lPj -zk_zIEeSpFofX<}frGVu_Kl4FY-tdm8{6ihX*htC^0|`5{u@jf|Uh%Y5Kpbu0P!g=r -zDeIllR9Q&0DNl<^`Iy0Cjp#*%f&^SyK#HQW3QQEF2FgXw!XL_OhHDv_-ah3c8%rj^(f3ph&tb6bvxS9*8oPlJ1B}M+S*=0B7h(g2QC1tUA0{Jd -z&=1&Z65^O&2#k)0HyXAmZ}{25hLzc%(>I4N_u8ySZGMe*hoDS+21QJF^Ou7)MReEp -zCp)e+LROvwz#ks2egQ-RTxh?vqTG-0i)TSu(H2q{7U%^e1Giz> -z83YWtwnB1d&al|!z?7ZY(!2Scm_yFUk1KKkVvXLo(-Nm)O -z3G0X9Aiv4?I3k!d0Nqm@Q1%#QD8j&9VfP{f!xyv(;MVxg8DIh1SnzP=mVs;(t{(cS -z$B+&pfoxN{0DpjDi+Z@L+DASR+(_mA1dv(!C;9Tj^TQfy6$g15C$e@GhgFfSXc -zS`g?+numcvoZGO+0`HBjXhvF0Z}MEHl1=!zYk~4@0~7fUt&jt+4CGz%0GF -z=Xf^_mv4k7CVY;Kr(fYctiz8Y;jfNLd(g>n2ie0vcij$u!;J)bF`+_5(2n$yc9rmR -zjGpHm{j%3~>j=i-b;z>q?(rJr=2zM4UPAz!57{ypPO7Y5B8>7yaG1hy;HQ|gp~CG0 -zIa`F`XPd*<->KsKq?`9{gKSN}xrwC%hG}oKHYL(gE;N0GdpKo{$pNu&G9Lka!Z{N|a2x`SLcTZZ_Qc@Lw -z*sk)*0E^1KgvTw9LL@URI -z4o)de82lKv9t5^-M!N>Fc{8Fnc=-qfh*_kUodG^c|pFVr;ihQ<@HHLETf9IXpQSR2RII%`=Dw1R$yD|xXaC$Od -zHqY`b_fPD(4Ha`Y2lH7z^A*77!KC37O<*Yt<$pmsocoE3oWN(_1lLLxu3E!dzHMM| -z)(@COEnAZ&6$f0Uh@HoEkAmbZ>J6-_%Dl2x^=m_T-8Ie(uW?jwOf(p|d^#QBjJ596hwNrp*d+Ha?3{+A2FPwqblRyaHF5QumWZVWx -zbh3~A5}rx8JY`+vcm5ek7)@^>BoLQWv65%G@C;*?8}|zfAgP08pUjfgq~Dlkh*aq` -z?OCq1b;Dta32<Dp260873|{%v5>Jli7EuKGQF@u3{K0f*M#kZg|LLY@ClrvjouD3?SbyZ -zppc7{8t36I5UwjcfTPjvh}-ZO5l~9(S#00s%@K?5;<2q+%~Bc%+s-<)=@!@UN#X~J -zK0gJqKy&xgM2lMz6$adyFjK#h@FfL1m9OnXFo(oio(qj_0;AE+Pl`^nABTBcr!(5X -z{1!m4k?q{mcIC;OA?<95MYpuqvfPeB7_T=_c}`?yrkRu)(l@-x8D0^Enl?DTvxq!6 -zvML2J30iyoYKFDLh=tCQhYXl<<;rEQo%f?fs3aps$rHe&fBtOZ-c1np`+`4^LCYa= -zCxGFGglfC}0#-GNZ0Rb1&7=i@Yf71wLUIW_v}T=ltu*xg=B{wzOu#r(Ah{6{3~KKr -zWs&aq#o{pK5j@xY*E42AEi~9iwlk~_c@tPr0g8?eD$$fV4c;R*e*!IMh~j%8Uh%Ow -zoM(}MU&sw)ZwLx-Xs?tOqrDhm;oNP??w(4UvGNe$=<|E)j7NF(qZCW$%VjDoy~hSW -zmc0U7(r8EQWgWSzK&6}t=0E*83{Y(G@gqS9cy+^7*&~cR;wT*lX!eSiN3c$ZGs@JX -zaB`zO;EKnW^Ie74ebnad@D8w=~CV3E@zC;2rpei;^5OtSFC77*7~r$M -zz?f0*D#4UOD^>Ls5SFM1`jN0uzuB^*4}Qtt!Dmmwn{eFV<)pG?<6@m;FnL>!p<X5OWXXODf=LN-jFV(u@1rl=ecCqeGAbqRYv=%|0YDzBxL<*8h*hQBOVgOdQP -z1a__SUaY{V1Q+lkFAQg%Rh;u@cJu(`m9F{JBB;Q+Lvm8qkD`91G^AMBg~whwQ)w>omw0xR0@ -z>`brVgGfIXA?W3aa)kvb6P$K~yez`+UIq;98wL}ee;X_mC|AP@B(%krE9{jP?M*+f -zUcXBdb)DBZZ>PdV%_cD_(Z1Q**gv`*AXro%Ak+XX@`>C)%!i0_26b&=sD_o0*i#`jYW@BD?Po8qMX-_Iw!B__~Y!Q}0FF{(&dX{{uzy{~78C0y_+B)|<^2`bT%IJ;sy<#;Vl -zDk<8*sRj_d38hv>sH99oPmPMj>&*H^i)XMltK -zgU~}iEARl)H0KVm+ydwJ4%MG5+IO#7ZL66o#EGq$S9=6oM7?Pbm~dAiI14u63c`O8 -zy6TdYSLHTv0w)~EAi+&Q>zU3KJazQHs#oluS93$e(zrE1H -zI2OR|*)$MFW;VnIkngW~qqwi;oiYG~=6=ATnCNkeUEO;`Et?5#9=&wL_d4jkgQkXb -z9U%M~bU44~0yEE%6-u-L5X%5a%pH&+qAmi2)B(WM;2~{V8hR&qj5n4OCf8-pwi#~C -z9P|Xl$c;Ky#WX-aTMhI}*Z7K*H_Vl>+^MXSh0*5KEOH)W%Gf7VZ$nUpD1>j4V*^LQ -zK@cH~#P2LarV@^ool)K47LbHkT(Uo8gfsRTSoUxw>#m{?@68BCXNrcVc!TV{Kp{$4 -z9KEXVxN(dd`V|@^KznS|BRY1L?{VQ-t-)XloTbxXtRRDsaB;wG06Rw{k8sXD0b=W1lBUMWAaDquFMriH*8D~oo>U7$;^eG>?8 -z0RNc_sFG&>5Vl4?>W>-VeoUGqBoR_ZQqenDg&=9E40@>yP)AfCR>C$@(RM+7#a$kY -zfz``;odKw!{8(2=f?;HI4{^iOd~V%q@-@cU-7=}Mn0gO7_U4IjDae8;y&wKCwNr)@ -zD$;mRH?{QlsgdShN5roDm2$?!-KuLl7(h&=fL#%D7{HqqdS+y??qp8)$XQF{$g3If -zyjMg4A((60Gf*=~+<>u+9XvmZqz4UnL&nkGyIaLul078HzBT*v*3=f5-@? -z#48%KE{E4v$UnT{5)rkllY#tM1l8+CEjNFoStd2$)^mekF*ihXL<0E|K4aKy-NiFD -z#Y3R2p>NvrWJ4ZsJqZN^LTF-(X6LOHyIAorRRI8DK%T$bli74?1*3fb8`5zh&BC{3 -zywC{Y1?N3mwW%WOLSicuf=?Fv=L0t)gCQaN{OsH#`odJPt_~JJ;F&9&KXXh7(B;{g -zFF$_#*q5K2U;4L-I7$5j@Y12Po5K$JMKo%!(-|l)>;4&*isND);YnTjJE~w;I5-l* -zKS>2K*dCJe;8AYxN0`GV8I+4+?IGF3jp{oZwm{kkwm=V0AUYPJ@0V2(Jxt3rSof?L -z2M@8_2eUbS?TeYP*U1dfcRWjj;11`G>$z0?U2ILf{Ej`>>4?sRcOoHBC`x4G2 -zN*RC^M@M1b0*}QS3VK7Uww3|J7bv-03VS4FfHEjoxjj2JpmW6NQL6M`#d4#g7_iBZ -zB2?>t1|;IE}wM4&zcvyvk7k5|sT2Vm{Vj5f)s3g(4i+-EgjnI2c>UFoiUu@?!) -zu`F@`#DcLMqtM!Wfgw#ds_Ji})wpzFo!i)O7a~~gWyGp*wA$fju%j{@ni#cAdjt!U -zBoXkkCD`bF{r5l?3}ip{w^FSqe8Bcl!yj@Oq|<{L;?wsKr1in0%uwq*=jyH<9EH_Z -z4WU&Rw -zsL4r=?FI;%8XO;6Twbk$7V11D(%_rT1hlv~>u0hNi;Y{Kgi(_Tt=QmZ8bY2$#=|j{ -zQTTIu5XTG0g&0hOnF7LIpY-sw_hSZ_w<{Ms#N+Huu&|m5z!$uz3?8R}%bG)_UMOzZ -zIL1>;#Y!#0YAh?=`QFNeTLF} -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 -zB`puQA!v-+>TQgK>Wxlz+!TFZ*4t4Mi8tg}L< -z6(_q|`z)GCXH@;%xZLZc$?NtgRY}LkuxU;*G`;o{SW> -zozW&c>PhB6)?QUtdNjB?bXO{(p4*(Y`oq;XV)}F1!H;6%@uNNj-u@TItrDZqu82F3 -zqRJM6qbr!}*ji+!yuY2RE0U~eHS6DJYSb=|?Xzd2pZ@gbh88FcHt5SK3Rm;X@wI-( -ze2dG2Td1P<`WT%)oXXkFJM2j9YVfM8NPWZJa%03yTK&}No2i-_Pf&dD4I*tsW(_a& -z4SLA?y4@LDbz{N>NGJc8wn*6R8;1MYxYN{+ul{EAV^Jd_eu3Lsr-|059BP83tY%zd -z3)T9&jqx15JZ$Wy%_MU?Yod1jnU7Ad^&E~O&8evCv2Stk_3%Q*T{&(!SEJLfxspD; -ze%(P}LU*pWdb9oUqf^A}ZuP^vy(JN}FI=4Nt{r}jlc8ic9JFitXJIl{Q~!SQChg?Y -zY2>dB-Lf*@IjXaI;}`dc3+i^dh3#e$;wcs5MV@lhT)AvVH#b7dQqMY*&*8gwY~Kby -zrdk8|R4;--ADv>`#OWJNss)T#3_SBCw)um3{Pe -zvq)4Qoo%#1{U-y8JqaoH00)czfOzr8`Fs>!o=x|s8aLeeL(>00Ce+Ub@%s!3#q$Z2 -zYselENy%+?bbowGL|4s){ub_&^j-ShpR$YU$#G4)8p%J$4_=)LPE(OSNGp{jPddF5roMl8|P`fIazsxUxSm6Ru`ppE#3d+1Np(W`}D~Q6#E&B1pMPbV>sOGt5|`E0YiNh8*LHydc1 -zji=Q43SI+S&81sS*+HPrmZF)-mVG>3OeS1p^XEypJ=`{V+*P-X#yf&92#ub%>TxNI -zH6G=uQZB9uz}AM3xOXp~ko+mXO+_mrQz^2OCz~iwU%hclZQd60#qrA&*T{0sd-Cy} -zn>pDY2~LmGaL9&}v>`f4uXnxhGHOVIz_=dKI9L+0FYY@D;>^?UUL0RH&9%y|(&_xF -z$h)-8u1?R-9zB2b=;_vP?0fQb@GJh&IaS{3v3W~4qP!#UXzr*S&Hy4)A(s`~-y_sP -zsPS8WChGXsIx}RTlxZYVMjr0BtK29IEp^4y#O@Cs&-5$>_u26bQrNeO)$bR_{DJag -zh-mLVcz<_ec{%mYLhFfikauxX`e08_exHZ@BRh~Exqg3y<0)F6TR%Cy -zeD57N$yiC!?G0P?JZrfeu?|<7J5aQF(M#jJC}Jg=bjP#0n@nibcRbNW4)%Ff*4>V$ -zr7CETLKT -zegOOxZIb2D2S>71y8bxe}{$R8HVJmO+N&IWy -zt6@)UAMZXn!LSg`0ek%F!RGsJX>RzX!Nd>RJ)(Kocv0Byux|MEo4-4{?T4-_JAQbm -z2f>%Q7Ki}g?rJvON^y=h*}gc20hfuy{AP37OPU6a7=oLPnd+Xn-n{KC(s+wj4%NSn -z+~1;|xBV?`^jD%H@+5(TR{a&Lh8xTOEt+AQ*d`a*ti*awOT5nP8vE-a>{!mMoMiu$ -zcG#Echg|T=!}F0q(jC5ga1@rhi~04*D2TPP=Piz3hm*q|RAPGq#q^=Xao%AW;ZE&FlhYu_|62gL1Pd5 -z-|QRe&2RX&<;!p+*5i_|eON}=_@0h;*Hda_Y0<&q8oE)DDHlm#tB9=uY(g=oDlYP;cS#qdfHw*UB(x6b!+YOtgYL#{L$=b -z`D}S>?Mty(o)=G5KG%=S+k4VJ6_@K+oj-XZp5NYf`{?!a=4|yuoWo`CwtlN+l5`id -z%f*xHef{Qo=i*|r&Zg_v@@amkUeP^yHmj%4%Y1cqpk6VXl+WVV>$A8%_}Yt=?o@Go -zy_&oh2kKqcv&T=LtGIqWe;V(rmrpA;L)~R9{^8eO{Co_nay88-EBy2hKS~NI8d_pf -zb?p&MbfXF1D?p5081AC8ySD)Ad)8 -z36C@mE>0a1R7*~%DHGU)t+P2H=lR^az|iVUL_=bFG{LPNRf&Zg4#e@m;z=Xit&j`v -zlU!bNw0?JIrO4MhLM%7fyaaB+Pa_{Senvtk{446L5iSFlO5wUo|H()}aGo|@S*}|A -zM~J4iSuqeyxtiio6R8$ByPaqnwXjh^Y43m>Cfe2~$5SeW>E9)6;mqosyq&lN3`@~O -zC2q*`nT)!|O~HPiIXyd@7P1x7(M({QPP!!bDbH3qpO&2swOQwtS~W7kExYjC`iTSaxV~L8H-lw|UlXgGEuOsPuh+9@)nheQ -z;`Q}H)UQ($gkewDss3CQx_v!clqTKa{)*|elC>(#OW=cs3&cb@@0ink(Bj!Lq`OpB2hLq#wY|%JaAq2<*Mk*bx=+?ENdW< -zfA``Twn#QN(<)~6bY-oU8{*sP*ENpHn_U0v|K`S(*T|}J^ZU48RS~;uZ~p2({#SqX -z_x{g+_4oe8U;W4b?O*-9|Nh1(G`V!YPzzD5ZoU+4qp&7Zb^74f`8^Nq_xvt@OK9uO -z@@dBTO!%bickXL?xao+u)_gy&^{0MEtYaMAuh{N?1lj)ni0?wSav@fA=K@1PBgq;$ -zd2xIX8pweftYd|O1J%E|*_0)E?}e>~M&V|=Uz|NX#WejiPhWj&8~|RO4!r{M^yFBi -zhx`V3j!%xuvZY$Rl>1~P*R)+W@}#yN6!4fpTBl~*&JTDx2$BnQ_PIzJrAOs#p15rD -zHKYpm*o12_F3NE3yLNuU{%t1ZDGG#P1U0;Wa~-_Kb^7UO>cZT?+u_7RI_b+&yYjg7 -zMUGIHs}twH9Ap;XKoRlea>4y?5|c!NGbUVI@^{7X3O5eP?Ecy6u|VP{Sr_&?{R!Vf -zL|qyvO3>(cPB9$s3Wjqvxsf -zf2z8>)Ap?ddgpl|&Hu77x(A%C?4`Kx4m8~o=NqgB_LgqS?$G-{8!@j}KNP>UGz+-AXajBnT29B@;uRXuv6 -zUx>*Br^};@G%diMOc$hzCFj3DRxnYUJ3CxuK0PoO{Cew6@%VfsQiAcFqFf!i_zi?!A_sx7P4;hhA&Ln)nKkmLc>Gk|H9tYO>nCj -z(V*ta-1jtCs*k8gsR;-Nu*}`<&jfdodB9UqO>FRoG%*~BZw03kx$mZ=gBHRj2thN1 -zF2&Nuwxu4llD>^LGWu*AB_>MGYzeZp1hk3vW^+WU@ -zh?uUb@>gq3?m2^N@X4jaW#x6ArDF_GpC2tRYfc7(Po5~%#yD@}yVyk7s(%X!3&@A6 -zY+9-*G;X=J*?n{?CV8rCOh(>o>v?UWRl0s%JmNUP4#bGtnC2Eklhz>AqZWGjAh%&A -z9lWw})m`)24xeov7sO0#Z2&YumAyt|VbYxKzyiVirOul|8U38&t~XsSV^PunhNDGV -za!;U*49en#;x658YakJlm*v;B`}YTdmK -zTI#%8_0wgabm@k#JDLVoS4}Kh#{NHiT>``iC9;10o$H_ -zWG=tP!d@+N+!%a`Qwa~EQ_=*eB0>raQi^cffEQ6hv=vj|bENF8U9_+*sgWJlOju*H -z9#f@=MoRNnEAzLtf6dKZE*gHy#X?xr#QxR%*L!deAvA4z4>4ouVzZ=;m?CFNQE^>tKyn;TbYJ4?C|bxmq$#$kSb)Ikn-K^(@AbYk&WP8#;9vt-pb02~ -zxNNRZ2J~PuXbn^pq(f`RZC-1n+k#r}xoaizYZ1nFHz8YiFEGKGXL5y0k(Ej>FNU0% -z11j^}AX9>q%AVNF2M#9jHGsgWb&F7_X@^6oaqAy8xomVz63xN~C -zUZf}%ildlV@fzzWl(bRqL*>v9sP~hGxjqXqOqYCbKjFFI7Z{|1<9`pQ@!Ev2rB)d+ -zMK}o?hTgp|u>X -zCsPw?+{=NFMi*XR*u!eA^mw+sc=mL%pO>M+HcC -zVPC$A8^yND_P6-0^lsj+W%C<&zhR)yh%<{RZV3@v@5G6aQz;mjHV`<8Q?F{ZAVIR% -zT1cT@tNAMFW(`smaNHxJwUR`k1o5TjT>;_LS_h>6B@S^>O*>yBi({E{N|J19tFqjQ -zv+pENb5SbVG<0Dj0;PzN9Zyfv6=%1!3M}jUA}*Kbw%A5E-!(vaZC}JYlPtwlI1dxf -zo36TMAybpB)aJbcWL>cWiX0cB79=s?Oj;vz -z3{`~PR2G%6lAb1kK@~XJpV9QiQupae~cpg*2jD -zA@iBh76oE%r0X1}5F97vI7vX56vv;=W-4u5^dtZ5<}Ql^#Z!2TU~!9fVGm_vxT -zkXLZ(#l={lBar8mL-a?jm`UtP4{=d;^HrVMQUoXLvo;x?_kG;C#gt@ -z@kue$?nLY9(YRKQ*OawtSZqkB;Enc-I%WNAwkCasJ8IpMA;)u6J%AIHnxjmhmo+=g-eZ -zIih&N=wgSmA#vgefj!&3H8&ulk~l7$Z(KslxqWwRk0RNJe^N)X$frmH@#?|R -zi=*=+Qt*z#il^|*#G{K>ukQcg_vzpI``+}0c5qew{@aZE-of2C)%~exauKl?Egfu>>btL@QZ#OZ~DPQ{P0_I82*aqjv75B&YDQ@-1pww;WY{djQ+n!RBh}i -z!*g~K`~d6m{#RW=P!6x7xA1#%j2yM^f3Yu(;Kr&;!5Q1vqd7;h2*OmhkwL$!ahe) -zB5)YmAa_cmA{?%9l!1*FdIu(3{R-8IRQrqO=NIRfxRazgXw$*bIyFP&K3FHj>?H(n -zZFu_euDKr68!-DKzkkOUkMHnibD4xm)EF*8n)chy2H9+^)}Z-VL?!J{1$ClO5XkoS -zmD??77UR{?sc-$%T2y+`l4rq)rx9WpNIwNno?MP%3GqK~wKJ{qL3?T<`Zg}-Pr{CO -zb3Qnm -z2(F{Q@|XKjf=Xxcz?g6cHp{fX2Z-&a|FKzWc2vq#uHgO5_U_{yzu)!J9u35|2)RMj -zAAIz^fzuaH5AUg>Yw_UCA_0LEz+V3~x9FPzoWQKOJS5ZiH=d`uDe~`!_onjf>hkwX(6Y?5{~XOAv1e%(JNjtao_h{c>HLz5JkC~v`(iV!7#x^ -zIGXi-b!~D&u*vf6UFm!cBoFBUSa?nZGO{K!IKCiAGOu%sGiQ*Dr4QSIOmLgXB&IY+pEFhFvqacvRi&7FH_kF&!ZQxPEA7jXYTg5ruJYwP -z>3o^DF%NNy0S~p3KHLHB^u7#&BbO`JqUy`^&5Ec&bxCHN&alFTrG+>P*a~Avd8j*nn$GMsQ=YNzUjo(q`HRV;j>N -z>CM>T)238(5T~m$UmB1!_hf+e&2QH1v8@=_@+2T;pJmOjkO1rxxiLtiys->=(0vM4 -z6Jbqj>_zP$lPuK&Jk1vHqae4v101||{#uKuU*vpZKMcga5ykwl%j<}}vG`&fynTLi -z+yYm^tSFnDzl -zR5x+rhQHC=9Rr%@61Oo2nBW%%!QUJrIJ-L)s=T@uCO_fda2~dgZ*6dsx8Y=#J>H3b -z^?ZPFCad6%Y;6ZJvCZ@Pty8lRq1i>rzByYd!)WcQwebTBJ+J~-reFuZ&7b`@$Q^$N -zsBK6uL)zOQtxY-&cGQ5jhE#edYP;iH2{k(BC>_XV%}ugvdFylKv6FhaYL_;)ep}X; -z(l}8*w*m3h$vUs=l_42CFrIMcUE7Ge#}DU=8LH_@O`9I9LTr-k6AbwK9vliKNN@>) -z&w%tfAY4+4EHyFy55CynVHx?XE(fK9MLvyctB>q=v?GG_wfcq;>Gwdx*&P~&szmD0 -zFSz0DAfN~Q?*2d^couzKN#aGPv(a46S&))*&l74E#;MfRhys1sopFJq_r>_?>eHWp -z`pu^=KfC(+o0s2wa&Jx2LrOWgX3G4Jiv(ja;UMm0d~}e&F~G(%O=I1~SP8r`=c^Ly>AI -zZta$v?m(v>`MXw#kaqdV4sI#Xa!6r&F2A{U-sDzSIL7{gLnYP{!b8G0cb&hrS7D|qS*9Ix6SRhsqu -zCM{h5z-oi6KrXTG|`r)ol9Jm*eeDyNb`yVgAI{5TU -z_2tX->rp5%%sVX6+oNUdxP^N3Kl}W%KWN+fD;xFzt08Gtb&C}r00-7bu3wssGe~<8 -z@}Gk)$;3-ZjFO~V68DjLMN61iTc0fU{L#60$~=D-B=9|dwvuLbpVzreWbl(3o-qVR -z0nQ~P_8P&t&#&WAmtl(1OC;yToR%++-{TR@HnIP>Fx$7%wugzqUjeR4sCXa$_zG5a?-Oci-QqfA;crBuM%?L&8O5(zMrv-Oo5FlFQRdu*o=0MC{t=SoA}JBG;^H{rK1?w5woa -z3sJEY#AoVNh~vceKFg9tPE4%h5Yw4^knXki-a7497Gp9x1?{YnLJS#?oD$7)8g^!X -zHHiTj+!%6+#2J_&6ac>vkU}CU6344bK`xX!L25Z$yA^YxE5VtuGhwfHh^oVtahus# -zRI7gY6oL>1RMLoeSuJfDZU9#11d0=O`5bvB0rPfpci?qK -zeK*3sm`9uw);#N%6DOFa<>gP#7%^veJPTLTg62}SdBlnJ0xbQ|rG?_#$b>X`24m55 -zxUb)sZpSgx7j95e(PUqy!bI9df--fzwy`wgq#rV5a*X`PG87~P1njbQqRg~ntI8=Z -z;J`7_wDMq&EP9d{!~icTCQtr$!XN>> -zUv!KxIm3G%jQ~_GT{I6<-lSb9_0x9lfl0A~yhNqoWAGt^g!Kl48d2?%`7zF|E6$vNs0x8E=vxb5cfg{n4P!JX}07sYsK!jr`Xoa+VmV>HKZU6|zCg6b#B9 -z!@CDe3;~Y!0Fw;M;Hnnq?zBQT+)z))n_q8tQVbvfyySc*XdYP<4dRJ_$JY`XzUdNWN$6fFs-LW -z!DBvIOUUO&lVYG(@KZ7Aw_fPL48X3RViL_=Mfgw1y3HCT+CJSQd@3?!2M<8W85~{F -zs$*$B&0CsfDLNu+zbw+c$~nZTsO%;4G;dHLo!Xt7;fXT6W?)KO7yE(kpF2j)fC-e! -z&kEILf`>!k{slbiGht)mF_7DvyHzD3qPavwohofdRJZJzpt)ol;g)S=?mqGliPf$2 -z9C!Vx^{%Xq4W6YD%ZK`es|Kre&zdD9l$9+KMbL7RRNc!Tw8@=6W2KzPf`7$f`bfHN -zlvk!rn#|0`K`@X>DCzfhBWd8+9CKjF)*usA!ELR=ReIYV{4}twI3h%9c2;0Cz{FMGpdt6JawtWgy4*yJCgjh654t7T1Y{Kc(!PjU}Ob2gl -zq>M;jhdj>DqfAPK0rIC*V5RsnzC1 -zG$_%zf8Lu6!Ac0DGZxA#$4(ig6MOD!pp9*9($ua*VvrqjBaLcAVOEt#aVBvl6$0#e -zv_lKhv!^hXs-37M@TwF2dcfuWz -z!x$!3hSeg@lUO;T<$8$6W_$y}3-?G>r;J!L&14HRm~f)VG@p<*magn={HEaCPNjXA=U3O+rGm$A)nKBdWs*6n=$`fRPMiw+Ly=RHf -z%bukXCY_H?N%p0dd&dhea2xvIKluNUl6V( -z%fpnvj0NKlDAzy8n?^N$LuAjH(ijme%=RAhG>;|tDRLv`6R9Sxp|ipbHwH6x5rFeV -zy6r26ct_Lg=>+mZ5hPM)IIx)HkahXEDKCj_GyhIK9B6o -zQt|THnJYr4zbNm7v(z1c{Q2q4i9#~oZ^?=0(|;A9mlTDv}#Y&Z}$ -zD8Yw87RuME(z+91k*>jN3}9Oq$oE65qxZ0Z9eJjlP*tIm#N#iue?O -z=GMeo$VIxaM*`HvjtIgS*>|{$(D(2`DA&DC>_HIC)YNRPL?&h)6O&{4r08tuZmvhe -zX%>|^w#)z(71^&lCep?Abb?)a@w- -zvRsvcS+05jcU%I9HsQkdk3dUq>`uqIRB46fzIwJ0Mm~o!IP0`~0BU(;8$p@Hrmk{X -zDSKqUJsTVmRxjRpl;1#0vGmq$hErzPW*!kAjZ?zYO0!BAuKpqr_{vPaJ;NjQlm5w5 -ztQH=-oOTdm$C1$p%r8ljx;#7cWsXw?vM&pzW=3AI9ak|euh+I*20VzMa8eKZ^PhKy-L}6TN}F!pJUxm}#&i3iq`;Jy+|z -zBqCc#?|)vdh*~Y-te~~hV-bSRdPXn?caC5;(|)%oSCFY(jo(EdDhMRroN1QZD)`EN -zzE*4>#~L;8T9D#6vFx1fJl>$s0wtr&r1r3(>oGCbl|jHCKCrx2IBFQc-85@gYs|@b -zEly}AX?D$oRXGgl%T;d!B}^7bs}-&+U|{`p(MqjyX=tV*!m2XlTApA8GHY@owCZOa -zkWs6Jhn?_;jPkINwdw>yNyKLpy;YHMV0qE`GmkKaVK3`=eCk9i09YD`oaGU7l9|L< -zv;h#y07#7CY>23f070964`4a;kmi;U+|q0y%ItBf0*fc2BlVV#-^{U86r9$(C;Y&> -zU;~TeImdF$AER8m{m|e5T|BZsa)?f6GZElIYlIEEX?OtvD+Da-Jpc*ebh!Yr@_|Db -zk@>9Nn=XTDQE-S}c2p*r3|IIOtFhmfYBVkFa%Zh9s%2AJP?~-wChntv4(87=p!Vtr -zfdYKsVPN8J)wLZqOj9Xvmqu8~E%#|4W-To=7E%aq5%Lqyy;xjlf-0oxDm-7P5!1~J -z0X+nlZIZ89HZ)$7#(wGS=%#ihRxaup%5xgBf~IBZP`!^64PU?fdIPgDeZYykG!rGagnNCwW% -z`|^_~Px@c6nZU78#>CB-oofx0CC@gps_zWt36A5L`)taMah^`EvWiVo4Zb=*yq8!VOSf`n$C-UeA-|RTYHe|wr(S$ -zGGD!hof;)R({QIGKn$JxfLTeA`N!*i80N%SNFg#%L*uY?Cs+xGWc1N!UxljD-GUU)Hq)C84%#oW5Z-RjEHUu`J1&4PL*-%>+~Iq-;o^ -zwj;olr2onz+Adr553n!LgBrowEfEskdY`vUNX$ -zIM4+CE)6NV@DggeIJT-ugGFc^6FTQSfkPgkoG@_*-D!#so)(I>%v#6T18usL`J2|#wr%HtVN&#Yhm*V -z824VW=sgZdt1L)L=o|zaBu%c(`=n`}s+3B!Ypcn$;2X=fs_gAyR8F5fx5b&rS(P_? -z5W%|X8ewB9SAlq{rRs{vYWz{!bktvjWFRRk%k -z(86eLjB$>^-a>3m)7BJE@`3SlN%;JYjmkPF7UeZ^A|`j{&Oay7u3A}l1zkw7mi-Zd -zE>%mb(d=xHp@n7I8VMT3GAbmID5<4!?!&O-5!W{s!Yb#rqZO&O#J-X1Kv}DUu2<1A -zGUsys*Y#?yR?ZoMsH~XDCT?NfCsDtE6vP*w`S*NU5jhfO$i|QFz3!dtuDdwR=a!_p -zxXd})XauvXc~ysKe6p9CIY}Gafth?rY;pr`iu|LsT+U=IXCCT}o@}Ue_F6vRwGKin -z8(n;v+n!s0rO4M_o*RGm_CPy#c0q@Mq+$EV^mO -zu3K#;?B3GKvZif$YSjh4Hv+~+DiDZ9XxP_M(IPBd=)~A&G;RS+0d@{YVuB29nS|Qt -zqNrywaOChi1fdNr5L@%qjTk0!H%ILXWa -zR-%zvH+5g2+RSxQbx@{ydTR3=w~mQx_M1;zh9=Ke&7#(8&;+eGn;<->buicpWI^jc -zb@pAt#8D%V*)>$^3JACA%^EG~qW$l6aQcWgLMK^gb9CYb -zv*>kC9t19x3BMn^G>vU%<{}K?-!-wC2L4^`-0_o+6NR9OE?+~Zz#ouNSGZF*b}{73 -z?S=Eh>#CdtJSt-L -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 -zAJ(Q63PZj>P^g~*~D-FoXuF*gCNy| -zz}L8B%wc%$aBBDiPmXR&YH(`=`djpeSWJb!Jm;g0gSsZwZA24KIbb*n7iZ_sxo-@K -zB$4+13B&MT>Y=H1FExPb%O-@3F{lOb#&he3!5A~N0l4geHfT8%Y#4zs8V8r~XSw`X -zw#J+apK^0&;Sj(6h?7~d4cj~L?XN%B5IClIJ3nF95~_E2n)dPwA1^*o!Vl)F7qj^48x9^+S;YNeBaBF*gGfW7V_ulM$E|9nVCEZrl*2$t;cTH}5sfd+N -zd%lmNLA%R3VUCEoJApBG1hTxn!_Hi;N7GdDB?TL#%|pDY@d;F9XaI><5t8Es75KUw -z{x)#-Kml$rC>Z6>l*}DPF53F$#*8WPbuljC(i*=tV%greV4N>?o#@DT25}k~0>?4j -zLQpVXfTqk|Qd}zSUwRokI$2<$O$pxhrT`xi6b$>akB#^YvsGSSuq%ow;UEf9zuvL} -zZ!J-K+QO%U$RW*A^%oUR0S}9{S67XE-Q|ruI!%1W#?w*B4(l$GO~CkWnP9M^ooiy4 -z#N(E2{tN_%(b;vm@2-a4U6z~N`e?#W(Yb3L(pjOJUtGwMWs*{!ylD#}MLML<1;X!+ -z;Azb1r0+12?;O2MKjb6{H#g;qO-^Pf^VT#3Q4r3yeEZWz7MqEow@hRu -z3Ep`X(MTgN`_>!xZ7y-E#GNaXLW^EN^4C}R#9LO*n=6DLfAKkvKM403ANn0`|DAyb -zw$+%)@wxGJ_YC%1V=#OVDdoS#ct040fgm_wn7Pk-h;VhhG7Nbn$`!7~*mn#vY%4@6 -z0+}Aa8o>^Hmyv$wT2qC3^usSIyhZvFo#m5uG;}rGKMJ6r!_&0;oO>flN|1Zy4%w7? -zezoaMMr9OTW*k0vnW{myoE^A8%>M!35a&~xbtnayqB)*+Is2huk7f?d-p6p(8tVoj -zA^9Q|+=TgzFX9fd|3N)NREf@*X>>+?oJ?l2B5KUEi#J*+B6HGEXydfSKF$&bE5V&H -zE98-Q*eKOTRUhlnJ1;ewFWgR*yRa4BKsuD*%XnJAaaU7pNfA;k9sWH!1vQP*6 -zxtp7f2Eh>b|C%i>lR}Z6gP2x9wCy*wneJBzVL#>xZX`$kHr`2@6vP)n!l8>x92gXda~EJb;iU -zOD6+z-4oD&IN1yX6&gR^#utF-C|lreJhFlxo}JGZFSRj|dV_Y1Fr~M$-90_HnlDPN -zM#EcnldiuS3d13kYBNH^jMe?+ib8}Vi=a_Kif3I*nT9^U{fZaCWnklnnscPFdeK)3 -z&UIE7@;c?aO~fDY8q8F??z+z6l_(A -zRokjEBJRPCE2rOOv@hzPy!Xq~U!E=&i(ig$)ZCe<&%eZPetG)sS@c{)lUM)I`NiM; -zC4Kto#-|6r;4j{Q5BPtbKMR~w?&Pv~@7}DvGS;f24~~or-K%enG5f{wRa_8fB=K#Z -zjo_9g@$#egb5V_OZ|Yh$Gwd=y8OVr>Jf#<1wQ|`Wzj`kcaUEqszxx5zF_0JcU)nPz -z<`)khjAFIA=DamxuI3f4%h=0 -z(L!u+wb6(@%S=+JVH(!M6}YSzSZ{62A@wV?mt>8Vl&0+~T_g9D@$`#has3 -zTy8)_gox%(BTwNJLcse+w_5!|s)rxp=D?gTWXu*ieM%gf#HzZQe)kSzyl=_oZ*FNv -z+_@cd4xdT(Sh^gQ3 -zuk)ljY-bS#l}Gcgn-x~x_m@oAQKWxz+QH=%(p?@)8_5Y-i{P}1cnN&veU{ma!z9>n -z0+w4TV6uq#?3q}JOlhDqs2K$<2l#K&AAC4ArVXN?r4x9D-X9I#XTRaQ7ssrsymxwv -z2*Je)A26(lwoEIe8+ft(#c`VJgyyEzG|kLNw|;q#L_00NgooS5`FwQe?+r=1K}`LZ -zP5Ws%J$|*Z7KjE7%dd6px#}AHFbF}e%ny+J{9_)NfGP5Lo-}P%}or=%JX_W01 -z+THIN%=6AF96N;M;bykCl>zPStkDxtxP1=!fE%=9A^_fa?b5m;lDI$WTlgC@3n6Lz -zbx*-vC}Lxp-fkWSjr=$jZ#fk|d_4^N`nx<4zb$(IO-#cfIgmC$j=#(2h~Wn4cfN0b -zD!P_!!-qG)_eZ_M^jjLKktTcIO-7>d$$Jjc%)@VC*n0QDi{qCN4!7mD?cow-E%IrV -zrx<86RIE8@qSm{5SrG@Zr7Bqdq(`Y{QXOJbrLX3j=v&N`Y0CHWKilUaF#73F -zZ*Kat&{LX*MAS4v;#8!Wq4aC*JUs>{rHvXbgEKgm^YWAgLSyfSCi8n<+;dK@+1r -z`>pcC8s@L-9WpwbMaDS8k~9ERhh*--PYx~9BJXuz2=185fFX57u#%{5zx?<|C&waX -z3iz~@;PD3;c6RRB&ChWRPyZgh-;Q4# -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 -z$n9ba1KfFcexGK4G -zEtK^oALtSJuf~GWmmCMBX4VTrv!}*?oK>mnbfp)C>M4}xBlwVlP4qk -zGJ24kuRACxnt|LJeKn!UZ4wUixHVrJ@`{P^t#p;wHG(|e65YCQ`u-dA(j`SEDV>~i50S34&)%?m96=M2JH?5wUH49BYbk)wdIw| -zZu5epEB+>jleh+wp^*F>z6QA?1Mu+Y@jC6P(JdpxkM7)&VY5KWA5TUp?fLn*IB+@cDlH~skuF;?4Qn6B3Ub-sN3~nvZS;y1HrTegk8I@;!EZ;(pDWW_=*nW89~^z~;{4g!+u2wu)uee6kR*4IWQcq`$#3i5)_w55 -zExKC3vLdUaRo2R!I{vT!ADEc&*!**UL>&-?%-Y*tFpU0t_c!oM+WB}s9ap>0JFT7a -z>g9)5S9_BSzx?n}j2oD>^j7|kv&S5sc2SS(V*gV9x=`&`a!NgKM041f`{h@keD=l5 -zkB=G>jOL;lrSSTo){xbCb?_yNnzYLK6^G;2BM~R-lxRMe2Y&>E*4V6ecTX6OL$j_R -zba66Kt%BN|3qUh5k?cmpfFezQrp#GC!6ZDbl2s)x9s$y&NY<6)-vXYBbS+z7`;cK^ -zQNOJ7-)=8%F?P^iVh2ZmxcWv+e=bT%Bljf_+i;{$%veGVB7m67!uf%=3w15?+K|eL -zOtQS`n&}($V_?LaC;1a$?ybdDEyFdB+E6 -z&rNocSN%v5Cph}OBQuE)20z}IfK)u%_Z -zF3GUW@AA_kk8Qrcwrf_jzs&CRyN|N2ng!z!d>T#am@_4ExV3&F!y77?R9YZMFZM)i -zc=tX%z5n2StQmE|lwI#!WoD)g#&4e@)jz|#zY5sIg9iuJs!4XWvn|JJzC@CYOcgZF -z)Kt$QPJW%O1`PD@z7>o-aRvgEPV(J6U}IW0ImUoR4B5<(L<6QXpko#1vUQCQC@g#V_e)Gw=%Ln5%+*VFDWrvgDR^{Hf$KcA# -z_2_JLTgRqi@)gxzy#_3(!7jbyNx31j3U= -z-sr)r-V(O^`KCg_)|n6B4EpMH$I1B{v;@@z4eeG;HrlXFT#~Z#<4o^4RX8wHTXVw} -zA)HOW`+&BTV}1l@h~1NP@tDT_$K__3@SkvKNVSj?F>6=1&&(E48#^as9=v*SeEiC1 -zZGQN`6Z~d?u?H}^9d6~oI@+qdZQeN==6N3e#6I4jj$xe#w09GwFm9K1bdaRkBrf0S -zP6H?RmCp- -zJ%4nzGvy*@#@oGFgMXe41)?IqKd>3zBIxl!oN+#DBbq&7mg719*?o9n$Bd`{jwhy@ -zMt1Jp>DKXxwMrkdw8M5y%GrzKpTGR((?9y;>Sv#P^6~N3iNf9cIPf#Hti^ilz1lo@ -zSkyRqppLgEA<@>Xk_C{?^#3Q!xzVW -zgReH~q-kWV2;YJLzk6}~;me=@{FAS)zWL(I+v|S(#V8Xgj^%Rd68-5(?x?7`6=|j4B~#h#Y?Sm`SAnK_@$tomLggyYu`P -z$MbyN>8puSB*PHH${z0-ku8GdAMVIr%zJ4|7=(g;Eh3T5siW-LeSDk0e_oWUC(pxA -zeQQ72Lnn<*+f6&E37U`6wN{SvM;U=&@Eq+w1jbU)8cY+itsTB$&byr -zou57&PxHw;d}>dExV_gF=ZD(lJERyEsZB5+>wtLs70i+Z&m3WHsCM8C_(ox*uNK)n -zZWn7cN~kjO=^|tS|MHNtDPG^Inr~@NZu6Ah<te-b&ydI+e4Txzat3n;*WwrpnOeK^N)uWNIDJM=^V% -zo2zGUKQv|9wrSnD>&U6nwimK{yB1H)H8x!1I}MzDZ&`D9^!nY$f*PZ`?ea2y6pI8g -zaj@b_p%K^0T&hKfqPVN%fMxv9j&yp5=l{i{N24`qltjs?T#lPA*ab;M%yndTP!coO -z^2+;-)4up89IUJDe|fTjnXNZ5@oE#(iIYFU2~wS@Y85oKRieh+Pkf1*>zlEqNwe_* -ztt_t~T3o@Z7b5AaXd~iJ5%X5f*VAGpQoJ&)a{P%!yuyI&rTD)ih_}xOM_Xc8@z)i< -zfA7iFN_^R<d`zU_@C{b#b%Lt)8NO(9RmKs;O -zc^}9AhyWBJnGyIjtzHE2ksV)0zxnu!&p$FfGsn$0HF0c+L8nLe&zAS!AE|b&=K1XK -zPO>F`e$~bw;+Ez|JV$?QBUDUt%@_SZalT9x>C0u>mk&|Q*85=d{OX$zM_Uv -z+Y;#)LASnl&l7t&jiybWA|>qy!OB3AGm=oRbeE7!r(ca4u`bj)W75BPq|4mI8tj<1 -zPtt~F`U0h?A_=&m55$C@%<@XrD%Z1v-))IK_;As-BFVna1QA3)$Hpx2M!z2U&K?j{ -z`o+iOwncWQ-_fQSe%PDLA#G5Ssm6OuSRViQ`3Q?!6IouEz&=wk73oy&zpuP~YXjGZ -zR|PvSUY^loQgzW2mMKirRb(Wqtw-Nl3rUR-OV!lgPJbHA8W}Y9cBbPF%vpV9ByS>^4-YC&3K5?9jNl#ob; -zrnV5v9#S*SK&Kf7&F<$Mv=23^kXOd=!D{zZWdgmsOquNQ1w#SCN)Aqt;MYeJggQCt -z8ZjKWT~bB4x)wB5R9%&t1PtQO{FbI=P*&fWZ4*#n*Qnq~59f!_}whQQVlw2qTWz -zgXnaJmUg)!G4v{)mLnp(Nv<=*nM_V>>EM23>riJ&1VOl=B%3i~&e=UM!HZA8VJcNx -z;pBubCTh`|u!IxZG6m7S(Yw!C3~=$s)75;XZ;`t8Tt7EQRikOTj_QsiLNT6n)d_(% -zoDoWpq|>!(Z3Qq0AS}p{UOhy05zCYIflS8kG`WX)i!nuFJi5*~I3B%mtyJ9P#Z2rS -zM{CBb>v2p1@mSh*YYr25(;@XV?o9ab{SJ;>BuAhB6|a+*O(Rxr{rF4mb5*RWn)K$w -zWZ07MdId?QB4LKK&V!tKs}EO3JpBTpOJ25ZGn!~!)8;)t$c7-m7jh(ug2Y;A=66@@ -zhc^M(o|~>JQIf8hO91!DvrA=wO$;v&co0@iH|E -z%HUMujXuZT@H!pMy2gw8Zx>XGh&`u2e+>0vH0AIzWqkWMU;hW_(9!9aO6P2WAl^x9 -z4hAaHKI!WaWx*pj{EtEO6>fRMJ7&^!CJ+^RcAHf6&e8cYrgaV@hz$;Ukg}?mqz|Fz -z0vBFHsYhj}^T~=A|E=$$S-e__tGH1MjRO>tNBJ5R2MjFhOI@#SkMk8+jg9S|&DU!~ -zW9JCUXr#!gkn_W9^UGg+j#bVlJfq^GRrT#N_|8#MNKw74Xmche(`XZL@Ky`4wHs}1 -z>iGH2G2H6y#^BAwOs%w>s>`aJU#z}LXM7mU}m -zbZvls2InHBWh0jukdrx$U2||fY#jX*2uX~1zi)kFa36kG-b#9Zlw(tFStNLatxHU% -zwDEM3w42ylHSaKg8nJK|QqJhbb5W_evf3g29JW$=Z&%49GtJ{wi|H95#t=B5MvTiQ -zuZ+-5l8G%Jlz+Zatt`J$s?g>mMww{R1&IYkw_M(tpZ3zrr+i#Va#Tvn3L-6MJ -zfx{Q*gr;Vf``JStC*qKmin}f9B{{PzNH8S!A&K?UnrUEo->P^2Z2Tb;I_U%Feet3% -zUiQUDeerQ$eBz7uN0qiJ62C|1WmnL;j|?f+DzQ{3?zwQapXJqTGsarb$SF2WeR}-r -z{i8cH_KUARyGvUmHA6Ukvz$u=#6HA#Nap?+HuYwl3H?XVyBMQWhB5?@LsE667 -zD5z}QQqJGZVC@t%776z**S{mStmM}%SlX41WcmIm&R-WM%DE}+W|dYiE|HoALwb62 -z-^EP3KWe52`~EWhnOa`aa>2RS*UYy@#CCDR{;ju(&@vM1wo6xs+3eNXGEI|5BUFW! -zq;IYM?DFynS2r=>57vGB=+PzDB?7y}?cr>BdG<_jWzOAmYd4bQY&7rIMShE(MRk+2 -z=jWp(n!dHi>Df~`QfnBzZ)-JvnqH1@0zMP%O6;KzEU_c2pp4*6L=qa-1+{iJx$qqm -z^vnofBcZc2=k2Ry?;l~EL;~(K7bI`g`Aj$tx91B62bFi0AJX(?ReWO-HF=fy{m~r$ -zgRitw;D1%tQ;D -z6Oy}0Fx`_v!O&<@4$-_%*%ZGNON6$rX`*Lvj<#WlY5O#RYhl1V0c+xb^)32mlB%`y -z2uVSNN$gOgOMG-=+Mh##!3zdPk&^{!Dl?)2)=KiWotvSM^rom2hgY64J#MmJ;LYnp=lmSERL`Rnnk9y1Hk_Ol2G%%yi&5UholIkgGD+mhCLm_4@ -zFF*$B&QNeB;Z+!Eq$py|BkNXzHad(cHILW+T0;M3DbC$m;`q(sQA#?Qj3%W1Ns-vM -zbB{fIn=;L=H{14>QQW0$x49F!z5_`>R_Tb8Gd-T(X4rlw6tzbIkuq-0^zT|2tL0s^ -z?=+t~mxi=KjLc0Bzy057H_W3}8Hbf%-5fL{^Tm1g`}~4B`*XSYMsUsu8h4j1f|k=t -zaY%oxD$^tOE8r{Qw3MihaWOc!Gx1A)fi-QU7SexpU5J&5ycWM>dyk_nO-EaqX?pd_k9>q0dtsY-=@SYZFq0Q<1O{))^$ -z+VdS!b!oebbkay%Qt42|%i*~n9+4K)B_D1JMO>gTSL?KI`q(|dwccJ6kf^FKg6th% -z+6fYb3t0vn!kK+?ZN0zfB6^>0!TkFUu3o*?xEXo(~C`6oB(W&Dk3<-P6L5jJ17=YDCkG -zKM!TPCDOgqB92BP*Qy55`|a=HA^l*MUeuYrro$X-^{1zA|MKG>zyA|_Fr*W9zBhG! -z{3Vh8I(p&HGKX7ZV&>C1QHz_|O~$@gL0elj-jzddfJfXp%8A*|Y1o!7*|Z6ng?7Qb -zBpNNIkOMvhyml>6LzNWXv6@@myDCSdH#c|#?W(r;$Ur2^&2j8EH_4JYdb)JsQF7o2 -zDdQgL3sIkE-5}%-ilzchE)e -z@*Rj!UI|#22}h;Tb6K~jt$|LdrRl4=^Rzw7ZczN2BoW$%=#P4KcevYCb!*<8je5+5>-H4xsNn1Bd2hiTqv>UBByaEDKN$=t7alvkQ;bTc?3f!W4 -zkrQ?}i<)eumUDJULX=A^>?hrz=a2LctD|c|2j{S-=N>mvA*>NyZ(PUR*T~9Vk~-;If(Y`$Tp#)895O0P(ynjU&?FM>Nl=bo;b~JEkbryseG5w9Yr8?AucL -zTTq(03;$^C+SN3GzYl>cIJ5qL~~|bf6EolT=6#d4K0}6*?CcgkY9%S!u&2=6AH~ybx10Bhj1Ad!fujl@pgMRT3-H?f^@V$hy?-d?+CkT-bmUU4n>_{N93*+A-6-!Y{{ -zh)kx$$@8f9k_7(cjH&sZ3%*0$O2eUBhFAzGf)EIAVUJLH+RKZ@b8@QnIb>E-qoRJ75%@C)|EqP&uFmAPCl9etS+tw!Ah67UiUMc3kJsmMzj|2*Z(-Qq1$QK -z0`dN|dP<^Plw*qR{tpm7@QNzqs{MgYq9R%M?4gM%cCr@J?C^bo8h-Ba&}qkj*y1PY -zG0#mRm$KH~+^s%a5!^Qy{0;F|1T3=uo2c&OOL#e}Y02L;{8!g}NFZMiZV>zi8vjK( -zDt9eg4)Jhdco{d$hPgLHaG!TU9OtB`H5%1R{p=wvm{@>p8Zq)z%aV9Swe(Nfi$yKj -zSthe>5MHhfTuQw5;LnU`ZlJjl8{xxz(FIqEZdr+;(bCyJ`11PJ@nA7kzscUZ1;m#o9V@6;r^m(@~(z_sVlW9 -zL{n~q5=y^2$J)IOVF2aCP`7an)v(_cF#I{Vb;`S`R*S1Ew-~g=c^q6ZJ&}#(wXa8b -zpn;N(rRtLEfrv-`CBXImCEIX<^j2Ir*qwx-jUY|7bEE_ -z0JqD-3u -z{C42${YfQh?^!xKmQO~4Vn^i8yF9sr#$k}V!Sfx-VI$$Z+!8#P2pi$+Yq)D(+jB$@ -zGj(@=_fZm=6vSe_+u^gljy4y^JaM;(L>R^Uj&&&%m}Tn@-|4Xy)o6>U -zOFdg-obYnMczVGh`RA~lPIH1A*in6%lxEAoKrvemt36;f=L6G;Etnd33?mAD)O4r&2E3r)KVK#{} -zE?De*)Ba`|eyk!*X(?7BqJEoKH;13)bYsYY5M^H-A@s -z3bx0l!wYGlLCIV+m84lA1$wLboliN*!F1@CQ~h}T{(1)S%T@x>mo6Lh3urL&M40Jt -z_iYz%W}qqSmQ-pli;4Xl#Q!+slRHsXjjmwv^WWo}X~cJn8L4{0oqixr7B;rE>3;d< -z=u+_GpQbF0mc*^Jr=KGg9x37zi$5Zwdy~@DdXc3I7xSK1!&{=tX3K_t4n -zhE%8RFLH<^vgR9YUATS7>H75DUw-)T{f{#U5Irg#OpXt28fffx%tfs&y+^*Dd$E_; -zzwL%d&lB-X!L%1ahfNb#x!^9H3k5U$?Z0 -ze{0dL7iTL>n?L+M<}KW6_UY60Z7%L^Zm#cGE4=&))iDlJ_X-6=rCg6dg4w}c;D?^l -zwtZ8Bt<&=8GQHx~+{4m0IBGvT)M4BV(yHTIc*}}8-{lW8N3Ea{+LQGtHhR5om6S8J -z>;*~H4ucdDC_2YH&c|-5hkbHmd(uGKWon&cf4yFxBfkQUI&AZt`n1{AKz9!+ad-oN -zCSO~UScFTaW@4fJi(D3m`-wf?LU4jO2%+M7%fLvoQ2xjG7RSug3F%MTk*z-IXgm&J -zP5fSUI_3dfV(pH+&4MbmPT -z=(8^m?r=m8AL;q!o;o0GN&2v#cQG`lw)4S(3A46P -zb*EJkjylRWSyXPZC!bvtX%1VrX2t;vBrBFTiOlWzs%PjbPPkRe;18NwB -zl2_lIAv>Rsf10fjQf)&KjZc4{5e2tel~P}*6Qa767C|7B#QKJa9;{{B;$9wl~Hpm1zHJi(VzcVD%exB$x^=?QGY8$^667ts}Jz*)ZKe0FK -z6vT1&nHW`9U%>lsZtRW5VFUY6cVzK{)nma-`pw+^wlgzja;_jf<|UGqok -z%eUYCxR*65w9#sDvt#MUV(S?R?b(-K`dx8ze>W)rN17=6OQ~8Khs*uhkRreq!6O96 -zNe&+}nq~1bA0#zPgvN}W)}&pFZy5CS`G~SkWaffEWG&X$SI(%aZ`K!ebzYmS@Kw6& -z3s7|G^(Y%mGbn$jk@Iy*&~?OyR(YxNoKaZguE?AZfi8_`3*ALvfX^d>z;3EpS?s@P -zYuONKQ7e*!3*|#%u@gJpzBONwhk4ycbW0*;s1xnyX#Dbk3fOD5YG_wbHw)qCGb{qW -zJ8RQ9D=YJBp3qA4abcAh(AnkR7ndXquJ`6_IW$ADcyKE4;$evC1q7Yh&HYtZ$gU7N -zVtO>M%h_ey|Lx~LU(VLedOfFp%$YpIXb*cF`qFbSSZQ2l?(45RviEwD`JV6|m;SQu -zY0omnd~kswxXx5lq(X1+33WE!S%ZbLO7;_-?*^RW=nl6zpk(JCd(kZEEz}_K8W<`M -za9m95!p;eO1-CgZ2^o< -z?>12*s>O~eeby;Ht9nGp$2=D$A+uJMNN>FlfhDzzoRkrFK-2!yXd>IXyg2)6>(?Zr -zpQUpwxX{=nO=Ia$)R4wO${d74mvl|6L{@tR>!Fjb{iyfx1S6 -zoelgtmtVn~@ZmmUeVniE?A^uFzx96eE)_BDMn*I~GT&(-(~@Iut>j{2vq|RQ&ouR) -zlQ2Rv@cYe7FZEa&MXuKW>OS^V*gt;vVSfE^b2a<=>rbDs>7H#SN$cd;hs&m|FQ0qc -z&E005`%J~Jzq-tn?Jg5qNmBXyI=evZ$g}-4z438zcXsJ7A8z?_ezUl_^H;Z5i|Ok6 -z+F#whzwuZ1_gDVv{ng`i^)SIbTu*Hu?jQWsbzLFZ -z)cEXpK+}R430PZ5*@mDIS5p;EhB*ZXdub*!M>BZHIhh$LC!@0xb5p! -zX02#aVhO=nC^(KhRo3couagR~-^~)LX%<{MdNBzIB1M*3H-^9mWk?pN2GyiKKkO8A -zijL?eL(!QKC=#53$f+>FPS8wClG2t&*x+omf{AKL6VlSURKdw^IdnP~eJXe;@(CbapUOj3Ng1dcgHbr%n -zU4;Pe>U33Iw5wAv_f^*4e+>TS!?k`Kh?WP@7UC3bP8Ft29BZqy;7=1EiHD8ML>$fI -zTwGC;rcy_21qYsM6Qm3dl2EV<uBH<*?O_Stx+~+^{}_nj#j%SVJ>3%w(xyd&`gF&B{k^@LE1KE83DQy -zK63jcXsWVSEyL@V65B+4k1`xU8Vhf!!y|+c1Z~StxIs -z-b$5nTJ$*Jh~C2cg&Ba-8wRc~+!$1eCSK-ZN7R|7^3xkn1u~JBu4r7E#(a$=GzR0$QRX28pu`nQw+6r6sZ-PoGztL_LQkCn8#ImSZ}Rh-DI?CM86Cnp8$| -zcqAzi_9kHynTN!g4!sF3TEcZ;aqeIk($If|mko~T3PW4cZqb)SRuGKh8btTHONe7< -z5d@S#Nyqk+9S2PXrV{kFjQ)?X6G~*c!_;rX{X`cN>CU4I -z0QQ~A`-;zo4KwmYW|kOOnAIe5shZA2SbP%M$eie;sNy=@kb)3112h4VY%!55RdFRT -zhc$12uSA%dCPmuUHpo^I1vLTK6(plXJBSAYYl4uKru`MR$83$zQMf$;$Ih>ZUq$p+ -ztBSiJW7fd|)0W60h^Yha>%_>a3d&W9CgLcG`$W7Lh!9730h$`U3a^JYJPk2BjX_f_ -zB6`|4>6jZGW~UBx@}&l$;i?~#7)u_3+9C?ajX;QFSPo)9;^&AKk5F;h%@RxQ5iJNi -zi)w6dqFbQINfNUjM#(&m_5;$Apd1F&G`iS*3E-4DMZ|ItY^G!8*Bzph^zh4sp?l~r -z0{>S*t&E^;kqMZGA~stmHxDit(V{woYMQ53W2z!XO(4 -zY#QA>_nD4^>{emXko0y?-&C(6`sqOXpr%id#;N5ojw*tVbr+|k+ma-m>4*(Qut3fT -zVaq{oNb-+>Y$d{eQk;<&kR+IR9Hw_k!n7g2m>l_w2!?o-6jIG%W=Ga5RP^OZTPpiJ<-Nm -z+V@d1<`$agB^o+r^GyL@alv)~XY*muz{8LcB$&Wb#PWv8iLP^;1qA7UC~VktM2~A! -z_^L%C!c3Qe?JB~43AQXd_E*Q*H_!m(kYaZsgRi@YAfQwe^0bJqP#Xz_II8>9#x&T7 -zO`O+#3+Tc!zH*2u`K;9?Ae -z66sY9$vPRS^G55pw20gBJMccJt)&`=)JKbTx*fOTYYec#N#ug--cNHB(~L_rg#ir$ -zsR>nd#7k|h?K8(LM(hXp)h6F|5ZchTA0b;rK<3^5S9Wd7j^oJjSL}CtVs~eHXXbGu -z9R3eT1W6o$1REg41AV#O&MqrvMn`%GtpInZ3AJg4w{h0zil7xLFb9UU9U=cz~RS8eXb^c7`^y}=43j` -zC$t=%DZw4YyxGLdV5E&;!Dl0%!K^XT6Jkyb)sEskv4>rTIrwWBJkx{$WDyhmLS%%W -zSaG-xX3b7?CB#37rm|Lz5y}&OdTD)Z)mGePuhVI(Q01$^Uz -zh@&IsiDuO+vDQVrKe5`dD5lx_L}%Mz6DX*esXR=_QuoxCTR$GmLclll!xSsA%qJE` -z(#izKpHJM74QIYZPKOwAp#!7Sl|b{N7We`GEJOlTJu203+eZFF}L9G6%}Gh8Cilrl5Rt8W(3w40_s -zpj=pINUNAaQM9IwO!<=CgL!AY>>36qd+ESXvdjO`{jbB%KYt9rn#H{$V=pB<>?4+) -z_@JUrU>Y;%>ESQ70|vfpR4UTpmgfWfI;btMFgj3>nCVFbYgJYIPqDZt4IzJl67oRV -z$U2{?{|5%kTAsO4)|OZ}4L*6Wi~1CMIQuksmv=;!Z{FJ-c5g6}Gv<|3cthC3ME1cN -z*DX9A&Tg|7s}S~(pQhDTcpkd3Q{QrV5C75HGR>xP^dQZb>p{g9J?iyh6N%#OE{hY) -zHgKQtoha)PQ*x8<-Q~a777@zgn@5(~{$dTW%AS1GfmnWgzQB96=1RB_atW)p269297hHZXv63)ExL6YE)( -z7}ZUuG-#u@-Ixx{&TeoV-6D(Ya<=ozn3I4;NSBH5*eI4)WBEh`Jju_B#FZB4uJ^wz -z&d%nIE_?9ynOZ=A3r2RvVGPu3MW)yx(9wyq*VNYN$x{nrX!eBf*JS%WIu-!I{kv^~ -zb?itqGRp7CG_FQ!Q3Wb0uW+0za$LHCv<(8iT3jXl2xbiN&H5xx6P(LF=48u85e2t4 -zGCdGu3`=QTb!o?v1s>YXH%3Mx#H8cI)~onX_6BzjCGdVweV-lQ&;UTiYRBZ3##Ft? -zmU$FD?tzFo0X!uUH`EzUFqm+PIlib72I8wFmO(RwFra;iR8M9{W`ZnBkyHe0gt8W| -zh)t%Scywyn>zn)P*1QI$w{L_|G8`!pZ$`jeEZ%{ui_jhxrqE@qA3^MAMxxZ^67`_j -z5vM1%C=(uYIqIr77pd+afv=721D5T`Z5BV3Fn6kKTTq@EwhH0>h}cS*=n(w!0A(q? -z;mMA1kM;3r?}k(gF0%A)XDStXaLRvj3#N;GhQ*E=O|GJ2bfWSOQy7NE)Z$FCv|L)H -zBgGqA%#xicWG5nK)2SpDHflHOByz)UHJPH0(EuGrCA!abv^hE%h<4B?R%@||1xA5m -zD}J@(2U8kio0#&iDXl{iA7UkFN+zf%`QAx6Nlmo;Dzp?7LYb(`6;kos8Uwv(r&e8U -z{Uh)uTH6PksA19u7 -z&x=7)IAaD%by0+yE#PMtckM|dqBSRWA~e!0y1?hzJ0{FEJFwTvX4`rZP?V4bjHBP} -z95nEa$`hZ+>=(P~XGW>dItS$8h)>Akyb-mb0vz@vF5IvLyXI{cw;buf{-11gUH3@v -z)`9Fy%qF`PWY&Nxaq9(mZ{QB+g!}AE0FR6|9Bzmwm`{w?zyJBeUS6@KM;9x`8rpOu -zU(j<}?Yg!vc&5mB7V}#*G}FP>4;ng^7}}LLnmrroN-6X?fr;TeT^X1{6dPsR>moD# -zt_oxWT>|c$hBG1N-(ar)=7o<04d|TY3K0FG>anaCmTQadR9;ia{}NXhBywllex7UI -zMa|jC1^_vE-L@42dJpRAH}pSg`(8}UyPt5bQ0I-GeKhrQ`1ANhV{-+moT2A^BR=s&*#l~RH@nY3&|&wbPPQHk_jVHx-TdT_ -zKY#u4<9E}W_&_?8IoJTo0kP%62N>)K)8xY~{!?Q*wp{v1NdFY3!s(OqwDaB`DHZQqE!if&3`m&I_mNkWlL -zihWW!0o|gVVSmzEM+FV68%KJFa7Kcr1uTj&Lv(eeF50r1);T5z8>gln8_+`}5O-D>j$4A_L-G`sH -z5bI0Nja?Az*0{Y|kd#A8U`q#)om*p;p;Lw#arYy@CL5gvYmt9oC!Hh*Nrk -z@pc;ur`JWYyz&V@bDP9!e8GR`dlrJK`ds9z+ZYQ((0dz#oo!nDP>U<59k6ehk7tt7I*$CEO -z1YMX=+L8{c{Aj6zoSi`<;tSEFx`2Ol^;?RuQUa~!TVu~#4{kz3rq%wGRa9eh`%X}` -ziHw4@$c>1)tbR&5_j4!2@ajbXTvCqm=G`{-z{;*e6p>jp!D3gmIf-x~jxKot!0v~+;YvfE!59bSBTBr1g6{P}6@Mm&Bvra-k0ABH -z1+5bv!zd1d_vCytDizJ$Ov@@Of`K|@rTY7UvJuMhRT0Ytfy7Q)1uW(rM%@wcEfsN( -z>AKq_CZjkFltbTb8~)XGM}IiU~bdt1E -zRWY~u$wC&ys9Iq*T+opKw(eXfsBx3Q}T -zv33#wk!W%buD~!FFkCxzvklK~NS`A$sZ79EAC*Xi@J@lA#em^57f;FtmJRvo#TLvL%rzVtZnlp`sfY=RmSU)QoL@5@%No3nEbo -zLW_;4Fa_0|4|h-YJfU3<&hAD<$^^Z6)R{5S4FQ)bU(A$jzOZ#;!dl9%=Gg%j+nn}< -z8i#qagBx4$%;&m!D&q1M+u$$6dMI@3>>30bwHQDzwo1xr=!r@*{?MT)YGLAC{lMkA -z5Oiz6%AsR*Zca;rDaIIK=d>htOHxJOyX_KgbsQTSS12G=N!*duE)_k2d858_ZK@J% -zpjg-rdoZy|3DZY)T0A$9>gPZH_VKgkSpL?2pKgErf?}<|#8)u*lC>fNmP60=DR(R} -zUgNY}nMp+QnP3!K2jXTZm)dO=2bW=~5cK1L0+ff}=4QUU%R!E}uwyC3hgQ_XHJbnH -zi5L6AK1q1%e%MMCxW=$YDR3qVqZODd_50U`B19rqEbjHC_m_iY6H5;Qc%O$o?vFQ%XuuAVYPYoXU`F1kmb28p6WvtN|V(x80u8;?Y{kzm7+(}h@ESa`Gt1a#?F)rRhm#+)$VL>St? -zDPhJTIS*T08K1cDa87At11hLEZDe^wMiMtCVzVk32nhZg1s(*mQ`VwxDqffCK5MNw -z=I+vHrib*2rH)~zP-YUx9hvO)M+sIT3N4CTJZbqA&9gDx8%2&&8QYcMt~sH&S+iXP -z{sqk>P78QA&iX12+sAkjQR(6un@R?Cs@P~@vd=+Bl8IZLmxpSG5`!7w`~oI8tQ9?6 -z`y49{{GHX%PCeU-I-yJ_xYE;7yl;vmn`{NU_px!_?(lqpxo)nW|3?XMnF*)w3w-t7 -zricc++#X_|Fw3??{rf{960^?!{gKVtG8YP8qz#kp1oVJs>X-!*363!>6U`R&euTS0 -zFEo?hk-x!MR-c(VQ2CpBVPFGoDV)RgmJN2LmEZl=FYq`K$;F`x-Dg^neQOFLM0 -zgD6}n9!w+TQGF6&$?dVX&d2AR4kltCa0CmAO+WlZQqs&T0hXuq+!M>)!P!ky+nw!E -zD>Wq>3{fy2F$KKQx(nc)2^<&j3#5aZFn(e=OKKKBcVns}%PgyK>3@#{XX7#E+}(-L -zScmSFk#BRa6Py@2-zS*59CO+bQN4|X5st%Kz#YT^xuGCs&Z0reM#RU;T=%C8w6U!a -z<&OoiZOU?xQ?>5gyylKQvL`}ff(@9_NHjqT^w!v{fq+3NpFQzf^smqs9MIa7A}7Jt -zSOG&k{iTlLx|=zw6OH>u4KWkE`0jSjwS-SvvxEn~6gN;$)X2;bdt#Y7of5^p;9_MZ -zdcTQHyEC^ZhUKgdWuT23`T*N$^Wr)Y1@CY^Fn5z3z1Q*YDHJ9ib*U`(p$IRz(jPs|5+SQ$GZ -z(^iH_K5mxE5i3FEW_S#8nLbo`^k*-Ig7Ryaol++-?$ -zZR9q0X4#z$68yg>2qz8$hzIf%$#LUc^91Jkx)RBJg)&(J0q%t;7F8U-#{%X&CZzkR -zW_69*iLDWdQ3V|<0&=AqykBrJ*rTnsHh&E+(pJFQ -zY?xgs3NV-90#XExHnx#iPSTuMVk}8PwcJE^QFb_n#WT09PmyLu!9KC_ULr910+Zh3 -z)_8Y8tjIEtIZ)*Uf);Cop^;Q1M30D7?zIcTMnwO_Q+-oZWf;D!;aZ38-NLA9V4Xa{S5QlNsuThD -zY(O}N+lMEZ$$`Jojq?5hZyZq&;z}EBuI_%Lh7~}T`LyNqY1@Yi-P`7eYb4^}Z#YH9 -z)@ixKIPtcU0ki>1Y@cZFi5T9ZKyJ^@;2~$t?l62=D@wtf$N`ddFHp4EV8D1LTn@{h -z4kE(*p5~pCD4ofJC~Z4a?xd*+NRihv-3*6 -zJVKd)Z#ZKH2|AEDXE7!4M-k0Lh3ywK6OwqNnN(jlYIgA?=-E17p21-xzUYeTQA8!L -zjH6OPp+%pVj^XidYWL(S7%sc0QTwLs?ig|-YP|R1abFCMR}gPw7;GZwKQY#|?O|lgAswqF2S_C|)VPqZiyTg#kSrvFP8cu@ij;vCIdidI>u -zZZ?4wUBL;|p1siAJ8_%zR62sq705_c%7O$lU3Mj%`*hJ2rJU6*j -zfP)zB%o{~EX*7r-D0`3mAzR7!w1w;J4i|zA&Ej2=TIj^G1BiBvRmC~0_K^_h`)3W2 -z$sGb)KnFuk01^Dg%vJ+V3?r=)wXxobqfY!TL<)!AtIu@EzaL7ZyLA@$}Vbgfx -z?)9MQuoKD2u9J2VgK`V(6N-_j{t^hn_Py>Pp<_0sZD_S(C!wBjYF^L&IGi;=pkBbg -zzJqmw=+>)I&Kt=dTURiU4(xEZx?a#rDJ#Z|cdF|Z^k;tHWZVnxKhaxn!{rYyUYN#9 -z!QM4IK8ekU?4+Oh~jP*y&Hz6 -zf2PrlIab$Nuomolfu?GF0IisZNR*7%^}qzeHj5Cqub`lFZ!ae@Z}?u4*;`{qODbZ* -ziE_0s%Z07WLH_plX7D{{3e#B=g~>DU_KYM><4IjWsgS!9!&7 -zcbqHWML!TZ4neMre~7dw^(^x_6T -zX5v?&-~~-vi{02P*c=Z^$_TXFAaHGS7|=}(Txv?}8!iwtqFiqtA=?-OW -zi6cbukXB#H)hz^B#u1dq!8UY{P_!kS8tQV0S-BGYH4w^>Fl;svc$(igmQh4dJPOyt#}btwX7Wr4?J -zEW4TNTJv2@SF$h#d?+Lh_*gTvuieK!MIC*owRv`I>>LeF4l~2R)@x$Y6CbJRkN~bG -zqmRboXlG&_f^0}Fj)-V3Zi3JKk!&O5gi>Q0`WTwdieh0;#(eP!3I5|eq;*SMC02Nw -zn@;1q1ft19DRRb4RQ_}#QmWf>D-BfCa(u7yzXab*Cr}|u2i|S}L>szd8T<9@ph4?B -zkweu^mn+k3xdjv%JEB8i3q5VQ+kGy`6tU^)cL0Vu3>t(+QgTRFg3zxMw{e=ixrHi> -zei}@-)n-z8@zQeaxNi<5##8*_Ft`m&t9Ib=%;{3;vpYD_Wyj4%-2eQK|NWnT{r5lq -s{PVX{+H1M#b%rBb&M{Htmno&crilNqQZKTrIt=&!09-!}Kjpsz07f5p$^ZZW +literal 64073 +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 +z6xTt{Sb74xxWw0Fq6V5DM#ks*#+&o( +z$>{43(Smr>EitOwD83fDo94@4>s$-QeB*N|pyKH8O*aIMa@8zz4l8P;m(<8=m!qUi +zu7PB~VVWi0I1!nayzypOXA%_r##i~EmU(_n?2jA2#qzJ%glnbrO}EBND(|y;qfH_Q +zzxC;QH}8h|p&R}dy32U2WXW=|k~3Da$apP>XpY!60SQc45m}9Qi}%=j{%W2I+*gU) +zhNI$#PB@qA##lDeR?#~@Pi0Zc8Nj$9^UYgLCh8RTV47ubh(E9rf1n;$VmLc~AKm;y +zw(3XUXDZ|B(a0?8DQg5SwUho_-1Y3Y(<+{zq#!_xz}p6hq^K9n{EE%>p-LAXf}>=J94-aUR{qy +zzFooEKHTN=f1_fuW%xilxW>6;&1Zbvd|Xt` +z@>#_aPR9)qwN`(3r@;0aYTITUxZD_GA<8hkij(&7H?BBd? +zB0iss^z^0<`-GISI}|Li)1H~!Alv|#1=MH_B^&Xxu?gxzdv1tgqW$T$isDHGAiN*U +zJ3eplEG5`afY>{IuIdD`+mnDuw=Vn8n}k3LcB}od3;KW-n!)>iRM}As9>yZi$-Nfo +za20%r4Va6x$xd!Qynk@>^m)dStDNi|A0GG+4Iv{#Ur}42Il+5_+vcKmUyWDfSGed%N`m-%QU+vX~x#hiBx +zng$sk^&wlec(2p`O-|x8&0(2pwuf!6}B&_^kJWrO{cxX7R%Fz(?Vn +z5#Cv0nH=-81}0jJQE?%Ud8K2Upyq!B@-k`O?Oz_uwD!lr|%&N0*_cj2T_tpJ&-VN +z(Bp#xAoCc0Mq{yn2j4*-1~IX$h+@vagYul~>(lhZvVMBvd;V$qgcTL;WxakaHZaX? +z*?k8M*GG&ZU|zhwLFvyh+1u#g#?%_-LNbG=5mBn1-AABjETbe7dD>gAKb&PlN$5;n +z&!_jdbF6cuUbJBUekZfE-U*^bzl3QhzLRk^n`F=Rj{*_%oe+R!XnkESuA236^D&A< +z+`ur~qTH7825>u_X9SsgVLMPZBU1rJ#d!&$_B&|1&9d91c0Gin6M= +zEwmj-&%}C0dTB?H1Qu_RT3gb{!M2=(&78fk%f`fDX}ZqFZYU&cIUd7f()zGHizuGbr;%M$dPAUlq3}~@~%4=%bnLWsZrPKM06`61J))0f^ +zMS^zzZRZnT%hlU>YYh?ByCt)#24`v$pA^+?<4EXjJ1t^6y1(}3zUfZ)u!ym_lBKgz +z_z^cO;53NgW+@mfxV$c`(o})e-_~Chth_jTw^{tg{dlFxxATpYjE5<}R=?tm +z-eBnySroiZ1j|1JZEI4aR)1A`z!;`0X8me1$@o%TLOVV`**tXM?usuMzBAfZkzFKy +zAf1Ibz++=RO2Y=)Ua?ja6lhjkqz{grUbX6uQP~S0;4Z5nw%*z#BbA)4Gmte8S1N%e +z7c!5Wbqe%V7zVJn(c*_erY|)J>@qnJW +zV`=~lqWK&+4oIPAc#~DhbA8sN}SHyCnasXfv%9Vyx6%!SjiFr!-}eto#C +zz#yODV*DW<41R1pOjqlqHmMs9R&2)8T9$O4DuAzAj^^!m0s#(csA6NeSYCC!<+NcF +zn6MEkWiRtqCF$H8^~J(_SDk03-M1%uUyU>~yYic+(}#yb&ynTOZjQXdN_24bg6+(I +zlC#Ct-xBFt`cRyc5LbTph8iEd^my^<|Nh_o@yiUD)9FT|C!c-#R-G_OR^TJ8+x9gJ9LA!E+xK68=zXgand2=EbW-yb3Dq3+ds;ss9qLu--83lU +zb>W+*CG)G52sTNDn?JA9nrBr1$Tx@v?{!KXR$zp^>Kr17$%AEo^q3QlW4s?NOhW|GTeMYsT^a*Ql_|?Elw)w$AGVpV64} +zbWMTpmSeqTPrmy2lOKNd*=sE(**2;H?YHo@&?~O08=%dD0MQ$s4V!XQ_Fk!BqzlA3 +z%h1s{Wjnh6HU_eOnx1SQ=F{yPNYG=wkL+I=t`*?I`oF=0GS)kukDtKP +zFY&1;9@Eo6mE5G)fO58NZ9DH*XG`+si?I&3*I#CpuFspKFWngHq1y`z@!JZ(HN9qs +zo2I};*Su2~Xmlg=*P+4iI`r=p%~vdhXjQ_32V!M2_Bun3|BP8d!@77iG1PHxROY&r +zS6hYtRNvz-zWDg7*Hi>1*<$2(%scCK&5=O@o-8?Jfoqw~MGwz`;&1_iDNyOHZdNb1 +zEMp%y(KQWs<#XQt9c}b_vTI-zrTSv5wO9Pk^x@Zcp8n?jgY4PSlgm7>K6(dt9_r86 +zT(4{1z^*B*uVP8jwhWgv0dgCWU!sHFC;PN51x>O5zkx6%-Re7g7%2bQ?Rz +z@@@unOrDTOeOM0fbR^WxH{M`#zVcceuk7wGhFg#q1YhXg#m6b0$hcPXzqdaBfwF#G +zPL|>Pn`lBUR)ivn_NH6q?hC^ZXd9#Bz&A{#8xbg-kPv^oJ*;|bi+8mrh_*E?^LPF2 +zUJ6bx3I?LvqwWrUAeLQMI}6Z{;-;n*EY2O12V(*1m{|QfkA%^!wJO#>0~KBGx<4|T +zGQZAaGw|2g{rZl936%P^9e}{WtuN85s{HNiaA!)WZC)hPjZSyEEkg|>$Y8CP(j?#g +zj@SElH^G<9>VMq@zt +zAZVE%z405DF1RN`6)ewpMw`9aR=>2LZ~watRSh>>&F1gFACB7?-UaGvJ<4SDwS2}K +zjDR>lPwza8*g&Nv&!|GmSbgVX09totg5tV}q5Ehd6L7}@^l5qnOr +zoZhtY+uh2Cw}-a}RXMSt*z1d=<`gz~f?N|uU$%9^9~~`@@UUsADnyTdCt8sIupC#N(DuC|~hJL?hE1E!Z4_Wa6mT}T^mfq||t?U6m+SLG3IO_>AN{sirCm>v584>$>(oCzA^_TgN&%wU^9iM3uGo(A7M+D-hn +z(;7qDg<;z+Ci>et@Y*y$j}hR$`uK~FKK|;gyPMJ(rqdxEzsH6A4$dt$rzxVG +z#XN`Bj4_644ueR{R1eg)5&Gcv+BWJ{tKUjZZVZSc>?D)0-}njMwZQ?Z*}3_68Iv+& +zvt`JkRP#lx2M79!qy7Ec`{&p30-+vO&nmVYUe^X9Zx|{z=FRftn`_xZs76$D#Q1u* +z^CW2KwQS%%e<1g-Wy?;!#6XQwT+hZm)n`ZZ{CYO;!&YH9R&+gEhl2-WcTHRO_wkm^ +zYdf{WN@nt4#qXB*b((A0!je77WFyL*-|TtA?c@1pUvgQ>db5Go=;l7WqE$6p?h)O7 +zqu(38w~HEk{cb&d`|(GgJXVS~pMG@mR>4!juJb4cR~??8Qv|h&#)TT3%_~*YH^_&# +zhsGwsU(kH$*kQ0&_p1pugHhVmg?!pi +zK_SvB<*P21NCoAk!b8@02iAVyLNw@2R=3u%ckfOQ@5}%?@Sj*#oYhI@5qRYY +zedOHyM3Jl~tQ1NAz5XNg(ObMxNuJo#Znrv5MIyThn!sBxQ9l+zCD`-o9*ws;y;euA +zR7L+c`n&pih1xq8Q}s96&>0q*w`~paPoX_m>GS)x)4uYJs$B%~j?VQ*IKG_^abJ0B +z!W{f@hu?=R*ki!8gj)#ck67cPy~BZCf!X +zdlQyUcr!9zDBj!H_jm&>2(~7!ws-aJX5kwzp_tj#hEv-9d&vpkw%fUNv-2hT0K6{Y +z>6V_`tw6qL^gV@^eAeFhz#O}3Wc8?j@2Fb5`*K9IwN~6Cp>N113)bxCUN}gMw!BrI#m#jcPPS2RD8gDu52_eZ93! +zDBwy^GK`YG&lvX#!@WDdAR@fa$L!g;T6M1dJ^j(1miE`zmJn8AmszkOxqVA^Z9MLu +zZfs%i7~L)1zI3y2+lF@<*~PlG8hjX;D@1Rd?&`!)&*iSi0UhqxncvDmqL?Y69$lqp +zw7Uoee8Tbm<*t;#1MOp&pa_acdAYZvr%0}}qgT2}*H2@e?7IVd>Cs&m?{)?0QLuU<$|&dK=Ft`@((TZjZ?zfp +zXQ;D3F-&_`v)}AUhix!G8SMz6A$7#wzBvf*-Ml@#{eCIw!y6}u?gGvZ7hijkKCyNA +zOY4Flk#Z_{RPzFtaKCEf0vm8yK1L@RH*)Q`Jq|DG>z7hipR{EHrpxD_K6}zzNqSFB +zuP%@7hPumIW%v8r!!@NH`v2aKE>}-4e?*RmaUhfABvHM&GeLPUNA^g +zGCEk?Nsb;u3AbEqyFAwQfBbpLB99ytf){Eo#wE?1!8@V%|_#}##R +zqgBO#wHqx&bg|TF!3~b-U)I=O7<{IGtK8%_&r1WxCf~T$zg+n`vY|qM-*j!e8~3P|vU&9;5y!dG +zh`pKi{r^AP(b2)dfobsX{m$>G+kY!sZEgh#LZgE*A7FI@U)`3@?6~ao+5hqTe_X*| +z34crYt4z9vza0Li=a0>kmB9%3JHhn%Mehm&|NKwkANX@==9T%&;BRA|UG^US&doa| +zHR*e%k?MlC((|W5J+_?0w4*f7QpBJCU;pAK@cXNu{OPa{^VOZM{!JSCVD{gmxyP$= +zaAqQ4D`Y>%6Md&kl;9_*9yN8#;j!~;%AtHwHdJi9zGik-QXW6uusxW2@viq<-q +zSABE7z&C*94LW@QkVG(P+E^QWJEJo@zW$KU&SWbW&_rOCo< +zp&Z}uC1pvP=vy~Xtp{zBL#v|~Ew7jOX=qUXLHX<_3m +ztuL9%4-fA=?D0k|P4yScfSbd9yzGAr+4~CRM?FMARC6K)G2?W*Hd-YUu)%K9o!I@p +zz2W(^KbSY#`I4{-hnJY(&280h&YCDeus;6)3@3iFSLIW_#PIzY%iF-c=G{%(W&&!* +zc8x}KH`qc&_fRfgp?WLC_4Xm|gIU8G_s5VFPdBCT;}pg!q~q6XoZmMzV?4tB47^jW +zri(JnbROKjM>a9?EwoB4Rf(d_S;O_Y?5L7SpLX*4H>r#742QQJdwYr>Ice6+jP1t9 +zM}oeHqQsPyod-|`G*8Zc{zs);e?ay-Z?;-78(9+|6P9+%_&@*R$N%?F{`If^!Jqu< +zfBaeZ4XK*GVM{{6+6^E6zyIhD|Lq_BSO4~({`ddSKlm?pzqMMird!*ue)bo?`iDR1 +zpuYX_KmPW||Lofz|F_@%_}_f{2mkupAOFd>KmPMhj<0L}zxfBKI*Z~pv0FM0pxfAW`qHf8l+{#nk-zWDi{@LEhex&Hc3{^k$= +z`k(&wpZ(2$@;5*E>;GYgq(rZjjyMA~xNT^&UVns<4nm#Yy4gQGu%vx-d>6Opk%wtn +z>e3`a4TKWXBvI&@B+5aP6g~q=P5at3EKj5zs0^WL9YWq_wn~#eOFDk$za=rp?Be*iFsi{GYvK8!iI<=2& +zSTvd{YqnadOlWA#U}ou*bFx1fp8@~WZx?MtgSNkHXKmB&Y%{q6tE@qq?43nbtF*kk +zw6of+TU4^@O!&^M_${6hxhVASGyFJ7)379a +zmH~&K@BDfv32;)>)F6|&NZE2kth$eO-@Cmg<4e#yvvzXHFkD=J@BDl+nG8Zw#%m#m +zg-n4L4QDWY@84E!49dr`3%)X6#AUmJ9mCSB@ALj~5BM9N>J@@D@q=PDMk&fII2;0Z5SInjf3h^63DUlDXHs0J1YUOKC*BGl2r;eGcU +zfCnBps)QMpqdS;i2ZZZqXAHOkSH7a-l+Q#?)HbEY9#7cPm38dq?zm)At~+*I*>_=# +zd_fDO0a>dR3|!U%JZ4jXF@5Lgp)2wZ?xR%41~vDNPP!NF9vrz0caI)E +z#DTtx(hIovQaA42!2xpe+|b3nhmjd^H|6&p+9B4U0Q)eg_yM)UW_|$DJk~`$C|U)j +z!ffo*RFjDgqeK7_A7w&dH9#YJ|KWs9jtI-xq+l#J={kozIt|9y7>}T60R2HoZ~^F= +zWxPeU)p&*2jHXTnuwGRL(KcEDU>jMAfn3TIg+P+A2A<4iJyjl?&Qj!IDOlkisfost +zi^m7*8yn}qLinQOQw>iv$M?+#L_mBjiwaXxR*NXZi=~BzMGfWne&%<;FweZb +zqGk>TVu%5?4GPIaRLnt!sA}24waE2Vhyv}k3_78aLR2DYFU_|Hk%3;Z@7Q|i%-NE`D%EK( +z!Ki~e&RcneD7zWXvvIvao- +zX($@jngzR@E>2b97c42Q!(5%cGDP_}b=y +zk^)?=ZI;YV8tA2=UIH}5%&hP{m!9JzHAg5Kkj$fSP0|xfV;-fIJrC2WkE{}am^jDF +zG0jc^BG9ZI^G2vFXsv1{AXfz~fr#nnXccV!LB>EEZ(}x5YCM^qIy0_#Q +z^Vb~rG<;cpHf=#F1BH|hv{W`5-msIUek8>N205H&jnH9FrX(>zGW9(H*eX**Y+{0) +zGVH-Xp~h)YnWY9Xncz@UHLli1Gz!KYCvOd9IaVy_)}q4$1J!ujoqZoNwIC*nVjTJW +z4QE!b0$`jk2SQ>hAQ+t8NRP1!Fqk8v=FuueoRwf+X(n_6-HMli%}!WvCu>;O5E36^ +z$(DW5g%xi+0=iNd&Q35At7eHYG8L!Y#<`rI$=Ebe&zeR}#5e@IHOToQXeL050G2UW +zzf%XOD0r0T%QXLs;k6T%?fEqxL +zDr7n3O9w7tTp+Il$IOU+g3JQ*%c*UevsQqX0NP(=Rk8&2Rm)csm?Till?Sxx1QrlL +z35Luin8Kr3+-7PkwENvVa~?NxUK$Y89p43`+(Iu%C3Gz_c+!7mfrL#18KAupV33+x +zkM7*J$eDLUC2;qa<0glvaFKj`| +zgGxv$xT@^rCA?0UGqV6P6T6>`y-o{*n=l3Sl{D{2YlxDHMp|d!-b4WLUDd+AiYuFA +zFmi~%u_`J)vACr)qb5oqhIpcTj2;$|VBXlu-v9?gt3uo&;2*dJDH~9~Wu4Tn8oD5T +zlWM6{iV7Y`HX~w^dg(P34Ob1VAatAa{X_vXHa&oaDRc7`HqGu0ikhU8nthx6MJ|Cj +zYYTy%swK9DK?y)5Uj?W}@L|1$85$7!4n{Km5@}~lp))PG#DIZgEoL4YFU;nA{H05vM?RPqs0Q_ZxbD@lH$fe +zI4q!=f*^E5sX^ZubciZw00B~|KsSYTA&@5Rgf=f_ +zT{ya@hJ$KRcRXV#qWD?MCsIvtHJOItb6aT*>i0ltUn;0KhYygtAc4Hfu(S_ODKmTn#Z_icE3 +z9;YF42Y{Ae1UQw|R-})|XUt^Bjr71}I~HT%rb&346A2!v3+D@xXxRfG5r8#3K@|Y# +zN!h%h9MLR5ipm~?d66(!lH;0?+6}q1*_-UnQnnsira;PKC2e_SN)Abzzr=-HOF!Iz +zA&rg(Pt<`s-!hd$SjeCeS&(jIFr0*N$|8f;0vvT)2XQr7Tf{aOSo2IFuPJyv$!T58l7f^Z`g5crn +zxKLw8tkj+?;<|R}p~m4dXnvyASnEBqcropO*8l9bG>ACusCtZHLM+WbI2ewRDEs;5y^Iup2fOcH53dB{9SU(u^>) +z4=`aJDpQ&9X=;Gff`Drw&PcTE8Cj^9t?)+~2Gw)k~B$9!tOWKM@4*Ql=n +z!GREHvVammkzEGew!5g~MpmXAP$44FUo9(a(KiG}Bn7Xk02i!RfHNlQrFWTVRPFtC +zgpiHjFf#shpj;Hg4u#5=o+bkDfA`GywI!1<);3!_&-%9CST*P4ci8MjR=^GurXZeaec +zZpj2U9m}TU`NQR*J*x)P1_3j=*#x&USirI-48(nEm3!o*=$~+^KO$0LoxKR@#bxa= +zz_1!P-b9Cq7!;6r3QGxT)1#Kwjxvy=IDpN>TUR+?kWifFYF1PVl-`7hT+XxxZeSp9 +zw}og>b2f9e7@kzk5g?7xw@7m$m^w&XwZxRHH}~9#CUt8!q(MUQn&oR!V1n*|a^XY( +z9v}) +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 +z{s9YUNm9sJr_Px1000vPl&=6$4@yyY +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 +zKx+f&>QzGJhqQO#q_ajZj+=X352a} +z#R_kE#vdeBJmjt8EI?P%2Yhs^2n7vlbSr){%zP$g644ddI|#si=_O +z>t13Kc`BG36zO2~3XW}`wW)bS?`1U5O1p_Mo7VVUz^NAP+CUFy0@4I&+Uhj +zG!$HJKJy%X3D#zXRBJOT%h+^Q!HN7SmD)z=zqXa9{j49T$yKO$vRP-c&?L& +z5lm|bJ<0yTH=y+-IvfIL3cJ)nP;~$oOT4eqKey}I0TfUH`X?cD%+8?^)`YTmzEgp1 +z(A;G#v;s8eF1rL0XdQ!U7wq*Uv&)_9ebW&J%sVy@_@lOZ;>Vb$(Hn{<{UZ +z6&Km90pqBk?Kx2kmFc8byD(`#tYUMSO>S3`IZOs7hJ*ZYV6Y$w8CW|M;cZ$#%g)Mn +zf`Z`jMHphg0M=nNh=smt(pbORPLIY~s4w)FeQ=D8>j0BRUaa@EGnEEtW*Dq%AivGD +zpe5ry7C=09W<`00Y~-4jc1OcOZpd +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 +zw{2}Y%v5uo_ul9UF&yIUa_>Bj6GTru1*t@JBC +z9!CC8tgmi_Udr-ARJax<-9*5^hKrxk3}}L!5`v?F%o$N#}aej +zjX(xXgiR2F!$5N?<~Fu1%%GI;Z9vH2vu%`^AU?I}LH(I~6B|}#s1tNomwo>6Wc=zC +z&ISJv4mg2%h~@(^rmN0s*ILd!$880Ea_ZW~>5Ur4eO#a>KblH&N(O_UJk+`j@xGCK +zu>r7k^A=zhFdwS6X{kmiam%I6?qfI)lJ-3@Q-^4a0hL5yQ-V+A%Svu-rD4wAE7SZpBtlB*)oET2={ +z^`cTT6dC-ly;>k8Hvn2ludHtbN1PTg41q|yi4oxm&RitgEI9ZXeufS9!j(s7ehmXV +zplLD(+p6f{*o8E!{G=go&<+r*#(TB5VCN0Vr +zyPZhr=jRqTUEF`zo2b-fvMf7>{ghbrr*VzIA8u#EJJ?1P1YT{Mm}6h}bO?cI4|o5( +z6p@(h{&}L8)hmx*y&%e4RLK(8^?{2|{UC~1n0XhjVg#`#j=xsoUC<53DVeSf3_U0~H +z*ap`~25TJFn9pOZHNZ&9e~sq9rTxpEyHsR+O2tIjrlI|7=x=So-LB!#JbPp_<}Nl% +zT!<0oOi2<7niX5sXN*{w@>9@Ccy*r3P#~_psp$fAB3`{p5^{v|T=VdCd1O2-LWlq?tISCY9yo(mOGLqRXl1`txxsW>DAw25H52Ma__5tNWDC&(4$eH0 +z3v`OibbN8%#>^B@nf3-VB{;6^zRi5#>cGBwHN@1W#89Ylg_nNo{7&`CLT6J-T@e=t +z`i3@A78dK0)Hf=#(ORH76l7Y8#Y9tR6U%es;quvUEI09U-~srgVL_yTI2!_1a^{a{ +z!{`OvsL>mssmI}xv)4AKdu0 +zdGNgR!Hr*=2fH5I`Ora2zN=F+%$AoyGb;7I3-l08p5Jz});Gtfw8CWD0jpAT9a$}E +zSe3v)^%rH1_vmJ#@_?K0?w@SeYlX{z9iw5IIJ58E{W}pb8O4*2|IRzxuW{CltvDjVJ?B_EJw5Q8g(re*pzU0$59dKZ-Eu)U-;FW3?&+SwD$4 +zyV%V*10>r@)|9D(OVXq0|d_z#qAGDF_B1>?xOeX`cs=O+#am0 +zd{|p;hqYB3)>d7xwpxR=)fQM=ZG*Md4p>`RSX*tt+Ny!Il@DvH8rD{uu(sL?YpV@d +zTY0dy+Jv>$R#;oLVQsYmYpZowTY0dy+JLoH3)WT}u(n!*wbcf!t=3?zMmUdpQGqEZ +z7a+SPTQ~>!_zIP~XkIE}Kzve6jJxJ~@Zf$gwC}uiiye=E9sFeaOkn72nV@~6`@Ol| +zeR3RLi)5sI>(OtI&)E{V=@N+?yg9Xr{KyxV?h@0ty`#4q%I@$j@41s>YczR$=Lp2dBN~NE +zJQ454^X|*D4ST+>@1d#KQMf{`2__F@qDGkAV*NhVo7j_jVqfDse;F_R<$S67DlfI* +zs`JMiki2_7ck9^@9G|zKb&Itq;#i#VlSt>RKWX2u3-19uawo^6Yh!=HYqfS8Kc;vD +zx8HicZ!=l1lSoQBp>`86ez1z){%ee+c59MgF#=+n_t2}Gu4!D92YYVoA8$+m?PP@T +z^V_?&3C6%GEC=k8WW55eX*pnF+5qOh=Io6oNYiSeFl%rjgR|mZYcCwWjJH`Izx9%A +zM2N6o`7XZueCys>5&}CFPJzQYexuimmjotPY-rtvDz@IQseoG^{&4T-05b?tH~;sm +zbu8|_)3w#FUPB(#jY$K7&BW1#9&?_E#%Ww-0=A|A04pyUi*9f0aBs-de0} +zi^Ic*B1i%8CoqXbBWtsBt~72U;~-od4eHScRyWZwX=tTo8NC2Q1jyQz{{H=oUMP`~ +zR;6)DO1j66Ibd$#QtCux*EXelsi8u?xt44>0Bz{9!l)dxz|@L%00ohRiC8-8DEbj? +z(C~J~4Nn*w*RY-h5I10|i7)rOy{~HDc`TuDWZSWYqY2m~&b6Bzy6ZF#Gp?|!lE!j@ +zbcr;_$6KD?_R^*q8(tDq*YiL6R?DUk4>h~S9k-r_pK^sk4K_ag)~)^$l}fD9?&T=D +zsjT_64mpC6pQacH1V&lwb<+BjohncxOJ{qZX`O!;B#hl=DbBtJ<8SowRmJzd_~hfq +zM?1#;ETm*NtUi5ie`@rpM>|=k!GQMFAq-}liPEl7i~0}+@DDm%ZD5+mo6!C9T?~iX +zF3;|h3K9eMII*QUxDG!Ac$p1sAO)y88a#!wdmEv)4x7RR1wqBV9S(8~DBfV;-7m-jAvGm)eY`QO?cm2-G;{8a$A07QHYv#{?ez)*hpmW}QddZEE~dk3tM +zlZcO-vj#tW^u>pt1oc3cANFL{EpLXWUVQlU^Jm{X^trve;vv@CmUU=02rYy$4$p0J +z2FCTTm;d3zUQR5e#7jAG(o{t0Rid$9AqAITPun##S7;hy=~d90q^=ALucG|-)ms-JGYjJ$?>vVb><7({*^t_ay$1scb)N +zx4qMLn{eSv1{qt4Re^M`Dv2#}-}>lYZ)QA|ToET#L3-?ojmxpxF1W=ajvG|$E;`}w^pcZwd^x92*q +z@&W!AGwuzZp?a8#Xan4sJeSc4)R9H^teoo}nAfSPpq|~UlEo{g&W@g4FN%G-a3kub4BxC_$8{Br +z**X|`MPWf9pPc|#IRvJrNnTMe0~TTsZI^XzESv?DgRJF7R`JBRq%Ru@r_ESQC4-wV +zW4xEkEf}G_sm(?SKco7{{?NC{2QUvMskChFTUVpJg8Zc(NYhMOt@ZHhJ)722^mBRQ +z0dt)WvpykSwaK_iRaoV!X>sFB{CK_-sQXJ(_$aQP4O_uE(^ySF-6068WqYM4Z~X8 +zQ+7UD3~S>^irgyX!E!=RMxKRV$yCX +z+Yd0BvRMr10}-FWIoyx1ROPP(4b&&q3+uh%tW!Ag~QXZFpP*w{_U{D6a=^ZOA1-X@Mb{kH^4%NMyfiawW$H3zQ21fA<1gr1Uz?+etJM5^xCon=Hd|e7` +zNM**oshkqSC8sr>$cd4MQk7$<|8Dd28Jbef`q$SVefrTCA3go}`o$MdzxeR_x<^T= +zEi5$IG22Y`?wQKWZ3uY)koThJQiG0xj`asbA*`d5b5ZmB-{VB&lS`3U7m2pWFwzw~ +zk;0M^6IRH1oLC+wB_;{Idl0lXIHVTuvW9)v&PJQ{YO`hA`Ktrq^jYmti(xP?F74u` +z0!Q{CY=?)l8|O`2cl|ZqJw@N0cz3!Ybn6C&K5%=efL4j9bW$feI&yNEaa`&cXd$MZ +zp}seIK`2-Q|H>{>x%9nC81r0Wcp}<5u7``#%ZF(#`BFjN{^|T=sR661yc;H4jt##M +zXDN-{8meLTpwADW`;H_}&Q-3%4=(!rX>4}?Jpa7&*XR2A)A&WtXDFr>o>oLI6&pC) +z!v1(kTjCHL{q`pxf3Ga_&u!ovJStJK$V)^AUZvykDD#xbrI+}~M^2soCxB>y?~)*( +z0&0>fgYyk|uSpkvc6nA?;GaG8Qn;TzTu46pXStG*^d8C43=-;r*XB~v*J8z4onftR +zy6}@!UtoH+`jp}U_rK87Fafy#G*0^_iUO#{D{%PL$9o|DL +zm>_idC+;^ym+B8w;K?{u-b0+fc#km+EdZNx5-T)ILchJ}j!#HP?jZjy$X +zMNGMixs+|72=^GJ#dDdup-y@3FrA_sqat1rQ`EU(by=^E{RK!4Qa!&Zlmd`YzVO>* +zsIx_#XU{ecIoiG7Qn4qzd##OJ0>sR=a85sOoFyia#GH3d5+^1O$#(6WN)^=PQSBxl +zHT@cXQasns##oPL6H-J(ty}RDI4o7snmqK248`V&N3d`%^2p+ +z(t(%;logzRYmQSWD6@KF+(8Xfvc0zTY?Q!W>QV)iTGeZX2VG)7ibnyBoM|=`MTHSt +z3Z8Zt5`3Y~9g6pPgm5-=x29NzspmGDQW!N$hPix$`eUi)rG&-0%iD})f)(3Uj?mi@ +ztC5>@C(5qQ$KLkp}^ +zbLgmH3`i0XdX1wo1fkZUsh3F=apj8yK1I+^L2Cp%GUWm!R?n2DV5HjrxCJ$e&tuBsEgLT$N} +zg&~ON=c@=LbCb)YiaF*72I>kcoyC;}p~{pXj8EjEt}bByI&G>$QJSV^ce)0k2t68@ +zNMQgQkw(Z0MJE<7yZpUge`+Vx&1rer0iK(AAI>j18FdtvLH%`+oJ3qJs@h+Ekx1Nh +zL{QdJ%>6*X;I$DA;B<)GmX&B4287b&Zeb!>#4a?-u!*RN&gB@k1BVbyJOOKY){$nw0NG}S=RKd%E7&no<)zQRH=Hmofc +z&F>CTQ-woi({G8c#)6hZptBviQH_O-ib@q_V>e`(2mt0H5mY+06VcVYL4q7+A;35b +z0Xw?WgMjK5W{S~XVDu`@S&>iNh{Z!q%582nra{dTIh2Jh0z|-ZlF+^8KY+-cJtT=8 +zz=EElK&`-C7rK_TIZ^W1M#AA5rxdPfJ98Rn*@b&x!Im2%ouL7FhQUUUm!;B~opK3F?E1)5OM#a$7i+fPiJo(P7tBUAAe!YaRt~ +z4v8hsz*9#-3#B7LvsTx|rmf~`)K5T~iR>TDgpCE6!cI5n2I?RLHxM|Kr846n4E>q~ +zk>Sur@B$eL=vCH$!%z*C%YlqLp*emHM$!Xgo>Sxz}AfjuX +z{2UA8+8u-I>Q3h77r~+gXZ7!mJ`qs~w3sn5<(WgL)MO%iq0F^4vNkMoR{}Q3E;)0f +z2IKJStZo9B95Sdt#a?R8-4jK@t3-=SA+N@ozN{~b6NgiTVRAbX=&|Qe1ulDY!)jaT +zUR=6pAhrR$6!{WRxSMy>l!*nST8#8377l2sA4cS4qXR$W3MMPn%+`#?vP2!3aIDBk +z4M7@<7d9SCkx+KO)J2HK77*AlSOhTNHTI$A3OQ1sM77&5wvtT2uR?YwM3w_E(MU7! +zLm|kwGL1Rf +zVHI*DVyG7}=E1DF_i==4-Pa@U-?V5t2Ugygc+;LCo%0@F*nJuUWkDsAJ5Xa?-wZ$*SeVM; +zHmof$JAti{Q3-{UL5ms;*fmyu(syb_#P30F{evnBUDO1TOmb3IBG@|Vd-zusO2ns_ +z9ajyd9+nJeiCb=5%-F?%SCMq&OCfs)+grm4@(W2oM6{`U8WV-QF5OS56wpRt7Yr)M +zzHv|^TZYpQ#Zuc4e6Ebm8Cud6YK<(Dnuxh83~XfYYH-yn1C`MNCbg7|Rwt;L+HFn{ +zkhn;r-Uv*DY$V{fqG@o)2SI}xN&% +zKmtrykDvmqAl{8oiOj&P(Sze%plB}vpkxC?k%9>gBV?lMUYVS^Zua~#D-3n`2=`O2 +z+3f+#g}|6@cC1njEBi~OqQyn*DEUow(}?s?0V%5rCITqEeRV|ww{>jd@0}ndz)=GB +z0Bs!6C~%@g4N4Qt8lo)B0nM7!yy^r*(dKQF1YO!G&Q-##R7T4(bYXW?4jT#%p-yEZ +zvYGHk!Rv-42UMEi)d*`nIQX3hz)9@A8Za>s!)j_(u8Ew*GkbpkQ>*|WSR=p11_i!{ +zZcVB0O=NG4V5de*Y5`1mAESzqb5hx44%82plMfl+aVn49NyQBsNJb59Nr9h?#uH^j +zeBty14C@IDP)w$7*n;dbnY(ahXfNln7CRclHH&4bGEuszpa-c}1EQSR`9al!8`X??WTH6 +z2%Ps3BWB_+c+#v8hH)P-HN=89-(L8EIGUmfI-V9DFnvw%u9Qv_opeo{y`4noHjqC~LP +z`DM_o0Okv^VMq$(U#PK)knQAFV2zvJm6__LN&(1bvUZtD7XYmma26=V!q395I&B)% +zadD>@>1@C5qqa(yX4kQ`ccPI{kO!A}e( +zHSwl4b%yIcAl3yppzDaIiOulpp;fO&<8raYJ?SsS3G5{7E^k<-P_aH=G&)ge8GGDo +zhF*5Ku=RGqNzIgGn8^UJvN0eEF~k)ZTNM;E>t@%n#$vXp>y8=B%y5P}vr?ZRlM>Kf +zMWbb;Hbi;B*~7Yl6~#60Q@6*C)xruM4UDB&H%x(t66iwIR6^-hB37ie8}h_!0HWVi +z@HjLzLnEQX4igZ~G)`xT;sNMD+@ZnoFFh;D;OS@)=sAmZUZ6}Lp +z;L$LC3r6p4$Wo3&OMBc&N(*vXq_!$~o)Jd^7ATX|cN!=Ln*gK4)S>9HC9D=zSs}sX +zPM%#hx^`{YX=B5rgo8#*3e?fdihi%z#31T +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 +zdR~wUyXe)nmR;H?uNC)4Ws;S;j +zH<7~iS{d<{)}hqTg{K<(db(>+W#cwn>fG9QWXq~hY{mtseAM85EON7RAM#UNOx>*x +zdo7Grc>rZjm%ULe$!)@hk*jM&)aX_#U>LyclK#NML{R=N6 +z8!KCx87`r{KNrwE1q+P6?9a?TquNU4=VS%LCA{21uHS4Zhc}L>y}_XyM@#}sT=i!e +z-Yj;rwb$2$d{wDJ9u1;8b>*O!lI6UMt>YoSJsXVZXzQ71=OEcb=1&peaCNr18y>3v +z-KM!w);ttVB%P&bm&}Ty`T4o*StKdt$(xQKV$AULiNFBCJv4HLRml!HD(@UUjo+s< +z4y#qVAe9qSvRa#lVI71su2dTOft)!hgd)Yt&TebZ#EvsN=G9=JHkP=;eE+h?;!3;^ljVOxE-0Zm7soV7yfpz)BzAxw^ga +z#$CiEEVVeeGYGUe3*`LGHGblrlk?^R;Rm06g0~{j_Ay-~c8~u~O9I;%jMJO0ecdf? +zwK5(ye4aTiQG}|0{e$s7A2sC=`q}?D42lWZQ-`nlLmOKBECx-xL_6l03T5LYc1q +z0-6xnG~^SEb5XIH#*AT(!{J0`0F7hgBBEv*z#JqLAe^??M1I1>iqLt@GI_ur7Fw4< +z)d4WbG|F2E!0JjZ^{DY`uY2JkF$ZoSlrTLfG$!$l5beb4t{TDeryLXUcXa{C)Q|~EQTgoQuBXC#VR-iF;e(3@te(weqC4lg9h>!9;Td;7 +zO&XVBqCw8VC|h1U@Hf?&?iL79e@q)(NQzC)7Efa-051}UB~x-#p4O2#=GJ7#@qpQ+ +zjxJ`Z-14s-c*=(YiV9*m-X;WSOFl&-)3ItiY0yru618I^{}78auZCH^Ow|c;MBcncgGB_r?b@PUfaQMST)Y7 +zs5nHSnpdcuth@2+NQA$#7{D1+D)24HKcig^eCiFMKpL>G>DDi{- +zwqBmNwsPWHZxD(C{@MOSBU1JTnI4Mmy_`JQ8vvFs)xJ(C`m=8R3|}f;c~WU_o5Tt0 +zL^vfdbZ^jWU1Z<7g;oXuUelQMU-}UZ5(ZMwd{RrA`CD9%Rol +z_;L(%(R}CK9}Ipln9XKC=;Kv$#c`>BfY1D3@bWZxB!c19KRi4C-5Dx4R%Smrz77+>jKIF_(h=-A5>KC%pNOo7 +zE?YOUm>`w;PK!sJsTf{#UCMcReD!W1!aNuY^Q~_~AFkEx{!@FWMEK&)onELHH(d^#yJ1n>!Ie^Iom+e?r~HNH0Xl_ARaG^y}&{W6CKO?1A7|@!d5eX{ZaHUY!KBRDIV_uW=mTcyH83q09mp_mbbjX2 +zEO)%(Vv-mEXS}N8+l?u*2j)g2MI9!)LY(eJ!9KfR=Wpf^t-7eAw6+?$zm8vh$bEY+ +zCt|-;H#Y5z&Fm0RW6PvwukN1|J|AY7Ju?0!=v54w{}`zO%_RHZ +zD!lRV0xcks{dfd&AdH(Vwi`6T%ydR#JXu50G`GKbr}_Xs_j+8Wod(s{L*Q4Dr2F^# +zJG-MvS(SGRA=LA`AARwn&-ZALk4Q@!3?+Jlk$(b3#Y0#1;%I;l6Bvvkfc-O=NpXZs +zz~iI6T0bA^(T;F^VFoi9l7`L<07C;?m1m!Uj$KiYUu_TL?J+RDc +z`uJ!!0Ns80o{9lRUcSd1$$QL_Tp>KKLGIbr?VTgB&E0#%Zag`T5-EzInjc>cFkP93 +z^&D9hSbo2D +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 +zc(F_ler5K0bHBdI_Pf14Bo2R_^}FKT4O +zhJc7WZM2@EE9&x_2GO<=&w}9|cfB3qU)(JBJ&wM9Pd~r_HQ7+3Sh=e=&o8Ue9wH(# +zdxisUy_)4n1o?U1?Qu-eSWagdyT!AQ`pFrE_NRoDXTySn{+$6o$RXx0P8Y!08sH6+ +zgp$6~qZc~S6$c5qC`3qj`m(^Rh-g4d?U%47EM45A&@vQ)>i+%v{5EWVpc78@0f!$a +zBBD~s=4Y%9y($%JH*PU3R3uVOj&2lmU<}+Ypc8f=!&-{CGZq_l*E>bjSa(ps>&B9) +zo((T7*2Vw^TmvT@>S{Q|82`34mP!=)$kvj8^P-=KG*pPEf+=p4b62M+N1Eg3!Ve)v +z5awSn##piNqHhA3UL>-#lPOAx5}%z*1(H3;aK^Z>O&H2Y6~WZ-+e3lMv>5;3sl)iG +zHqCpctCANX3~7zIzZ4igQj{PXR`%0E7%}A?pzdg69KZ?{AUfJz3H2O}c!NkRQj6X~ +zIElj)m5EuH-Hua0DUwcDG_Fdt#56X9 +zng*n_FnEyaC_pFp0YNBk#7$j|!h5Hu^SU}JRSsv{y$M=M7dWy04Y&%M{&Sd`oO=WIH9$W~7qtlH5}%!(N*6R- +zBalzE`^~G`fZ;~w#&xbzv_&c_RocO^g%`!R5ujy>N&Q6AaDF4Jc~fnUl~?6h@Zy%ZB!M)R_o`_MEi3_ixa&bDSs_US0UbUVqnUXcXB6zup10uv#^gi5- +zRp@QVRB@R$3I3>Z38>1$9K$)nznq&QR5zk&ABjZgxvmOK6VEU-Qt^ewZ6k$&)JhG~ +zi~`Iv;`0w&ez6GJ)5rNfUPi$3=K(`3BBB +zNC*YMWE?oMHUZQ-!QK-w1N=HsflZO*eepzALzXE;Py#hVWD_IFLTmO4hO^i&K?EBM +z;3qVBmtzAOEFO~c#D*7C83#;+ +zpMZpe2v%YA9MU~;D|9srSQecMH?1kn5x+=IE$fn?Tb=>x2FFMc%(*%1Y?L7TVB^za +zm@fG0LYMa*+LrW@Eo89&MKDxD7gh)mdt&SY(u%>EM;wqufF@1p;?!X3=d$MRGI`l7 +zgHzagEhfnsbH{0 +zA*yr?)Y^V)mBsp%FymK(2g-1{0#vuz@Yb2adl3hXnVt$HbQY9!7@r%9qkxv?N&<^S +zL3wx|khJ36kkKx)JzX=PMLw*VPDBH$7+DOROX65Xr5({Rx4B3R?2fV(B3F1w;Bz>| +zJ2zQgz)svY=3`yz!1d70LC?cv3Md7bI>u?#k-($&{$eeyyqt3~Ytnco06me6rP_*~97w +z4JQS)u^!FPY?&i_W9%uxIqBo+2u@n +z&~kR;vNc{fQx#J<3B;lDughwp9-cB-m<8;$$M}@@mQJCC3`DS`TufXAxi|=c8%~)F +zlnRytul)FD%nT%rnJAlDyBdN_G*ZkpvTB2KvI7sTM+o6A`1^S<#tRCrNWk7qN(2To +z<3<=0)_vj@k;3f)>tnsxrm+7y9RvR)OamTM5C^mZc8zK?kl%p%#BexjBtAo=4$BYx +zaF+Njrs*=n8v;%|j-Z2WOBq~VNGsJX=fwlZX`$7E4M%kM$?*^7$5-FTmfy&h-^iBV +z$d=#8mfy&h-^iBV$d=#8mfy&h`WxBO@Ar*t`HgJ(jcj>K9#M}?90Qx4 +zp1O2ja{}V8U{_(=I_}dyEag*-WImQXJbQ7WIRVBSn9y4f?f@2p-J^E}`9kaWwOCO0 +zS@awaFup!OBHDtYB?ER3saWqumQC_3ztXz?#zW>+RY$;2S|dV@0bb(6DT-}g +zKg{1uhDZk|%b)1C-W14EEu%G+?KxY#T$eVF +z$fL8f?l)0}H2S=V%=#J4wHi{{uGazXT?5H#fWSkAL~GoXjRL_aUQhsb*d;IQO9;T= +z*U^fpsh(NMrv91b7SCQOOe*=+4X!Z9%9~qYC6(D@lSR>w-popCi%r(oYNS_N>$<9Y`WUuF%=)U}{$PTZD{Kz?@QJjyG{qU3pWyep{JIVBFxnm +z_Q~y-2#~fRGDBls#Wc^z2LvL^D%1q_OPQ>%SxkDWN6}rPUWrPOy*_O~Qjgtyx +zLyzU2d)xkpB!iUnET!;K&Yw=y1HO?$veAW +zf*(LZtZ-zw` +zi+PdAuz!4Ya#Xu957K@<&cCx%BZ0$O`}ebZ4|`)F3Ry1gxLe`{!X#^eqaajAgOAa* +z)(nnp0I#F*g$up|EPy45lYl`oLuDi$8-C( +z;q}I4`kmt~>BYM6(0o1*_?5wdiKcTWRgQHD%rV7}KES8p03?>8)2KA6TMFAS2=81= +z;ET+*^?c9+{wkLff%;O*E#tdKS-QY1t6sV%Ab^;x+^I;*v4FR$iLh+vq%ts>3g1O7 +zRTdVw8!FzjB5PhAu$&@Pd-8Ucm?ZhS3Eg{5JAaJ=oR^!fYr~u5jynkR+gZDZz!<~) +zMN!%8>l*zL`_V#IZ1n?`njeL; +zJ1h_)z|Fif?%`K?Z7Z`A=ke(#kqZ4Zx1NPGzo6Si06(=a&HILP(wefVme~N1Qw|Wk +zKX?3A4jNNHJNCp2H{6v>*N5BMZ|eU29()=6p!n-L8AV>mjn&sf*xVwb*cKc6wZ^Y- +z5KC<`mFF1QVo&(SX6V~*Fi)46NY4QsEio?T-id936ka&XO;A2Rd?s|;B?*dENr8*& +zfC&5EZXLR|21`EM5~bdzOyiWG$9Kp}Y_k*e7)!hydz=rW;L}5pKVYV~iU8wfBUSBlMv6ckxgICOfffW2GFI~EsqfLDF2CJn+XXI`zRl8 +zF^~f@inpT2PnwY_{GZhl>n*l$ep8Mo?y +z$pa%&1L7iyZNv$m-2LDN-GNt$BhjVnT-%J!4ls&`u3Bvho^6+W65+8tH=XM +znjr8Hsy|fw=C|RD{`W}WAArGkn7)&Gtg)9>>?w|g)Fk;rkm?*;9UM~AJl-Ez+zrNm?f#T`=k2{tP)mmmFK=tW8iVHQ%`+2haD8EQ_`MDgy +z%nMO;D|4TJ{^7@;J^kPaucD`-=*4J)0;6GC*hS|{W;sZe(`$-BW_luwmNCG*lARBs +zLaWcG-8n6z71N|jpgB1i>QbZFtOV93VkpU`hbkH*{fTD71E>S@w1^g&IKRZ2Nkz2G +zBt47uk%*VFtb2DU24?xwT>WBau}9efw8Sosd4KVR7=0>I2`l%UmaV>!Dh;9?vkZ0I|u*9+0~+ +zQP{kk64!ev>W>J07129@62lRu$UVNg(*qe^WJc~gG{8iJD&}m#{c-rTH<~H2j2CtV +z>4J}ocx6V(+_{SPZfLY4WuL(bfCQhY&aAIIbC#v2?yhXO##1O@W>E6{2Z}4_Ej^Q-8 +z^zxG`8sjlPjc&rhH5ax$=5lmhd{gOmbdbN8K9y~q_*RLwQXI;7%ddhMl)>?^^i^rj&-PH=>~5> +zo{w=n03Q{LgV7KlI-A)1qfbBj;-jY@U%&X`=@%dNE7e-BHd#4Y=N(Skq{_W(Oa%-^4~@_&M}nyakLtdGh4ww#zhs8#iAk3v?n7n;+vNu8j}lSGPEW*1Gr@&;wha +zKDRlC8Ud}d5bF%b8cRX;#r^=!+i013HP~`<{stqVXo3T67fja1utQvcu=34L@3>Xy*r|=ZA&n5H +z5CM{MOh2J9#P&@(zX$97&2h6x`1dF-rJl*5n3RkCJF@}QtmmYbJ6BJRkFV;quXpd% +z0KXpX><%j3x<~0aM;o0t)jLP+M6vBh?9Xe^(e85xXg5F#wQbXmwz9l(=HspAG-z?Z +zs1wVQee)ht#UQo=kZN!_Y@6*SAn_2j+KM=2Ux^XkaaJ;JIBZeed+@Xl=zVuJD1sm8*8h0_9!H +za%4g0uBVP~k`!=)kF%>CkrdCrLDL7($||WBkZk%|fXCSE?>#|Ows)g;>s-$+Pq*fo +zpmYG+i8bQS(>6ntsM{@_;T}ehF5=kutPEiH1RuvU`m_D=!mb%@|A9BA>q>T-++gE+ +z#A>CxH0`Ln2I1_<@uyF}_~0jk +zj0XN22HPw>wt&ddw=Yf)o?LrwTi{}wRfv~0qP1q;ee3$Aov+q^o0&B`_oTk>yN~(A +zDeJ)c&TlLmg4x=v&$oW=mYX2d++g-fJJj|ZE%ih_7+L$$TUL>H_sMZH;MH26I1X5g +z@Dc&=%O}V0KmGL64?n;D;R&bC_55upiD&?r<_2i6oK5B1ChhH}+7=+N@qPjjadi$>rI; +z9uJTUe4|ydw~brnnS1wIXR8AxTlr~w{NV1(99DSPz_@74uQ8oRKUQ#H%g?f8aUf#f +ze$n;WL@aOC6Atgdwa6AYz;sy{-g$By$*KM*X|5gVsvF39S)k6kQ=f_UUoT2gR%W-U +z;7lgK6i6@YZZ8vZf?>!z_Nt5GG5+(_qfjwW<; +z`yG;xB432ho8qzqZpls30>)}pqNj9>v1}sXAB%oD9o+4Y)X-)Fp19!5q3Rlwd`NLw +zq~XXy)&Oz83uX$8r^1*!(AzTxe507w*R%07EN4sIi=Zwg89eHJ%5Wu;PvAf&@6zo; +z01`nG_iA$sya7qdyLjF9*{ey(_MCR(&(9AqJKywM +z@vK8fax!86@_tx+^#eB2440iI(#zq<8lv|?vP5Usv$tQGG%m|Hubew_tc{(8tlnjH(79z%(#Tj-#2}QWTb=!F`en$Wam_Qp)PQT;V +zm2+U{1=m76FZ6t|yWiHl1iitRWGDF@HkAAU`MxWR#Q;b72k-%dmtX$CU`DvpliwY@ +z)6Re67VWo#-!>+A&Mx>sN_x6n>ZzJ^BlZn;@bfZ!ADt$j(OUeLjb1TQhWzdj0O~RT +zNL^0jrrfnN8}CCEHmbvPA5P5QbX;Q^;2rGi2lemCQImgmS14CNC2bNfys7&WtnMvn&TcGkjT$H7V +z#xKSK;KqX&))KtY)4h7K9ehIr^guBPVt<#*%L9ga)Y(VQWt5NefIe=2 +zw{v`>#DNnP64gRps6;+*tr-#0HLgq#&jz}(5leDQuyd)xx5ausKcmB6t4F?kg3e0e +zyUt|X?}Yji6rcNI0+K=~Y(g+%8c!_ou*{jNuX{S%Ixh#Js8LiJ?kmsE#nZ8*>1m!Q7tLtcM^e +zc%;VyXLk`3*y9(p3ALrrj$l`XXfM__ik&WQ1Z)p<*QuFMc2OF+C`mrSxHh(kt!Rxp +z83S_#l~Sako@R27@AyPauOk3T_!=OK`}w?Gd2tZomoUPPRb!*sk3Q`KgBXg$^q+q4 +z{>Ps^`}@})eE7wO&%XHZgPs^cUy5|rIfe*fvSJC~IT5Wddm}amxz#=ztK3_y +zjmR_Yl?E6VS;AuwoA|x!d8L_U~Jmk^)FS +zsj&%Xsd>1E=|BT?9o`(cNR3_f`-_j_qp;xM1U(9xgVE}`j&`~L*7G_Xr9A+=p)zBP +zI~kqWQYQ_vePFV{c3{MxXgncgtjIzy!WW+)hRJkl8Ilw74K$+UFoi=PlLFwLMc*?b +z{VpDPyqGS`9!_hA2RPpr^+xeB$SdFiMSoajCs4H!g|LL&bG+20?SKdZ8*G&#zt%PA +zi?Ka{4vb~!E_9nZ{OpQ=cucM+SRTA_sdZSWWFmI1qt&G4d7rXhOM7lHMJfWN*&>q8 +zgF?e{n*be}IG?RN+uDyM5Ll^Kfr@)moh-5($A0QV1N>rkNNCvDHMgpiCC`1i6G#&Q5;T`@$GZq*| +zd9sgfc<1PB9>PIDA>KyQ?A(UzDF_KTbAe77A~n6VGHSS>)3NtmaOAER;yNt!%%GAV +zm^52bpInr^q5P2b%z`mkb +ze=^U4;NhtdN`_H!6RA)=1R*vqP5Nlr#~<@Ep*mhe5pk|>054Ib>0b1TS7n1rt`qE| +z+g6o+8^JF#I=eVOeQS*t?Jde91x9CeQF+l8oY;8WY&D-#3`GT~ZlYr1z*FFt%ju#& +zs*v?l%W+1$J$&QY>FHR9A@TTm6(-bf;ON?j_EepU7>W~fFr+~_D{4npe_Q^ws-#RS4l;_LQ!me5$bKX7r#@7xoZ#-b)`tlmt7Q1lx1tx;6 +z*=9aye7)c8)BgJe^}t!5HO2F$ +zc+nIuo8rBuc)u>*?q$Xb8}uHd(kcNY5HMWk`u}h3%XTD3vMb-?D^k-16d+_o?%Om5 +zqiQu;5TI@eYH0>~5E4exNLn~aW15lfK}S6Zm>&`_4+G3swEk%BxkkEsR%W=JXiZC% +z;maZ2Xv^J~a@~^VS6l7XzjMRxmj%NvZt?=$HNN;S|N84^#LfQsAODWI*NxwyP<=Yv +zJxWbqBSIp*{uUPLaMzmnKcL0_B)Wm=PzXunCPY?-tF+W~^7`f^$UZ^b+*BR4_&$1e +z|HXV`W4@n2-#)Kp8Gn6KxG!C*AD&))pKh)iW{;*Pn9>)|e%uOx{dl8>t=qa+b)dQW +z96wdR^ADfp9KngEBr&W^Zx +z`N7`!BTUD+yA~g+H#eX#J2Nfjk-dWBCJU`Q^9EruBG%!I$lW+$@`qH-D@klOCbpGR +zzBXxCi&>)|E-2OBh#>Ow&!gKJrFSpPy?J=?-*!SL)4^*$q|N>R4*&d+cVgmg(j=O{QB*x2Cg=P!gZou +z>(3M-OAjJ3t_=<9S4MP|Wm>zaAiAm0-d?+4wyq=FhmAQRxA5{KG$MiLefyyX6~Sz} +z*B~=)dilRo?}O>9--6Y5p9&lwDret+Nv<{JqMA|n(7nAmzt1G`&%^8 +zFsTv3h#{#vBi(-w{Y7QuO9R65gD5IH*#)YUxM|v_sj%`(w`p}A-wmq7!bu_zwol`9 +z!AvGqn%384vcW`D-8@(M#d}DW80f?HIdBgT4>GxH+5I%@dYikomB;Wwloiyi)~PVN +zNsp4g8RxWvTZ_QA+lZDvs(7^XVuXERPUZIa+5a!qY1<0Es7Yvdrki~^+w!Is?a!KW +z{dFDj>3vR@*65IL-99(PTwyzN+w}+VcRN%!qMOCLCTIBl;ZmBuk^hb+S@js@yK?)@ +z&0htSar|Wv+T+i;vc6}NPr(uw=jN)JRdc&FH1Y3cuz#?Je=^$EK<0gGXduUF@mh5r +zrz(v|eeIgXEJsN&$?blX$LNpzGtP99MMV9LV`r9BYScdxYL|$v6Owr&NAfOt&x+;G +zkdZ#mp_AVngb8VUpUds#AD+RBc@9y+&1qqQd56M7(Y7F5@Jv;^%bj>QA}4K#4gedr@JJw^0uA&N2HI +z=2E>5jT6kx>WtpGt%5AAy~`l=KJlyir7Bb7VQvIdoK$k($eW$bnn^TtR*|Pw?ewly1}Etvc2m;^#1(&=p+3;G-|PUm~OtO +znLKvY-+cb-zyHJU{`PO+qYzDRT1V6OkKcs!XUPr!(bh2gZ_IovW%TOJ&6`SnlSYoV +z8&+3`+yNfrONhK{-dJOF5PYP +zbLtQzYVv?P$O#+UFADO0yhW92y`(B`G3q9T581s&5QX%Wzcc;wYTBDyH=(cCUGwF+ +z@U6z{*K5@KAVTH4_ZJ_)g(L53ne(+#8OGd1eI`(f+bX06AJ1#-FI&y}dfuUxP;YKG +zcYOoDG-9^!c$F|3wcItX!K~@a&Ig&I(pIY(4?X)*u&KTSL8?0gL$mBx8~m;9N3?># +zpj;E??lyU)?(MX9`kNvh#zAP2yHD?YCr4dh&V}2(+5A12&9(EJuXJkE1bMhUY0UC& +z!Oz0F?T01-#MDN1>=x0_Z0GH*I`1IX6%po= +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 +z;#{_C074cS5e^AXI}tULktUDrEQ-kGp#hQA +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 +zn8ViKwF +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 +z$mx +z1=HGn%VmsSc2C~OyTN7d@)QtC7*j|=*pS>&6eObh+6fz5Yx4_oLQjOLG@;3qm;{!2 +zAc8`pMXg5ifNe#X<;)Y$*KNH>87rB*lB3GK;;6Q5vv}~EY +zT;hh(qEmETn|#3Vil+C%3KtSFF^TVjZvxT14V9n@@AH*&qI)niilGv1l>|#u1$X3^ +zV~09`bH}v#+OSM$Z|p>y=1lMK6^x>5P0Ug6T)*blFwli+@tKh9rV#~Tv|))v-lQt# +z(VP6t3UFLdXcFF&yq_xJ&z(%Ocx3;u%@vfKp}{f-WQ7bQj}Hx0UqT*8V5%PEhGn#z +z1f@E}iOM1ZA8DybST2tyd3;Moa8M*yTu=v!)b)_hU`-FjblY5!lV=8CA#zRxzZjrs +zQevST9nR7xKu*Whg`%nqMz4i)s08VRJsIRkIH7+fAj`57nkw41VOiT~g0p8`<~Ne- +zfp!6r=x7oB*rwh+6KfRw#TA4l#)ryP93ryTwnWC3%F8xYF7aB$gwM +zE0*Zj8xdCD(DhgnJfheuK_2GRmWrtNyb-d00Dn|9)8 +zTFNJYWu2Ic#9&EvJ)xN@{A+L&dq5MIT4mV9HYVh+?S!xzk2fD@V@a?&P4 +zKD9SaGZYfYN^DEvi%TeJ`wVBKO+h;{PDvy-ycG^e^O;rNw>eg +zxCY097*UDD5~x^AgUC3eoHM<@5}KQJh59P5=_Vv?+5oE}s|+cY7QyFkw{STc3N49V +zeMyw`#XS?2IinepgZ+Ui8hQawy3|uHpjxx)1$*I0bOgk#Rtw50doaU}Y!NGhtH@Q9 +z*dfS?2c#3V8bTJ5$+ +z%X#Qk#1=Huha2kDpe9=)q(I1AgK`jz<__$_Rl-Lc;UwGA4rNw?*2o!kiw^mUJPPjA +zr;DV9yE2oE{v9 +zKq-9*IuQziP{^Rix1IZ}?x|p5Milkiz~okwqf<@j>din|9Sn%U}>Hw+8cYNlI$yxF3%Ed|hz;YHSKa|((-Krbh=nZ- +zQK4t`%2X2(uCZccON7@ahCT^npfm{)uR2>eqAB4tPpCxCY>#C`sy#YtF;0mUPW9=Y +zjt7%#k~tUXF*up+NN# +zSqiEy?HSIrVLzigBCKE@O4LiY6~`k^aQgs_B@c&cAvCx0B~gZJ9^{Sb3a0FeVE1Y% +zBsTOsxOy>Fe>Af~!`iSXpAMc>nC +zMhc$?VE`3>U!bYjQb1+BCr5-1&%?plu3B2*nRz<1p-CPj@Q`X&5up)yJhGA8oVveo +ztrykW-1{h6fyhaDvamNpEm9+@edV#J<6h4ll~5$$IX0aS`8K{n3o0}k7$PAz3RuqJ +z-ZmoW69Em{jjRxgmmjbTjYr+}tPMwyD0sd{hDcs=*t@;aYOqYrk-e9r#6O%z!gOc3 +z8nzpnF2=JLj;JGVLOv-h6_?|xe(t}#`r^)T+?(*V{P6zlc21udT<@8i}YZR#H~9K_y%ElrRj;9iU+4<{PGO?;G!13 +zqWWzgM0pyBlC0pIpw(>n4DfUVB>@L#D=y~!Aj&&g+UFoMwj(_j5Na%WNPqEDq!Q +zCf|DWC^IiCxP~N}$Hr+XnZ{8^H;#+&tNbmy@qN6)s{i8I?|%E!?dwmU-YUGFH7vDk +iA;-kEiEX@VyuaSw=y{wAQSWA$V*Vf8s3}@O-~#}4>qs;J literal 0 HcmV?d00001 diff --git a/components/resources/adblocking/easylist.txt.gz b/components/resources/adblocking/easylist.txt.gz new file mode 100644 -index 0000000000000000000000000000000000000000..ccd31862f5d3657bb22389f284a868f01b4fb9f3 +index 0000000000000000000000000000000000000000..8677476ab4d6e78896c47954a53ef8f21f79a589 GIT binary patch -literal 136086 -zcmV(yO;Hk^eq_#RM=Gxxq>r&#c#u -z4}->JH@REn0bkbH9PV%sD2d(8X-QN_O5Hs${I_4dNU{CMez5yjMT(DNu^uGne;>Q1 -zx9#EjT|fKlyYlw`u6}dqM -z^wUE>MeL>wr+_6_h3bk%jiYu2;a+b;NoY``+G$t4_~^sA*M6^cz=HB=+HD9-`-wo+ -zLDLnY#-6B|ZExBD^QM-3xieb=mGWK(U%lw;pv?I2@u(ZBVBL-?XtzL*2;nyvuX8-; -zG1Mz<#$BSUGpfhV=3ucM7=%m;hM8esz-(G)CYVWU$KVY2e>um!oxKJLToq;j5x}q! -z_ZEJz@>MaaU>417Pf(+nwC-W3@7m!nwwrrhyjP92y@JmsJL!`_nfkpwN(0_>x=}JZ -zA542V7u1P|Ax$!ae}Hfvp+c!T2i-XsrEQ*c8@`R=iv_LykZ{oLo<6Ywl!3nXCC%0L -zJ(LT>djj2o86T?8{W0$>Y@S+u>KJ8I>s+(m)y4-tf+XR!*Z1+}mz4=`pZF({oU -z&;Zkupdx_J&6vQ}Mi@aKI~n3?4yOpt0!AGw>XZQ}GNERKeT~{cn@IrHpY{n%JZ=Vc -z1h7|x`D{mBUrH|* -zBe+D5J2Ps=y=rvNb=deLnw(t>ijpX&!Ke6rkrS~51s>~({l0nek@gky#MCh{=~jji -z^Z;@TI#MU;8CHqw;sm*Fc~hAI1%s}1LmaSQ3`n&JfotR1BT%oX^yd5XO -z=wG-7ii}4B!YCt|G%dHH{m?#2Sha(64UnFNX@e^GaUI5fSMmjIyH-- -z6g+OtF5#d>D0K_r!TzTN(9{HKs;Wz;XiU4elnPa>cHl+3iCHxejkLX8Xws0@Eo#RzOW* -zQ60`+ngij|@9$T2%jC^aqySpj@Hgvzh2SavMx8@_vaqEb47p^6Y(oUhp?#e}pJQo; -zi8{l$B2@7QbPF`r){5F?3oq+_v85%L_=E>rM#Rva$LhYk<*qYJ6Sad0t-Azx$Xjb; -z6I-VSy-Db3o#@ooSsV>PjHjs1PJ>_-npC6=eZqBUe9Vnn2X=Yz7h^XZsRDZPXgnBQ -zRC!|AtxMg5YUfcB(X9nP`eCJpghA^Pb~87y4PqL(K~i=eB3LNmfzsFV%gX;*0Eos+ -z;*t*^4|cRWn7g8IguZhJ3>(*B3Wo+tHFnthvr_u2VCrCH-*>(Kxrg80j8c3>YsDli=3v2cGq)va! -zLJ;4u^YLvXJKVROv_y71j;zx?CP-%?^$4N#nus2cS$xkG+)_qxpO9WrYzSkXVug@) -zT&5dow|=%k`GdQ)Nw;={s-Nw#$ikd!XTpAN*uXG`w7^9dowc330TJUa$1?h)Y0;P> -z;6=Gm@1LUm^u3jhI2zGL0F!1f>7&rRlm&MXFtfw+$LPzz3UmRhg%79{hyo|#G=$eS^=ZQ&?4GIP)DG| -zpe|WZxrE=ZAvwf0yv8S<-wAR(iS1%48r>DLTug7aoV;S!U=aZ`^s)Rvr${4d%rMdE -z5`yn2C9l+|3yP8DY>Z_SnM_TFPpc5c_6hk6ZWt{uQ;n&TuUsp~43(rKu{lXjShx8^ -zP(F?X4KWefuC{aNtv!@z%Ei*9YAADzEc`^lMZg`34z`(1A5tzo2g|9xI_f(b9Z2By -z-J276y7km>)yeGiFek7z5nj79n?!KLyV5(eT?q;=8GrZvo75rqUq_P07vb8Eui%@N -zfR9$ -zd`8AbiFjn}qJn~n79A9Xu|g!MhZ%fz0|8NLb@nU{`uwzAPt~ugPVpd1gh9nmQaGX( -z^uUQ^?d`Uc3`P)rvYo_^y~qy?kzaH4*_m!sF$6<#LV6CVne#X`S(&SNWL2<$Vg^qV -z5dy}WyW!G|KB!hXi7uqpWA{gi=DL2XRgeMOJOa~w|#CarZbVKHSnwy8KYNuo~?lfNOP$D4BNk*($?2(Ew(@w|D -z0fM9RqtkCcb?aCfLj#Pq(n9U6oN?bEo@oQ+crD2I -zksZ%L0b=JHZvqBAcvdM>H?)qhsRk8bDGemFWQ90CqI)61@dG-1yu>~cIgY+C5lfL1 -zWlmgtv|M~dISrF{lp|ABKE4;QvbfdV+T^ZI#jIcecvASwjg6G&R-3_e50?hbjIH!D -zwrQRt1hJhK--`q)_II=SY=QplO9?_Te~M&`Gng$fWkDoD8~m_>i`q&#Rh*~!#Zbmssp -zE1Do;uBwaHUly4Upk&~b4#Wb%TtFwW+|FP-(SU(2M57&EsTzqjzjd( -zviR(z$5Z^pqUp`31D;t@FLXhSr`o;gQ=?s%cVahicJ#(}|ckgCgRByV1B1ViSA)BWozjPtC -zRz{u3DC#|uV_f}Zc -z*=XZ@IA?iXRyg+otZm>7Z0z{BH+z+U6=mN*jrvW^$qQmxne^R?>lOOQhm;QzBH$Eq -z!2RuIH&{hlbQ*o4_!F2+tG%bCf9GHyw`?hak7ogVRDz3R?^r$NMw%f|6Mz+r`Vxsv -zhW%P%I&$%H;C(s7RN=CE{o*Utba_EtekIEQa#6o4I0h&h(?v~f7aR5erB(l(#?<#?bMVB& -z-ADAxyZMkwav@nWN$d1=nP|DW4rG?7>!*yRhqw-w0uWy!zz+>6~= -zesJ*y%)8m)K;nHYtb1F|2Z4A&p%q^-@Et8Mdx))_rBiOA<98%u!P69nA*~ -z0Nw=If@x=8>X}Pns+}N6IwuDSg~vy4!ZQaw&BL^|);P6fjW@Gzm8J(U%FA0n{O#?~ -z7-cDcS!<(4@vatn0b|}uU!AqC!_(zdtb4tHvf-V`);bhK5)R}`YHT$V`QtaDo!0oU -zOQ;#|m3xo_(|hF>NLxzXi3lzZkeKyktXFEuhI&wDvIo72=AfR{VPAl5j&|+rV79#} -z_tNrVgox9Xos6?r6WZ^cU7N+2*}{rs9PowERhPa3y;1$VRu~#3K;tR41=Xab9bj#w -zU}w6lzGr8=10}}=sN~D)+)9?CHBkHH2tu)<#oR`nO=iWht#5M$4kR7p%kON7H4qQ6572-31wr -z7vvHLIZzgK%tYizHGzB2#L0JjU`pr83BvTV)RLg=&BY2A5(-K;~e8ZayJ0l56_Jc8*^iGgNcu-Rc|1w(W*b95`e -z(#vkgzrBL|5?%k=AMEVC(*15-Zs7StYHHLr-BOF?TuR(*f}|SdM*_kAg9(TwGheNi -zi;MvbVr1bFf_!wggPEOK^#+0%_61v5x=A+Kc8=1%UWQtiHd!{T|=oLNIqn|KHR9DY9H~O*lQtBciu>R!xv*L=dk42*fZSaeP2S -zm=9|Sudf{I^<87VzH3B?In_6edMlmKV@3o=R3qsn8|dCbj7ChkS*E0nM?n?54l_5w -zZ%GiGd0u>EDWHnL$W*h7{^}FDP60J(4Y-{acJx|_p0d>0RX%o?u70DOF|1xORB7yq -zL4FBXrz7t=!zfibtG%k%)0BEmxD)g_j#a2eOkC@jMb$Bjs^u+uof4Sp>ca=j#A4X| -z>wlR5ZhhBT+1TKF!qUl`AT&0?&Fz6LaDJ4gF!Sac^Cx`ZHe>F}2T5P6L=S#w-^s&( -zPim&4c-*a%YIrgs07(0Y?P4ZyIi5^`}TaEXuj$faC -z;qN3W1<8c_?p0SU2SYd2b05x!ePyQU?z`$Woq;cv_T%9z4NT+hYly8~wS@sy&uVEX -zQEG>#TljPhqukM|gO_s|Q5;`cyqv7oN0P%C4Km+puf1i9L_IR~Dp68q7VQ7-2$Detm5=IOz(99pM3AB=K7tX!V6ba}g$Uy!Y+tH@k*+s2oU6x|`MJ*tqHv}m12`i;5PtEm-nhSx50XUkd -z1wXm=GJsFRGM^tz+KX;MpuAYhpKPoBi-W%V-Jjey|H;$}1QG0n^%jLD+X<0|%%hR( -zj>vUK@E;Vqnz_b1s4LlR&*-~^nM>L!)@QDDM -z$2|2+B?F)zhdzi_4-V3GqE3jY6D(kobRR_22a#)eI*9gP^j-}x&!I+hJ)vj>bo&hE -zfK)a9iBc~&B`8I!x*Z-gvXnpm@sF=RV4GX$-|X+t_V>5eeXK_Xg`;rC}AkPW@0$7K%QAc`o&(PwVoU=Gpu-T@!8bct -zy95#jUy}NsA#{P7v7?pf^iSW1dus%`4`bO8Tr=2JXl1_!Rw4t~kq<2X<-vg`g3Uy= -z&wOSh`TGJ>DnhhL!6I!n)(ydoV+qciEka*m8K(wT4zjaU`+6GiFKj&iMPf&y)240x -zzpzR1v!9(m`|*Sv%R(Ui+86zTz6H5`!LNScXmG_~+n`@z9C*kLm#;7$eEEp6vcAs7 -z#aF#qXkkAteiOL`T+94M-TQafyU~h%A8j{9Yx>=3p~GSu`ZY45#kTaT1rCc?Mi^Pf -z7g@#^v2Td{!sks&RFya%q -z^9&!gDTV{Dt`VtzoJmJ~Wr)z1)PbXty2|2$5?e}HQ!na`o1y64Y7#N7tdGwzko6J> -za(UShV~grCO^HL>^U{QLqlGxXkC3aI!LhoatS=~=3(EF_vSSpsUPNq#utqdL@-)uA -zDp(c>GlvN0BkOYPIsUALw0Y7TXKzLOF$3xIjp43uUB08^M;c^neB@VzC|Ctz&epZC -z!eRR+K2BZR@R>(Z9`HnWK>0in?x!Xm)%4Joz@YUUy7IW2rrP`6f^A>V#a-(u{@YJ%L(OCq -z6$mK`1rCrE=7uuBPZ5j-obsR&5)pQG`IR_oIgr@L9kPtCt -zYA#;u9Rd*a+T+56AWIpYjsq?9;;PT&uv9ephlA5mgF&jPCQg>2yM+LgRvuh?kT*7> -zzL}^7!MBIngt~F5K`)X{!E~SIGkRL&-GB<} -zV$Oz5N-Y%n85qUqN}fVgS?A>FDQLyX&%+514;m;UWn_vT*AB7^_T-)gL4^3IhAn%& -zq!3>VXjh&jD}bg2ZGwc0bwyKW;)A9+wU4l1Y$7pYH7b=15Zp6aT~H!DnxP;GW4~xg -zp$&4-%<|FbuGZNP!f8lkRT1pQ8SY7HC>xNmy6M7*Xq$kSYKKclwX!(wCvtAw!0O-A -z({2f5STx75mYSmD4w+PY%+)KQ?%XRw!nQU<#&Bb1UUJ*8%43A&woqF4s0w;RqZ(KX -zhnUM0ZXR25PQ`21MinO{Oq#8$hW?sz`0rkDBN8hk;>BZ+2$0!B%5h#m6x4zjFiQxY -zJpKIZzkZKkQlMm`*K5zL@x&}Nfiv=1Tv=mA)q-4PWq$Z#JP~u^@B*FDaR-+ZBW5My -zBh4--wq-r0IEte`%wbKvj1mRu5$Vw$pEw#cxFu>sUX8wbrKk-5;VGsn$Wv!YX5m>3 -zSv^mI*$)ZmeK6LZ>&$a$tH;8qSF<$J3S&$Y${gdh3oSPW*@WJiIRe71oa+n1t(==V -zVS6PfGMG7a$Ow!*=$8}3O7XB_u&b2TTVc5#tZ@x#Gv+uWae)$(Xqj`kufkBp1Rh0I -zb;y5am5<^wM`w@q42O;^I~n=+%vrWS8LbRDEiSFLmTJ~qM9{ev1DR;PySPDKTk>n_ -z01^r`;!Hdmqu2kYmH*fDvsrC`g7abUG9IlLwpb%1Xj?dbu`@=dlSp+9q-I7l{aC(( -za^s~iJj*@my#rkht@4@j>3Fn*feo`1Tm-#ft!30i%|vE=&4QUp%>inH+!EsuZ^ic{ -zQqLVldF+)V5icy#)(?IDFd&B5T8|ds_qtTAw?A9Uzm(cnZC#tx3Eo%u$LcHsT(llt9}al(SpV87hk+Bd2oQ -z5p0dv!^93I&>k8#2<;!)O0kI_41LZP-LpfF{$Hlf4eL%#wd{&{WvvPeR+cMY%^3hVGuMMo7zg}i8SjhJUKWl#zJKd{D@Rm -zbeN&1VQ@;fiidkF=p$!K!nK43kKH^AKEu-dt6@R6TdB&TsS~0NVj9qfp41$VCW<-u -zY@yL`g@suqIYD#hj%gO&|V=Tk45guW3Ji -zF}-21zkK=nCfo(yV^)#O>Sc7!uTnf6rtjn1u&?&bs -z>R#s#jv7oAuMYY_9~31Fm*&W4bL{nP#P)y>i;j+G6RpORTLA6#yI@#q0p1G$UKBND -z_3}`OS{P6tMARqXHC`xNWzOsfW+^L{V#Y`B9SJP>LpiNObi+_zR>aDR=373_OV%TP -z(pk4z2Cf*aA2D&&&}_y>yK!MOwKcFUQAr(x-hQ|}X-c5Y4;n8K4X6k*Ln{xi -zJ-G4UmcYmt>md{KJ;WBP8NLp2#Zaa^(f&tJoL>KoCE8PX0hF5!A%j@>pvRw4+wg>Q -zI2|b245Dl4XJ<`D*h#6{eb}~R#TrNNzYDGNkH&#D)Zuw3l|YyP*96GHVVZ^Cxtx@yA{n -zZ0G~7$8&~>!nA!ig0|7j>0S+K`NKoXgEQj@C!$e>S%xtwu=E6kMclVXWvc@TO*`-x -zxpV0xA`a+vL_q3*V3E@lDuO#C0s2#&J2-MBMXqN4Oa&(xMrko75!i#v9-IjD@r8)O -zc^TqIKW4S(z5`YcvIbQR;~^4@kf{q%I?>EwGQJtyj=F^#bCWs3%)p@a?6GD9kD#;_ -z^d_^g*c#h5Sda%F!?h>hS=cZ+h`guCk5-j4`-e+gN#)%vmajj2e*M(~y14=PsmWRc -zeZ?c~28?ZLx>&q|7}pRYjws7Wr515VG+B4UnGjTI%}TCOdthDmmcSbUap#bN2--gj -zX;}{vLj8S7i|I0KOpY%2$ELh==iLIZx$DEge?vpuFCb{liu@AHVj|#FG=tqb>Zzja -zX6e6t`FBGhmXDyBSpew^WGvX)NB`YyQ~(sLyMU|9Hc&K85q1rteir9;93otp7xO}V -zJ#avHi|F#T?@G~FUI3W3EWf4wh@lmu_Sg`!_tx-JchBH*xXVTXvVm8}orRXMQD7?$x3sz8U;0t@sA1 -zJId%>JAZY)cFV70U5oyVuU_yE(Q(%dR5z>#UHvq`oBcN()|Py#zTjCrB>#t%g3VKZ -zPxE1Ec#L7*%ZSy0D)1krJnA$7+_obQvy2L%XsF<(=TA-KBQdv-Wb7J_jh?E~-%{)M(7^0I~u~UO^M>eMZwJZSRK@!E84%5L}KjotNr-hBT&y -zG6St0v~keZL5~i4a?ltL$G)ES#f~ -zp=&|XPc=)J&k9ENooR`_pDck-btF1S`y-f>h(yW>C>az?YGXEcNI1dC$m8IJ_wK%+ -zEr9j*B1pOT&Ne+euxI78gNHmvVHImnI#`THS01F%rf+p|FbeL$_PHh-2@fIi>+}e< -zTH+gk)F(pCcD4Z<53N18@t_|E29d5*=eMjeJVNQ<7M)Xg-4Zt-tSg%VD-RjBXM@zW -zWchXLhZywJ!kOl0bU)NQk@Hedtuc68S6!BIt%z{IhJ&2=|2)s+;l3m{eT|wEvJS&A -z#0w02WhvCg;WCoS!E;><5nPF~cCYY+ixF%0$3o0?q*1^vRQmBOE6Mr+pmI206fJ3R -zWaoPiseN -z%7Srq=6j=2>6Y<=vk8hZhYX65th$3(=^D#x4jN(SH;`amJ~c=tSdGl(f?$aAG39CYv1b2IaV -z(6(Yyvw=-l)?BEIGf+8L4MAJz7-$@!qHRPhFVqp?vKEvQ&VS?1?GU#!u2HEE;dl(B -zy8vO{3#|D90mmRSajAC7Eh2gYQbYb_#<)*NyGWFB2$V!AZLH`#pGIB7lCLSkok-aP -z=&XOIhGPPxORj_~{jv@Dp(a*wP7a%w`?o}Va&)AMliQ2lfVl8!-hbv!2jyw_JKP6fVMAN+`z~Vwh(> -zb~G{IpN4WVoRE4s2{oCGd5sT2OGOc1KD70pU>)z2kWO&ejR1Qumcv{dcIK)aLbcI8 -zK(1BSAN{i^Omc^?`EHH)7p-N;v;NVo^^Fa^?9d3}kRbxFUVScPWlquZQ}514fv)nm%$HF#bWi-Cg86 -zQVR~gX6H^aaDlFN9M=bTFBy&X$m{_} -z)|f}pQ!Be2V~@BoDEgbS#<)V&W7r^r3dhq9|9su-H|oNmForwH~KhJ&#N=leD-FG -z&(u|)ot@x&(P88N=EnB-tP{U4`j$r0_x2Rok{vEynghfhaw^C7ctf)L$e;bf^YeUY{_KQ_ -zpIw!Hb}GQnOtAk&%PYTzBAh?Qj7ZtczUCJ;sQ>Eb)fX@CewnXLUjhl!y$wZ8zG%`# -zXM}}vo7qY(2gf4x|nm}5p -z5&FJih}kyyK4dOm{p$Z4t!I9yBJ_91$9^jv;FhZ2Xnp#3$N2pN!S_a%F+^+nrFj-@ -z=+{#iLty8+347!jPeIy=rEP$H5O0Vq^NA<~fQ2KDxLF>39&2Co*;}F+gN~xW7!XB# -zcts}W9U)94i=qp*9Yq(SQxuV#4L4x|)puMJT?i~Q=_3;K>zGzFw<THeB|rDRbZ+2;D5^8JTSSgKM;++`5mnZ2 -zpM{g3DRYrmqa)Bl*B%UbW8`&E4TeQ{{vJ#yuGB>O5K2_4O1P=Q)PTqfts3M_#YFnZ -zk011RSu;48VJ5jT^>^X={A^vH|Z(UE>z*NI;AoUs8fX~MTs%t@m=`e#fMH5y@| -z5NkrUTiEfGSPn-C>Xq5lwT2MGw)n6!6xSebHzv$;nj3FCC%~g70jmdsFV1hvIEG<% -zIQae&=ODrU2%Yx#qd%zx8QwgrK`2lbIKy!)#&a0QVAeA{;1pgW4#i!^a-6Z=o~>Wf -zt?m}?-3v1(2j=y~H0Kxgu3xdPzlvyfmZ$|9QoCMOEwNuk+s%shkrizpE3YrA -zMbIHC+)q~FHnQ@%rLtiY8FuoRuLEZS%I>Y=%^Bf7gK|ov;)B^D#?3hcou -zu&Jrba0-^%yQb7^ -zU48EAKPQEp+9cJiZT&P-=#iVT*RXk|7HrZ41_TwFsFe?lVX%Y$JQKH{k1=hBoAsE9 -z?@pLsPZhU`X@q0GH?`?27?p!BVsw3kUM6$fiVAqRVymEj>Q^d$x67e%v$R2Q`(3QZm2Pc}%W#eQ&8;zt|04&h&zkf#1>?#;8<7aw*G -zQP4N)aDlT3s-WF^Shw`8DqMG8(0Il%y^x)T}_$*H?^AiDrJ%ZV^Ao;@bI-{>0KIltN -zlKt3_Ngs$)MQn{1N*5A2l(T5r_^y%UDq|w2h%`X?hiF33k%ltsKu7eQs7d8j*9Du# -zHm3}Qxlj{{_lPEh&9B3;y6KA8=UL^yzw+t`WQ)kl7D2EWM+m2eCV3sf;9*_-IKnMR -z6t^k9rltAPydcOo_f+`(PGPv%H8WdPp)8LyXGwJt<_KOhc*Eh8A)c!MX3i5(8D6VX -z!7|!_Ad9Z7oN>2Jn`QWX?&|9mK^wnv<7Nh1JKc_$oBgn4I*EX-VhDCl((^-HZ&y(J -znfN#cp!&KEra|HX%lWt*ir(2D4eaDeiv~m7(m02*By%)^GaWXLU47k}>c`c!og7WW -zD|Q*mdEe#64pL_0e)59% -z05)mgo|DVWgu{tTRZ}QCO$+{zYwF1k(eqEfr#c5*e*~C|+DRN_Dnu}D=GkHh -z7ZR}{b9pNagA@`jI#(yLainoRW(?uPFsJfZ?6SaMI%*2{6V!xqRy{tBE~7RPmG=eW -zY*1;m=p}Cizv*nzA;eqW`a@9EtZTy2gtyTItGK3c4r~bIGKAR5gKH0d4x9cnZ)kgL -z#~^;YL&u?-i)xxU@AD|=x2umhzYueXkHa$Tb|iSqho$@$w7)$WI3G`rJS$EUlc0kg -z)u|Ez_3{IFQZV8ufh%B~KA%EFpN&ID4koap&f7y%XM>c;AwT2^ei;tQ%rAu}xYaTs -zUhRq5h<9W@ZXNMj0T<)mCR}dB&!V7(l#r==y4#;-w9m8cnjq=2CZDekw$E3_+Rs<#b7T -z44$Gl(gAuWKY0>)wo>Q16cu9Rf#E1qh}muk2>#H2NM}V`vyKbi7$D*IZ8&1r0E1Xv -z*CCbx+W?S1d}T<=VOEc5y?r=s`TL`b3PcwT9L--A@fP=YCk8b3R-SuGYMbIpiIYS} -z3382#`yRho2Ylu|66f?pxtMX>xXkT0mp)VO0DY2+AudZ03p2opncCB4Y}vR@Wh<0P -zv_)E21<2woina|%Zs1vhYYc|-foAR@%UB(=QJFX_>|OIno|dfiL1!b2!sOVj%`H!Q -z>dz2U=ZTipg#9j<>ptQ?_``M#4HZI6_vV9wpy5I3>J$VG}bPUK1A#C)F35loZlz4V14Lv*vTEXu8%tG;BXE)Dw}=m -zP%eFfqs$3zWD`hJIDxuaFx}`;RV{z*kb93ZgAYC0ZnBI8e*Fhw&> -zXo;Y+a`t@=(cD;8lIMxhn^o4 -z6fCxn4`|FVYT}X%>{ggh+aYnIKW)djlHViWv6T)Y(>s(3!ytX!k45@rN25Z4kVS!p -ztY<1{;BxpNrt5a~XXA01q7LLuVJh@U&=*1V@d9&2#_d^z| -zNtQ8cIAZk3+j8`2E}LXRP&?3EgltM^Dc{V0j}C2I>bA^c~~|%}twXaCIrog0lA`G=c?xfmeQ^ -zNV!P(o3S_==oh!!12_g(*H=>6$&4i9!c3}qKK~3PxKRBbTU$&qn+2lL>|qm)Ob@^J -zvu38Vok5$0-cIu*$D6bkp&>DsDBMuLXv{Dj?~Ip2;iVh=sHWM0;v$v@$m~-cd0s~z -z?wnya9(R(ArO+yE&YfK*@K5xi)E&%Q*pj}6Z+PVud!4`k)r?&i^D#i!gEqw}J~pmC -zuU+TlM}23H)jGpg=!T^Z8ekb2;9o<~Y!-h%d+4h^AZ7pQYwIpKl0fBL`8QrcPL~UG{ -z^Dwpm#gYk(#&hDe65TRv{`Fk6WUJ-?`tQ5 -z-VJio2gLYPl7XP``vm?P00NbRt-z#sI{OwtUm3I}5F}M|z|*Hj#sSYi$kwRfl7UMX -z3!l84=YO5yuEAOp@?686JG?_*Jk-^dL1b5sav|zYX9>5xN@Rx=jHOIkTFF7urpw9g -zG0PHPO*7eDiJ&W1)+C3NwYZpv+B^NSW@SxlDnJ%!7U5185Lk;+{C*7t`$uJyxIE^1 -zhRGojOF*_I)*-qL(Orl>2BgBDPMl;Otgu~&4XI;&L}8eUV}p+a9mV0POp7s6j8E7Fc9#nQAqF%bV(PT#92Sr%QQd}$HbzZ>yK7(1Bnvtjinfo3C -zDuQ2A52+uGP1N6$vUC@qEGu(K%1qm~*P-FmD44Q>KYQz~E6;-o|;%B_$C^gL0s%rh^vFcb!DadcD{SS`TQ` -z3xBo1iiepf&43{{u*85zX&MEyS45$b(VWk#ZLiw?o{YR$)N7i$m<_Z$;u=WfjXCH- -zh3Fe-9HK9JG~hs+D0N1v)Z9ABQgo#$>Jm)qSLP$k(6z^@QY8uE{IVO5D31mC2ySe^ -zb$afA20XYYO!vG{V-weFMJ%c*N=!+OUt -zEAALn5y<5V#P^CJ{S01N#IaX*>kmWNPN=20^9KPrvUgf>k~z)hiEa|Mb@?v*kZmXO -zM@O5zhqR%(?pMr{pzhZJwh6E;$EHXOStQs6_sd#uW_lM)eIpUb+^Yp+OGtDEUP}mV -zy!F{t{rnrO3#Rwo1wsK5&S6ic-8fI7#mrHnD5Jw?mKNGZ4Ut|xIjX*`2nX=&)l=kh -zMCLLM{S6Jj+ySto%>|;(!h?~Mg%Rs8*u0I!V5#{cP<@+R^g4b#d2?F=^PXxN8|eUd -zPPjR@0shMk=1sS_qSrQqtKTU&v}uU#MdP>BYZ_Rv0}7fDMa~z#%`(c`xM9#XWc|iC -zK44XrMsJ3E$ay|bWVFm;zkt%7Wf);u2*h_!7bG6XI} -zG82lsr*El)S}qv8Bp4+5%TaA^`&xwd47AfTC#H@z__V&h@P`ZyerbZcMmMLQO-hIH -z{+&zaW&gXowgN;k%t}~#kj9=KF=gFSt|^b5agFgKzN>Lr1WBRAD73&KF@iiDuI}2( -z&0FRs${lAAes$EyXNXIm{V4mA&hvF$A9Z~>S;sN&78AyaaoMb%5}2=jqLHX3I6h -z!aY;BukL}mjeOuAjk9ddT?a6uoVZO_e~p?Mm}5qaz=F<;&b;Y;;r(CfvNXTu7z#{y -zL1Ne2C`TG_G)Aa@-2Ab3G1(9ch>^O2u!V3-lP&x&xt|kSRbci#ND2@C2{% -z*K=6{TU!GHdk5<#jhh3DbAi;~uebE~>k+tOu;Q@Q3pM&ZbIZ|$U!k%L>>N{X5pWaXZ^Qd%naQtrtZqsIuDwYH&~Scadub0kmrjV>RvRCA-wD=SzB&b#uwrvGB^0-e+6#ZpZ%e8B~e -z4sI!AnB$b5q&UjF^=ZweB3gc3J>b2*?=5mMy%elVG`a9DL@F7TeCNK!+~Ve&N^DA4 -zFr1ovhFF;9ox4v_L+)NA=JIbrbFi8a%N8xF7(5Z|pJo}t7keq6-L@!ZcrwT5U&c&t -z9=&|cd_39&+o)kZ3|DY>JTfGTM2Kn&jy`+Vlb82`wT^dQ=NCSD#Igho+f6CxaILj< -z8+@MWWc;2;k2uzDDb`kLG0zO0rWzpJt)E>z>0sNi0~S3y~2pT -z+M?8979|q};jSy_icE%lu~u5T5L56(CmeX(DNO9XOz%qMiL{{>Qe9LncAsWg0ew?} -zyRys^Nk{h-cL37g!a1vKbggF5<#Qy&1O#0krDiT$ -zUpjU%#%N-V9A=F>X73@S@zxt-U?pX2yLJ$6E?X!0%T -z(jMnxaXo2sJ8646X-7%!rRk#fVCTWX!x%Zl&%lAEo{6eYMFAV)5{S8+);f3kn`)Q# -zrrL>M|Fm0*tkEnO7ei6vB`xTbNG~jmH?t}AawHAjm)nA~bXYC$2%jy@tsT~ObCEZ2 -zqp}2drq|-GU%mZjhIT=Lw0+17NEY<0mk3uXq%Mn`7-;#5$JkQlqw%xP_D2veUUqS+ -z5Q&$YYe@ArQXS2onO+8VB{1Q3UAO4cK}G;_uHeJ`nqWiuyKmvw)Muo(y;gebh0w^A -zPG)(wnLM}~fHfHStqgRruYuMMq7m!-&5XMhnF7R)V2gt`=Isvl&Sg|2a4>lBK_^5k -zQ^f1S=)&JgrSW#KFPBI64h_yGq@h|Lf|C1g>6B~xS(rdo+Up>Yo6ENJhae{!ClS@1 -zo<16})--2t_7NP-@wj7>y{11igW54oa4*uuaz08Y9UqH`2Yfzy5!-^Zt~-W0;n9iV -zc86#YU^7I87>Oyt>48wgwn_F#s=@40v(TJpAi9y+Q%GfrE;@zo*^W{9CjAKql!E25 -za$oE2;`WFz6D^v*J-QYl)+H$etrl-%8J^B{SthrQ=}BUKpu#8lK0rb&2j=*0iL^Jh -zxYk;cvCv;h&^FoY-#8SY2Q(2La=BKmqq!`2-qsX~x_p=6X6~`OGGDNedBuRC(Qq=n -zEt+GqLe9djC-1fM^`>i$UVm78{rPXd8R)lPfBN$Czb-!i?f(S)habNz^osVMIyUqF -z_|qTU=}jwD{Neu&Qgx(?MMzA`$tshEo{GWjmsBdi>B_h=4axdF0ZDt`bBdNa4)Pq( -zfSH<8Bv=ogf}?1_+oAcJ@MM|J2^G#dU}cu6u{vw{l0TE48&PXlbymK7UtqXpPhci@ -zPb|}0EmP0m0&B79c}6luXOzQiPK;dtr$2o9q~s|PwOV%7s6PF{CBe&zVd(z*r%(F) -zC5A)=?w1Hv;4#Om8FBv>J)>`DXqQR782ZEdW)|G_uUlaFY8YdAGuyr`n4+{q_cQlx+Q@U=f?RSxqbg(#{A+nSoj%OewS9vf^-U$JtZ!?q@crB{&YA|kf02#J -z;bzvlR0@^!$u3j3GoHJ$0@2B4`2GL(dlNNomaUh_x|>8QDb1aF4Mvc>S*#5v3hMr{ -zk;Bz2$Kw$XFR7wJ){&Qeb$euB-fyX?g1iEq*6MP=OP8({r}Jc)OomNreT{TRJ%Mj# -zHz9eJnNWBT5Ld|$YS9d($f1d1Y3hMj$F^fL+@ptT-*05Y$-7Rb8%?jXbYi)BIB2F*RFtUQ(>+cE0?-HZMvwbthM}`fIa8_1y9Xnt088w -zTn(0-Wmj}J-;K}2TA`3oPd8<(OOCo-X?!rL+A%$fv-v*ReEM^l-mF=n@7`)_{e^dD -zkIvnyAzz-(?;mCS2l>Z8BHdu#Uh0!Xj-THAydFEyPNAEb20WyV;)L~}yPX@ggJs?t -zP3LY#kPnjs3MaEcrj-X8|h;;WPK@{G()HIo>(_JiIPxr`$>HW+^b|4d7S*7SFs+x -zeDvPT4N7g%mr&~Mym7Lel23o`uYXnC!qUuF+{+A2F0^{>&ydZwyRHvZ`KCx-;pYS3Qn&@jW;@!*T>AZjk_9I2qx;3M -zGDfHrDAY3jq+M74%*qK$zfqi-*3~&BgT?EQx8I$EHZuVSm0X*-{l%;ouvc#8vs}HF -zxzL&SW8HmfK*2ykqu(+2 -z*WbjiL;hO-)cl(sa|1S%xRDtRjkgAoPKSOQxJl+p4!*FoZF*&4xtbR}l+9B3jSoPp -z-OXA{y!&3u9tX8USHo>SJbyIKsMuHj7tn#+JP9HjJNZ>gGgw2e%B>88G*@c -zUi;BH>+_?6i&f}Lb@$V?X^N}qSF$K*o-HnYALNQ9h!Le(@kj#$jiNhU8Tj-}CEE!m -zi~5Hi0!1II4J!QO&ab)uKneN)K73U#MS^PR-S6tB?Fa31ER*{={wbluS_Bi6@$VL& -zWu3S;4Pfb)sFvORPFTg2s0J|}?~SV}wkq!tMHMt>3>%3kgQ~POI-fGvZ -zDtp{mR7WWXzPWXo6XyF7+ElB2Xt}-n)o9#7RtU{=M;q2z@$y3$2>0h@E}L>xsXSr0 -z;{0BDpdPQcPoxUo%_q|O{+g96ar&I^=Su5$`_h|PxYB)F5QdC-mD>HV -z+waR;^pu@G&h$~9qC0<7ameyvefDGZVIFh`F -zhNZ3(W#0UBO;x66hrau86byC$(YG6hFo>!G&T|wWjDi!)JGPT~Bg^!0o~bOqp`_{C -zGJTlm8|+S$^>ixBkJ=0~eM6p)vb>+;4{H8T*}?G95|pC8oCI=h_m|rdi?% -zRIR2=Lyw$S7k`6KV+gDUr1G#;Np-vRlDD{Ty*BmN4UdWAklNFIeBp594weVP1`D*nC*H%{+*> -zZ9gu4EE7D`vAija9oEol$)~QrkzOr}vup%9bls^Lisj3=7w_+|%5f#(wy}*KLyw

oO -znE2mRMyXVHsP0u21joKeVK?4 -zCs~sYyE{TV2 -zW;UI^eRLVJLU`P`g$i9bVCJ-{5M$9 -z$(V$0TNf@t*K%iBD&9WI0+aWfWHNMbSI|LA>!gd}7{<=7>7;8obDO;%aiVPPh| -zy0^iAPvEXe+mt6|J-cq^LzhgIRpkk{o$i#WpwVEoF7vg>?r!qoPFbIRF!fEI^S$9W -z0@uO)6s2E#)4X;RxRa|-A)?E0h4#BUrGh}F9Xsz2)nkdrq9h)+DbW~tk5A%``mS!; -z%?Ej4mLH_-M-K-)`qQ3XwKdg#r -zr;2~T{;K^dq&&pqnL3CaG`jN=XRE+nqQt5NCT!m)kyN*22JI^ei*(Y}+L>dNA1jOW -z4D>p3QT#S|Jijl};zMYsKZ;&mb*;Yo1Tr^;tH4m&(@MzYzirI0r9dQfp5q%bUw2M% -z8P9Z5$oYbOi=2XwHe)Kww52l!@c7-#gE)+Oz*xTe@jx@obc7+Giqbhq-+4e4QV#W~ -z%7i(naoEKiJd9zkf}Czxu-m8P;J2>#2mT%=-9h9@^+(rzTw%eY7(TNH&J(+lUt$&C=ZQ -zb$AX+&%#7~K>?@*0Tsm5l45F5f*y3ylk&PNE%IFV41`Lo|PKyg-*D4)@`ywTx -zl#7CJX}`#RZOpS|h3CTYieh`p{30DXCt5w+Prvs(Mq`;1=|Fc#PkPMxpL#k43HIuN -zFgG?D9*@4HqWgJBHCNYRxl##$qGBiQVa@$d)hCR}8U=mX -zjUWefO=w@#uTq_8t~4YMudDMdzb}V=RK^%dyl^3#wyO5OV@JaW4AR<_sP9A(f5wGO -zS*XMmndsD6jFDfzH^r#S;Koe184wU;p)2 -zY?lVDcq%@d5doAx9tJyWK~xd{X?Q8j=or>xv-$H!1z%Le?MW)gvP`9@6dkW$s-%Yx -z#{kS2RLR6@)m}fBS+)FNt&Mg~{N3e&4b%q`JV1xXxV#Xh!^s&3IV{UuDPx1Ji}bSu -zNln`5{!#Sv&z~_)&mVKVq;+U()#!MEh-OtsVBbfl&cr?=)MGCx+pqueMaTO658O#YijX!LLk8-gB=nfQj>bPMx@vNd -z*_b53ExbG-xO!Dg-6FWFQoh^Zr?b0n%-IuHh>Mb=FZRTIdy3P5aYl!}RiM9_3q^D! -z+{i>S=7Ef%`o|KZuGum#!xMFFhnK4@qzz3ykD-jAk$o#nqKTmHQ6hT0cu9{dz!%zw -zuhD~Uo+XMpk*4<62=m?kC5we^@ZafR6!a=;88?~Lx-lJXSioobx9;y0u_BP?U<8M{ -z4t$x>h!?>ATC5R$R~#fi&z{WY4lPq7-dh`R>5 -zw$Der4aVmE=pzlg0qwjO^r81O(|@eDjA9B)LzDHb(PpP}*TbWK){o6jI((=*U^sH< -zdvpI29$*JWSACNr$-91bwn70jP2`_&C(8_8m<{@F3%U)6@GyG)0ynv}KW5P$8&9>t -zyv=$I@AyUgr2Jc%vSl2|Uz5Jk67Z_ruc -zIs#&3!Z6OM7}|_TO8_th25hOfM0tEK&$Z}YaUWr4VdI5Uo%>vo#%P4e` -z9yeO?Xw6YM&tp5_O0Eb!>aAVJ7-or4+K0!!;v0GYz_VoL{U;yyFaD+nfB(PyeksPG -z(BT?w5q80K%{8mhw^wMso%wA~wM~sZk6te*(-x%)&!B!>%r%kn|Ce&H_1f6-yN_S; -zZH@3x)c&6=__F%*9Q?KHt^ea6Xf&MW2?Y;dXm6lO*ocM1YVode%txsrz{0$%+etbY -zXalTJUFHF4eXMWf(Dy{$Eh7lt0e>EC|MwX^)u)aAl=~C>%Sxt{Fgud;lCQq1Vn=W`v3m7{}rCygYaNH*tJ~r$N&9O -z(ZVQ+9R?Gp97~iP8dOiy>xnjI{sHg%(d8}=y-Cs`?Q@BCujN@3#&ymlso&v2k)XKm -z9O@-EPg5pRlYM&iJCTYSJ_Y!FThmVDcY4jY5mdgzaDIh5A#NVTW8jng-8bfQ;X1!H -zztN9uOQtZx&Ncj5>X;kfA;&3I4ZP!QDEiUhj?F6_G}AweG0QLjEu{uJEM@@yMQLaf -z8$|AsR7oj##kINg$%nQ!wO&fxbjLhhtRidL_}yW>9VXqg5|eCbVeR^=4I#Q+P&Bcj -z+%S`mZz^i>Zo^F8qEx;nP&0Q;gLZk2>+tBCB6^5(@YZ -z4@$>nuAMr}U@nrjZ;WflcU^fZ-!)lvZHbYF^@jF$gMPkOf^iE1FCfqoAe$+Y8UEpmL$AihAt?h$-u~cTN=qaLp_y7Dq4-e0q -z&1Nf~_1V7vft1z5YW=uPHi@U`O+C{GhLEM}%|r6=;3@kt-AudPyQ8eP+tp(d?;btn -zWw#N#b?l#7i}lm?W%c~zDBI0Tvfk~4fBE+Dag*+zH!DvOJNdXyx4xWhA~#Pj@=16~ -zmdKawYU4}ZJ+GgiA08iGJSE#bKJT_$=_$vD_-)g~Z!h|&wx&I9GI%n{)-KoM)1$0j -zDs>o7K3BGT+O3k<=XyH!@G)ry^UCFV9#3_?j^Ce(#L-^h1>3cZWA`L{$a)j6cfL!+ -z!!F%y)5pwHlHFq#Lt}c1%pP8#HGLbztCy!osIC9vY!inaD~2ygsb!{ -zKB!B&DPO<(G7Vm`S65!HKW{%TZT0Z7d5&Y>#jDk7o$l68Prk`k`Ks*J>tdNojjtig -zX7jiNcCbj&1{s#2uQ%CdBQyWxdiS(R({$&C`D$A}4}Bb;+%Q-@We+mhY`1Q5te%Ie -z-Xbfr?|a$CPa=CxHZI3YmTX~th*L*NwolKG+wDv2Danx3tNe{hNe18~QafmCTj@OBi?mbjqjISotv2b&KO#{=fW-*ykNqm>?Y&ZmvKzB!j&V1TNoy|%xY@4l5ZXE0JiR-ew#n;;>Qiuqd(D%8`Q%Su>n91rLXv-Qq@6!5xan{5+M$@52Gq6JO8 -zbVw=>xE|Sun&zp0jEfcFZT+%Qn@vOb+y1G3 -z+Z?y!$@f4nANvlt0Oe6#+CJtlt|Hd;FR8oc>>e7_ZYK}GqfDmFL$=%PwrT1n|K{P) -zzBPD8$mUpW)2H^5Dx#vPW3Ev$Y#48~O0^kO0f{HLS|ab?T-* -z3zxEe*gV9**fwiVkn|Af6uLonM2uAObw6FFWB_>-GiXd5EW-e=12IlWm$v -zH@LQ`r0KrRpwXV!Tj@W#$dUqB-tLe#Su?tp**$FF)6;e4x@EUs#WLBwFbcF+vU!sJ -zBX-aj&oGD{A3Y^mr^CD2KMgD5BD>ww!();>dogJDxGtZ>+u<}i%F|;ichArzj`AWl -za?MvL;@G|M5t8Hh`SID+^YIyU+uepHAM^mo -zOsl7jFZN~9j;k6@L<*c*_zFKJ@3$aOn$Fdk{N7B7tsV%gxinI@@ibg`X+o6Y#h73Yz)FQ%?2!rmBrPuPHeA;v`Pp -z9C=DsGD)7+$%Cher{{W;s2oGJKjm()K4sbSCI)`sKJ9t+^dMHLcyW22H#_Ken1rtW -z&;i9$wj+l4yalP?*-eS($EP%VjzL!N6aiWZjAj28SR$Z#9y0f-&(HGhNp&@qnLa+p -za<%o##B(Y^n|OZqv-&wpb})gTR<7$`KswuHARxJ_zO3N`fd{SKgnI!tlRj;prGIKS -z_OUEZ=XF}p6nS|R4odrI -z{%x^X?Ox<&xATk^FMH8J -zhr6zPnRd?;Aueo|K|mw53!qqGJWt%hH7<^t2J84XdD=d@mKB@T)8lTte%N{n)ZihO -zzSd%6&PMvf{a{5sB19ffU7q-d^I9M2Fi26> -zr#kC>YTb15ko8?Q`7ajjK1s`h^u&~qV}}?*kichOf8QxMsF2Mp88ZC^0<;L@1X@*^ANwY7aYz_pH%0T?F3B^%gKP}EW7~* -zlRABQoapiIduu`xi;Cw^3S-HYjT(Dv|MDqqe@4$4(F`e+#CkAE@J<7m4P}#I03Y31 -znHVlJROcS*TZ$$~;w8bHXw4ZdjFt_vV{C>}1{u1lR0Y1G)@9;_k39>9eVGrU7b}8N-fm4q=Sw=v6k@Sk}(!d?Vw*;)pmuBU}otU -z*x;P?+U^|=OW;9lS^&4fYwKIZUUe*0)z`;C4u^5?$mznJMWv~pF0?NZpG@hZ))CGv -z(#R7_Qc25(1>pVU%Ub3H%)(k(YTcfe!(@=n3oP8AlKbSBmzQN+z8gg7naCJVD*AC~ -zz2atX1%m4LDeX0gIa%Dy+LRxqu*{vlfpjM~z9 -zUW2FFO&fY0ByKj|EFHHI6|Y9xVtjmtqbXiWy+y{UZCCMZm?LdT*cZq?GvLFpnC-`u -zaq|@FR*!g_cU`jb$lE37V-n=HEKQ%*8%D{>A{pNVYlW=s6QNjDvcO6r;O%jbQy%8I -zB~Y+!i>fp!3SaeNj04#xEsm$O>B@6ku)3A~P$^kXWqK^igMWHogR~MCY*kD5Ljlj8 -zM9oMe20*Ra=A2ovE=<$Bzimv^LrOSgZ{t2W9AIf}{0lLVre|SkRpx@O1+f%Z1J$4y -zLCOBjqqUeOK8Q+%4%m$3+mnPWqKf@9vu|@i-;%w9hnLG>I;G;ievtKm!-HoOri-cg_poVigF(%Q}ux*ZAHOG9Hi-rvM>Ri!SglLL&qhQFj5PvZnc#b~3F2OM%Bkc^G3XP)iT -za_arC$?`quS>@QivEuS}=*}_2hyIwZJbrk~%cEa^vbv~>x8uRfAb9inST(#l?GT?& -zeU+vM4EO2Cy(mG-)0e>atUY1;q2y%{bv&edSmgXuz;Ta|AGhz7WLjYewAIf+ -zBnQ?9E2e)e1I4c^CPq+QCl6!kTP6qX3SHF`5ZgrE_DltaBrRs8TK*{CQ91%%Kg=`0 -zP^m{yvQb7X<1r9c^IVD+gV!VvAiq)fotLq8;{i%c^#iLS!yiA>u?NemE2Yv@Te; -z$G%DZY%V10s3IGaDIej3+QXTVp~m&pomt}+dysniF=2}yjBa&GPySP&rP{7jMaCvU -z(KXOV`-~B~sXC5sR1|@}SAY(BC?P)5o=9~q7} -zQE*(f!bJNqxDp^Ko?VIi)x*mJpLYAzZub%rULKwT!g{w^JJD(%2wHo+^p=dX?c-^h -z&SU3i**#9SKIiJl=xPf~P@RcKv8~6LX@*q_QyRw0AUUlC38of%$+e#< -z?U5ztd^!VD8@mG*A7~&ZDavGHk26JplL^Dlf@5KF!7v(3|}fmATw7Ttfs)c -zv1tOk3A{+8=NNk)mW^fz#vqKy)EEzC?3IUrT(SlpaK(5VVVRPS&sFddLaDKqPTXM+ -z$le62V4-1bN}JRjhOCWR%BZiVuE9)G5d$Lg6CaGU7g|&u@wEB3N|<=v*L(4Ne09MP0V$ -zYTq-G&nfX?HfZdZ&qQc2I`#l>CW0T2u(7=Lb -z(VSd0?a?Va_4$b7GWM@-L;-U!FVShu^<0B$Ny(OQAhdZq>aCbY>zKfAOxV167Tlz& -z^uAexG46bFJ<1Bt9!ga)E(7gyat++X>b)%n(fTEr7dZoz2E3_T|cs9~vmcQ*Rauy2-qbvT?0CKomb -z5bE)iyjtq(Ck(MF5()Z*ci#Ycs4b_FwPsTmrHQ>E(SfcEz6Cn0N$_(dH<33OXKSdW -zWIOUegJrS6K%bn6H?SI3I0j_Jp2xEVz$8b!aye*Md+6YZ*HmAEDqF$;G@QRd-hI+L-ok78(7=gIO%R?yp2ZOk)4Z)J -z;LsJD?|AXL*>^FlSn(9xhbwVUf~hUoXt)vE_IUIEpT^b5-2yakjyu+Lz$bAJziseB<>1vi0of?}@)e~FT0?VJ6!$Sw -z45J@Go(E=x!VQ1P8MrVS+>V|zblp3bGP*bMo}SA7&0FC+T=$i#Mr>3zH1HzY)~lR= -zw_V}42S7|-V)#pojMLa=O?jNA+;ig&G=VbTH-7xT#pyns+Or=hZ)xG%^DXa_vq*B* -zoNr|Y63afzR5!WGyj9~=fd1YbveawWZ*|_Z%zXFO)$brZya_M0_3_X*>cE_adORH^ -zdsKq_sOggoBvEJ!cf1Do5OdrpQg3*_P|LDHr@^?8hjWUD%-G<8B$#!;8H3T*r>c^A -zC(x6mtYVQLnN_R@WrAbCAy7K^Tcmv^lDA`-O}@GNd<1Fp!27$;PcVBy=^Fa=N+VXz`J6X?zbBi3?Ipj5WF_2gEI9uJMeNU$3`eT~b&Ssb_lpa;H-GLf^pz&;mBAsr6?WMITHZ_r~Q0cOv% -z6`-r3z%}IIoRf|Z# -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 -zNV>z`5ep~UkZmf%BXsoB&IU=oXrh)XY -zqFdTrff+~>J2C`DdzgN4%RL4pY#J -zLUx=ww3uhD$)0OPWGJZvU#K7O$hTVa~{*?rT&eperi -zeIl7H$22){(L~nu9m&|D?#_~VgCcl852Al4cIX1nhao|V_~Ltu&~`IO5)|V^ypjEy -zXwf~D#4o9|)8detxCU+BQAFe*M~}n`>FrrOwt5P5kjdJ>fyJ5lRgo`U@ya!kRbCOz -z0a#0RC$(>oEFYp5!p1CvO3~~>mYF!tB+JU_cP?Z=ROFMqkn1S;FFX^zk4Q&mTI$F$ -z87--!AE$N;y>Ae!uxs6*)?w6{b&Za;?LL;J5gWQA^(5$|yD -z!1V;EnYaDqqs_J}jUH*}8y?+WA4ikBZXqp}_j*q|`sAotU^XVC8hsu#DASQ#QDQ3( -zw80u=ihe#91o~Tt`48_t6k2du+{MP8&hNd4<- -zWok>(ir3RX$_tJ3+V23;z6U^)3ackh1#WQ)Swj~@a8o6Q=)Zv`ntF&GHZH@8hkf0wNtm(w-9c+qa@+eW-hZ_jz0RxvC? -z*Dn1i+OE+j*_k@+tyoI7!3e_3AU~N5ud<#^Bd&7@byysLfr$}ck!Q)uX}12F46~RA -z)flWPlOMFX?H~Hr0MDd28V8}YX_DK(MiQ6xlu*#Ja9$8+$N4SqB(%xq=FbRfCJ8F8 -zZ!0S#!+vOr_u|GO;7~O*R+3^C_64;M#fKi$uHo;ZAH|A|>|c_R?N?0%zh7>7=S1@r -zYu}hXth3kz(IVbrF>g>|A5cHoiTxSLoJipCt=vp0PEqa%yy`B#rC{*I6qQW#R+BNr -z3-A6^YKq;)?|hD-2{?cHXoAD(ri{>~&#!1p?!BTl44^VzkhZG{S7LlBUa40y`@gkr -zZ2Xi@q2Sncf7xy?^p9y|f>_alPRN0IEooP31IjZ~5K!5ap6)9=_e6$`lf;d;?VOPn -zBG#NeobKYJPM&(WrJ1pex|C)UHr6zud -zLPGS21NL+1F0|A~uWh*o#+#7L!=$Vq+m3-O7Dl;$Q)8(Z_=1X*ID?cPK`W`uX);cP -zt`HR?gH9n$Wgod7Mg6S4U6w#?69s<$D1} -z<`mS}pT?C#3Q{0AL{17tyUe>?;6h;cM0FM4#k|GE@F4%zh5$i8s2B+P64jrN_8b}x -zlB$$9d~bSO223_Y4bz-W(p6nMN$)NdN#myE2wC*FD944%WmF28$@CzRr-*Ft$sp4; -z)u>HxNjqne7!fH9o9t*t^Nn7o{v7G9}5=-E{Qc -zO#SNR7ZY`$#XIcc+@N)H1LKL?p+`ijbMRHj-5F}UI(>!?Fa!}EB71@CVHZi5I^`eh -zjI^efXAG?$qFJ;yaP1~}*P?3)=f`Ds25@ilxC*Y1H@+@PMi>eGa9t335^2YS24nQ2 -zS)*MeC&U%IC-cbDe=guy?!l`@+8tS>h7#56>PkwyJ%p}83bfYC0j@Nozsw99$);P# -zx-E3)jtD`%_{izlIj@cM9{NQbn_h_PnZ#1Ic0yzr6NfO_$#06$0^8Y}MY-gJ<}rr> -zu&f*e-_8roY_lAJf41afA}e4^3@6ymIZn)e=2F6Gg6jA@qMi3uPY2JF{}OQCtsfE` -zik**#SfgZR=sPv9rCl_i*I!#nOUvWp&wU_sYU5nFHvH*-da@?}g0C|CEwsMSiZESj -zg?7nvTO=i&MzHA6Zrh@j<|(JmZfP$CQ=1CXox -z_`a?S6`=%LpH)JK2!NXgj|OPH5_1)5AcJ+MBq60?Q878;*(WuT3mZ^N1Gg#FgbYD7 -zC6Z3x3yLM#))D!n50Y<6i@Nw$344+F1MLVG!qQ-$2zuy?Y$40V2ZUSZlSV1nR`!;d -zZn$A4m-#DhjUa4Bb{{I8qIXuU@_7(rGLxl;!#v>i0w^#DHijT{f#psAF@U9*g_i?G -zmLjHPQ?#dV=M|AJoP8h&q(9V$3T#FIrYkWzGY+*bplKjC-aA}&RH%^OezG9efu{Y+ -z@_%$@dkx}+7GNF^Gp>(HKVgt6y&@a|Y=(wlEWPZrB=+lfO9vd$p=b?-e(N`xu1NnW -z@nJ!S`JC(2C00t27vwA4ASo|)7QgnWB?Nch3&0-v(Lox(xd7YXI-eJ>Q(xR1^cfE; -z{X)-yUxBuslTtnSw>z{JD3EtT!Gi~^S1Wsad^Te91)uQ49OurQy=9Js!cuL%1Mc4K -zT6-u7P=QK61VB&=C_E$kuWZmn`h@&0Ks*?&5y^vP!U`$G+Hco&wIoC;?Q`0F;!101 -zRTMunS&bl3sWPH37F2z5V)1)mBhh6}kr?en0>Il1EJD-Y6y+I7;em*sn+M?}x$odAzlAPQ0g_Y?bS^^Z3IfGw -zWl1X~kV+8bDhSxwq}x5XISoB=X|V#ZVxe8|i64=ODYte<2+6I;g^J`Pn!M{m -z3>gbj=nnu@65qO1s4jrFYvLhG&8ic@A0kY@AwWNMo{)sU<7xXLCajz~g`r5a)S -zxp_(H&pWisDCAVd=-L2{D?YV?`j84)CFqW1NZ6InOGvx2e4I;dS26agr%PNG1FS@n -z61^3#QgG;OQ)nKl1KF*p9@dKk)KGBz#5z{k5P~)U242d#&2A{@^MR{r!%mYwDe;|$ -zBFzuG=DA3ZmtAO3__{OHBt2tbu**9Lwk2IYCmQ1os!D~;9Yl^G68M%X|7z|Ppq<+C -zh~;k)=?}nXQ9$C8srrSq)$jkIzLP|Lr(cgrzklVsm+bx^Xo#YQHi($g>L@_;E_nDu -z7)N9JVx5+h)De^T0VfEmOTj0@u_g$!RZVyd07yQ0HCg%5wHgY5DXLKU=q=Gg;1rV( -z+C^jKoPa=Re{rqeoe~nVz6>Mm5tPjO`L&c)1h>sILD&Bf@GtQnvvJt -zHR6Pt9?u+y-WB!vmb6H3e=f~%G|I3RnRi!OE|Soerm2cc(+Fl=+GRw2na|A&4y}}% -z0#{tPiXsw=8&1Q?twg1TF5UD+(|XSx@C0v@36Ocv49l-8Y7APOtb(+!N#`ClD`zMl7>buD2tnBbDSsRO|%dk -z!9Sx!%9SSxC_G7{on8*3#W8OM@=E7i@jI6&&A8F23DUob(L!RT(X@}O^LMWdnoo2 -zUH~(gg}>(@i)$o->xSe7aauZgsD5fV!;HWJM>ya*?7ZMk2WZZSoF@32#D!~I6V32_ -zfQS9_S<*5*Y{gf)&DgAeEYNcSKT-p70^4^ -z>bzDn=hCP#%0Vw02VIugj3yl-0sH}~%3GBn8d(wZi?6YhF-Yu|6k57~`^tj05EBt? -z81zasPi1Ax2H9fwTW#@}syV!jo9(ozLAOq@eHBX5C64VwBuq3T1B5D#+ -zse;f8q5)Q^5wTd6R=O@ovq4wTVUnKi?BRP0>=~ji;wfYU7tTA?z~BIwnS9d(;BfnR -z_{;Vrl>Fm1I2=S4g^h_eAy!UoR21v=GRU%4?{&3MZpCINa#UKp@HT3t%I3sf -z_nfX&FU_=L?_xvCKrytLZvOt!{`l+XFW!T&2?wZW#9GCIX}X_(0my>y*9^lZY9Q(M -zANB3qufM+iWQsl(eKh=9ZTIWvKlCu>6QmCO6h9~kL+|Yr*~6#Xed@PhN;hzQTdfhc -zTZ0~X5$Ua?4GctrJ5q&cu0P6omVrq}H!Nl7h^4UgN%o|s-K4tvc$X-CL+#B9bK=B> -z2t>5=Oq=oHDAJ~a>J6dah3ihE0Oe+MQ(U9=8q)dxkG#USX9}|78W9m9sm=Cop_1Tz -zfQ~k)@yHz#KX4V<#?{!zRO-RGk^SKfYJWM)#HZgwY1nOrK*hG&FQ^ei-R{&u=xo~P -z%gLfNXzXz5s7tGw+%+JxWn(V>*SfWo{3sEAuf|G--eUw03F|S5UY=z6q0+$m_`VcgqnNa^()4G_@ -z7Y=sQW&+SLnTkl=<7*st87XSY<===sS=U}(Nt;lQVGt1;KoRRvmP8l1E}f0U9&1Do -zf`@B5itGjO*jul!2}b|BD+oI3?}~A$VT(8%bm#y3|B(JjHuy!igQB&gI?Zq}MD=p< -z&4Fyk_MLYLtM~Ulq%ZjdS4&-_Hpbrq?Qorsr}a)^AcLB#3!?~0gey9>fD~Kq8 -z$1M}$A|O&U^dd6ydP&G+-Qyhd-KGuyb>Yx6mw>O11R+TbUqJ=L&ry06p)!M*cmrew7Glz(y=~U3D<4rCS)~bZ%VK=Ujt``W?59xj?CcQTB2SutP(94Fn1h?xLa0Q` -zHG6C5QG}l^aDdho>4NMGC(LnB;X2)GIkROTH9@4dP%lYnAdW{lDhP6-=S^1FS;)_Z -zNrZ)bKB$OtX~^Js+<`_L;3d_QLi;h-s!QTedFfddD*s?q@ZY0Yfp6;(A;1-p+tJ$m -z@Ic_YPibY3suU>Jm*oL0uIQs76?8;2mn5UON9>64^@Z%UQw~eI@lDoZYbEVLBmkoy -zPbul^DtmuREaZ(=ZzI_Zs!dX2Hs`W*ZQ9L|J -z8yL>y*tB2?^0ebkuj|ZSItZv=g$a~`ylfp7bH>iiPu$~vG9?XE=oT}p>3 -zji|~-t>98}XSba*YqSBlog^aiO9;|{8u8#DE%46LP(2pB%z{>DXpBWX$Nh3a>&1t8 -z+c<(!hn|NlOeknf3*e8n&}z77Kuu6dV)_xy0ejAgwFof2FpB1aSat3B-nASAsnsXF -zGI0=|JB0BZqJ_(zk$;tFr<&UN)(XSyxf-*+qAO5oUXYUGHAUK6=!m-r11-SU(cqL) -zjGCuw5K*^_*CPXpct&U4V1#u|3__8z=qHhdMMQ)K&-~Gds!6=wLRjo_07I)uiw&;}L~ref779J@^qNw9S7uqHdD -zv794&QK9Um04wyB^1tn*fY2@H}9lw3DOLY8; -z|5T{4p}JchnrJB*sS2WY -z53zVs?8_Hrx>Uo=gp_LJU-#WT-|VOdZ{72C5D-+m#end7Y^-1O4)sFx+QSz6jd -zSA=;CTf8C#lG-Cp-1PIFJtV--w68?)gihU1bVJgn-Gl*=`pw05Z09aUCX(gD0pU6w -zZd|9fkM~iQ&fREcE`Fl3OaVkI2ycE)a`on7M;i+xI%?7dnyP{lU*!E-)C@F3enx35 -z@eePs+SQ5`b7)Izsn{3z)NKJx7%*ddyi?D$UEm-(M?+klgq79-Sd848g!c0TJgj$lN -zEQ6dEQrK(NAxT0>y5ij9TX)s8!=U?VZ3VHV!5KP!#Af4skb%LWmU=rE;X&B7-j>-C -zSG?zGH$njJ7La?RbhhlYJJz7*Nm7<^8`Mh(_C1n9rjH!NvCx5%$QwWDP~*^QKJz-} -z@jRxqwSq#A8k@n+LQy=n-2o7CKDFVUb*lcfT@=2Wvs`c*zkmJvZ_6iz=6kFE`s>HP -zT*1z#^>i)U02Fwrh{rgY#=eNHEC31d%`SbhV-@kP~ekrCj&ENEc?mpQxfBhZd -zYTJER{syA*-SPK7zkdAH{{7F5cw+wfSF5i1^$)+&zyGwq)Q|5iQ&c0|c1D&$Gpe6j -zyXkEe6vxq024ZekK&Bkd|4D4s&9n?)GkpJqG62{x_GvQ92V4q1AI8g~7Fni48{nT5 -zZy7z*<3k49kYp2SXvj~f9tC3e$P3}uNTv@){^|-!gJ+e@<*RPVv%fQ>J#rQv{x-<<$AIR@@|Z{W!%@otzw$6jnRt> -z&c+|dVt8@r@5H&uu;MMDE8?5)p<40x>b~LgWf+kfpmlH#2qFoa1vRLNlQ)7s`bkDu -z8cnwPzI95kaf(b0>1Ap&NbZ(@kzRo8zKF#{Bwe^sj&a{>c;?HDzyegxaX|&I^O~NSN%4+r*zm5emaKO6V -zjN7p&y|_(t+LIZNjX2e9>X@nd%G=vPVW!@N_SK}u@qU@se9V(MR5M3DpE6F3VNXU9 -zXpU;Nlq6^f1mkdj1J^sM(`fKsX1icDtj-{eDB^&`{6<6QC2Tn3lMt>BereG{1&Rqy -zaC*YW;ci^N8&a!zX*e>I0jBRIh3ub3?c%BSr7GyEc-jP)Km@Ln7u3+(GH2D#BI^m2 -zAV?p|BrDi5#DN?s-nA43zaEHlx?K86Tv{BaWS)hboq?LE2W*`-8x+juuB)t4XJJs! -zBs*;*CTPZ(*Ek0z1rl-92`9#34wsM^i|%2nd~9-3pItbs@lr0>3lgFq4S|0x;o+$z -zsvn?r0;nU3H(0m5jNLf-so^y@!^^PH(1}PRGp8CI-I{ltt(gzq^PRk+f5~ -zQM4Pk8w?4`R*Gv{2k0&3A0#AVNAsw+M&z2r_gke#%8{g?}@E*`SBUgtcvI$*> -za}3LFOp=S!nYZceNe33!_Qi^?9;%blAorksQ+DQL-a%8Y;oc6LPkjD+WnK6_@)z_i -zzBgeuS(1tO;{c{GXav#HWQ^2QeI#w*ECNsr$!=u1UYYX3iHA3;IR*6aUfhxtYMKms -zRpINZRGM#ZaKu${s;~+26Jo7i6;msxW^0o7&Dpz6D9Bgh8!8`Ms0+Yw7tH_aPJ>!_ -z+Jc&h!v~?51lpRxBPLsv?>1p0^*;KU%gmZU7OD0z>ou?2eTYHIqjg9QXWt2QZd4hH -zmO0O2dy-Zj^|Fk(5In1vMifp$qOKjzZ29QGEaP7K&@P+uObet?9*+tsc#YD>8^+2k -zC7a?Y9R|HejmP+{?FkUkvsbF -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 -zz(zgnH|Xfc+C9f@v`zf5EO -zVO=1_a|d*={COb8HIUr0_qM9lQMD|BNuQ4EIgCciv4)|MSN*s5H>O)BbzM -z^gnO;-}(E$rte9A-0J_hQw>%&;jvyT#uV*WF{;Ecudr!^*Csh;GqSd;&IwP!0DxeL -zgiKdd^cb}mVSk61mVwlNB}w_LNbJU=!lZ~mq%N|u1KHTpMG#_@xdKR$>xE?nVU{K*kkM#KrbAepZVZbM#XK2?Ci -zHvC3{XGW4WtV{$c%jJR-)EZVLDa1Z;)KzP_)LO_wI$qs05)YL#B6uoIC^N|+zC^W1 -zQ*kI|D~Mi59kLlpg^dJqjF$2EVIpbCv~{2TIZo&38MmiP -zImPXUt?TG|q-nP2)#_3zL!@C9uufM3Q!R_h3QHc_j{PaQsACONa|pwY_CrP~z0cMy -zt}$P`(DQ0?6Doy%DnQFGEDrfQO=yK9gI=KSmKxO|GgGOjw-)!$k&DShy{34SxbdtLEh*k3z3SYo -zlwL+g)9jUP)Kuc5+BAzg0&w;M -z<4L?pH3o^H2vX_k>tnFF7J_H;uxeWQ<~DNTL+mP3g|6>&-}7#&Dw?6BGN2>~(+FrY5`NN>K!OZGa2tlvj{SjCh*I -z5CVFbc>f}*8-#CPTkJ7-LiG*rZNBoj+2jG9yA -z(}I=;QG{j=1xR^&Je2+sfq0y>z%i~T})|-d$r}=thGsoGjaxdZ=?JA -z^ZVD%giVwxMT^B@Z;vI2__luROylg)<`l*|iL@X0aK|V0(;SA$o#V;Bnqr=r@!%j` -zl+HqX7s&wBCQ~CQ+4jjg(LRV5vM{6hpKXOk=UW=u-trd2I9v$gCridr9QVhh_*|p5 -zLpb?*vem&g?(4x<03pO8)7d#A!hkQCX{jf1i(E^-^c5)|&Y8CY!9BKu$6ruCNF5Z) -z0fL&#CO#l2uycM|P;+T#*6+lZ)!VlG7-lXRnf`8vXDF`c8 -z;?2tZ)c|Ad9`k}C17!KV9yP;yw+-~P%`-c4M=T9lul)4c_M|A}64pu3_7=FLJhZd> -z>LcGK{HVkH^<7ZX0-fu#Z^B<`(B@x1{;;9|Pal*%M5F6Ch?bg|nL9C&+VC5Q?j&1{ -zRb;rC8Yq^GVvy;#5py(9jwC3}Wx#x+60XM#d%jn(m#S8eAC|Ly%QeP9rS9v($c -zzsdKhavw<9KNTtn@xBcKyBUYFZWlG}GnU=VCDfl}AA2?P*e&X2>?FFC= -z=H?_C5N$^5L$RBesFQdn=m|YQ(zZ+fg_>L>t}ZRAY=|X{fU1B3>M@HKERpzBV_!1i -z>`KThek~zCl@j{BLgl@CJdq(K-w`FWkknQk48&4o#!J7PZr<}~`SC!c(G?ohJ&7>W -z6i#KcD-)uhX3>r6H|`DUDao%OwDsC9H~0ijHgrAvytfi -zil#!8Os_D2L#>Oj03P{W*`%6}@|q&5IpS=NWJVD+nTSN|2gMYLX|Y$YN8(ij?-x`e -zakW7$nco$_SgW^)fq>XA%;Vu*`MOSRzurjRd?~S{=1ip0(+ZR)Vd%o>&Yvg4BHahs -z-y?~&q^ssP4;F;fe4k78(RN)z+PM+~V{!W=uGz>k5Cdgj@Rom7R3!cti85ZIF~9(8 -zWZNf??WN^Fh5&7Y?;NmCg7_6ZVke16rpn`Iq&BNLnn66CWQHn-xK)`&ZAr8+q*o=W;R$6XQ0Lz?pI6s#<(Ik2%$ -zh^9Sw2V_0x(KM>#@6UFfQ?m#OQOIh>m#Cd{o5LxG@m8?$$QM6PPURxpb^QY;zcg(odFM -z**$`R*@xSc=B&3caw0*$BW>0=vHgy|{M%0epW_)hyqV8=N;Wbke}B%YhV$LrZTSA< -z8Fe|R#z3L`Og6P`4jnRCCTAyc8JT4BJ+^}ayy9p42i4=Ct^$6s-a4ouwSc8oJf;ve -z3dr&I<1A_~k~J-$uu$>@?&1MZ5Vw^*0Q0hteFTxl0 -zKn8v|(%ZOqrj3Gte#l+E8ByJZJetI%@R$Ido%sw3JvXGsYAhLMh#=$CS=2z2C800C -zJ#U=sbOxZ3HMW(r{n3$rD`*9VPU=L9sA2g?dfOM`O=x0eB*lOvDqoYmDpV#E_ll4! -zFF3z62^ZhmuRni&|Mjc;qx#Id^Ks2mOIr)xOjH0=?bs}0NFeTN9VXz|h;NK~hnJX? -zSd^pj*^&bG7&H|1swwVKJQx7Z#Bm=FpjXYJ7T2JP9g-S~HNpP;_n-35zv~~>H}LLt -zq`;GTa*8n|?vYC^ODAZ)9e_*>x!22Um!XgxWk1tEhCHxfSvU|yR6QQlxr-7um>3)T -zz-tgl^94COfQv_zGtYPfYoQ*yeJJhGgb6OG+u$8^Bdd7U<}8}4+fGX>YUp?~>wOz~ -zZ`q6<%-?MJ(6nB-jI?=KwmV1H=WJM -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 -zrC-_?6S^h{bMqC6p?q4SQkz$8;Kb@BYu% -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 -zHFJ^lSx-|Fo578@i9aK2BcDr -zP-x)`xX?Qv7trqQU>>wBDLFFjlX_2LQSvwd08%)z6>YL!hEo|Y_AX8>vlRnjUP?r$ -z%%%r=+azQ9K{H=!74P2v2e=F3B3c0ZG~x|V*qgTIiSg7Y@~To#YyZ87m9t6sSGFwC?boM^^HIMvpjL5WfXQtpKx+zIxMXN -z-g9_(SqUX_87y$N7zl4R;m4nUd(t}OElKVEgDkbHLCb7PmWP?_9Z#a-Wf_zfetnnr -zoh&=%t0tlD4Gtp37p4RgC4P}c1rzVH{}BdGJd7Vw%V?3QD!tbzE^dfxwQ$r)B7kz_ -z_BNT+?Swi@k_DT+e>vwF$#?FW(RTZ3O;}i5ceLH67+PhKaBtyuO(jP*0(Va -zKKMn6FHU4IGj<`hTNv=37F^)Cvt{g0pD -zzW?}ZVP@jBKwTx~@5XjRfXe+Hw8?TqcE!B%F!<2Bwi7?gujpQ#SqBUwgd9D -z`*YvzF35}7%AWZ?K|Q1}Fw%xVoJi_$p#iHF*s3sj;F=M@TC|&VjYk#${3z*0%3n}q -z{(;Uj1(@@kLYDzqb}KtU-|>4$dwhtvphFBl|N15fIr<}UZcW|KDpm)xdk|q1pjsXi -z2elS{8PYPkcIuVL+n>W^8-a68?Gz4S;)RN4(V8gk>Tqm9Y`7I9;(7rw{PNaB^j8g~ -zkDqJ~G(?Llya$Lt;us(%G*A`(MBIS(0*u@!9J@p$wOX`n1x|OOyd{WaN!Hq{IARkD -zC7|vavK9q}2Ecq5O@xgNN}fj`NwR{>lEP^p)L6aDs(Y7C6r)xTjd5@(#wcv^G?b)_ -zK#`dNwk6^8q5cRn8fVR9uj)x8kub+2oE1tYrZ42kWeM7WqE}gc9PA3Y$X1O#S0B?N$ZwQ*XBi#3LGTw-!6s34jD*R -zaQ{^`W9~VybSCp#{m>z?i4>V=jW?VH~PC7p+fP -zgSDDz2J9&hW-XvV3dF<2slf8aWvUsKq2jW9gS}KN`jxCCW}(wyGrs+51sk -zwhJxSs{|YeBFu#Z3XcX&E#M%Md~mb_&Imr=Mm9VBW?o=H)Y322&gB^|Y5MA=JS+*B -z;x-Gf@Qeb*W{}WI;w#$6h -zDoaU}-kHzQY}07VoSVq6b$YXZ%23^Az!_#m)2#%IC()KOmiZx6&aflvdHF+K196g! -zmXhdj{8pj+xA^BSg+Jx;*3aCfr^Dlaz8x*KgXf-@e;)r;L*TblIwIk2vVBVZ)nc|q_w0P&H7c~O6t1Mhs*kCFh*0*I#R@_kn5 -zO?x3@*44$+NhV++@gdqX#}aucA4xzO19B4>WP+1CPl7H9^!6=Xl?Y4nM0InreXgXp(FR#FD~F}r&G -zpymsnlZO}3BFkCh?`huo0an?B+Ej0LQ(E#OEU<|3{@GYREC%^}ReP0*I=+w`PE~IZSF$oX`YfqJ?C&d|f1; -z_CU>IHJSEa4r1VdQr;DS@WA0{l#NaXu+RnP%*-c%V@L5SwSGpSZ)ZIrWPKV9@he$e -zsP(>TlFTKpkohQk-;jrbbbBYBk`o;`IRP``7lCj4Q@!L~djUz}CZBcD5KE}x($B*- -zU$;axc=Ax|BnkmV0@zIU#ZN)~OVR6PF>;T*ZQ@0u92x9&Bz9H!oD|-INc6&qJjiyA -zoSF4*|N5={_iycgxV@95{RX^d;wwz0QTJk9X&ep`0P7~|G5FZ7>%tYpJd)z~O`Ui8 -zxKEun^RF2R+2X*QD+=kt1?Wa~~v -zEw*q$QIo_hrC5$E@g$f~8U9{BsQ9dfGFw(oK=h=kax&u1vk0Z2Mx*TbYEjK-&iVsM{0~( -z8s;KL=73Ir<|ugat9QCH>lWJn7Tn?cKX*N|@bf#T;)I_+MMJgS5!aqX_{nLl0pT-3 -z)g+k^5OF0z=mSdDz5FO{H5sx(N+Y6%iI#9=E`S$mRW?L_-Sb6VkaXVr|^Y#ZN#EBxL1}-zN9+ey37m=mA*J8+D -z|NiwIzM$WVSX`HVqP=5R1Wq`yyWsn;1#$WBc@52sW0)vH+~H?FfS9-dJF%wwi2AFc -z34oSU>G8}U&H<@K8W;i&dJ#?(n#B(L?8QefB`?0oI*1!ZAsney8RP}b$<#z6N(zT1 -z4Ol(!aRdB`EzY7MOn@Y+WQVt_QS*`p3Cq5v{~-;FF07!t@{*Jb$ehC&>De`6KL6{@Jore0V=0S+KHyX7# -z@d@<8M!a#^PvV(w<1GB3HHzH=ND_6ugcp!{+(}%H-D5$UnkfTM-)BMT!8A$-*ZCF2 -zuZnJl@ocivWJkn~f9cgk>JHf=7t;@#l$}?88FfpwKmwaaPmQEbsoM|?K(66&GGXdw -zdX6o7;7iIz+QMdz$GYrj1WzrX_CrVCK3iy$yEwi96k3H!Sb$SyBK)pM3lr-YU}=c= -zH4n=BfZ=Xq&%EoZUTtwm9%_t#z~NyMHvxvkT_so2$s8%{{3FUX7aq-S=%*4E-|tMC -zvMPPQ=G0F8ed(+I%*c_w~&gVFDJCkKHzf9m6Ld~51u#5%~ -z1|9pjbmvxTpu^{}0{}k5KC-|L!;}}LM*o_a6iCsO0V`oxdPQ=16p!2oofdA}zD1Q* -z{t$5R{stoR2BfG1JyLSh)|Ad+AvZYkwqho2X0;2o*OwR2+!Gaveref&pavVW5b% -zdB?74aY=s;p%y-A1(h`-T9{SxjmwNg8Vd=O|_L?>fb>HMe?jnb3|eEI%2&*_`= -zkD&B4bA5%!YH1fn(t}^}B(Y17=1qhyw66w|sdsF2wT -zYnAbCi1#9NR$SzA$y^8+MH*G%N)*&CQ#2x2HUPuZMOIO9ek;yV!t(9gC&er*WLTdD -znK7K)78amVSX5IJ>xhVU3JC7y5m~f4T)!6vBM7utXcr`sPm05#i0Ug0+g#(1qI7DZ -zuSOGz%|fKRcqB?su+0p>I8@Avmm~M%0trx*{)yqibY03T& -zjZg*#zNhvHWO+nIifdl-_iLKs>1k>3T8hXq%3eJHkwJBEok*}95D|i30nz7B6KuJQ -z*e{O$y7+EqQx8i3f?~NI8Ipc98NrSCX#+p=W*>lYM3wIy8+dx&=yB~us+pPx5$v@ogX`R61LP -zrov@ov(dER2d1wS%g@a?4#dJ$8))``b#fDFE1~cPJ(<5e -zXVr>Z?NSdV{e+ls8Fya8r6*}?5lACR^pDqInZU?-4;SBB=g5fJhrre20wy?cC9Oab -zqN4iUw~5KPL>!vWjzF_GhHHYtNM5@JF6lIMg#%lNgp3Yi9KuP7z(d5e;(p>31G)Cr -zsF&)Z;4vh606ghvGKCk2$cqcQp&QF*C4&PX-&sZsuhe{bje+7}9oi84(W--3zEZI9it2dvA{^8OrjeaSW%aby7%K7=$Sb4GzV%^jAx3=EG7pAYf-? -zCd(>Zp;kQsV*aG<4 -zeYP96#Z0BqX6JF;|78Ex4qVrh!SVSlBb?_=+yv;xNoHb)gS2)#m7JM(9bG_dRaF=-0)T38QimVP -z1$xX&+0+!-LmZBrNP)Q>;NcaTq&S-|yjJ3-WaujvH!tF3)6S{QKs%`z`;L!*5$H1U -znKCuYNIK?cJ{HvvoFK5Mf#l&`=nKu^+1#^eTDV>f-->o2ZG|QZ7s;aJ5j(Y(Bo1^@ -z;AC;?Jer!(QOZIWNXPPP!QRqp8*x -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 -zq{<|IvXRjpPn)bpzsn1U`8X}t -zD8}52y{z-})}dkcoDG7m!u)owvSLM@^?1`LcCZnxr|k~6K^C;}ysahRAi;&#$orrs -zcZH?HzC+Matp@$T_r_Hac^9r1?NkocLRZD?3P>Y3)4f;#xx_K3@22otfU?Oq12+4y -zT$$wJqIAj0peFr00O{3RYkwi{97#GNUIe{Gd?=Zl$m0>{4n!mVtQ+x@s%00{1B;Rf -zA9{=Wv&55SF46DTybE0mDh=pJ9K#73eW#2G_y8ZG_)ZbTfkZwWm-a~$C624BM&+f* -zPiiL=ktc=W5Hz5W)Blt#7E5~-R5$vX)q6v5hsZjp)TI{62y=rRRwpy@(M_8}+pDaD -zk+no7Gt@@8z)-&KUZT|aAzPz}s;OruzhrOx_tB!I`-MpC -z@8ae(AuVd`1)#i%-KOCQ4+jcZC`lzo0mt6yZiib$?vU?iC+nP)HT9`dNG_beuehICCOFa_aQ-#r)-ZOm3Zh5?rVBzAZ`jj*yOy?~6)SHDc<~QpQ6HieP$^e$Ju(9S -z(^jTwMFWu1j`W7`AVrjoLr&sQ(;0=XWKe7*cJ2&a$3(#MxfTf=^cf$)3HGu?absvF -zr1HUE^dQ1Ljk7>G1g?fYb+J~>u7^TFY)NPA7B(BD$a2YkMMrcpu~ -zFiCKv6p4Gxv~eYmm@PCdRM27>4m1hWE4}JaJ;aHx))mbtLJ%W^zTQ2l=G6T7_We)s -zBaKipobjmA7kN@deY8e$Cx*~_RCt(`SdJcW#dfZF=P1?y6TJotY;w&(29QK5)(PSj -z0Ma1c;1n;5K`}VjgOXn3sU>?`)EQB8TJW)@3A-po2t+^UYRKJup${f^%1%<2YSbh# -zN%|kWRJQVVs4_U$-(OSJn%_E8#@RbU=tW0}td5%Mx^0Kzf6ux2bd@UjkxJy8ddhtg -zdDo(((Xm}OA- -z5~`m=R+JO42&(d8R*?AH2E=O%8cDtlwe{dwZGcfH`vT&BcKf)0Jf;0@%7c$@YF-{X -zC*7DV9w5$$QQm$#L#$zR#URyg`Hl9QXZ=m3aTd`lM0EL&=B*ZNhzX*BZfG(^W!T!W -znYpgGvkl8*-Zxr|dbUm~b{lbJy3Z~m4I})=!(N2m*jZ6M@!k4tIWib*j+`hSyPO^bbJJq8_&MKn-N7}G?7oiux=uC|Ph-o8OJy6tYytdR)#^_qj!5v3m6Cx6P_dr~vHqF+pz;OkXhz@I~&L#^$k1#QDRuIt*UK}andaFkYvn;JD$KR(K* -zi9sYacSndr;oznSmwy%`pM+-=hXgHI(lC06tz-df7a^qw!Tsze5l!PXdi7d*S{eLt -z(>V=A>1E;Lljyp2C(&{Y>%ADR+SW}t0TLh#dlKOT?VlAv7A#`iwyEhXc3ByOJI>9V -zR@$>Xh_gMqzND4YxuZvhbIvlWKY9SC<$5yhB)LCZ#15WjWSY}OrhP`7?#460#?XR@ -zDiorLLa%QiGYtooP$+4W>R6Em?p0f>l+3(}kusSR{Q$+5coKtifc_&zZ4VPqUkI+3 -zrYdo1C;*FaL=!D^(~x_sf_RgVU;nL*g0kNTW#o1;2xI3ARZxHiNVW!)IO%-}BoUfh -zB@BhEu8c|qV*Q4qgBEyDs8!x7+0va0`^{+R4(6}F{-}QLn~-i0;7Ga%LexEk{>P9B -zM}UDORrJLKLrjTuAC_OSMmk+Ng<^q??C??z_X|a%7gW0Q*{aRDB#E>IP)7C6jwD|HMP_m>ODSILswVM2 -zdrX??S@-5I-nQ3)v>?^`Wa2l~QRS;4_#0K5%PxeKiV!aN6q0!3(3{ky;p`JHWZ;5{ -zHv)7u8Es}x&MaBdt?~_G=LE`9wZPj%de9GXPXL -zf*@|F&q!=7-J`I@dgv}HC&cYo{g~PpsrWoP`@?6mcb-g`leLh2S{vdMhGVAVp38VH -z$8ukD7-DgoC|w?pJaC+HJk9FQt?{kic!iwvk`C)8y-F|dNowVJeeql-hTx7b<>Q(6 -zmbdXs?WGSyVv09rvW`vM^riGmAY7#H|JKwEh7e8P=U+aMpuG^GNV`^K_rZHCkg15; -zknvn1YrjMy9YnRNxQU0a1`03S>P%k%C{cBFu|3d}^8XB?Ll@~?z*=IfkBHMw29Lh? -z4b63AflrF!Udz9|X9Si~+(;$ATmRT+8?{VDpF$Pqx8Kdwl2!YLQfZt77K9|aK!_)RGDE6%ZrItOUP -zb0bHY45VgZ^qr(oLH>Sf^MwrB+Y3s@19BY%`dNZ2-2$qq5hO@`Qp}|557c)yv=!T} -zRSPL2Aa1 -z3Keyb-Hb4Bo}AYG)wh4TKlmDYzb{!it5RsmdoKiMCBpwm+m;M0vZo%!E~y(Hz=c+s -z6KkjqJJ2{)t(GLnI7LMY?L;$qYpAvOdpn$8vI-vJk6;st_oelgVM%|MS0yBDS!oZG -zrmItRAL=NI*(7c3I=kFEUKM)k#$z;as|q~oq|1_*h3n@f99ijv^iGQ;TSP%T`be=K -zEUK~#>P#jA#_9gZ8lv~X;2|B~$%(E-WZU0?v@f!Q5h8d45E|YUCIqe2C9-{K_ay2K -zg~6Y+zMG!}cYY(J0uHZ3EJi3R{@Zq|TxD3GDy^S^}suR7jphHPe%K3Sl34@Ml^0;m&dGbYDxe0{oA+iJT`G7o|562 -zl@}S^oJv2_u`XP3Q68xha#VupTw&iZ%4_`c^T#xsq(zG7kl;3-<7j@P4GHtg;dD(T -zW`j<1t@KDLnnTQID`u+pHQ?jF(MFLGN2D;Zu9wX5)!Dk%Kf9UcN?_qrlSIcXUhSYY -z>Tt~X&hrGtaD-Cox}-PJTuXE4lH<0FtPk|2jBz>2dcIa3%i-JpHJdN`&;2%}b0J9k@EYvSKCZMQ3A>)Jv=i`w%^_f8hzKEvs!c-AzNl9Y464y)(c$%pEU`h3s$CWw -z6p+oBip?Zr#Wz=fL2F6}7TkL5ORtGX-j_R@c -z^YYccIuY`cfS5t+K8V>5IIq=skh+r)K^^U&G;+5ldF?ci38w@JLd8_fIWfBtAu9kW -zJO!;RDFc%C7J@?*IbMi$R;Yh;iVI5buy}==nrKtBr~3DsprCF-3=9^XED5AWW=$qL -zglXxTjR})_@eEo=EDJJ78A&wF?Xo}%P-teml6}Ngmw61Rzbi~ZcGZ2))iSEyU}(Ek -zNheD2T?z%X{I4Zsq)PKIQh?X`vwd-HCmum!*=RTlMf^S%0r9FFwD1xn3zxo{!(3*b -z==UBXyI;OHqPpcA-po}(d91%K68`Cq4RUc -zcZS%!8{SGaxWYr%1YqWc0_Prw!4RQB5?uz>kt<~@4SLH -zaOf-wNT$hZjq0q3bQDAk9de=MrkmiG)g7EISJ4R3gZQrz87qS10r`{!h+>*fTK8r| -zG`(OaPT`Pf3#dCMh!C6AB&-(6Ak1HYM4+r>%W#ZDTj=9rep8+hmteiQt`)Eizy1`z+Kv@*ZmnAGU)eY^21cf)o*%rIu>2mpiM$>g;tsA;;L& -zwR|GMTi@Y;$*m{pHsi5bBc57%S~uV|Oq&%p*k?n{svW$7gTEE^-ifRkViAV7tI+;p -zRe^?s6W{0O4`cq(`mqc@e~rz9oGV;B4S{zz?Szu{4zWXxM)oPCxdx#%V#ww$g>g&j -zXnNN5NDq#IJrXqj!hV^@17Mk*TjpbAYRp2D_GF==hLx5Sc<9A_ysZ`cctjAV*{K<3 -zXsoC#vS&gdL=sO3`)nhs3JF^JR0*%>1H?S_?)O)Dnrci4#s0&Zctn9(kFQB%ba_uQcbA~ccnwyc=ZA)C!aIlFH{Fn7#4&IoDnS$6z -zqAEAnb5uc3zlTvJI84lVM-Njwzj0~!5(HJFtfH<8niR^Pt}Bwm)_Mx!c`=^Pb2|X2 -z8tv@^7b68grU|JQit7!#9H^OUDU2jTjnku!VKtkas3lnmm;R>3#$IaBTZ`J_GSC&# -zKRpBl!t3Q~Ssscr()Xtz4Dt&H^6M>tI4ZDqbO>eXYM^@cGX1wc5~9UzndPRY#p40E -zCb<#OXdiBJ$QIk4DCcukI=MFkpttg*x=BfzCmr{@_$kuxc4+R;qLhe?@m94YCs=E* -zz(GL4$-<*ZDink8Ccv)urv~nad_ylJ0f176W`Ci#A%EXUU0SrcU?!k4pX-&l3(JkZ+3z<7AJ|H2}Qp`)b=aIm9 -zBIwG=m3lgPr*&NCP6rc6^l;88$XE;JfVb5Cs_klEhKe -zLbhFnL+KxVfKeiUkbhEujPNl@`4pS}8vm*+Bj_mIfwZpbN6 -z7kV9SlUPdNRHFL(6_7<1x0T-;p(5d&CrH{pDp_14Rm^k}C?5K!^mG9>y|0iq2fSmk -zEahQhqT+zUA=E70G$dnAT6hTU6AKu1c_XWx)P9LWUfQYaB$UZqNE6Ya)&nBe-U~62 -zN#jvoF{*ef4g3}(2{%y*fT#%JNYL4ZJbA;ZZZ&N99^ujmJPv9hI0G5Gl4F-9UBTD~ -zdo@8rlFS(VU9KpK1iWi;H6VGuDl8hmvL-DLX$s;p -zICbV3<>8+Q2-Jh(lR%WKKs7B+d-^MfSNyuO#~a#AZ=^t_N2guHgKTaL4p)#~{Vt*^ -zJBd<3R1n(y`vC`z7JWj7!Yp4Mu^*fhPlB$INa6{RFeuQ~A-vc=7Gdquj|lQq0EN55 -zHGCb)h>rec0Wv3E$oms+Ig( -zSSU0lqA8k~rmAZ_Y6zc)@3q7j5P0FNbU&0M$CHdWo;C!fUMHmD -ztF~@G&*RmM;;>@J3C6D4wt{_W8UI0IusJwb5AB3)HnXf*<(@@a>kS#D;$3MAQYm -z=BBy8Np2dAtu76ioWf?6jB2Ol9!vFqd{AN1PRkc(jhUuVJ=n(4HhwM5*{^0|HS2Jl -z&>Bwl@9A6rlf!mS0GQF;>S5uhicUIF-=(6OB1%tg2m1LyB7r1Z3{4Ps_Q9WXXHb<- -zSVk8a{&pR946GRL(`VAOnz!OZ`pE$k{PAOCed9oe7*{?kYUA@|B5b-J$^7Hb^6g(i -zFAHLiM7mQtlb*%v0@3b^EHXqLt7T#0fZRy2SMFNNN4hm$P}+VC`tsZDn1&y%FY2*Zol<9nrPr6P)FDC4$3vPekL=L -z*d#BR%Lb^N^AkjrQA|mc@XBhS(Z<$i-kXs+U!RdhQYTSEZf3QK-$ME0^C@b(r5~3o -z+D=?m4mWDOiyyi+kUgbD)h8fQqx71@M+Yq_;OYf2Rt|b2s#8lE@rso92hYzHFFL$y -z)!v)6ruO7|G+p@8>KGan%xcboCUPd*;Pv7!T=boMKn1$xfYJxz5vM~6LhgkbPm6{(V{UshOyvxX -z>+ciZ+>YnaxNdG8lNQEe%I)6r2xOE%Lb~z! -z28hu8hB7KiqdD#n;99si0g;KDvms9HPPOF_{T)=7TE4rT`f|#r^dab0Ns&#&s;L2v -zG-No!W+f{T4PGtZf -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 -zzzOCm3@vx%ujC{bHm_|np=U6*I`FC -zq7Sssf2a20|Ksc0mSn|s?E8F2Kg>jQR##>NbF3+ -ze%Mjlk|8nJvLs7O1)deBBt)OCL-Eo`m8?@zrR`D4Opko@=>fEd725jYbgmeOIs -z`{7yI#`OHOjZR;-NIj)QJZewIj$w*HF>y&Jji`kWZFI-Qi(vB&rIImOA&Ijvwa!~6 -zl8L1YJ*jjKXw09Iai*f~7BlCJ$mU`07nx9U(41-wY6pVeV+ukva}6E~I7FO}n14v? -z9AXb(xzHR7i$$*!GCkkwL?jWjKu_w88^JqvX+?5bRdw9xh_45fP<<8*`UEx*sqmuW -z>%}~tDJEkZRBt8(2E$D(`jj#1m?L~khB+b0kv%d5YFojbm_A__qDDKNqTmA+?hy}b -zuq_cMv#MG8TQipYom0(A^hwNy!Bjfl&1oA3o5B3*ctRZlmSPveHW8Ctr^TRGc7=|~ -z`DqIU-2voUtZD!RfvA$x!(OpMf)^O3pQM)?^y#KGzYV4kO(4{lWIF=d6HptFJYO&h -zHyOal;q~f%JFo&RN@CtiI);(!foV*a6F!kSV#VR^@I)DY091As?HIH$l*};X6-%y$ -zG_g75f;x-E=rF`)tG}6Yd*&7fhCLX2$(g2EodX-nCbr-%2>etf?{&u7v%E|6C=5=` -zQF3RYByRAyrovNT)g7!9uh6K;^h4Glaxv{Egzu;{#lqk*saw*?02>qfd+zI6*xQ)R -z?bOO;?&EUs?NnH?#2dBjqd^HVl~KiLxv89qfpDf1nt|XLlg*~wvWEFNu}zKSRH2JA|nwz_I);>zv87@p&E_Ey^7m6=?I*u@Rn$tp8b9N{oc -zb?#&v2~P9+#<3#Hl0^|KSt(frbu|*SQYR*vC=@bN1Mbral#P)kf(H#M$uuw$WmAn% -zUvVD6%r6C4euDH%Lp=8#7IHp;Fg7$Ob-DA7))EN+xk;BP~hOs{T8 -zBeUZT>$6zf-AJVZ1mONbbOB~;@_}^Q-v+RWXX)ao;7iA4GP0siqHUm!Wowd5Ml%k{ -zIUls9dFUtDI|n>Q-S0XMNi?|u(^}lx%C*t+GwK&rZ~t3syTx!m6X1{TlKs|XT`^!y -z1eus`m}A4Iie)m{c_t83HOt$cr8KZV#0VN_B*|1SgVvn#=6E)Xt>jB7jv)^5pvr_I -zsS{Z3N%=oBUtg09BQsZ*)P$Z#;V156(iTvZ$fZ%Y-Fa!iq>R%}w^C^ly=GB)1g2hl(q22i%TdWjFGeO5Q)qGG?L&e+$- -z_iKDfi_ME!*Ez$`z&HqVeGz>XihJ)}SK7?1cp{;1ESY4WlE4Vi;EMV$>>I_H)gPTH -z`rF%=Y=dPXME`3rW1*s7!(tT>)x}s^W1TJPu~fq?eh8OogD!+fC~{%P+jz_3F5!yV -zj`>`Pkwse7!497I%v>$XVr0o~;u>Zb%^Oq$B5`zuG_gRBaX@J$*aZ8Tf${C

lJz -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 -z=ByDNVXaeia^mciDHnp(o -zfvE18X-9TF-NPS_ynvZcv#H~8@IL*`T19S7_bh3ii^f_32 -zVS$I`70K70g$kt^m~0ifr>^|+4%zk0 -z&9(q9aD;Nc6^#^**=*f$L3|j@5%eln+K5sdofsscAbTFfrP~&eSUkY|t@Ba#zR52X4`t -zqAr!;uK4bQU;LRpqNj%3im`w+Dfckk7MI7}z<*}XCpRntfadXIVbM@CwdB}}5ZFJT -zZ24G~NA{$6*`iRl-4v^%?Zz~os-5)SWaXpL8@QKu~CKk$p;ay+!K|{iN4F!fWy@bfaBU@ti@zZ-Rr{B8L -zeMK9th{uG!F>62o(Sx^9jGJP<=Lx<|*ae)=)$9;MdUc!bA -zwEEwOd*;Y9LuQ$vFVWdRu7XC3-0dU$2TY)fKRE_lEZ|3LIxR?R^7mRH)x8?b6RQ)A -zAQx8n>>bE~<9F!7OTNo*QZL3X0bP`2N(_@NB(2bPQjTmhe8>(xt3zEGnl~WqP?2Jg -zJa;*h#({zQ)7X)$MbIXA&-)B(q0)L+U(pMp7ddL~gbxoRwAJNzBM^4gkWQH5! -z(lZq+ht3$Q@%Bn?gMHAE2KrO?7zIx1lmpn)6{CIQt1~3H=8mq2flE{`5k#2ONr8_L -zy#;ee&J0pw!;2tR@jA|cT65&!`-Ta`$c-G7bw=tj$e`Wyz?oNl>^P$afl&JN*}@=a -zMalX>A-;*osmZ$@8mX7H$U(Br(#J`d$b9A(m2-a~zclBhV{Q$K6s=vb5hs9jEmh5adI*M${<+% -z2K1znUJ&C{zSIZ3Ytt7>+Rg+n-tG9!N1d%Poa77x?v_+XGw}fScP#2FhDvH6f=Gob -zaOqL&Y(K&wcm{LokHfoZjDUIR4#FxhbYGBXp3^nEQe>EP;~nkd$m=pu(UKA4WQV(( -znm(YKLdkY~)s(dZx>Z`H;>hKL=4Ho8>5D~97JhjEdOdW($iEAHxyb9?1g7|M#y}`y -zAD?vQvW}b}3akL)3YCL6&+qlDo|y%E0n-Bg|*2K@>-5K9w#getlf)`6I_HX -zIAtS3V&-D90M!A{I>}91Ras9u@en?96Hn8@*BF@SbGR3VKJc+1FlY3xi3wsoYe-EM -zhLK-r|x?!|8?cBmp+Fj5Sy -zC9h7FVJK;}I?u?>BUHGeMc-EZYM&^CQ)25(OEW7Cwc@iG3MCS`d+*UR|aZ-shw; -zYfSJq9KQG((l2SZSYY<#{X84jl+b57?}MU8T_Vb|0OOimnb*D;F8N+0iowrj*v78^ -z_27?BdhG^C((~CUp;&>3`pFQfitR`>((M`k%kef8JmJ{J+0Jr-b&s -z@fRJ>_4ajrxqiaGw~v>P5dZl3a=m`PT;D(7?-eO;*Y`^=7tF}W;00pc#1YAwi&pX5 -zW|{9~i(p%q>*wd&ug~>V^@;WQ_WJexO|rg!em;L*A6Zv646NIL-*)Q9|MPWi%aQB0 -z_WgWE9+IlGFKv5l|4S-Wltf9iE|hs`wVX-5{a}&0f|~ubX9MiEnj%2}1lGE}ynVmF -zJb&g#`TNc5`b~X2xyc^C=kv{*OxE}5TGUJv(|e0aTf}1RMczcB>SC4eCd$B1!G`7Z -zCN1FNV`?yZz@;sO?l+4$G#mI?r$yxG&g=o -zI{C$*DI8jw0C#fxx-^mRh0C)C@}xg$*B{0w)MA=10UD3}=(5ZQk^VuHuLLZ1FntWG -zTff)S?-dgHs@ROT*HLJ17I?RvoFeE@th|Y;Q3_GwkseN^J7HVVlAsu`?)dk%WI$pn -z0jcRg6i@F+<*Q4)8(B|-TsweviWv$QC@RW*(H`I{wGCBsS!h-_VVWyG!m7UTwEO5$ -zGX4fyCqNbNRV(Cizl!#rEeYjS)^%VeoEc+OK<@w_p+8yGz39AbFF8d+wpDy?`XUF$ -z6nz`8d|b_+tCxju&_WKZVwtN%uTi4E@gydCr*6u4TZt~6kzoi`cy_WBZ1MGP3Ubwp -z6_|5VSRhfxYNbuKVHoU$0Ifw4ZFNZ|(CulFnF^q1paWoX4|;BHS9~QD{RSqz(TP*Z -z0Fkl@f4;w$ZiQ6{mbS5y?(_5b4VhS&0ya@LOpc+WbZ#LC!e%vZm71A1Hz-rkJ4|JRi -zd!?Iud^b^Wulq`HF`d(v{NWxK%eWX}Z#M%boC3Ul$mbm`6E601x%!K%*obTzRW((IBP+7?f@)I@d&=*f+<<5p -ze)6_>-RXsxGwo)WWU=fSEE|mm^R%YT9F+)C{`U{&nzw58_E&GnOra2 -zin~EyLzO;>nb1JfBTHeKxyw(c$V)K5BwGsaPw7-#0{sFRs+z|T -zh3BG_smhtc(>pbf0GfatTyJ75?UH7q{)`(of;odmkW -z4BNRAE|j52`=aa&B##1oaGq^T*@s3iT>AvdAf_eP$Tz0%cnB*8r+sCnj^aZM#PxhFY@B}T3>5f2mgRC1jQywLPwD?SU-S)e`h -z0}66nMo!5A2@Ni%n6#!PvO;EW;)eV^_Uft@AnlqN#fY}KCf`z}+@Xr^6*p=93TL`k -zi~*fE`GmeAGsUw~l_qJ&Cr2Yvsx*rTDFaf~rSj$=Ws=3l4ACC1uCqq&Pd}g4Ji8?+b^qaA(VQP+hgI1k4eeIbmUH7Kq -zi>%h-PM)i@SW{f3OL<2!J4AUIhBT?vB#{WGL7inq?j#N -zR*W%=#-D`N=YS)$<8n}&JHZx+Lgk6KCo}vd=`WiOhK2+@o&E(zkpi7)G{;tZyn4eP -z0DxsfNAo24w7jy_XL3 -zylnZ(P}3rqPmsNAh2IjGvWT=<5sW@KBC?_iJLDC57_)@!;cRyx!r{}MguZ+{GC -z8j9O4m0;6FQuy%6w72At#ZFSY!g+5>)W!D}g@y_c_)lpQSa81?vY%jMq -zkRM;bC09z~yd;k%yeCZ9{GwzXR$#*;5@@p5YqMKIAKCq944};d52q6#Sg+MOC2; -z(%>EgcfW~4)eHDaKuL9pqMt-Jw5psEjrL>B0)k$G-w^bGHe|poFKOrj%p6dM#lk|j -z(~ZVu8DDUC^Es?DcdMX?DGk#tY_)KYXfV8XmlW5wyMnCjopHm?jGMs^L -zHS}If@+SBj)ALPA$d&n_NKUaZ0+pcs+8Dp7d?j-2xv$)l70zp4GV_WqLb81C$zVu7 -znA8PsPZ0u5uF@r~Co;ws{gubr+v|D?C{{4e-dD&gkRxLxyZZq9m+&J?7p(L<0}x>c -zHsd;{5Fz-{ND6wJ$rZ0)9U@DLsc{R0rfc?~^q8{8b_EbbCb_lORsDS{%Z|q;sFOhl -zwx)Q7f25Zey#LFBOLSCLWcjNbSWj{=yNh=E;YKTli5G-WJTa>W*^>n?96w#r=OWD1 -zsemW`fK=svX1AIS3m9YOi|D~k6yUn_@`N-$$;E-TuI2kody0)!<7t0RCCg&!d#ORM -z$RFzNC}x+;@eEfOWCKeIxV^QS``ZJ^l3nZ*DiW2O$ZwW7kV7EC^z_p$9dBM1nbsLs -z=1R1_p(9Z(*s(ihAN@ygc!x}7l7<5Hngss{Tx6?E8W__ENe2L5pNMQEzz#u_|w5=_j -zKCWPkF=T21AuPdKo9J#Lu&+l3^b;)@Vp0E}r*F_GiqU12goYvi?DSy0xyk96U5`y* -zZaQ;Q79IYai$O#(0FC{@ENk4#i-8Y7V9R836yRt3y?a2XhQxOXw4s&Bf+1y#Ch<>61;3Kp8r@)twV<_t8oC0+WE70%xM1kRQOz#{kqInNA<`ytGECn**A3{p4j0h)Zw4-n -zR%`A~(x53vUJir^@mMYRh+^seJczET>?^sI4^$AZ=}7Z=BBNm8EK^`)Darc-h`VVK -zu7i4u4?$8*b)d&iW+4=L(L&I?1PgH4lWit0rQneKO!&W%o~oS!?Ur8ITlZrf3L!JE -z+C(*o3HUGk$eelb==4L+cydEwIJ-APm7F)O>1?u50L8lh@2)4**SBvpr+oTYS? -zqhBkd*=Z{Yz@+2$4MnW9DnLO^29TGTlO9CS126QW!^Y8z_kC#J!ci5WuJ|Ymhm;9J -zJE~{_(S1B5aVx&_`?ywTWl{!jw01v#3J{I`0dbB(~sRRr3$p9 -zhY2M4BzeG0PFLp?_YrKJ{m4WHem4rCv23}?v9w7n9kw8};MNu$o^3m-rT=b~OrM8RC@VhISxZrtpEn -zyooJp#Od0*nNyg3Z2+*Lc^D;H3h2e(`2gHo6)0)slTOwnnEyLDMqMk=N*LN+`KVT! -z5oLib+q280bGo53Ttfe7 -zMY!z82H0uLCDWQmRwV6o51P7z-6Jvi58Oj@Aob}{7yqNU$qOgUg-kE1s6>&T_c6kZ -zKl65?lIHpI3v -zyRb0>TWR{fQBh29Y3`aingWF7eSyv3!0&$C2}Z@@QFwZyue{=pEsdxuknHw(>v^>% -zDSbDPU+qw()uxfZBNv{&Up7OnO`?mLanMejXr?s9;jEl^8H%%0U!2s4({k;50rP#V -zhQZcuT6rlwI|#|qm54Bvm8UhyZlV{F8S?y-U*a1;jQ9q0#0}3lhXy+|I2`PLke(+* -zLRqp!GGP!&2oeliMQg`&+)4)(OcNdHMw^Ul$vwe^0tHUIZH^pu@)?cz(Iywe2D!S^ -zFOGaj5y-TlHpad~?D06HF}$v69SvqukhdHj_x*_#E+HUp0d3 -zOyrIiC>s9~6df|-iiUS^w+lxO2%UA3`;F0dOtuvrR}@mO1!YN=?503K` -z1TWHK*twH#!cm}z&?P?aYK|^R^A?5AK&$9{&ie;LN2w@Ins|d|K?<1owiq+j-uiCE -zZ(QX7nHh!^kYtlrAU$@De-BpI1aqHg;J%O#7XZu>7iFx;Ngjd9c#;JS?84!~=R~K# -z$v%41ae1GqssOz2(LtF#lLF_M6Z|0+a7|`ZZF)=O%L@LaxOZwi#UgFsNo84cQlm9N -z*icBwKI!Vhh!L4KRA!OA5!@Tc7^Jenq8BlCnSRe^ze)W`JLWh}1=y6>%G`@jq{juj -z7jM!74e=)3_<1*3yV1jL!UM7CCZ?Gjd)y^aP(85KJJngPSgM1wByNg?>u^==nBX=U -zF2T)4;duGQ&waT79J|14L4+@E1cqQ4>=fm~&BawZ)KRmx}A7>~Fv;6VjI~<3Cox3e0*5sKs -z3ry9HlPqSvLgVELuu-Qo`uNFD?hH_8w;Ii(R*MF0ujcgGHJQJ`+ut{T%TLKjY^R4)_#7m0FtdLF3Dt?J{}WxrI^+zqdsZUDbpBx>FMS5 -z?e*>D>4BEj18ubT_l3Xu`RV2D<=4~u$LERe`Gb`2A7ryr-Sz3$%gfu_>+6Z`<>Tq? -z=cD^`FHiRd)Sn->(0p=bVu(!#8L#T#=0v`S$Pp|H-?O9{F|L -ze(%pQ2!aNxyqE36!^2B*NPwBkWR8RPhrG*+BwOCmA3maFyQ;g{NbWf_+9lDp7Lp>Z -zpUBti^?5C;=e2r_awOpMJmj!lv4Z(5=!jOqAEui(KR?Wiqu|OdsT^2+J|9p&?FsJe7VkhS4uIu9k9-)lc&464GDa -z?zpD1cSG6Q(~7 -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 -z{mS#k6-cVhKKS(I2vW4>_0C`kwQi#brYqV9#0 -zg_^&5{9Q8D$s!7+j!)PuL>++G@B@|KmGu!fH39UhnTdQ5*6f^I4L@)2-UA2tf29Y5 -zN*va|IrBJsL#I|3Pz|TMp#y0jEOp=?6ZJbkZMP`|&^R{n@uH -z*LfcZzUNlwQ#7lJf<{8JBtE!TKhmrxNy{&%N=vo8s;d8o{(j%L_l_NrdCmnWN>-IX -z0yw#c*s)^|-#oCDASX#6iuHNS;>0)wepTrEuijv#Y|iG{`GvSCc{Lg;AkE1KN)lpUS+ -zeyH8c(1-Z5wS5~1^h-{&0r#D%_c;s#VxZFi5a67f58T+ICe@<`B_yojEK~Bg%H?mP -z>s$So<9X)g&ADXS>=j^ww34{Yh^YxvK4ajrkj2Ad4 -zGUIc3p1wxPEdAK$TLPmSn!gJA-^97t-_^SR&F9OO+S2_Us%>AStu(*c!I@Bf>0bsq -zx4^zy;wPPW7OlW@5$G7-i2~#1oG&=??tmz6SLgCzU2e8Q6cavfB@z!I?1m66Zj6rQ -zxNq=o@o6N~1-}R)cX4Q%Wf~HV3xZqrxXGB{%8Y+wQ1W>Oa1pfU>7ykloIr#sY;SJi -zZZdd(6ERsX+Rl)hVR3o@Xe)%?Qc3z_BSmNFPtws -z$-h?!>f3Bk$Wl8bfngc3!sW^WiK3&yO_3H?ifYy>K(-$Si0gEhguD>A=G!vV`3Q%= -z`HQFCBjxSB{BsYdfB#Ep){yceg2-9B-k&`JnOKxf#9_pY%gh)Mo}bdUr-)t!6Y)pH -zCl?aNT>N4mT;2l-PGh$43}_ZzCTpy7xU_uOycSXrrQAg_ltyebf+*1j|A%I^9a%RJrs7j_AtKhlDHy -zl#%KOdeQ_`1NfWho0f$78U|hKF_|YQC=my;19W7|#7pg2o}m>2`q5S)rQZOIGg^x> -zYT-B!$B`H$oxe#K(JIs4nSY5%a)X(nJ#IE -z^gWXMkVS~`V?GEdh<$PCu;Dj+X@P67;O)v}Yu>|wEH^~{KI=A}-_ZqtXY`)0EQInx -z9J)mi2UOHM1|mXj1T5h@a=~C&f;=j7-6O5*vPR}aENq@`2vZY#?eFyO!B4th_9xG? -zFA=j~3#I)@htvFQZ7qjcmV$I1Q%cpPrDut%GM@^KVo%MC6=yx&`VXivTY}t+_8UPz@+jl=sv~L@ -zq@552vREu5V*T2r(FxV|NRmP8BP<%tOzDtV8mu>6s)~gAAk6co>2KM)c!4Lq85{8GMZ^nZ*^_ -zfbbUog1*^A<>i#}+rxUp{2nyu@wOV5Fm2n`vUq8s$<{tovZY;}I-xbjwK6d35D64V -zf!C31GF3Zd@DVC`Rz>}9MqtP2XDPO&Q!<|=t30Z8*8f;bLcpfEp{-xPW3BzS?r?pe -zf?q})rI#52nKhQwmf&n_3O1s$92d8)AA7uS`ZJDhCr1(I>41&mWk;1Is>ToD9%DlJ -z7F;4f&_-E=z`eXHRM-~x&rWxQBHN_afxVb(VFuh++fy0D;bZ7GzcAO{#pNbNWPvPG -zk)pZ5?4-Fkz0ZwZ;fXSQRmw5xD#PiF*r9`HF#I|?0$tSu)B)GjJvA~1`zvP=ovk*% -zv34T6k -zzceXCrQHMlPUJ$0JJ{zq1=`eAx+?heaLoYjhEiW-_p?${?_GXH+hB!bQBEB+H(3A -zzU$|5NFa-=QY!@w_Ru5d)x{9k5BMZvi4GX20k@;si)RzghVGp`ReNMy(ljxz+L%bx -zSTAkt<3k##Dw`k$ATcCIUk2)S@H~&oR1ynPuejzuN4t=q{X9 -z3H@E{uXgk&-(P*=`IBRjDD=)2JKshgoczR3uo-D6=5JQp_tE8^Jkk(t4h``}U-e^H -z241MLf!Yv~%FpajQl22y?HiXq4`Pf3qfV97&!&+~>E|p%*J_6xQ -zlzt3}I*~(rZ4t?e8z_J2njpk#MFR&-^Zb`y{vxfXEbNzm?&5U%_eb~QhI@1m_vpuT -zASElG=i`A$5F(LY&blRQ>gk*#$|n(~Gd7c|JF6V> -z>nLq~9a;FKb=8F&G)I()(MAI$*Ago(Okf?h5U3HbU`deUY@mzw5n5R?Zn0e$a*ye7 -zT}Ojkz{+fF&SAr0B`K0x)>tJoAkuH7jb*kE0^`;xY|y?k(#PF@K=?SrzXG44s0tNw -z=9ol!1gdJFb))Xz#}Tr%!~UZ6OR;9yCkmV}Bs4@|5VQ)kKpXg?+emd$wosu{SB%K! -zX;fQtVrh<;57QqG;@@st+6oETi8MCCT(^D=s0ps!P&q*oWerjg)JXoTMOsuZnp++p -z;UjcnK7=lZ#R+li(FW9SWb}}MS}Y<^+3o5?KtC(k03z6q^S~mpEDBXRU)IG#Io3bHR%?MN~^$e)XNq)^Q(DEbL;y}tkv!okt#U{FijJY -zH#q8#%=hRtr3ow+K6!oAq;v7KRmUR|A6gTgWU1enAWoxmB(acZ1ecGT&6v=1y$UOH -z*RIxX9C&LjhP>K}*z6)+BY2wxA -zVM}EAE!Y64HnaonOrO^b$yh+^g=@qAASFR0SqOws6n4H5(iQRK6L#F=&(q3>G*27m -z9}Z$6r$t9>R<=Ffz>;@QAjq+uaC(_!_Q$$mNm&pXuuTqa{S8rb^xCVHy9r0T96eQN -zD+?&Djz8OG;hJNdk0SVHNE)HTYyqqWY^!x5(cF70)`JK?YG)$G(C4pijs#TJM`I{M -z=EdFsH$mD1;)76iv)1TuHut{#b7#~0e}Dg_nWSF-((HNQ&Ee@Mb`Ekw*goxTFi|Go -zmT7}fR8)YylL;k?>>)4&R|hKHv|VH@(i{XJoi%69i%5A?P84u)*}i)DKLx=Q4YM+Ata5dlJkS6!GeyF4OY7=j>3$Wb&V&;7pa${EMM -zJT7J%)v*lC6}KJLc(NRhws}ohf7S#82^;`#+8X%+6_|7ppyWht<)56Qjb#KS5tF>6 -z9EH`@Kc+jJi{6ZFZw^kNe~n_XN&;KWwxgm}ZnFu1&&8Eyzg=d1#Bo2m?=_uRYwlOk -zidh|S+8yCzW^)HxO^2JVn6tpIozkuN#e8E*sEN%<1kTcSGhYdAk|{twKg3yx)|20{ -z-?Xu2^f$)A0W4xocSrA@@Uc5MVhH9qyyVULO9XU?CZ!?mp@(3E;IEn;Z(~W?^AK}3( -z<1c5Josanb!$c0&Vc`die0(h2aeiZn -zwXo$!7t+{LFF}lM}9zI7TBFjr`~o? -zWi&V1+oD8{Y?#uq9FOMLriSa)ZZ&?UcG~_z#w;YQ -zq@5wB;Z2*iuQ|4P$2JbS1tJx8nz?Fe2B{XGy4$&5XT;{Qa-T~qZEFJ965-Sx0^v(| -z9)MrOUh@`3@Gv&^gs_D=k4wFv8S+(>D;?Wmzo3PxXh~`@IxAVsdV_F*8u&CUw8R!s -z`i0WS2jYN;?y$<)mc^RfWZS$#iYZYnv5hi5L8p7%!*?EfE9ZBc_{jrRU39aupbZ$Z -z_%$=kK~#4|VI+$%Mu7<@a_9P;9FtkK+;du1`nw9OJeLN_)yDiB@VgpQ1FXFy5W;Kf -z;LeXWQMUNeJ3smY{o55V?DA4pxc=ye2Ovk}Ifsya-z_V}2TP -zm{L(XuP4Z9b;vjaP>RAeR{w-_3D)dg?!iKGi?+ZR@CI})(qf_L#m0v|Mdn-Msqt=9*|uHD!D|s}oDRG_Q3nDfV{3(%(uX1ACpsOmoPxg;dts@u -zt<4XD*7t4Y&lnrBH3lvfJ4g1*dsI-v?zyGTXuL__jw!1qO}k`t;Owpn6&CdcL3o!ju-(TWxIN>_@kiWzFGqXSoe#4FZLWHAKUM^pv<$a& -zqn9m_Y*FG<9PiX}-lCiKk56f4vYH?ExLH(rc7CCa(dm$-8q%@f;)C;3D?4B9ABpKs -z8vd0ysxSino8-LWdZ^&HBy51Kw5qbR(^LMoDtmOFe*l|`p+1qnWsrs{jGD8Dj7fa9 -z118MLa=%El$|D`tEiNDs--uCLNc3S%%hIY80;7OQjzTw6^U+o&t}kCM~L73p(Tn~ -zG>fp|*b)u5;Z=op&bSNpQ4H{gWw|W%<5*SkLAZSM5WB3+^gvP_cpo_a1^-F>1$woi -zxq#xl;P?bE3E0y_LaXoS -zHvYnRW;VWf_qxAXmw1!W{m8~XBThx9^J*I3+0h@=@SWwmKO_tIAFj!}YI=KbDr%2w -zZPiG7(3jF8hJ^y>0Mf>g$4unQ!nJdE&Ex-u8^lvf^>c%!63wUE2j|H)@jj&KqnT;#* -zvJL+E3gMNPh6~k1s)d!UX05RWbaqd~=kUZ1Y3kV?W6-30YI@PnRI$7}9Qyp6kdvTz -zO|HUb$FWdG#&<>*x8iNX?ettH*J=)Y&#^r#zdCb -zdmIfp(MyJ0H&rLh!#GMqT)O`A8WScodn0q?kg7u}$D@TuRD|0plOg#rbUxI;1dB|s -zw7!L_5iL-eWx3hP$O??aNW3QSW*9UL#zXn~s!WU4qI$`_8T5!$K(QdhB6WPf8s8}h -z76@)ZX2$vJ2lt^8Dxt>@XmV8DoOiI~tucY34xEWhn1>Nuw&qFEs?^aJj3Luu^o2E_ -zxYbBZyGhD+2xjSEYq`43Z0)$csI_%}u^ui2-VU`US5>^fs-k!wr;9yo^P5$SXlVN@ -z!e^TnruzGa5bCOJVQgPLe=@wbr^d&dL(ZIE*v#52v~)t)05hg4vw>=k1+tm7L0>?; -zUB5a*q7HLuJ4r2wfo-d`qi)Va^4 -zJ_A&LPxoHrBX<0j5EB;i*TZ!BGmHd#2uYZ)NR2AafER;JM}Xbofy7EY*?BY}@9g1!!R92)H|^j0u?x2WkH>a(-RwqS#d -zxqTlg$;8)T*wPCc2r0P%8(Im>;3DN=SS1sy0s$$cwA0RSw<2%Wwj9Ohw*_`EL4gqN -zQG=gRTnAVs8=WLfvj-IrqTCYrAv57lblEX|?h9$Vzp{Z*_?>-G9=z(Vy0+<-Ds7^| -zGqgE>+n`Cq6b!LU^D-4-=s}RF5g}vC=Y2B=k>Mf-jo=-Txe(^<8n_KbeUulm9d80v -zjEjWK^Puy?8M|w_0V0l)Ny}9LrIrMzTCNzYfNaP!BY?nwS>uNsSDJpV?bw)O-DNx8 -zq(StDy1OB6)&mju;HOV8NErG-NG<-&qq2sXi|jOLAB09b62ULAI*Yo@>D)}R<*hyFur$ZfXama?AhcWF -zn|_?5VIy>*=x*SD2CUIBX6RXrkBRZXg_I~W)k2EpE#SbYQ4YfXYPn8udk_aA#0k%7VS%*5W{pDJRQ8@9toV|XPe_m`?7pMMglMu9XGm(V%AIZptlDPkp -zwuBf;FcyXf<1RLZj7=<46)-wwW1qU9E~3~!LB!jw$2KqCBmWUEnab+42((c_;qwAH -zxs>v>2~P4a1aCh1boF4dkq^O~LP9~C&Bpi9h_Ie -zBqMmg^%Oso)HpB9h!%XA%5%xWR2FlXwn?802^~ORAF2Yw$gkN7%&&A|%qT+*VnuUi -zlUdBdzQCLsKh5X@u=z2%EaF<8l>ApRmrv9Y+jqW1XVv47V093QK-i;Z$D_dyn_SD8 -zZ3ZcJZO*|btjqx$wzW%hVh3$-!dI0Jz%^)M+D;;$m?i`r*w}-=BY@1gDeN(bh+QvN -z#nsa?Sq)p-s@U+Rg*Bd+SmcNjAlBI7mZ+UVG5FB$;v7o4V_0&UDz}QcMtwRob5Gn& -zYhS31%nu`|)7KVCEIWrAw}@IojqK$q--pvf=d{dqC~}=wVn;i0aG62W;sEQrj{xhY -zia^QdC8z5OdJl -zD%7Bv*a7=2mLVmEx;q&)WLGksE46Ae4WWZf1zlm+jG8vZX2U?Sa!=wFZRuHYd9Yts -z+lOIrP`gx%Fk5fem%GCz|4Ll+dMsxX13=*+uOlKJUd86>LeMqmbZaNv2+0ZJ-*CbN -zXF;CudU9}tY+;UtuRMKR+*+6$`MR2oE*fXy4|czxJ#G`{#v24pXY^#DeC$tAH0fn^ -z@WI6@ds?qnZFRpmXe-lEvbyqWX0bXas)#D$w8cLCgrlJBBAN6J$udewmO%u1$fsFx -zN`qltCHW>$lOq?JPDt>Ab0izvfnX$jSpr)F@kd;WJ?F`z#YJ?__x*?WFYoDjjk~DD -zL;vD@5nMb7PH*TEJ&5i_;pKzqp?}$TS@C3@++M!#H0mUXG-HjtV|}@GYZGl?4(NpP -zLBmGU-kkRXZ7NAIQ5C*U=JT{u7xh_kdazrF&44Mb*A-{BA^x3S*|_Hc#<%4wZJo(b -zZurZS_Wb_Ec@SP+oS*5ns*Cg0`r`0C<-L0W;shNuG%Z6$9X3polBkyE^lVH->%kDa -zPDL(pqFKx41W|WbK5Y)a^j_)H5+_$o#5Ec6k~r5_@{AN^U3QIqzmUmIS6FTE5bq6I -zsG#S&sPkr!;E;bz*bS*5%&%i2o%r{I(;zs16fW*5ofM=;Ei=gTzFv_@vsX2m5;L~_qof_@PbEAwp64>Du -zB)!ooUJqWO>*z!jYNFKagv!u7tDMuS_dM3`D~5PzYRcBtDRY2b#^l -z>_h^(A*kd^qHFbxy|Cg$AObXG+QU(^#R1#b#GU9M{F3frn0DH2F-e!HU5*9o)Y}wN -zvPJh)OFp%X-=@lD|Vz~gvga3m3GpeGw|V1G$mrJ|o&Y{UlOOjHdN>p!z -zYWSKI!fVylx9?|l_sl~>wyfG#ad{X{MaYe?3lupuB#VI)}@NITbJA8^uQ8c%PKapOhfY;f$X -zSHc2=^GiMnQZT-m4i`#SMZ{jEzAPr1kUaL3R?n_V^3?uxm^otHSP28%#Um~uhPQi2 -zgqNQxJzJPwT3&mP<=s}C0XfiW)wMc%DDnA`dl!S)i-`+t-|w(G;BTmEA(ZgGtRis+ -zmACB6x)GHE%y4@Mfo2c33$_&2_GcPsL4MCw=-Z48AKFT-E@~p#wO2BVOv@PmU#>`c -zC0x^p89fozdi61A-DT0mrI->6Ny;l|ek1z1rBv~AYb`6pC_O<4Tcf#dvWQM1f`7_- -zHhI_T1J#sue=rCGRr68k?uk^-m -z*t42{B~Oi+5f?Wb&m1x=CB%UdT*g|{tYuKVU{ov%2TNHrkHUr*X6M_P=%2@I(6qoy -zXaA8%cZ)Co+}SDc{U^q;GaT`l3A~^e#gG>#CZ41B!if{wkxy&U)+J#%&~M;{_BO?^ -z9pwif^e;W!4>|xHlNF1flB~JhxyEIyOV$>@;vhVqxDo5_j|v3gdf{ -zzlKKA5+SwHW@C5n-hJHokHc3=JPOee+$!6mGp(;i&5{_j`R9Nl-X`X5{x1ERiyUcw -z#qJ-Z&gxBl -z2j&w^x{3zdd*s3XOx*fp1rb`VVzo={%#=@fe2yU8lSR9pb&awsIn8r*)fLM$8dT$< -zAoo=0wJP>9wPuC+JX}=sP@hp%FBQ@K`Cq}1b0W&<1KC1j60X9AsArhWg(hh(#tOxz -zctYn$A^@uf!q-{1oWlF2WImZn(zl`2^HuGgeZ>CfAF=<%N9=z&k-#LttkXdT=V{)m -zs8vikObdjRE|$%9QPv&PI@6KFbqaB8OaP}(>qS+Sf}40=!gxS3nR5e_ee`Uot@5V` -zxneVnbE%HBk%V3Dv&nFJqxW;4^GUP;&lpFN-nM;(FDZ)mSg8%qy1660`+LItS3UO~{X*3Op7|%KJJ?|f} -z7HrW>oZljiLTyJi4WngJ`l0;pf+hYH=sZ1ete>V8U6GJu>d@*<;T8oDW`pNUmuVK# -zy%wMbNF5O*fa(qe*a=;;vb!=}Mgy`g`rgIm1 -z48YTfSFo83XDXFhv}h+PqYWYAr!dQH$~R)7MOoUtsapg|pX&=U=hR6KeB*E;Mc56y -zhv}-0f=OA;;uzPBwhQ6Udr2vE6)~qXRFSrZ%d^dM6;4z~z$k-ABWwEx7Nrup$x}`- -z%33qq3YDE`bSGheWzqqCrps3Ncl6}wFziF;tpzbkaBqbF)g~h7Cg_Kb@PaljoD^LS -z&x2uW)%o-OL)fruZNW&~rL@Q@T&0cqxWF$rlK}36;zL-&01ovieTv9;^|O48C+jj> -zSeFEJV9D;|qTpENEchf|t|aO|ELVEpwe%O%vvk|Q^67uz-USB<0%-~ -zn@2CpGHK}MHgkR0v5D~<0lDT9Gh`mLYGN`P -zif(?&G%WngwEqWWzPH+fu+Icc=&cYHwj&uvY0sO2hdw{p7YJ?7jIv^{xk2*tE~Ci;?gQrppov@1Xe2}IMFi^d`> -z>=NDI$gYlD8345z4r0344i-;C(a<9*n<2dK2gf?#EuPlX(h()xL5QLdq%-XMo{A@Q -z8mJz@1&J(Lw1)$NM4NEzL*lCau1O0m8Jp7B)DQMRJ`J8~%q -zdIU6BuJm@-=~YJuA;*$NgU_=&|X<_dA)Vz_JXH|lUttwB>0Fw>`wcDkZe(F}< -zfkLeS+#rvzbs&eBr1r}$>uE2v0~S*|+#o>8umKg}KPGz%HV#zq(yB_NS_KQ&mR*o| -zgtnNJn1Bbf=#ZaTfsRF94q|s7oL){As)m18w=_NI3yE5bY6w#{El_0Nq|3Acxr+ej -z0G5J?ePYv+Tt73_86t$5m*A3w=S-|ofD8~erHB@Ywy!NN$LoqYJakHfod(hszz+mX -zT;mYnEN@Z->aWm*3qt1-^}-|+Q~2Q&<|r7fZ^MidB#ipzby_+gT`FRV+A^w}G -zrteHMZLKhg323zJ-09)QX~4b5Gq~DoiFCsRJr@|JP1AMbM_4m6VG21FE*q^V -z3itrYR2F$-p;@(t#O~eY_DQ=qn-~}t;~wfBb(njI_ObSaGMOMf*V@t>%v5;9HfA_( -zLsDOCHwYj6O(fII{DLy$qgbcq*q*!R_+{^{&wTnuLQdPzc;~0*j~;kukIo)F -zI)8TO%lqEh>G|n{%ZW8xH>q0$)HZSD3&i*6XcL(s&;|^QxlyYNy8IcZY}U`vQWG>_ -zD$PiYp}(}Bo|IKZ9VU&Uo=PI(YPA)bwIB(bkb;epjA$T5=xY?5P=+1NMB2IwmNW$m -zhI9wvbHlWG+PUxGGb$u19K<}rDji{`v?y)rYU#?%vLnf)R&P<4vF*@Cd}4-3#zE15 -z%{MlR>)3?q;W5+3gp~CWZxkZ561dAP0n6sMDS_l_p$hvk1(E&pEc7S9F0pp3LIbU` -z-xhigq9UgG8|bflG!>o6dAg|co5Yf`LX!r8FX&3r5cc7=_`EDVK{g`SAg$$|=<+;m6`un&KRcfgup-#YuH$woz+!9bRTofG -zQ>%QUgp`+qHxNR}Ym+Yb3#Kh<02KDulbN+4f0YY*Rnyh%joWB`Pi1*uBua@`{Gi{j -z7E4@TOqhNc^1>})N4k+`lcWmRrPHlGyEi#+a{dyU3iuwk`2sShup!9iM;w5F*WB%K -zd7oBh#SENV`{>xHQ;_sNQaNfYtI^zSXCJ&jIlzHvN+a>inxCCMc<`()=NFHj(dGQ? -z^70v7F3ui3n9yAFsx65Kp}wgy*s3jpydhF12Dpo}lBhR_`xDvIg!X@Ff{f!C99q~4 -zY2uM@RYaV%+wRDZ3?ft=M8both>)_%?Vat^l$C)y?2a>%dypL63u_OUgi0IXVUE$( -z=+zU}>kFKFb{A^;4v=gfXI(fV#(Yg6WfCWG*)*x4%2#O*87Ij2A)5Kd-P@a6W(Sr$6)gPaW+% -zuZhZdT@!lqdH(M1X)*%q)T?x^B -z>Ce6Ug;)RHo3Fh0#!q4{xE;`;&$CH?#7M*X$1cdthHc49GQ*oW1ph -zFTDA=_kQNd+n@d1=ihqsb5Gv>+`F&7`TFBmUw!8buRVEfvR2!LO3iw|1*Y)R%sp9g -zl%YgCxED`2dPAeXX(}NbjJ*#H@R`rP_vD?&Z+w~-U}Z>Ps)jz)^DT|ZEvz1Z!pnhw -zv$t!aSAzC2qL|T!YfLH5F{)0(0?_HiEdkg!_ujS -zsn`7M-kWcx6JAupcFtLvpS|_w!>4pUh)Q9y#MGa^u}eOGtbRlM>ybBHTrFOIdje`B -z>e2a3LxcHQquQtQGoFEECeS)RBRY)GBP6h9lLMY}5Tq0dAV -zZ$rAylscWXi(=LUWs9QUlv&qC1C+z04aW*0pF33$y*Ns#sj3^?tU{|~rkd^}tR|jiQ>7;e`xpdU)}^Kl -z1OeIagla8XVO_Oej%#`j6s24Z8VObEdEm2r<0eBAk^6fpB%R_e!y -z7&P@$@OJd2U1gQtL=JI=6fC8jUbELIkwoMP> -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 -z(~qvy01==rO@w;`E*gF^m;o6U;qNR -z8p%}TG{F{PHOX{9v?`qvI1oqhUmQ%pCC)gwtXSta`t=ZF(EFF?NHjmSS?g)%Oa4=? -zgjOIL3ACKGCrV&`zO_YH{Sc-rr4KKZ4;F4gd7IWclKIFXdWrbXbe!`@L*rwBZ)`_` -zI6OK7qtq}3Fsl-x>yp~8AEfFY(GG#m7QuBy?|EsIwY_M)hzaXLMACMK*oTlj*7RQ& -zTdPgbc(X!@K)T@gG}EG4taWT~IcpuletIs~B2|UAP^nnjOdC2ol8GRXrcKNyaxKmPUZa#e6$m5&uZI -zkr*~3=;_O8G?hR~(`}dMTlUwO!RTdR>5m$?Vt6K+!p*Hf*T-8QJve2kdbE*ny_e%z -zSP~q!45F^DN1$R%(1s7u74O7+hd8nMd|ge1Tj&KL4bV{-ZGhu6D)qcz_u%inIf*l5 -z;V2j2O!_y>X?uyOoFI`zSt~%hgg(tHy4-i@MV5guO~q)d%!XeNQVB-m2MrYgM>IU` -zR0uQx!UVrgS#*6(&LeY+N~Yh>cE=vPt8-tb1_SR0)Q!;fVL#}3%5ORb3`3t&IpA6c&sedYH2Fk^94Z?`m@SFd^h10#ufR_$m-LfT^FT+~}EM -zxt$gD$EV?+3^lc{|BP@%7^$?_=^g%Rd8c$o+q6$6NQ7Wkw -z;Cn1tgL7|8z0&V{$rB8p1d# -z#(}I$Kf%N*(Wb=2!AuUpDhS;r$d_)l7k(5FQH^voeuwZqLk$6R3Bs>Tp%Ch|1!xQi -z5L&<}6*Uw)%vC!vCkU~o`Ox@>FMSlo5uhBM-H0aTjzq+5Gkh5x*c|rZ@QhJ*_H^+3 -zpG_;+7Zz!28C2hUlM}81CYQN#x6t3 -z)*3i_Y1M!w)0l|cnoM*D!?$O#=|F@c6ab5MxE4ejB1^cILgi@)(M~UX;fs=Ab%hNg -zLFF3D?7W*+oW622S&2E6EqA^qpbCiU=|77yTN)sQey9egMwhR3cLah4tv-Prc+f0U -zbIFK4J+eG?xdln*1+{fNZiwa~GII@+>B4vonKp!+q&*ybEDf+0naOZ#n=U-OKdqmx -z(#BD?U7oWdDv2O<5Mvam01XTocv4Q`7qd0Wur63Oj!iky*)5U=h0U72V02X1$)J=r -z1Ok%Lomg)H-x6eA3Yic05feHd9$0}gaJd|LW9n)TCZiLjRl!Qtm4Iz96dTVZ3Z1HI -zNxM;LDL8=Nrq|u5P0{z1kd)dwjext>bTWt`Qn6i~X=$~@jf?blhuR`*jr>UZN+Q`q -zMK{sNj*t7X;O4d~`~D;-M5s#4wcHl>@)b{oTLJqaM7QY0H72`?XsHv%0FIeh#(p9^ -z>d4*&88liWBvmnO{y=Ib_@YFx&BvBEsA@>N5JfAAC*HSHy+#3m!10^c2{ZZqh@A~7pjRlrSQ -zL?9}5-bAAq+gX%#nr-|P -zNP7;pGE;-a%pwRpjDZc;3?25lE{8Cq-MZzj?O!i$_l?hxqOZ;S*D$5hSl)=MItlU1 -z1&$;^r@mir0`I_7PMHrAZ77)VK5SQL@)_ESs{dG%CC`?-*xy==-irTL*LS -zz}Y1N^b2j5FJ&Y?uFHH-;f}R#?6UNli*Qw@kZK#lni}TiD-M3JZl;G4;;GHA+CM|^ -z$!l2DWejgQgcK2_SsKU%VIu{xEii&0AoewkeH&;O)}@xeF_bJ9ehP~*%^A9mX-0+S -zIcO^%_k!cXQBk_v2Zl$PB79gsyKnC|>#76>%4x_LSk69Ci<)hj1QV22FvVf{ijuHv -z0A&!}$=-Gw1$`Y@H{0uJYin5%uzVcmKk?IuJajm@IefKgX#sxxo#FjXf_D6 -zWO&wIwIz?aHuhrjCqu(I)st8|pb>R`B7fT&n@ajjlcQD)8e2HqmxlT!%ngyjKzs?t -zQ{#O%ED0=ZXqFkrx0dbcV&!;`(UR#vY}uBcZlJ$4O_>)MTM6wnVU1|T{ESHSKr892 -zWTJXI>*BO{r92+34uPZJP3lh-?E3iOb)g?l|0(0ML$(P|5{1Kf6ShNI7m)b?F*ZXop=d``Fa+|Yp?ah$zNp0%i!QtS+4*jF -zIdZ2{yPx{Z&)lCR+X@0vGYQ{|aJwc0?H||2wc1{sp3eMsG?0JqN%~F>br=NbCNLAo -z@s7Ynt0CZWAbzMp%l5YmqrCd$-9<7vJ3T$KsdA?r1Csp+rN|Mc{8Gf?LH+oxrB6L$< -zGmh|G%1etI%6f}Q5@grjGg0kt8w6w<2v^D?;3QG5nVgo5;0ikyHyzCBK*jffbXmLz<*Y)&U&gFhc7X5wT4RtE;+#NV-|l -zO=CXD@Sm1nEY9UVF(K`^T=#R1krE-8#!Xc#%Xh%fjgAwMvw07H61ed7K|zykTG0#; -z?^EjpeY3Dfzuzi4+LTa+GzzRRBd&eN=A|AxYT -zd7cxqu1$YRU;8fLBw>r&a%yS#fvW)l8~vBP5+Jk@dfM0zSXmCON8>8=Z3D~hK~xV# -zR5Zl4sLSuzYl!S-z1z(;+Z|#DGzQ-+l!^S#B|vGq5Js5Fl}TqsQI2?y*G-$E -zF{OZVxsVer{qq!xHJ#_!G6&qY%0Sf9#a%0Ka?8;HK5lCaIR~du?;7C+_?7m&3?RD@Ag;BSt@S*ZG&nk!NttG>{2z5o3wX&-m|oWQ+$@uncyT=! -zv`$LCeBtnUCzvHW3$PSlq&1FaNq5dZOeZF&yLO%Oe{YAQa< -z6$0%sXF2oNu)>F|=wM0Xy6mcnWGO&yNb9^8BRsdC7C7RL`dzEV;nU4_gS{GDYrL=q -zU1sIGIl-?w(y}u4`T-7}(Ep!5x4xMpH6b9Oqp>YCP3V%sKh?U8^uDuf2rdvwatBlet8_S+0&7rj|S|LerbX59h08^;Rd44V1{#}{#h*E -zg=|J>yrqpZH}h+JFRPduVh&qpSlEcs0rN~4GjR2UASS!8C!hlYCaSFA&e9g`FoHyRb+S;c?z7KZA$ChJ#CI -z*>+u)VOQY1^e-wlIvD5V?BS_q?D-Wiji*y8dCsN^ly{y6i%u?y!ML!MeHhVL|mm!-@2Qo_|h*vc|o*>K`A-{5C+~^&Ch=~1Y -zp=)8%7O&GbF$O2B7-jLGE@GAW34=bRiY}Ca)>2`0Q4B$)j+t~J`vccBmbidTNSA37 -z86w{JpDtkGo?Ae-zy`7%e!kVRdE!HQtFS3kd789Gh{KA_*k}r{PS+IJp_xET=sZ+S -z!bX46Cu(`0TAi6{iikYDjS~>x($TgZ2t1NdQY&3{oTqwv^mK_;l(r-vxX6lq6rBnN -zz??9kY}by>&VfLMPJ^MHtVG>J`Y4d?j=s35t?M8GSvq+EZ03aC)fkAlrC$32(}2p} -zD2N!amo_vd?H|F_g6O&$05^u1mfz5)KAXaRaV_Rs)`O2e1Np6n#@ThWvtHK6#Xohq -zoUwi1vRJhz~ -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 -z({DIq_^~nYvW`N8E -z#|`7q>5lAC$d)-GS!~(JRCMb(1SnbK`s9k0r+&N*K8l^ek*5zjX{+&wh~O<}+v)AB -zS?!@XD29;%5v?pyAZ>faZ)V|K!?9|wI-)6aC>$*@xvGq>F=TuO^@<^?!(imw*NA6E -zY9}J_U}9-fO!}ElFF>7&d-pD~#jbd8kEmj(XS*EwnU -zC>Gf0NUV)GV(lPq{NmG}TOOlpi)x*%<1Wav -zp$Q2Uyym>_Q~B!bD(I8SyJN0rjkG9&PR?b@=FM5${<1 -zue#dW_?6lUVs7I5Tlp4C)0z1$JLVa~(3q4?+{7*DumURDdP8GO*Nn2_+>l3WJtDRc -zX+J}XblBSpU(nb-v5i{SkDnl!f-tHT-K-oGsi)JBWh_b0iH?ptr~tA|W^JO#WjH}N -zNXD5^25H$yQOJ1DO}3`%97aGQ!uKKAVFn?DIcEwZ%z(a*h2QkbwLHs8qPT>ph8y1% -z+(U%oX-tB^{$(wYPXbY!l^Gpax$4ps}eyfP+E(41I -zjX-k0j6)dmc=)h&P^L%rIGlg#Q;%N#+=RnX4~-bB*waiVk&h9CeOeN85YY~udrvxe -z@nc%xM;*CERSfl~H^fb*Q?F`~E{rlYb4yD1QTrdobsBmMVJ1GSTS3>@T$#b*D(F>6 -zJuR+-jV4{QOyL;``C0}6P;BylPLGQ7iMv7!kPH#vbPa)UmFA_}$vSeHib|PZb?A0% -zh#4}!VVhVMbm+y;iI=l%*kcGGt|fbdRJMqR>1sBApj@|Axk9vyvTal&T|?wS_+O$H2wcL=qt9k!Z2DdC^NeYLEYnFi%-En0kQT}? -zHv0EPblIkx>~gbJS8cs3@1O7Dd#hcWUlA|~va7H<5AH3Syq={X{_v??2sMF1KlVZ{0pE){Cpl645=z -zgR^z2uz^OP{6qT&n-9mnk5R_R!l7y}PbbLF?)5t% -z)S|t9_{bxKsg1FihG*CYNTelRg0~RBlr6G`;m7Ns>h+0|sbh9D%ncmRi*67Gb|QXE -zy)_^AOBzF*SWN4R*6Smpb@)ayT_-(QPOifF|;K`dI{+ -z9tS#Zi=I$J>mvlqqu4rGH#Dv#FUIu_&F^qnISLf>!%*M0`9&>^;%jm -z&t>J?{HsQchj7K&wl__ta+AztqekH`K&nbcV%jf`%Fvihh=BFkd+$q>>L4*Bv+3O -zjxb1H-33eht20Z{`Q9oMKwyzBtj>Z>#`4faMzh(QY;0M2VW!}!$1cM{pr$?o0P7<^ -z%sMMb$z82R5$@GKtQ_>4c}g+qqKze!COW`cUkiOaN*I8RaAnJn3L -zt#GAv&a0#(elSdsNL+)2D+MOS8KT+};iHeP-^H2nr5zcgn?tpZd;+2j*;x2x$=@Rf -zwL#F^F!JEAGI1>>oE<^$ra7NCSys-=iR!ATOhgSdwz}AiJ<$ka -zr^_u90dT2Hd{jd1YLu~hrgIjlUB6gH6qcPZ;Fb9A4f{SG-aQxmvh -zK-4zXdM=G(gxX?0nUFc{D?higN_ILtBGe3h -z1i-c*xh0hPV0Uk&&b)H|8BZ!MA0~N_I~8YbbN2K+A<_<1Abf6|rQEX5tV6uLrRwGU -z?5CFL<;@QuVuNv9+y+0rcsLH}&=5CBHJ-nyIG!6j0?&n%9Y^S(zI@EBhteSh(&fy_ -zY5P+6r4s!@&`c-d97nfcs~KZi@3{U@eU+tAtrIjIPNV`ng6(bItgYppDH1oem}uX6 -z(O9`Oa(k}wDv!65IB~>NE%9K&G9zMwF={{J_5-^$Z9=5O#XwW9G#PSRsKzZJ`ASJL -z0P)+YmpT@UHd`Yi#&;cbsEVk-gs8>Bf>_{{3OTPEZL`Nfs_3lCPacUWeq*xopvoo* -z?>~APr&(QYjm4y{+T~^cJ?sU;f}j_DU`Z59{^qgR4L}?Jc17V>FV#=ZA4JLA9Uqe#Yq#20$6}`_7GjklP-1Tl; -zn3xB>()rohy-CmDnV -zVl+JMv2bc_jz7$*d6FLNrRUy#{WEXRKmW$3U;WJI33nX$vv7rH(q8p}qwM6VxsHvA -zo=X(4uRL^7%PlsF2nol6-*KcTwj=j4#^*;&ytt!ay5lBZP;{y#wJS$u0=*zdq&eys -zz?&_uBfX-Gc@dUedYtFohz^QNo#TZ4*!tcTAFEzP$Epd|FG9?;io8V@nPj#a9P~B8 -zA_KR@6${pMLw=@r4R5V6r;$Y -zXEZrC5{&5Rs<1{**X$>>A}&3S5ZA}ph9X8aKv8WX7YhY7eDKCk_EqhQv*@c4e8TVx -zum!UrQl0oEI!LOMU;*i7Sia-+w-V;%tS0xI@hqq2)|EBVcw{!EF0$Y;%WX~2SegI^ -z&Uq&XP#s63B<2zjQx6ovR9A{=G)3BIc7=7`4I6SSrc;Hzgp|YBjOi$*ZV%$S#k7XM -z&uKvp7*=wiewa}N#$cI5Nm@5kI-!tk_D@=Co#9h%Xi=y4Ex>S^ZzZ&-yy!6O#MESD -zamG6$14Fc(Xkgl)j|^n{Su+rWHh}Idfa_sXVlEu*6S>f-?q -zDO*Gi!+36T!$1(Wad0P+uj#aJHlo|Y47IZXJ{rYgx)H$g^NZDr(vEFoCbM#^|oAS=5Sa|z5dPue`2D4&q0PBP3~ -zHSM*D#48yrgRCSX#v!L2;W5-^G*#uBjN}{#7t9XvMkc;n1|4D)8rj(>#>ugK;!ABa -zd@OtTO$pbcVjz4f(j{?PU2e2@hXK`?%(vORYjwp*n;IqggX_{y3&Pwz1JegQs~g|V -zq^?c)F0~uYkz8(ckU>cV9BWQcB+=eQ+eun*5dndt=?~o+HlJ+grBkI!ZR9t7M(F7} -z)>3Z#(6)E$ELvGvQorYHU9XAgfrX21mpWqa=~BbOB0%0S6R7_{BbLFOsBkD!p?Yw1 -zATqLRM)Rf5+EIBoBVKD~UAp=gv%rd9U_vZ#TN5FMjPc;(Y186MaIe&g1=q&MuTR=g -zaWVjpeeH;JSTR$`LN^Y(Sh8_)U{E?l>3uwJwN`05U}TY7Q$-m9O~n06)npvhkE?wn -zbG-B8cdDZ?7B**_^QzvQXMT|%m%nWu?CR}B1&%5>F&l> -z3Kb&Z!q&?8R*BLE6Vi9+z|G%GD?;@^)QkC5iAa2j7hYS9KcBN+i26=OLZ?sLQ*Y>r=#F -zk0E*-9SPw&<#xbP=cVTqda0^Ej?#rgx2EAs&o$+$F08yVr`?mE^wdx*VV)H0Gc#~r -zf%O}j}qt5DMd{r~EI|`cw>0|*^k+L{-p -z#UXpZ_r2^n`f(IwiAPw1Q({CC}%9%^x^<65(2{M+dwQ+@)NVdsKwM;bmTr8o%O@j^r -ziJ3I>7K+FMtpoNIv44FQVx|#|avvf6nPrh+Z_FFuK(To(4rRe{2PK@_TB$^n)v8`9 -zFg1qkrVq%s?WWaaHYXwANgCIqgAC5JqF|^By0TY#Cv_Gmpxa`n3C%_aYLsW%m2*Cr -zXR?0tMJx*E4hfBQ?m61gTs*N2O0f}wTNnc5$~r%|>8qwY8mA{9aVhF(@dAOul-6W> -z0+c=``)KFxX;Nj&@WstE0D~Pj;#)r=UmbAV1c>>l(b!S6(iu$Mj%`~tFP@xSWkD6N -z#`WY`T^sn>#-EfE_HH-)>2d|>OQ8L9 -z`s1B$_FdRvVHV}^!m9aoP7$i(O -z{tH4}8F)LGYNWF-j29_Al!i -z*c4AlaA=|LUVL;~ZLp4vqv=-k$HWAYMt}n8d*|%oS+(In(khSg;O36!7Y}(@Yc0(V -zXCl#0@*AHc@?FLcS7Ae&4TWl`+GsSTN`*L_IMRQbd*8w$d_T%G|P<`i@2(c_~}{)ZY>~bMP5x}EyO5SlZLD4;{H8Dqd}Ui;ut6g -zfoMvT#)6=L=!u6PIDS98tk@L1GJ3-=vXYW69g8N|2gD>rqsEN~wv$?y>pFZKz6O$# -z7bjp*0KeK4*2|SJx-8kr}VS`_05{acfMC#E4ZciQUmD5@r -zKP@grY`CP1O`(fexnJ&*v-z%|19j|hIlW91QGg%5FK!(5HCy^Jl+49T$BCSSQK-2o -zi**!=)w_`NxleQ%Y@&m*u5NhnYL=I@LZx}=(A?(W5l(qZD;CEmw`_om=ykvm3(fEz -zWVfuD1NsG}pmQAY=+<`L9l!4Q%8F3F(;*@aeO*ET3#t!mC?Gj)A}5v%|& -z50+z{mczfPFO~)0A&8J6;gC=Cy0x=wd(=SLU=AHm4*rRQF&qv#IXLEj-dX3Lw(KFf4` -z;6X`5u;->N|KTD95$21)chSX-b -zgbLTmVxuF|OB4;;dumFfC}NlyH7>YVQ^$CN#YUlz7$ZgKN88fyH}>(MRYc`xmDM4= -zEg>ad(b#US5c{$oJrxzZEnQUL@y|Dn=!)F+gIIx+?#)y*?F)f&3+1d$hGpc?b;|j$ -z1o85)BHuU_q5Gz&aSDk$Z0dGPTc>bUIfWu~3Qg>MyFt^|DK0PJdsQO$yZPxy_9uO_ -z{h9PXv;HS1MQ}7gu2Bl8WdZnb3d7|?-cfviuzhw -zX7h8A_CNcd1VDIB?rgjJ7Al>bQauYy_FneO7bA9v;?v!a5-x -zchCLeVHSDhRR?J34;0%@JGXc&4y|kD*z?*RU?$5~)79IoFG)jzuWZqMRceEA>28@m -zwb4x9+4(70Nrzp$I5jM?Wf$2-NjtV3j@2`e_E8`C5JASxd_u5OL-=JX?k>*H*mo1j -zL!gB(vsqJ5ZOZ1rX8VJ&&a`86$a%DVA^=k)Pl@E!1ow9yM=yWz&iUEpgUg2(_b>0$ -z%L!>}$^r_NGZ~u0b51W=AH=ck^v^h+K9XNRuu~N<@@8HJwNUpHQs&=c62)_O%In6K -z2s-vkCqhOD!Af95%FDEY*25_fZNY^~B@rl!J`wGd*19yh1e!u?q7#qS72axPRqD(! -z$aLt7lO^;YQD_O`X~;CC*c08f8F5*#6f5fk7W7+GErk -zJC3)BGUMa2dMa45;6Y0}kdE#57`G{qK~ -zF=V -z`L6Ea~W^*cj+Tc!-w08Ou1G!8?8kOySTi_l{VON^7Tut7;_kX>UrPK|ub@I_Q4fGJ -zc#&!Tv6@cz8L`SvmlG|r$Nrw^dTkdyKWgrwncNb`Ogqc_X&h}MBp{?xl|=)S1L3R? -z1y}+`yQ!XsnVrM3ZIm|ro6-=42|6H5WagODi@ok9Z!ZBQ17#!K;0T3fF6Ia(&BFt^&h!;dB%*YvjU~aAcSJ -zUBjj|!d|NMO7#~3dj10|7#$^|H*YDsl0yoRdp -zY&x(mjA9tl_YoKp$+|vBlMK^e2-`)-N`yG^|Hllb#@wUFMi8C|Vm$`<$5dMv7x#pU{vn2FY7!a214yAO+ejWm6&`5s+VG2X -zHIU7iHu1SH&)8DoopNnvDsi(tcG`cjp|cp?Ijc5z?k*M!R(p9Sm%Ks>)|HN0!dW{K -z{WDKnrD^Q2S<=SXFs5#qTdOS`lgxmPB&gA#3E^t1O50kSLjU%@%p`GAsgNa00?9U| -zSTry>2$x+rp2?$EFl$1LU^97Cu)(L%))S?c2KH4Mtcp>nm?x#TX(xcZYnEPY47mue -z^ovl*>vZfu8QF|ibp+lKd6z?5)G$R4tmWHQtuk$q`}%uty{VJ0LEfT&1vHjJUUklqWwUbL*^NZMj{j0LS8v8ko -z9T{?&yG;NeVNVB-_*=UQBl%r3*SU`7&>oHa2JhaT8Eb4E@mvBZIcbq1;;@X7ze%4y -z=d3$A=or1qFP&7fYk?uEzUqkPHjiduj<8Ons0kHuuZ?$k|LpJqaSk&%FJm^o##zF>eAF6yXwMY!=$R7aA*x9%GF}iB>045-!XTLx0yfi^@Q$zq5bJ- -zm8tr35ay&vGw=o*$}R}a9CUpbm_Cb|XLp`KNR*Uon)#g{zr$u<_jIPTeiw#Muw00J -zhP7chs4VS)XL3#qpV+c5ya=OeHU&Hw6kTAv8A-M;!N<3C2H7V8OH3!4|Fd6ow1>6^ -z)T1NgdzKL&V4^Z|HoQ@nVYJCxTaip|BB@EiIhkLP{neUZzOD0P`)g}{5ePBA68kH& -zzsgw}x`jbY;S{bar?8CNLhTfgA=eh##3{fR*A`ap0K0yQLMX>ZWL^(Som=t;Z7}fY -zOHnW=#cnBCx+Q{qZfWb5s%TJ32BpC$)!?~C4N8Nzw}V-?Yq!)5p6do=U(Zt?jI8 -z`?kiutsy9Xm&mKecZ@c^{PBJG_&)sYy$>^HdTQ8u3c;fts=PXBUM$M?$7Xp^d%^P` -z-;$4S$=~8z(tV1^)$rp>@bM-1+j|LmJ46*^%as=tG4P8tLN;@$rTDTYDj( -zT>T$3%+ia+J=WbB6cdQEzbj69+)bn|(I$~@XxVZC;4>m1hgdu8?5q;+swV)z!&Gv@WLi1zhaZy!JQVP~Df -zGTla!Q=w#Ayrn%++2Y3bybQZ6a+*2Zw+ed&eBbo6Ojbd8+uS63R`cW|ENt%xH`+zL -zjL$hIOh9^0ob(&TqC`;t`73X|`$RQqfFlPzcr@<=>)GcMH;*^427GzwmcnDK$rh2eAtP4l_xTH1)4miCS&Noa|4 -z6>QBJ%TjYp-%GmOFI1YnVb3U^eJ8;lH8g^ZpPy7|93wI}{>!wB8F99#oMX;IPz`|$ -zS}c03rpsni1RdFc*WY_{{^?JBe*Weg@4olOr+;$(%Hwxloxk&`ci%qP43{)`+a_9j -zezGpt#2IKqbWEsSm!7}%@CO+N`e6pqTY6JciAXf()6yRmf}E-#%sOw&O8zSb^v-ws -zZ8V38`SXZmyxy7zm#J@K3y+ruZRRxS8PJu&*7;q%ZTgSUojyey>H=sO(pOl|Tdve7 -zeG});K)}m7w8QH|MEKSP3r#SD3WtsQ0TJm*dPPE2ZSrN_X=HhmIIL-jZ?JT^^8s`) -z?#vcS!doAbb?}?RQ(R;^>z1k -zX2_-I4}$={%*ln<9zxT#g|l;rRKiG&Q(ip(x7BoCwx;n?Ht7~>h;O-^0_p-fL7JT- -zH>WT@L65Ui!!3>t!BU4i#7}b2iNSMM{h|bBCQ%LX=9K -zRwfRkYNu|I7TYb-HV%r(u$T>t#jse8iV!l6YqD|8vL4qIyKxO2oKekgG|w_0mmx+x -zsOk=?{KH;!g2q+xVXtI7CqA49RojEADmtu64yu~NNwkNPXx9f-tHa?}!+i>eJ;LFK -zz&X(=E`~2nhtH;5e^CxYN{4#`=#^mgw82_C0^tIG;7#Wv(E -zOcRHKn$Ot{O2dH=i5hEUp|5rLL=bGwvtc~oOPtK}#>r2MHDA2L{N5)qw-6p_RcaV8 -zo#|~%6}jQYkO2}Y&a|fn2H`*m$U`-xR=+5rRyeF<(JBe2q|u>>TyI5RCy$F=l*ZBi -zCnNq6Lc@DY$xtOxTrpSdNn}7Fj_D_iRkfN>L?NnRt|KbmR;V=H_FYf=>-}$Hi>u>++ -z{?)WqS4z6j`}8b{4739isS)kpR&8AdX`#Y$|NUS6{_lSO55E6zzyJRC|M2_oOTU_C -za{c@N@cM&)cK!SR`1*r?b^XC_UVre**B|`+^#{Mj#cy4I@GnfI{QiLcyMIe<@4P#l -zX4dWhG~VL -za{Z0(UVr23`|EFg>-xX@+V!{Izy8)AUw`X2uK&AVy8hO$Tz~7k*WaSHuYYj;ufKNv -z^>1DO>wkRx^>6a;53axdKL7YNv+gOK?Q(zpTi?3=?XO+`*8A7L^~cx0^&8i}{Y%%s -z^()uE_1){=qH%ubgX`b@+W-6y{>k<4eCzsmf9d*n|A1@$@Xqz`{POkh{ukH3^Bbo5 -z>-gt)zqaRh{ybjAQ~00%0ln~_U;pc0xc>UrrR{6n_Q%&>|BdT^{Y%$h|CQ^nf0x_7 -z`K{}J^R?@5zJLAAKfeCvZ(RSIU%LM0uUvogyVu{Ow%_~U`aA#Z`uBe0`uG0m`a8dP -z=lb`4<@!7S;`%%P;QBlN6%~Gm>hPZ5`?uG>_p4OJKmLFkewly$<{dmn4}a(X)*m=k -z&{4Vm_U~SQ`@7fQ{_X2;fBX73zIOfXZ(V=;{p)Xk{rcN~%s<}e%72ayzd>L2{s-5; -z`L*l!zjgioA78)!P5%AC_51JBk2}}z|MK;3{$IHK-Rt-N^XvD&K|l8Ypa1&*`~Ls* -zZ~s+rr~P-on%-$^`n~`DuYLc!-~Z$9|Iz>W^WXpD|M4Gu{{#B>{qO(L_y2hRN}1;h -zDeh@v_TZ}4KJfkT=m&mY9ylTD(2WS@Fkp$#;lO^fPQ#f<;D&OT*Tfys_$R)WsrVM2 -z1F1!0%R0qn>89m$AeglDK-4ccqlXV7{SCxZUO+ta^FP#pcrW)sk=*!7cP=g -z(%B=4l5_-if~-FQp#0&^Y&O5Yeb|oQr(eez+fH8QT$FQ-7hXcVR*tZZ)C7#1T(`cL -z?;dvv?B9TPjYQZbPj~p(#o}X)^xs~Mw19}KMltDx&}kqF5lHgI8=%3^oc0seoE8`I -zlM&f8B9ZP4<+6vP7-JQ&Xn9lZwr`da -z3-@NV(XHdql2(X;3jNt_gQ(0$V$V`%!yPcuG^SYurV>`?cKk78dsHR!6d`JnOR&vp -z6^Z|0IsFeY4m%6^qo^IS)p_~6lhLkcosWIK+s}%)U*Uvzuh1t{IFd{f5|jOAv}mn? -z$8EdqZuZd^ybf|5y^+%~jy}S0KfH)Sy`~A0Mi+Sv={SpJ$iKia}SdTs|ULuI-EV2O$5Q<>rq|)Cz;M5cDQ|Zpc7!|(kM-}|HQ -zeRuzA%4okym#XLmX-~WV=@0%@5#RCu-LLKcm;dscfAMes761AD@8ZvY{C|9d|9tJg -z-v9Y8{6GKv7ygGo|Aqhd&wt?$|NKAy&Y%CnumAZk{PzC;_s{;}|MqLY^1prSoB#Vi -z`fv8vAN;>qK>Pmn2fxU|+HbL#_SddI_?P_SUtE9i-(3IxKXHYYzsz#W_l?Bz8~;5^ -zVt<9jv;Xq?8-EN@t;lBo^jm-WJOAP5|HD7|)8D-Fr@!;3zwsY_e*b6x=+FMEKmE-= -z`@jC#fB9$s^iThLbol0<{X^>T2mj%p?EmCn{>iWZ$v^*-|NEc(zfb7s#0W0ss4@_K -zDI&4}_DMlfrh%jH)wz&4w&{su-cc+{K8856h|p?OBU#EIPe}4xO_=UztG4GQgMx1Y -zhTRPs4`CrERo66}uaW8&L@NAjSwzhQfv*uSv_Vc%c_7V)VYJY$+Ngt=zBY!~X(3U@ -zB+ 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 -zJUM*OKG)=3+iK3sByu$dy)ZbWE94( -zavJj|eqz5@VX={8u9_DA&aRqIgk`SM;w8=ksRIJ(&JDe*O==yy00E0mOm7vc9EmPF -zLUBf8wr8eMbJlxAW6(KYZyeF@(kw)x+d4XV;p7T&4RmWx5UZct59e(F(9Ovw=-8xH -zJN?TJU3ES^AS$7g$Kkt-R`3ngx_x(B1oWcL56hr~_|&}ZAgYEPt}dZi;}>JZuN-?i -z@ab*JJfap6;x0r%D;aA~Qq{cusrP2153D1^w`-iaw==rCu)ymOfF&*IUATc9o_)H> -zGeE~WdfFjrv>v312m&B{7oN5waX15H{M-@-&gG1#&G`vXxQ{k82GgjO7FF&=ECFrtR_oOEi*n<44Pjgnk?mv7knN|w -z@i5stS>yI;@w7{8J(*>cmB{ML1?X5y`6U$%1H*kwvx~}wA(i(G##GiOGN4I0ykGmJ -z)PNYbYS;aGDX4G1&I(<#B5c08buEQzYEGWM{0WvUz$AkJH3DO8<)JE_!A=h(6hD!r -zKHVYOd=;B>t~;*0Od&%teKRc#orqbsl?&~5tBF0N%Yx{b2-5csqlXjy_OCjxA03l} -zr;*o~IGN@{Kf4Mt0iIuZfq=kU#ML8Om^sQ{9e=q`Hz97IF4!=A@RiY_N4r_tAeg}@ -zPzM{L(NA8Ot=iU{&6-vr^a7nZTb@X^fic%U337lXkc=kAk3;|<+DCt!xt-2aJWQB2 -zPbDtbNtF9h$O*lnOBsL$>B>R-BquG%oiNN#hNG)UPRo9=g@M@MIOkg=fH!B52PE2w -zrr9V6?oMc_ePTZ8KHjvRi*;V-ypS&tEHle*AK*UmY&=Uk-xVz<9okPE2OC7Ol=S6w -zEH^r-8OCx>(rr&5?_ns=Wvbq?L_t1@rx3~=3ltRY1cF)(${9chisn)lMEHsZdryNl -zX^^U-scJac1^sdy&Kw@< -z=1qtR09J#N6Z#vLt3GM>l49 -z-lM2x8D;v%+CMvgB>PZs1Py4bVVpUr68$FE_<@6b36i#rL8V=^U=n1%qBqNn5apJ3 -ztL||>&RqoiF%2d0B_}XPDk5mX<8-t-qg=#1Mq0som7R%=6&Jwr2*|pv8_%j-`QelFPeVwimDbYsU`PGTG7#{3E9(yKl#M7kY%yuGhwkM -zr`J6Wa=3rx6Th)0K1AccIsG)>bgVlIWM*ome+V@?*v)7|x2j=;afH&k>YA4BqlH|V -z3Qcov->^<=%>$HKi%YSKx<>G%13royG*EehB-UM)jOg;5W|A!XlK#tZVjSUe(nLV!Gq5UyLCw4ib(( -zO%4>zkZ9#P%DmAG18pR?#|5b)G3DcmU8tL6^e&4oF6sS!%4HQAX+z*H<%koK-NVCN -z_4f`Ob@jt^>{7)4)7+`t_glVCP{C}SE>q#Na0gMUP%@8+<`ex_GfNg>*!bk^<$!qc -zmsYgJbNUy1JJ(hu^G_VPNuvQO8o-{CKtp_nnD?ZR%a%q1(x}9K(&1SexNYxM5hwxF -z`l8aEqhBphw`N`P3ck5L)MtZ!yMpfY2w^sj%xy+ra_nm~J2JZ}eP0j|K_4CEW5lns -zkSJpMML;TTtjO(Tr1g5Hy}4gF5u(~IjE!cnx6usDFW=VrvHi6*zXD}{CH7Zlf5C;* -zEeu);r$8i;8_mEi)J~z;IfXWH3IqY&Xa-JU*H01jlpD=pQ0m;0KWGa|w-g0~QtXzJ -zrCZ83gVNS5Rnef73`&Dhs=;%O8k7caZwIq(*KVmBJl74zT=iRF7dW)@3+-$|+Zx%{ -zs4>45sr_Z=5!+u$|I4m)YDY=!dCU4=EAy+c=ccebQQ5l6K2h7&+Rm!BZ)@z^8bK{v -zgVpM%Cq&_9>g0u!*sHzawX&f-`I+4;FBNiqAH&c?QrRI%9dn~c -zdx93eYHn`lsF4*^mLIa4;FH+F0DUiRN_2_a?1c4qj_2%l236G0){e@6&iQo9+rD^m -za(4b;c1r(0`vgbMOM?VTR%v>4K0CYr@b<>DV~vc(pniC9)CP%6B}?;_gC;+1{Vsry -z3gM^2X0T1z+F8H6M>>@u`yKh^h6Q|w?L|wBRdeeg1lxmB#9&7oP2Pax?Pc(c(OE8g -zdk=(5-W+cv##W2l58F~B%{kIWwh&QOSZg|#^b~iRNS6pw8x0i^GK3gq? -zy5uJd{`d6Gai+b(fG-@ee@kf4-U(t -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 -zx-w=Oj~tRV -zv-8W#3*v}g@aX@uW7k|id~t?F*fsffN4LHBN?*_7pWSA+8CKsz_c(aEx!M(5G~Izb -zOqE-@xa*~B{h$+-}_g)X1mb^g7AKwhJoU6!u=~w?@f-lUbvH=(xXiY -z$AugG-hEXzNw?{=Sq1%ms-qW~w?NLr>h#bk6gZ-VCC3k+xH!Wy*H4#m5Dq7NhW%ca -z>!;xbkebtg?=KhevQg$FJvt*S!h-I>s^U}-&5@@8B6gY8N}qOZG+LcUmxR3itu?g( -zUZL7u0> -z)iyyw!^vZ%WSOfACs^>%y97^v;O?b6RA-A0K)QOfaoX~=$^~=QM -zirf23&&~Zz6-&ei6RzJ-qjg}V7j~)j)b2mHn4DBe<@?~-PhR-{10ITVY^?vKd +zZ11sT>uSUHY9;yVgTt->NsvVG0X6`#iWRf-+cy($c6U`DDPpBFT|goMfHnY0pa1-StyH@BBl)-F-L6_um@UvYgTEzeC}_5P&p1 +z(}3T6x7vO8wJ&rF->vq)*{r_%_rLrW(EjPxF+n9De3y|?e)r${E+dM5mkavZ(>5KU +zEkOJJ`|rP_@SGZ+GjorbtDC}-FEf(O64JI*%yhaTEh(s2{OV_^#+u5KQl$$d%Vosprzj5ma}KmL5>BI}^va?VAeaeOOsL8PQgM#wbL +z7!H++0ouYO{3<4CLtAwYdDa$~gJfD$>^5Y2#dS}w37Fd>SwVAh5%j;(=AbKpys)MOq+k@ +zSr0w^3rRSy36ytz0t3i0jUY>YwU2S*Z{YBL)o5NsLN7b}f@ZiN@mENE1hQ$KO^UFMOiIlhmZy*H=M$hsOs$?RY;d_t%1$CQUO>c<&)6Z8Tx+^SQ +zo0AtzxQ1R_LQ|cl#UI|1mcv;5$~@DKr|grAr#&tS|LBYkwB{YKp?Sf1QQL<~pf?3o +zXF01I89!h84h)NU9Op!ml9}3&C9NW`Y^s!t&H_bRvQ7X!r%DCDJ}G>@g6(Oaj9xhD6q=CIaqJ!c?`lK)@!e2h$`aa0y}2;1%H6K%$zn*o3DV2MDtWBA^CtNHjOK +zrTEOQ^oh<4m`R*%0%j!p(YKP4Htkzvf+_D?Wr+t7fwf6n`OaH|M;u8(&7x|HCK!8A$cQanYh&X%YrPdOwh0UD?0%=EwIcKZ{|9kmYk&& +zCO*oT651B5r6$dR@t|~xGo}PaWMDXGIwvRydRfkF21nBs!SjJj+H^-#`xHeR=%cdF +zQM@yCL1<_Qa?=-`(5pnJKwmIrT0~<)Ru*KJr^GRV9L!L|+ezlE(*;!~VWr^reuky$ +zGsaU=*C4j%Oj)eLHp1YQZst)a{7fUz>$yv4$TH^kOUIvnuBNAFKJ7PT08wEwxPn^fmiOl2(NP{*q~o`1Sr# +zr}gV4+|Wk~Z-R=2UG8C^Z9z)9f}-l{$iu>0n6qZq%nHq4up!jwO_O@yqNE)Ko6+6< +zEy@wy5g5&!nU~Q_(GE@u6M@=ZJog?(soy7}fn1P=u0!(0r_MfQtM`Ic +zJ+J_)3L&hdb!QvWu#hrc2AYa{iCF=Y(ju3#oxN!Lz@#Q^*DQ(aVwSbJ9wAIO&`wHJ +zNd&vJ6lO?|01mUbO8C`Ha5HJ}3pA`>2gN`cu)8V0O$$N2Xn%4k9#TMuE`z+y +zq;lp`rH8pe$8@Lzx{XhIRLzS`Qc|BPSqrQps@qH5Q(9++N}9ru5VZNmPMO0Pfu(Eh +zlzAzDdHn9*s513hj)sy+^OO?9`?y4{0~1ELnsQ`-j>Sv_Eo5$nHEPQwl3yR$E$pog +zvv4+yXY*&}W +zr@OT0^fD5{a&htXj1fDJGp-2Odn>sx8AWgY0ZMX{z@g<1sx!88*Xz}S?K>`4=GXn$ +z(zX5F81O{2LM~-$)CH*M!D;QNXE)o2+6l~D4IW$ +zju=R8Mgk1fxl6dA(njknBp>S|?-seK@ZypvsV0v$Af!bwy~;i@jK-wFf)Y;p8!L_0 +zvWJx&wI=6rCiEBeG?SL-)|x)lfP4>?75M1GFqIezMv`j(hXw>5=h_L~)d(%?I%>29 +z=|<29d7HLxYBEMMlq0aaX3{kSfkx4m2Nb7xz^{2zT&e%VByOf@r)MgGax!Yn08;HD +zFzJz`z+vr7Ymg-hn>NGOw@fWGWHvB*bs+P6oicd;j>&&S4X)#?wdET4I~4nv8@#4I +zxaDT*4rZYY>xlu9ninfSSJiy+>Gpcl&|r7N#AuV^**Xgcj~)(Ma)s0rLmcB?&H3)0e=w*9P+-B23> +zf&4&xF6^&`x9~a>c>oq98shVoo8lgrmF9ccr;ZulIHp`bbxKCb7n2%R9z#3$=04?s +zAdCvKP$eusfawzGx#^flv5HO_t;@FMGWu10Ch9-$Rn2*&8Ka#eRR1oKpUVLZ71)g8 +z85u3I?6kV5l$D)H&uYywbQi8*oMFeJy^Te*pAlye-%dkXuos^(c4NqEbIX#8c~PG^ +zyYzXxKi+&ME|@$By`w%EgJlGd@Z|#94Vl9_%ES%GxGz!*HONr{MCj%e%_QHMRv7)k +zxZ}>ITawIxv%|ZiXKiKyHf1)NuxdX_TGwVQ)2yBAx@iptwSHGU_-X4?#tmkWcmvWI +znYrr|bT38mVp}s>SSS?K5_HOYsQFblA{~L*6m8M;HyM1Tw1=)HVA1<_dTHJfTgr$~ +zE~SV=$!JdcT7@jqr=20288uIcv$Y|N02r=uxgk?fo$Wi=lx`CA=`7Xb1Ie?qfFS*E +zRJXyhmYl6Iq_MPfSx6iYJ4Ig>VcSi&88+d9;^J*>V5>j<99!NYJtw`dZ6?!ZV8mjj +z5$sy2K(!NAJX@^T!|q^Tvwuc6$UH(a@6G$9rX6cKvqrPAB_QSI`bg*SAWqB37b%tC(lZE90oXokH%rkGGgM&0V +z<4)58V +z8~4Q7IAF$!XOT?Ws~QeupXj&0qm@eRrcP9Njxxh6&dlS? +zq{YEkS}(r3r} +z2JAE&cY>XShKQWf`YchvXq(Vs*|fm|(ax`?{e}}Iv&yeHyMLh{*zoLZtLuObUti}O +z3k|t*oUxcK9b+-=13_j{TKbG>(WOm|1R1FUCW>8Z>Gi9@q4ovZz9@X}+iNq+({_^Y +zu4|tMO(Zo#Y&MqdFE(iXqA^oV`kEy~yHC2KiwMDHIt(H}64x5^P0E=oB6kYW;gL{@ySv}l+i#nm>Q2cDTe963$ +z(&ZF&DS;XpX3NeMlwFcIPTD~iC{*lmUsciU(!=t!x_HNK6fBxPt<#r~6EsRo+fp`*ty)PRgs6Xm8YNzyVkPB4PcCt`_joIV~q +z7;8}*4TT9u{YBI4m1TwTx%+Yj&~ApRHJ57krc+LDu|5R{MxH3u7@4P0A*ids=#?=i +zu`+rSqNprv)IEk=tznhCYZh@w11TSs4j{}5EfdHVtqAI3zc +zz_p8LJKyk`MX!~_GfRY_ld@(zXB^?vLLarRnwGog#~MX|N+fv7S^|c^f&llk`WFl-A8T^Bcr?M{HdIV&HedFx +z=*1;aZ&GdAcqXA*H8-z>Q8lJDoq&<*9Ul#uh(?jF`0+btLriD6?nFR{L0pVq@kQbD?Xd%e;q5|s^hQ{Pe +zA_ichX3LAb^~xI1g>gy95OuX8tV2hOAFT>rxhiKstSt`@t5{w$8_5K@7K}P~Z~^2j +z=}=G=JT!||D~CynAYc~3qcUF$NQu;aKxh(T6BIX*IMBCI9JS!p1qI6@{I@&E2+FQx +z>?Mgn+BK2T7)wfhQo;{ZBh@^!6VRsimo<_`G~F_IVIXW1dIie~=pMJ1q7L!;=1IEK +z-Yg)-Q2g2xNklN&LJ2HHo8V>5Do;6r_ZZw~dn8HDW<`^fc4JoJzO`cdY(Z#C(mH1m +zsiWEhRFk&TET60L4J3?n1Zr;YLE{8eO)GWNX5Dz$tSly3b)94f*U3iv9Inw2$(D4e +zKSvObK6hZRL^+jBgTatt`4|CIpN%#w!OxymKLVCwmEzGbsqJ%hBka{!Z4}jP9`i+0ym^e +zFninqR7S>oc?C1HHWskq*K5nThsnPFo6{-4F_lf!y$MK|gASI;Q3jk;j2$dzs%nx* +zt-m4^bi2H7fp-uOKv7`RtUxCObG!V*oTm2IKBXwkZ^avwcPum68smNnChG8bSm`C9 +zbrGf?V6yTp<2th`3(+0}n*?bA&n827U3$t-KVv;$>hhje9 +zjvZ-fJ=a!uUh}JYnpJqP*%St*;9~rdWWWA$MvWx)yhLZmV12cP;Rc8Y3*d|g4)Cv6 +zVMF??(>e>&K`WlWWsL-X4PJkF~*hl*+NyL>KKFOTy%EB +z@@y3Ef|BL;>utG|?~d(@$2p``#=i +zuOu7SPvmwc=!!9sEEj3x5KLslLnPdLn&~xV)%7=+z<28&J%qRtI|Ab~3+GDcB5hu# +zXRV-yc$pmF(mQZEcJjq;15cdwZu@lNpCVvoi0v+03>7nR9JLy&a>2T8yQDC +ze(}=b#x{uN-Ul7%IFTm7$V^P40^D*^N$dBs1SJ<7^Z>C4f$7bN411xeEA((Ob{3_n +z6?W}Yl=X8QpvaFAfF%oQP9D>_J;1s!S+gAruklj<`2DXX{0Bl_i64LUbIi8i?sTK) +zV}?h|7W#ad+oUo<)C(n38-14dbv@I2PBuiqZ=P#My$!PfHG(r`qvaN)B_(CeM@0!o +zmhnLWZkU5^@KF&cFkQ*yheZt71L;7?|FBqqLIf-K!y=vn>r^&0;!U9MfF_bVoZ*CHJuu~^~ +z?GiJ0c){l54Gx{xdrfEDt`NcitmZzobz4f1S$putr?x(|^Qpa09enD=CC(r7EK@dE(lXhL3@?U))NbBj_*LWm +zleiZE1$Ll)fPl>-($9bN$zMy*5^7MT(y|BT#wt|b{~FaR9eW02q{!TO!)(}rIc=HLubc-N34t_LGM>7XM`nUPf4fz?z +zcfEx|mpYr29#xk@81&J?+&s9HDZP1^t>FjNrRF|mOHB`fZ8ck9I)qA%b*h +zAaZ91kaucZkn>~f+z*q@Kj&`pE|V$FXO4<5zx?Gd@whjdYNR$fIb$tu=-M3ELD_iT +zO>%peGyO9ebaU!t%W(4rx8QWvUDbmdw)##2({$nwfa4}YiXlk`Yz(lFHtO;0Du{lP +z?tnSot#=9y41>N+C5&RlUAMF8t&RrAowQV%bAT`|=1Ca)_kWu}C_H_IAlBNQy|3AT +zd5nrf3(}>{(|p*N)QhA`5omj9Us{liar0i$6SY+bwx!5I)-1@J(2*Of6e}?rSSO=$VE-sz(KhAVRsO-Ns76D)7q8U +zYSW$mlMV*NqCfLNw0eN&&>PD~Y|c3aY!>Whn}UwoRK|<*SwQm~1mNvtp{4z0sjn<4 +zXf>cq2%E=H5}O?C@72E#W(-x#^*s#8$5LX8z5)%K7c%)jxpBjQr5XB}`o@&}g%l=n +z4uf-EIgr*O;%A;qq}6jNXl?-}5YT3@{{{4_lxG{YJs~?p5maw&yBe|@*Cr`(@HEZ1 +zJZ&?#?dCv*=v>k~ct&bgv`s+4cnPcEEGE2V?laL{XATZ?Gn;f>pV7!> +zGv2F2KrIbpq~#5pwwkfwt7(T0Jc%!jpt?7$TjKGmKQW%{JpXEUB}_M?rWV7`#qv9B2068y59=qAeyl4IRw; +zglRB$toex#AYi#V1I!fN7#Onm^)LTyKsw4)->YZVV%#3ye?m5QGUb&YXnO +zZBK?E91TW8>e`i~ +zXm~5e<~GE}PUVBrmJH@O)6%d=6$ZChSmciKY}OM|43^h<$wM73zGfL9xO65_KW|Vl$ryNQy{DYdkLU{ql*%;TGG%70G_7G +z0Abmq$|AK3DS*%v237GFcv}u6|L{A5j$-D=Un~}v3+imr_~Gbn@mn30mw@8-ThhpY +z3r|D~64XJ>Rq&vpqD^Wy@)sW=7BvU;@xx~p*Xi(J=ru}5=Bs6u3koz)+i1^^Q8TItthp?4TmB!T+3Tf% +zEdiUhaZDd$f*LI(sh&KtXl_F@bSiJ2;PClYkc28tl~3{fOy8dM3h;pcD5`bFr+Bv- +zj4;G_fKX?enuw+Sw60)*R}YbME=Jyqya%34r!^js6stkDHzUp-80+RKwOPEg41ss$jnSsTq5$#U8Djeo +z89g;I2R)i +z8_jd=wtVv7UVvqpV7Lzx#2iL)E9$|M2N>=F7yz$%p(7sg;?xftzou%gH<3Or1swn* +z!jumBH@uITZJ&qF#yW|%S}63>FD!St@Z(NnMeY2(5)2*hr_SOd5U^?zlH)XqY{&$y-gJ +zfKWRvTw7WH5Gl29CO}stdJw+<@fY?!6;Nl3dZI~tjK!j^^f9=|Vj^w~L7&tC-_|vg +zV-uioy~h%ntT7(0B_Fne_XLrI#fDo{YEKgu^EhJZO;0uAwd`w2`rC)C+>X|82lsbLf<^<4Z3$YUi&ZV#9hnwxSt_b5q*%*>SNp_ +zoe$~aMf~`2DF>k)%i{M4Z9!7fL>kk}hlqf)#n|M6ug#8@zOp;d&*=kv!&rg!O{Kv* +zJl@P!c&*mQ#o2leiU)sO9~ESkOrwM!VVc`7J|eU(wV_NO)_i}DfX4m!#ocM{Ih}I5 +zw|K^t9GR~g)dr)v(={K~ROwtFo^o_#=-4yqcj%z8&Ksd)nI87W8ryS~&a5-$32LSF +z+bf@&K)#RBrjqzwDN15oIN6ZVrn9$@Ene*C;r8S&{?oCjU-zmxKW`>#qlZp`?M^cj +zUicEVGim)nb7tMwW9ED#U;p{>vkNea28@V}jiSeI%tlhDk4ILE-Y`)(aS!pVWN2t% +zIPRryx*`bT8_R^Yp=pp!8gU%?oG+Z@oJ3AsYIq6kgkt +z@oS5x^;S=?|NIy7CsllH{?PtjQ?J4yCy$V!<-h#?Ys0<;nas$CLdKWlzE13P`T!#q +zc${Y+2)qw*^)1R;M1NxiyzBlMYD4kvYaP4%tiS6y-jOYu2l7mQtKhSURiCgF_i#Zy +zPy5GscTiQ0TV+n=sYLP +zuyHlPn*p1jyxl5P&gjT0YeoC%Eg+QEiAx>`s4xiAV7C_0KbVgz5oa|5}NABKq|Hq_q$A +z+J~q)>BL0Tn;@%)_`pL^p@Y?Ky_c+Ayy#(gAZ}B?R~FDg4fq?dzpe3jkM4OL+!%(T +z2Ky6M?PDF%?*zj+^A| +zQ|Y8Dl8n{$N2cop3y)QGpPCvL{f49Z6s4M91#Qz(>Q9Sk*U}?gU~;5p&sx)WQmH0+ +zhSN1VT;>Ui*%UI9w^{11DLlfg-91oG__K9BAm@PvP|}vd+Q#pSJR3V(sVm!gxU=$e +zd>2!Rkxb8;&(nFG1}F3Ta@rX0{S#udXUO%bWz +zy*)U~@+lt4n&+Zd@9V2?T6>79Ph+LybF8en+lM|xiEa4DECdjXI_LrcTAA$^MT4L&c2db=_9 +z*_a{HH{g7RavzgVdj5C$;IJwKV@I$7ubc;3x>-x<@tcDM3G_NpZLACmzlQVBZD;Tm +z#+tqvRUb9~pweq1c<|+Va)(wP&^eP${Zu|7;S#)t26(I4-T4@+PpG*L#9S;ibAA^p +z7WONNAJ^1dO_PA%L-QyKD_dCeK*dlrC;d9k6qUocWPiw3`s`8)) +zMb}zaKWdPgJ;A3sece_!Wn+oSa}NS&Ld<-E>j?(8ivPntb3E^ku_xjgGj8VE(Z6`^ +zO=<{+*r{>`3Ul{Vuh17XxLf0NVCTddH=n6Ar|99y57233|`pUDaNd|9O4h@LBR~C4A!st3!v}QxBdl-=3D6-G2WW +z+P%848*XGiLDSc0wVD3LRMt1iB-HC2zMS(;-JdJTa(+iwz_T%tfBE_++_wD#Fzipa +z6(nw0{Qm2|vTsBd2KgH{EHGe6_5v)*LVsuFttJ5qb@za%jXg)MjrZz3dE0I*h-^M} +z!@)%S=`Y_rDi-g9Z0_;B9b#rlepYE6#M8#3_ +ze@Yh`?^?`k2=Wsw{Qeym{2R6(oZk!srp=2Fu@wQ +ziNjlVlTVBujfWAdGOyVU_qCq1DdAm!h~~wb; +zp`TBCQSdwGl0DT$07D17J|~?kQ~GrA3=dHk?CH)n?*H$amTx}6fmK&g+R-O={6}#Y +zk7-~rZwB9vB1Ke`Eu +zKfd&&lJl0h520dJ_mzsYek8+nbSMbTv}<&9N>4vGL|q-2b>wRJZcx2=t}g44mNw^C +zBIJi5=O5P47at&3R?MFCLazI5G*h$Jo@M%@g?K3VNxvc{PEvPj<{OYd4!ZG(qdSk~ +zW9Gg^!@#O-pHY@^cS-}QKSfrg>NRQMg^zvr4J2v!Eq>8NmduBkKdGSa_G@~{(kOU0 +zc40lAiw~-QLnVxYH~PMj!=KOl$O{6PT|MSKjg4qLPUZr1&1bFc8A@rQc{4WnbCF*& +zeVt);K7Y;rYR!I)>i9hrgR`elbMPB%;rGqh@M}D5{-!`*l=uc{KSebK +zqH2#u2cN +zslQ5B>16mks=p3GcBD0jd+B}Fl{1$8r-Qy9yZBJEZt|C9!74dxSeBW~K1?2L{x5h` +z9@fe@i%&}-nKSJw)H*6GZTbkKHroGrmwdkj&;q`ym`sH +zIDoVvH<%N{VEkfL3~$)bw*Z{azhz4F(s=Uxr6Mz#nim9)Wp1Z1g!1M6DFZwmXFd~& +zVSQc>>T~NRz6!_Xk7oJf4{xKpDCjNa)6?fL4ekK^HJozq1elL +z%SF-SLlgK)3mz(2wZJjyN2Ynp-G-&$21_&-${nKXJ=g-Psr@u?q>m +zMW~DB_G*ObWj1f`WHCr)Rq2z5=Rca?KO%d>`zp@ob@or)Qooz#joh5w2urFXc*ml> +znnb^(Rkh8=p<5TWaxd!GDf>6nb=#1CXZ7&lZ>sp+|Nh;a^s3ZX8`&nT>~i(q_UPL? +z^wu@~ZMAsY;B_^)$%&jB?>xnZ{6VPCoB0oOvuuj|A|WAp7LLqRKS9u +zg8A#%!mob(#Xp#Dp8{L>hyVA#{|~4uvwVgIF-Qlnt^@&IJ->9n{6Bw*7t5`l7q6ce +zZ=M%#zd%p=n{&;9tS|+5iPZGl7X~h!HuP~JFsJ?tSgdJ@8>Ue3L(48~R*<{iLkG0E +zyQ1_<3kpe5L|}8fRzp$~Jo^J)N3`CW*71rldQ)Gn6oZn*^%m+Sy;8jW0&``;febXo +z+lSB|*B@l|V7%{3-`S-D??GwuqY@r>Y`;kF&<9`+Ly +zh=H!Iuh|#8EU=~uKP>WtPq#dzCH3iqW`gCD;+zYRWCdbPhsd7nMcMGEKz^YZVAQ&j +z=&GWkZGoQ16i`=su_^C_Yb**$-eb2+jaxzLALJ +z2Qc1_dKtrT*7Jt`K)R}7LYQ!XA5y5I-9S2*(S}Pr*ncsv_5%gI*4!1Ac35O +z(oWhR6ovlGi{ghXXqY4KjoY=PhDPnkzSY@(`f0gb9C^N{Uo +zv)j;p1le!$5$OfE+b11N%J}5I+bltn|*rB +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 +zF}$rgGLGsD)YnCvn{SXorv$0j= +z78Sx!DvF1J6pK3x8GSx%nzMy98EcYE@Gc3qx03|@($my#xGeY%u%06Rd$zay!NCaEsR +zj^=dI00YGe?An$U5s<^8v#turjM}d-sfC*Utm_=JuInDkfiK@OszbLXv{8?E%0Y0c +zkITjIE0HZ%<(NhU0~WvHBpMtJs&oxA$YS%M?(m{T(9~5-D8MWdF!TwSDk?%P@k&|$ +zLLKyCpm7JgKJp&b+DJ-p{6Q~hRlMl1EU=$i!Xh9*WMdoI)F2dqlfCw=CNz*Ee&blm +zzM)=>MHRsI*T>AF1Ddv^SEMDpd$bF3roNUeElY|v9E@lLho1NL5=;ZRB}G_m +z&1&bFaRd6ENYHMK1w=z|fq)WBY5T6=s>Mpzhhc083QL@96on1g6R-#)<!o=EvRsMS@zGETJ<56* +z+u940rpSswBu#O_(-naX8kocx&4YTLd%Wd%+Ng@ +z?UJ;>ILe%sLakfVNjm|65P#s<^H +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 +zn>-~|t|P_Fj49+mYa339C +zFN)XGP^tZTA{sOn#g0G@ucD0)1tr?CX)m6QfQo=Fg`OfYB{?Voow$fDUO*7T3n|`R +z-k>As@U&{sLN#Py^csWkB33+z9*qc3(;2k5>(q51bhh?VIF~i^7YpjF`_QoMaRoKg5DyA>VCb5%l%FUuae;1i(~}N +zyaxTl14kaQ637ipO^q;!*N$HZm=$BDp{1T##ut*YhDsGO7QZ?2mqou@<8;pphGAH9i#>} +zfeechNi#4DX{@pLe9Ta1$CHD2Qrq4n?~6O6aS^@FYjVq8dvOU5e67SCC?iBbB|XNf +zL^+VwV6Ws6n*kLbo||GQNYoc};Ub&FKa+tGI)FA~T{me1SdRXlP5|Kq>V4&$;ub{Y +zVt^u+GMMvPMlfyMgC+pBHC_kYFtDZbxKf1y6CkvwXWf!s?{dI0B$25G>TF%f{(8zT +zt7QzuhomHWA5}*>cMoC*vjduT5RidleSx^lGM=2+R3)ZE_ClJ1m=#us*U>Mm&(v +z@z`-WW*EVvBAlij?@2Y*Lls&cn=#r096JoW1_H(FwF49w5FX({MwIf%PlE-5Vx%|C +zQkq2+Fy1S1Ax-r3a2_v7tVG;J1f&HKHnU#t3336GbqWbUtSO%K_6zsYyujELgK}~=43m7a4Qp5vS7i} +zflxdGg2E&`qRmEq(Gra&r@fFAm}B2WAORf?G9tyJ3?eSa1%#*RW!#P`Nv#;guP;qH +zeCI7oF?ug1iLT9};lbc*pwT`pqY2de681-ce#q#6hr2L(FhWxLA|{xB8UsQ2n9m)7 +z1&+rncr?yJ+uBiI1lT&T`ek&t1}c9PwBCmD7%^jLKNS%~-=0JMKf>O1%TiQ{7JixU +zZ`R1lx@6VMd}AP>q9_XDWj+0giE9~QcI|U&_wFtNmKTH|t}`Cuu_KHMYRpl%V~7e# +zy@7+rMvscj@z$3BUBjUU8l^VPNP4CnqO_L7v{NEtUyU#=1MOPGz`aPx6swr{$&YV{byTiJIO4ZDk1u+(Bpq6j +z6b?hI-1XEf2v36W>l?OM2qQ{T(y{#{-+xsSMGJ_$pgq2A?se;@#9Lg!x67lT8J#Dq +z60}B0_Gq3Ve@y7z(1<2tGikM$ml2dmbG}925~Xagrz!Dl#{L`Wg8ns+fcz04MxaDF +zsihd&4?);OkkG67x_(@vn4YYLO?zI8X0xps$0^c1*pQ;F8W8&#TLu>(+QznZZM8)h +z4Yzx*gtSE*TiKDMMDZPn?bdWm)yK@&^stR63A8{ok6T8< +zGO0Y>+Sbt7A%8^jdD!T97<$KCv>@04&oas{N7Q9dHLwNwZAxI`vrL?@Afbo0oGE#m +z2ha*fd3v@bH>ZJHNz$U-GU_4=8hsKxWM5=MTbH7Pu9k8-34{qn7DSeVM)ml}a3g4M +z$hUv30;Eg6Apqw(-9WJ;5;blUZ`GN13Qc+xWKD8u=F3~%3%mQ-CSmNBs}2XJzdh9H +z@O&eo5ZQ4pdN0C&Xb5POc0~BB)jDP0+Ae +z%l;_=9*3tZ!BUtTHklG_gLu0XSdnMYiabk7IpCy(Iew#eE8Cp*?W>xFHNAwi72> +zX)*E7!>;7c3DE=&m7q3Eh(QxW+@ge}&?V8yis_tQ`Or-1#=Y9t$1roWylzSS4hew? +zOiHnjavSEBRH8gg@^-o4bkJ6mpAf$L14fi5LJ@KZ5m9o;AwuhJ^D>fHP%ICExaW-{ +zle8<~T8mI|oKGZDZo2Y%Wg;yfByU|ATpH;Gq28r6&brF*=TfIP;5*CGjCs>XIl1Kpmj3J-UKhL?-Ls^ZoNq0dEz_1 +zh&hqwNW#}5o@Nh7%%>UQak`%>$*rJ{eruZR?>0Um7hlT+#HYXcENd-)S^%Gct=i$} +z7UJrwZ$XUc=|chUz4d=_;eZBZ)!iSDbW*!(FDTC(QSpInq!V-!ZRGGR_cl14jl%Ve +zo43gAETMza9bXNW~McAbMeX>!ZG +zClJ31`;As~6iz3kr3~gAGkqeYga;S +zoLL-87;nrfSa1`Em|t}yT9YYdr=^80*cRH4vlT;MX%tf?!ONRbz#8fjq*;)vnFI$m +zgj~dDctHlQb%;-6(pXTu3MdkkH#M*?F0y?dz@&Vbj( +z2yGB22l2}?+Y5m4fn~(&A<${T-WpiuEqI^i))FH1LeUos6&Czr<%UZNA*$s_72OCZ +zIz(ItNMi}_8H&;OxOX5C8qiP6QF1Qztv4q+2__N3uS>+r87U*Z=|s;1E(YUr5ONy= +zXhxE5cOcaVNw=p3`(4QFH{!KBhH?xZr)^EugnkL{_>`X3%pwB*0It +z?QcD#jF(wIi=W!`wUcxj6f6?euFzxs6G2Og380VZ6qx8avQJ-oVTnROJ2ALjc9cqo +zc)nFhNLO?LvjVa@6tN_V36#F_MRale-s!+L*`g9+*;&{DxhhB$xegs7(?)7@S=-m% +z8K@ii8UWdm@eDDw_ukdgiG;(?w0UsGefc#>3�mOA~HP6T6F +zlH{k`C37sC;Z_C*&Nhu0P7|KYW|AmDHJRS)`aGh0Z|7()NM#ypBP+eq9go1XK4_}BPt0!Uk8y5=Zw_( +z_C)E4-bZhy?pIn!8aQX7yBD=UXYNrcfF?!omQvfkggnF3L^}}Do8;-|fK5UD%+r^> +z2rJ+5kWYZkC(<`w6uRn{K~Tt~h3BN|GsWRs9|bWLLsz_AU@yrtf`W25<&96l@zxcJ +z{0+d+Vm>)-8)C!?ShOqHnvQne!UW+sX-A(iqD46o*A4&#ML`*(0MSED3cEyzdL(dYgy6WFM;zodj4=7yhoB}H +zw4;-EBE{ZenH6-w6P8PMX5d}}4+Q}0;%5aJenr8AyVWU3+*xXQQzClg?#VFavoinz +zvCf|*+r^+UoyKE;S=+Dl5X+&m!8iRS0r4y@F_C`at@D6|zTKP7FM6rz%bAfUq$-L> +zBIPL*A&a=P2xX-nsH(@5$*y~Vit1g+ +z%JVoZ!@OHPuZ(@95e$bTU{Ipe5m9So48vxzz>IT<9y$;KodRPCZLV5*f9pK@5HFZ~ +zP-t~_mQgN1BF2>AOdW4T()x-OP8Gy-(M6*4j=)`>g9uZ3%(4w}_w5AFX};2>W9dms +zc?g1Lp5h)Ig1rUyUYc5|l+%ceeo~IKmt@;RCN1hfFQR#n#5)Pxrb0MQyrfIWqFq@} +zZTJ{r1DF(vdtNy7qN`}}5K}D(R!fPT5uGs80lRXlMA8}2p>X&UcDBZ`55u(R#sg#v +z>;P~cdTzm*3&vUPs&rFH5u&S!CDAq~of=`YVlrLH3sWQ$MoB~lC~fpfiHmop@n)z5 +zVUjSuIu1X@M-Qrh3RBjIi|eG-H*-?sCcfHYpFxj;a;8~6r9`N9lUU13+taHHqguftyYP|u45l@= +zbfKbil!p#xp)Jqhior;9APz8yM@7I9V#Z1$5R(DL +zeJ@D`T9M52ayx(E*Cd7Mf$4Yv1k9A8I*1 +z1x*CW95BA3$f9Dw_bA@zDA3tJ60V^Gsw20s?yuIP3Sob}h`EK8TGH8hT{;Sf* +zk3X%i)aUOr_NI==^nUIb^S!FSr|Pp$e?k}jJ-~&zB8h(+WA)Dg!|~Y+)uHy1Uigmz +z>pcAG-$_O-SnvNBu>Jb^>tp{jeSSwK!oLRS_t5!e?mvDu{~U1q*vHwJ-;=5S`4%5P +z%xBVnes{FtfBkd7Pu2gZKQ71u^P%eBKdK)eS3;-xFrQVWzW@5klr(<)9Nb4k|5^We +z)#dY}Mt!q1#`ww5Hmrg?jR|Ni*rfWzvC`K^z`y#I5+kN3m;h)4Ur4F&4)zXLwi +z{(VlrKHA@Z|M?6*K9gOiB|nyEfBbVm_xIQ5Pp>|He8-mk$AEbue)azGXW6HJ&clx- +z|7?FKMGx`opI`WQ{YSt5`Tm<{`}6zz$A{LxuXr}|_r0=zKJCwIZyELRyZ`(i_x8R2 +z=h9S)*n3IxxPC#JTwxXIlH3h&jYtrHKqQqMq7N>lt#wjANA|I1br{X1O|=?DfdnGv +zeaLZJ+O`+OgNsL_#qr8$4Xo#)nO1HM(3&Q3`OzFc02CLf%ZH#h7D1}DG~8cQV(lK% +zYMZuOPNNt=tos&Ue0HTx!jcnhDY;l; +z;wkeQ6?=Nc8pXyuUo`fxbWW~R>U1PQ~7@>vDmp5*ZX5hQ#JQ`g`&5^lw3 +zT+~~a&ivGi@+GVeAXX(K=vi+}&{5NfRLLLWeL&O2+I=NZoWwrR8FwE?{eaRD%M^CD +zGX@yP!+Hx!r(VF`TQPjC)a+GPKg1htCq~ajsD9Ny)SnNISu<6W>SL!f@e0T{)$AKO +z_&mvFeHWOVyFN|7ee3^yNa&Bh-~asn{pZSiF#1RJ`}4aNv!s9h{%OAd`Od3Ln|(4n +zXJi>|tD#EczyUWz>Zd7R@}tr9=-Nl~=Q~3lqi$+XOR^?;ngI?CouaM}OS_3THmW%S +zf^KJ4H;n0!NnTg3Hnr_g!b@>*o +zg8*eHm}0|pOTH^;1_bQPyt2MPQ=iXgo9 +zimgOkGFnSQmCX@W^Wr;^k5(aF7PS>_v=Ks|MeI213I?20-WfN}2_Wh5_O=!72YVWd +zwuC6&w#rCI42?8|7+V|xFeMgaP^kqjI>9iEU7xKUR%)S3gG96EL>qQee1KXdT^w#E +z3X{n>z?v?vq}=%%9rpbbeKu8AK7;Q?1MUz^8EhiU?E>Mvag*U77IYH*BFVk>mH}Ie +zHk5@z%M*O$YfS$&03|9Bov5lK-710_Yb&HUq&L)=aJLS#6sz+hUHe3aE+|e*YX>bo +zT(Sd3BXy&|$gW#?xye|h_FnvtD5N@GB}37E=I@IO)$lTUg$z^4vn_F)v~<8Y6O&gT +zNIe$wk5GWx1FUuw#5Mp_`MPZrSwl3o@3q~gSp=idW0#W1NO#P)K%NWcb%5h?A+_kG +zYkgB$4tPf21o6W_nw`ARE%cq**=OFQr%4k=4LLU?SJ>kDk%ok41bNESo6q#7l*Bn=220zrS!j|#{dDP@!F9*YiJyiDRKu_WBsQn&@U7;-<3 +z3UF|OH(SKY4OV=|5p@dz-oFTLIu^i$GZ7T&%3^pbu2qM!2iOO~Rc&lo6i!D`FQTNX +zjeW%|#bJE@J3NUz9&V#EZEj6cV)wKF2<1B^%DOY8>SEA9gv`U5vnGyvK +zui8aHebr)}A-S5DX8o+?eHG6&^`iTI?)`kZ5=?_F2-urV&~n@P%GNgXCT~gV@2gz( +zu410$K4C>=PT>^E(fe^(2vDspG#UPBgxb>v-lWz0)%_oQPwJRXFn4(INEfO7N;M!ZYSwrU#0)>FkLVt+`>*J*`xIv@*g%~^_C_*3GVZU{Rx#d13a0R}V(1%)%2DxBbUa*HJ4W11S +znmlPTYS5tAG%1R)7e%e;jDqNAP`XONj`Vaf$U_T5qHHBNhSJ-aI>GZtGcq8bc8OUE +zQJ^Cph|a4p-rq14hse_8o8VE%lcJedz+uQ=9)>h)#OxUPS(C7tQ;SsC45=87X+TPQ +zha+4JXdtzzk(2@FB?o)<0Il|{SFCLw5rm5{|_lWr<>DRyng +z4Bfh<8<)yIqWhHfNQg!$12|tp6d8dS0Dt8zP!uNFBGOs89Z?{orF+}kui^QtZ#M+x +zD#LxFi|lyVolpkM0_6KBwRH4t&X*Fs4P8d8fd%HslB;|>+0cPRdo3yuzKFDE)xGV4 +zY?s`e!7jH?u;f_5BM&r7Pajc#>BFAeS`r>i7{o&_CBMVk@wNw+7O4jp?}cwR2k+!` +zBP_z)WlFb(h@30&1^UpbZOcA%Op5Yj_v=!1YV8L5_n!t;PiL;1=Y6uxaBSBT`F5`1 +zTyNQ~eE@C;c^Wu(_vyP%Vx9E2RDuSSuqRbr{}C(5!Ihnjvg!<$X8wGn`IJ(a~g|rHV3C+qLSG1t|4{HPezARLN-Gb +zBoh86pC>_zkaE``z;uupg@QCkERpy^3Im73>t1gXi{K&!9cU{KdMvGN@hz5CftOuB +zTtf9FzKv)o8^|q0ZPgg +zsWhaJH+Wqzzu!B=xQDd;ga^uSFIh%C86arz +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 +zOl3qZ8{$WU_=}+7zFq#I{av4 +z^VHjwpq-g_fUFu%+=dXpcAhBlFeRMHKcYX=ISZhvTD;vF3gFLMx>=73on!^TYicGQ +zuG^U>*45v?w*LF^gPBA{jEpybRSv>8(~6%=jqwvHc@HMV)`q&*I;@v7zOG2l?OBhi +z^;EN>M=jD9xi!yKth43}hFWLi>p4%2-w%dEs?CS`Ys}y8mxGO19=)gi!!K_B{Gwr> +z<_A+k+!H&LYTEoS^psb094%>B5)*Ai;WMj|*XX$Fa1Cfx-sqM@48&w7A;UmMe%l8x +z+d%xX@q-KUf{1cY5DN#c##SS@IE#6)w2Km-5opshN&x_*)Ugmz+a@7NvwvxIwJlM9 +z;u_ti$0`YecU-2gM&ieoAUCiRhlr3_!X!eWL8Cp0K*NP)zZ&ReTD8H6CmIB}b!pi* +z1c_fP#+LL}Ylc$2het+{G=tV8TVS!31yYr`HZr&^DLA#-3ZmTeKRf_C7n;n?U{aIj +z3?~Fikzcd+P#TCAFD^i*t|GA;(WZR4`u$!1eXoBrYpH({YgB(LLBXGQ`Xi3r^2ccW +z@5;=mYhv_zS9TkwD=wjK_Im7H=s19=Zo9S36MwKatw#+A?TY!RtLmnn7G&YQScQF|1ST%`WdupE=P3LX>+tiRI`o1DCG@YnG4oOTs}u!|dz +zjQiO6Q44g?+XNWcyL^M5h1jxCP-};}t;z%JM@VBx+@^C|-ek2GFuah~iJpDpy3)1V +zOPOIfvvMPzeYd6wCre=7+L?(q&1m>Q>-9?7RaHUbXCmp`u3P4`WIl2F#I<;8xDx59 +z^rQu;w=ba1MykTpGdX=cleh%C0Zu>ATje!U@7++9s3Y;*G_NEdBS=3M+rZ6-i(X52 +zsMMWS0EdunE!;{(&$>mi^oMZW6O|5oz=V+=E{K~QLmUd?hAK5?r4xbr_Ywwg<*UM- +zBw7}k8I#0UBVtq&XWvnKKf&)WLec5Z+RR^wCFk#n9CxvQ?~v+#!Zh)U@{XQP+$9ui +zVjYAzhlpCcq+39^OJV>7?}T8=mwMzwFfWh}+LH*wi1Io`^4Ea55_Xds8-{&_IVA4IdLcv4BH?dQbeUkkPqPzqg_zK +zZ?v;m$O%taQZhs@KBajUjJc>o@hCz{z81)CQZ1v@c-U^0Hdu7?1ebrh-?=Gu^AJ>FB$c)_;<*Hgj@J^ld9juf>II>j +zzi%m{d6WW)TKu$7C;C3#9*IO)DK%1WI$<(P8Xy56dM(PPChL(Jtz*r*$AgV-MQgt?OCDIBQ=9Mf)S;FqJ=8 +z0!i?>5jGT}9brEd9Ar{N4tuFwcp3)lsaor;+oC$AR*0sPsk9~*pF3v96P?V7M*HELc6|e%Ef~?CpB)H-5^fngTEJ3aA|fkRdutC7Efoc|gqq`r1+%1Ny7(S-VF& +z-P=75$03x^7lg`>FjORYJP@0^aFo!XO+xBR5dGP-CvTgqk`H&R0B$X?=1kR-(1QUQ +zg}tT4fFHBsFLdtfO1UhW!#k`2suS*KevoLDG)bzBxD+n^;iB9PC +z7utfLrxtql)u72K;RQGLh7MHBy-Kwe3Q3cRXPJ1W+Pv*)wee1g?x#g@SG%?L*y7)J +zltdRSB%Vm*z}~0lJ_B7uCrR>Nl+QhpmBIS;vwVSuP}K{bQAPm0U=VokHAKDRZ9FUM +zUa#P8ABnbp(f!1?eFDlpi$F+vmaVnq9lq%>9enZruquR2(Q!13iKN4~p&wtd>m}c} +z^^^FOVyv|5qM#fMH7rpVcj1o+Wb++8-20AKhwb@tpZ4<^XnjUAW +z0-<&>*z8+W;8qn5Moz{q>Ba;Nt(bIG6e@);2?N(D36naefnyyUV +zI>X@7mO9i6qJqRF(GxA)bclAgr%)uG5#}~F%;K&?GfH7Ws-ie%r5 +z4Jm>{RPWiBQMC1>T8sXV;4_l#rLCLxu@11mn0mpbXpj78VByHg(%; +zTFxp6M`2UZgB6FNh-|JZiNLD)q%{1l;iF4tA#6OP}7ZehIR@PP(Hpq1zoPMWShpk|75~M +z`mD;EUHvG2h7SO=)XP1 +zsQ}|4caiXpDkJ%BHE19@6EWI>cIV_p^bmD9R5d*Ps{Bo#RPp(6F%p+v@LEI&^|AqC +zRepT<2w02+!Xg|ZO6WYH1QH8ZW&>zJ)+fW(9D0j&m3tv1g>5P!ZZgvlU}?S8)3Gdk +z#*&WR4+C%GX`9qM?$g%Jxqf_0RVw6Jk$M~QX +zgx!+beGFVCn%c-}1t8VP0wb~|&f?~p6xJvoZ!|`g2qR$ano?ll)>~vpb=+tHpt~Gs +zUdj{^zltu%D+5?pD|#!gQU&Tn5~-G|HB5r_Ga=6)n$ZUnff<=Th&oEGPEW5RZBIS3H# +zM+lW@6GMU_1xggNn23UnLA(kM*d(SED8?KZ+R)idABt2j)V5%eHx?8paDF?=s}~5t +zl8srCUgR6mU7-|SHzsLO_=wP65yX1`5VYUlzWBD__Zw8+#g$GoBe%D)RC9YtQAAkU +zDkHI(mcmI&FC5M$=BhMId}0Vw7v`$X(-B0Y9@>XNsKdeBZh@ +zk1NkT%2$d3ThnK?S8L|2xAudp^~%$~DKAhfo2_c*xO+<~ITuuDHe}}>o-cEZPJ`DN +z)-WEfZo{ffdzq@*_w8+Ye=9W&ULU{x{&COmXutoW#W!k}6xyG^0FHxDwSiCjR#g^S +z%yl7E!P|qVACccdRN8zb%xPk4fzcgWWs(~nJgj~pe)9oHM3-Rx$BFy;K1B4mNF37Z +zOoGu}R)0p0colNjp>_AnobzRgU~dW@~5Nd^8vmWuO@zaj~cfHAi_;Pu*0PVgt#&H0`e`4(+(hh +zn~2H+)y5VnaeUojAZd5X1!=FCu5&T1Ir%&TalGlO7Yma`g&1-fX9i-OeTSTNAUH`l +z8T9!x@Q~$h5D`){xwDu=sT1v&FLxfz_N-_047-B*^N;Qkh36!_*i=eQadUe}+KL-( +zX7M2;T6l|s=p>cUIiSQ-#1m0J`$_6aME6LE9!qe`fnW`uqBxY&1e3gWOzm5XVBy!v +zK%}KaW6C(uw&*A%40_>$Bsq-~ZClFiwqk#v(r0dQ$?JnAs3ikxfNF8gCB6Opthi0* +ziQBShH*oXw=Ew;5TihTnkxBB8V*liVsxR7Dvm;LdO1P3pE-S_mG3Zp$2`8s_>koU_ +zUn$A=-H1WZqJP@P#bX?Y{L&A4%tk!K!|D93#r7GjgnnqNzdy}by?`;=3VM7AbGZhD +z?I0n1ZtH2|nzU^->29#iBDRs%eSZZ0rHS>Q#wKHEZl@{pP +z)a*rAA)2z+eu}Kzu<&66YV8Whi`G`o(L!Y_ +zc8hERr%~@&Du6Aj%U00E5DoCPqa`IfH%UNTwxwuMv{POVIS;TJ@)++2I2T?!3$;>c +zT}`xXu2LU7_=N;R926+?x7QrD!1Xj+l+0`aRRRBqd|8m7x?ii=0^iUU6D{*Fr1vT_g2_2{WIUSgT!bFHrUZM)2xJBJosK)~$ +z!za|eD;nt_28b$Ps8OJ&;pqjJsB!n6FL<=*gr1CGrzG)y(E&j60_Cm0BGG;6HD9pe +zzIIDMx&JZd>(!r+OZWZ96aSC5B-x5zlsi0N#ShX95{rtoVXJ51KsnN54!WFJPe*+? +z4mZXSQo*s;ZVab55MJ>HJa}wMun;k~fo+XM?prtHaf<&Yp1hQ=GQIu%{QmoQB`CDB +zf&W$}M$GyIL(&4tRj#U3s-*~=VUUXJDJf)fSR>8~2XJ}O(xk(>60&D?sh%igo6c=P +zJ*;bN&6}x<+qU^xhgB@q-ub{5J!(D{ee{gx*m_Y>xAphWG8{Sde%U8KZw#T@2KDo& +zu;o#^e_We0s9lFpaEC3)y0E4P8|ER)!|re=zAV_B1x!ph>JXj +zwuBUip_<@j)DqaV1$bK2P?E;xo;uTp(5Ox*Xd!eZ_5PZRKp#Zi>sAvnuxF5tL{gjk +zLE!Yzic%I8MAYRoZIM=y44vQNcnGBISN^yHAePM`=k{wqt>D;up}Ln2)Fp!LOmXqA +zQkV)Z(pP}M6@7ILptG*zi5AQvnN;!YLi8SvrYQA>01O-29!+%eQpNvX0={BN(teTs +zp>)3aR7fKI*}q&R)F8bep-$biiMUAMd(rWxdU@Zk$R95X@9BV@FV4e|+f3g>v`6zo +zy1x+@z(3K-_jFsiPV;2xWAJ)F9TV<7Z3B`I(sF_k+4?&WEzxUuGa|i^c)HC4#v{uG +zxRq*dqD)yk>DsjG)@>Y`)lQ4vmf?{*rfhTSrk+H^UGVtn&@G%S7h!HUw`oPH$FZ>o +zvYn@<=904Qj39FEjcu;mmQBEI%v*hgb>@jp{joI&m*uHQab?TF;wvFcE;0tYT@W$@ +z))BvdfB*b=|M5bbH{hyn!&+%X76E`tfB +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 +zj%kNM`i*ZHL8IG4O&fHf6ZP80M+Xs0}K3*nZU +zNz{7KaU +zgd`-U)n;sXRk}8#T-S@~QF|Mf^|6W(h-${R7uTR~-*J2Z4X{TldDT`7!jXV{k!LIk +zN!Fh0qxRj!82iqpV=oBAWX(z$Y>0)RCdLEEfv7&f6FAy|u6f#J&2GfIj(0wS?Zv5FUz +zd;}fbz{fBIl3o?efm|z=)u{(CtZCu8g@si9B}9*Y%vE&&TztF^=|1>S{ +zCt;lg29cTAhh$FoQb}HsM19I}a+^^Hk6QYU)q{TVk+#t4 +z#W}vr!^o#Z{xCn(=cN7&hTn?reoCw_EGEzWkk>N4@g{!3on-3giMT$+wIz` +zPU%H(KKQJW%c1g-%e(Pr`A^sR+T35TmgPdsbDfQPu$s}6cH%ZQ*F9_I{r2PdMU!sx +z=+;mBH*&IiPoh~n`EefW{jz!V+iW>*t>2F9NK>S}vh(`cx7LLwrj5rPuvFDs?1$wt +z81)AU+iANt$pK)VApD5^<0H)P`|#V@&u08(`n36J{XNu;c7Kjwf9!sqzJD}bSf*dK +z>Gt$X_m8Fe6CZeI+UMt0QthT6B*)bTZU6mVhT4B$t^Ub@p5`alX +zLL4pE|CINj?nGip=C&?wTx&!vF<;W?lWb0+@dQRa5}U#4oD7v^D-y6YO5pP8%?EIr +z%7f$XuC0$bru+a0H+h*pjUr@`2y^vN+d6EQrOX47&xFCn +zET(wg#;8bP+0=svqA&*b=(z9u>tOfDy+ygn%oTA#JD}E1CGh9OSGy^&G@?If?TjXi +zj~0`i(xshHdz}t558Eo1LPE_m@rF-mbKz$KzxKxj6pkoqkwlMD{r2Xz^u@n=(+W>g +z3bOVO(U6V+k@Mg~=`7g->>nJRbf5@O3$Jq1R#}UDAdrGE4M{vg4(3 +zdbK)KpE;A@svzPuXaP}IpZh4*^j>!EgjAw4E(+Sgmv=|4O=8scz9)$~p`ML+w8v2S +z;n?QxxJp&}>iFo*$LDo)c;fJVUbZa0mo^LOf$fWLdGl>JB2Db36k8p=(SC1wePytD +zliMX;&Q{X0Ydp|3-m1P7_7V#UHeggZ5!q*;l|n8hkVr;9dE|4WI`*KL%%z%EiC3B$~10No|xandq54ABH8~RNRTA +zHOYx=GtoM$04zHSB1z`;by|>Aji8QF-h$+rvk0=07aaz*D40iroYsM~*EaK2ND_C# +zPfCP-aN_Y%l~}Zr&Ql56M1gQo7ZjzQHF3yHTd>qCXKfEUq!KzCvO$6#c+t}ry)JcDm)m+OO=wfJgHJDaX`zGKQ_`l%jSg7eMlX4=8S${^0Z*$m1C?mPPs +zVbtMgb>AuPR*hw#UlV&%{J&a|2Jy%cj9Rgyxn)=o+( +zxb|{Q@<0UDZ6&y8_%BJU2#0DJ0~|Cw;SMF!ODJuUw538km{TPTO7;X9nTB?vnG7

?72*}WSiozBh~RVa +z1n_SmyjPNX*u#n2-=2RYUF%j&oJb_2xiiAeaImR&q15$3NgqV^%A_>(O{IvDh$``J +zN+R?9EP$r~P`H+$>U#$&?0tiE@+5)9Rt4czi~~BGz65ZXCg^g5Y9xaD2_tda0)>zP +z$SprHD%_ELS@00$o2;c+HzKF1OrK*#^mhqclS5(!yloG+ot$D?Z{ofy9knOyqYyRR +zKDrqCZe}UbJ?OY}iIZe}7kbxC+tP2Gu;zOmYOZtO`yO)ldW`-UuT#69dCT>;pc?O| +zG1il>`arWU$jec?IhiJ{BTFZK({)%`PxXWCX^|a$RrQx?#1D-bHnwi~q1)!F8~P}$ +z<9_VSkgDTYHon@}AM@HDkFj4_0{v&O+LP)}DnIsksBX>6x;jR~@ZryDe;*`;#UCV5 +z{L~zYTEXzpb&N`kt-^gPg$fIJ3X_)S +z`AJ1UzwjITP=IL)=4BnkTot@mRF{xzy3{QrAx>DeK`V(MC{s;b3rB%Kbu50Qbc?X} +z!8F#;8xXgIbRf{;}+sY#}pm4a=QmNPLSMDuj^J$&j%XZ)}jq& +zMVk#mI0d7u2OhQV~T*DwJw6*iyD9(g}cL-vfSulFyz-iEt84Ft{d^<_C2*NlMEhYjZ2`M&kCkQDuET0;?AB}q7q_j +z3Fj2%a?YN)aETD!02KwPh~J$A9nB8bvrkk4hGv?4rtBXDqR|bI2fwM|1n%75(R{G7(oIP +z8)?UgK=S3BUJgjdw2@g(IBCD5;)+J0;CpMIUWq4e&Dv}`GB9pO_wqWr|?5~ywX|I6SbsU@h+Kf=9; +z3X!|!c(MFR)QG}z?<6%rmWEWT`fO^|j!deEU{us`^1xeMKoZuX1ZD8KBD|l1cH!o| +z38C(@6sSd4@z+NerWY8S(Y8Cb3DJJPY*HeMEw(q-FEfuA?N71OUy_i}e#p +z)sw2B0LN8=y=A=^RG40GKkQ9+J```A=@gskqsQ +z^@H?yRKXRc!>rnI7Pfa_idBcP#bT`l17tE`K(~ryG#F*IG!7tm0WxSkk4 +zE%usVIkGVp9Y~Om!Xa_V+1Lj~gm;nBI4Zq>If{}27C?x;ORCpd5{>##S8dJdK?H2J +zeoz9j4_Q^M5{dn&2O$Fv^`)KU7xDr+P+ELpCy0xd!HYyVNpZ^$65^PQcx_ZqX=-We +zn>3(y=PWaWKm(EhjaU0=2j3}}g;IV_#~?65Es9~9glZImCQ$&1GtP> +zb|?rBUMxn4ln1+&PHb9Rk5WVJisMZ0kI_`zIt~Qu0Z6kYn6O05)utD +zZ{IX>5uj9iHxTD}5NUXQ@OhCd1GTkDqx>RC5)~cqm(P{k8Acm}m&nbf5hD#S$n@B@ +zdZPoW5%bg25{nFBZ+qG>GYKh7n8F@CPx7D^0C*A$ypOK|kZPZ~8_u@vY4YyG5j#Ry +z-cP=M+?Hjd?be5dN6{!vvRJjPzP)M|{tGqwxd`FTs8b1-t~Cw#EFD3}R%a?oqof&D +zUn7Vlx+Y|gil4WrBz3>MfwD-lLI`lq&~k$849tkxvu2RR3z$> +zg~^4wXTYd-4>^>GXRW-A+==kGdLbT5tW1uaJ-W2QLcH-}p)mu_Ym$Wcm0n^bP};m8 +zfkmLEfC|SJok>Ms_Gd95hzA#CAaO3xe6@>!qO&FfAg2}^8jP)R0}U-x^BCDGGk02d +zG=TzWn>u=RSrE;A=9>siTBs_R$6G5R#bR{c1tkV25sS~XD8(sYP-H_k!Sd@ozsr`u +zk`Dek%4HH$;TLY0Kidb;!@hGUw +z8M)P!UKcL0kP1x>M6E|}egOpB%jac<@LGtT0u2{*Sd8^YhZulUn&qlZAMZ6W=UU48 +z?#b#%ounxR|&B(vEUyw{iIFz+*P8*M<`~BzVuiyU(yaSyo6Gz8e*GVoyj6}B?I|f)x(=Em(vd}giS<~%>8mr+M+_<~ +zxTt3fElY_GAN`;I{1gP*)Uom#9zZ`Qe+YfFVhl&Ay!eM4<>|9gJW4NTT121+%5QaH +zVIz1YY)LjD1Duyk`LLhBV?)wV{Ppvfq@AS6|B2~i9(vG8jOpYJW_=cT&?W6M5=NLc +zI#OvwPoBe_XNe}@m1G;@i`55{d^P`lwV#wmCDAx-;=j<=W>pmG4L-peU3sACgMt>VhIrZ?&tEMr`?28IEA +zO%)e_p9qL{IerD$MjL>+8bt2^iAu`RertmmSiqst3HB~ja??)0!dK_theVrwqZf47 +zHY6PuLY)v1{bqNejha@e($u-ko%y(o5cauYy_uqKPvc +zY_ReRgI!mIRFO16lX7#v01$=k^Z1Y@EWTaUn)kWc+m)ft?K&4OtY=pjquOsnw}t=X +zcjp;S+Qx-c4{l|bgh-#NSk+Z=K}P|_X-QfdTN||CIdohwr_X=>GQQs?p+N)glb1*C +zW;!d2>Q^)IS(v9d_6&7K?fq!G$>|y(Sq>z5#!s-U2MK9hA)}4gfBt_JU*wzYe|x*VO#V!vVKuxB0p@XtTfW+;6;ZNdNXH-qN#M)6XR6xD|@9|{$1a* +zM(z~K6LO1W3B?)!wflQm*ki&#Ig}@NGE8SfYuk9TJaP8`aTnrs0?V +zi*12};o*h3! +ztNf*pR=|ln-BbV`0i8{xqCw13) +z)~&9L!rRP+2hhP+vyEiDxe3@x= +zgDC%+AU>!lz){gx<69pwyp?*=>e3pe1RhtD;Ha#mj9OQS$_kfXi`vUh4+e?I8xvdX +zUt429q$R+i;B3dGgGen$y|d^uYMk>`eGaE@X7)upGl(Rg>f^xFyixRO8v*!B^+d_j +z6m<{8jYsxbk`R@fo3OPxD1Yu7;`As(Bg1xi+AQEPJx(~ +zifQ%MbKJDNd>PK3QoknewhlI<-ba~DhE@GZc3M~Z|00crhe`-wyjabNEWay}zhJ78-u^(J^T3aX%sM*;4| +zeSO)Xne#sYYr7Zyr^^jZ8;3v5zkYKLjr!I8*mM6TSBUxcq1$*ENfSw!lCPk8(^9jH +z=~$KqTI#74qWB$v186@bXWDPGgd#iuwTP&wgeZ|D6eaZfN5U9_n(;_g>-!37bploE +zwB&MlaslxYALeuyoZLqvlo?`)O~3BSp2ytX(4LMoq8~Nhy|z+MvXD5--=PZtML@d0 +zt!FVjPu88UeHKS&u0a$#$-O5Jdyaklu^@+ZU{i~O=SbalOP9B|37h_!f4wc9^mhQ) +z5tbBJnoZM5$LzI`M9Y$I=^6zisApF)(R8ET%b&|bBP}qAlPFD#l(|QtGkECcbArj1 +zsfGh#9kNZmB59ZBx-6tVi^zFbtggA8Udel}ySQZ}QAX`>fpIw@SHQ|hKiNb?Q7uM> +z8fadK2k!!9B;=1I&)-KIt-0$hO%U>t0rWT`s{Nu70`y^}ip;)2n~~`Sa(VDX#zz#DPg(kuGNaJ!I6@q*|9oFn^-e +za0-}19#{v|QE{vc&x=r&pH|XcN@F-Ui`H7x +z9&S`^KXJUgS1*K1@|~Kd59i!+bzZ2k&s*gPmSv_%DfBror>-@Qw9}?!WWr +z(w9JuWX=6eIUzzmW`*bnF><#SpUx;QM+%4d4g})X@@Q5J8Oh4{+$-kg?G`}tS(HDl +zMFm>=hlC4^rgFmW`swdHeK9Z>nx%sLh#TMpfz@^)E^^8`tJGCohY(dGZrHX$u&35S +zG78P0;={+I7EcRQ4=rf@*tK@ovt?9i-`Y{AchtMx)+J>^DIJH1+YW>wthBSj5 +z=rf{s-$?L^F-1h~`gT`?UCfJ@cGpa{3@^VjrCUxvXz?9%3_Y+ieCO0mvdygC$As@r +zdb41Z$lWEGcAMtBu3>h0;MRu>R^$H-L!wV#Tx7or=q96Q#m8FpyT`k9}jxxNd!K*$d_eXH46;<}>Z1 +zX~Z4IKq7kb)5Me&>Bs|P7W{{HXJa1N9Hd;5nyxg=-~=ScI! +z79S!B+z4t#v`KIt?y-ggs3RU1jribYnoL+oWoHTvo738j%={OR7?A?I-RK25kd7o+ +z;S!D#NSEaAToBe$D;3BxJpN*l>4QvgU2B^>uV%JP&=r;f8d?BEjzuM5Hm`cyo3mRQ +zD{e8FJT2qFgjw~S-#c+rsDY>lo>6#82!P&_u31<=f#a39;lx8_N!Rx5$A4%2tA&$1 +z-=zPe>eZ*`UE@MSpG2`f4@a1;4)q;fCa`#%8%+r@l4QYA=wQ1a)9-2|=x +zo3V-LuH!n7H30e11GPL?Tz7GkR9HqtFc56WBu%A7xa$K +zMcOQP1fBP6ulBw@bRWgc_%3+RrZ +zoxXN=hzHSDg!k~iO@I@fy8{5jYPiZn)CzL~{b;0f-5`(h|475al~&vYk~rI(kiQN?L9WOlvI@EnQ@^TtV@Wyq +zgAbw*YBVg831|s1;)@Ruj`^~zIz;#x|7ns;F^F!{F6RJnWiN@=ytIh4B$7Ks<3v@~ +z$LSsN>v27)fXJho#qb}r6b`lWbJjMlCc4($#sR--_40you6hZpKhGCa4n3Y#%^TPc +zi5MDW@Ky5|oe>>J_@D^gP?2Byc(oh(qP4DZJX1JPhchMVf1=KpvAd|q0$U?QNhHEP +zK!>Q~Q_SQeo+C6a2?;q$^D`g_1lz2dv|27`c0sKPe!y?hkSIoih8&js +zvzpOATY^4AEwfP^>w?;^7YK7rsHx$iqHmFRe7%lw9eaL}+$mc9CNS%P>yU)ein5!9 +zgT|xuU_3t=$L|x>fJj& +zuo}XN>AC!P5DKAA#XX*ZsAg2ndx+HAh}_JDgMjILZ#=E-q}dDQH#_dc>&(p4ysct^ +zZz+yu7TGv{JL!a*hrz9*<&C=kefvcHj^ab-Rf83%?!4T0i3jKRx$LV@x_3;$0Ed@g +z8v8z7o*`$(g}kS!%A{{Le(qBDOy3TZO}e92UBWR9K2{c +zW;r+{WR9qDLh{;3%I7J2P>GPcsd)y5} +zF!-)}OgM^prdox()iqdL4go+f78I1-*q0gr7u=$}u>6RG^l${ooV4y}FdMnjYj0EN +z>|aDBnoz@0kihULT@Ny$qu5l3Q +z+??L}Q$XI{dK@C@fJjRcpL?kglh!~1S&XueJEqi|^OF+q4odyM%E+*3E%%>q4#dGvrP+N!8o+&jX_|dGZYxdb +zHYHyYX<#QE!9j$xfQYj-YRT(}$N_BBn%hzDa>j}D#`qGXMQks`e!z|6d1ytCM$r)*Sx*op>dOc>Kx!$o4BY^~dFEP8$azvp_ek6qs{*CJeczVZ +z$AGe8noGS?A1z1~LlIv|oUSxHv#{oNJ5)B5TNR1D=&7TKv~>WeJjQAebzG?hm>guC +zi*K4a3BQ +zk1E>eqeB$fNqsECm2pc=uw-fzFkbK0Juc)8yNxG>8gOtCy~xb(gpaM58^Y+ +zxU{Mwj>&6ZW$eaRsuq@obY)rnT$*pv7la`-_o&5R#%q8TYrtu`hyMR#N<) +zJwoJ>#H~Tdq$bn15*KZ2ozt6onC*v;Lv2jWvL2glr_->VBuq=`%bwZ&5+=XSRxFlj +zZO69X8MZb|dm7_1p3^yU?sS+f3OsVeHPSRH+=RNKkkm5zhft4DO$cURPl(l~Us37C;r5C+aS|%G*bEJ8NVs0B1#Rq`Xd>?j0!cE|& +z?>@1@f)thbL7dXPaG@sjW@u#GXaF`Z&K1?u`6Y&-miX}P&BSO|gt)Lng9x^3IR!r0 +zR}=eSCc)KQS`+UFS4Qu;5P1E&t?3UE5m-R?YEea)lst+z<-%>6>d37D$1ZOaKlm#X +z?6Z~pxUlm(c;m!GA%Ny25t>dw8bFvzDz3R$Tpq@fRv}o99p;sab;pOGN6Ar!)Pi9T +zz#?B2xswM7A??){3n7q|9e}T1fUChnJga5twft4>b|RFHh)cyZM|ueDxd%_9zEDW6 +zZ-qigG?K3njr=jogH$qd=i*uGG#u4tE`A|(DsMHGGxA_7_Ok4V{v@HH^Sh)5)roSR +zAkdkG90rYg=uCg-bILVNG=G;Zqn3fe{wl>PB^mGLo1uX*q}-BJ#y%dT_FiBF5A%xm +zjb9H2<|e{YgAkwRo)2&!-4hxb#5YIL4KtqT7k*o6Vg3OLNG~;1t|s=I4>wYcq)8}5 +zYU7j!2Dga10yVUw%3q6Q^1c@6Kq#G;??5X$55~R3Dvhr4D@H>=ctC4Ni-nanp`OoU +zq)-hf2wvio63T#2J&$1;Q4O_!bdObwc^HHJ1=72mZ-0;I0DN2p_;LvQ>17f#pam2{ +zM`J?5g2-5nm*#8^*n)GJ*y#D%W3 +z@`eDm&oxtziJhHZeu(EbGDIU$AGN0tr9*e4{bhp`J}xp+R*+mo2Xv#`qQ7_NhSney +zi}TroU?P%iA-xH2V2ucZubD&{q<3~GRSws9C$4x0-;q27J!=6$%oLnGa=s82 +zwS+4F@zDgT71tol1lih;@qrNAqA(okWI@usa{VGQB`Q=7i4DUe*#2ECUUK=1@_&sG +z4v28ROK1=;f_Fo{3w$9JOMw;-Oa;BPno##U8%tCg+T-&HbuH9LXoKzf=!qo3cLJFs +zh{V_yiM(=m)UJShZBhfJUQK_ThTBRMDezLo2{q}9pd;pSm;B=+*4h) +zi~BYPc(8~W6=M$U57?X#MFY)W1kIrn-kwF%Y5tTtYC>|V(3teuvXEu%GBvoCMW+fB +zC{PYSm^I2bRK()jdl^yT%9cgGLZai@ZGPD*o;cvV6@@**XIQ8FVV3$_ +zkR~lxiSO*Ep2d4(riwmoaFE9i%;Wi1Kssrnl5sdh?GYEHb$(u3QwJO$B19p<7a;NC +z=mv4oxRzcQd3U6??2q0W57h=cJQm2^0lDe|5V9)&yZ_D3u;rvs^S%H7^Yec((oa8L +zD*ONQ?oof!2#E^7-YgOLK#ZEsl2!>45|q^7IdlC@+i?!avd~0_)4V;AQX`1ge>Lr+ +zT?L(rAR=%f(GzkSyj)&3UG6+V3a9`WzrNQ^yL%qkH5Zjcg@;k97LZ&{2x;S!m`~r! +zvLiKZ)t$8t+~fCH*qrkGrgS}VdPiDICl^O3Khk^4(=~Tw4_`pT``m=NT6#VnWeF~Q +zchU+-c`ec-d3C|ufeH}qQZj;+{dw?_Brs29!n!f8gEG`{z$4_ +zjUXW=s=eUNF7y7kK8N$hR=?1)k>H-c^+P^+EZq&j`-lbtApf_s!(X7lRcD6c2{tYC +zZkSoRXG?Ypu*eWUi%F13G)i3s2d2|i`1}%`r3>lzg-$?GtC#3=(gUk-B#T5_o%2|xv3Zx? +z3iMKa_6@(PCxOU_SFgd7ES08oavu({EbOYOv~-BE`6HDc5hdJ@GHr_=PC#Qok`eQJ +z_aS$<8f|L@V!j}w(v0J$lOEO1VlrqMk?fL0e+i;cH`)iWzx(B~+H1Di-PU?eoUcl4 +z1Ol_F1n)ZO@O(e7NR%YaPefYfnwZscP)H(Gp-xPR%hKD!rR$E@FrIFC7 +z)Ks(jTlCT**H%D;5ea-N(XM^iB8W^<+W^z&Z7(a$<@fkf@_83cZjaJH?!Dibn){Da +zNgvDGnDb65LTRgqS%A7_4EAUiQ%u +zsA=pVd#gYp-u^0OgSvh9KoN&h_VK1b!f3U;f<%VLZ7vy1QmzzS@e^b$eEft3*;usZ +z#q}3c__R*1#xc)!La6rdZ1okhDPBir~2AoF>++w)Hg( +z{ag;g(D%l6YH@>k3B$!6hv@e_%1PXhqKj|Y1AOGj!NTDX_W)Yuu9su{RW$5pVUuvf%a~`y5m}Za-PurB2(rfSX{Uz&f^S`8=2|HZhV+w(oIkwwu_Fed8uIG#yXW+S;iL`84x>n>^PxzxFw{ubsn`SKYMX?Cw2zwrLl>p +zAjU7$f@?W(ZY9OskPOR=VvS4Uk)Tc3(zaCRrZn@IHFZf(D$XxAGbY%YOfkE=H9^v< +zp!|!bS)8cIwL-ON7GTP1$N`*JjzkI_5xL7H1lQ8d^k%%SVBM;9WiGD*3l_D+%wEx* +z(`=%6fy*1Ls!8KBB*nb0(jlTco#qX7#X4S=p!MYu*7;^!1xi=Ssz%Z>70 +zDkSOY^8ORqq8`e+78k_fMUrU>JZiN4e&ntGxhoZhqgNvz`s;3$UZc}`cf7E7ftNuW +zL9GbYVcg60fCmqV4magg(>|S(Q`?Kz@2TAa99_Q3h5p=*nem=!SK$;}sO-U-P!A`}^i(6XUj-+*SN8Ex2r>A*bMuH0h +zsf6BwwOIk~I6$>#!o~_X`}{c&BbO|P$e|MVpo$eC%%GAK3dkXO<>f)0ufC&ntZEuL?Bgm7X1J)o5V+u_8GJoUy||+%+3PhE~3^uO5MWw +zEMBTi1r=uRN0nI>`7wnKwGoJZf<$`l;Kffiuky+56DEDIuci?BmEXqWist{p?|>AY3lTK+qq%KC`>(Il=~ +z5UqQGx+;{2e{`KFXcZ7g;E*gOxH`JiZCj}=v9hnGu>OI9q`WVIlMC7=Uy)t{VU$Ap +zA!4-j!f*_HHXK~g#$CEcf+L)VRMRF-y=kHsR~KM~oHcCY6X+Z@6h1(kX7Q*7rySf9 +zNfI>;&=pUCLg;-TJzILHJL>(5B+5REN;XlWK3qpfwTP~~h{WJeL7|`X_k$B4sxYwm +ztrjw)^K=mk$VFR=ytBy~(Sxe03h>Kw#0>Q=UW|F`&5~<5An?@@YxB}w +zLlVORb7A-IOAtBT>L~E$YG0_8KRv340x8mqZ9(MN{TNFAPKxF=KS{vc!?EI@VRq;& +z0TnSJU#B=M{VIOKL<6YCq!l|QIiKghab6O +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 +z0NRvcreMwjhb~<>vA!BghC&0e29@4K +ztFKhOr72bx*^^i7q?PT&Rlz95gxD>_HI0XOg!?k?Yf-!P537cE1Mz^Srp7XjghD#v +z1cAn5Moo=Yd@t-JqLmte2T8w&_pLI*KS6q?_jYoNjM{NBSvu#KpjKVmH(#SM!{J2@I| +zSQf=W0F`j5m7Ul(M8#TnYBNJkF{u2($6X1VWKg8M=4=q2ia=p$rw_`_$W}y>ZWP#e +zSofw&kl2NSLByGMnDdOG_@R9s@}S3>6AT29kwlP-{E*{ODM$Q7gHL@`OGT2#R&?~H +z{elDip3{q{JJh68aP>-PzE5a5>X_XrpCEF*frP3zBjoZo3}ly4&GXUU)u5AzB4&Dc +z__WYTD-7_C6;k?q_M~@`7QgJ3e1~HZf!Y~4neuM6yJGB^wvp!^P~Tq2Ri@M6Hus^l +zvY22xqOUJ_sC{81*_%X!AjJ;UZdfYdr7#Ew(h!@6EiwT57NEs3KksQ=z4|vlL0Sm4-^@ +zN*Ydp{Z4yefcp;aVDT6ymxl+MT8Hv!Pct+W6W9WyD0&FuHz?TzY~g2(IMO6(!S+zb +zC22_2q$){ncq6CN28@q&M?>^dy9#AAVm-uyrM(M~YS5srKSZ@4fooEr+06xh^T!mQ +zi2j8y_xyDRd^xPcGHEV@2Y(^1vv!2~Jl!k$$Q#4z4=i#;G +zOrC^U;4>s{zkmNFTA_8K_3(TWiw)g8t<5qB2TB55)VCQ;OHJb2u3DgR<3>|0rn@*#V#TLOU0E +zmq_~V(*;8`(v?WWP{-p!pz%H04AX>W?tWfwkl()#dD%uR1h$r4$uo=;&@Tj4O9GNO +zbM=K>`l3`|oJ} +zvx)acLO#iUIbYZj>3h$O1NrE&ovu7v8vjThS)dMA%j;)1K}gA7UQ=@!z9lLlezfr_ +zA;p4Z&-}P+)F?OfE^a32u6<0lMqF?$;~|_0dGIo3g~r@rl4?dQQw_3tYTlfXVn78# +zf8GSC&t62dWHZ=OiV_4mto^hpv8v6SM3D`skB#+Fp85 +zNpUigk}{unQlq>W5}-4Ui2NjC#F(R&NFOtjMw>11s`oD|8*AF1%a}Bn>#>kIksTgoucD +ztEP&=*RYV(#1dS-5Kgd^{kOQHcNdO26mR!3dXf49y-g?ZVL{89Bq1fm)ml0xq>)({ +zLJn$~?v247-q4;fd($y$<*(ro-9>&mXl|H!S)mv`?TrtzZq46&tkw4gh!_#hnwwlA +zqVc3E^(#Mu#9Z`>PA8TDq +z`etH}{Oi*E&=x4*sYW+_0w0Kc9LE=2%3rxK+yr%Wp4MEf1$KQ~xYRp!p=gUD8AHGy +zB%p%UIc|VCL5k4@;Ub|$Ki6z}Dl$^AG}7KsQ2UPtTMz)h3ogYDiHb}~qcnN(O_Ua8V0jiRDp9{yD#@RpdU|D(#I;$uz9jF94xPqtQh+Sj`9lA1ujXg7eWh +zn_7h;z(4vn?bJL2z9Kh(zJ}D}TaumSHlI7}U$oKhKt9P2$5mP8tt<%Brn4J? +z;_YJx7a&Kp>Iy-TpRfSZ0EHY!LCX=@qHU4)w@nmf>=Ufj;x;gi*4mSD>H%@pVxx&M +zLDuL%C%G`9lo}A#R{nyAKi=E*HLUt7efsO?f8H4<)G^Zs6%@IxRmNmIS8+&vtZ@k9 +zNGw6gs-`sq2C1haZSkhzjA4R-p`c13j|+{D5G5*1hj!n)u=r>P#^%v+RT$ue??-2P +zV;Lw}AiMSupXj4FAWHxu>*FGbvkK;kb{5+gD%kgcLwfL-8j?T6=OBHx@i0K#T(?9N +z4N0n&cknMQmCbjb#cW9;txJWiAnyzd96T*vuH%TR4K)k9t@X0) +zRqRt=gTj&^qL_~J55p8-?;fpc)%Jrt8Hk$CS`79?*h%YyWW_rjWi{}q`rJQoVhL3s +z;r|z3x9iZ0cO;p5IhS`Z`6BIbd-bv-t62n}ftZOkT>#5W1tM`noBsg@0eY1z$69Y@ +zF`=Stai;99#YQ +zLxsRZ{neCI12UxH?CPS24nUkp0t4bL#G6f8lFsu*2bE?2$ZKrRBd6ER-Lh(kQ?pJ1 +zb12FQAI3fnh3N2xgwIZ3$Pm$+m;Y3trY6mS_A|36SR@^715a#~rv|o=Mb`icL4xLg +zS;rdHoas3YS)m938y~4%Zm8O<#!%X|bV_`f8C1fdIg1=x7*Ko#G~msa;jAdT;`Xe+ +zDrl&25YKOo0UgNDxXQI;c|A$M)gvisCw=p6WWR{CcogdQc=6-v``i)N1*43hFC>;O +z&@E9!z{@UcfY0c|z!;ht7?ckAEpm47{uXJB5~42yJgdBT?C@wy;%trl{^Y4-lBQ9` +zup*_?L5-TMR(xORZafTXRQFvW@m5Sch}D3N0L_BPW!dN1q)*LQamTvKhrW}<_}#?j +zCIN_&@bBMaB0dnQRBt*LG2qU-Zbs?E>mjGqSfF^`-JJe+Oo4S+Em8#F2X$LU_ +zAhg{;xkQ4UzM4|Sc%O?$9`_)W)ZEygcQ$8kl}FeD;%Wq~%z4}uijeB#W?EG$P~j?G +zq69fGEJ|+A#!Pg&PWKU+yLBX)a2^ls*}t5-#Q16%>W_WstGVL)UqHL`x1sNMGD?bQ +zuLW`4T98^qKR=zOAUX(y)m~CP2bcE#xS*o*JWQn^U#PY+_l$N^cRCa)z;QBu%9DM2 +zVs`;V<|l9z(GLNKrGXoD49uGqH|Wa){D0u +z5S+S;F_~Qr0=+jF!i7m>&?G>KtCshHrd3HiE3}^KiFS%NL8KosJUCpggYltxqn`#7 +zzS$4n2GDke_<}1=#On!`QDcs9 +zqcUAIcis!yedZKZvddMWGP@oDW+v3 +zxrM|;1sE3&Ys@u}z!sXKb0p=rNO(c`H0gy|Nw0*(JYFBboet$OxU!9m_A%QaBcC>wHAPykgxs=pr|akJMe2|5l;8Bp{l(OiGM;U_=FQ0l4G +zEOC(2dE{Fl=J3x>_*+P0L8b*;9R`I#Ey?hY?nHsY1%+@Z4{T!AQ}P> +zo%8%OB*kZOMW^AjmLRr7gI6X?D=N}6giLELI6&~VM5~!ZD*dhRU3FH~kaT$}8^o1~ +zJ!){i4-a|C^u2N?sW3HK;%0|*RT;R{XvRw#QYfQ*O*3_eIDyQPh4~20T}a_1Zo(gp +ztk~x}RzC@#IcSjqlK&;5wa}YH3EC%}bR4U~t{<0I)&oP5RT)RH?DF;Tf`lNX8yp+y +zyJD#r5;nftZDxjPENP#aH!XIO?rs+gyrbiG^6GKGk3-}x-_s?*o!~;4RVqM43A~3{AKnv{BZ$SXq +z2>!#Qm+Fdb#Ar`yi)x#=Jp`ThZjR?|jLNfGmu;OKF9g!OT4Rwrqg_qQ**IW|49WMwt{z9dN~gs1c3wBuhPjpb+mho5X+<6FJkj?TLh4IpXB)oeN#I8(zOe~TM$uL +zi}Xra18^?q2SbNiwREw#T}{YV4Tq+K1m6Pudr}(kwEuQ92pOLkSlx?Rrl(wNP3o$Q +zmiK~%`F<6@q;t}fD1R<#Vj5r`4TdL^4!;IyRF^Lfm3l)QRaU_Ag4!rN$~bjW;esN(m%`)0QV!t%R`q^t>`GO$f&#i +zFGZk|FaOVjR^3yuY(MW%v4Ae%btwROQm0!HYCwd=&5f8^e8umdzkcx>l2`)ulqMlQ +z4)K~%>WrAff=Z;j_$3_6!7S`;dDBux9H}H;IYJ!?7IJ}?%k7#;_1&2YQ)xn?80yOZ +zpBrPxNx``%#6)J(`zf8J?;0`qCq1;m#=j38T03GSL)|xDaJT0too7Ax0FbwbRZ`Gy +z3*J1CN|F-RuWPM;=hQQIPp-U +z)4z3fe*Q)oMKI%=WZ;|q{!8Mw^9|tnrq#7b2TA#UvGqRbZ?rlDkE!bcohI6(IHsao +zkta}NlM+@L5PqJ+Gy{Z!-v`BFPO$K^lk4aWzU!L>A?}E3epckHmt5Yr25^mn9*z8j +z%%#z(RfGlRDm{bzs~J@Ya()~mpI+E(Nl2p&BrASBFC#vGtH_A-CAKoaWis%0(u&=q +z7#|XF0TS~?Oybs;qHc!KGr%zsL|#A!0=px=mY`r?mPd}{N3WMSokTcKJ&o;tj$-%? +zNkV;*;Ug#li%=wbBXR!68sJnj_d2NVB`Uf6O|Ou!ETvMSL82mty2u;?XSTidO(U}DyYnS?h_v>X>f1u8!cmlt># +zAO!$a)z$DALONp?x>iUIv7UR~*A@9E$@vY|DTs8q@F)Vmy@+<2_l?iJSd^&RSDTsk +zA50##to$yzT5W6M%ky1P44BkXAw0sm)f8(N$q4~s-?elsUa0)vI)W?`RcR#hMp#l> +z{2}BM^qmir7XV9%?W$OD5G-x#mxw^lNEOvzi_XXs7cPQi_BFfVe`8T)|MQdgP1^Hb +zdWNLP|H6CC*^EJ{V;&fkIg>KOZ&?~x!os6nZYUBoEu*xe=>W??90?p85fEB-rdh!s +zdRu}@Ljq#o-)V`tv~p1t?0edosz?&z9`%x(-$h_aEj44O$@T~Pgs37E6gp}1iui1cJsZs`~RmxyH)ew6|n)4O!hV}X@Ons^fR6hZN= +z5~E4&%Abj;y$OJ0ADlLFRHBnMWNJQZOy-g+sQdEBTFs?&ad*wItn0>nzU*qvQ!CI( +z^46r@(qS-(kJ_3e#=lPchvR1QwyyDPUCDv3+m&}?JMEshFDvLfJa-+SVdQx1sKrEs +zB@SQG4tDyG&uSozZ#V%$EZxXhQ=MvRt&`i#OvGMPGCM;G;>sV%-g+d737yH^3XItf+7N{35zlT5f>N?wz +z3?+Ib@_j;ZJ5^X^IgyZ3!js?UKcL(vnR +zX-C)h_m~%wi#SrP^y=x*D!r^hQ((&Di-%#{;=J$lsf>tShS^Sj8i%~Le(d>Tl6(~J +zLTc0e{6F&EY*%_5NfW$}=Lj^q1L1yrIco!nL`~1d6i{_j)4*Izb_OVkk|n%0kQ^9Y?F@9YV19s+=)-(ismXoRi~Hua^=yiR%T0la<_L|pnUHN0aa&^Bc8Vui0Hz)-7oL^V6=(gS}BTA +zd)ww^FxP=)pbG8K_CUh&a9Fq5;g%xNrnh=EgiV{0ww+8%iT2h+n=;~kBwF35Qg+01 +zBm;S=dx=}YDfNz0Fe0<@9)=b1L~*u8`A)ILWboDkCx$(<_M$nqCZG|cf79CnEJqV0 +z5zLQ$qT^u$2$ +zwjARU@n9a4m#(+FN48}x`FSY1C(r-R$zc>~M3HmO-IWL83(Fd!SAe7U#OonW5b@!3 +zsGkTNn(KrNE{5J7b9;S*)?S9X>uTN`!~m-&^hG(6g{m-1tv`2bgQuF9QRTf!%lxqw +z`I4xBk%9Jf))qZXy`S%-|3t|i-i6`Q(;0wi6-Dvn9~1yhfNt5+dN)Q4W-60x!aBdT +zE#$R-2Ogd#er+NoVQ`1^egyq^`!dJuFOP*u1~3N9W$>GJ@N$>%%7*ryx>91^`To2QwVsONK}Xj$Lf2}lyQX%~%%-!hSPN(8^%$%* +zF;PU`bFrSrB2c`4zklow^MypR9#y9d4@EUcBXx@g?pf!Wr8Xc#BhEXf6TWCw7;lMm +z8O&gl3-28$N@AEH%tJXaU5?=P3C7Ct9nsTtAR(xYg@Wy27q(r2IxnK|R4&62sD^i} +z^;DRy1bf1UJU7H9U_Nn#cLh>HB$&(2@v)$oyOHl|VGC+`H=`rp0xS4tiRrBO1c8ZD +z?`|-y@u=RD#ZS=^2C=+gEAbN2faLigO^2}5$|-lrqXFv2%_09zfCa}-Ny3M9R +zoYMN)nnqA=F-|r0r8)w=(!oVB7%cjM@9z3Xfk3xVsi|MCW`UvE@N1to@s;!BUR;R2 +z%O5DEv)~NYyDErUq9|8L52LDN==Ec8$_Z*u!g#kS4-y-+mJ{)>yntB@9nX}1#rb3b +zYP?mUOjaaW@@OiLBr$(aU^MYA_q08#%n-zNZ>afc$0{+PqSpxXyN|z_VVNgg)07Us +z-Sn#G3`3jr;6%=lrw^Sa`ve>WrVzT{0b>TijB~LcrI`_oVGr)lj6?hAy3AEuGqZ&j +z;`<%*Lnped}_0ByjauY1LUOjok8_B%*a +zfv?*TFjiXxIGns&4e?UXZ9*e#Z4|X&zY$%JarY;KPGWd(B%i{gQ +zdZ(V6iEPxaFqt;RBCDX{WY0{CvKar&A!;`lS$e`-mcOy4qx){ma|nMMNC|Nf3YL(PrX!0H +zx6?pln#r2(VhIQ|LKE(!oq76T>B4vJX`_(2ID@X7lyy^VM>NQ>7<(8E0@|eok??Or;7(8*1B7MZ3|{%1o;@a+s@9Ol +z*iTLjGil?t)S71N=vdxOJelA~TTu%2lyl=8$+jra8gh@3?}H@Tn`W39&G*t6J;T+* +zF{sfCdF>f2Ei8JBl?TBdanXsuF<8}O7cn!z%5wX4O{8>E6ilPsAa06Fi0XNgOm0?l +zcvbiP{K0ugDJVhig*nJ1cn5ffoBK`U?}N?wC>okit#H_wJ%|h^ZSBQ!*lrap_jHj} +z?E{pO)HN1}7-E6Q9EoFr3QNmn^jvpD%TS-H(frtbtcucgQNFqce?ee$g5m6 +zDIHo4j$dODBsaaJgZ_pf5DEu&#+lwepu5BxxevnZ$ZZb;c?#|K74%a +zRxOsJ3qfuNOjm9(SQp(x+zZVdNa@+YXy?=$dFu#wcwG +z6F=!~AT{M!H&Y=7t{-GH5MHmCK0Bqsly5RQ2krouS~RsT&KRn+k`gj|H$6O@ZFJ5c +z2o|ccwpNAqI0)q`EC3FOZwy(|uo>#7;si^pC5QqehtnFt&V8o6tnJrlMAn`{a}+b$@&~Ta$jws6mImtuAdOToi82$lUI_Qtm;E`}KPHx?OHQo%e0yPq(D1>P)yAs6&FqtQ-H~uyDX$HNAZ7ji3kh +zJlAvWr16mU(?rsy6{K-kEU}y&%w6hv*|3Fv +zs3uY6uuDSpCt*wuR$`D|ODtQ8u)m4tgg`hNn2!k7Y`|VAFjUlE$}4+`pk~?z_Ima! +z@G-$q)(C6fK2foP8sh#?^!s}^B$u@yJXVph9>Q}wd)NCJ9$c?>E3P)QR=kHmD=)qU +z2soM4XtK+V~g;HxZ43FGWFcc>1XwL|yy!Z}* +zfntL}d8v{>YVb(kU6-=)-isBuusxJ#AjvGDSe(NrVZr6b6D9~Y(9k6d-9^zXWNYfF +znm^4A&an~&!3ehf$ZMcY-X+?bEU*QSa(0Ju15O9;-Bji+3yReqbHOTizn(oQOUJyd +zx~9jn7`s(J@W;m4S@hq6r7l6Y25?Oeyyo7SN7FnOyFvSy( +zCUuT>ej#>WG7x7|IMBVJq?9KFq2&|WqGQL~ACZTqG#)p%g`c~DtX9E0c_Il&h{m}K +zOSlH<-yj0n?6*Rw9OV_70a9lWcF5i6%`d$0oOy7qOOfmmKSSwPTR`v`jwj|!d0&ix +zL|B0hG<9!(DQ%TMTY+17Ac8>eJVY3{lpL`=RZ1w(1lny}8jjHv`EyqAS8 +zAug$ZD5tcXux^Vt-zG4$u>6=mgs|Nr1bWx8Cu&CBDeHg*MLZ09xE9{*ViZeRV~zDq +zbsrdp!zi1%=9+ey@d3<4oj;M*I&5+hRWadwaU +zrnBgP4lj}K7AjnK2uI+4RA3Tp>0N`JM!lDY4SPXw+@B~jt8{t4Em>pS`^nlu2D>L9 +zTsA0ugI7lds64|349db^jRokzyg@O53Du4~=4?tB?Fz1)^3{>7@nQ{zu7d6G +zVRVzt?rpj{d&qfCVMDK+n$!6qmD!Yb)h3MQz5s*&_^rB6ZtHIvDsv)E?c7 +zs~$Q~ZZbC(ojI#={R^hTCPVN7{@$BCs)T1PD9uv1T#Ml`gY}v`I^(SagvsVu{|0Lz +zdQ^=v=VTAZ+ou}tgT-N=1h1L5!$@jf`<)N84n)vpb1W@oL1~rmn?a__qZtrM%hqad +zKr>{S|73;$h1xADEcs~>S3t#c8;nFrR+6FdZnV{pPMjsSNly%B8KeVI-V=1A5Ep?<*2pn8_DNpX`+`QY|hofp)*Do$QV!k{}g +zgJ$NEM+Z}o#M{0M%QPrkW$l5y4u+e`Eo#%4oOrsuc_8ACyVRgpKG^6Y9S1Wfpdk0k +zt%<&x6IKn0qJ;|&82Z+j1j`Y6dSb8JG<7vihJF~Uys9Qmyr+$6rVVUM1*}r1R1G!F +zx}<#PL)JX5pQ5&E7Gup%J9Hja!eFQO&AT2x&n4Pm>@<6obAkSSHXTOzo;ok^5a@%2 +zNcVjF!$>PBD8jBO*V$vk(qhQx2d&-aHDa}5#XC3JQ_1qIBic=uNsLX+iIYf^9;?Q4 +z70eCG@?x0A+=Z%)H_!h$e#v`NfAVa9o6$|c5$A|lOnm&?uRK1IItP8JaMy?zu;iZY +zqzCEyM%QVfcL(g4OrVRD4QaGUUCHe+rRjQjHl|`QB~5uhcaou@nYYAMm(!4OEbF}F)}Vm)y(k49<3wf +zQM8hlUFMF*#){M_)4Ti`>uj8gX~;cFE{ai;hP&lB)>YfnvUb-hd$4*)2Dd&(&Jdr; +zyL`UtpDvrJpk{QSI3s^z;|XO*2(F(lK@%|3K95HX&>HQbv70ds>=Up$oEHixo+D&z +zb^r-1wbSQCRd$0bMLG)BU`&+LrN$1Fl#V=F;tgz9=Q`EBi~1cOW@;4dMMGM+R9HMA +z>5Fo9%~YR)ey~?q8`bP>+R#yDojjWIv2VQ8cx5*xS=RyTkPBc9gq` +zfxe@O&`TcoP6R`b^~T{FPl>euE4gv*$$O4uPg*k|ry&R*tDF +z-7uxJ+0BM2orbcR7z5ehGBBnrNfKJ@*oRa0Xbj>^wwc4=pE48_?CQ?1Kp#3RwX=@cw$*Hp*`vjpC?8+SW7!X@NzAB +z3To47OOx|?)+5e5kReOO&`38%ELW{IiTe%MENNyd?r334pX__WT22(v3x)8guyJ7a +z4kF5~@jVk8nR8K1Rr{b+qz{*4Gu7GP>RwN^97LCmwVQIhnktg<(GjGUr5WeSnH&?J +z>%5yEdH(RmyFuvotj=8Y{M0ffNz*p&(0ghhr0A2r)5#uZIU$yia97InG)`d56~@bS +zoX``6D95Hj^N;u`iola6E})xFOF)oEKjLg4H9?IZGZnlrDx_Cx0}61|f!ok3_rU^e +ze>aiDJSE~WF?UCoyd +zJeo0|-IXLo=B~z4arGdN+F^uEvYyhsdbn$oH-t4wIgYMBY+%h);i+2dEaFKg^FvEl +zO>WXTooC`)(337^_cprCDnfHG;P+3|k9O`KxzlJS)5)UHS)UOXjz7T;R!hoVh~(5a +zo&q@yeF^e<+IOjGEDUU8w3#Z<^BlDkofoY(!73gC5}W +z(Yg47X);BgPh%rS!>9dCXUy$ld&1vLGJ=`on+TXmN$dT@f5s|uScq=ta=2`myKb0B +z4NnOe8><|H{l|iZqC1#m4Re0Uc`bvE4iY~x8R!@;jOF*drmZO5l_@wLH10o(VOu#d +zeyy;X%y}-dnv!f+I_8wtkAXjGJA(pB(u1TXYy>cHRm?KL# +zsq=!)AUHctTz#Dxwt?34v+{lzw&>1X`E~Z-N}w5>dabdlZnv9Xb1oiW1J`6UyTF}` +zv>jQ=z)aiqmARy}Z4OQDCXIxfxqWK?jz*f|a22!IkxySyo7y7l|Vj +ztiVi%?fqDd;mYnOSW}#Kpaja%T+(Wuzac@z1-IE+(BTAIy8KGowIe;^s +zV!G+~80czI&Qi^zG+@M$)D40hy3Pa3m{mGB{J>e|RhP8mG>wi_8?c!SD{G_NZ426! +zvqEN*jHVuIq5GAxY}0pC8GT?6~zi5plH~@iC9?MFy>u>%4Jj8Z|tLn{g}z +z1EXeQt{11ov+Cw4zub3+;}Xk^Zu7!|-=2TXKqw;E8Zhs7l1i~Ep1)e4V4Dau0q;Fi +zTY05`Lr9jnvYZFz<|pmj11~#wASxqdTVCx*fB*T$(gWvOMtG=SM&BSKDOnMTk1UR5 +z8dIyr9+@46RR8)PB0<^t`;m>+4I=lYbPYm2a55~Jg0twrK|t1=#qY|QJrhRp8Rd=f +z+pyZpnMS&|kSvS7cp+ar3e>+fxZ=p7>P5FBI(7VGODr>-MW-3bSgk=$zu>iLbnvmD +z8j92iW3PqvinmBPbq3uu(q1F +z4NwJm!P@GJA32yI>WYaR`9_tdi}N1+i$TRwYMU_^VY+CVBU8K*kLuKcUERm~2J!23 +zbWjzn5-epvA}ov<#W;P!B1~;EJfpVxe@8ANu2_5jz|x@2Eyt|UrJ%DHooTh$EV8j7 +z~FWB1F-XbdU##k_x==c~WwlYm3G5RPrG7CT7B7CD<)oz)`KKpl& +z?1Z&{`47JlXb*T>f|xzFa8B%@G>NW@gknv)Rs_WESegIrsfDshql9^iN1e+ +z?DOo!3n4D-3y#KWuAHw`s3eA?A6jAOlIV;8mh%08N4Av(Dn6f(Eux!5!nCr%5XZHV +zaE3=K5e6niX%;sRY;5XMz59i@gBF9LwL_Q>`C7&|w8WsJi@$oTHrxHeKYv7IjCm(~H4Q<Lw}~*R0NMkBEH`KUsLFG&+e;(|++}3$gnI&+n5~PtQU^poctaM1n5c +z)i_UIej6T(@$GmcWNK@W>>1i2dumA*`zm@ugq(Ie3=6qLO|PaQ@(}NNb@GPX<=c;r +z8k)7}sEOWFtXiFVVQtb{vAA(TtwH&x7Bt17#b~kUhpL*z2bV4i`i6CU;Fg%lyTUbx +zOxSn&r9KAdY4r9H%eY5H8XcE{-;29D+MpAyS9>R9&y9#KqMS)v4t4k5sq2eoFy9)4 +z7PkTJ$In9uv~n#T8+`)Ds?u0fHv0ZpU2U1`k?}z0*kOJjRtbsSUeGNmHe@i#mq_`L +zfuK({9={wok|g4s6cKu7>%8H{VGc?#RxHXe#_Mb&U61VkVvV5xvLaBP3$;{fAtOVtw>7Vv>DoftHR& +z)WSpYc${oF6R~94BE+M=*ro`g4@*4i@WYsV{>lo)^CiB+F&vnUh%4Ky-4kq%9MQ9Q +z&$L($I=*uw!aV|p$89p?;(?fr6pHBhSi(xa{6dYOD=%3V$YYzX5haO1_cuaES8_$# +zxV=_UOhH(Ui$B?&D%Ojr>QRX#VbMp|7-kdKS!)p3@q3t1b=(_P8%pOb^eo_URS_C8d +zGxY(sqMXv`vU@4QmzpA(Jsyv-Ug`3d*}w2eW7!yq7_Cva1AgIZq{ci|yRqFK+TqPb +ze7!a-wJC>3dDXCtsMDWy8ygpm<^_|*KLfGF3KG|17N6GA>GEJiw`=iXupy6rqLmqy +zR|`*dBKoQ=#VW~|#TeJVTEwE(&}KSv5bIzqs~8b0$e-iU`flLd=O5 +zsy6&Mwj)Hu@OIMf)B@>!06z1l*;>0oP*G! +z6>0uNnBW1Urcs@-LrB@pJNM#<3lw=!DhCT^9UbgW=I8RD8m~%Y9zU*M>(?KrBP`wA +z?3v|9Wx$lpxr8rnd!_bTR{X0>Vk_q!f9Zi0Ysi@&q>E*kCX1fP%Ug1bktrUy +zk?6po$8d8FL`0yZ_MF3DS~NcRc!c}=*l^U)*K)e{9$O11-(VgOkL;NZbX~pdk>w)k +zgc*kM+gV!fZju<^7K=j%RFtceQoPvP71°|AX9?L0ol3;D#vtq$T>WCHDb@-MOX+A_C@r|8 +zRaC=Q4M|UNi^FCF!R+i}lf*Ko7ZTN;Rh(X0xC(R_$_E-%sg*!bwK%7L(KWcd;wCDn +zEu5xvD^$v&pMeqiMcl4jc-~3if7mYyA}B227mMfxV2}y5q3VY`M9=;czdP_d1m}Jc +zYXr7jPGf;O3iEqocfc}OBcT7B8=YU8bg$1#Z3u{YVe8s@fQxrC{=?`bk4vG|f46K#ulb5ZClzv=xbV=je)Ty<=`m*3V8t+!MOT9!a1|AYTh^Kt@g=mB +zZV+)x$h0g01vBE!LNshLMq&dN_~8XwD*DWxiZS{o*5e=|Hiczay)!bp{c +zhwacre~nK`bTIoyECxf238LoyLgxgQkeJz;A9i2NasiPY)A@%Ikp-j5)L@4*J#_up +ztc5^hH|-fHFPTmB$7ZsoD24PF!A>()p^lsSGt2V~jO)l!di$@aVyM6V_rJaU?d`w) +zZTR2!%kTgGH?Y6pdb@aw$Cq8-Z|9%u`TFs5zTSWS9#G!DLdwS_q

~D2L~Kg_PUn +z8d7fekn+Af`SW(ZeZc>(@8^Z^g@ljuC%o}jNcaf|@0Wn^aUk3R!cXvw+xvGw_z2!( +zdBXSi8D9ST{d~P%0>Wp|;&u(L?YG}9clh;>^YwN;UqZt5a%gkCzaL0H9|uxMxLtk@ +zr0ds_bZm7y{9c6eeV`m3bbRmoXGnQJ^uYU}&DZTfS)L4pi=C|SvEL!(*@YXxLs~O;R`x61Wu+t(acBzBZeckH{MI2y +ztLxVi=dzPV#NIo>NPmCdqpXk1{p;%|&VpYC0rSMVS>4&MNxic^Z{-4xy;Hsyzy4{> +zFWKooADHb{j?*nGpC3SPTp$p{;k7vE?~jlOHcz>gm-5L> +zA72llDI`Vk8oq`scue~y``Lh_%VGz8dZJEX`|a6}9!Kq)nW6~7Ea!7{J*fgBb +zoR?Eab9!WG!X$YZ#t98RzCmmYf;C(R7B15!F}6HO*uMzssO52$HB=R#2ph7MjqzCU +z`zM-*L(&pH!8avGdSfU**%Bc9Fe%$Q6YTI-t;&}wK#tUPHZr>*&Icayd|34Z)0$2P +zmfkQA98uO;8h(StfLpztJ5i-H=otkv1BML4k_$=>!VhDYPNW+`a-)gJ!U514q#w=d +zc0aY-SsK@i*zXeJy1=bv6ps9@Y%Rm)uOs7@a +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 +zks{=aVHloel|sytG}t(72 +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 +zZ%plU4Wz)zJ>wZL$##1SNOs#s1R36 +z$nD|}v^lnq-PR=K9Mkun?}uN>GG);*sSH_KQunqnxr%i+c^kS@r9}G%v-k~7I@l(& +zKP;*aE@XTlO6K^u#dODP3mkQVmy^)Iy+auQ0I% +zH2*D|Y`028lo!iK&Qum_qWc^Ey;2!g72USHx2{;70+j#Mmw*2?Rvi8JvElgWbywfr +z4^EiiR90w$B_iq-%C47`-skr|Dbp+q3<_&;T(9p;6|C$@h0wmS2HzKveP2H-D;;7D +zX#2RyshKVlk2ff*BpXL9isB>Qp!+J=d-gNl)Fs;Brp>h$Y4=UPO|-$i{^}$duM@kx +z#~XCxqv-Bz%#t$N;N!g=uIcx8b$NWo8`N1>RK*?aND*!DeINUj>GF0%hkC5Rck?lh +zX$LEu#v3Fb(@)V|xcs@t8|eGTG|A~!zyCxV{1i36f!yoAFJrvHbh%IIkNQflX|zF7 +zGxa`Yk3w}tv_V#0i+=p-F05&y4e0HAe0=xjo{&7=pl-YQYxwxcdHg4+lsDMQF7KB) +z&hNiJKTR_HT+;Yh<(H3M-c_Z{^c8RLaVyFD``8yn9c=*I>p)VIq-_#y!0zP-G)Y>S +zvv`A|uTp+3D)o7bHmGh@|CRKqf|(g@P{Z1wSne;6InoM)!~Jk2=1%c|F}) +zo&3zYd(oh+=Ep;oLpsFYfsbYSUiC`PGApGrpbB2{>CWQs(3)h- +z3ent$M_jMp$)MBRw~5uZ_AmcOU>GA-G6Tms3T +zi_%};v{NMBQ7RGh_qT>I%i|pd3h+39S$IvV_{sy@snZR)rv;BsIn(Kje9U=%e~*8r +z8Gr5xl|MZn;ypPeRjtO$IA(2Jz|6NQ|El<0sgLh?gQ}Z5QNDi+I=cFAxBDpbOZt%W +z9PR4cZEV`>1x0i#HY-#X?wKZx*=eCUY12oVD +zSLQu`pQ3B?_D#p684T&aMiOuEF!iSzMR^;dd)n>Wlxk32)5|hCnm6)&Q7K`={2-jY7g=6k}cG>;0gTlzkMKHFU%<`(bC^t=DKasHuxe&X+t)kbEd +zzg?R;{uA^|stUHesl7+n#f{3Vnd;9+TDQ@S_m(F;nZB>}d&Q!2@|KIV7)gCi+pqXn +zr@w7=E$Mci}w +zMYBu%9cn&)eJ +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 +zNbu<~oBfr%byjxW&CWlk#}Jf@Z- +zOR>voBxPl#=Aotu75$4S1!$DKb?cK+u3aMu?%7Ar{)njBkJC>ey?+cX>EE49xNwoj +zIdY$L$lGV}Xv;K^jA_`qn6$IGSUmj(>WDF^d;!Q%&#|^dZ#VtUQO#CRZ)=*e^i#_@}-NU!b4cOC0Wfph7V>)c|gGXEoOQPZ+l +zV90JH5PBSawCYi5;}mT9HD{Z2IA06-TNgJlpo&v(LZ& +z!$+&Cy<2FMGTXnBEs1srunqYG3agq5%8sn$-<`hRHixcpnQPFAS+PaYZN{5@c6|2G +zC;gZd6wQO5gB-YQm2S`}bhu4TSDJY^aX+=W0O9WKGih|M>U*PC?E}*_C_UiyK}y$Y +zKw(CtNfHtES%#;92t4>UO&#$@lNBpf}sT|cjyy%oOwcq`h2mF4A(2O5}d+6;J?S6b!m4c+l1`S+yy9{gRB +z(zZINU=RswGf@Az4(cP|YBifSX&zHlb1aSgZ7ccPYx|&o8QM(`d-~gQ7&TwL$kk;@ +zn{_9QJABaS$VOiI0-ET@%%!Vi5ON)mw)cnhi-K>YNsePrGG*Up){xcI=GQ +z@-qWVN0Eq6w70G$49j!YTK#X2M6}W#=}Dvm`Q!F59n%{H$Ei8_(*e*Zk3>=>Asa7) +z>S!kc*Lv)QZRuL<@f-9fl23B#0YdnZe-lhEUJw>Q+yw(ZwnGzdiOi8&1=1ALAmY|| +zAZNMK9Q$M22=x-=Q5=_+2_z0_d&&=6OkkPJ_tZBx(Hj#z{Plk!@E$+W1^z=<_HcN- +zeM7X~)J>m}xJ4vdlgG{%{Q8F8+5!j^*$rO+|FFw3g0#eDZGLDkE^sThg*GF9@x1N5`w`0Y^-ZeH+@MP!Y+`%ftOY#d +z5t0(pUw8|-lU~lSs@qat57mG*`S6jQ6uQGe0ZB$OT!J^vNRuoFZ+<?Kp}-Ky7w)nc_omPn%H0z7?pPNRB$AwQIrr&=jV_>Oq#Tl1_6 +zHDf(hkF6@S=X9>VZ%%hR{?-}ILlGwoIqlYb+BmpF&bNrR^4gdvDfCF}b5iPQkXeFU +zS?*Gu?hdA9@{pGq5e<2R8D(vn;e;ynK-R?TuynIc*=DZijZ8eATbNUvWd*~D%tE^_pL=!HB8)TT6C1SFIQ=cX{EnJgXxZ~=GFm~-w4cKYd^f7v_au)L*Kw0av +z=%r!JV)c~P3RkN!IWnbLI2iVLDmKw0(f}(b96grfag4{6ltB;`x5%V&g`C0eEbKWv +z1)HH$oe3}?a}-j5kEn#i5N1v +zf719vT50ZZ@U4slFDKIZoSU|HUc#tmJhaYOC#0=W_lNb!uPhr+Ade@pg?`xV4X;u; +zIS{KH5A3~sY|Ykau~hwz)=*n2pV21#Ge4vFdE1P-x|11uZjryqQ1b!8FG+>eE{tfK +zbvDmQPNz}d!qFxjNbM)BMWn^9xi^YFwvxZ+T%QZ3R{{42REh97Z>z?t|SYH34N9fmaSC?n!)&9vTD949 +z%oP1h`U*~mCOn%SgH!iaGRSAG!SG+Z0$}(4iEGpFUAwC9U`h2J2e3OQ#_%xuGnfqA +ziF;99B4OKf!}Gb)cfUG?sF3Hyg!3LOzn-;WuMJsws$bsTJP@Bip)x@xV^Np&hnUnE +z=@wPHB{hctQnv4Hblz +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 +zm)P3L(cw0o1o{S1wIr&`s^D^E9GuQw75C +zEOZtG6H_}#E!~+5r1O*2$GK7EqmL!|C_HA@2dO;j9+^kWo(0F2q`GLWrM{1YDg0X_ +zSlLGUBZad5xUs9IpMp5)6v!?<>I*{GbY|-U-dZk@qLE|ok9GZjD7say^x+FXJQ?fy +zcZIT2b1Rj3&ca&z@xgA*gJiz^2r;fcqE#y2rWp_b@Cw*;KGO6ugcX;B)DaERuvNq| +zy5r`k4EEc&=Fa)%NGb&`kpjXTSlz3EcbIZM*J +zIhGZ7CXk6+%F!o9qs|#P{)?3$2&)0fRgv#L`XlQAy>MU$Hl9Gg+h=YA#qJ@Dx +zkOByU)AsSSuHc!ry$d@Hf=-F1xcpK*=(me!xJUwV!f<#Gr>Y^@dMq;su6L2ueS{T& +z$K@%>UVi8-D6~*GIf5ftdgN9&Cy6GL+?5G`@9Z)=V&^^ThCi9HI$GDtMSK4tE=|4r +z$^6;tHPLxtk1F25`|sr_-cP*#MI16pm18@=G^OUVw0`@RXYew;^ubr7wat~}uTV%i +z7e@GJ*ON>qyHH*dA2`l(McG7jmJnJrK?t&ACR=)I+RGE(-&`_?x)D!%4>zB)?0IsF +zZafSwJ@PaOD06n&y5V>_uE3j_BnY%4QsA^5C4;GaeGAYD&n?B;kxaZuNSW}H+6H+L +zeSDE=n!JNIxWtIRJ-0v@?L=R3$>E@I94znvcxqf_+>2oRDSmfG!+Z!$wr@1$)rBsc +zr@v+-5H)EK$DpRq%@7t_+ENuRW +z*xPx?2N~>Rn`iyeGqVJ-QUd +zu6eu@;#3rmcUxKN+~-c$0JXo+-g$MVw!R}%*i*bWNBy-3Cr=VU!NJ(uR!)gl7;Ka| +zaTI0R<&3KK*pKBPA#ak7>oc<7k&J5wUSIe-NK~C1AN1I%m9fhmi*1pV2JnIW9mPmX +z+*ymn?a?{z$diUrgw78^BNYSg2_%D6)${D%bJ9Lf2iEb^8@tne@;x(tk>qRXJ)L53 +zJ*@u;we_8xLN!; +z;ebufWASpG3Rac!j@G5FrMx^rrEsyn=>XygRXoy7#zbb)%!xaN8NceXkr%MZ6}X0X +z<@olIS8AML;Vj!1fr8F0mzZka04u>e(t*oen5I07Mx0LU@W?3!lXf|s$`9|y`*G;U +zow0pZN3$(9yEMTyKT^Z}7}d>d5jy0T+F9k03aQ2b;qu#x+8Qe+!V4gaGqJ^=ucyll +z10dm)0M}#qvZfT=2ToDuNs><@&O7!&QZ#=(Mxr^L*wWQ@}lXIX>^$XCUr +z-9CXQjMojFFjs-tP?b)H#|_IqP8ph$4iEm`c*kxmA9${3*~Q&>nQhGHuf#-xL;fXu +zX8Dx!lKe&Ze={+HK9Q#U6a)w!?T+QE-VYAK!sQGo#AnST%COE$Js}EH(+;wtCDq$9 +z=(Mw)M8eno0fDMdd6oPP8HE+O+!W3;H^_t`&PGe2e4&s+D6So`Ft^rt3rPHyHZFf4zUPK^+h?ypt +zPDC4?f`VbLr$3L3t~==sk|hYovGBs)KZ^}Iv?5vyMIPdPR*6!dyk94nKu4ak9=%In +znC{~&HJYLd_t#~sTLL8L3G5t7klSd*q!4*GQDx2-6qXf +zNx=*srVv+B>u7oU9DzRHgZq+Xjc +zwe{+FJU$a4``LD=O2z^-$Zh6SP&`KljIs2nrOyPt@}tH!&mJd))8NuNT1Oz`#P&KV +z%0N0GQZ3*@U5UlAeRabZIBTn +zPD}bcmzSaMOHGa2$k7T=iU61N^)NU=@80aUDSxelU_ZYM+~r|^d8vXFD<1NTYs1d1 +ztcz=}s_N`^tceKZk^2Q}qryf}1Vd0X8EU%2jRl4hxvCPXnx5*_P#fN1dIyn5`0Kc{ +zFAl*48}troGn_ZE&ZFSHxoK-7ad-1-4S6;Yci;>mkF=c795Y8X&6#8^pjJQTy)vw-xq_g##_1!wjUn%6X +zsYpCiVt^b76DR+~?I+};?w=L(U*1*xonbhbAWcg%4ao$U&xIhQwfE&T7?euCK`ylS +zmCtnDX0nrIXg6ka*>uQp+tkB;!(lZpEZ>3J +zqn>qJBPg5JY!r{Xo!MoIXUrWOukhCdNtt@*4O2U_=kYMDVsm2ck1RFnr6jn*zW*wl +zVU7pQ`dRmf*Uy-2$o1yb^H&kQ!w+}&(!L`dzpz~yGKhZ7=+&gQVJMb2s_1@xKUK5fl<@GkeYZV0tcQusX5S +z3mKE^#VC#dXIDLI*HWKFZg%qIomX*9TE{?pU}7QiTR=rW%T2uDJ|nG$6Er7|x(|SS +zb-H(JUhmEQ%ClnzlrE3VCP|I+O>~N_ixoPgyWBQqLn`_+z0_(fJ5#WUd;3dicIArV +z^3pPOC3*^le%7nB1P~$BjUF?YXk3v=2x-@JY;14_ywJ*yAL4#Abpr$eWxz+Lm=Mbg^a3v$_wvGeSJZ#+a3X{0w6=9y*B +zXtnW@>qib98@Ys5r?0b)UuWr?-F7DoZY6$`u66{^A|Y-VGmla +zi|5JKq&Pd^Vv+-gR-)5`3EbPA^^5N+XWApfQ?~5TK+J$WRG`~Yory?QA&hn2QNXZi +zW$Id>s}oZ26)MMqH8B=`8ByV96yS;L^1d4nGJGsZ``T-L2agmTeh)1JF&jL!n~${) +zAut9(MKMlCEoE`#cV{U5#}1*{B36-jS}S^mq|v^E4IEj7=`WwG?KGOR=Hs#7g0u%K +zKi{z7OP&{AzdjPDj7c=qMOtS1(E)WSX(O_Y0zX_Z*Z@C3z`wIwDn6|#%m;Ib(Nj0~ +zlR^RzNIkD65c^!bw6Bg#;~-O~h^6HdfF$#q@!1xR +z5j7vD4^0sq$@OM%I@6=A{TJcj#fumI*!{BK5~DA(2QfNucN$XO#jJ;v2s9KR7Pm)d +zCWigJ$j6U+cNLmnmeo$)ehMm^aaGuq^a8fh-DpPE^{G=)iC&y#VBU_xFJfM+EMf1wgI0ZT?ww`!D5{9@vT}k^6_{vyP4UaBAs+>%stC> +zxY6-^UMpq|PHcayomh>jIiGWS9Z@hIMVpJerhj_=!O*!*Lgvr?c+m13XR81ek#tsQ +zu93~8Q4#N%X~*rSIY)k%LVL3y<=I0x!Ja6Wi92Li+kq)9yKvFwaonzxSXvJsM}OHM +zPxAH!aKVT#J>DN5@B8E9ZM&tv`Q!Zq{iz=BfBK7O?;!qnJ3r{bqA43M;nGRFHB$_d +zDM>L-rs`O*$Gp~ca +zEbBWVWPIXs{kExO>VcZfbYl=a^;gT!-qLdNqq2SL4+Di0%4N!N23s*d?5KrZC6HG5 +z89P|h{Zx`r7ZaV9_eap)oxc?Z{M2&2$3&fss<%aF# +zAtS9sVxzNE=L0wG#xi?;CxNLMWcMM!yIb?Q0TG1Soh~%{@E1e&=C$a3|1jITS +zPpBTc#QLV2mJ0FOmd1=7dbA$PEXaQWPkPgznZQmXP9!=j8xn+l;gat7}s?*>uYm@~K7@anCAmMmn5GTUvA7cL|dU!1&OYLx4 +z(m>FX^1uGC+Z)J=KRpNP2&{H4i(UuC38Bv%qFVIPvjAL;S8F|VsBZ*`9eUp5RQ=A~ +zBN{jTIQ?oWJstH)bi3P@ySHznn*}o6 +zB?3Tx`01y|mtS+P-zVU*)neNmIP4MeQrhP;V(wp)p!Fy4^pDd|8+-s!orP&zH}}*H +zwQ|=BsBP4@5couD{tdu6ZeD)yj~}eWRR2_$S78@Hd2q-S)aQ33lmI3656$6|#je?w +z?!s5U`f7thor8T4FVN>-EPCQ{?s8Mw&@3_&lo+9=)*!LCYT#f$F}4U_IIH8fgrCQk_~f%L)8GOBt+%tc +zp1?$*cqCV90!KJV{M-yCQ< +z^0-K+m$E1rEXe#~CXO8Z0myLu+ +zZcMr%@oP6UEv+BZt!#rHbQIZUqxSg){Of?2?%hM|Myh2;cZ;3~K^hcJ!DZ~HC~l6R +zJQxuiFHA}DF$poXdkuH~Bps|y*ihzweP#Wi3@%KUX|-RcWVxTqJ=(yVDTI>-7Hl@#Q*Qm*st*SbI_ufafvaoo2JlvXm1h1vF_%d}AOY#W>T;dqYe= +zF-<%r`TJXJN@g_72WSzOv>O9fm6$T3CoD)6OtXSP?sJAy8DJ=L-mP5DINS_(ugDUM;YL22edimy~LJ!XKbQ&eI(} +z<9Ld9bRc12kwLEN1K{nI8K-_5nyC$-wU9foLBrv=RrcSb{<97qi2<}f`#++_?0YVM +zoYISvP*gjfCSRQsH6iglj@aV_GGyH*leiF~Iw?&IDZcc=&`7z0u=Z%jI1$qzsLJs>o +z$gS~Pl;|l@2o_Rg9&iY_wS`jKx&T|qr1+e45s!9%`~EKL_jh@|fW1xR6A=;1O~1Qc +zoE6?hJCg+e=CC@g5W#~T9`@iVz*lA^SLt2Q`bpITa-}2gx2U&H`v6mOWy6Idc1M~{ +zBAJOJGeku*k_N|u*75@2zn$Hi#JvO;*_O3P8|PpIVGS2-n$mnXc?4p-;Aml+<^cTb +zgi>@Pkok!oNOfV~$X%~qAy(dQtzS|#5x3lI+z?$nLb|AH*Yz?zsVA!fUsgB3=-|uK +z_Y+?cafyUH18&(re|aP1T(RUQ4suWXk_d^@b(SHGT^?)`C_%)5=u?Q+-YmFu+v>qc +zEBKNVH5R~Dr9}m_tGe?%Z0JraD7_v5bt$v&9pvn}-YkjD98 +zy8x`gU`n@i;D;JAL`D~}p}|S_jmr~Va?CaN>c66GwE4ooKe+jo*d8`F^uODe{Aayc +zFA!osb|g2-+YWJ#FJSDlt8E`413H)fD95YlzJ@NcypzA~L*wHPAsNZf`V0H_kL-$l_neq~-RpxJEwPya%MnKm;2 +z*{lzDfBbafh;+IC6A{r*#Ts7H_*_`DR-b(Nr?3C~tAG9C(?9;^*R<#w##1faMKS2b +z{3lBP*!s^2&Gp>QA42`G-IM_TT>aumAkj +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 +zo~~S(f}Bz2+zOuuXW}Cjy +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 +zKYX8CNpUOpWlm~~ +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 +zEzJ~ApdXqb>MfV3a`hTWYTU2k`ixKF>E;+* +zIl_Rm$OeRq2YhoG(H1j{8i1Y^aEg3(($ocx9}IBcLNnF%GQxkVr2(GalQu`5Gw;GP +zNP4=|w+qhpYF#l3k{W`j6%NI>fMduTe_glX&HCf?QbiAa8h9BA%A1vBSxNSh!02k& +z%lGZsFOb9!gQW8&ok_H|W@wNQygT-kQbTRr2WFb1Ew$hlvv3scY9Rw;zLo}JvQ^_D +z6(v>|FZBBU?dZ@2z#vGoB33fV`4)!Z;m5j<%LkuVf>~+4!R-KDh<1EGOgUq=?Zp)$ +z`w{0~(L$#`e>}C>25k3_^so>9@q?EBGYeB9!V^-KA;LWNbVEbJ7&erbJ`71rhpZM6gN=0#F^Z)r3WiK2PUE<;DP7u?_2L}gpPGY;D^W8NH!A}CmRVRV!huKw=^e3kMsnC~ +zjn^rh$4Ax@U=0SgEV$?$CdQyGQz1Z@1SZe}pO07joGC;!#@R^wOh+a$gGUTV5SUCu +zSvJlsbcw#}C*3e)Ze0MsR%___w@&RTcX%ghQ}_oU7F~)k263TTT8$11TjW_&OR!3k +zjRPW%!p=vcX#jgCiKuc8Hv}{ymd%L`{nn!vBe2npE<10tqgq+`Y_RRUmJyeXY{@k3 +zB(21nitbB`4KjwvViz$`KGuR!K@r)v~t=sW+ +zGvQix8AjC%il8O>2R?k~#P`_a64!YmBi6(yoosWL*U_TZZA#B%MOR4$q^yA%5nfM_ +zP}w5`uM!9}Dej3C2}gyjrbP7sjjwOUlKmK&tX`!WK{2DrxUAP`Vov-IBlB(T5O<27 +z00(e}oI$q?iKx(^q`~|4z;|?p8%2F#rN`*W-r+O$L_ktnQ~qA(dE5P%pXDqvrJvF^ +z2BhaT7K1j33A@OKVULEJ1)4M0(|;na+9F!s)P +z9;!!4+y{UIw6U=jCYm1tTEh6HhI=9q6To2FD9#gdkxK{dJb#X0t{@R2tdqdPB9S=6 +zvPN;i0vGl375Y|HR2I>zn+5INP>IKH!zL|RGKpf53Mpc$?5B{H%Gk(c30>%D+$u=# +z0pCE5-8TC6n>Tmu@!P+yh#bvM>FR+_Up>FUIla`0HWLkOqIN7aKnz5(*#ui0oMHs9`Hg-r(}ye= +zE(Ef0Q5L%MOmr06gBF!ImmE3J#WJ1-67Jmg&A84~V7$XVTfBKKt|0*XlhjZKLc;RA +zG%Im-q#sV6)VPWH*BnR8*}rqhnPe=7CJ!+?(}eiE_*|zjEn7_|Qa_1}Mjmx59V=kr +zH|I&iB&FpfOF%T9>^|w(o#o_8E<5cz#&h&$9(b606kMsr#<^riAEXQ9RRn7Da$fie +zF_NY}c|c5>mHPooq{`xaw*NcV^1pK}-Pt*_U^8Lq43XtoC(cjdMHoW7 +z4Qzr_zt+~bH_u8)EtqjTEl3X?ZGYP22gJF(jigMazR@LnIR4#6rF5aB33q{4?n>G*e%Ao +zDV#(@ubuAO8ns{n_+y=nTetiphBIH(ell_8ME6?P0i0oFcg_U~vxAfqhn*v=gL!75 +zYb^W}h(PGX>v!4V9kxRrSq7S5qvlobmzYMKXn4=KOSX5-?C10;7`XM@Knc-ga% +zU)Xge;1}^?NzmFyAA8|^3NJn|`4K0r?_6imVT|&TVHW{HDDp0cqBqBg=*ZQ=j?2pI +z0cX|lP3C1xuNQ(m?*>mMtfA#X#jq$W0HbYzASW2O6X-15dm>nIaT40u=o`i>+=rE~ +z%4R!iDi3m0?vWhhq+zXFG(8N9)@-3_d!2D!HzoL-0An*S#)Nj03oF5s3j3uxiU+}q +zADyLUE<^+6l2WP2$$$zK(M|ZoX`L+B=*zFnOZf{+Gx? +zu`JRa=AX2q6brplDRc!=;^4qs$U-%_;ddQ#HLBee17Ye6rlYez_^aRMkAVqaa*WQGf58T +z#WoJ4V75#nmt&0BWJl$BaUpvs$+$Awq}#TKnY;JCv1$@Ji|X-Je6K|vc5F`*N?XC9 +z%{~;Vg&w3Np|H3))V`|kkL*9A+mpVBm_h_A${A=eO5LA;ZwUYAl=hC_of}7-) +zYbq!_b`O^|speAJOWvtBm7v%HN0vPjUaP>>*dz|S4;6B0{AoZ^OnK2wc|>sW-n2K? +zG||o9>(8fq<$wH37ysJ=klDw<*A3MO(+E?-sD{Y1da4VFedqo(cahVrObm|&YC^=L +zTdy#~MJXG+L0_ie*op6Mr_d>YG7TJ6u&CYjHYQ$(D3uC*K-VS%wc_}VZ!wI01x%}^PX(kQK#dVe$20by~&&OGT@sW&y +z*VR_@f6DR6K#--Y56~N^Jo*NgK2g|uFlJ{FuT7U2L4!X4<&XI|;(L8Dow+M@DidRS +zb6`h^aB#Mw)bpGOX*)>8N5k{o3=3xB&tE!`t*;HOfj|kkNKSE`zGjmB6_=Ep)hN~? +zARF3b8yZ}85!JOTISZR<=k6@D8wCtgpr>^sCIxqdfl+3q0xtJ0l +z5Ykl_?*QQSeSx-~*pBAYrsvoG2)&YvX3sJy{B@Tvv3N3&NJ2&=h^Qms6M|phR#GVg +za{CtKQp&xnZgg~nbf}LJG7GXQz82%e5%6VX5X>jHUwh&c=#kk<5OxN;+v$gY+n7xb`=s+6KV^1E#|pZ(^` +z{pauemGjkXHm}Fe{`Kw(a~n}i2E@ +zl&egtR5`>ZZt~?Pi*4&-8wy)?&52~lsbC_H^z@BLC6(pWCs#5_d4IE!-@hFecgk_f +zVSuq@lX5OdAAs-j1$H@YH7H@1fp$g#YzxUf#KAg_*i#rcAP+k_6+(H!2-B0O4tSEO +zVt2&>qp%VO(DSh0Gx=e(6hps4w6#zDlt|~}umWxKh{T%FB0VY>@_?eyi7UI-ntRCD +zZqc-6=dExY^I%&u$r6}kkusfpZX1UjgOZH&Uh*B`P?8c8XQ*H*XDqLpm6ZKM#Tww& +zO}UU+IToYD)w^8+*pwFG^2}Ahb0qOM_Go~hUyy;LU_n2e6c$SN7wLykkryvo7^6FQ +zN_oqGDzWQ66Ppab26)Mm6OYbE7FYB#T6U54XwLj?B|q-g|w!ztk}9*5}V?PA*;)Nqt}@3a43f<$y>j~CAyt|;hB>^wA|Ni=FVWIE8qt==) +zTK4w#d9IuU_3QswO^7=yC(;N~8hO +zK#Ohpkd-A&AqlE*)CK#r8R;%8K8sBp1@MYYc8F9L;_h?IWnMoEH<#F7iMGD$PrWN$ +zI|s9b;KPZNq&FylctTuN6tXvWVh26X47n;Muy(R%kGc}WvqaOSIOCf-fNeWt+Y-`# +zpdC7q{!8%?W#lB8#qm#~DWhW90GTWaYKIatGAsb+<%F_8d<6KH&JK2gn9v)prsh?Q +zS#ccwna6iJ~$2Cg;8fo`F*}rLyiI&Wjb2bg+ol~!$LIap4P?B#q@Hbo*U(!C= +zF#uXXrN2wsZM$HLmGV1|{~^KM;jKv-pM*q50|qj{!XtB8Ha!YBdwC>{r@RrAl}j5F +zyFJ4IXpkUD;B;6YCD&I@ow{3ez>P(HURPn~qH3UI=y9Njg46FbLh4%8K!L9d@-SV< +zPCe81YP%zWcC5TV=mI%|B`066uQT^tCZRWiVF}Qpn%KuA6Hdq$T_1;~6*XYtPJ>QG +z17$Gvpwt1_S;EL9xi7!GxccSGX5+qu7OpN@y7GYXIGG?5naZ1Bh>&ai +zOAJiS+OcGYBMIW;8RiHvFLQLyvL0z9gS#POyl!Ik)XIfGs+I<)Jdkd&Z8#9$#~+J1 +z6yK**9OP9!W^(Ac1Y+@scxx&fO6+ve48n-Wy{p8MBqe73q{0ATDv^fbi=izmRD}w@ +z1K5cA5!DIcpE2qw24BKtB^-<1B<>favXrBx%cN}vZ)i9E^23iqQ1TD|3KKWS;rE4eP<&%( +z;YMm>Iqx2m4i(T6hD}FIwTkMY$$xnU8p7v2tisMHaJAxMARWz5ACwia5+l!5KKBhx +zY2SbJ%MTNn<%xeq^rnpO+pqGI4LbB=T-hFx_r1WENHWTX|MdYG^lReu?c^hBW^Z^^j!giP`!-X;mj1%_(Oj6}-)*3*Ptd;u2Lw^WJ&6*`76@I@kA5mHh?} +zr_~XA1>qY`Xfyz-9}In^Njcbs`Z1KmDsOzB9;h$Gv!o)M@$FE>*tYk}5Ao?cy8J7P +zayqAv(;n|n-zkPv)&k^L(0A3I1}K>x5c<b~v>eK9Twd4lwDFoPPPCt&x}^STj{ay$V|&nP5ww>>+Bm5r%>1 +zPC@eARmmLu<%fYU9mDX}qP9~vwm`#3+RuCS +ze}xk8cAPZ}(7meMvaTL1AS%O7kgn+ooKq6PCLZOeq7d<0b=f#&15W*I`pXahkg>6u +zeT`q2JbgcA#{2wXUu$KikMUATqZJ-F%wyhBmc^MZb>4;OQC~&gzAYp$MD}t&aB>8% +zH^|PbG|LUC1t5c_-o@s@I1l|d;=BLlhp%t&0=C2AmSA~Rk;48OaF0Tc8V^2Yb(A|_ +zCzJlVktcQJW#gg<<4@9>ispZ5=lUZmW!QJo_(t +zgD>JFp*Az_T9@TSXIB4Td*9kC$8nzdeSXCW4|msOPS2c~b9fafhPpXIBwG-f1RF&h +zR9~j2&-9I5-E(FR28O-a%_8;+yICY3Vi*etksX-gEo?(x&MwTI%a62k2K|iJA@4e$>BEMN?j4y`n-$RH@>i4@o%1i^MFDi%Kxqw#BXq +z7!one2w)VA6_%i58MpStShPHeIG9^BS5!fbSM?3_M24S9mx$VhDq_UDO^Bgr-7&&c +z^d-fY74UW)thCludq=D7DoAM&rih%#`fi9Db1gzSAu|+;lulFGP6pbIW-s43&@&+j +zJbNZ;12i~82WK>9v#HXj@)?r;Bxn%3kc4v&7DAw}Hu$2+69TnX5)~*7`l1*D3zL$} +z24AF6;zT7PgOeS%n%Q~C0cay)s`M;T%>=5^S`R}+q-DKO$WiDpq~XgW+VUP25W(}d +ztANacpk<(>sV}MAHIP$-Go@QY`G4D7@K +zh#Ob{cPH>PP+P~SLU-FzBIG3*_rn5KUc@1oivuEHJKcG1)Kivy+;N5y$}z`)7>9Gi +zty@SX_fM&@8jq@*OV+pEtm9j+C;3-R!*ZmFX|$u>)6>&FjAKs!iLlQ66|3D4g+*P03; +zMJ7QiLVwM^GNhnQg +z?M}aT?GmSN+kDgc;Pu2&uJ4VmUghjL?qvsVrq&P+G9E!j8i*8)5i5^QTGUMdvhqEZ +z#_03lR7|s-b&W2mE?7GFTfpJ#>5X&45p(S{u}>eZU?cbUgGmp|at;J-eLLYR$lo9%% +zy7|Nks=jgqu@qBg9Ylc8f3d!mu~}x4XZ@rY+$2ii`V!d4+*E15I>kysDvc8~&(1-YMiC@Sba_@(yz4{67wxjt6-1gYpeZh}4my~^S}NQ!09Cg@ErYykq4o5_SShP5 +zEtaqE3DA`hO3-Uc#C4Pku!&^yr!Iq=n`odyrI0m{I7S{~+5j}pZ_pj=^}MLR0_z88 +zQv@Q~1r9^?qH0PG?FV@}_Ul}wg=wJYvx*TRirOkb8w$0~t245Nwu1dOW|j<5Yjk-& +zMT1tWn;m|mdK|KDOvX379|>CNsn9s{Fm<(gjyX%c&Pp2sj)%^@Aj*82lz426JG4BE +zw#_Mss!Iv0ZVO}*6z0|f^ATr-*s|+kvcROb_dIY_ZrofjnW6W$?!01w2X=K$JLj87 +zz~4k8>29x)<3xGVY$4I#Z7ruG!)3d9 +zh|=^`Z2C*doT|ggN{G9me-a$$9K#)l+--u+yfvw#?du(=I~A))YMTjd{Xtf@#y1H` +z6drE*UV1*nXK8K516s#8ACxQW7@3c|brBA6{vKTh-^8sG6GWk4Kg +zv;Tg!P-;+@I%Y)o

|1XF66ti$$iA +zsa#dZnWxoo}@?mpuy>M2fVCYzux7 +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 +zy*!~Eq&}!QnajOSs*`pn9ZDopcbszNf# +z3EkR*?ZPn=O<yCVhvjwgwwic)uM>zUTWpV~GiY +z2n%ON6eW&(Plm_!i;Y`Clsa;@M#+8|jSMkbJNTDQKGw9w;cGzDog$@b{4QbFUJ7aN +zWA^&}Lo6#X{^okev*-DXlG>ifkG%4@FW{!H=wvud$miRCC2+n+#Vytl=m(wSSHBFr +z2B@S}(n@j@!(w3`Bh&9a)q9?NTBf+>N6{~>z#Pv_UA;qJya}%fGd!xmeAwtEI6`6+ +zno~B-8IKmL9xLoztMMFA3D%$Pe#J$0AhX>+#JJA$q67%HIS37dbv0D{rT|vMAj=LP +zTKPu$XI>y}MM=p|9MHDeyp^!1(vOj%u_B4(8db+U?gB_%sm9a9L1V?xM`{lJvX}7e +z-TailwwoT!+JG;S0Kk1=ABz1})<4o4@yBE}PdyIblI_k{s2V`Kd7Iq +z^$3XoELr9VZXr9wOd3_Bo|UoHA4no5Y`2EX6pLY*PT7iZL-%4|fNZ&0(mXOQ%6!cO +zHG|^eC~hp4op`$C(vcBYGBHDYmgxWh1oAwV&Rg0^KUiY+bjlVfEE3k{wvR$p)+E%d +zf*I9`Zr69#hC3dTCR}ZYk;X-f+t8OeIYMdWC_V +zl&K*{=~kx64)sqXXX1`Ze$sdLg7zm=7zjHHas%Op{2LWIb&9*7Gvkk8zfDF=?pq3W +zOR)9l@MQ@#gIMPIj`Yk0%TNlGl9PEEUyM#Y=3l +zmu`hc$^h~t)*SSMfbr4hw}pVI<3lnTlPT1U(^@ljX3Se?b(0q~S%&J}7YT(PJ&Qgr +z(Mh7ZXqv+uvUBUEmhnPmUZf%@Ww}r&l#yRO(`cUiU{0lRcMz~#xji3ywpwJw55~-#^Ea+;JJW7PIJyY +zND}s6nbMKT(5)kOv?E~hz+eT|K?dc4g=7QHNty@>g6ELr>{oTPrY8g%^0V~Mi6<#T +z>T$Lh8hGaPKP)*sg!4-IJI!^=%8ex<30S}6II-RVIMLJm!=niOi-MQ$?&3QC53-xh +zn)P*=`YyGNc{lHIMY2tb6M(;!6%yPud6&tozOZLwZ9W^QCQMv{n7ML}2Pj5|)iXxB +zCAIE>ekU^O5gBII8eW)8yi4t{E#d2?bA#L0+Ny21v_P|GL2Z-wU+GZ|b=xlX+P&k> +zd1W>AQsq-yk-3aXQ7>wZMm7Qs1VJmRX;itE6w^t7AhON$4qIV>Z5Eo@4+|z%mJWZG<^AH5$7nG7xyoH*0VmMz4sFZ^`*0SSuve+!UiHd`j6v_|+-`v|0W$9;#qNnl +zYuqnlTDM~~M~iI*Wfj|qe<63TkT~c>lsq>gm+`7^tH7PMYf#vUviMbaL~K1f +z_*mlSrcPm1BPk9U>?)l9_wPuyi+W6piu9k3L;$-DxhTg~1*jD!P&HY6dI|Yp-zanQ +z2!_ZYwvoR%-m0N&zbo2bO&?ImrS1$2`qjyht?|K*ImZ1<$-TZ({fi3mVK6?nQ=+}h +z@CEtKjualIGOE`Rc>rzU>Um)Ro5km}w{W9&xxX9qzi6%H%Df73V?kb4oE+AlnrlRS +z9l6B>V(Z+R23sjZaFg~yve~CzDxkW`m}Bzi&Al?hMrHl5NP6iTtEjBN&tbB&*X@{^ +z19eLmPw<(zF_ICKwM%B}8Q8^!vKj+aS%qv^XH77Z9n+ +zlU&{QBVWnvw)ji8fA1i^q$NoD2LXS~(x&@2R%6K#Ea8w*>MfTorm~{9$PqGm2EBhm +zm>Gb!& +zYjvQr^6Y{Y$roQ_w&-T}a69KCekV!_#|Q(KP~S0P<+mO@<_|}?V~ak^!S&; +z;jwsR;yx>qC;2B}6Lz`1+iz97PXo6W5_Dn;$r59iw%cki%`Iwk*&n*FH9=Q8<3O}_ +zKzQko`OVz#A<05!Km;BdxB!qdmW>*$?^dO#+tqKQd_s$nmRT&wlpvA|Omz_1o8Wi_1u;}Y0)e5$aNW(7USW#aXuSWrs&^+o9}J>V#*UI6=OaUEoq +z0+5!D1s{olhxno@dpNKGg!tzpbo_~LhVR+59@h0s2WK&KT%3-f$~!48XnfS#lhX_a +zgwH{8j9{=;bQ9Mq0Wn*JxfL{c!Je2^1!Az%;UZ+rij|tDuu0g=$6z?+f)1|X6`A$z +z?70CPdf?o(Fv7Zmjou<;9jW=H^%V+`0HbqAZw@-wXg{aC#53i7QRr+jH5J54KAhvuIG>3;0VU +z5T2jgm*)>=LpGv4h)zjd#}|L4wdZ36zm!$~GCj5~gI|oEKSyxAyux<6YL|6Uv`+hz +zkJkct-6m&)?gg59mV7l%+cR*J+X6R^Z0y&A_ninAwk`TiEo>r~&Qyp0+{h^~?xhHChDcB;oX8&~ +zLM@D2bzv$`9K$h~XwX(B)e+6oHla8L8$n}KBlFp)Acs0JHRT?1vhgLo=UbpuLYb*s +zucdPq9fcc8F?g#4v3@E!@5gizG=Hn|V6XDH$`h=PnnkKJ7>NKNH?au}dN~xOZJ4;5 +z^h|}-mnIh&Irq4Vx}?%SGIc`WHboz`6?)*fGJEI;oDBm8dqhNbT?bz1*;-*xkE3@` +z%nam&lM)*dmd|P@F+U>w>kfK3_wRJDwA+5r$ +za>!g(&oeCI$~P&^abXG*J(2Eze96@cad#q%)M#L(WwIMLTK;6m!UVH5(GbCDWEKgX +zmNx*XPCkY$A4{%*D1CRba_l;0G+cg==lRhvSXDOPFI`|>S{BUf&alZ(1@Ng^(>xUy|ySm+thUQM8Ruj>TU~y-#j~G-7C`8>;#{_vlMzgyt})9M7@2r +zzpt!JY}`$K7a96#hL(-qI>ia +zzDHlq&LFKl*8|Tp_=SbLfjxN4ux?U{Qe-N0aHaKFETP_hq!&~-LQJ2S7Hzvht{|=Z +z4NI@>mES^VpAKB94^&f9!X+mp#i1xB)#diX1;jmr5pSNJgIW|xyr`&W1_sG?t)@&5 +zb9V4XG1U+=jNF)ag@?h2i(i5%B-3$kY%6!XDDSJTdb6K6zAa`L%}Z?guEndkKv?+t +z^KT96dN{5hJj?eNEeHX-lnWSWz!xJxvyp{_b%OaKjL~$Pxrq(=*p%|w&`sS>4-SZY +za`RezhrqZYeDlyYrqQO4#?J5@o$cq~;^sC5JMpDBWcm{$WhQ%8dkGa2(nsjLR7=vL +z?PxL*6TF55ocVh3=Dc=yk6tem@iJHY*H%g(WkHqtSl!8{P|I3XUXC~F3&Zc$Q-30e +zZb|0i*L6{orG-zMM?&S;WyE@EekJ}~OTsiaEgY~IHD1d0gy!>68K=oJ2 +z7)(e$!EOz~SRMC +zHm380Ciit#uSi@3roDMshs&TwN0kPUWe@gUtk69|#4T+#HOI=0_KUBa(Il(oYv$BG +zo~P6;N{K*0a5uP$)HR}3EQWGS91RG9<`WO}yp%B~;x%~+a&!@rgb0Zn3DwP#PA~qF +znA-0Q6*WOpcbz*!RmBZTVq%WkpoYXU3NMDO?Z$+zFlJ=i0#MXHozoDwNb)#E4Lm!X +z#dDldh)JDJ_ioh12v&L`p-fkJF?c>Tkbp#@|#eB^SYjrAdn921K9I>4ov`33t_C%z=?B +z+?0q*i{q148fhrfISh=f5VlDJGI0E +zFnWpi*XB$g$;-QYX1m2U_S^(>H+GA*UwsyoJN^5`ivp}F{PC(c(CWuI=E2PoeS3Pd +zNBbvU+mgGeCq(azw0_c+6)FKe=PsX3xXXr5_xegMP#kEdGTbAYQjgBe)lR+V0jW(+ +zg_jfFn)4YQu~$3VhE(P5iLABc<|Yn+f0)6QRiscT&nl6=2`$$TVq<>bDW}Pe%q|`y +z--qiyT*7Gz`swmJF&lMJoKXYQG69d|SV(Vld~^ncGT$@lyDVE6IzvEF72{L)1l>F(sab-?t=F{4w%NKUjO@X#+wb|5&^p3Rj_G3g%NUf#qe(6=X2t6 +zR9kxMK)*4;o)=8EL)qDD!>ENrlUuU;=RsvdJ_6K0w7qx4z~r>~bKc>LG{iEb{5!9} +z>0;lFKN@01mMHoyPqsv(=VFd4L}l|*s%0q+r!(T|fuqo{$EN}Az~zcDwfw#0?_us# +zYhI8ky{HUhnPyI`Ly|lu=cppx_v?tVm5IOEFW|))`Za8^{AKB%;5@#cS?NC!q%e(Fb +zpLWHmetXPX%?^3_h|5fy}qReB=(H9nYR0Lk&wrl=W1h$ +z%)59!CqgZoa;2Snzx<)eejgqd=!G4bBe!`O8cB34tmuXD)x0Ajtaf@GSXxI&uZHK! +zdmN|Y07(=4F6(gDri%211wgXWo@dfcVDv*v)O2SG%Ri+MyDI{hCGvL{k4m%ofj0WuD +zQTMFk=^%#pGp1*L{MBt((rdE^f`+T6ysh2nMsMPMPaXjWaeN0BQ6-llu}`sK#P4PL +z)htJOd<#%oZhJzDfEezDr_bFz!|BUS{qx`b$49;Z(&2zNh}y$kE!t66PE+B16T!b~ +zNv&_^n9p)6ZH#^3T4WWbICXj>(h{bE8{hSz%Q1g!3S;GhOmWQyJ}D`zAza)&a>W%b +zk>7!GqrUK$E?t_h*$107ZOD8Nib8QNcxCQ$l-og<3T}bGdfYb{RI`naa*NMaJTX~V +zn~%=NtSd9!(diQBU5}bR3E}ryrgFVHj!U49H1EI;D5;Q +z-2A%8UosqO?UxL%+$L5No{LD*Kx_vQyoxN#|9{Bv(MdYikj-Wxp8t~Jw}JmlhI^4s +zVZ&!3*ZzkL-^|s!$#C^wGCb`6lHqyg*`WVJhEsM~;m!P# +z;VD4BWVoTnFBuNZnHc^{hJT?^p9}CBp&!KV&%NFBxwC|0ct$ +zX#PWnUuXZ94Cm|@*9Ai(>rLkKIQDn=CBw}>{+A3NKK&)b8J}AEImkihVCBp;Zkspk2 +z03CDt9ad!NsuBu*$?%zx|B~UNzhwBL#Q&1ve;%PrB{GBt?9S#2iaV%z{LmcBP0E8Z +z9v-*F+p&9;Q7o{+ds#t%}e>ZX$c +zmG{QOd!MnT1DUzST4uc4Ya@Mca|H>ndRD&dL5UNDPngE)Yh}vv0$fQu`02N27GSzI +zS-0MmQqfjp`;_G7v~~UHi|q|7c?z8H{>^D|^Nxt3R&e7YQtK(7G6x!P!)jIUuD-#_2R +zl9q4{pdv`|NU4c>o)DNHx^D3_ +z*r6>DJCdY*VQ|w_KWd&-O{F~yJi+QSsIJDS+5G_T;_iUijsMLD^yn4UF^?pX*E)4RJljm}3WZv2|RU*&qHn4HifqH%>C!&2PF=?DW8F7DV +z@>{9Ot`-6^Tx81wijFp_o)_S10-0aDng{y`FFbrEG2XWS0*mpybYvNr_&h%UK5Y^GcN^1$98usoU%{jSExJked~b9`4dv1;8IQcztA}D=Q?h3O3OWx +zY+@O_r>xuP#Ne6t7maD&-<%2)TJ55S&!anNo%P=YCJ<}qXiW|>pkxL|aV>12oiR1G +zO;lfD5Qgp?TIDG)2+rXQhF7hHEoc5=;!(+wG<*{c|1*dVRqC4T5nPmk8WP0v;{wRA +za&Y9p#la&#;x9BV+@$Ue{c>d&=sZ19mm-wTG@I3_MauJi4>cP*>m7Qw^3;jszM&Sr +zXUER$>vyq&4#@su{YrmrgS!{2k{}s#`Sm8?6tE>5Gfkou@ks1>E4~m;n+{^YB +zqh`>4YvF4nMq3|9V5B?bXN&ukf);xXfn+CTQ{7bY;_Lk+XmkJNo>HSrh6Zm9{+|Qq +zvB%Y*0UnkR_bW$=vgq5>s7K6L;B7zT=&nn-#MFYJrUV*btx9M~XdZ +zrIW@q;aReDCVU;AQDYeC+BT5{*#5%CLoZ>OP(rOs+zIDI-D-F2c;^S8Ni2jw7Q)ub +zV&*EVX~?-KZeHs70eikcEXFevw2L!0>7*L+EmkP5V=gp-RXtkFiD+sG@fsrJR4zwl +zHG52CZpYa3lEwjjMP^kXN?a-k-T3Cr*D>@ZM_g7^R+#FGJ~!p%r$MG8txW&J6(3wX +zYngoS2vcAkep~}!jB9rguXr)zy;k%Hr-(t$Y5VavG6jyp&Fw0x*>AfT8@aY5Plopb +zFtN!?F8%PK8N3}}v%7MPw}T14j$qH^A0^@LF~|mT?W>!J;9Ed_6mh1L?Y(t5p-qe$ +z0qYLzrd=%bzV1{lq^i@e4RrRY49Rq{+{zMs*a~xN^3MJ=3`bu8(c@%Qdvga_JB;YC +zi|Gv1{THIvNs-Wn6kM5fX%IkDRDr(?c!T$A=SA)Cf9>NlAmM91)i*70^MT*;9Qwq+ +z57Um?ySO1v7C2FjazLwMjwo19gN&jUG!$rcT!JnG!^}MWXZUlCVu-?Cg4gag&k3N3 +zS~87`8nhjdM@HG~)3k4uG7pMj_JkoPKGGZ2!|Q;rbWK7ol?Dt +z;Q)C;AHGL>zFr67ge%YjPk4$bQgjOusbBFceWPz;rw +zBSS8Wwk16XTAxVo!0Q5YBr}7^bfVh@EJGhYA>;RRb2P2G&XU*r*2>*0f61VIY=X*( +zXuTn6u)^1DQ};;X?(#1#k@4?%?h3kJ)UaDpq)uD0D8r4eE^s*jV3#0UGKd@2fCOcT +z+60Evlh%y%qf04eA4$gWmmoQvM4(8+N4>GZza#Y-%p?|~>9N$VL>~V()y`dttiY0l +zPRtmn^Q}kaQ2|N950aqgeuqfi%yct}jY20j88lp>YF$9;QhYMaBjB&cgh~%)C%~H} +zYlC=wA~9zuY}5gOvVoPa?u*l7Fp}~@8d +zV-{B^!(~(3z1b6-nx(-Z_arUxILIAiqCl(_wW-LE0urSlZL*plGz^k-`?YEN==F5h +z^(yw!U!qetgMy*_zB$T_@2!w0Q5vqTpEhb>qSrR;gqZfru*fllUd+es9Hsj`-U!?C +zuQ8s>ANLSt@+LYcU__~EM7l>_3qWQ%Ub6+4jH{-pxiEqNvvB+DB&FS2^#2I>cM)&6{f>(7?zf7&svX(vF+r@R3nKYAPb!kUU)TJoxNAH +zJX#&tpcU^+k7m!{-ztw&pw)`>yJH5lecllGCB|k()|)M}_O<(l9;gF#Ji7HAsp;F2 +zfX#ECY|o$%5BzckyWhXRB^eY$n@WMHuJfa@5VZ+{S6ta=jj~5@v1f-&)>l4Y^+CU5 +z2-0u(K%IK)#RZVNVRw^{C)>2(}rnN#F!7OVgqG+NChLsRCGG4({^Bo0*2k;v%wN(X@Ok}rNqusQ4 +z{%lwYR7<%@*!{d4Y>b64n}pmFV}e|J?5v{axnNTZ#*KPO<>U;!FjMhnje*rfqBo1e +zFqN|y7|TnB*Bt;J31sicz#{3bP=@(N#G17plt~N4V}_57?z!6IqNTxvGCq{|3lwCX +z^Ro}7u$F>L^j6h89OH`Mc17G`?zX&kcP1lX(_xy+AmLrlp6teRtS9O{EJ{n}QhpG( +zwLE_f1p#5OAVs}8*>TW6zdn7?zH5eUzgTnA(^VqC)~jiup$i^m5}9WZ01>D|W9TmD +z@o*z&?XI(rtpMOuKGA=EQ(wDqO~j;z{1NSlB@h3=;JF2>cVlOutBCyO;yL;U=!JsN +zrQ^{v!Nw-0{2Jwr2Rb*l=OM@MM9hdY&>&P>5ZM}tG*@ce76t=Bi;K9}L^blMC8&~c +zUMCC1qplmK1Jf@JAPocQI2DSK%VM}oYi{Xddf6%XPasw}hQ=PO^%Qb=W_KSo-gVUE +zX0)pa@^llmzGtLa-IYL-N@m(#hFj% +z_}KC@?QnwRx!?%0KpV(%s7e%{C9F@@x>zU4yN2dpP7~~k|Ga7zhl;mxGW`hpP=)$j +zhrwTLd%j$WythD0rrXPjK0CZzgRvo)eMF#gEUoKQN~{7N=)?L!oWNERn4$-{tiuC9 +zyzlQ*m@6wK7k_Ac8l(Y33(D>JPoPQyFPVyd*?mUd2aehY2W9OyV~3~R$~(=y>~-;t +zq>OLn`~LM81&6qI|M>24 +zPWe&5JC*NJYTepPrnmOzKdu%6QF@E7_mmaqA0LG<8N-KfH!>MUY%TQ`secfIUyOc5 +zb|*3X=D|=hv_oC2vG%b1h7^Znzu_yoW;n~j{(WX=+vQgD{X*ETJ!ectKDodPu;CQJ +zJXK!iF@s$totOd4_mbV9y`bRo^DMuq4+fW_ND{`2x{&_u7M-L`$zVKy)%5wiUNxvH +zN<`iJuRclueMkcF3^pIi8~YCvE`ck66o$2xV8tMnx{aO16=?f<*qr@K{LPv+7oe)y +z#Glej0r`>t#Zcz+*`0JbxYXYhm;W +z#PyivKU9uy=W^}>I+P%22vhE#{(LWR0#-F->1#!eCP26hgGZa6Ss*!}#b*)#=y=k2 +z)NkbR>ap!q6kILQ`#zq(=RZ6M)DypO%#cZ3w*>*rBjEV>V}eFUuSE`&D8~+HzSb$M +z**RXZUkxxa+m|@6t#gptzJ5gp{=i@Bu1FPXiYx0tE +zotk(vFe_4bd&=cEB)!nNGGnY*yreT>*jST8U70`k^e5;8)ZN+?g(^l&kW$D!mE*IK +zg;ZyyvS@-cOdd3yZ%D!nps?AK1hE*s6U}6#$+8D3h0p3f@Q}3S95yf@tkBraZi57g +zw@a1E117NlZQ>1f@qjiK;eQ%q=#S{QJ7R4zSBqI6 +zWQ14J0V)(R7^ONp2UAg_$?Gw7<#Z^F2LJq#f6k;T2-7#xQ#d`cMn!YsQk10JY7G&CZ& +zQmASe<@?RCIY0~Y@1_8ssnf6z;oHHz{Yb7flw}DZiD|RyU;%lw;xR^ugSBDLDV)S? +z126=jmON|nGh1!6;`{>{2r!AaqH%`M5OJXF;KObzyf-Z2W>`Mz^@zu}A?P2OjB6q@>YlVE +z!TVyfi{y^eL~+@TP;YLG&1Le#^c8-MzVK5sFOInP{xz3W*7)DW>fp(>`A!~(S}_T7cENR}jt +zo=vz&f(6NH;C}KhlilOY{F+k*vh|w3nxB?nGf3Y71F+eYdQ}=|;O`f5_;{nBhgy8r +z=Y@9E3E3;F{(?BNJ)LwyLTepz%e*$X*s+7_N_n^`lE;aG8+`b30VCuAW_ItGXOgk1 +zDD>h-p~#W%9STJo%3zl$7n+ZCny&!f2ninIxJFwQat~eQ&t%1KxeDPqcqX-GS624e +z`H{{Hm+1E9$jEHym92x1CTPY1EhCFlfo5 +zsg^kP`C6#KyCmOS&)Ak5gPb94%#VuFW`GsD+#0CROTO7{gnAl~G5TPpeV^*&BB_`b +z5gQo|=jTreT4G;zYZ35KoFPkf^spMyS~?VymIZFkSAI31q@_i63(#!0)2v+(Q{ehQ +z8L>LIf>Cx`bF-X8PEgag9T8-0hZexEVL1;f?=qvw$ +zTy+F)-~EI4yopfZySc2{dcTSL6raS}j6R-~EG>ih=(PGl!`uAWZl-;9P!o7q(rn$VVewtda +z`SwGJRI4i^?|D!Vx_)|+ZFOuh8SJpWrXp6C97Pp__}ati +z2!Vd=T(W>f04fqw7MvF#dmauMq%t}yCuTvKo7@7Fl`R}Wvj%-{qoHWy|C?;#|Nmd| +znIFT{%e(*I8C=RF*l+0n(v8c%5DF*W8@b1jy~~2;2jC~<)?+S^>F$@lHj;df3OvJE +zOuvlb{PpuUVBc>HI8;J=$aDR`V4^m$D|AwwFY<73%YB)Z9lQN93o00q!yHwS7*OJ$ +zN}V=&5KG&+DZAPag~SP4-OcLYOvo%(bWOS79M-upjk61mP7eGG621>3Z94}vp&c9%Allp!P75$bbx*2m1>%*be43mX00x_8jt +z$GGep6a)shY1>BtFC5fyI4^II3LQ=v!K10M%13yFUpeUCCV(l2uVTiYeDgqJr(@3b +zEspj(-5=J8c~A)_HEKoIpx`RtR#Q$`m4Md!tQpG90r&Dyy5TbiNAkNDOUHocrSnP@ +zw4iEkYM2>by(Um0HkdAHXrO@WupQY?l`5j@bt3XuZ86*`;-*PCWhWwQ1&jBRidieJ +zgsLZxky?$R%hKPFBOeJg*U)9%P;-$$q{2PP@R*Nq&K$F{vuK7_JEWUXyoAq3N~&Ps +z4+4k7Sb-}84_Z$YEhcx_mb{=5bA+pBS8NA85Cqbc>=VAZxK6P&sJ?4Y29>?V_YYW? +z#ICPrCjWo`lX^ZH+EAXix+U4z1#9qEbqSv+F*RHycf@t8r>)zd+3td|&tFyw*MVHI +zJuE`{-q!7tm0tAP;=0(BdQi4CLYB!uC)cWIMc0~>NCelR7MKM5CM +zI48%MoBW4uG{^UKJCK7m=H~Kr`Qc{NH_ZI=5A`q`Nh1-%?vmKrE~r!89J_Ob0gQN2 +zg8uR6G})NV&_RyDh|!QctyoQyy|F`^rU}3!l!U5^)}Ay2Q-6-6Ql2fcG~+x6Da=K2 +z=%MJp^pNpH5zl>p8w*UV(?>GBKky~oCoGbj-l2oFVkznqISHJ(ycQ@*?n$B-<)Jpz +z!PWmqr3?Z@qt~goMvQ-KbGkXXa=^B1TcKR9Te6LS6->uHn!WuljjMH(zUFN99#<9g +z)iXacw>vC9yMI?I#R)Twi`kp-r>CFmCKtM?KYH2ncCiZ3C4rnhkP$+$(sE(3DDE%^k&?0X){GEHV%G`(TPiVkFj7 +z7pTy;9 +zuUwfLeuY@53(eXB(c?lMs=qu3KL?%W>8$>_KpAU5YCD@pq?!cv{A{nu%?4#BMUM0c +zsJS-T0;OpNLdq~DL&vT8kyVBcl$qJlyiSn6b}Z{9xLu237~@9O2zT~fg#N0jvzKL8 +zx!41O1!93=s!K8&aIQg8;}TrcX;U^}5lo<;%(p($ZJy5p&C}n&ZUAaV+nEa_sR%1- +zoI(p}@A(1I5Vhw2`I9IKxeO4i?s?69iqFz0n0n?~FYv(5;%Bnq>ozIUd&zt9#%BJs +zA+P>le_$^c_87%6~AVc01az|AqZkHk3J(d +zIrj67pFAv#p*cs$8xz>-W6XFdhS^R;>DG%cp+VcwE8{I`uD47?1|KVH8b&r)#TNsz_2?C|hLQ9kJU&ym$+q6+F=@IkKg|3765a4iH+b;~t-rTupE=Aie +zVwd#LZ@29TD9842v4-ttw857bY-EKmCjcG*JlF!|DM>=&rEAdYiAA?eytaW@aCfcH +zi)qcABb4^1KzP~ZAx(O6B78zu28au8kaL?kiDh0~jHJXZ653T^t)m#rdJNWqM6M?$A&HZU +zN*b@KC=4ZaF|b9DbF2CUDX7mnp*R$h5lE!xZ_O*e!h|XtM-u}V4tloY!z}G`UsSF`aele!)5B+2_tl*^GuAxBG5yYLBQ(;dGf8AA)LSonFSp!C5 +z1~#v!>>oHz=D3 +zG*449-9$#(E^wOz8M*_b4mXztuB&SWeS`&cQiWSY;@^<)uA%l>rra;=hTM4JHt +z?NNuJD%_}rJ{>d#jl^X;X3S?+7$GoSZ|-~5(MZ1p +zShM^<7jl8~Zt;0T2?q0S9-~3ZNqdcCacTdwv*x9Wjqj=!QZOgs;Hnm6=ref2YkwhT +zspB}uX-=kSI{<Z8`j$(^Cl@99G5@h6Y66AmTPwu08}Ti5P4StH>gg$Cnnnh&34b +zDPxpfBEI(6&!U83e?kHovIuc@npU@R8*evGjk3=Ht%vOTaBTNu?l|29y|6S_7LLqU +z?6qP_d}q6v@i!F&=Gzr1ucz2=uS(%j6je;>pebRico#9ugakOh2LO7{U~=#5(2~d- +zA75GR+;O!|b}uQ`vFmO`wq}o0Hg9E_y*g#cN8W2OC4gAF$U +zAdJ5cqi(vRiMMDPCClirC54C!j6527WmgDl1J?+gTtMKCrnKzY>bR|6ru!z*EBfQ( +znfWC+mpP2cTwL4LTDnij;BG%OE`Iv}&-po+;xfv;E9t%+WFNLisD07x6fwQ@{vtXE +z8}Pfb4a5p{Y3${nyfv6n;u8SNGd9JwcP$fogpEo;=6^4xS!^qJhScH2xgleOGp-{; +zJEyvkt%Sk)EthW^F$JtE`UZ!3a(j(yZ1*YkF5n?EJIhT +zM(;E)vg5+p;9qmGZ&?5n10Hkf3Oi{XCOY>V)h-~rlQe3A1}qHaS)th`A-68Qt4cC! +z8M}Iv5F9c-1O{xlhtEAr&Wc2$xktChPBjzMoo_QO|w +zoSqZ$026BF^7C1}czs6e3|+qAd55f&&7P_l874ys5g7-E0t1h^ +zE9rd}sAua3bH(P9)uqc +zvlYw=@XA0}9+`1W*8@=UwN+9%BY-N%<^j%KY>z|jTAlqT`pv7$(VRxuh$tidovd;+ +z0S{9c6#H>ZW%UI$oINhTpTP!in$MRBA{5ptZmCL=A-RC9LfS1+Vp-v@^SmeBYha@| +z__9W{o_(|9v8I7JP^nxHS~@!MNDzLAkb)v>dpzTdhJv_}pg2u#jIb1BaJ-L@eYH>{ +z2Z_9;O;sPm*m}T^6zYEFD^FD5lax*c+D(YrYJF|$LAqz(l~@~NAvl=b$mzWNn@XMT +z>)=v&o@0>PQf_`hh^RvKRQA +zcO&R*A{6D!U~BvlwZFf$;5e~e00V7>3lD_(m2Lf1r_Hx4r%9Xy@h%z0430btz$Doh +zTX5tO6%+II4y}3(pj?VZf|OOK$2TN?oHqgobOvA{q?RNsYwt=V-eCw?^5BW;nkr)W +zlpM@}xtpQZo7=`L#CyVzUw<1=+F6ITzx8ZC5bQPtcHFK)UMr6j8&aOUr74OVw&KAL +zs>ACV0qBG6A`gWm{xE4l0=#s;{%d(a4v68_c91I>YZ#Q<8@Zvkv^KXx{ug8Z;H?lp +zaXG*E*~Aeob0cRO!*ediYwi$@J{(hkBn{Y2dl=f|BK|FpL~UqXAbKcOpl>@yE>Rb5 +zbGHf1MeT4_nX#3Eye$gh06XJC&(LF#SoU_#A<>2R08L@d1C&#?;d1R_8Z{F1c +zkjC5w0*&0;h9cP6>wE~LOgE4`EX<6PWas@du +z7M6mFVNpnKLfVjCblVPQqY +zI7bt$SkMoi?y$*|5;z=S!ki#0_fr@>=YVCL51mbcWVc3&dq4^37LG9oad1e@ +z7&C^(Vt@0%AF}6sdXi>oI<{lH%*dB)}l@1PC +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 +z&mn(XOx0Cd;S{liT^D&O)?_h6j +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 +zd0P}nHFXDsSNtqu)brN0F +zm@~`#?g)>>Ypi0qzb#=o$McxvKNou#u3%m|Oif=*Nf!7nj%K&~F}8VQF&KjXQBy|4 +zv^s_AQ?dr8x#lp5C0s)86&$Oq(0@pXQ8gE4W`aQ#f$wV4lh|PrxxhroI>K5!4vYERu3Bs6DZ-FV!b}U;O9g +z1GJnD$C+}70v)8JUFl2MmU2dw;@c_*xM>iLL{u)(oS_2pU+8tH)FdHN2_@7(x(eXW +zg(v~}uTj#4At>_GTacv_j!J87EQu4*RB4}2Ef^o9rTmxhn{yGp7N{;zi9{mDc0|kI +zQIIm%Je`?hzQ%kMx;$=jGE`YyOqS#$(EcC4fAuG8oT4n$6Jejk^!c7DYQ2E0Pn!>> +z{}Xr4@PFt@%i8|nGgNWIHD>TZZUoMSIPo&M&Jm_Le`tLC{Ez-+ +zN;L{i<_zYe^THhEN2m_8wl9SVJn>wMS|Z_4c5ffIA(vw9F5joCcq?Krv(vhRGn(Z+^qGxPPLmwJO@O+P +z!6y!LUZCP}5rlfqjNDzGgK;~MD`>3LAy&B?o?VK0m_s&ILhcXIJc+Y#*S2TqbI~=& +zm)ljwT9sNJ;~r`>S2&-cV9ZoT-`LuWD(29`#R9;Shvcsj0g_|s>xxFP_HuuK;MB%J +z|5S62oGbUzEbx|hHQzs$o3?M)Z3KdCi<$7|(pWR-up&MptSAn_nL^YgvMkldQG>5; +zU%ZDduH|z&jex?k9HpHz8zk9Djt;gI?gXEkH(R#ft=&$sNvM|ZRIt|XV%k_c3oa}N +z+S`&qx(*u~wF(_BxOlVqXl`#2vy8}A#84YuvnABA|4Id*5RF?47j8(vW9!Pim|D19 +z$~ia%vAm#1A4x*N%si`z#Jfc6)?FW35bX^=rc>b%639tRygAeaEcddimZNEW9o-J_ +zp~y!;Tsgi42ca=C`;e!~t^mz#xziV2)xG-ck|`BS((q0C(vo`~9EbS7 +z5jQE9^`3tH=FQ<~ep_U}4791JL3V~>LdjcElGl+zMju0CDu=<@^JIaGk@A^OkCWDy +zyg>`o9|q=St2Ex$idqZlhC(k+j>GM;AMa633#XI-aof?2bl6f(*R%xK%pp@pQEz|~ +zX=;lKjD-Zpy)VBT)EYQ6k3rgF0}50l8Cftls|4K0H+n3x;2JAnKo4P#)L!CbA42m9 +za1G?B=p9`W-bK(=#$sqdZemtwA^^9khaT|($qaPsAK)9hUE^9hsswF3%q9uXCla$}6BOTxS +zIA-%)#UhcUJRNvjCQ!G6cmO#pi@E@8zJ1MD>mRX_ +zEAp9xVeQrvA$bu>a^|HSG60_BO@xh)u9Rhh3g7MxDG@>IK=mN2X1(^@8Q5J~!1<5x +z_kY+RLos88D}g~nkPuMd=QEazI_|5L88pegWA_Vdqr$+H859(!30byK4Uksk +zYbHQnQ$K;^iYPS_mhdtpcj>Tz{`;8O-3Os8SFE@c%bHGb{uwv$zO^IzSr!$e8As{A +z%SYnML8tY-5QZ +zfrm>f3=|*9w$YCVxnd*-N~iY$Aitg`hGlmJAn=EuO)M +z1gmz}EPKEmLUw6B#j$gyBVB1^lHwm9REB2G5`$R8Cj(WRgBzN)0N{yj;uJMnr5g^| +zlMwwSFZlkK`X6X}Zqp7WTwDH@t(MY4BSi(p9V;#*2b?4EQ2zlYhwbeN@T0$artWK( +zcR*c_jH?!&h-FWN)~&c3^;EGZ!{`UvMg@Lws{9Aq#xj)|^qy5Ig5|ct4LMB)pvd@v +zwsG+xpV{aRi8g+qZC_y*4}5L>uZ#zvKfP&SECo)8(JWSLhckk*hxCRx(V#&2?I(r^ +zj$2GPvunqJr7kd60e_pa$8&Ii7_OZ^>DwJvkA?nd1wWZVdUL=<(eLmQOMf}Oa{z=I +z_;B9|j&e>{Z4^9%Jm;$J5bz5J<)b@i0B%Wrlydamn4HT@U6?|eAOiB_yP8*&02`Bm +zr5ph3aquACy!0!T;V>qseQOQlKP&N^MOAv +zVtQ|uiP**+?#JVaH?)XF`^;rc#Ny8uRU3~!UcGkllfhjBxx%jS +z71$~4wwPb3t_n{WsiHPYBC;l~=uQVC4m9&N_Tp|o^aE{Q3i55JqLj*+LM7v9Yr(6L +zSbO`9L}GQJ;ZJX2+Z7xm%1CxYFDu3W?x#oXAEvZWxtF0-m;tQ}BkRL-zzxMaE3@q? +ztW%38-at(#*4TYQZ;GY|b^3v}E#<3DFukmi$uOWLgFrpTHZeKmag;}4GOkmDexPj| +z`+7Oigsk~Qb8uOeA87mNysmK<1P^u(oN +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 +zG`1L}Io9y_t!rT!V9bA2S8rPF +z%txwm`Rlx6W<#BWRKbceG<uTc`{@{%f3Gb+mM_us +z;}`wSG>q;6Ws$xdQTG#9VETS3+J^Z4>cNE@YV^Kkk#1hQoyYlfo$2o+JHk0!hc%+j +z*WaE-9=S6g!+do>9DQ!hpii534m~b!w;4Q7p#n4q+u9MaEa$p6FX%a$m7A%0B`CSM +zgj!1kN3in|zI3!^Bf6xlsM+0?>a+}Y_(FVOYwN^VMdqJ^Tr;O%o(D!I)h)svrI}of +zMA|hLLsavQvi76MPe-839S%;H +zMBwXp2FQ)={$7;pkPeVUZ|vvZ39IWD+-k;^HbG<@daq@iAm2+fA2prb5m_#|62VLE +z9dp|F^yixnEDs$o|8z-vq`~Xt0Y+C7Q4Ls%wR?gdAH{hJtBbS&&e-ZiA;%xgpom{A +zJ%tPc^I+s0V|grZ`d+)P!s8T^a+6v5#yWu)5MAo@*?ALqn8S6X^yPm`Bm66&fx=ct +z{~{52Q|v@qHh!RAZ61KLWTzR?MR=RzyueG%|LO{WdqV%!5B0tVj9{oavbWm_py<1ghsd%kWX10J +z*;N?OekwZ24c_k$(g{@8Wuc>`mp +zk2>7*#)YF)nYJW +zSBkk_pzAAs5;IdDIGPkRIKh1UJu(|!tj(M^^^&|-`;imo^7z*-yWlSybbAdM9?ka* +zq(Uq&U(MpMBmXM)(AjDFmBo8ZJUyijyJYJr5BlP20VUSdYK`PX-E~rW!&A;$Vg~Ze +zBmG%9i?G2G*cuR3UIF+XVjGUzB&LeLylT|8n8hnWNM%*$5%uHk?7zlqzj^n!vV)&d +zXF)*%d84XOe^D4{gQUDVkd9rQ_UvW^AO@95$Mv +zYYF>|82C|YzHFQ=@VxX=o$aM%LgJH&YceC;R&qdC??Y`!@t9S@*Cos8ys&Y@9f@-++#Ia +zCcWV0D+0Vg^voko;Ez~ +zeQoFSRX)Itxd>BMe=<9NR%c7WM~EX#i+X^J0Op+0L4MOlG7k7-V+7g5E8neifxM)5 +zJ>tCHY(wlJ9jSwwzb98a$YSecT6Y3ufW*#ky$w(I+Fp|;47&0W=Yy}PL@F&)99G6T +zQk{ft&1Cfu^ni9zS%G8QFol9vV~m|s2&#HH!`9#CD;WbC6ogm4<xghS-zIsgr;tSaegHLNWX}Uo!y8;KL`(}ScDws>ckQ*&XgR@R!g!21B +zXUkRj(*OX%4K}fQB*TKoLMep66r}ymAMq>a>5~D@?(^=dR|+*66Vi@~&NrTgOrv~|;jSbo9#sV( +zFq?_0JSxNZ2_%o>{2<3k?{3A!D8=Szf24sUG!9io3|Eg(QQC;ec5aFeaT8E%NaEOSXoWr{ +zpiH)HMU +z8GU3=VX|P6U`S({uDnKa&>JtT^XrZ%&?hl3uGwatbGWlG{6q`9`^kIow9vqj3T%o0 +zd=C+MY!nzN%=_{4GtIa}-b4XReM=;VhPXo*x)#Acf1EpxkFzg)x~cXV2NLoFFNAg{ +z0P+k#Gbxzd8>f$EIzxLBHN{tFf6m3O=z_qtO7yo~Fzb{g!e1&x*MMiZh`GbPn3oaE +zN6@PGq9brxaz+P?G0dt~a;g^kP((Qib2CCL?EuLSWU#@$3MZ`yfm9x+ZTdfUuV1a3 +z!P*&|$@^cA!!1cKmQ%2MQmo)x&pq`_g4djyp@a$V>AZYl*H-GjoQ;sW7);i2nC8kh +zLlcFm$VQ{U6CvEaIoP7zHEM`}Xaw{2qe@xe7;MN%^?kR8y!2RD@MgyHXY~%Vidc~j#4v8gJ5fI@9bmpEaAs

d?_Ppz$M_f$LvIfPhO0wv^U7Vljc<9kPAe|#8gGPK)U&f^vMXve5y(ju6rJMCw7jw@TP*+w8p*N43pmaM?M+4>%y2-_ +z)|wJ{L79Z70uf;qEP0=^KDLOo_xl=%uk2aTP@9wTzc@G!X_!+!?r$KVX6Qg?n;4E1 +z1OZjrfNhEwPkivzLm*T7&j(FNt1bmY`*%MyX2|2@6nWn;-yw>(0PBUn>Yc40>#o?A +z3?9tYKPgv+pmF-I9u*U3Xs9XD)ZgMWSShX}u)KZ(U~D^waQl=8Rkjy2cZ-%tEtT@1 +z8q>jG4?Es^I0wJ(5Wyett@?~-uz0I`W`uRIkwu{Q-ASee>to~F|1RuW-;%>6BQ2$t +zI`%XZ;M@_IS#`)7S^5sW7VIRo&CZb$U6 +z3ow^%O)K(pb#DhP;-P;J=RZ={L@Q2K{}ntN_87!&S#3=x0_Ug^2IlX+vr`JBmMTp9 +zHTSY6226>Xym_D37XbpqsPf$K9^D0J+yo~(v|%>_E7zIgmg%*AzK`?_m%EtVOOCX^FDxZ>+P9?Sm3Wux$}Fe +zqd865?sC>onODL!Z~`e)>Ytl`UaP=T>| +zSjVZsrNJu<1?;%*pqjITeQL<(`_xR!WcBHLNT80_40?dKV*r}|AVr{IMc0%OXpAH$ +z!$sOPNvD8UfAi6ahOZJHG_6PiaWt9>!RICo=XhLVzdJzX-+Pa4OMAuS@Q!CapJafy +zc#wSzYxrcgCp=PZAT|E@K`!{hU&x6n?YR%&v{AfRP(3lfh5^qw(<0Uz~@l1E)oy=M0m6s0s>h`oT`c#f`>MpZ +zFDcS?;vWRT#-cL~Zxd&N%ME2jaJ1I$;or|Ioftz@_uw +zw??q74Fhke2Y*{c7w{DxT!q85^!iKF3Yi)&(j@++sNVVWk};~}h@w6_8rfra+)x+pBA(F-A9u(0q)lqR@}h>0pd#wRVS(q2Qc- +z@__g8PHERTr5h_*6!A%`FH2v|z-fFRFzBBRxigj5+<;y^@s)#^K-`8Kjc_zV1+s_g +zsyC?6u_tF&2#9KzF&d<`EyGdR8maxg5^-EIP}`fm$zMxxVB~AvM!D-l6@_zAcp(p> +zJ#OU4HsnD%XIkdGD;7OK?nb!o;Rl#DDq}p(9DIv#y+@S6C%YNlnK~NlMkivNOxlH; +zSwuvQ1kx?AyqWnJqu>8}Y1+bE+kAP{{C_WsZ} +z=c~%oQ+v@rKVRC(MCcBPedVg66k?t*T+YwLZu5(jFshfI0N^SLQlDbSGo2|@(2Yw0 +zfoGy@6IG|EP^&gQ&ozq*s%5B4dC0be5)Lpa0vI|i<5p&&R$ARQ%}InevH-{_Yy!*B +zJIgZSfMf@1*fs4m?0miXs2`t0eDg?51cs?EQb!FY`-G(48j~Oi)Hs?q-D0zZvjdZ| +zL}W>xRXOY&eCz +z&u*xCj&Ofldv%9d?L0i<13I7Y%yur(`cHeR$SVhP;rl7lZWyI4I()gYo(q6=>KZ-Q +zHMAje0x&p7hQ*zQlv=}d48_n6Y!}PU0PHkaW?&TWZ=uPavtz*`yOS|8nIfH^h9RW) +z3P=2#$o~C`uIof77;G(OvNc|dVuH&`Vrmi74ftw6RH!h*O6D!NL& +z5>)FRZw2DgvxzY;*+{je(#Z9a78eQn5~Pq|iPC +zSU1pO3|EYy2Pe;ZeI9=F1M&_R1aNo2&Jl(~CF&B7E#h7Mn9q!joKKq;V9Jn$qbwD0 +z4EZH|DUj9;cT$_3mz?h~A?^@fo6~3J(%|H34sxGf4TH%CG~1mV`2c&gZ+>6pn()W$KOgZqug>%>gF&kQj;z!4Jz7m{zV>t<)_Sj9F8_!R%T+9dq@>+G39ISH}*jJ^rI6_f&knB!4TZ-p5uRzT9Z~Z*J>ZfX? +zHbXCUmxspcQ8KHx({7h@L!-X}9!ud0q^;Rol>*TTVa{niswnqS}+$x1{E`6 +zPRJ)?k3a4<{*Sv20#bm5kmm*HHyCo6&ewP@v^xjjw<-|B)EV;t<*C5E;xsA|I796G +zG9G8-sNW9ZwI<-iuh$DmY3^i0%bkX28|pDQ#rG|rmM9Juk?)cuy&@}sb8fnm{RwqC +zm~?R;$5%RjY#E9x2qo$fYHTrVn|XnTrEHc703axlQgL%3p+xJlJ4Sf4PDsPV>QvX4 +zeHeo4^(C~3E{6=bwW?wPs8kKz{z6x(aCy}rm@9KLxGa{;7Pm*%N}Ua>t<@#8~Mj_?@-YR-RoR6 +zXW>YmT$iotng?IM1+SI>ekeS35#&bhy#8bkDkg+gnREf +z7d0pzJq-OfO}5~;U)gqy{t4bl +zV#VOm=C>r13huaA5x=$+{=m*TF388YX1`T%$u-DcWj@MOW<~b30&4Z+qV*Hx8)BsXcH8pg78v5iMK>L2QZL4E1j7 +z0F>h&bNel+4!j*kzQopJ_CMyfi5;W?gas0b2WP3=(e)DAfC9YLOqOs-|Lgr5C7{n{Uw +zg|jG3M7l-nVCqx050T%Tny0$oHzX#pO_-~JwAzlSuNvhC0>Gi;f`1j`ltaYB#y584 +z0S0lVe%hE88mMMNdo~jr5HI;_L`swx|9rgJX&Yz +zBoye3ayl_AXgQg1v;wv4_wml^%vQM&^x-O@!K`6}Vj?|E;@N6~hqMnQnv1?Ih@xlv +z*1udWnIi(0t@0G{U5+yPZ(5Uww% +zLFLEy!24q}bCj*?0rz%{-saQqJy*>Xgjw?m-EW>2GTL;~f{3M1Da^W$vgnd$ruuUD +zC#vMOQ@nR-MVQEi45C9PbkkIN27($fjo|@V4w|gjcNb8&u#iZuJkROGOe`$u!W_%I +zUi(B^G3=bAekGyeJV#YsrRPTqdMQl5P3*}~iTXcu%Tixf%6y!$TxqluRxD`5k>Y&T +z1X{-=U3wiiPs7syW$_m~R{}E8J_J&tf5`1mea4>w-VeDAX*g&vp=HgpOQOFGWOfa7*9=5oBr+Sq32?p+#!-m_PKYPrQHHBw*`o +zOQ5yRU(d2(0r%7Z4sNJxJNv5Ix{L-px7$$>FjnnRDuGE7!0!yf)v!v!s{ZYsKgBjN +z*=-Qyg8bW}A)1(wLgJ+%aY)hxDH*-#XwP`Hj4(xDwr+a1)OQH2y{JJY5af{pP?)y$ +z=n}B{_{nZzC{g;}qeGFJ(1IhcMyh65KE|90D1ZB$UO5D-d9E}}Grzv2*k^>_G$aF1 +z>EgIu?Ke$#3C}!8iD6;T(M0p4do=`MX_V+2Nnz#@SVufkjN4_dTCzUOM*K``0r{?eo(d`GVWP4!_*F}6Wh!pi)GlpY*zqyjl?Cv_mk{t +zzA%#9_Ic1eW{)C>aTi+E@Wh=ClAhY@TTO?rY)@$zeo9#SJ-G>Yp5dQQ709?E3d6+%8H`Pl +zZU}?Y(EdoC013~~q=z%9)D#`%_Oq5Jp`9+6UJ~_BGIB%>EMD1;?o^W(%M?QBce+s& +zfF&D8NQP9dq$o7WEPtMAyB&D*wjTY!_N2TNiD&AQRHc-Si<8g*^yvpR_3;~Rg&cACkngbK~D<%oi(=vkUI>5C~C-!a8c&mCW +z3GZ(ev6L!RC9I;rHNS4CS~uR0w+&3XG<9^|NPGKJFj3qcM@Vm5(z6!U&Hj3{_|l78^Gf{j69t31Y2L+g_!Ta9G3KbBIOUNO +zN4l6{?#@Gb#N{AH4evCkwu(RIL9>T>*jJ27VuIME+kqI_x$Ykg%9} +zy|VWB8NE2Z<`L}}HM#3zcec0=Yx>LGB%dm7O8oaZVBO0GWjQt^KMJvjzZ2T#!CHrE +z*e8VB{h6bgED^Eb*q9qxC$>!Ab`$Wh?}d_vj{uC>d8*#5eiG~S$>tb5q!mh>GRb)S +z7Jo&&t5mYO>dQIzuEaCu8aZrFHA1!7&ILe~g+8pZC1P-DtSmPoF%D-qcS1=wR|lI5 +zhy#&8Kn6Fu0ma%*TP(cuzu>m^LP^E5fi=&r7^Dl|U5=RLxrAit!Z~TZb#o7^ZeN4h +z^$)o1g#SXXHTIYNGb=LP_I#Jn?FZbRQbg_5=U0aCtXy?;<3}_XE@~bPZ*UI^#7fcc +zYtwbh^Md4GF8c7A>nr=rc}MtQ!D-t62i%^w@Z)R7XQ@~EA88r}|>Hwmbcp65%XcrzH^6nN2(FG<)%SgaCS$4P$9*P4N#rK&BrwU$53^q~Gi5T*d +z#*xD1R$%)HW64Vl!a!uhknV0LH6{3iH$Gmt#gDhm^^doG4mO^zq@8t6 +z`yJKp3$GHM$DX72yzWe-c|0=09D1TXwYWt9*3DG{Ac5JJ`9$9|D$=Kw8zA|wxBZw? +zi)BjvA8%Xv$J+dJX* +z?O$(u5)eM|uKpmkzQv%r7icGE;LPqty +z9=loD9C&HP8ktW`ai#WD54)-r`FV>BWgn94x2)E9{Ejq$CtD~cBTP#ylUT!hBS^Jx +zfdNg%w;V|2uJ~(wU#zk +zBQAu;Va}j#uMtG>y9i)&*n>jOL#DSkgJ6oG;q9GiQ9CKdqH8F+HZHZfYTi3<2l!v% +zL@lX!zDj5Xis$-dF+}i76l8}Zj>?bc;D3=Y)u{72xFgD=AXz9Qx#Vuh5Jqt96_Pl6 +z7zyIf&uJ_%J^zu&<~FCKaI2mM{*%#GUQSfWh)s+xHSk(Nw>W)t)vfF~%s6@I`xMhOyg$5;iB*RfwN6&52cR+;M(gjqImf+Vut1J%+t3O2L-1#H +z5R2hZkoNdKck2`P=ahj$^I9rS?R0hJsn6jqsbsN^i3Y=0*q?pr+vZouAS{W$p4cEP +zXjgHxa$1HycP_eVOPcwT +zL$++iA668?H=n%Hb|!- +z#{vM`E(-%NW6@6TH>S4WnKD6>|0%fH=Qsoah&d7i8F;Nt4X+h+K0Z`*R~ +zUvHcGKi;-rLl<7ECRgxDg{6DAe8BO@KZ2E7x +z{-`uRDqH`klO3b)(pRed?2EDEb77Oo|} +zycwnZr3ffgukFYI_VfZ;Rtdj1-b&|{!B-D?Q0Jpf5yKyCULCW8>0Z?Wd9LzQ778zq +zN8;~x>CZ7ygAPJI)s*JF>Sv9XSOLTOf+?Dc`%0y@J#Ehac-sd5c-w^k>utx!w?Ic4 +zbm_DGc-z5$%Nho;BN7(1x1ayZ+lGw#@wQF>+uN?jSms?l6dY2~uc?}^cU3;zyx{z;Tn{3X3 +zn>v#Wijf#$GWVdZ3eEVnQRwMP2z`T003K%`>p`fW34q(r7)pjLimMSTv!cr?vH%-M +zH35V>hXJ3^ZW>h?p1}N`<3$PgkGEYd6*>t3 +z0pymG70(mZi?S?UfBNHX|JGk~o`U@GwxM>k!;oTzOGKcKhpPLiqSJFjuyq|7XscgP +zRqH~x8H2NQXLCeEAY8aK9MO(-*?>z +zHoyV(Kiu}x|8m>?9(?|*u^Uy6K@Edjw=-_>0!F~ST6+pdDk#CTV{ +zRQX>_BUlSwdlC&!Ou=NLE}XdAEce~{K9qZKZE`v;`%fr6v3gN@B1!5`6B`y|S$Omg +zaDPYhc6!m^oB@l(k%B~2T);$Y{mFy)uJ1mcu^*uG`pS(Z{H1?56;CD=IFpk63 +zT&B3f^d4_x5{WFsN&86`ZAIZz~)Uq-HJQEyN?qm4X5= +zH@GdCuLF}}Y<5hrlYp8hPr)cg13~S@)G&`o`lQ~Opu@V3fa`l;`2XX!gZ?kK-Qu;j +zphNP*ZIk}XZ7+rj{SUVtB)abM!)?3%Kiqaa=DE!931Sgcgb`lY+Zy-(<+hpr!)?Q! +zL|I%zAM)aTW1r$rF%&KbzTzR5n$s*X9P+=A{=eKdjRQ8t+im;-&@$M)t>$dA&n#&+ +zx34{5d&!6oGhsDML06X*RSf*$mmZnHmaXMuToT&yy!; +za&cTU2%gEXjIEW>E%(Zods%aJqH{ih=Pm^zc_&hMQfYWXS*i}(?8QOk_xy~J&PO_+IWNCJ~(l>rkwedMclDCGCk0ADY< +zf4@KFiM7&6IGSE?N&|@x*@?bScJf}I)f6L-+TC3aAz=j;#61>an-W#yaQoXJk!z77&?IzIx- +za|43acwq-dx{n6lh#$>(NkGWdk%aN0S*J0urgotJ)e#5a01!yX8)ow~;!VlT-zL-s +zXnXX@T?!)N3gln;phi(%PBAe6?R+ymc>7)SgVZm6i062*^i>UDJpC!Spxlf;U-O~*L>?m# +zGt+WWgYJ(A(Zb+NO-s`q-2oLq0U4&G+GcH&L93D=T|5%5Dr +z=>)`Xw~6&*2u;g7%8kZbBH1!I#lR>^I#9+Ac(^Wk8iN&UNoFxxQt-ZFAr(X#O`@H6d!C{6(5B5}c|kA~aHtYilmM)+;ugbD8PH6Ibs5Z? +z{H$*PNsE2gI<1`Z8$}jDYRzSVq+H7DQfb)za%0-9+EPcs8opLzTu}mk$Zr#xi^XXp +zadv(Y4FC)Ku>g)HACFtVO!MlrLy#8@NEQ*txR5p9ho8NqK_)cT#T{rv=C1Y(JHLAv +zb0?@V<-#HOOV+g{TEcp6F|#$$YV56;Z(VU&Ohw4^cUkFkpK=XOI@-gA8xNbu&9oWx +zDdH;neP7p_Z_|evcJ8o%BH$_$?6h%$nD-2EqrK}_RjhEfS>{11m}|r^p;erBvo8^E6;qkw;?TD5!Uca9e!gpnc$~1c(HsR^XDz^e9G45OC +za==Q$Lm6r0@usYT1jfSzLd$h3_`lL@HvQ4W$G+H<`4+4wUN7oqI1Y@EJR06ejX$aGKPV={|aEw9mxU!CHKndOHDzMHjY=h)RSWFwG$ILo(68(|mVS&$2 +zJ{`JYt7*Iz@E*JwIRPR9YCEY$G*_uEzOn7D|1Y-fIrRp>{eQ6Sfp2UZl85aZ+n)Tt +zuH%IZ36mLLBq`!DxJA3x}VjvnWUE +zB4lu)H;bHbGU*8JKc`$lR($}Cd?a~XG!|rk;Yg8lIIx#<_DZH+tB()M;{N3tD6tFj +ziO+EK%ay!~%)V?^j=uhDJHLqy(@SOeusl-mV#L!{<2B7Ai+oLH_VmRRuwh~$AQiS6nH +zj}c!WMMBpqsm+ +z$9={e&K_U)4Mq#O8jbuPw!>lvx;+=w~S=gj1zx^jmv->xZB8c?Tpx!mYK8f;Qdz~BEZ9d!%tPUDf`cn +zZ6x&h9fBdo69s$d%fN5<*4L0ox=8BkMPZzbcI>!uxW>;QgAmu`a*x63xOchdT{j%_ +zGE(7yx=9|b9R!&>+KhZUp`;vO{p9PYhb87U&o@g)6bnb<@Qn9}l`|ykDBJ$z2_{K` +zCAIjnwh1Yqx5Y=5f5;2cKP=cEOU64*h8c%tp7y#t`eKwHHO5x{(x&Ml61R@XR|6HS +zoO4n7hz-yqFodG(o7eRQ$^@g%cg)5}S&gHwy0Op3ItsLsbZr{$vV3X5^<5oS%BR=$ +z`vloErWG})9znKWx5G8r4q`R4GhKlMetvo~?9j%OY(xY}zMiE^hRVS)ijiBt1|5`f +z+I+XuT2j0#gK3uJ9<}b&x-xB4)^_CA9sEvH-EpX4kh+RWO*wI6AkT0y8;YYgAvV*U +z)Mk3CfKq~oN=69|(d85|!qU%`+EJT$hV81|4dCa1)k71|NHfmoUk+e|QK984akfm& +zCq@3Xw&nj?+kz02Y9XcqgvG +z*7oc2a*X9deOzG>5DFcDKA76KwaxeYJA=ob%k|INUNcfw4?AF@0svh2q6GfoSgRh+ +z(aKGlQ6Uk}@K<+Y;Y9_$_60^apL%w)U%r8J(Y16(l327C}%5UorwA?{bsF=6|MI +z0uoGxjHXx-! +z7QX8eGVf$~sr0z5NLmIKmis^vV6P1XK{R|I5jk+eJ2&*&e&*f&ec*f1Um^1zYzZ&m +zTb03f^Ty*qV2uNOn&u7*l?%YxMS=xcg;Lag`263+mHvdv&G7u+-N)(R249s6^`vmUW+V)YDc;wC{QeEI0 +zk~#|zDT6-K!bg-f{8MowAbpQz#*JQB>oENA3}{# +zriy`b7Wkr!A2w>V4wPP`d*>CkK#~m#n|1MRZ6|Bl2%MbFU4V?9aWu8@^^Tfw;YN$=}v?|37Pc>z}oqf!q0QZ8zNQKb!b|TiYvTnabQ_VDFtSCo~3nGSlXwG4$EF +zWSdw8B0qMa9p5#M8m4pHV0S0T+30ZqfRi>PBS6*7#ribr>mpGFk>@np#U#@hc}e7J +zphe-k2Sxr`+xh>j?Eo2-kk0GLw!!T1i)RtsM%3=cUts;-z4Vge&vWC7Q}nn3kWN?% +zG1($>D0ZhzOa8od*n8vlznXFXkO`9vmK>#)%#5ffETZkhZN^O+H%h5fd%&`(fVs`V>unOCr^G`+a-SagbuBQiBfqz52ml2By#XsuR8iB +zF{;DvC3rm+SQ!Px@8~IJ!S8 +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 +z+%sn=9papvLH=ihQ1cKNjA(Mxs +z`Ce!{FVwL|UFDy_X`{GNLeLCF1L$p7*Bwwne3*}PR=LO!7{6C|rW$HPw`CPvjJb1$ +z2JiLU=5u@gEJ>Afl`b*JToHtzQCX4IXDc>E0KYh$$l^htP9N(;MfO=Pa6B$rKS%xv +zYXa5E>TxT9Ew*t_Py0YoZu@7?c!;_+3MY4CA_%8?%qa9Pwf(-jS)DIAskq?)t^YIs +zAGJM%UGZOPyX!yHHgOfS$bYEq_HV6oZ1Nwqjgk3HZ6D`TqJ2}_qCj(T9^M>$yI*44 +z1sRJP?=KM%{fHk;!`_&t%IX0$u!Dhd&3Po%#PN}Q!GGrA0_u-Pz|e^g>a+34D{b5Y +z(28vSQrivfRj91!yQo3hnm8fr2RxhHth5P)p)g)eJY11#kI^BzBd)2=z`99W?!;2y}fP+v1>L;n_tmb|^Z} +zY*EW;;+7_G@=_5MjBRKA)4grS(01}~dlpa_5NTF?g93YEA#!N4^ +zea3i!ouQRl?F`$p4}5Kc*%E7;{<7(MyhGgDL=a7>Z)B>8`iA)0RuR;{O}xS2{z7mP +zW5jQF#|vP%=4eEZb1Q6?+Eootinn+VNgl1TmDJ(bivbnrK$L)8sc15=Khd*ti9>!z +z5*y25vfUkh?o>^klxUye6!KS8{=l*P+<--K$W9T9FP=E(`YvNRyT32JVg6RavNso$ +zLlHbQ%Tp;(E;QBW;SW;U^13#lWILVZuo(F`oXD=+C$TLyU-6a&%tad>ag4LGgMHMz +z0j1I-+*Ob6pk$fC*akh?qS*J0E8& +zI@e!I+juE*V~Oi4ga~(XOYre)R;!-FCK1!0GC}l9dWeTZvVHr>Yg2#>FlT$Q_-*BT +z<7K$+^0rrY56D0wETQ3o>6kse13qbY(DZ9I`o{5;iIO1qzNfjR>2NXGI4Vi-9S5G0 +zQvamwFtfZ4v+=U+TC=tV(Q<*G{bRl0QbmXkNld}w2?kJbvx`XWsJPvg0ngxrs9*=b +z7qkJwzLvOFoy737u8tUF+&gz&!=jYA4<7UNFDqAfj=TJ9h=ts8Fng0hhbr(PKLD@h +zhBrP*RN47L3=x#qYGlW&tJQkMnFM!)>=Ned4}TO_&Mu5Ke^y_;5-f__JW|WXeoNa& +zu@?N(>Fl|CCm<``cyZQV0eSS*cbU13g&CTfLU9uJsH*kzHROYJ#< +z2uk_oZ{@g}*n(?qtQd%lhpd~M@9#`-zSXGBRn^2|_-|+%{~Ov?6UFiD`i8bOp<_(Q +zhBQiAMdFoggq=_gEf^w2ZEK}|EqKPtB$W4F?ts>aWrXa6v?;S|D{fOuAX%kL%+lC; +z!u%4$2;ltD&&Nu!=n&0|Bq{|KFq{waB_eEF +zM$F|(y%nMbO8$I}sLkkI!$pH8r-X#gvAJ|J7+)d~jZ{6Y`v_;hwz}R|{O347!D +zsEtpHx&lyUx=oM;ZPW=rhB@Uf;SvI=Pm+)l=iKX^P!ACg1yyeCW6{X!^kcTMP7&*c +zes2{>7Ygm<$R(dNDWX3n9{u9+!k^qQf>5xMdME(gq%x-Ml&%N0-ZQWBMJmJhG!y>M +zSGtV@Vs|z)RtnKvuepUz=a+xHRl*~73V65^n6aqOKWLkIo+|Y1Q&NJY`~COI+EQ}R +z$A`<<^XJ|50a5YPQ?||6+thAfxAz70d;e0Ej&`Pq&dJ>CEnq&oOa0 +z9q-GpCLtUAgB*Jk=^VXxDRBYJ7akGcZkx6ixx1MZ~iCDx9w4sSQFw+BXV_2RSS +z?hyLy?5_8Z+lSBZ_x0dv?&ctt9sfVlcJ!L^?>+v{u2%1wmvVdJ6J+8x9*M9@W!25Du&{FS!tBQTa +zuB+28gIZM{&|{e8%L&Am-K+{3lhZdzB2=-!XjB{A1tft{V6ezOH}mgsT&AE1Gtsb)OZiBO +zL4~n;ee>;8hNu2X+xT2v1&2O1#{xDC6SwK9^y$}E2MgCe95LvKS9d~d2YEp-FKe<{ +zbf0&3*sc|NxC{q4N4kR`M}#_9I%lXbEJjbx6& +z+aF$QS<9T((p%Q_!@UF&P=et(#XC1e4l9Da=JB4hP`tw|F^H=d`3W;^JnyvhSp|YO +zb0(O>qTvVFnS}M@sr<8^y2D~f`Zs&2x5dk}U5o?=K0y>?5=+Bfh~B7U)m!!HOS{w2f_$s_jN7np0Q|`7gAc`3-Gv{e!l#SpGuWPH{XlC*&Np +zVb(&%ErLk&5%J=ljBAmPjT2P)6N)HN0Q9YbdymEy&N#F?h@iUq7rTRn1y#AE4oap? +zPt9GGRRe+mwk%>~_831#8#wynE2+mxf=m6a-Bod#;04l%sHweao<96ZDogCN-_d=i +zwm~u}Zedv>F{~XlBiHM#fLM?TIf*96ku0EqJ+0NdBpB11M@n{|UTj?8Ud8_M;geJ1{Y$P}cO +z>5ycZ6l9*OMtxxLxn27sN7xK37!a2^WFat)rWA7>U1tBt4bI!sBa|5ctCV@FAh&j@ +zT7_xg0Pve>lv{rQmuldlaJ0?{^7s0@XXm|Q<;0G23}_JeBXsM!-iV!8U<0;?y;`M| +z{aS9a-`ue&+fU#yT{)LBGw^NsSUVv4Jr0EZGi&69*jO;188!qojks|t`*)`2jM6&_ +zu7XFaF=zxCUsTbFO?I(XHAj_{c|ZZl*GpH{SCZl0g%wij9Ja2bx!2pgd3%=+bTHFj +zYTIC*ZFoAWVj528(vDL{D~LXu$Fudbv1QqK@(V9uAzgxcZ;!k}dwo~bFU)<m}iT1J%4Mg#gIOZ;k3PlqsIyLkunK265G+FDreO%MT9F!z!*_whv^bsh+{s*)J-3g4? +z`LDVI-G8ENZ($1BjqO(^2#%ko7>*VgfImCNAFDmyYP_Xws;~Brx*z0!*K|aLydU_y +zos?9YFpTfwUP$s!7O2S&ozj2Z@f(ZdnV)9K@1-WZG4iZ-Hl3{*w=WE0soj3+JpIvb +z{B`KG5A9iH9DI3Z^HJfGjB%mB&hONC>BU1oOt}4uE~)8#I#)Ue@5Rb5tYP^m`LsU| +z$JgZE{`;koziSPD4<45$ZP%@4IV1dH3!v*Sgjs=S-~MTSE_8Z!6Y_t33Fr$*;Ewl(MCBq0LPu +z1Z+_f)xf_%_^sd>5!s|Xbju=Q&i2uqlj4Ha_oB1jSHnUA;ObF1g4T7$Dt +zqgBJ5PZO4FkV>wuqT1^rQGC9mY1cW?8aAlHx}#Xy@drOJMFM}(ZYGwrChMn=04Zwa +z3nI$BTXl*L%fKOT_5QYeQuv6>MmId*+`iCG&Sj5&472yl`tpKF%beebo}iw<0>Vn_ +zQdSK*YfFOhWV`d~7!vGV^N*y5Mk4FnceM?i_));6TT96YO0b8f2$@4W6ai`e)P@;lhpvPYi}PMH#v0=$xO~7 +z4*xFG>ZD52jfGy>C~;41*{K(HKc2ao+T2`5IK@cE$#&}|JSjWY&>gnNw@`J^a~^PYYZHnQI=ANbq4&V*8N7pM7`SoOA+AFDIWM{}i#C-lJP;oNbS@{C*-es6hxmq@VOV>z~V +z+i2O4960NcET7BSTht#G)ZL@(YKS?bB$&5LKI!j0+3om#EScD1^$!m58-eDVrqxzK1+tBBe{xseld6qW*=y{9S +zdgGpsYJ?XyfDC;G7#`v#^Sb~jIL%1jme;L&aFP0*Krhb+dakO^B~}SLmb}6dRvFJE +zbcElrRl1*3P*f5h4z5C52_hbQ^s +zu)OJGU4@TNyOCj4y`w7%~wBDrx-JI~y5pTrpT}``^s_pE`=BWH0jIDnG +z-?s*#FAQo+3<~NKDIcPcBg8Tunqe`e)3hk2F4o{@arV0E(Qvx}r@O)je%!|eSRW7@ +zdG1sFb^rxOHa2M%cc7c8F9Z%K=NzElp<{yK?q+%Vs^X5J8#Ci5$0(;0Kvd*xP@z+B +zoZ9^{quRICUHJxlL*wHLt4!TyFRmnJ&6B6mx6_t`rg +z(m`F;#5^m_0&DY1Gfco^`%BJVnm5%0nw8JT+umq`oiPZXURQ=I)cuUuJegN3s-wK5 +z%io9Ix(xFVr_A)Wt`l#?DA8Ok&pMUF{+ODs_*xPmH +zvQ7i~dd_ObMNIj*{!MLvzITV4*A+C$!&`g1D&f-5$}g?b^LH@MuQ#tCfk#(dC3`In +zKXqXc-L`IAAoU-r*L1getD`mYdcOsIj6Qu++ea^2%|GHV-;RnqvDMQ)@1mI+0j?I% +zd_MKIKF#{iXnJHea}}2!e}2w(PZDT%gn(Da5q!`=9SFeMnn@{W0iodfM{TEXx4FbACsilu_@_ES +z+LK-P`xAbsdCyP;v-&H_>d2C48YytRci{7J_Te9BWv!^c{;9&izG0dQuGjMHH%BS6S?L`L){i@@@=md> +zrSWcoL*mvxAsli8*~uj7b-lytjWp&I{Y0F8YR +zo$^?P +zT9jL8)II&ywgW`GZpO@0e?DFBBysl0v>ziW6zsWzu{l^ST=O{itT`GXu_gUnA%)>2 +zPxbkDwwq*HCTpmLb9-)&Do2_U`H;m{0Wui!@bmh6OyrI}#g*&B>0m=2p`GIBh#OH?ptDi>|5KGKsB0l +z8XANPS!BVtFgn^!KiGN{zrkrVR}rea#v~4-2DBBj^;q#@Nm!}W0F-XJ=S6w$Td=*v +ztOgIi?}G((GOP +zd~{0|hBNDx>`SEfvoyU-J69)JF3H||*k1bqeb=I=yDqo~k=?+2I?eB$$0=q7FH_ob +z{RBl_K#k(G%$qzic^y;%O7jKz7kf>;kaR +z1Ittf#}Fwfw&?6Kwb1OL9V6Hv9eMRzU#_%D)`4ua;1J@&egtZiLRjks#0R8$t%(#G +zi~{EJROI3Qk1d2p(F<}xJ;^jHW?d0J3$8DSJP)={)rgXd? +z%qs^f$s6u)Q*LiZ(67XbB)8EOHk}GqkkaYUf#A~K`Rz8>WtqT@zUKfTwX+;eo{;+PJNv(h +zS$QTc55O}-pRs2w!K1lSaRk%$_bcftFb+gV>|!Ehg+`Ms09)5g#YNjsuIXWxekai) +zaS+co*w*QwlGi1ve&0!*LD47-`H9uP6YCSs##1N6U!$l2BrqSWU2>1XS5#KsG`R$u +zJ-c2g<5!h;oz>xMIwH*FK?&427?V3G#*gQ1*PA3?PQK8)nbhNrq4kz=rVTS9gDy;O +zT8;gNf&`retT&raeEw5%(q9$nC+}8v0NBmd$%4CaeSTLvT5Dfxz=_jeDY_7wO^--f +zRENlJdbou6*V_&|#1F01qXKqGrTOb^U-5t4p?6ndbSQC}a_TymKyB;@F5%df<|rHB +z51J-LR>Lm>DXgd{D*pAh#}BnI55K+bQO01^RVq)pTI*XwH1iRyiM^hDf`fCa5+L@I +zGokOou_iJ+eFnq)(J3#FQIPtb#H12wttW{dzg91!X)suaLB +zAOIY}6#p+*XD^OSjTQ$i7=xRVgXt55(~867gr9|aUD5qo-7hnKL2=br=G=8o=a=DR +zS=EG^4M*5w=@Mlkh<%vG?&O$RDa +z68VVr&^@~)1IgfR2DlgH&~-QPXvOUW6T{X77IiyCS89V86I`W)xRKYk;Z%T1tQlx3 +zxSA8y3^|#P{OvjqK6H{GTbUjx20zZ=&4>XPQ*isF;l91?q-D%p7hGE5*kP~8?Cky} +zUK*Xu70{_j%%<~D0J +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 +zl=ciS1qZb2egceYW42Q!t8y#XwKkp +zm@*kGEb29`GZVdXp;C!^cBp{r8q8Aovzfi@O3<)&?;$U%{$e57&!{oWADg7r>3U<)???iZA}pf|%%F +zj`@SiDn&SFLG<@Bxj|&3g5dJ~Fpgw*DKCGucIrVspI?%i;0}Y2H5ex*8qxAet}`BI +zi-ScA0kai|Z8E2vtv^L++lDhlNLt_<2MjmKOPg0W#QSP8<F$7-V)ghP>q +z*oiEk+CGD!*BFzGmqJ|g0BNcN)Jz`9PSE!YTq}-#1A}E!o?pk~5AC};%ze}Z9CCDf +z1N%?^+0aa;<6n>b3{Lg=%*`T;rA4YeCxfiY^ygZf=;GwW5C|hjKgRcwi;r4^;dR7_ +zM158q%}p=S%7WdUpnjFbGKxE61$f4UT_Ia)8;WNdgu5W?9C%S-YRqRo^=vD;SN +z{Ra&B%rS!O9(?orra?Atj>oZ1)l$@p2po{5cnRpo2(J`MKFEA9ABP=4Ns6GG>Aky? +z`M|S_l^i#DGK_?@RFGjO-bfR0hwkcC=E_=iTFWo_*7`%RFwo-D47QSk*+Y+n_tDw!9ygpevhQhnN(K9A17FC` +zWf6N-T~b#vigPzY!jJZa{(s2fI%#x{W-f`olS(il

_k5R#pWG&Tu5 +zw)lrY(NFbO3l_V(mj}?r3}D6VP97ps5(^UYb6eCcZ=V*l#d-soSIagD*roX;Fj(G~!KcvS5TUNTxvFne4hE=rFH4H+uPD?Hr=yr>2{78kYcO +zXfZv@k+|r1nh>Q1f_zMU_p{kG^C(~7L9y#%_^XF`}!9l%3K<(=0 +z)GyRfctU`?rfXgS +z0ODBmI^WB>o=*;buExp4oB3g^RsYgK&Lx%zshbThA4EV0b)h!)E>whMAqaS7s9d{` +z#n*c5u!oJCb0F?}e0#+E(+#^h8UDO8q$R(ksH`EJq+l1e6}UPa*yr|ltrjRcSrwdYA0EbZ7xM1D2u-zQWas4B +zxBT@3K&YOnam>m&7bp{kRsFuZ#>2{g)Y#FmrdwN`av3@yc3@SABua%HIXJ!@V})|0 +z4P^|cK?Z1v94W|D2gDq1dKZJ%bO +zDFwymwJ!AE1a($ns76fZ*|9@8{9EtsIWEEoYC9z4#4g^r%zMQrdXGL6KY@p#yzrg@ +z9po-cC)vKvmb1JUB6vz0bCnrQOtMM`CSPtEEoJV&39micUU7)gbvn5wRK~oh^;_*X +zpgEvS3DlBsMW~K?`$vUO0~>Ev*kp`p&rO0R4Le_H7WX1Eq8@u0#ohYm5R!PfQNS8`K0h(zkmu@A~Z +zx2V^u{Nj==${;@6q(|o*^GUB{3=@+;>ZWF{lYapr0lN%jLt`x$Gn!$tyuUBQyA_5l +zyU4}o_mTjJ8@F=v;2UfE%&@N`p7+eAC5{kNpDGzows2Dz7VfHISf6#5SzhsQG@CQ4~kMo9XG=BA?Jpeh?>NrLr +zL7(Vyiv)uuyJU}_Ec%?UPH&-P?XFQb?ZplZs*sA!o7sV!{vKe9u7=t&j!fm7fpbf7 +zY=x7Fn_|H@M4zTH!cDGv`pAB5`3Tr&MWE<^R^*G7o7_n>@4MQaGtEU2g*AnTV79KH +zP5YC!M4{Giu582;8?8+x<+HI;2-)c=73=?k1&mXoRam*LjEigRZz&^E6vCCMU4us> +zKfG~>mLYMrb;VFX$3*x9jcd_5tQYJ}4DCCb3Abc)^R%nWPz{L7WfWN@-m`eVB$q&c +zA|s9^sDL*qF>|77xox&JPxQhy-8@_f;of|1J5Kx&_1ovD(7*Zp>Qbos +zUR;8>n$9iF-kD_dbe5Qh`E2mndc%-5McQ9WWZQtRhde+u*|bNU6_w2Bgun>^MXN;nspj!SqrH-) +zfHg>X0_l1T<*`jy8wte3k|P>^Jtw9P*4dkg0ZMCPF^aJ5w;PxqC!*OW((C5fzZN4Z +z^tR{Y*^ZF59IuG9%iQjb;p`1DE7nI1naPVm)k3?g&Z6}(f;5>w$ljB#%XGqiv7j9% +zgVHnXXwhoz5?A#L9cLG;ffl;Ni~K_H3CiQ5WZon`SgLYS7B{9bP>Eqfhy~>15t*Jv +zzp=?oJXVm@bc1gUxU^r$AuVte&i)WHAyKPWS97w3bvL+U>^%Ft$qdD#&oidg$uWvp +zHZj5ZogksiI7uVpOi&6ss9Z7%41gd8#Hvz0D2LCUzvhe_Ok*uT`^I92D@wC_Ce!aP +z;3sGl%ls?a9Wdo+)@sfvXzTq+8RsUZ6 +z?u&^-6`%tYCk$H1Q(rXMA(43D+*3boN~r%_E^P-=RNpW4zNa0Gf65|k51)m!h_Wny +z=W#9xVsrAy7`cYi7YJ4&SGtJN#iM1Y`r0H@dT7cZQ9~1~#zUcd%9)<3mkL_q*}1(Jx?! +zT={zZMn}iJxZIZ+e&Fzn%gx!YFtSiA$nfQZJ_t#Es9~qTt%@K_cCmwaR;4a@gL6P$ +z`O^2eYc6?r8F>yRex0@A~$+lu>+8sN*l_t*j0DfKU) +z4EdA`8ePd9z~THvm{r`QDT7$ZiDd&2Lyzt6Y>EIYxQE*TU?P{-8!@>}r}!i$U>f@| +z((mtOpvz%dKds>W<7@BUVzT)+C&AQVhl%z-JIE0Uw +zd~IM+AQTnSab(2anVdjqj$rx(g~`O!5myq#TL$QAcROMA>E+rliP#eW?V~g2lPnC- +zx7j!Q$2P!HobR%4RVp5Wwd)8wcHGczRb2AeVs3ZI#pK>A;o#fk&@~<)JMhgBT*&b+ +z{mh_{4|Df#F^7P!d@yaz0UM*L{kfXFBZyghYnm>vI+5=IJpvyCryuRp#aOe9KjVuT +zxQ_KFj=ugdJy~l+?@Pp=yuXICU-xNZsHtgn@q!ccharjAy2kmxz1cCjfajH_XRB>` +zTt`A^i6Punv|%jdy9^`aivtJG;|4#qh6aom$WdXUh2l!Q9-jx#N-hMgZ&(2Z$gSfk +z8Cw@2*+dAi@lChR5^2)QQk!rd$DaK5@GZVM!i}e}@M(8uh{A+)ziZaL7&-CAxThZ( +zIt0KIpHl4QGM@r`;mQHpkMu0gS;15U!Ziu`M!4k{yBPfa?fx6#F0cLv;m#5L55led +ze<0k)m_VH!J__F72sh$703Z}J72yy^y6K?5pm}gA12gJ-26*>q+C7CtdXb&Z^X`IEkmiO!+=GKD +zSdtDT*_QDQaBB_8PNu$`F_)lLL#H^lHHTg$9lDt0PbEPIjtb5IPsjxsKkB|&Ne!M* +z71{T`UwPg^n2Fd9O44;qaO{*g_>CaB-X0w5galD9rC*k_u!!Oy<( +zBr|O7FA!+Q`e_N~gCp_v8ATw?4OunIIK3xRbz*gM<2p?wp$Dri7zq%G$YcBzb}&gB +zkb62vN8yJ*LdXD>7)nLzKwE#)oYy2z!{povvvbqxIMOIs5^v20btj%{0s!)6jP^8p^-JvX8=eJfx+A< +zM^Ctn1)^b)F)Al}3W3=vfLe-j3!pcjI*o1BdRvG*r@Od$kDBovezFm0ov0KpYJhr+ +zRE5ofurl;d=9~|A0*fRXwd=WB-|`;?A0eCtFb?jg67c>OO6$FP8DEnn41_Hd}RG3Zw#%5i{TAmLznj?vn=7q#pqR +zz5w>dwTMyd=t)*ugtNDT4b5gTWv>jyzGh_Et_26EGdI0FQ6(W22tF~z-czunZ^l5s0w{Ssd +z(*zy>rqsNI2-Oi&h7=YGt{rzDRO4C^W;|DPkUV;=H)FL%X?*G$N>t46cLH1q?_=?H +z=o*h@)S;Isrntbf@+Eg2lYnD#IGC0aUfhOaWK2HA&Yn3 +zs^*sn*%jrx1VC5$0CijEiUsT@ePQ5N`y}UWW-%`3*X$Pjmd?Maz1XxnKQ!!sk*hAa +zi6y +zBMr7W14;tQksRbjq#c~L!J(TM+3Wlj>#}tq=<_cKGwQ}5O9&${@-Q-+#w<;c +zfwh#EDXPc(p{u)^<13El`tYT@7>z}OqW6A99{+A%)~yE4YFj7Iq{o}aR4a;tgqHy3 +zL+&5J#)^%?obcn&u0LgEuf|Ed@)Cf>A-2WRIlvH>jSAB-@m#!2X!$WKfxrCY>=M3? +zScfNq>KaN1{OyiOQo8J16?~Pz)h5}36EAf!$vq=m%4Fs)Qw^30x{>7ZLI{0_LVymJ +zDf>={j}MT`-v~wqB8ID8BBQd)GF*uhg7$k!$H$CM=rD<@6318q7iuQp+=w&y_r!zW9FXvP0Km{y|T8^u7K7`$i@b5#Brs3s){U +zyTt|@w$;c#?TAg!yzj0Z*QB%s#cx_Yhr3Q-_A7`A9dJRpZ(Oxt3>QoD>Cq7>pucyM +z;6Yp?-Vg?}*Bs^|zC#@#FsyE`?oZKAY!O{P_#4Gfclm-&$0ngH%;2WH^m^(6*fQ5kaoShZw+&-^rFiJ&%mxxiIz!Ni8x2mF6{wC`HQp%0Vw@x;aSR%9>Dgd +z;B`GCYYy2eKcEvstB6!Rs)!0or=ZeaE~tf}ZG08)a6~XL+hXf%62*jbDuZ!MiNhfy +z)*+P=JlVXJ_&!Y{ekl_L_a~Yyr5Xjk#$>`1^gDV~E&DRp?&HAl +zXMaSoYZ-Z48_bt_Maxa*3zXVJjg}2 +zBJ%x;iOj&4yi$eXzn5?xSiZ_RhsE${K?LIQgf?`ML9?em! +ztCUp}qSL%B6Jo4abkbmtPW*5kvGYR@bo*I#yw+{FAn5;{kFJ)7fc|sH%3Y@L2$djO4>UKo%jiubi@(0SP0ZpH%nq9*Bnk<)06ECiW +zZG}9}O4x=YtKKQepTR;KTHCDMT+PxlhawUrbxnDpo?I0!|&6+4dyUWs1OCZN@{X1V*p3ou&D;Z5eoe^tZY$Z^b2Fw{>W~)S2KUIf +z!TpGCf%mu&`dOcPh|!{_^RVb9qvM{_VDb#w>D>IJU&N}+qW{<6F8Tj5xXG9J4sGz$ +z&zqs7-i!fweU#sPa>5Ov6Np1ld-fG&;d{A!e}A!jBSXY!duoFib&3P4q5JlgoHy+X +z-q=ugU%}bG>;0MY?a&df(f1g3f^Qp-2s6_97kSnK&$jGC4-Jf~RF{m{s?8{H04JL- +z5Y=s(ZpwmQInS-#MZzj@`&c?nWiXvGpHyWct=i)aicW}=6d8?d2QOj^h-X5C#FL2f +zOvqvHfF@=uB?_8&P?)(5X6CP4I`$~l?r4yxN!o?u%Qfb3+JxSrAIp3EU2J}muuls0 +z-yolCTT^ekN%a8SQHSBB;ytS9>y`kYmG8}XK6pS3FP6dod@c95SoO(;TvUGK%^mON +z9qg!X)ddn>*ccb7B#8+BLH}OQ6ZuEoUKSWSZ9HM5c-nastg#gY@b>>8xT|-^S7{9~ +zcIc0`6hz2XD4_UYhmxO;(mC!B?tc1=POZT}YqsNoXO9N+Pw57C*<6V#n=qiXo5KNv +z-FDgVfHUSQI`DStHvxIGqR*9sAH@CG<{qTPg+?07+ZPoub!Cm(+!L7%cDDW@A +zo%R1FxKTjn{}SA<+buT#65Ow4*2Ok&fE3mRFJ;=+#x_zhz`Zdh0je`3G$@(!DBs(Y +zi>iGS`UTmioAxj0Lg!ysj;G17O2WI9AfCD`-xJ>f8C*8tUW;20xfs)bQ+z#Qm +zDHWns*g>PDYfSuuVAbeVol>R6DTyHza`unmp>U7~AE~`=co>?1`x>2Q#L{&fM*Osq +zooBYp_5hV<)eOdq4NryzS+P-fxYSa8L4se+Y2^)#zbW(~JET!boXl#xD$#4S_8phY +zmrw@5Zqt*flR)@CS|)21BuZ$^aJjtzYy0Hz-e!Q_`nZG352LH06`k_ViD&tbY=GCm +zxeUvX3{O-;$Z|J{|CCPwu4$CtaTf +zKR&>vj*1+KE%ZPefdbj{E%HO~WBZvE>%rjzo1UJQiYvCcB)@ +z7awq|R#?01rDeb~5flYh+crURJSszLLq<`Wk42>d1(*uHk{dyoI5mYCaonm(?T=uG +zL2h0m&5}B`l9lxGtBr@k03bfwiuYFgT_Zsz`%ufbXz>ZyakFdhTgWK^>Nd>|8QAs3 +zq6#Ta;L1Ic%O{8JAhVNnHq%MDihO^wm9ck3($9rJX?XBlt`M^@!%%WGO02Gxhc$14 +zKw!D5{yzk_Rk3H~y6nTcQGwmqI4S9&zqTl!MjQQsvTPYd$AFputJ{Jo|M7|p6qh5{ +zG%u9EgQhCW()un`R(#pAc}nuUYfm`>87UUn%KYcC_qmQ5Vg>ivr#>YhD!74%QhZzE +zVms#v_&Zo9jN4qJ&3c~#STyLzEz>pdMQ8VHFEx=yFK4{{DkRy>O68Y8vPXzM;T&Ii +zItHz5SnR@n`Z0D+U3Z97PJ2B?@G8+cFEa32X&P)Y`PIf4cA{-LjXbZo6aZWw%eqaG +z@%Rl-5o!VofR+r0-tMv+(YzE~e%~lR;awtjk4a}(CHjeg_P$m%P^Vim0NpPKilc`C +z%%(e~XY8>r-q;qu6{#ATR?&S*=|iQI9DC(`jO-B`ZGG};8mY&Z3A4+<0(p$ +zl;1i0>j_@DX3MB~u&rnc$>_(_d#^^9s`3=f$u!mOxs2~=)?)NN;fRM#p8MxqubYmK +zvRydvgUgvW*vxv{fi$R=71^veIx@)YS$yCi-dYh)1CPXTYHNDN4EQexRj?9xDDm%< +zg7Tb51lURL`VPk`$BuBRXeA8Y(R_>bkbP5y|%`cKPD3{q23bP6TIz(3PNLw_g*#JxE* +zubNuj`d!e(gS&_RZJh!6vd>MlH6*@9LtgRcasV4WV${2}7WZ>8YH?xUG(G{a0)V6%jy)H+q|QY%kM*M45N +z$DRJ_#z75(G)~xm+>QeiXPSl4S3tfVnv!CI2jn#A-b +zblcztfG`p;YJ_yumU=7aq7NdBVxeHcK0Gaz0wVowaBKfHxMd-vbwhUe5Se44wNeFH +ziVgM=v;Q%;1LOuwhlE*tFpRRvZj#O&MPCV*75U1FbZ>i@bd|EXk);%ckS +z(nmAaJ#~(e-W4>6a`(ur?qt;kS4}1|mKYc~DM)H3G9oe=<@1GX)0Bx-!co?v%eJX& +zaD$+9NASZkHUL^JCXKey9#H7z&Z8YS{>KCeIyx{d>^$5}X+AG@Mo{9{^@^_hM%OJ+f +z#I6z15wZ_~NB063mL!O*yv_ragcCx5ODsr~^BGT(dpHg2ffdr~Nn-Nl7A0Y-L@@>) +zkoXW}X+`z%Ew9_WseOiDTE@X^+PzW>!?t5D0flCg`pLX=Oe6-P3|h73Tluw+Q^8kk +z7F23Eagq2iJZ|!sU@tb?%7F;!L>$Pu*wq{Yn9ff5?>PJ!hDdt%fs38g7RAf1yn;o4 +zMzNVDVAqYj>}7eHWAxr726IQ>IX0MWy!Cm^b#tGS40=3G##LLy=b$8K{IQjW$kF=L +z6v&3gN91F*hhUUJ@SlbrwO;LJam2;5T> +zVUH7S2Ds&0vWzt`8KKvRKE}-p2xb&)GfGDK +z&x$^Ey*kgWnZDe=26qMOZ1Yd)?}gl?XncDfeuqw$z%cVsG~L%05%WC7`?JA} +zmT^M1>o%thuPl2aZ7M+AO|e^sLYm`1oxm+mu}3(5L*NGmeqUS +zXs9^DnVXQgZM8B9yMJ{#aZgaZrt0;f*e<|j&8T5|237th%D)CT9}0N)KL$54t`iuW +z%G|fXec%^B_AAfO?-T1)R?Kt +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 +zi)6Yq%CVKgZ7Q&Liusw5 +z?pjAjWsU3@)XHLB-oKmSR&y%t!s_MV1HF*uk6D!HJ^T#uRB}}QkYQ)-`uGrNSiA>J +z%d)_yq^iN>O1Te#1iQg0kDSs^BeK!%c}^7aiKZSk=HK4l_dL)Ul*^ein$TZnp&gY< +z2+Zadc~MF2gdM9dU_*w~H+gBkYlb%|b>}>i9z@&2buO20!vpAB{x!I9{u!1HKBj)H0kzp^?QW&PGj!i=VhptBPzYT7#X4;jAvY>N{ +z(f~<>ap9bQMa!-#{mw*;HAHVyi4WN$M#fXB*)vzMCTwO76?mDg=7gKO5GoAFgt +zgiC@k<+^dKZT*6W1}A +z`=hZ{;|Y1v*K)wguLYq=%j*T-to +z<0&m+*Hxs`)5ey$ViR$Z;>Q}qDz+voMear=amRr)eqvxM^+C^8mThUvAkPDJW;b`2 +z{L@tL%~)5vSz_O*jJz+ln*3pJkL{lJ_!f7u(N+Qyp#^qREQIFJ@t36UBr;oIDud0}>=k29SP$;m;DT7W&4WFMmF%j00d6F-cnb@-$tEK@c%m}emT)Y(ai=ZhF +zP_-X6N>_oxY6nF7m?{kHh|&bqFOVHpCm()KzGz_XH%`;g>f_erXi7bD*!{@BJyrL| +zSeRS?;%sa?V6Utw158f(c_R_OYH(x3P$Ms9y1HXH8JxT-C`rReGj|({GvdRaBI3i( +zUoRZmck*M6{#fgi6y``;~;11H;DKlMsjGrlQGMIUEUE% +z8*$Uv50Wj|5Tg;Y@l149Ie<3@j)az;wtzJAYA?;Kh7us_z`{Y5>5p3uCb}*XAjiDF +zxBut`zzjyBT!DbW@(b|!IU5L8@HNzpf1X3}7THdS`vBbToGV2?wX|cxq`^7Oeff3&$Xl~42+UeVgpLaOj%%&3V44J*5Kd;XUqY(qaWBt +z3|DTw0Cn5Ne930N-;z(H@le-p)u6m+$=?2~p)^xV8boc4e4mgG^o&2yeSppS`PPiv +z_`7PV_G^dzx2g^qS7o~MJd(i7nSj^e#dF00=NeY +z+@O<0fV6aMgh*U`sAm9V4SW#(J!6 +zI1ymLnGO3o2==SEClgDDzWH{r=Uzwk>Vqjbzf_lY@6?S}vwMOZ8i98vrf$s;;Z(ez +zkO?~0ydJ&ul`*32C#of3N}LbbJ6rR6WFVoYH>d%^Ouq49f0&Qaw41jFCaOs_NfBp& +z2}4Pp*94>LRg!pSQtwI5%UMWwIuc7rM>B${k+RcCX{+@>pD?xIcw`x)5*rc;xZ<%D +zWaFEYS7=UNtPs`l7t~LZB$Pb>7XVey442b9le;qnc+Vcg_eof#FB8{e!rNLT!V2EO +z-l9MV{EY#;P_Y}li4Pz;Wr$qfBUCpZE>r?i*MhC&y}bs3c;X??(8CJ~J6USnHz~Ec +zJkS3;D&P&=olJOF8R)x+w7DOw!9N`RdUoaFf2tWC1iy9cGwSN+ki~Ru`p4iNG?(PJ +zYNJ%$7czsrLfVY#y3$|e4<$$4#3>QbBNE^3V#bGLJLlft=f^34_pHV0YN~>g!<#@Y +z6=`kUX^>!h@r*+G*^0U|r-@^ecZBpyq6;=jEw-wU9<^_f&`jz67r$IJSVst2FQy%C +z@b!7Ab!YyTN-XgjYh0mP?#D?}Bt3{jd9atcY~?YoN96+bDXc^QnA^xOCc7+-;udV$ +zb$WpO%5#$otgJ{}MO~69gmj${xXs~vZN&}<9?x&8A$aAG!QbK%d+x*UjGeAXC?|4z +zD3}vl{9YOv8ZQfpo{94@M%N3=B^E&}zL4syrXvC)SHNdr3fXfwz2aXM@7Mtm?HQ2`Wc#d^FkCF?Y?gEKo#TWrv{2sB_I&9%gE8`&g- +z7L;57t5XkuTu!R&fhc};{^Z#4%xHM|)ST%>PJ>g{ct86@%d{+*)0yUytz@F7dK(XF +z(|gS6R`%L>mJuL)y>yw_>h7VwxbDdadCqyaL1Xvs`s10g?SqQ;^=YBAtJCfL-3j!_ +zYwcHAd04YF-jd?kvv9h8-s5HX=koXpk7@w%xMf?<-{t*@W1(cr`>R=K*+z1$<(gM! +zyW8N)TkG?Edc0-1WgBn5#i`x<-Q(ry^}MA=r+a(*``h#B#nsJyceGz&M#lQ^<>WDD +z_p!YFa~Yo1N6E|Z)4vl~;AtBBf`?&`xC8zN +z;U?6Pzwi0!nENx;_;qq1CF%-5+dhwk}G1!?; +z^TT&K>zF}V+Gwqw5Yl!P)jO=x`8so)p_vKd;7qzLz&Locm&y#}KGV#pneVFX$C#|q84 +zA2`nfQNRlfvhj~z(4eRz&d1}L?uQi*&UJ(WGL>1k5tT~Sihj{ZPPMWCEcx1)eJ(LN6;1Mc<3{Mzn0|^VN>mifdFxe`I<4|HwEY +zH4MfgzO83-8$fHAG}T$JWL(1*o`txH$0D||5wRbhMZ%Q>AWcrCt)_N@rAbQ=Xz1#B +zv~nVW1M)3kV2tZ8l^sPh7tLsnC}HE6p=BQ_I`y5H*o@B||} +z5sI_XH5#zZ*w;VEw)&Bq1_6p>XPm66K(=EsZY~lJOB;97li-AWK{R=k9~ON +z#nZ7hYP?SL-w5}~74!*djw-=2NdEp$HJjBv({_ya?yE9!r9CDcgCC{TmS|z5804g$ +zDu=wmF*u!iB9<9-EU6HdnWP{f567i5?k;e{rEBJGXb_0?xcN#vu4ZhfHcEOf;f0THi5eFZ-JXNRzMYc8QJY0EqGM$C=T#?``n +zN~h+>+QyAlg0cFCFL`OvZY@xcTWNnulQCeXXNIs%$P$-%VLOH12|L^>*n3_cra#i8 +zKQJ#9`*>!v_RZCj55w9gejLBse`(mqw6uulN+0`*mmgj#R9wD&(WK5k`0y6T@OKb; +zVXM|&_H6EZcDF-q^R)eO{*<(& +zwc(%z7|_=nG5+=s!u{L;yxVM$Ljbsu^x~|K@{MrcJiK3v`Tj+?F^S~zXRwXNh``YC +z{WaX%zZ&4+jiluTA7VsT<-QT_yln35Z-m=vE^-#k0cl_$69VQRggcyE=O2U{CN8R{ +z{6zy%`5WP$@3`l~vBiu&B?s=O0gbWdpg8Iiag*}NfSPAbt<2}VuCwGw*9mZ#? +zlL)8JHS~vz^d4WGQvV>_Pm(4z*K^B0=Q-H6ZfGH|>wlic`E{pt5r#P1le{ySUevm8jY*6ZAaYmwYmKon`hZ +z{_N=@0Jj=~CE|(zwO1G4e2dJih&sDnb=7dmx=(nq%IONqs7eRbnRaimz=APh=Ip>y`H~# +z;GwGNU3V9pKNWzG})brscRmcfveh)BRx2LBO(u(X|c+{=CivUANaF +z6ZduZ<-Rd8ufqPcF!gkj$tJGd=BpaJ9R#@FyC#&DET=_qSi!--+&kHenMY_??dTe? +zptg{1P4}gDM9kv!YsY9zz?@T_m2^5yBLOnmA7=$Cg)2AD4Z0r7ebaCq$U5oQ;#=2X +zb#Il8eupxq5oLYI&++vP!yZpc>ssyb<83dR*P{bJ7=*D#nx-HNY#!@v^v2$yGJ5B{%I7@M`9n`vnAgy*a<0^QyDJBV1U|I{1frC} +z7~ODP*zLHOcsEW{9$xv9l3$|`#KniaXX-L}tvh|XsePE=y}#%EMmU)722s7Atwmof +z$Z0CNYsxpR7S;T^M0`~mZf70@*QKaLCu}etk(M?y-UjT7Sd9SXR2(}~W>08#_Df9# +z3GeX^OtI90#;9@#NCxHHit%oH5S;dja3Kl3DvBiy<5PSrRq6fVqj3#MnD{y3Qp=Bp +zS6+R4?oZ4O-g)bE%6V_9Q#y5Qw1X(@5^2nrgDwgz0nG1DmLG +zQVife^7ahOE{3wyl)B)_D@1^`)}FS)1#(I5!MLb7khV{j)8ML9=I2kR$JY)tN~X%m +zyk?rT7!i~={1{L!J>!Ob=ED{}xFRor{DdFLj~`NaY!2-XjRVs#nxdk26?U`g=|brZ>te-8`rW@38md6^L?{j}@CLftbx!hS!p|SYu5>Jai=dc7T-)JQgel0XP%G +zt>k7t(W{R7(cZB;Kd_L%_a2P7;=LU(f0=uY-}wnrS?xnLPalzwCE +zYk?|{DobTpq@A(Uk+2pc+#sr9u2LSL6 +zPEOYaAdPdF?Bz$O)n`^b(cyT44B%=~YBay(;GGexmi~Dm$m}b)jSr;?c^c)JQW0o* +zvH%1>gU%DDFPx(5l{@e}2m2Xb)U9XcuBo@KjP%0VCtp?J2fO7p@AsHD0aGfGVc2hW +z%1}_eh3eyn?s#Qf9+WYDw<|%am&OdOP{k&o!C1 +z^Q{h*lc%*nCx*gR;jhAN#e48q;TFQ6`Bu1l@I>uAeZCd$*t@^2@!+mNST< +zwp~Sk&g=aj%JA{{H6HHP*M~w5RrPLdi=K}gX;p`9Qb}yC`fi;kaiZ;aOMua1=N3tr +z43oaEvo|BPg{PNwx(km=_U4|ulrJZ++dXbB*CdeF6k{aczOWFwc4QYw;!mFD5S{gzS69(~UW +zZYZx^3lCN8tuYlYxnhAE?jr)aA0_XP9hpJdUe)Pcj!9E@c+Vy`bJ4B1$gR7=-k*j4 +z4_)^Z9f-EAi#oP#+p5^MlZtKIw(X>1+qRulY}-l2ys0_YUTxoV+Ib((qqQ;m-@hM1 +zO=FQUxQINO+Vb>y5kXp`^cFX|FG9+%H}GA(0Nw?*+A}Gu-mB>yNw~@}j@cjIWb&fq +zE)tBf5)#Dn)dFarN@#fZ_~S+Z>679*!lL1wd81_naE-$@hlhNw(EsY-lK1wmB?kZ& +z@=`{+=ju3mc70e8CU&9>5JszK8e+7`^&?jQtua +z*!{%y6YY7N{#_^^tkVqgO+>ebK;Ndlj|o2C;TAYlC9PBQ1K}ftE2!dG!LO(Jd3jdq +z&L#6T%pB@}Dco{Tw*R-nedj&>%bB%_cg8n+l(w7xOSocr43-3&$h!K?spgj&Oi*Ac +zc+PVD2}O_3olBpQ;IT{{z>-@7iB$WjrKRar1|!J4@2Wul>$7p)BsH(sk}(v+Jlz&z^NWSzM0=(>p`rCgz&yCrz-uKrPJojk+}*i +z=7R5DiR)*XdXCX#xIq%;V{Z{z2sw83zLV!V-EHkBagCYidPiXdjhKDzj8*2=jxk|2 +z7cb`Vcqza{2Wb*)18T7|j^$nwr`?J>jK_Tl{a~J}@-9{ik{;xFy$5*}{R!*2CwYO& +zd_}NundNOrYA<>MZW3z_JJjUL^WGb38!WBWp2sTcDZukdO7@Tmx?f!*WgKCzwArw3 +zpx$AyX03k^wGxD>m`A46Dl{FDc#p34(4~hjK!x97!Q6Zksp^Z}wD>B%0OLfq`T7s5E +z47`G#Xqk`N<=a72;_fJc44L%6G^npK^&{AoT`3R_VP};4PEywTiZbSd*J0azUhq8| +zBy|chSO +zdrq}loFiHzZ%V~RE_wowtffSk8xN`jl4$-dBrmvs0#5?T7PiTVV?`oE+=fF+vaADr +zr0ifR{++1;MSh@V{CJN_UBU;}&7^vw1w%Of@J +z+|JzNME*om-wHSHpte({g5|fu9fT?}>pW5vCS(~A*OcIVGj(VCR^S$+fl5PY_ADLF +zozlxi*xGf$OF4eAROLsi`HFYuy=%b^7QGCt?6Di_rwKQU@j_08zS+IF6!^z7GNg4+ +zD)$JnZ2ri$`fXW?9#L2lX-f11QWyweRi8J>fl?9$c-m-kM8I@R><(eakYHKvU_g%i +zUOveKQ|(G9W|+|--@I`js28bJ%<&vO(wFXQ=L461>j9k~)82T_Y`eePgUO3_ +zyFa*sYXOM&d<^>OT#n<4GQ+Pmt8%=!x)S#z08To}6{Cb<9Y`p)*hoaG;jGRpW>W?Q +z_Y^iBk6*G2iS(*00xU<(#P{R@L)nxPjJ;NRe9Re%Ile!8sI8exNjSw4%@H5?;p!n7 +z6mVvY!eTmn$AvuYQ{o8e94E|nDSNjN2X#Ij%4r2#$&vHmK16hCvjhGj+-mMBFQY&R +zHy33Vsql-9%cU?PQApniH#eFS#Pi64uhx;=mrjD=0)mgG+n=tBHXm-yhn-cVRC@G) +zn3Na(TTS&#W^iL4dH=XynU2R!Nc;|5eclDEyb@M>;AtZd;M3>e(A=mv11Y}^EcN7n +zm;4vu{_~A+PXxq$BiufCrRQ5Kqd0&U_UE?fB63#;7$fdQ&Y&z54&A?LzWmg}tPUeC +zNVq}K01l;Jn%}1HfGsVh+An`Iz~a|XR*(@|! +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 +zWs3L0B7k6r2fxZJ+pF0;29p +z{2>J?$3s3m?R>hK8xI90H=+a$f+L99GQp@jtv`;@NTD04Gis+!J3?W{>PeKKi)U@F +z0QSPFa&hYj=}>j19VaFiyo8PYRo9h_0M~k7B>+8)(_uX3rqd=cgRUlN@;*>$KqcPJ +z#?T}CS+xol0MKq{JI<7OQ1T8F)9x6Z7_uE(oj@J_o0_Vw{J`qo`x~YeSjmeAHkqJ) +z)n0r#31$Me8g=0&5@`zRCugkBTo)K?M4+vu@cAkm7mMXZI&d-(SYA;9ax4gJ7=#K1 +zQtJqD_Za0jxec}YO>R5(L4T9mK$ZU`x1WUmOKvMf$tiL!TCmCdCAUw3KK~)N(-8iW +z+cAI1?FT1KkDo)|HeDydq_Pm1~Mi|H^cQgQrM!Hsg +z*;2~Vlc`)r=Rf=$RInfw(Qrw0y2-HpZq#h|Rqvv-vo +z7zR$N!SrmasT&ZkA^ChhtkcZN2{gWzD!K?)tix_wvx7TT@hIU6x!t9dPz0@p0`XBI +zmU)2Q!PiCbpd{Y)sR9Q*PTfD2@BF+7j|l +zzZ>%=qf5*oX3EkU+l2T$T%`dMSbEtn_03`<M*au)JQxoWHVpCFxryjD2R1@SxMHhK+ +ziEL#A-nln2D@&mP6r`jdvH}4Q>MS13kyhrd+qV-EbiT3CoS8|hsKogcWDw2(dL3U!M?=>va=VOgkcI9 +z*7dmWWM*;T7Z$2xJvrmc7X5@6rA?CIJ2sJjNw(XwhT-%3)Bu{ML^B>{UidMQIk;Pl +zJoXyk-{_>I@}s1ooq05sA0BlS38$;^FwhOO1AhbM>}RRK7~{`d6s~=Q(m6~)DS)$< +zk_K9&xv3t2L=z_>tyEeKMjxyaS8p;m!2m`L&7mrQ< +z=qsE^6zZ;b70m$gZ0}6QaDIurtYoAS`LSOFpQNVMYP|MtNb;x+7D@QdVCynO;pRgk +zQYUxA@%&Kv4W*`6Jd#-(mQ<9kRa3xQ>8)jq3D>w>%MUdV8YMmmhUd$eyl%@4PalKz +zQcfTnxto|~tOxwTr#QX*b-{qJ@`}8Mxg`mO(}qU}qx|uGYwuE=afw8Bnoy$cv(__~ +zV5y*9T>VcQ>wgSwpqX3)9p{35L^Qfoa?KVpC}i}InfKn?d?vZ{gwA}ZN4PY6xq$g +zGDg@2I)|Sv%|TkNMxVZ<2Bhcf^gbh1A7j=oS*jd{wO}6UblvpG_=01HfY=>`{Psf$ +z7xa;f<4sU@_`wgAQjeEaf}-FMI_Zj= +z_>zJ*Y{c);$~LUuc%tZ~vqm!)tc&c(6EXi$S6y$+v<35Iel?{Ki?f*5SG=%1 +z5Q4s11@7LHEDt1zt%1#-sQr_xDRiG?{6w%VY*740k6l*ollfYW*??f5XL*<-*C*+YYZz +zePQOKTgzv51KOYo`Q+U3{?J4ZDqHW|_?FOI*3Qbv?QGvP)4J#i8&hhcnMl8Z6iAZn +zV#o86Wi9!4+DGIv1J@x>&Xhr3aR@WA%SuEaCrbf6vyRU@M}_nJ^PO89vR(O#rp_~g +z-Rg2b-MzvLD(t6INpNgUjMKxFlHDZdYBj_xs!5f5h0ijrVt{mWG8Yr{u65yCI}%A#Ild2K~y^-aexzXQ?b>sPO^I&nNF%J +znrdyxCR0$R&de_n5lH6(nl>pHyY7sYMwmEo(6xDHdAh~hvpj>tL-;*^`7S-yDGCO* +z-or$X8Q3MaF@jUu%Z_^-2cjz7#TTb?vO9UaC-$tbUZ9PAG=bb-*tpa}jijt?S2V+EjykB1kz3$A`Z#+}l +z9z|0)VNW+`0 +z@Fzb{a8+OwNm4%+e(O+I6-)I)cnJX-RlLJF1IL+$^D;%aQygcng8tjJy2XS`AJVNX +z?xTg;LA_bEfgk`Dgv|3S2ygztkNOfEpnaP9G&Q2SeXDV6R#OcBRI7Dt%jixJ!aZ^zX6Hy@i24Qk^r1WsS2D%Az_Ua?Y9J% +zP7^YWMmf@VK&KE%Br&^!Smp`Vr{HAu%ER<@>Dq?ot +zpu(8%?y1K;$GIh6K(eHfphgw$OuqW~1&FN28RVVW&#fHUNK4ciV12u;H64!;@fNFs +zmx+ap8V3PHDgNiPQ?4b$c>PVT+r71g$M*d?XXwi0i-NgOGgHRzgWFe|Tt(>a?3TZW +z2VLTTe|5h%7R4N*V7CIhdsq%cG;kjuU5rdYJ}iXhvuwFpq(vl{=YE8SD|-`MTow4` +zm@i*1U)S_puy!i?%R +z#JWmezkHNG&qZq*jWf&WqDgXx*h;0_mWl8geerEVV&?c|wBQyk1WAsj4%2x^srZSq +zl!ir;_VtEZZDWnlIweS=F?vA?uyDTmQVJ$6tB7W`AXL>kq5~|E=}J1D=uDJUlm&tt +zQ9PumZRkTPy16nbb^;bsd>>WCUievtPw8oFW@>;e5{x7mQ|JLiGncfg{SH`g&wTCo +zjYp9in`AT`;cYuAHt_u35n9#{h20%gO(Z_~*g08aPyi?279_LEyqt?H9wWiIJ!C48 +zqf%0TV_Q+ywTN(@B^#sEXqTY39(zXd-Knj7ktXr_AjxFn4$KJ`fltdvd4WkcZ2V@Y +zpOCIO-D76;=0W$3yR*n6{Jm&L1{b*sCAfK+um=+Z>I@*nvDHqkCr9?5a84s0N~atp +z2T1!XBYC{6@IRcR#1t%s)8%f;;H!Tbz8S0)_-~Z#Zv*27aftS5m;w2{qf`ZR2ID|% +zAIwy$sg}~@qgOvG6Je^Cw^!kaN&0XfwDQCEcV;d*T5mT%lE>oH2vj%Q<3|}-3Q^Es +zuSpU^^h^QXC+gGYPS{Xj9TfmK0cUM1b|a`1yB%b%5hEmRZL$c;eTJc;U8^qc=Belx++8 +zfgaL(2&MJv5!DpyVKL~VK6w|lUQ7Ra)>%T|6}#5(24umd=~<_UU4d0+4AcHGpHDqo +zo@O35STbaR*{F-O!KV=|cM+azjAEI4$7VO>tO?5G&Fq)MNBz+wCsH3QksuVgZBIo3 +zsfWj}|AqBQY@GmoTe%mdMzv=(XwR{P>$XYB2M6lzD?<{6?L45r +zioF@{D^Jk=*+pok*CNm31>bCtMa3)rtnqfvp7u{I27e-pD`VoN1d$=gG;ekMVP9JF +zQvcw|LkXjK(+(qG4Xpsb=esNbeZT-g@8~rXNVnyi!yxo}7&{EdYf9q53KY;>FheO% +zM;Y8Qh?mSBBU9@TP`b@n;2EO<0#k;8Ew(3O=*Bbz?H{3lfzMlPIlvO~ea$qKhKC=$B!2a;gg9@AK{0x;uZt+6G<`#|Q(gV_Y;KJ=`9(G2x$92V&zq +z!5|?v8keP3nkQfn%77v=oe&?d!L$wKgaXlj&U|V)#RQHP$Y+bfdY|=2MGI@wE^Y +zsP*TLrIS8ElDr$#qH{*+YMksj-=UzeTCPQ~9;<=+)M>=CU}gfGR5f%uW2@E1_Sws% +z?Jnv->n4%>!8B1@CqmX&+~Tj8HgN=#3426TWkh$JqeMqe#~&k$w@+@iKF-~1Vk;3$ +zui>L00%paw!HYYhnDcXuBMMt)En;C!0egc4DzWHKyMP`7%A%0QhH=s?L$}ywvzW5=EPb +zh;S%~gOBu1XDm#$-!1JH3sQ;NuW(Yzr8oMZULE7Z;3GI!`ysA;l)%NX{D(4Xffo@ZhDUtyMpX(+oWySL;(y`gy04qDC +z@ZM&CA3JzLiwkI= +z3l8~qZzkaqpjxx@Y(*ov=NyUBga165Zj$VAFH>5(>!qf}HslrfS6(wia{gI})QUJO +zHy4jg1_Ce@dZI9bIC5eEGvd5fo!lM50fYM9z>%%LXDu!2=GT;Hf&oBsww36i+5K6B +zOyQwMaMASXr~Pav!as*w6wrB`1=6qcg;g0;h|q~=B(Fyq(?)(H>1?KxY!%_|b}eK7 +zC&3600yW{zbMe&o&x47S1NB7xN=LU~`wT4B*icg_xOccTlT=hN9RQ?3sm1*=^#(B! +zb4A;9ljGyo#TAyHut^l&6|thwNLB`UqM383(_|WdP_412x4C(@JER5@Bx1O3+DLtwm+a04gWx +zeCZ+`ZON^V3W=;VD@<+4+sq&Dcj2JNKiGLs7n=zqdC>L(_H)u>>H*+iTOHf +zayd+Pw43FpM)=x4!=k_qK~{j*;?ls{zhk+CKaTzQ1UZ>8A?A^3*u?lih*olIoev>BDHj-?oXU?v0(pGRg7 +zg;cT3U486R62&4@`0-a*B4)Q{j`m4%_0j-<T}5>XKqu$lV22C|+CAy&ox0 +z12XTi^tND%Yq08^bWZX{M*om4D+4!n$*}ZESMUrk>@1GBISR64eZnHH^Lc+?Sfx;w +z9yrL#(5ua=#%*+ghR>MMr@5_*(wGqva5>}N2mWeaIg6v>rQ#_{jyxEr2oXvcu+p(Y +zDF?xe`opckNC6v%7n@y>p~RhvP6g}=R#7y*GW_loQ=Ar?un|&Bn~gkY;A9|^SHNA6 +z+Y^7#)?o0>ZWC>}G@03UkSlU$|4FKAtCxlbsRN_gO#91%BU +zsUuN&jO2@@xPdLT1}L@*YN5AFk1l?;=%u|{aNHM;ah7N`1j#+*a(nWZEh?>#+R)OY +zxy4gE4=dCJtf{)>B!wJUVX&tMP_z8N$m4J5qoUjdHz|(UL|+!~XaL}h*F?&zs;AfF +zwHe7}tzR&MRjcF+Tu`t0y<&M6gyW$#0ve}3rHP}R5)bh8(v97e3a(@gGD3>eWLXA8 +zEf!q}gNr9Wqx?06-(sD~(j*y{`5}B*)pGu;(rY~OO04oZ49q730y=T9X7sGh27Q1? +z!&LN=Vvu!jl~kyCKDM8r35cZZ4B}j4@}ZQA +zQ87Q_p|mS&)6_+3j?6VvvP_8`l$HpDyh?~aw-mE9$YwGVE3xLbRJJmbqiR{7Vvngq +zrpO0V{V4GnFE35N?Jv9SW91;;Y(ZyYUIowuy_4pjI#=Q#i+u9qK!#$r^-yQ$RCZNa +z)fkg(h#(h`fxI$;jRDhPqD=CfEOv33+ +zu1hyB_M)(FI7be(B+K^bI72W>^E(NsI9U920tU)luhFSQGB`*YKy +z0HwIl>6tq6>jIs|l5DKU1d{@~&YvAP{yz?hTWyR*ujw-vQq>qcbLchH3Nbsps7rN3 +zNiBg=;+$mrqY!`Vlf9|zVFQ3a)op0mORj2-z{8MIYp$FlTNe~1?YUaMWCigHBRb(E +z-+3LezSV6t?ZjpQS`_xb>bCN~>bBuckt58-a$DNJ +z>NYEfz`yGD{hEK>pa}mSFqxD3Sa=kjd3vE#jj}Ve=}K4K@AiU71w}`Ub)8hXVu>+qb%{?#%P8Zhwg=tkz`x +zRk!h|8~#qi8P0jwQ+p7YfFy;|Br{wH-HUMQB +z*7B9eqVnEUR4NY8ZW()1GqkD=UT7d5F`-~%+74ZSi#6~q$fdRWD`&4D6_vro6mh|i +zf`LS?5&a*jBvi}rj+FBpSqAgUntCr{flUJjFHw2G{B7iyIxe(XxDSiQ?16#_kVa6g +zfgh653GRR>hE`OtbKXKNZl6{2F84?QGzd$H`#B7+dw|9jF4I>u*f&qBmu(5b5(3od +z0_$G>3vQOBNXc>Z0C)6L^MbiYjwrUg4Zgb=7zmfs8ua3vEJ#}!$;Oos#c5ldtmE@h +zfJE*A+7xTgv>^ecgm+9;Z=QAW;4Fol7r{UGXg`&$M#v@0s-CN+m@t}Qd?YygbI@cx +zeawL*OXvN9xgBMccFUxkpdUxKFilf{J1*IOK$235@p_;H*;9OB26F*+4 +zf2?N +z=;DU_GMOpu7gR#9@>0m>&$n6nu7H~EF>C{HYmY7CmykgOK&L9N$Ebd_1-BG`hObU1 +z5tq#8m+nvMh;xF)L%v~?hsS+dMg^0b*)%1GB)!ugsogqew0@Pb$6Yg-jPIyn$Xc78 +zGyNWgN~vBY&0$Z3!m`*ua2ws}XhaAkb=`wP`1>rf$_I|BsSGRx2#7pt+&>$wPF0q` +z!g+CX0&em;|FqAQIna0{>k-J}D-q$xX-6+5R}lj4hzJb6zpqFU(u3~B=?mFmcNEL* +z&*x?^sTqcnw6g(M@E_O`{LPYXi$n|NK**gW4LheUM+NXg6hK4e_3R>Azb!zrk9uqL +zl6*{X(!N9?r6hT|KXdgKD%l3P6cbIC3-#`(&7s&=B$eIijf+Z`()s%miw)UGv +za^OK-dSZE&9@lhQ(jXYzW1?aAV5+BjodVD)Q@(!kk5kya3p#zTr?E;t?CR|lzyoN7 +z$37>6-zTr6yi!qP(L_;|UmNP4GfK%>ZD1HqFqrZ0GkbUu~E|k8_Db+!mvGN#J;4C5`0i+q5eHQicNP +zh(b%Qh)?`XWitwo8O&oisKi#lX%9w&8cZ3KVSSqAU_TH?9(eGlD?)Cv*coz4yqz$@ +zMDhD0@IuB-GC>(G@7r{Q*)A+XCeEX@^D|2`CCOXurg?=L(0gln{MOAL)1fZvI4$J^ +zl#NCElS2%dFUjZ6rk37F2Mno4WaVI +zv-^S8lCkX(7NryjHf)#G?@T>g%JeRi$(hSu!>BGba_~!??olQCB-*?TW}wouTzpm- +z4R9s;6CXiTVlx;es0COu{49>)xWlFsg2zD5Q>8J$6ge#T$jx`9CTS-ybWh(KT=nD2>ikRMLVsD^E* +z`;F2Ik)}&67Sf1saY&K~bfLz`aWsHFE2_?}-=CPqoT(e-z%nAc!U-w$N-E+9;R|~0 +zwAaJN#mti_cs}JGq+^eJ0dza)K}=Ke?_Pkm4+P6XmLbi||7epj?m7fZ?7 +zG~O6#E;U15Zxd0Dsw;}N`--iHmU?Du8?0xqQ97mfx5RdV2V-xJxw8CS|I-j+OSfQ5 +zGxyTVjX)-uDUBL_-T@< +za5rxiNO$Ta4~nF@rhLG&G}lI5S~BabjOr{6My`?(Us0C9O}8uk$IJ?z2#qi*9O4368C$MtoJe5>2c_an1eb(uFi7#91Ypel?HNamXF +zVn+(dUz48L#z7D+5!Ou1l#wK~b1{J}^SgJsn3DOygGpAc=}nZ+6KfO| +zTh-psKd!H^fAK+V4%KcmzhZLhkONV_c!*P5D>eFIy17hWVpFL(SO0)XYp<)zLepo~ +z{YjNp@rM$^W0z+;#F!c|FGZsIVu0>Y7p3C2bwUO?)1&NIhWNEXN!U%1o}y#IbU24C +zos#r#cG!)Dx|U|;dv2b#4|vr32Qlyl_hy;GTmm}W$7T);P>U`)m_ +z)8^C?mXBwoZjAvP>plo{GKljeh(DAMP`RNh{qUn_vnnut!DyIq)oDL0ei+l+73K%^ +z*gn}EU@DTVL)%rLkSBR}6z&a2%C*$0F@aV1rkv+L)#ION?diKEMzNd#1V2aBp{-_~ +z9Ri{;TuL5uAPdX2P<*dh3idE(+o{+iGm5VPo62+cZgI+qP||v2EM7ZS#BEwe~*ee7|B|*L=pfM?tHr +z#A`jsZ~AGeq8%Tz9vMaUSUcK^Wu~GPq(Rt&AyroU`t_V%XzU#m(-A6Ca^pnf800c! +zFZnzEB_*r$S7Y8`l_nRF)yK@z4WFpw5}&+w4obb@op}r@NZ+XX4`T_<;*reIQhKVR +zaanjC#ZnxOFu_JG^Ie1E0=8y|qdeEc+ND`n{6X`O2~Efg@kQm{HJ|a&ZfjJ~+&Unn +z%tZO2ZqHcb@UTAiS?G*V5QE+b$U7VOrkYVHyF~0?LOR6Ecw76Z#1M(HWQcK-LJj1Q +zB+F^&Z~VaJgTg0j`(J`WS*2ALLtjs|<)Ow`ETwuGcZwVAjB868)bSJGmX%Q4!-}+? +z)pOU*0tK)k3B?tIe6P(*V7ZiIMG3sM#C7eT6@MZYTbQI<0m`Q1a1dP?1E_AVJh +z(xdYC_!)Cc;rxbrM0*%l`@)iit@ARR9ttx$yr49#g(lAG0GX=x#;mpVi{7Zg!l1zP +zl^plw-0|WOw)Wc&I_k_2Wik>95fH0Rj2+*LsWvEn+d1Cz>RB=nEp13=m~TCba6to6 +zZ>spiAy~t4FH|x7jn*XU@{02HdA!@VTcMYeYs4DuRET_s +z*09Qen1szW7wOLKl44gRoY=fc|F7m5+?urKEQt;aKHn8RZc9+$XTNzlF5_s{`HbUv +ziPA_)qO#=^{KInb0>NFJo|BNr)^7$YWFW)3k=~+Gzv2{*FDqxovNDdd21(Fv<0w{ctr-V> +z$pB9-`~m=WrL%O4A7c`Gkb9`_)jJs;BzEkK(T)Uze_ +zh5Rh7n=HZzN1RdoC<8vM6Rrd=g`oU`09+7KgK$#W|&sVL>)jMm6i^sf`J(~ +z_Z-~(x%+D8RWm>~BHE7hAR(Q#pbUHl?&`7OA^I){#o7C5Lnvha8ZjyFfY3T1aOaLx#B77C+w9 +zeV)6N2p!otJUw!L9r1(N2&t9q9UEkS*NN~oolL)J?r653rE^58CAgW|p)Scv2r9xC +zi0|AXwN+-X%y1<~sXL=QN!4uMQwH~faK_;$OlXIg6V@8dEws@|j)_n~0Ot0GdAfJL +z*2~y5<%8}CB2xMa$5B?##TT)$b{5#SeVy^g#{0taRf{Zd{nge!kGTB>IL@-*C3?g +zjTrQ6(cVtwVRwdR+leCf*3gD7-SNCJQNAfIC}_tQDCJsC9>2Pq**()30))f~DVVM= +za*w`7i18&E@C{KPG4J;61FZz+y +zWX7RHS+N`^w!(N^_&KK-g#t^#ZE4#UyE=r-xvo8QjT6YEiemfvX71K0Q^+aiGf5Jx +z6QL<9JWKV(3h9x_wh_zT=fiO{GZ#DBuZi9oJ-6XEA_3T?5f0-haO$e9$=8wj_Lq~q +z5DclAD-rP7ST|1&-W{*O?fkk0vA5^2uwJV7h9OVvpGw+(!tnk6v5mQ;l_V+QynzE? +zh<>QY!w{Gx`@32A6c!9Fei((D@MEK@rcSHWBlLZ^Fzrno6V0P8ZBAyI90g#(t3H3u7{VhDlSV%7?x0yoLPse`>BCyNj!-cP%S@;Eu4!11W4 +z6B|j)x~&>9P<2*|b9Owg4&FaIa$n(di(#bUsTsE}K5@HEjTbhDst`-Ka9%Y?XIp|p +z0^6!%H~=rXziL-4ZnjEZ44EJdlyB1e?}<4m-|?m*`6!Y^<5N|e^lVFZESRSkUFCyDd@Isz4>NTrE3-wmMPl_+-6dsu +znKiy%c{XUGg3m6JKxlLxI|(4!g55k~-*3pO>`6cF1(|)<^_c}n_qr{OO;nN4_ZfAr +zI1?VCkU$XKoN~*%#1bG|JApf8&m;-Izqh@C(NUb$-*XgOG54WQNdGp#KW4-v)mazX +zGIQB!u)sq5sLXmI(0rf}EDIf-F$~;&1e|N_bt}l5OGj9}C8nGUi372dHO#X0?&c!T +z%t_G=RX3ociZMc5WOJs^f&?^9f*uyVt9$M4XhH3)xwwU&EIXR8woHU{E4zpoxB6wp +zUECyW>Z31^VbK8jV71kMILnex>@T_Zj=h +zgZqjnDsyX^dWtYVA{0St*D)0Mh(f|Mzs^L`S?fZw_obp`Dy3CwETi+UR7<;cYQ}{t +z+bf?~)4uou>22iwWZ%HL`aVmc!ONrUPXUhrg=3?7O#X|{@<_*w>BGZUvhZ5nN)BDa +z-8tFj_u^zXK+?a(Dtj#$iQp%>{Eu#?Q!zo`u2&Y@M!t~wh)Emv;1Y`^^1?+m+AWfl +zY{wi9NlDGy(#O1+d8x*a%F7qR1~ID#^DL59=8;K~Mb8{|E6qVWh-EKc2!g&@@T7Z$ +zSK)74>pL{0qBUr(bl~@UrTP)51z($_?AfDQ!oEWiT)p%@JYR1f +zpI>f<(i)=*b(W@H2hXVnuL-<1*EW{kRQhAyL1Pi1o{OBs!^*}!IxJz}rp}&`V&GQ= +z8b`FKN;ccG&moD|h!-s(#hHEL!rQm7*GahUm`PT3xe4h|mx|O)s+!n8d-81Kd#EZ$ +z5pOp&8^O~%Fp6pDeC?hzemkxA&e_o5wPw8Pgn}%o7<~&FFk&I1Z|ykT*CW +zl2DzuoLwoik4GPbJK$N`PK~D;>`z@j+z&*^8{!>+htP_kITYR5K04d)<>?8Uz*+`c +zn7)frmb|6BXTD2Qqa7l1=lJ09;`7`NuSD$U#hHw-^!U~{`7UDCNVHvIgYIvkW_C2k +z|9*-5=~!~ZGB8pit))r|Oh4blU^CZFiW9rK>JwXjBt39+h202^y+|fo?XI%vcyWf; +zSYXwNnXiw;9Y82DHGAb8({e^==pfE(8h~$%GX!=1pfK`NhvEM@ZnaLSG#?c)!FKVnaLyx=15U5rQhnN%Yw!ef2yxiN5D^^dx}i1tU_UfcPj +zZu|UEx1#{+_B^_{L(%A(=zj5Eb(?u%;z{IzTBVde}bHaFgdT%TiFmo-$QtXED3jx)&nL*Bv5bkBZU@AM31< +z&axA>{G+bYLKWL0GWRE#^DvjO!|wiIEg1j^w>$YiHh>5!%xXD46jBz$0P +z$X*3vr&#nX=o44jq#{L694h3zU$jMJoRk#k68aB{La96#liPZfub?z?fOyU{sII@5 +z=r*#@L}Sl%^LKl_$@zG|uZa_X+0j7~4%TDr0gMmUw|m2jptHlNmY->Vd%a?xw_EvU +zzMMW{W|Z7?yUG~MP`fm6Z=whjVl#E*-fIwWBYsX&tVE$#hruT@IET=fZ#3Ok#Kii3 +z?XvO|I$PMrHY7EZb*c5yxQEMN6}Od+06eR-I$ESUcz&9eT@&m<4fb( +zGEs{FM|PngbUmrIEK*_>V57?u2tc=WWrb|uTr=S%vhlvLk^rhPvJyNsBP`xZ2s=5fFCinOR5a +zKQo}bdlgfkF-wN`LI`_5-QX?TpIJS9eYz%ikMpCw+#&UP-t^?WI>m--a25-iiDC{} +zcr?FF`h3@`B>}`OCyNwhM&7YV&vjStzl5!ynDNlMd{(*{Rj$xJx6FX^vNH=ko;P|f +zcu6KZ7N=#kXg=~Dz}liUeTdj5Wxd#+ya#opX65Lxz2?7OoFVWwzj&t2n0vW5@(mDh +zYE{jRGg$Qq_+57`P5kIiQIhqVl +zlnl+#V^#Cm&QMaDw%U)DKj`+qFwi!+~1MsHTheGUKyukt*IKLCm>{)a@-wy6T7zXwMaVL*iel +z4?X&r3X82)t$I5~_jaD_$2Ri0^mQ_Y3xcNt)z=K{^KAQ>gM;sPqini`7bL_TRGTb% +zlk%gNp>EEW4j>DXv^icbE^%i`1fl3Y5$9Ny_2myh38cD@mO%24d8O~ed1dm_mvSC+Onvs@Yvz8t3@;iG77Ai$|w +ze?{w>^&Sk^+)qE!R;gJRkd|Mf5hNyqeq8SQ@mzB{;Qq(legc@=Te|>r`{`!+3Ul5_ +zyFTKkI#2$uxvlUdBi77P4k=D`hJ{xPF(h&E^T!(Sd+0nY7{%PsiKxFa5kRjkxiT>>P?VGPRU9oG%Hyf?wwh1883s}T0se#H6BlJX`_8rO?)h6 +z*WZfUSF5xwY=lvN*@{-^lVJDUMx>58jT^rLf#XZ$a4;vLx3NAq|Ll}iJWz!n<-^2gk^a?$8WY=8J;Zl|+~A$|Rhot*`w4zjHQGrBKU{N(1Ga8b1$Z>KV +zH?7_eRI&zHNtg`JtHh!kzu1i24Hdy`Gb(2!w8QV6pi}(d2bP!mY8067c}$j3c#(yW +z4|{0k>xjw{BU!!IFLrirz3JYi)e>xYjmUPUCl=S3!MsHXg_=$Ew8!6b&!5^Gj7>i3 +zdhN1vcG%aDEWMDoMe%S$y&*LypN!l&LqSAxZ3OnT-9BvV*v7x+plWOFE^g%YS2}`C +zJ7(s5UY|rS0XOT|Km?a(U9*GsiWRi9CGi>9t!{X#d0Fc}KaNI-2W<|-x +zmE9=+klR4x1YUIsSC0g%&-~n@1iXXI0CKxIZ?lrjndA?-ea=zvhujuyrUj7OMVsS0 +zPo4mB+eU`MJTq;Tw_~H(*5|<+=!d5iPl^ew46m1`?e}qZrU0uf?-cv!hXt{@ibGH4 +zkBVF%SeOpyVp}XRrfz?~c^RZ4ph#6haX-_TOnv5S+kKXEi8ap`8+SA};-8ocG+qP;^=j`EUDg#@xT5RfT +zwffFh%)JK(W`z6YZy(~U!F75jyiD-d-=}h;xsiibomG0r9sR@aW1IIKrZXO&PgPDN +zQnOwkDuo!?9h^IpooB0jzdSR*lb6$2PF6lLI_@^V1!G=rcmF0G;$w{ix|88{pH69# +zB0PSy;eJ~w-1yu+nQcE6y++>EI#)P?<%wrPiR_7%A$t8?V}aNeY3 +znNKZ*_Vd~ug5ezS!>oX-yLadm>d~+BMQKS?v9ZQ8QctFv)E{Sa8mkZsMEJ|zB#uXw +zk~J6CFx9BqD1*R63&c0nCxiZUPuk9(D7`oWrG=H`SQTGc@H}}L2=KR~ZYpFg61@Un +zA1r-ECq_*wW9EKlbGS6iwY}|AbO{K)(iiGI-U>8X7*Pcd?$5n|C+Z!7?5(_BuiCe@ +z2Pr9T9|O#7M1Z-?p-&CQw={|$jI_%cLE!}}y$|_8qyVa07hpHFNW++%W?3`lC$9b0 +z1&mI9smdoDwT<9I?TJQMN%z4T5!=?zU=#%Xzs>EaM+UvbUNHa2UZ77m=P8v9&KeTw +z*2l7kN0s=z_U>8>^&gK +zJL9pxY@!zzCKl=qufD%k`3Wan8`O^dc6)LkMbR(RafRleF&*(4N6`Y1+jBc?rYT?k +zA-DGo4)pju_iX-<+sj0VpLHQBf~mzlrgov(vMkVoZ*TOCtZdysuw{s$W~XBx(Z3P# +z5;1$0y=rtc4(7yrH=j2-6iyN_$) +z*GLNG3`gJGOgZh;hvVf&_79q8qhe{u{xKX*j_er?v9!6XnT_-ESBl2G?J +zrSEoQbeGaRPu|I)q^YA@NEVa?7ZGYikG;J0Ti7XGO;|dwWk-*z=-=woMw7*}%aVu? +zew$e`wFxHU*n0yB9K@&zn%T*%b7wL?X0X%sT}oJ|gd6E!m;7vE>8uv-o*FZDB +znJdBT1@KS@Za1EhmaLLJEf|{M-3{sp2^?6CWjO|ifNF_+c%RN&89VleK2yu +zGtC5+<}Ni~G%amUrQR5ogMD$YeOvvY%*<0Qkc7hIH6nE)W0Zxm44N$xN?C6~uQHa} +z6pCQbh8N4ab_J4v^n`la0}6`q%C()&60_jp=xmsfS9OO*m7&%98z=O}YN{YBdQj!u$Yj_SYad +zA=y+!;Q|8&AHyYmOs^;3Uvm58pj7Q{acWqR9#LZ=?L*KVo>IL5iDUnVF}x;obk-q) +z;cDD$hzvyrF)S2KfzJG;zp1zm(D&{Hz8nY8n3LX{)+dAuq4fxqJ30#8e5ovx$`a+4 +zx?yD=LN&SDu^c;X#VS+Mh<0LS3w*yAN=GUe9<>Rb+#6ae*Kp35VhX*opZ@Y=uOU-e +z#prH@q&+}sKJQ~cWj#Ms-b?Govu6(R#0o{`K)(%>ccIxN#Sw8{TvH*Q$KCqD*`#PW +zVq}7Bt^16P>dC5z1mBb1%$nlufxBUtZZBrdPW+Y>!|?V#6enx7FHWo#{a)PrMEJ-H +zWF!FT)k(LzTJ>>tNk$|JU)>nN&Nq^Yd$?8#*_hbm-i%~lHwGEHDOs9HMS1H7qkOiq +zmoX~^G<**B7_st1TpdE7kH2WeQE5ecrECo+CK!C~BhZhv3DM6?$c;=O(Ez!opXE=m +zpWe93snFS8&GgN8q1DKp0FB8dRt@hkVFBGbJCZr#$1_ErpfRNy3&l276%eJ#NaMO( +zB7wTr>dxyjcH#EYYxni_LVmOc*uL^+ZVaoP!KXjBivH{CWn7{>{XX)&&w@ +zb-S-6M&vN1`5r5Y8EEJ*>7WC%lyuh-3bScC*q~WA%A=qkXLmF9uD!LBgXDuFWKsLp +z;g|n0x0C;x+mTBM9K;B$pZvezm9U#ejSVmc_1!<8H@$98LzijL0}??S>h+r8<-l=4w$4`kjWgA{MMZ2f(JMp +zrt5%PZ2kCbncA_zP3rH3H5t2a_C`e1x)0u(gQ;}|mbaOsoEta{!QT`m% +z$QJAt{077g)CIivECxGSfmn14<%HmG@D;xvkMm1z#{66CeJRV>qiNeIJ0B;K!p*&o +zg;+!6x(;yvD4oB6TZe(|JEO)3GAm$zdIjY8mVboE>iv4R2!L+?{0H5}{)=umaZDNO +z7FzKj0nqKnS70Upx}BR0K)3I^Dgo#=uiRE*Vqfj|G|5eRnt +zazGqaqwwucXX~|OUkx`JBQlY!lNzW{6>*%7Z08c{jY13^t`E7eL#>}2t;qtujra;)~;_uBd +z@K6i{D0B4{hc|12iqSaMvM>l5n<2XJJ;dIrf%(lpgyDtLtS?g#R=t?-H*#360crY0 +zn~TOHXh(u>a5~cK=-!PuD=E~e0=j(9Nsq=W;Yf9MuG(+l`t`)}a0Pt_8#)%}Hl?() +zF#aYA97sZT3jq%!J_1vm;T83!vmS6ipfbU^@N(zu&)J__#D+M#YsfCF*|5V_q~t%- +zzuaJ?N`AP!RDp|O`Wr9qpwM*m{uNJxwu-AzDC +zm_X(CIpf+&7T3d=Y{zfh4de{>#BuCAVPg^!t4jN$ZX=pYlO+<7&d5-E7#iG4QiZP0 +zKL8ct*f~g<`$Q=g7DotCj~TLXL_eIIUce2GMgiqPE`ySLZd{qdJM7%;j8PgQ4bqrm +zgnIao$uvR?hEup?;}te=C*)PYr^LuLYsNXJ8s3&`;lIefqS>YmLpY{J?%X^jv!ZS% +z)$LjuO(bryFq};Ddo3JZ-HR2D9S^Q|1qnDf7*_AyCiVsGVE_psn>gk#gT7|K%&+1* +zQ?fWP=uNFf+l?C>8aThBj!}sYNlpFsx&T9SXzTnM|Ad>6zKTcIm_FCo#m@BDuOvzMIIr9zg)eJ8Op84kT{r^I@ +zsYm~!+hJxxPImxwTaN-M`(hY?ZZm9tOfoF%{RiEaZm(lUF9)F8n%p|NmFbjQsgl3Z +zwEm#m7QOd_>w;*KNgSWDDb^p(RDDBOyzUx9Ke4LI=hX8L1Tf!z+|k)`hHSGV2FB)i +zDE|np588)SbSHg<&&oLUuLW#q&!akfybw)1S+i* +z=d<53d@B2*P^7(xURGpQ1amnWZ!2m`C!t$Rp2#VR^;=bk!X6WrZ3bm#G!s(r+@)*#0)ymJ{bmxXp`+P^NIGnGpW*54!FA +z7u`k%`Gao%68_)l_8IH{pxauixi{X>;a;uIenQ;Y5h71nh4gSHhySA62~vO1?cV@& +zyBdIQBm5WLwwnQdL1n@!Am$2EP{@;bWqQ~brVNMpe8cw>7JyA&&I6#^mn|fJ&}}XO +z_b4#eUm?~<-8To-oUV?vy}#7H&gg~)TqON!>;5LAQUgG@=djWTc-_UZ-g?Me%Srx0 +zw;vVL&C&trb~6`0Z0u#>OXktcUv#_iJ-C8CJ|BwE&-C_K|HB!8Zj(d#)^CgdLAOZ& +z=yqJ2nJx4Ghi*&!gKj%Fr>|Nvjg0<(=(bHJ0Nv(5O|trnZlnJP-Ol<4-EIY-+tUDa +z8zQTd45T9ESFzaKzvwn50Ns|XnPjTJW>`~3`-^VB^!`P+Z&kj_P{EqcxbukpR_L#S +zgoMN~vu1IIapp(2oh1x#_b(0-p!v9g_1I{!lyo_OIa}}gi*AFH{fllB&?k!c{s-M2 +zQU;*gvVYL+-9PAd4glT0`HOA?|3$ac6!}2CI%69F=r$PIT`s-2j>bKvam@L? +zFe-}XX|&c(O|t_J0NsxK2i;yf>P@0iCzPwI2B6!>VgI1p=#g~*bo-pr?>iAa3&CmA +z9?*t36#h;V`6_x%V8xk<;!dM-z!e@hvPLZpjmep7l$x*9otPcDF&oQB!?YMG%dWR) +zOn(VKGlw5IIdNDgKP}Kjn4!K~%Y79oOTdL=F0pI8LKI1hwn*bTqvT(7JHixzZm<1j +z0h3llh}I#$VVCGcaRQ**@c*LQ0l^AZrDTypEtn@471M}|wdMeHJ2SdLDk{|Whc|j_ +zAI{OFROGUUuOUt}(~JJWZu03-PjNB^GVU_=#AFuAT`#YNDe{#_Lj@b*(wv*ksZkT8!@@^V^! +zz-p!(!dK7it=jrD=U&Yo5S$BuvXOgb=M}Rnot*LQHj(rl#m|V7;c+sFT +zA=6r=kVV^5I+}CfZ!FK0p8MNZhU|__EURL(hvb15;BH~l9r?Zd7v22r?6_AJ60Uo( +z2AERhm|Q&cNGyfzEGbhq7X@JhrA5D22gCW8#XC5Abs5zi^thG0g&^gn-`fw@kh{eqyVbSGtYKv*ejZl +z-%e|TvHX(O`LY72O0XLsa^)BHO +zlck!(kVu_Q_d_MG#c?HlL8SWwaNFtq190=C_7NPRTrjgqj9g50tyH1khiLbW8&`q{ +z#=6CCiIfz<+efc{QpO9|{k-{lzY%^!i)@4_I9QeGD8WDTW)^wCd +zQuF&Vv9gpH133SsjPwGmsb*F#^)KRYG*u|vsPT7rLjqQ+@*p6@rR<|M+l)5!vo`!r +zDK;xgHAb75>w^zD{Xeug!!wOEW1m32Su9e-2U8p;#SQ;+*HN#@F#l*;k=pklr8fjQV{rG)yCa6$_FxVz6=gWY<~fFoU?!HFY`NK@@4 +zmv}`gp__(7LK;tw0wD%gVar}F@Hmb#OU*zkLR!sds6NQK@y7|zM&dqo7k4lG9)!M8 +zU0kzZKxlF90CrvUz3$}{w1W9ZWhZoO^eRx&NzB7q&=YNhFO@;XJ_zC&ttUBf2YwuJ +zYf>G>mtTc)Zf5<%1;2+{&d%`=yR35LhxHZYASA92qH#(~%~~UeFRE)OsfzXqa-K8h +z4}l6GbaX(b>`o40$z0U2h3vwkVNsWkjmDBidd^65ZBOfyrn1eC0QJI93B +z|9P>-qS4oIX)OsM-mq!|7Hj0y#M|r1T)1`iN8dgLcZa+}_*dWF$0>6K=-bGZ7Wf!* +zI=G~U|IxQ~5_$4VWF~~=jwXPty5V6gVIix>!op(Wn?wX#sed_84Af+T90S=eoeAy{ +z90OM7t$i|w0}ufE_MJI9qDA9|_S)u`6w(xofB|xG5^BYKeF#*@SGkeJlE6 +z156?ZXPZ;V!2Z519p@f8C_a8XNh}aB_{0h2%SH_=NGQSMQr9etc1lM +z6%jx&h098YxM|2Z@9x<}u#CO3$Hv77G!ckV?y}if%T{8{%vqzx$5$^{fk{pjavLm( +zQz=LZN9Mp>B@}H-gT{kF092-c3p4#hvU8hskdS2{8WRy0;*(~hi+K5*PJ@pCgX+lh +z*d+DC>?>2SZK>ULpI8Hqf`jyjG@kBBUxHe!PoX*bl2s`??-HB +zngD)#nDyzW@=F~oWkAdA%Uihlq3B64wsJQ@yT+FLB4f7n~L +zVZ-LVD8yOrmR-e(I +zP|VR0S*@!XGQnjmap{cROys0ua;MJn%Nt4VneskjfNDCY#>4}O2k_e_Du4Lxu;1%_7~!w+Od~|d +zdT#h?|MJ@sP8{F)+Qd&wKU1 +zIscH^-Dz}^Pt(f_p#|{UG25$54+dU;_-%pp8QSZ`9KR~ij=%giL6N}6a6xx4N*0iK +zrVZuIa=r8svSTP{%IEk_4TtIl994UWxzGTViMA8mdHS(nB+9|bqjHC7A6iw#5hR}P +zutny=(xn}qcCFA_a-d|xG>0$@6EGVe1I-JudSJY2#DeLHu}R?amY$T2r3Mfx=tjW| +zy6g?&BX;o+LUU;6VTk#p2b--bU^O&BHyARIkSF81;8NFRI! +zgO-#Y{@Uk@Mx3YZXZ!^rm&9I$VIq<~*|GFnN#r|+T^I|u;S +zN>WI^fI49Q>CNdkGLx~6(b}Q+hu@Y{u(bIC;J3Fq|M1&ZfBEfxdma$dKm0ZcfZsm* +zhu@y5n4k9Y-E3=FOPPh@0{(8?8K)CTzGa&0YsfdzT-K2tXlH*~X;RgkcCh>18!Dha +zRID`CSlm*-GTKopUS0L+l;uL=5od`Kp`#qRoMQ9Ly3EBGK{*uNKQU648>J4PvzRZY +zuD!Jda~aHrM8F`G8_R&MX{#wx-nCwy1Uy80rm%F<#*Al6491~zCPOUrLPD}A^{lY{ +zSA7Q?!q!?XK){G7L2^%~+jIZ^S$I-7$ky_bafp@Q5Z}-6grt(TaZgPFA +z741g0z9bn7qh;f4Q8ozU1LdbK3!|A=k|#)-3?%Y5<|Q02`<2a2E&22%DsP{Lo&d-m +z_tB2`vfT@@#9q<~ALk@EBVdtCaQ)b`FggyUkkF84#~|)@2>A+L5`mGz-d!#fzDQgj +z5YFvNBt67?r{fkT7&|=MgOi(qagH-N?~S_W +zT)yjpO_5skd-XTsHiY}bTB*5J1~mBYd4z2j$ojlX^f&V2JBUiCq#aU|r+kT!d!S6K +zE0MMoO7MQRZX~RC_>BjSBcFyN1a;^;6g9V}ys4Igqianmg;(04$EjTQxpISOgc6|k +zv-p7zO;BD^s0v&-n8Emx+lQ+@AyRVzt8*40HVRz2D#X7EAgsa!IjSa_rfJ}kNfK)_ +zY{l)jdH9u-Z=tH=J;o|@r1M05GuteZ*}f*~4RFKN*nIOAiKRwoj7q)oBG^^pPPdr| +zht={MY2D3dELP>ucV!`#N1_|G3e^_i#m1F#a0qQ<1>ZmYWm23-3nWTcJ^Td>BDlSD +zyg*7_sBsrfh~FWKA$1be99IW7o6EpJB*-+fu-34f(Y2+QTrND@+8f%=vusYz;4XVK +zh3f?GBm(h^jE`iaXs8%J^by7c6}XMH`1l+dTtxrJfzRgt*z*B9-VLZAH5x`2r +z=b0SIzM+OG#omr{$zwktMIWDo6)z;1tm1~ok{EH$BTZeboy;(tW@!*4t1 +z`#FQ={SUw0{fFPqooN;T@Y_j6cEA4c+cBb6S@A+M4YG~dM#)Yr(&eoixzU-3LS(A} +zoz^~wFS8Mh9`?!6|FWd)2`VO#Zj)qQ=-CtNBI|jdi@hg=B`?&EX`+q_@V;=5U +ztco;*3JS805O#ns5b!JTk=5uxPMpvj)BlIx-be)S+gxZrD(=r-dD1@dIiP|!?P2G7 +zk%fwT$)!muD7$<>MkwfR0sMC8AAb8r`~Ty&p?q^%hu5f%%mDoMCRskVCBEolO|rf1>4r8o`|ajwdH1h7^G;J@0wB?ywHUg8b=@$Rqy!#OK6Z%_SdD*G*` +zyW*)n#+dCK)Dw0XO#;M{NPrBr=p?I8Wv=AhdhW;3GG3}-?|+pZVP(Tzc)lwS^c1=m=5*tPlTcjD0R9nU(}ZaNuvr`WTh|` +z$ePg177nGsaN`Q?;c(7{Nc%n6F-e_qpUj6C>q8&XDtU%ahOjzFZ?Zuh4^o4^Zn}M* +zM8$N!h#7Pb||p0aQX_`m!%3$?dKKuGg2+d)xV0DpThpyO>MR_V-bK|oe~J#C-!2EcF6 +z{1l2~f~1>Fm}jiz7gL^;^#{%*j^ANgp^^h@L+v6_AGq@07$OO&9bOqNT&nlmQmplc +zwEvgiHq4y?CXf;T!*5Sxt56hdN!%C0?fN<;tU(oSuZ;>t?Z8-?i(6w83T#y+#pn4BkDbA1^@P?15RR(h9Vm +zJ#DTnrp&RVkh=K#CB1~4jShHE!0q7ELF@x<%tKeO4xi}so<$#jTmZoVaR(_%$KMH3C`K`fB5a?Km4|51%Tg9 +z{)gX=z;R-nM7Y-ZFTYKlsP>27mIm)}!WX``@N1zzlk<6>TbBpOZ{U@D6n>oSs@~Sp`m&p(d_oMGNn2ALJGtAF +zYQ>EsGza&b&j0e;+W+OZga7i|+)zgRejXe~Fg`XI8q%~eOXhPcJK-Y{Dqv7{_GGSn +z-i?ux|MJ`PPVz$k@Y_v_#Q=Vr;SawZ=~u=x=*(KpAF{;hTffMO5=yN$)Mr8guIUV# +zA6v;dGBp%1W|a3v^PhUZ0-Di`AaAa$;i2IWn +zoM#u(np%R8P-A@TA;2SCbSc#=^U8H+cY$6?QCcJ?C5R%XZPv4l=wz+@uK<2q2EcFs{>yJ4Rz`WPT0GcH +z0{HE#Km2z7fBEf|yU%qMYeZjld)uj%x%qYPEr^L*jL3GufD+^m=yI23}+xNXjxp!1YG=KGNuH@AfD*XTI+oL6a^zA*x#ItFs +z-<2Ewwr$%<$F^-79ox3m9d|mmZQHi(ob;Sad#`=|Lw%^LYP|RJ6!JaEm5Lf5Z?H94 +zpcN})cw$!gftZ#rU(q;56G{ES)VT0GZOQ0d)OFcf%>6AoQV`1S0gbjyCV^DB3}<;< +zy#fA4uRIjWaA5VqK*}xA{_!|7iY!x9Tn-zK*8v8^+JJ5V4(omiv1J*dgC`4CnBnF~ +zGBnZ_@9sC4y>;~qLck>75lwg`s +zU3oAZ0EFDMW{Huw|5fW-I_fA?^0&Jl)Lcmt;;)B4>Mc4AglU_FJ!)bAhg(ljaC|!N{DB1zV@+eY8yh +zk#_~@69u)cqZW9?VfDkH@V*Ud2{2`R<^-8_;a+FjoeXFt4%|raNP4}MjK5+%JJ!62 +ze36vBE7_<@zSkY(5Bz6XV^Gagm^rh}P|6bk<#Ta`x&UWdC_4okYPnJ +zM(ru%pH@SXjT5hz#U{39lM~QakjV&I@y}s^K#=a-P#BWc0Eh?igO&dB2XcYHRD! +zsa>kdrt6~wWBF-YfPO`!gGqR4R-_2Nl6JqB&p-9$Kxm5Uz$$+L`ZRx(2;|v;T@5}; +zeqM$WE%y)&=l5T7pe6w_z~@!@!hXiH4F|ic#uKMRa9}%V$GCv&x=F+e3vTF5DXFX4 +ze`A3I-oX`S21{bdS%9fY=hQwglqtEeNmb`FU5GGQFFHkQoI#wj9>vSQSB1vcO6$~i +zn`M^NzK4m}mhqe^*{xg5VQjb-wM;HZRAw4V>PD>0X+b^q|&o@@4h^V>J8|Khi!ndb4o`0Y@~OfsLp_-*(<{PyNw{C3b^{PrlQ!r%OM +z@aaKRXsFkGJNB|~9^}00{Xh6^xBuX`U7#6WYxtr*H5KK6q0>hahl-q9_W=Iz+ZVG= +zKtZ4oQ1`5snWS6my`hQPLrh%;6@|r72o;Jbeppe&IpeesKk)bLK4`g58EEW}eQ?~# +zu)#P3F(0a%^(2z|`wq)kr7`**JD#z`y%c}#-Yu(eZOJEqf=ehz3ZtWk*WBYGTBc!`Pdq+PQeF7SOjR9LfAgY`d?4zp~x4ZV9&pOcDd;F9U^1v@s +z+`rq{ubVRYmPRuicSg$Clrfv@X8xn3*}BhMX7J}&HzyC#)bt)MV%CqRl!Fh9vfQZ~*){u!e$aHOlsq +zDqkJ4+QyjNZh7J5-qS&N`(@VB*`HcMs;I%W1$#epK@dJUJ;%g#@?WPdqyovJNVOGj +zPt%p|nzVT>_bH^=vU!n}t+yhkN2GWxze`x8A(5*64m*ky7>R|@vLG11rB|)VOD9b>!CD+Y-RHJ^0z0QDlxu- +zCHs{szpx`@p3C17x*oxWB&u=?50_-Q|Pc1&YC_jN-1dg&hk`NE8H$ +ztb*0S9}Oz^4Nq0W$qBSde5mXLt~{#mdfGR*dgA1FCYDngAYtFtr4(*q)$kq5H7MUJ +z%p(|5o*eTsBx`{mfVMvCE1=0XqC +zWR>$bWD;QNh{GiQkMNJBBWJ?0>}bhFN`Bd8=c39qul(J +z*4zEZ-}Xdi7W|GqrwBi#r1%cxC$g?JLofBDatsoIhZg2>zNwGCp$!`6ELKf$Ih-i4 +zbc&yt9ETFX9smP1)~9m<={3N`lKbUvyL>p7RzWmPctyx5h}nF5)6F +zk;4!gtbfzfjV&!vZ1`YE}LiF)Pzek=S@=Q{nEy8q%Kho(%GRQ%xpU; +z*LT1{2gT#cIgAZJ;6+!BzISaBDmKQdU-`Muvhf?LH+(n*@WJ`hqa!v~0;0VA#EHQH +zATqGJooZNn#gZTQF3=lTH-yE4tKoc)5_k~k<0a<-&~;6f +zLK@(ti+9=1#8~Qz?Eo4TtBz(E4n- +z$lVi!o$% +zN6{@O#*T}qLn6+-D2vF19jDyAr>mB#l0{eAeR;m^IRJqolsMD&AiE)Rs#}1kf%nhr4nSw8E}KWr-nIB+u3dF4%4h-f~8f@}(%8dQc3>W}A6! +zt)Xe*D)x)*7u7k&Yh!}ii(99SM@9=JcLh4+h*5+61f1EOc2ahVIJ^-u*_zO=SH@gT +z%bl1;xm8G5ovQ1164H#4ttfR&GDEpzPvCJ=jcU*m?pv)yJGXfhp&}Qn^^|RuV{(YJ +z5W+*!KrLCD7J!VFYLB1Iq0IJ0p!u!G9$*@WyW@`*5u@5 +zz^-=T)|eZpPIyM-I=31p6syE;@0gcy3bT~Zw@dZAA*9JJEVU_dwXjp6RLJI)Pc#@M +zJ=)M57LCIstCXu!yd*RDlG^W<*vr56`+?{ke@<|msK_skTqHWiWx)cIE7_|Qff1va +zv#FE*eC-;WtA5?VQgB1#C3ln}s#AF|867;wm=jIG`UMzyZ-&5W#fs%AlM^Q#d)frR +zRN)a>ILd^y#lPuR_;90N7QNLJROtGytiN9pnUvoPe3E|B`Mld;lUSq*=}?G5sEfia*^YhiqVw@Pw+tyLfJ>E^<0nf*ZUf%F}8*>bgjF=V&97~M +z$0x%+T8pz#8f7yhDA${jNe8}3P2Q#+77}(EMLF8 +z$TAA|>Q+{#+%2~S=rIq{NO9P4!HMGu8BD!*|2SC9_%P=;Y`|UG=#VFMdbbhGBSf&dpVL~E}k%()|xKq*#cx#<6C9_@TmeAcsmFJNc?Dg8pOQkh2839!2_Yg%M1LbBzBx7rMN_UcWh9KN-2Xt-UBOZ*-zl`sYQg?G=?#O@@ARbVaD4gI9n9vkwc?!4^%2g)?)oZd6V!7qGk;#J~(d>|g +z#G2a1y#aa>PdWm-)DW5DAX*nLMVidb84RrH=rs?wcn+aVJn=ioU@t6zN;zzVOAkbu +z+_#^Swt#XNL5G&HxmTKh{SpgKG;rT42oN#hLu20o|(fN)?#s +z{S2dIehRkO9idHjx~#I0iLhNa_$6}IRMgYv*|-Bu +z$=KF5%+(F&J;`^~0f-leBf*)_pkCg3u6a|LH&tI@8VoK>dOxH+2@SMPY@4i=G4sW?I`hscq +z^F2Lm1g@$Y9MZ1xgvwKkYl57!Y7Bz_O +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 +z!)H7Aied3k(B~d9T6u_ZD{SqLa +zmvZOCKQi{fk1xVf5a5Vo +zO~r=H*WhN^`Tb-VGyj!;JHcBA)#K%8j?iNEQ_R|omVbpk+UVkYBIG#NBAa(MiJbEb +zq^xy8W*nw%T;J%<9-`hDTcNj2?TEP($~WRJsSX0CSCc+h9NKL}P<_Mmo&NbBmHDJj +zislWAjU5%0eS!e?ETUwN7%C%m96gD@sK-b`N&}p~qv1Bd3uF*cQ~S_7z6X%}Dsj+# +zL-(890?DShft8NJuyxXoTC24IVnNR5BAOUOva$sBveW1muj#HQe!Dcr0(}*)eKyn2 +z_EqLOf%DDPxwNi5$2}xy6D({%I;xmhN1u}6s}`z+6d9yf+^FfFc4i*%URSE6>NSfQ +zAd{C_qC=8ll9zs}9Px$0=XURn8e=oEVnAHtkbw|CoK(nncG?(_y`OWWN9ZvE4l46f +zMsDsn+%+8pQ6D{qK^wyBif&g(K?F8f +zIht!_miLp=eHM}#ZKjTf4GeOluP)urC{2UIdwQ0TAr1@IroDO|kK!xD$)^hZ3+e`+hkNTsebbWZ#3x>0a@G*dE;0p;zE^*wA@Y3(pj)%su2>rBGA&o*;Xlo7 +z?oT50kr*?0Lz_Wv;gd#s#`8Y%jt(foYCE=~`|e2JXl%rNOewcJH#l~^h +z^2qzDz4uPr=yuEcz0)D|C-rfd^@Yy++7G3kI^p%Vx%rm+>ox*0|5H5@x93v1Vp;yX +z`8SyJnq~6!gj(*Wy^}?kvET34q3?_zQ_BI(wmu%na9B~;1Fovj8+G4XU@>Xcu-kVF +zuT^a|ZxWwOa@&LHwOFB>@a|0)*{~YyeS*;8cJ}YZ?j%|YaTL0H-{RXN)(Y2GkMs$f +zQrdW4L|F(A!cKfxHq<>BT)p6k8l70~msEcdZ1$WmMFQ*HIO>qkX1n*Ugg)4z_crn< +zR?$MI%gO@GPe6Yr!OI?wY;-VFm^P*9c|Dhjd98V^x@Atkj79UKSM#XlxOn!tT$=6o +z;o*RsI#D_co>ySP#mpd`Zsl$jpVN``6j{K-xFWh_d#%1B;g{#$x+UU+lb#5zX3c4u +z^HQ*V>=&&Rt=&E~<@ziSjLvzB^|9|~7VRQhKI=HZ$JS4DX@-;D(bL-{yx#~{2i$A& +ze13S2vy;Oc2N4w6l+s4sQjP@rUs-q>jpV?kbX61df8om?)SdMnZ_mY_yPeO*Z(L44 +z2ro84P;%7fb#*e_>Wtp6q#@uTY3;zls5vm9wmiCayDlfP%=MK27rO1U>eB1+Z*;r& +z54t`4g>HMR*G1oC%Tp{8(|tZryp6aB@p^Md2k$&ncUqz|`&Xe7BCCCIX>HrC1SQ$1fl;e)wDX);V +zW7-oOn@MYHnfY5A0plc~-D4X}yGNa!^4=}PmG>0LPcjp8U5gaNsoJ~j8Y;s@RFkdR +z^qXDY80ZZ&5^s-6j%L9%Zd6$oQ-#+KVFN66&eX|PkW-@Xfr_gFsrusCly1|9^z1J8 +z&#mNTj1`0VIkd|$qNpzfv8ZeMrnRje6L!645}x2R-{()&T@1C|ol;XC(l{)&!}ScbKLGly5{4l9no&~32)M7Ldh|0lW~^G|d;+PmX_ +zq1$I)=(g+#lK?+p6-ZAlN(wiAzU$JY%lb)u8y%dmo7Mh$>&~zTB87j%ELqGaoJw_J +zKBDy7`SUebNl`eF1|LA95N$j_<%WHeOm$#{Z=zKr#&kkwdJxk`LOB1`$Ijyi9Efr)x2rP{{^Zot0 +z4~0cGI$@Epub-VD1pc?Wooj~iz1i;MMcEI-J#KnVmQg`3khI9vs6y`tK*r{WIraAC +z=E8f7dkQ~KXz7=_-BKtwh|?CYSV{2P6~hS-^wqXVJ4H-*VfK>D!OQob>UM?|mhPo? +zvw)`nfZQK-+w-65c5zxyEV(`z?vM6+#QM>k%7IN46n(*NbaoZET?(=^`>Gbq9h9zV +zC=d$<+8JDHGTlm?!K80C{gC!Ug<+PT$sZRs@^Vp=;-ZQ5+|MLtRd{?*vH;*_l#&Xa +zozM9sG_jY$k5`2nHKu^yeOEENKhkd(`-Ld23p;hQZ;WayFpzg$xjI-tKd!|#TtN(U +z9m;q0o^L;OP?AXNz1{6^dlOIeEj(Hle4e+He;hQ7r*OC%d$*p|igq;i3&h8so2Fv0 +zO$NNr-_O>RoPRXxE&cY|+}ZQV*}Si}obi7BX!u***7&1tuk1|npRab>{86`u|5mp< +z?>5a4=r?);)gm)YW-g6dU+bgWKYQnkJr|>QhzA;13a8Nd8e9KT +zw}Jnt+e&!z}xP49c +zx4P}#tqkE)mAZ~dIADU~`hk``}$4qcbC3x%QO=_k;64GxN=&X);j`k +z2sTLBlY(Dc!_y*%_{{?=JT4i<-3ZBjcj)4i1kEDt#zw~(3^D?jF5OjUCb-W2FJkVV +zy4Qr(V{7Agj!%z*`lpUJHZdY6r +z{r;8x%c^^8^vVW2oN709p6U0+#VxIqU%KltDS*V_HH`JaQrWi09$KTsD2X-A?;0r# +zM>yusm+M`eub&m>iMTgcZkg(&KfNYZ7cuO@ +zg5S`z`kwbh`cb`+Ak>&CU=d5LiQ-lqyX!27G_)! +z59}0m+wpRwjGN6&xd~1j}Kha9zGv+Lu*QH2%lk#_ayT-R;W%a<^H|kpJawM}N87omu~M +zw~hbhZV&zKZoBK*;mdZ;cs_a;I>_P5*{)H4F$x{3)_uu-Uls-QLG0JHO%yiQ>zUG`eM9?7b~b +zg}5OJH|2hZ+yewyFd$1pqLhRK&M_YA6Vw_Wyh7MAf>@N>TbCnekx#P4d^#778DMmX +zu&CJuibFaQbvi|l^rf>)7$RJEg`@~@Np2}UL49{QHl{pmr8!jbCF}r0p|OIx2Xo?+_28fQC5 +z+?uTYW=ZrUQsxujfx~;B$Gg6Nae&bhlMoFk7^?7F6GaZ-cKDNc4eu7%E6p3lVH<8r +z{L6WC^e|%GhE4C{H^fA4kA4ST3mri46OLK)6kib2vKubSQZSH?&F{>Cz#CX66Rljm`ahXYZ^`Ygbe-=hSyH<67UA +zUBq!H)mJvc?@vpKs)1hsGGA6!P}9WgG#oq7kvLFa+a6&IQ9YpYlC8GAF-991)*0XJ +zDkRuHqcR6(KlaY=-({nV3`LhsJ9PrY$7?vj>n=qlyO%|hJc3beZY~dSx#FWKK48qt +z!!`4V0)^fOxB>tGk2}Pt#$HCy7vEDEkhsRWWpx?PJPplm2L*4S`kFM#0%q4~8TUX@2&x +zjXgLOxH3Bij%xO*Bu7nFx>I-4#?42giBP4qgrvjgi}1>jKdWizRT41JV>{^|cU$a_ +zyN$p5_;}S3x?j%Ry_Npo?lztsdT8nI+rQoIrtMOhf4SRwf4SSYf4SQ&ex?!py7?Fs +zfQ=tn@ShAXO*-J6fU=Q~=k-y4yW0SNyW1Q8A9p)(FuZzjQtz{G6W`rg<9ir;*M0AmtTrj}b> +z{a|U0G&Dlaw`~EKab5HkYHTpUQ--F6BAG|VG(vZ@Gy5>b+j_nI(~Ipn$P`+Kz*^4g +zl6H{$*kMAu{L;PLR(LJ@Bu4k5X#ZFws1htZb7EY+7vOU$>jli}f5O{3Cu7I`=?Z-WF={h3D6bId +znYOSon6WnkoYFQPRAM^VOvIOt^<>v90|&L4m;V>MEnLHBCS{+2es7+~fBJs&L9BG} +zX2f)5Ag`0HPV-!6dQI32+9ltYZsYOL+d7o +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 +z$}~2)yE=xDQ_Np#`^;#^289~{+?DBvGz +zJJcph=^Vs=?q`1P=nMUUM*R;`Dw56i510IFLUs`LtfeRDzgTdiCOlwwfG3Ts{v&*I?g`+#0DOtmxCD7dm&>+z +zd$ygezq>gVC75U#gw~r*Wj-VdoH4L%iZo&T5$%WdkHjSX<>wjFuKUY7;UMQ!+NhV| +z$~eWov}&}zUvq2n-|Gu_%pFpb4wDvD6?T-h3)u9Y7zye055gtrP#zD9ueCSNlzWmW +zk^<2I`$~Zusc4(D=pT>K6t=wqELq-2jF#cTGIZ}yz-EMub|FE;WXAeiFr-;>@d3nL +zLsVNQ;ZXb%dqu3ao?U8Ws8^$6E*6iKqz*g`kP_JAON(yHgZktZ*?_e`I9kf#5&YjO +zkt2i%vHXR-KIS^^Fv*lx*)uSHW0siQ7f*NX?B+2TEIUO?Fe%N43nVFBHjwkyFG5rp +z-I;NQD{D?=c(v)`J*sdhX@dPUWJFrOcCiY#i#`==F<9Yq!(X#|Mw&KDmynW6$(;2ZwwX#5_7FPpUHQRgW&eCcMrERmnCvc +z_nS*0{$l|=6>Vwq#Ht2)ggrAaH|=_0hyTcXj;#+kc8`R+FdTz_>DIG;2cjSKc$wskg(5d?3 +zmCnf|+}UD;;U4nIprr|ukV5J$rKy*>2OtHy@@Iizs}wPvU^c(r&cwPQ3sP~Bi_7C9 +z@gF#9ZQ;o~*!m*VrWj{T&$AdKN{qic4>}$`&4jT61Fdz!390;6fcEw{fxrrvS~Ht4 +zQ^g=;ptZ~KT-=$nT0@r6rvl?vuhwpd+0G#FZ8I;@1FHNhZFBUxFJC!`K!V-d;uQ*X +zNq9yZJ6L?zR~%JEL|<2+-O+>Z?vx`KpD?@i-Fp$5mbE)v6?0@nTmnE?f^)}{O3*6% +zPbqvlx$eck+uledK4-^i9~%a%f0t7voTYapoUrR|yhSseb$Brw?=ODdpeF695NrBbRb4&fi6N~OGTTN)8x+jTmFK#U(ou6*hTmE`!y+82Vv +z#ZetX2>}!K6&SElYu!VrB{8h!s3gji#?#ZjAY0NuD2Y;F4S!kl=88ZH`GkZt9_i~} +zwb0xgv+1DC!ZOJP*8IuwXdu_(eZ{c}5?#x#h88nncF|-g>1EWOe#@o;d~}XUSrfWq +zS0lNrfTAL8nM-L<;fBsQ5d^~C4G!QDtB-VjF_X}NO|PeMxnbWTYfn$P)OBhh+-w@F +z1ZQWG-pOeqF1lsONb0BFUMpxlI8{_oSUDxKJw!-B&DaNW$^?#>34PhADdh@yuH{r| +ze=nBaJ`+E%?60()u(vMoM7Sw*nQ2>Se_Hle+K%(vPBtP?Esfn5`73Ql{gJlS|47?Y +z4OZzhJS63Rq-~x>6NkzTOhr%R<&Y@Esoz%^YaENgIHWL3CEEWZZAXk=a#Y9LDs}ue +z5B<#un`~X^5P@O|bm4=i`XEvZLtBN_Io~n*glrb*J2}{D0w@jRmMW#jE^*E<+j?B; +z3b>kGq=4+KXFw4PHOUIu>T;f~lAtlZvd9AmVh9ix8}IZ3>;s$p@Oc4AZ43BPza8hX +zWVBQ}o_u>=Ln5V8RTUQ}a4W6@X4->~n|u#kx-@-!*=%s{aaP0ZrYJ61+G!kF2f|XI +zYSH2j;Ljz7-=v781B!S=X)|uHL1boJWEc6=ekrN;r^TOWjC~kPLh$rsaRV7q{eq#zkqWv9t{T)U&(zfY>2kTG$>J_hqj_)Wqv>qD)p}jSP?Une$ +z50dZ)&RpeU=Ghw$WiYqCICX-fjhbqKxO>e4Ht}$YWJxFrw@znLrk@S&n1iQqdAxxT +zrAnm}n_E?N=kJ&$iFNlFhiIw2=Ud9v4Y(6fH)H&2chnD~rOMP0w7A)BBw;+xalS-W +zom +zo7{qds!-MWJ9J+0f}sM`i@iSQ`76A0Jrkc;bC!;z_b$B@&VTt>_Bt4r0D!GQq2oc^ +z(^`CL3?GQ4%#+9lxFy0EfrG=Lg+vW57km2~p(LI3Kfa(xs +zq>$qt?MUIz7=kI>ZUqI!Q0TlQ;LQ5AObZ@PG82LwA1nq +zpe%9o(~`oLSfS6C#^;gSQ4d8&9i=kD2U=^x*~cG9f=(2YeQh7VpdgqPG51d_!G*-Z+(GOc2klS2C`j5|AG`vV%*SUQ~|EzMlA +z4^em9_&aH~x{f-CY+r7O}56Gl9}= +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 +zPINKn*RS2Pa|;ktr|U<8!c7(Vum4Efmj98q +z$F4=r^I3_J`OR2drk=qftor3TR`+V$=Ko6DL;9Gk|CP3-{vT=kZ~$~YOXB7+|o+(g^8PuO%q~{p|t3|2mk}1wh +zjrAu{w0ejLhk`izNbhvS!jSd6sM=wLD^<#J#6c6+aNtU2XU4OuPQc3G&LM;HdWO-iOn1`vF$o32pi&!;@Z +zf;Mspt+mS%z`Kc6;~7;rDFFZ8dxW`^Xv +zUx?I>h$yoVk4y#vFcW&FFornt`T=Ild96CJJNTE{E(<3Y`b%x=5tJ4IfdPcKwG`>4 +z+*Hg#qVUkj-%IA!LgUi`i?zh7@emVMi%RS@2FW*c^s$VKxqbq^evSX}QBuxCOn!C!wzrem>I*^#pw-J-WWJkL> +z#&^fpKZcD4GsRp5+KNvbmu2@KHhn~|U*|$Wjt5g*oUr$o3@XA~=01KoInx?xEDM)m +zoWRrg&c~P$owRNgb~si&$_rAmiGPzY1hNM&w(d?&pzVK8(v(&OaOSxU3f4=FmS*M% +z10x5A95HhK$hjr0H_U@}zqEBk-5GBHakI&gVk{wFDow6wJCuL&Wo-6eh!Hu)_x-4y +zhdRKVx<5SY?|y$HrS`m$yNj_A_TR<#B)` +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 +zF#kqK9nyk9NGq#X;T18s{aTrQOO2j6<^=u +zQ;f|xIBsoG5Dm*KQ5R!QtQU8DEvL#;19xKu$RWh`2uDFDz=ofBQpv03{%dWgNq{&S +z0z+y|&Fe9osUbyaPr-elm_$=BT~)FR4~q}X!J*rg^dAaPCP_o5Q?2?jODQ3wH7Tfe +z>b#+0ZEccg^I>cb)^5wbFo$)xf~ej-&Zue*n*%ZfT;go7sn?ckSz$1^3K?tbEWz!REoApTIQ^-aG6*Ubw_3s?WG1-OiFN)A9Zj@ +zGl}f~h*KKgTAPCCPWvW@RnR~-GB$-@ww3~cK&(Wt4HDnKiV!6^*q&z`EF-CChO}

v2tq%>cR&T~-H?T77rE~b?9H;_8%aJ2vq%cVTDy(F16A#b6*YeniJF4cH0P?*d7S;UptmnA2z#Iz;9JAlx;IO(S@smJR;2_JPubHp!i?P7iuZD;()+MbZ%2>Hj_R{URUJ26+9YZOZDA8UJ+3jygL +zYn%MP*7n2yTHC9nBL7(1V=BNU3MUCotXCaTQKd)8FO4c3Oa +zMxU{euisavuKMg^9fqP{yfA)i1l^C^@l`U(8&mF!$#HkY$;QqS%}Dc2g8h)l7v$gV_f}bxK)8^H +z?a4YOzf*D0eM2X_aI~ma;`d5DR3}oXI|yC;yRAs&WcY1CUnDRIcA=wTB77FzSQ$$8HcPcNNS`rz&jcD +zEi+3zCS<-Q>NOr7aXIjY1-ug{;Kwr_r+KF3KDu-1%oapve&qmUa)!gCN$09n6=sNof86Zq6)89?xJTe +zsRL04)#ZH|=zd^h(l?5~lWxH>&>|#NytuKPrx_+Ul;TlF3Gw{oa$2%r>adJ#2vua{ +z=$#kH=J(U5nQ#3N>6j=F!jpt_?w_dI1*n&|ByZ6d7g+Z0w>_bV)%&PfsbHv8Y8f$SLChB0KRO$;1JVSlW?x!RBYI@2Os~df|-ml>U|{{e(h9kfeasyJA`o +z@^n+_FJhdrr6(U;N6IDDSJ$P?IIb~{8{G;YK7cSCPgq@p%XpgIR&TmZ@LB={!}jBx +z$SRK7wh6e0+p63AjMSoEV +z%WEA}rgQzH5IvEhA2snn33jLMqJ=A-t$h6Umiu|WRP8^r7@y~8Zc^A-wsXf-)?2Kw +z{Pm@D$htWmmtZ(6!(!o7QSf_T1s6!_g%_7~1KVx2Izs8H4?Q`fqWbD_e&sP^ldMX_ +zz$wD81x!z7(w?eWjZ?BhF5X33F1_hW<5`*YiX8F#Yb8i56V@qI%&pL%B`MN3%|R7u%M?Ce +z(!tk^yMoP~&$owwJRl*Hg<}ES@4P5CvBTOHTgKg>xKoT%kHH7rYuhv)SBZODOz_mP +zOB0-U(RgJV?Lc$pk=RUSaYBF{_CFN+`BJUOoPCobKg`J-grHtJmpNc9J4*n!wwTG| +zPM61)szpuqRcmoNBh$J{UX3+{l3?|85YHObcABesreL}oH9Q%k=7`N9*q#Z^p_@96 +zKn>aI4ba@FBbJz5*msOJP%TPJUT~Te%a-&BC3r(0;RCN7z!Wq +zOemL@4Vba+Si;0v;rTc#rbL@kv?~KPpWx}k&b#+bq13fA=aEo4AzPApkwE2XVm$98mz00 +z1HO64y~W8wo23XeU?apfXCTF)GmoUt94bvLatSC~QbtR~fQE#l=k>0WztIEe0ke1o +zNg*F?Y}~J1g=A0qe9|=%VpZt}XcN?02!~wqfsi5RXGI_;a($9?PZvTfS%Fas2Ls*_$USgzNqlV`vm}?20{TK1aXD;iA{Dk_hto{rF2?)x|Yt&)! +z)4HVzn2e(xyLZU)0%53Y4FiJ-80esdU<$1=a1rWjM)>UVf+E2zkz{lbX$Q<`b_Puz +z(6*WDvjE*VE;Zd?eKGKd?+|jwFIQo{@dCpi`xL-#Z{iyqCoElh=)_LMXX#BVSqh$ik%pAY)t{wP>LICM>fsx&#+fE +zP%9rHGjDob?_n~*ULxCRxtXuy*EQmTlkD%>FC{-9xV4qz^RDnNF}$}%v57h4xjWzi +zD4)1_XpXrQd_dvHh02DVwf9DgSXzwXJ7J53^EMz3#Ks=d?SCiKJYpSFa$5))O|`1o +z8EWEER~QH32=fS3I3!_w8nn4xII?lMV7pIM9E9?PPmv2Gs7WnyU4=!!f9=NljFPNX&pBZsD5K +zg?6SqoL~eq#EUd|YgJiD_W4F_C^qOiELVV^Vu=-Wmh^j&hJz4=M+kneK)*w@0SpJ_ +zE5PDGU_|(qE(g5c9uLfz;eZ^ZR;~C%? +zTak-EP#~ZRb2b5hNA@+JrRTQhgUp;MT_sJF$CU&xv+L{!a+o*gwL^C-r8tL$e4`^N +zi+m_!qzV=*Ghaog4LXLU3&$(Z6rI+P#JEw2qjVG3oU&4N@?wJv!cS4lK;c{Y1SI~| +zy);|R{08977iutfjyf!5owY{Uf{*HCw+Jux44Z|Gcm_NPF-5~}`YHbBOe9zI>WRFr +z?Us=wFl{Zw#?Z%m5QsMcG6FrKu&9`&hSMgwTDR-b_cI^fu=Clpdk$qaTOk0i^$EDs +z9hoafHtzG@=T?AQ$6n()PV@|rJhCPZV^onu3kqsXr5B5Q%)~zN#1_jLeH>0uxbEzV +z-2@U_0?O_eV0e$lH6}iM7l!vv;pU0jdimQ!ueCo?kQFpiMOfhUvbsZ{6(G>$fg3bS +zs=4BsO=)w0HEc*71f8lxMF!ida4XgYo-TmZfIEgyDVNJWsz_G=$!v2t$t2M9aGpsJ +zW114ng;Jm)&+`h8La8wW1uWJ9A->fCzl*#Kn{gK<_^;Y)3;SI;(fCmc$sZskf(3ys +zcit;1_5twtyQuqI75#?0B%}`U``);@+~H6U6t_^Yrq=|mRg<({mQlQ8r^Al+UFY*n +zeONspRoFpB`MS@55`i3Yr!fRXSttp8y<6|ONNBqP3WtrG-EEa}oqBDmtdhjvCSF!f&x{%28GL8cs0FKwS +z2d<9;z=}tlYuDD)YPxrfu@67Nj{FU?{WWIwswZG8zTui8_PTtKkVad!89hCHHCFU| +zTcT?C;O)>kyt}_XnmWE{=srHJa(D5&T)o?y-deN>P_14ooZUS~-+xWn)%d=T>|P#! +zwV>{W-H%^0^tN|)!abIy=5D8)yfqgIy}#XmJmHSNyTI1))!5b8ZR78+bLwn=;cfBq +zb$)){`S{xTc6WVxb8g|e-`{RFGGlvu|K>Sl|JuLKJO|J0rs7EG%0Kms^Zf{D9_hQd +z_EysOBg+mAb6$aKQ`wW0__PJJ<3rd*YjuSrn1qpKdI}J8j=h+fMqYi|1GGrz=Nse< +z9PB)%=cW>)%zA74VEC?b(c(X|@^70XVh_)4@s+SstYp96V1(+=QVYKTf&PK+=M(MW%|b!(l3*~8 +za`;h;-ULyGol+dKJ7$0=3fJ4v82Yl;ZEVgNZ0Uv%)1z^+4^Ma24}7=-k%9M)8P`^G +zLZPoGQaSYR*H=h7D|K*bj$saU#@^PE)FCxvUZ(65m+SWr;CoN(Vqvgvdj{Ov>tp2Y +z`N$<(p&_MxDhMk@+mj9c&ug@A$ErK-p|LV)Emac0>cu{KhlNfOtc3M-|AeX&<)M=s +z%oa$>Wm4HXFO}_Pa@Uykxt4WkM+S%j!8oE5i{IVmIYRvL!|cq4AP +z%LW@4BefPlZexsKNxGj@%P;)HopCz=E-(j1-rIt%pqiVnOv?fiRGm7NVKc~9W*NT)Y2qilt3>ZDmkt3{eFn3 +zs(z?ny@N_&;#W5LUJk`V3%SrZXEr_Xf<00F((sr70ya0T|xnW*{TnUHx9HC +zd)by?fqIHJy`S#k{4RA~!2J^w-C8wW=b9353ly~>ozci{r_amuG7Q#64vW!i>@bNe +zJT*;vZ!0lP4w)v2mdVSi)gj3+&P%(|N&d#*b-f9}%(NL=(kH5Q$Uvx_$}JQ;JsOD4 +zhAKbQB}f_uqfmJ*C3EzyT0?4K2k@C|R^5EVAFy>--#HKm2L=7U?IwE1>WQD=99Soa +zKO|BO +z6`NNZaEnS0CA;trwsp7_jc<@*-D19(a}IR@U97F$bNvyiO`(;;Q`&@k15>x%1=56^ +z_wq(HP;}i*eC}Uqa)THp&M0^v!#ItqZwb+LvMV{w$(Xb%20O%uYl8i&3vJ2$mOzpZ +z%}WCM2y=oN0m7+|?!Y)H7i2zvBI!%*6Qz!q^}d|RPK1VZ{4DEAluQleZGMJV{6~s! +zp*)|x?N6aQ4FaP=Ph+B+*DTin>9+mDYK-tM{(RPbpWYt*X2Cx9IuFN4Xe)u|or5@Y +zKSxl=Zkjn5$g~!O@2ZJajAd}z}q%-dm;X5Y=V_D5|G +zPjCG0??PY4q(hmG1N!fEIWZrefL$~@bA>ktvPBP0Ro_>=?@!+-@70uj$%Ks>@%yY& +zrS#+$yXU|zVKI3BWCB1CDCqQ^Zxxf1Q|$9e9M=G6=Fmc>(CFXu-O%sI1d-!=UGb~totlgCpX_EHAhv~>*{kNLaP +zCGy|e79TOOW1g+&SvdnGxSr5z?N(?GJY$nnHVpQ=4-oV;1OJDqd+h79-@gW)ZQFK} +zt;u#xw%ugcWZSlF+jf&}*W~Lr=ehU(Uk~B9@x5`p*805H{kb%&R61!6fZO(x*A=av +zs|MJjNZQive6OO;#Koa^KCDLoZoAnVLAXVk^Klh}o_M=|PdI{4;LcH(atXj~&zC&e +zWdUmwSk;ol=E+3^B~8P9C4$x*XLWg#tH^Ap0l4k5zufj3N5<`|OwwO&8}kalZJV5X +z9)c0#eLuffJArTNG8N~r1FkqL@gAV|F+x$t;2d8X!9i@EQRiU}n7nO7}m +zOaDNChWF*D_%o@-9q(#Dej_w3y(Sch@@w9WSD5IA9Pr9Acod}eS*+$aFAXQG2Kqe?=gQNQ5Rv#XZgNz6JV!^klMlD9K=bi9Nl4t*3 +zCjPb67g^CQTh-gaVXLqCaX^`vm+YYvAG`9z*xauKItKJQOLC6C!n~s(HMcJ1*LNw@ +zs{#L|2b-nGV~g98v4iUjn1mR_H)NnmaZr7eOVtxmx9Oju+QxhiI98KvuF4B;=ZIP4f$i=uUYB{-F{SP-ApUGw +z1uMm~ux?r`BhNNIB-K+Hudw~qw(s|O5a6~3}Qrh;P +zkklOaAXq4w%v{CuzG1msc8`0o$ZT9DoolFlgO@J!yjq;?>{dZ&i*XpQi{F2w7MN20 +zqCt4mXfNJ?NWZW@cbY@Q(`O48=Tn!d5=mIKh512HfbQ|ffY2w!S7cH!b8Gq@F=BfF +zP>2&+ZpBa7KAXu{kT~G+=bQTqHb-pX{Q{})H~Fh=2UiZfj~^1FG2WYvRAh$<<(YEqXK}F>|BC6SmEzo&E@*@WI*@}dyPhIS`5$xz< +z$fq5wDjh^;$-5N;Pj4NaEheg559@gNk)jd(bPug}@cNmuUu77!(^ejo3oh@PKk8Zd +zZSJj4O8+Umr))B}C?5cJeziIH8{B +zq~*unU0D9=YX0DmdcRe8A{$b3`};O!u}XmA)dVF1%i^wbS#CWJnJOih)iQxfc;1FN;$ +z+ih4Llm(IOiN3r#W^epNT*amOw7Wnh~Dmi844iz!649P3TqJF~ogrEN& +z_+%}lY)w!-j?TADARxtM@G-X>p7HKB!BNjabp$Or`*#&x?tT?4~~y30qeC%ua1e{?9uYw^#+ep@(yitoh`!1sh*h%g!gnA8=VFB}iat!m|M{UG5P86`rz&OzEb?H0GUCnK{|zuCI; +z9bXQ__B&~Dmmr5{uBL^xF%N++_x`3oT@T@EHA%3c>|8%|o=(-cGq5xu6cPDnOy*v^ +z`Rp#J2vQ9%A3Mj;%!qTW{7 +z4Z}WZP9lUAlibNT0qqc!aA&0Z{5~OCk}zkh3zSG|JqrPPJfu?8)WSv5UUys~>Y;%! +z8fApE31`H`KdpF2KD;4CJ(371a)*;>BC=I1N`0E-4zeFy{Us$FSm}U3@qxv`X??aY +zrGK~pwo7d>;h&SKAp4AM;q&2XSA0ga$l=LOg!(YXCb%;# +zJ}VlgVmh5#r@~^py%BL`ydw78RD3E_3~=);rYUR@-Q!>wdB=+@jz;2uQKgRBzsz?jwgXiaue8;*t!pi0-|AF?5q$o`Y?rH%7yf0oJ5h)L%=YHhe%_?*CX7aX(RSV_ +z=5%nw%pcy^LVQFJVXhs6gPc`@wOKgs`B^|$~Bf0_1HXfZc6rK}H^IvBByw3mk(~g(n +zfLzHaNWYAO`Xi6Qi4vxuh5ezt`KDm8N5eaVu8>b@gw(pP&RcM +zlc1S?4ffR7`OIF!EPG&hjuQbu+2%MPiU2YiocgP5KmS#>5s>~-wl&;ff?Pq_8NWDx +zqUS9qtjdRUCm>dqNWuF05UORXuGa&B@p?$D70I$)lGBL5A3?S~`D4Lyzq}cpZMVN{ +z`ldu;kuPpx=z1|)RTIvr@s0jfw!{9TY|lT+2&LJn^co(YX>(P9#cKbfY|8_bZHOb6 +z5C4zXVGw!Xky`T5RU9l8KqjTk3)+u*8&~Mr3*IdGs`%u-IRlFRn>HhX)Us>s)v6?R +zENgIYwWhJU7nBXpl669W2!lklt)B~8-XC0$OWEhLx#7KceI2F7(nr$xpV@E(#h{_6Vu+ +z1otD0+1MW}3;KU|R>+l;Uh +ze5c+@$i%|^9p+nxi%FW1Lx^iMbEA^_F6Wwe0ws&G{FNaABw(D^Oj!`W^+(UP`E6^` +z`QC0IDa4z0Ur0t(t9Y#CFU78eAQbMPB*rU}0{qVB`!WwWI`aX8T$z4hNg!UJUWkKF +zaoCw@#11D|4!Ix$R)QuxZv6hNrT6$J8ji`9yq;6WZCobByL(v+t>(xnS>&Mw@*p|S +zZUcK@=C&k0%Ul!RaM;3q|0I#_*UwMlG-|XTi@>I?ipOwa49Ejk#(3u6OdWg8x#Y*$@G&UPRq=Sdv!57yLtzTqV2$iW4g +z4a02|K;Wq2*43Aiv&l|?j{oBA&cYk+o>oTzHX~N_9Z<%FCgea%VD7&?s7_6Q4`o>> +z?-wq}I_qT_O2L$Xkm{|fSvb0e%xSUO;SjXE^>&{E<<@5(!xP_GCm!!3Z(3pQKPt;e +z7F2(dcDB2Gi+~0HZB>kR>wv<={PgF~d&Z|){&STMf(*1(P#_%!rdYZH7iHM`Fa&TM +z9Yhr4gaQFUc(nZ`-gbo_^zti~&)2*)2k(Sc0tF0YM{FJP^OD{zM7=xLH^1`8PhS2* +z3t;ahA`iZ2pA38Z*^(PvZ*iFX{r;BR`O|TI-XL)VEpcoI1ju~F2}e>~Bwc>8QmgFe +z)4Cus;w6I|W3u{glrEg03?N&a`lEDYHZ&WM?i{bx&*@o@koiTz1_GUdzU@lNRWES$ +z#@Im-c2DVkdRf5|?uFOQm8E{vHN&Zs#Uqu!$ToWtN`;owV$n#MV}>aaZ$rO7R(jXu +zpgOxuKysdIoh2KZ@gL;$ia +z3qZEbbZC_T$aZt_E$iT!ILqc^h6`GJ#u$i8cJ#%=pHw!~-I&D>OQ-4N9TmpAIYHlK +z&*u+v<)a5jHUP41kd?Z5=OB3|;t1`R7s|3Rf8*a(qV(7d0YJ8O?h#cm544Rm+OT!M +zz?{Od@9-YZM)3Xeqg&L&QNHr$l|lfir~h7pz1ZanIrmI|B5Y<-Xycwup++0E +z_=n9xQmmL@z#3wpRG!*g9Hhcj1wT8r1VW8g#^2)~iH?hUKtrEDyvrTP-48AhlVbc- +za!rKV_&%WDC5T9six@j*M&ATwJdd3#KTH?)ELQI10HB_Z7b(q@)@QfxhiG%&+PXk@ +z$22IG!iq82pR0+QuY2)jOpS=9bic15LS@EFS=9;$Jx+#fxf)d^v{>1q4m7Klr}$I) +z&D)VBVRR|G+m~#m-S=C?(l}EvxU;f{DQ)t(Dq)ZiU-MnY +z9Oe^lE$_Vdc4vWoMO5)YxA_c(zU`urZAvIui27{a{59(EKH+$Z&!2N_D1z7Vg1iCn +zzwU-V4f@IL!DIVtn^7vU3YA*wlv_Y-^qwk|eZqP)_s+_d$us^Ky-Uf$E6Bn_BwIn$ +z@SNtkaMh4%m{|xMT!+OC+dj>U=xlhT%@W^Wq3li1==jjX@w>EMB)kh8?wwQTbol)t +z)4=XeeJv5#X36wZh1Y!jp-=#=Ks(SlcV>n$3T1wq1_s2Pzd73fci2qeGh3T*VG|Ou6UxHu@lVw;VVVS9O(Pl>83NX< +zn$b?U+}gDSs9#uJs7vNDWA%_Qzh=((Z(L0{k +zWQvJKQB;kr9+BoT;k@6oL4*ZRC^U#ycnR+O6n#GEx<9Jp_Hdya +zpcDT#uN(gBCWWqZT2fZEA#SK^5ex5?-AfYdU6`_ClJ8$*dqq2|obcdnshe96HvO97 +zE&I=WE#mHmP^)(g17l(%RBoUJ=vnS(>&hN81XaM2fi!jIpfw*8*iHhkR6L72hUKjY +z|78hL%?13L{{dO81&Jua)@njzCyCl#U&gK4Zk{vQG +zF$=d=a_ACsR-cw08Ua&8-k@;3rpn`@Z8`ouIg-EkqXH06ZY2{j0~8?}t1Dk&n@3;m +zi=m;bevZ<|t!bwx<7=mk49Ldu%E4)052Ub|6S>aTd5-WhN1$uwVG6)tM>}6DQ2kJZ +z;7Mwo^`hH%hPW9Pw#OV{TP=_EJel_?Cijt4g_`L@OEyuE`>5%dkkdZEErIRzR6w;BibAOKsGXZo(dY6b+im6^Y0?h^G%Z`& +z90!h4Z2`!(Ra~&&*f?yZcR +z&u(T3G$oExMa3Bavb~}K`sFV7tpg!e2K1X4;bg0g5w;FC`T~g|Del0_i*kV9>Vhpj +z2tUm?GVf>vwSu~21oT1^|BU-2J$Nb$i?~e?){RS6E6PE%R{opsbaJKoyqjv94KwCY +z(B+ZOF=cDYWN)`GEsma+`p+*MMG^Fl*k~3cWkR +zDviD+qE-G@vU2KVUsGagJ|ZSMf{?XS_W98;z>H_ewBOM#I!Xd+NdW%DD#}CHVWXdP +z-%Nq5y=>sH#Ii!DlCBigBf;0yyEcBQLnM4g-XIJK6(xtYZky3Avg)s~tuuz`#dF-$ +zwBW9-_LfUGsDIdPTl?H@*@zo}^QHu%8vjw7Lmn%Kq8s4Zp?TpmZueW<+Xp=?AuX;m +zTlCnh@5fe)fUUG1kOY}Jg0dCcS}jQ%c!)h^UJNw-OhisGhIRLc0$I;l|ET8=^qNw6 +z^ak0Vmv{Oyl;60hS$|FE5SVCPTA{+bXk;rRN1R9IhYNXKUf~4^3N%+M3z7h-29Lo` +zv&8bbhQKKyWF?_C5G{$?0*{YlMCWP-cDFdlFHZRm)ZPeug}mpLly83dJUqGp!jQ-3 +zk)E&fulH+dQ2FK$^1>KcT+i?P0SP@Yt$q; +z^8Uc(Bqt8`|oYq2ge}qi`K`uNZ04A>O!3 +zuZuyXjXZa&UL{B-^R_#Gk~C!Wu$lU{G3lYu&jykzDNMOizABoMk9Y>kP~cXc}aXk?N|D} +ztUSORINa#scJRi`efAqo(7J$Yy=K#ov@wrEy;K^J!=TsTh_GjIyYe9F`}YpXbgPcs +zNRuWzIaCPqy)l^A^BRZ7yo~N&B!LbE#0fuY)5ScE0(oW8{p3ag>suXsmi)zA_|(O` +zS_jr*o(SQo35Tt1&rrFb3b?v3 +zprmaT4Y7;z+2Q)bAOttzaJ~nsSFK1z`YM+kI62??{nTBN>C|m8-UKpcx@sA|xODxg +zT~+Q(PTACAswk_+cTYOU(_aOA*N{l{P#6T=;knuRCEPPUeZAnbA2|g9$+kP);?2ak!-h@)$<%p41W`3P(&x1(az5~(E`Z;r!MrcGr8<1bt!Hfop6o1my{VMn@}PvIXx|JGU$CFmgPxX^f;H +z{i3^!cd-`Rw^TCvx4gfRj_5 +znt96FvTN{^ITeZvf;UTHP(`EOCH?}O4Ozcdg=xxMQrA25@BE!bC(nYU*f2+$xX3k@tN>o^ntZcc%9=gE;t*nW?z9+ +zgVwUFPiN*yiN-1(2K|r-h@o{BSxo;rXEdZZ_|{w1Uc~lH&M#e{FO_cf*bB-Nks}#e +zvq2{PL=G#3o3XZ-&h6xQM$^t<^{>C(0`Rwa0?FKsBtBGC+p^w_pEb-A;TG>=6h8Qu +zPW&n%ymk5)oS;r{Mcq@eMV!iGIVfsxM^bOm;2W|+g{xBxg?~}xuZ&rJ)2RtdhT~UT +zX4imzZp2qf33F4^JSU(fY-W->MFo@6OUtC#?}??DSavAVpYM_sz+A_86#*KtC=y_y +z()zid&n0TJ0nt$y7}Q}S4#czEan4qWX@tPvrB6=l#Sioh^xlU-B`=AB!e|_5EKk>d +zcvuuQ5-?`vZ!BYTgqPPS03I+UhiGw@K-!1a{!P%x-amh1u#N71&ybAVHg2{WN_s7{ +zjxI#d1t^P;2kAweTfUwIPv6RM7Zl975^Q5g +z%~@8s^n= +zncj(y8Co(^U1i=4UCe;0EW#f?Fi|TB(oM+w4!S5GDN2rnpP#M9D;SxL1AzvDVc21- +z6TET8jgv}d_2u^-Om(-F#aw*f=6^}<#f-#0Qc#& +zsx<)MeilzLP#!?HKwkL=;I{b-a1+rzCPuG5+Jl5aHp8Kf?7$}RR(}XJcb#Il4T#e% +z(DuV8Q2Iw9HF#|30^1;>7x4zMf)7(v_dF!1_V^{c@QH&diX*vZ&xG^#O%iGc;6lSyqbM>eeQCCM)Hvse!GVP-3Or}@TPcbuJfey-;s#&6Hi1DM0edK +z8QZ!6w`&oD?}geUbiuSkT|`BGH1SJk291U=yw*MtPqJzOMZF(PAOk3!>*liRYDn<0 +zkV!I3Y%xZxr{Bfas~s{xu-ie65IIu7k1CwNbq3(>%I2gzcjEYXk?wULJSt3tY<6!h +zl8oT&J87K5GZjJpD7V%k8_7;b4CO$UI~Npo;tm@@zQ`v%P#{Z6_NS0hVo2rY4(5I! +znGK1dQzLr3+Ia9jAZs3bmLG77i`7k>j~b%JG!zl2&#nJ<79IyNwlkl1&)? +z=dy%Ah*rb9Af}`6Bg52w01903Hm_J-201Gt;l004It0N_?{ZY7h%Zn>9Jq{#T5&sj%;TwjfD5GP8by!u2J7q|Ek +zQ%9`-oj|^J9no$!y?=(9KXI#1$W+F_T<`&Y&n}}MJk*a4IdEzYUDNpP&z?1A9aw>| +zNo2j`p!)SjToTiTyabWRJh7bI!kL=w{^f9);!|0!Ns12P(_^zdy;&9!HbzN*f81$g +z7sh0yoi#tpXK`q+GZ!h~H}LIJm6|uaGF+0Hwa5T0dwt!#ks&ZV+5hHaG&Gyopk*YUta$M=-Jh>dJ_Dz1< +zY$N`H?5jXPgPf$?%Hbp<>N?Zy)r&cfqs*fZA!oE^Dq(&r~zwUw-Om8d9 +z@XF^v071WdR^cO-*9*)dkuEmU?WgEu{&X4dwYns+okwSqP+Be?%%un-7QE%(Cun9n +z?wP}Sw)WbWSocEq@`;T<3A7!MI9No|T}yIrAvJ%-#@`}imcRR$>vaQ0UMDz7t=|PH +z^kfx%NF+odN?TU4^Em&Db91WL46SJ+5DGp$SFZFMn`gsdu?^*g-0-wWqI9Nbji>VH +zv>Fp_FD$5zyYVom&QtGXikjr%AW%6`1tcd&9UnqxMG~~124@We#}RA4lo$5cjd4-| +zbZf?F?rMzpWCbID9iDoBfnpC<_U@WQ&8t6_?%cYek7lQkSf*5=zBWS#qA0lFmEtF#x&Gp( +z+$E4>21LH2X)W8Qd1Ft{vOaH}4iKo#FIdE&m!zLBRQqRI$qnRkVSfp35TpMR+{%9m +zZpT1v0Kr`?1|Yce8xCku1mp<)k-7Wokd&lRk`G+TQS6xG>D+H5{AHJzy(AD!nKqZ0 +zE|yG8F!uO%-$v{LWqBayUbSYP!u4B7CifjN?kwF4SN|or(dy61S*x9bZ=dThf{85z9x9l?m6G4 +zK?0>16L)VAmyX(536sa{#$SSaA3$)Ifh_%p;3mHifdLTQ<$03-65M(wGcR=HQ}eAg +zZ}v2u!ko5w+OJ&P{}S8@e}LguQS9Yp)&7s*?yLNl;FfjbuHXrLhjLZ`5ZucVTI->h +zNbmn4xUHR*Hs@1)pI)$yJwZuzw(s}!eN42s* +zXx-yIoL%SH+MAEz8aX$J^K3Po3~qg1zw@+y?rOgu1Qj(Q%dC#1?lJS6BU$dKzRf2& +z!Kfs1D?K)~j(N)nx&H)+5B{#_+2sp+3+}g;z=io=KB7Om(Df}A)2U?jm&j&cjJz{k +zdqd;(IpAhgyGyvA7 +zvER^44{bCj(4mWlS|$p4!Bz^`7j#P-x4GbLsw3zUbo!i7YmTw#7Oz(hqX)2zbhcc2 +zq<>*>LYeQfqAm_1i=HW#CEXwuy*|r%{9I8f^U)5U!0;GRQ?S#{%cX;floBE%U0+ +z0%ogFI=r2`u;!s7W93T)+qM~dQk7@eQuWNl&+JU1r__Qz5T$P!oGHU&jC%Q#s(S!u +zRXE0mA6{AqWy-brKw2w4+jGG +z(Vk*(#!k{r4%1ZFd+|e!!uf^)nwUwK%RQq;P`OA+;@^Ti3DqXv49c2B+_qHV5s~f9 +zz(XI^hEb-tVC8u22|EhUiutyxdWtH+>(-zf9+2H{?-+;Rk(%nCk=Q6XpB#9dn^|U> +zk)NU_56OPS)vlrdo2Wc8bU)%;Na{0_Gj~{q$eavF!X>IZ3{UAcS27{2mrf5~$Zwk^ +zP1g&=Ktcf4kf;j)uwAw1~`Ds%s +zOd-8~kx#Sekpw$kG&igyNIoy+TfQT%l5lTU`%A+^YS^CB09vh(zRM7cr_%KH7E1tM +zB`5X%TYW~v2ERsa)pQtoVZh_NOgOR$re>t56eqgoB-GSSrRW}S0o_S`yP-oIrndc6 +zQIa-W3Ic?~SrSKs;t5svpc_M_C-f(GYR7|5kC +zC5^F3vC;JFsB5MyFAywvUoKk_w4eF*JhEop`_6^r2eh%5aMuSz^1%e9xuBkp +z=@@l0{W;NF`;QgEf&No}O`Wn9>~S{;`k1sOrUpSRl^MAp;B1n_edbeYc`#PAUQ&(W +z8^8BaK8vQYt`yNaOUS+=Ghjq>IDiDyFswN^SPANp9*b8KWY>jSi7-Bza3)I`3A?50 +zNSYe#J;m`C;jU!pGw}oS?~s!nO&;0~s4r?g1t8p#0E8P3rO)Vqqr3fq5+_170;e%t +zD_9+i=?838=TcI8<6eelABxKalC1|n2L?L%qRl~ahb5$VWtglqkb7+|A1~-(6?ZmY +zP-W-45HC_W=43H8cripPUfJ_+eVcZ$_|N6;h!|q>`B&vC#8S(;cJ(CluDFZ2@3B^f +zA4UNqMkbE4tXBSmm|Y=;4^`*Swwq>^Ug)#`DBOusQM94v9d1dFmaEn~{Cu4urH6_r +z-}X@xdj$g-CO;9X@k}MzLRjHxj;wl-2niAkvZ$F~p=C7({wmzr-hE?+?<2ne3in#b +zZ*R6+cFXeZCoLQUGolc5=B4vk$%+|JE2IHizN*ucPC6un8ZV+=t;GF&|Ot>A}E{9Mi618^M@mH;cQ|6UWRnH>nsW(HINQzMbUz3j#J;=8*d5;!r2lZ!LLy&>ZiP%>xkYD{EJX=Q4K#UmcQ&UOnj!T<{kdtsL +zppcGE#vi(Y8R36v9fFwrYTM7U)ekRif^|0=vM;tRQSI0D!&?`+;Awl#JX;zBAvZjS +zO4dD>pek<=rr_s+p6|ycO7i-p7%U}cd_h~JJV#k!0ErW3*q?qGR4&Q?+Y4RrgEErC +z`K3Ql=EM|AKJv`%cZM`cpwOF2KOs^3bzBc=xvMDvz!GbqS@4X +zss=)R-hRq;^J;yjA*kz)e2tB+L-Mh9)<-K>ezu2t;xMc#ys~0E{GxBFL=sg08UMFG +zX)Yi9{5_w|6W044M?Ks#@~GnbaUNhYAsP+_ls`9KYk +zV?{`-CJMzIyAmUKtXxMkBeS4ma=mdB!H=b}Y8>P7)^DQWrMO90b3`}aiLjH8)-Uud +z8xQ4PT7M(?v+63MiwEgFvJ~ZbZU45ZHy2b&Wl}*zg7`6C?&>2b!7IyyqdT+uJ5sek +zRHD;%t-rUowGEt7PKDF055N;I7Bnhr0s(DqSAwl4#wxh16T}l++(IXjI4#Ea)^m`; +z+6)a6SaH;ki*59O*k!^gxiz$yE7Hf)>f3* +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 +z{0x>!Y>^X$3|g=$!B9EK52SQu)7}b}XlY +zp2fLUN#*!DFCLc;Y#quk$r~0ZR@kK;wS`5wifz +zyy+!$BzNX?k<+o$blM9=dBl7GugSsyLPW?^Gtmy1*S=QfZ8skj%6JGB9nN~bE3*Ka +zNWgtEO)SZf*bIapcX~ioECnS0D;HO#6$TEWM7ZD@yOmGR+=5Q*}bt)z^`7O0_oVr7~FzceT1w=q*Dg3%24y9+p6 +z)0X`@j#&|rbP}ys;NcKhq6#%?wDTZ;m7F-KpPO)%#V7aPVMA0S0fsX!D@1LQ)f~AP +zPlqlbk1p0)T>^b))_LROCVBj`)tql)yHC_%1GOrlbDO1v2SR2dUQQQ`#`j1e!dl5Ds+Kn`O)Py(A;33L-*Hd@_Ec9PD-z +z)GUv3;+p_@@8USuTl=tZ{!alo4}b%1Hvz*ioQ{ +z7|#?H)M9FaO&h>b-1He$&u)|{k*$wfU+fcwY#25%*8k-3*mOvTb@)Z0OGcg +zu(WShE8+_120+|t`Pv$GFABRr@U>$H=@qc~o9J2shuh6rf*6p)WL$5W#>auY+88m_l#9C7qRr +zp$xX_@+J3&Hb(^tnD`DR<5$YsRmuk6AM357(^ghnlMR<;*5ACXOYqNWaP{xhDZr>_ +z|0{8aNeSw^_yMij*)Nvl;EUym0VMA40Es&lAaNVoA4yaaJ@t@w0Qt5*mT61IA@^dz +zj5lJ9zcPl{0wnIEv_b``b-~G@gNoRLzY;h8XxP*FIX;Bd%oHUxG~M0Y2-Eg3KmDty +zB4Cc3m(;aqz}}J;HV?ReijAvXS;{VxkbP^gPq?s~R46VTWE4 +zJ_s(z5fld42xS5o4c$15(Nj4i5&W?W5;|ukeWF6b3&o`&5lg>L*-~!NV=h_j_ICyG +zUyORw5>L3Lrk#5^bUk-?V0^16CeU#3xoUMm&aS_6S>HC^ju{2;c_s@h!x^`r-1-!# +zmJ20#eV-Z(eMN-aBYuS+=^vNXdUvU?f{=Ng8Wc3d?-K2XfpJ%21%rcFA=GNE(lrgs +zVtdXHjlsAcD_{A|FEsgG5J7H +zjn{4vcCdrH_epYedL0~w*LN*hM2GyM|x^iDe@d~mZ}CaK%t9G$_KT)zi*A7Z$@VV +zLkK3gFx<9SI=zEt5&Z3nT?sBl*fJksY_uHpT$>=1Rj9ZtLyUzcOIB_uX~#Y5PxGw> +zJeQD&HZCkuO%|;brBLJP8kbso&$a|pnIs}ZY&W_oBH-s+8eiq(7)y6VWKF9K<*si> +zS%Z3*k#Q=H5wqv>;>3BZ`a*SCk02z|JYAc7X!{ennvR*`u$;*N{lK@$PbBx9AlPQ* +zG$%y9qa6%;coMXa7bex5wUeq0e}1f4Y2T{TK{ilEcO``avOS94kxh*ygj{6Qqrc71 +zVEc0?!s>Ga3~SaM08Kfu=c3NS4Y@lWIc?Gh$R;W$Jm^oW%*s|^$XdYZv0{03eOT0T +z3R3b_(GqRbbM1I|HIxnIPZfAwDk(6pgkjym!I8=Sxx`N~1KkSMBB$IL9;9UeXe*$O +zwmZh`K%)2T++@W*W}2UplhyD6b|JM^>!DL75u~=ic9Y~FV$cimuQPpQG-$=%0R>*u +ze^VruG6V!43Mq@+DxyHN{(RTAUfZ%6=kPupgQ*ZLobOzE1Q)~g3DFKvl+BZ9l3^*u +zyKae57f-zTy(PF&WGXW+H5*H|vepBHTbN{GU=R9!`Wrr|RLa|q%bRak(4X-&7}ScC +z-N9&-Edqg+XJ7ET(j6AL0H@r>yXMF-ngUg`mPlvc6<#@X`3|x#I-Z^2YS5t_{wyzR +z6d|JtAU&_+r%@=B(untNOp^#aqsA$5%!RHioh0bAnA^NqY#ik}-;>;5bx{FhlJr5q +z3pVffFvTXYDHSbzIubQs4}=wxYsRY!Y+cBFpnU&ZZ?%!zSXJARlYD<#=_7r**Qz+N +z(Rgq{x4*QkA(|yILt1DUO=|P-?w72i{-<}8@@U8-N5KzL`@GJRp^wnjS+5bS2TQmP +z0NY{*gSp+ZTIBZ88GLK>dEq +zeTGIDixi9YW-%HMOVIE=l1W<_uzkY1hv|A;?O%%f*LP+illazuC~kkdQW22#d&0E5 +zybjaZhY5T4dv9~MX_OmhbmVX3vn_vvx9BB88AzRyp!lo}`SnIr_frUYK&?dy)$+a2 +zSX^+&0`8bv3@(OS)5_FH!-LOyU~qy0XC)G+Z&p;$k%5EwhdJRNikrDtsXi^`KNR<- +zPA&Gq55-MSN6_kk{X=m(2IOn}P~3D!q(2n*d;!1MN%VOz_6P$Gx>Ut~Dek-YOstdk +zmLH0Hr$QZ!Imt2U;6cSuUdsy+Mg3|=Y|?WRAN)^T2aOrlrtc3kfBt8 +z0pk&RRji{Cm|v`2d;#Ar5=Y2{#IXE*di~Vi0|AlrQfTiN8_JZniM6Rqa;NT$4XnrY +z5qJ*&$-fjg4U2mBKNR;pf~IEZ55+xunZ3szT?eK2LvgeCnEXR=`_iScs2wNGJ^u0P +zarv7#AWWN-y&9Ht*Gr*Vq(Qd;sM$tyo+BW+u=G-+R;25cNtfBXKSPcdmt_0z< +zkTBE-W6L`j`K4UsWfCRX{T%d(ruh*&moR>);g?i#M`=EN4pB&7J)3`AWs`|kbNvmAl?$rYDN)&V +zy*omN5*gJ$nS1FyY0pEaN%2D2$0Q=*1!y;K_ +zRFtCLt+aI^rq)a)ix~IHQoGF>%bV2kQeZTcki4TxvtHE;wJ!qeF~JEW6vF~UE9T&ga`GjZ_9#!!IOQJZZ!wg4S`LO0S1GNd6cjkAX-tLV#G07 +z@=kRi#qv}Yl$|AykpV;{8Uk~cJ$ +zTW(O+b|C2aR&g?KQb|XgYLcAlx^n+8mW-K|SC&u=^ZiP|QdBN)kabUomv +z$^~sa6rvxcJL)a{XnBMv^t)|CMLA?w<+n)^JWy6EQ6n!GEPSXlt<<_`rAdKGp@ym? +z*A2VogAbLjku8iu0yd9$!QD-8j}fJLZY8BTcE2e4_?Dy&rA|LW+g~6LNd)a_9N3`s +zvp#F8$AIboE~6|m(9G6)B-8-@tL>CNh%`<32=yeYdV;@3M2V%#k9;H!M^pp8YX#-W +ziD+@f%YwkQI85KBKsbn~DXbCU)xhzLf_Qbb_!}OFD}DHJ650MMuKXI(3&bo`DRyuH +zx&r>dNF=C1|i&>e(C;Aqy +z6o+JZvM?lTJRMNDOM$9@p>?ve0Yt;c1CsG+aQCbxw)CC|3+mdj67(>*1?6`+#4(9z +zEocR@GEu^4&sB`c4TVI86<*vRub!bjlnx#{Cu9W;9ht==V!-#vb>8O~QYi)WqreI| +zqff`r;A5ulV*d>J+z)6T^XnP+Rr4I*JG8>HjU{3PVC}b=jDGsDen>VNGHw7c@${$+ +zl5?Jq&%(oPWNCm5X!4p<;RB4IO;m4;BPOfFYI!rhfmMha_|+TKN`1j#ODDD(2}6evlc^ntgd7JlQY#M-cEIRw~XvL7?VZn +z^Q;+L4d*Y%4>rIvAv${y_*rlrE{`*dK1qV~Sm2h5Zb#ZR_o*jhsY-s}ee9uIRsY+-`2 +zv|KZm$mX;+V31N(xVO?tuYmw3`Y9kg52gE0qaO2jR}FB2l_fI9-RwOpFkIC^abW65 +zVfz&X)`;I~E}PN_t2T|#vqR0^F=32K>ZwKE&Za>m+>&$sSOYOTPWPtwZyM{DC|SXl +zuVNNfpLE0V&5b*ePCElr8O0NI4gYZ5(ZAU<;?C}t^hf{Yxc41?IPTM2Mqrde2dmvb +zppfoLoyPPfXmq8&;baAA=-vN +zudC7%OUE6qcu=I@gtG;d?3y)at2TV2CUxb~Za~7gYj!w7a-TW(ND`-qG%Lu0P{c9-8JC4qd%)HZ;>wQR(A`lJ7ZSX|2dlMB7i2N3aODJTs8*DUJm)O6 +zj?Lm5y+I3>lRvD}SZWStOk4v!8B%t6HUPfql{Y*!4KQWXevg&2*nMYSB#9wCfAb6Z +zhvUY>348Hl9lQ7Cb;a9k>JZ7Akd10XqxmW6(BkiqD?am`xI0Lf@B6( +z6qCJCe4%?pd)R}r6WpA&Esfcf5kqr<8beicB7j!PceqZ@RLLc6L03ZhBLUiTtYgisiPc!AJ&#u +zq{i*C6JxJGZ(Vq{Tey3Ijz}DXXKG#qjMfsd&=`S4#NM?j2r@Iz>fclaaBkFGZNtmRki|Nq+25~?sX||0`=?|P^mu>!V+`w$RF_%Y>Y_K=zZd&f9Tg0v11ni1` +z#%eppZi#Q~6;OjRy_#$u_GOVU#{%|teE?1xN)-%Ox2c=eZ|ZoGJ)_0Z_vV8KQoO4dIplUFv9X+F2R)Jho~dh?kR1@5L2AYX4W7Uwk5!Iz?v}9l +z@h~65Bu9)6!9mY`tmS2mB2%HJzD{WqAPz)RZ3~9lC*Hy(nOb|} +zEaqyA19(vYfVpkCdN9s&_gQvcr$u+~0j&FO<-xPWxG4&U?*)4xZ;Yg)li%k(oO)oijuP+(rp9H!R?J +z$8}xa1dONSsw$V#{jU{EGAZ=15@p=0DohUx#5e^z6AgAxaVrY7@I-0h8|u6LA^r~_GL +zlUH`g<~CQ(sZvpc!wu&a9V}5)6H&Gtfsq0lw~+bp4jAA1z&mHHbShCEe?V@}U};#f +z%J7((nIDk*8OS=ba-ViVyHK(`tw0F6fdyljs7;-ux}wK|VtiHq@diYlSa#sXXSEEQ +zzU&2+B%(!>!~#u%-;=ynXnJT1DD3Xg*&MZ@xtgP8kfC; +z=TZkWS>eFan-nWhiEgf6>y+z)hNC}B*nQ|_`m9c!LsC-v)?F`@+^rCZ*Re||WR?5G +z&dLc|JZ4Uu(?{z`*4L*)RUJ4z-y|rK=J&-`z8ym`3OTh9kS`&DJ9Vv<6hi` +z@28H>eK?1~*F#>J8{2KZu(ySYbGz1)yUWz4$Mf^kb-T&!nMyyOZtr*R&re3*PPsHY +zKlts~Uf=g0+T^Y0$K}4f-oL#}P_xrh;jJ%tj+;Zb{Ehj +zvsb8})_1sm4HZA62vM?51HX5xUIz-*gI-8M>&N`8TI8nRbrj-eXrsidftlF};nU8A +zz36DU(`VIaZ#1l6!c!hJV3_C24~Ew1HmEi}<)exUs=F;Ge`i{CKYl2kJ7N_%dQquH +zXRIf*h}aYuM=CM<+iCmUBlQKfPCt^}QK?H3rHTbMsoK;btO<+)gGKhWRfLSs9tT92 +zgNAidzC}_BYJ%18ALN)mY6XCyaIqH^ick5!B6k<_tr77TFF*AcJop{ao=>hhubbv* +ze6P;o=^j5mzkoIDxj*GG2Pice2ji>uD{e;YAg$->I$O8CuiZfM=ng(y3GmaW_ul&( +zQI}T2*FqcAp9U%gXUqIAvnaoIdk-w5L*Ks=I5T|6K~ +zM10((WXwUHh7a*3?i|t|g9An+HM6J^+n)J44!OOARS`B_=k}q+>pxPNnQND+BybHP +ze?io@;X)T1P_ya$iy0=(X$x+rd6S|4I6ImnbeI*3)0olnuhGK_pLr&sPjM}?`E*PD +zAIZ)556PXCB<9Vy9{tojMO8GFfEoip-!Amb;8y}SwJ*)%XCO&+nS<*W*beiG +zAbF%WFg38|-Y8nxzo6 +zxTgJfP#6lkW&3pCu?ZS7P)Nl#raYZ#J^W}j#;4aylFzvUY*e0@P>8y`d!tUDfAHHb +zZ54bc@?owsUia%9e*JJp?7?mScKwoeZCFhH;sv1=NH7~dR#2aA8$({w5+H|1yJ~w-M(T25Xx_yb_`A@r43Bdw!M(Ab4ha;Su{S +zQ_w!19ty)C1Tykq4{MH#FV*!s^b|j?t5i{!Nr~4>q&N)JV?KHp%n4a!C>sN274tPg +zUp%>S{<}gPQOOv%jtU?RRMk-{=W;Xsu%XQF;v8IKWS%?n9T?l~Z!I5&@q%-l2qIrj +zksN}&+sy{({TyzS6*2^dGmI$*NeenMMH)vVgEPD=c7!d(H9>v4#x&vFJ=)&(czMjK +zkNuI}o|w0X(2@?)=Y?td!@64f{3b)x*9qDCa&?aua7pt_>+SjW8+n-a)}V>++cqB# +z*b@YpVON3P>3Rmq#d-b9$oE^^YC>mb$H+i9`JpFFzAN?RN6Q$UOG|93_xHW(YAKrZ +zP^@!c+|cB#&1?0@n;YC3oXKN>+xgP)eJ~DkjbDPyk#L@Dd(U~P2h3&rYJzR06YmSo +z`6JWsnV#<^{$aNqmh|znzgmv7W*ZEHjp`Jo%?s6XEA8{6c=##ouFIUf5pvv5Xf>|O +zG#{SHSvl+a5(B4*x-SvO%V{T>EaH51fnl$?U6I;FI_o>Lgl(zLUJp^`k}`G;}Iep5Sz!sGRC_tM_)jsm=~}0$|}LYl&-r +z7;*x6G2roA?P%8a`vW;_C0vQ@NMz +zQlPB5G@jYC2n{ksBLDG%nA_k?YuvO2n~8SevHf0r9+vx!b}famsU-LdDWL35p*Ehp +zN9zhvDEV{Lu1<7)L&adfNH{YWXzOV8vD%}Fe&P79z)knEb1_MPdBQz +zn#!p@vqk{_YYr**tOTGE%Kb&yy{)pc!rSPzYh0+cz8oiuZaQ_jx%HGal(WEH*Wm@F +zyc*lH@%wIaOXjNSf)3jDI5E^Wf;dna1JlMV3n{$;5-A^W3G!l^a}ODOPN#7vmZ2FO +z?J)8AQiplXY!TprD|VWMt9B)w`!_|g1HNI(5vkbaQe)OyU}cAuk@>|fHU#r9t-OhV +z9e~PP-m`YYU|h=~SEbo+jOw!i_;-@74{Rpzy$9D^KlKkhJ|REohT+Tf4^_XdY%!v3 +zNae^cb`h_(!&mfpBD(j9q6Bth+#@wQ_yTuKF>c)y*$+rm4NtbFQyBzn{guPRr^Sn| +zV|E3YX3!>uuZ_BCsadY?W53}ky|>)9@! +z*9u&?6cXVT0A`e0BH$D7;0h;yhgyF9jh$3ns+3$Da5E)6RxoPl&WKIV@L7_w@GrET +zKb00mJJq<#A!uZ#A%viU-V>faI2E5;d!SVg&*SrWI^VQC3vV5`ndPNtzItLW-1_P +zC$vNc4R@(zYK+S`EUpO8Drn@bZ?1v4+xEg^IS1n`VGw13VNVZ;nat_1x}U@@i{HoG +zRj{9*))V)hMvwcG5vA)-+<7ma(oKt$FStj`XFL>zx*KwF6AxAcoF8-K{<{s?WC(js +zhes8i)wk#2ILsOlf_sC`+4P3h$>ZyN5_6?*IHk82kn_C2lNP=L@Adi6N>_s;4aDnS +zNrfTKBnUm+l`RktC_@X79F|O}Gk9wRI(?YIufWzl5RSV9(dKVWzgD&u@?kTA-m&@Y +zi$r7&1bj?kf8l17#6d@)L%RiQ!btJ{r#1sOI?$9ce3x>Zc4*Z%db=pcVnL) +zZ-#h#-5OzR#I;cgCd;h<>-5e-W5My|LqxbFzWecM+NBseu@Mj7#TkAkctOUnXS7OU6i-O#b;cLr!>xPh-lqW8Ca@;uEo} +ziMR%w)Yd&AE)NALs*=_!AUokR~)H0 +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 +zUr4yzZ9+!UJdf8hZE1Jqp}gB?Q*3+ +zAx-X=)u3a+Kj+8;>{3AD8FYwgp*DuqIi3j~s%?kb<#aD;HdRxdUU7&L50!qiiDi>hp$O9!Kis}{M0=SBr*Qea}OlQs%a^qG&?g32SU(gObzts`)Uk&(J|W$=#wy4IGmhp-+G7Jxl8lXd5} +z+3ae>vr-^!{@xpxZr&tNMdJYqvJhs}rMuj*!b-y-w4U>HY`h-W)~u +zZa-RBKjf($)1|;>RByj#TDzv3GKT&^xix`R6us;9{)2LdcWT-29&+O)@%4t%j895z +z)$Z-7{h-`w{I=)vfD$Bb|DxRS@f(5iFGK}#<#hCwdjFu@-U=kEXXB$@vXN>FrID*8 +zEiTmzCCDKyD49aXYI2TMPYa?!xJ$>%gJ*?BWrhfPo!o?kvvJ)~Xz>sNCWhmI_dv!o +z1B5{fVrGYfG!jlJqyieNe-K%$W}n%JB3s_`W@$fazt7{;KHt8&-4|ziZyJc(W+m&c +zm%odn()d{KEH4+V62^QJAh7(!XbwHO~BDLo#%6`8sOMpGayPLsF8 +zFhGH#H!~v#D)_j%v8MzR5vL=c8M(@iPF_uxQC5SF`P!ay=U=nYX$AK5?L5(K0;%uk +z=L~3g25Ft_j6ec&6{|LGgK$0Zjh7mDF$4cR#N|Hm)PD#LhN}HN%Gzj)X0f +z%fh1D=e=UlEt7IqeC9($rD4OYO>I~qDPe+6^f8 +zOCNrGNQ{H|_4Gg&b?ijS8L4=OZ-FZ*H*a#=G729O*qv{vC|;r_j-Pf!_zw)BE5v5F +z{Fc=xHl6iIS*8xYVKkV0H(X@y>cH>q+3dagTy8jAXR?6-IbWP4quF0LgK(Kf-*2#G +zLf8RLw;dn$%tSb*U$4^Lazw=>d+Wavb-6)ZsO%xB$XdD#q7@8aRXxPAD`{W2a>< +zK@%>0IFjCFAYKX6Z~#g%8}Pjj4kND-qwrfbaHU6R3N}+TFNjVetC5dZx#q8w(&srP +zgk>ZSm>p6iLtvBY9abTwGjCQm6j!i1?X0U&o{j6EQ_P42bt4@DF@Cyqqih1~8&adj +z^06^-lqYDAt`?a5YfhjJq147vf)sYEq+h0}Yd%VcWe&`i3QELtn==GT0paZpMb_&4 +zJ>L}0^$Nb(gUJDf+bm4juXas~QL>bl_xcKjG^k`S+Ry#ryJ$5j=c)s>2;?qAI$HTY +z+DF2R8OJ-z`AK};i(=>}rmzxTX7}L>nfYsZIjkDi2%d^SlKg;=D`Z;v98&^vm|Mm_ +zBQ-mXAailZ%+2Y0pjVsshFr&uW{l8!>4ju_vu!tdGuF$e1`=xaPT^?*8U`5`No8O$ +zHVE5nM{BN#@gtf*$cN0=O0BNxdj$d?IyDA-|F${VBcOgNp;)ZaWg#i=4Fbx-rJryD +zqCg>A;HFBgEvLM_Mi!`&we}?>p1Q`D4DDA>naBk_$3pMA46Wjg(j;j$Uf0!iGai86 +z5Gt}DQC`f0nJl5JmI{C?CgaYLhN6R_RKMV(Jf$)?4l9Or6K7uWz@ECaunk7`~YAKu#?kBAS2S61>4EdHX9z+LQVS5n}vRrusX%cujK(1n3aaH +z7>q~ELTzFau(kINdN?p9BDG4GtA#XQ4XQ605vcjg7UG6~5a*C{BEi|Sx03+@ +zaV>>h9uWdBXGOhN5}%U%1!8W}$?6#ukxYg&D*B}wMaY16^)mS(K}l+934U*+-V9G9 +z*b(V{*g^DoI+}dWda3vAgWZvZ`XHF!`J1MzswGmfY!9iMu`v$P0gzZu#-m_|p8a#@ +zOtn(!cDKR?Yx`mjx|XAag;4-#e;b +z`Ti9!+t|!JW&J_`o&z(v>BvX#c}+QG>SR>cr@P6!2AzyBLMc`Xt2UDohSY_*&L`ff +z@(sYGY(}ua9;Glrdhpn8idxS=2sG9xDj>^2lg$p|5*iN<3fYzSIh}-=RTNW%bCJ($ +zk60@vo}0|Cq)g)1QPo!I`JsYd3UjfEJvkb&!?*6=)R!f7e`jo0TJ3~XXIcs5IG+{4 +z)={bE0mrb@@H9YK0;R#FfDX(L!NqtjzxYpmMe(Z}#0i*4w*ed}eXYT&trqsaEn)p~ +z7{XuK^--s3Jq?(u3`-?W`Uox{4#$UsE670xZi|)iD~}!v{^{ufQ}2}T;IUY5d{@Ax +z#cK-K&L4}{+@EFWKJpfV)yC7)TnaT=x4Rarxd$jBThEU7+!72u?qlh-$?xie_J?ig +zD5wZB4dcAgs*?d>zy9|1jLFuaxMPqLXa+9hRfA4=7WUs0JE?4H?yy8W!*aNM(b`2<`M3j;*4Ol}`E-1+uP279It7Swff-`kfGo`+R=wrVd +zDg!|tDFH?3S`RM)yN{pXJ&YtvUU_tE&=Q)m<(Aphw%}vTnbq?*&l!|Mu$yN~!}jtK +zyMFr&Uzmp60x5kSwW~GLb(iqYfs`1&1RahyPt4Xp3YABRy^+3T9)fqoBe%I-=Bg#@ +zGe93RVg=_m!ApjwJ<)esZdI(j^jH$2I3ZBgXbOeO1d;R1pc|%kU?1CN7M*Uw`Iox( +zVQC~T2=Slb?DHQ}<+hW9=dpOmL5;c4sfIt+MiQ0hj!{!4>G$L& +z+_5mts|{ +z(}q$+TmO7+l)6)B7OyRE=im;=jiu^vQuW=%Cxa?mr1m5yPW&i$XYz=F$jRYQ&FYzt +zFfpsgLi@u382XJd9glgun|iDd*B^hLc%kQ%O)5Lr(jS)#0&+!{6U;E=jYIb!PaA8J +z{ua_75G!ntr!y6jSEw*H{&ia^3~gjQhfsyf!DbX=H~KubAm^|CsKTFFpYg*iF&V(~ +zNZ-DK>W$nYoKwD`s0pud?7#A3Y*^$n1>AkpCkCQ=AQSSN6?1A+S=RiF952h-*;;6Q +zgZ^&q&LK%naL74cv6kovyOLO}f`n+HcV)BTN%2~(TN7vv4gF3VxZRe4)1dB9bmfsqu{ey3R{ey2){flpJ-o0a5 +zQ(DF@2oj{%lppz`tHD1c3a-R^?j?NqBu|xl +zHjOi@mzIa2Azm-Kk*ti2LGVqXIdMz4X);Uv7+F9w#0ONG7+lh%}6>cE5>PyX_DMfH3GB6()?}mvN8Zq35mr*2Ig4 +zAKbCx9?gkng&BVg>YAghnQ}?{1_cG+pdFOUp00hj?m(nR;7!JwTZY|FFN1DvUk6bwa^ +zp(<5*UJy&!hZM&xTN-{}7%kxO2CB(0^8)Jx_R#Jy^4eQqK$Ejl2-|UE2lIHE01@ga +z5>9v9VURoMCjJJ>nOd3P7^501D);_u)qH`FG{9MFX=63ge0UtzG}`70VT6E-AP%QJ +zSmY5D#!NE^mN+{8E|e~flj1yvhN5fZ!k8=AgYza}>J@I(f{N#>q*kCru1^+YguwqW +zb&u_NKwFrAW2>=kqp{i8wr!_zW7|e!+qP}Hv5k4#bI#0s*}q|5>sjl5B=T^xk%#3+ +zvj{)Q!m8By9NdxR(fX~FNnIq@Wr)K#ck{`dJxF8-DP}bmSe~{dGI`9YsoW|jLATOc +zN=r$Ad0eZc49^;;`YDH&s#(0Qt1zzK!c0<5pag{4S*~qI{9*1m{QvY +z{%3E`n?Sv?c++z0i)f7F1Rs-M&1ZVoJGK>`VI$KJg4d@_Y7Fq$X+qM#WzKH(-QUCK +z+uIbH)xQ8YzMc-m5pf@zA0HG;^TUecd&=GT&VxiaFHI{{b?5K`zXC85Z&-DK3Rzi|--6;sC4K +z$x3w};w8;!^^Gs9huVJ`@(lekbIXY2xmTdQW^-OU0>`p{6wX +zDbyvIBHA(DVDK^%xmRS%{1R20Egt-l9om9^8BZ&#X%JEhjV4gna6?G6mOesh54j#6 +zTdchu@&tGL$j2TN1d$T#@GAEDypz7Dkv}nL!&dx$Nnv9B(KA&SQ!tLbbUl1m)|^#X +zwg}HL^pQbGRr5x3T3ZVX2>5UA~g}8Wp!R +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 +zuN%278BJ +z5DmHS>dU=oeWN6c6XkouOn&=*Ak$4fA>1Bqc5q1pSDdU44L{>xD>0X)^poVH=7qc} +zJ4AX*bDSwOKCNq)c&1B}VS$o4evz?>P&uv>otG~yA?=}~7Z^}roGWGIh6=eRQe$Fw +zi!<=zE4DKueZv#^z6C6wtmlF7i`+V@4y*`5zFb{c7muBC +z^Ydo^iJ=?!Emgw;ZM)+eP(YqyjYLw|=egD3XK?r{;FCEeI6c4f{Ik>?MDm%dM+}3k +zU!e~L+F6|mj^=&|*Pyvh%Q7p23*jIl0q=6Ec+3B{l?~{1jST+*1yOd}J>mm6q>(SsdA;ngBx +zuhtYaoWlfq5^PnCdVHd(OWfcLM9Ys=-w!su9)P(`5Xp@mRi(FAFP*zVxihjhizoIe +zoWq`}o;40P^Vi%SVk-KNxt+3GchN{7?6Jl|ymoYwXfdB$asWeJqH&?K_jIX0nNB7$ +z$aHNAFt;tb)jvz;FqiI#DI3-q%K+wf`+y#JAg8qWsa)W1^o>QL@1&V7l7~qZ7I%OTvbuvt=Gz_$Hug?b4xP!KZ +zF}yx16OH +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 +z(a5@gk^&5D{1%2)M`xu^V?$LH@3} +zvarXJ7mFK(lKKu-teYRueCxfUV*d+~U>9v4vb^7Lmz2z5bl)3Kk0%V~p7I6;-t>yF +zr*e|c%QBL0?9Z^H{o~nuV;^=8SS60Jah}N&uzvuj+@I)NvP{(YzTT~22Iz?E+!Bwq +z%Vzp=m8+Dhq^P+OU#vHDAf*~{{%#zFT5a6m%ntKrI}9EoEjVaP9Vz??4y&LA6*u6j +z)I*euNwqyNWngbcu^q3Bi02ROnI6w=Z-9v=A$7Dk%a@uXIRhnzgs +zu#G1<0JnYUHnG*!MSFhLtu^$N6T*PO>D~3^rM2aYj`8_mrMIis<@(`h^+3=pV7PRv +z_UHDHOpn3k^Y)d2fYa-x^~)#-AR0Y#1H5fLU4XZ}KCPF0@@gUx^7wK5GVVsJS8e6~ +zOs7|#Y0GkGE$;$R@3tI9`w)Kwn-s4>Ta}!rSzebSJMP5zOPrkstZ1YzUbL0a&O`4 +z_=WLm@5xqkwl`L=Xl!CKsEj63656j{=q&)vp59?lY5mvRMl{%0VtBNvyXpNSw?BCn +zI&sr3sRr=2Bf>TX$B>WI*jwzMvPpe|E>fm58Q41|&?~>gsaKdk_%%ULVt$u?H;b9_ +z+Tf)Lbk;P_Eq;y7M9;JU1C1UtAm#_{2{pv*8jCD +zpexcb4QrDUfzEtj$L`Vg{FSra^Ivcq5&&+qyv#j^Py8Uq=)CmK@%=Bjo%3IC+w-T= +zmd%K-r8c;M%ou7GPRZBmo?ex9_OLocjEy3@|CGdSa +zj~i0>@EpEz0ar!Z?UT$jld1Q(BT!+scqC9dSHbSl4!3P4EWV*kf%ZBT`cwb(Cl|b- +z$!NF?a=&6+BY{7Q)s9he&Kt0T2=c=M(o0WtBI>ytSqx5iiFI@9gW*uTwXQ=9@nzbj +zAS7g``guU|$V3Eh3D~203Galwxc~FE0olO?-(3v{!=A>K@G;LWOd$Z4RIDsl|z6RdaAe&y{I_+@mAz8p<{STy)8+gitfoJkrjaiJcf)*EOJRYT*(sPzhi)Iv1s +zZm%223xeWAB+ib|bih7i-|!&Y1|>HQ>Kn3yX|lQ!^^Vi{FR^&|D!g4^iW|z6AL*0) +zpl9y|a|&+HZ|6VFGHk9mAa~)h87t7=zFnVXr>ju% +zDY3En@AbLHnaBGZ_PMEi8a=P{;+SqUVQB?~^$b}E^$7Y#!~AZa=WwO2PWJSlA;QVk +zIxI*Zd1$nh+SmhnmRQ$xIr9~{Oa1{V`{|6Ncunxt&e07KN$P}jQxr-yz<_DrG5fi; +z)bp7?gmYAZ&Q_P1@tje{OBSum)*iosDPsHO+8SzAFF(9!;V2gNXXeCuz`&ng;sT}A +zh(fOcm0vVuMYl@hFh5L=#P)Unt^pB!SjECNw&;L=d--lV-lwBe#?a*z5>BboE=SX5 +z`N^&~wdm`O$v1Kh6RRzbb$xf7m;SiC{Q58X!jB;^OYPoRe5c7B{^6-_K-s)vI^_Z@>{p0(d&?xyQAOQ7Ey@}6wV-dj0Rp3es! +zCz3H;0HU!73|e}1q{kQ#i^#RKoSOgAOWuSufU*BWnL+)~ShE-rqWoH`FQ>`4sqgcv +zCKV-+h@#+~6cgE`^1l1DIFzmqT0O~+hL}b}_1Kf$vX%HeC-_lft@a%U{L??C9VcE6 +z0*if^zrcX@Pbu%8yU1qYiA-xtx^MPZv9aCI3Gc58m(Zb{`2w +z^jCWO{=ypwaLjH +zUr(L2YL&?mcrPG1S +zBrI`VdQS1O=Tdw8Ok-m1AAH|iSL5BkyIk*Dk32N9eQymtY`v{mC#mw}r=dXIC3MY^ +z$^%S;C-ogrv(+KL!1!$tnZB`Ud+JX`5S|~bUp7Che`NZmzjILPW2_w+uL)5I<=xt` +zFR~qG4-bFbkF%v0U9u2wP;Gz5o0cEH3ioucav55cq|Nj7@Ju*QA%MZFSl)Yi%CYL= +z^dKZTV78I6G02n~#h(a~TgSk^_@gh13#+INH}%K&u$gUIult?gYm{RDDUBK4;fu8E +zx})szw6C)O@2r?Y%w7D%k6Tu~c5DW6`VJq`$E`^GE&tbLw8gJa-EYWLK`k*bY2wc>^X4J3cSIh?bJEYE>64vavO21nrrp91|OpokwNstD-n0v +z?=(Ni1_tzMjPn`la;@JoYinrnhRBqk@94U9E&y`-2)+&7`X_(z19K$k7u{A8M_WpM +zIw^?4MS&ob+`CQZ4{-$qlPi +zlVu>9sa;B{;MZ+ia9(UQK<+X9fz9BY`uHrewn$I1CTLOS3td<83lOSPgAeq*>ET<| +z3so~@nD%C4G7m3DMOA#hPeKmChn$JcWG}NNLIel3zo;jyUD>B!Y%oPF2n7BdWRhj& +z{9!SZ{TW^LoECU?FYd!iuUVdOqQCO9ANfxj_XDe)or_4ek+!4t!Ci1>Wpa=odGwod +z`_?)H%!NIHq#%-)0CV4uPSuGT;p!E1aQN8KF+Q)_n7;9DB4-(#rtlewf^`NJAvqyOS>2`AELLK4kr(&#r5xNH&rfsawXJr^|jM# +zzw|-p>Fvgs>mGFJ^D#3!k3{-L^&vjqf<#9{3(~dmPWZ9_R +zH31=Qos~$!^|ga1{~MM}Lo`cSKi85f1PS%gq#N{7;PAMLJ+?BT^m7(-aTqK52=ehj +zzH$@syVO`t|Kq2V(?`#WpJk&28}2f&k>#n)4TiYTad44l%kPTotd8{?Pn*%H`?~)6 +zyzV{r4J2=0q-!yC9Lrxg5>(GdUR)(0tOW*Q2il&Wb&YHr%=t{(S_CUw1&uYXKv$2P +ziWp1Kl=yHK#$TSB3~DvZ8m_Vlw2)`0xLi;kbvUT|A6)%2<3>u$#kT`~A(2Hv;lOX$ +zg-ne&Mjyn3^Y1r5w4i;znl2Fs>fd)+r5jgnX7Rkaj&{709Kk&r`%_^lSKL?z|C-zA +zzU*Q9Z^P25Qg&Q!cMIC{*FMLR@N1yo+~;&oM>n)69|7hzja63|)w?^e%begdz}#*> +z|6}Q_E6R%=>E)oL!z63^3lp+D0UYvxnc%k_bvkgm(qwDl^?hL +z+-8&B8FUWUBdH>O5eB3=>znjU*4f~1-8I`UU4x?^Jl$tamUG@; +z?+tDwQuDr_)Jm|71~xax3~!HeIA&(RrnlKqZB5;GDWBdDH+#H1?nz)T#iqytePJOC +z*l2Fhq#t}uA$sd8Z~WRBZEh-5e1=}-yfEIoR-Wp*TVrZG3PnQKyoa0&2_e8pFeO$4lNr%qwmT=^Z3(wI*)`MgM`+}bp +zvyeED%bf|CbzY6{$l8@su`K=s=#dx0w-I7Y72j~JUM&sxsX>Q#k3X(8kUuG}P66t+ +zS&QA380ATa_apLXBE(Qa^V`7qwhsswX#+dcM_Ueiz8#Jf6AyhcGGp!s7dheb7UK5M +z#Xh>LM9^@EdN|(>hWjqKF!6J*?xR2;W{Shgi9@AHcxtdwTnXqw6;KTyV-KNfM_4h}Aa<>Q$Z{zAtqw(gG*$ +ztvz41_|8eq(dSV8S5mfB_0_K1R6N!j@qW5)>;R9{<+(9<+68Y +z6m}SJ6!%*gu!Paee~$ET+xR6xQCK>!tq`Z8%H$&PZyz)T +zldqT;Ktma*Yurl9{Xyd92f1c0~C +z{&*lHS2Jy)nBY6%!*N<8rAC>|qyH{+!-s(*Xk(-O10T-D<^Eu_u~So;MdP0|jUJd% +zNC(;FD8{-;5j`jqaQV~TGRcLPQJxbch4AHp-;wcyMAN5Oql63Br-xdC|ibh#0chg +z7aIN1N8tGNk*HlBFZNs*q(V +zhHu)E$dj(GC@o-q_5GogXiAAR5DlZ4aRCeQa)(4c!_rkbBOy7m;`x+s%sU$)xKT!X +z^7F>S;HhLaF-J=b=wI4fq;bM+SIF{UXVflAi!_+$bEAq=h#FJnpF&>nn1H%=j(gJ$ +zcukhroMHsUje`1!DDEs`SSZ*ay~V4*oA`Dh$?$*hHu67s8-iM7698{da_bgK`9>Qm +z4LjS`m;Mx($UaJAIcX`>@0Y;#6b;?rp&u$;IXrOD;|K=8+Z}(HPW3-zv@_I2nNk^W=ThsKsqMM_~q?gN(Y~`gcS2MU<^ZJ?J+l> +z)AE3CwSzXNbZ4eV%v_FYm+afeVH7IW2kCXkgsCOP&;kKZ`}euN$WMAkjmd{t2wi&b +z4F8$}_RR>18NcoCPI<>O`THZEomA!91qGZFyWJbS6zCa5KJRb_A^d7 +z+TiR2i`|g5-!6%oM$UK!K63a7zI*KjkpmyDG3il=&c +zd+~2 +zo$UvTkZFD{*Lu6ns)AsC52wCnlqAYFCad>K64N!6TqDnpT5(EIKW?@+pDL#+eJE{+ +zQA=Y9*X3dZ*%>VxA)&cYgwgDcIXp=((nRqK8}4qkCxF2)Ty!PAgwQ@2f2Ap +z(n;viz^u*-FmK|So_jTccrvKV{>s}Us~t4Q0C`)Rb7)4=IB1$`NhW(j$fdR11J@n3 +zFjEKoaEIJm$NZ)xs{CL#2xaJ9dpabf@~4Qrb&y17LLf3%yo&8*86lAu+<0jyoU!@v +zY_8CZ5EU>FP!I6I%MaM;D#T(ZShuMV19|*LTrRv{Ig9V{VCCN@o*Y`v*!j7x6>lGO +zY<@IFZ|d9(-mwNoJbLw?I2zU^f?DQ2*h|76OoRRi>3A59$%#)Bsuso5uMOvN`6q7| +z{FS%yyB~ls0rK`0P6I&RhOz7dMOy%!`YUf=^w3SFxsJ0XbphmU7b|W~fV>?gc@DLh +zn$-7K-p;>f|0{1txeu@X0jXFoIJBo9VR672!LDegH@n5z@Rx*Mgb$8Z +zIc`GEqBT3xW~^%N_!?&>QY#Yr-QxQ}WK%eRT`%lD3he*3h0INIUsYg2iQF1uBW_)%OMMXe?3@jL1arH=xm8eYaBcj0|D|v +zBkkL}wlI2P+fF8GVqF(XCw8DHkPhq=YxJDvHV2Iz|sF9>>ii{YqYIV$F^$F`G>Z9BQ?7ki(t&Z)ZpVXdk)*PP=Szj1BP9V=+&fP&2xIS_;! +zmqJj+LffagVCcFm`}|s&efkg#5qiZOr_ViZRBXI=mp=Morbk7sGbim +z8o&M`!{k~Te-s4+RTP7-N`%P+364UcQUU)Co0HL43t12PnbDkWjaOT|cgKl?S>-oUC#8(7M=$sGjkN3 +zMSV|4S%L@V@>?M1fQTog*ZmZ3Kw<2o`!A$#MTsh5c!4-#s_!3xZ8)$Na#O84ef`IW +z)UG}@&zWuQ*Qjp(+SoF2e61wA}Qf@D7{e +z;sNaVzVkM>H)uFrhYf-YVZ}G)ujhV(w2&wym0zS)GvDw{&+~CmTW_x1d#qN!mA0pK +z(R~n69cw>(e|yae7jC`(*2zvw{G_1F2K08m*82G>J&Rp6@HGg2?!>jHJrrOqYM{f# +z9gdx*5P{Asd!`tjF6uFL-8;QGwoZr7lJb2k>*x5^iLz<}gWpYK!VSA +z{DQ`r(|?r(E<7^LcR~`|9JUXw#|4@1E=iF4Q%t12?pwM8qz+&)Lsc~hHCXw)@tH`Cz}k|q6A;5SyR}S> +zplV|T|G?DxJizt5g+aUBT}P7NJl&Ej$SKWv*c +zuOs2`Q@*ip6nLAH`|F^^6hCJWO4s?{KZ<%GH5TGaYEfA;0nVAm@ko0b1pEY|rbqy$ +zAxj)<`6c#Uf7UDOIy8&$w_HE*e%=r$(7*LF3R61DLIb6X_a5%XAu{2j(>mpga6Sm! +zHcuK&OkPLcTKOle{O(V%#SNK%xaVfN!Zwo@?5Q`j8)=9Z7smvTmTsQBIgopQGhkh} +zkj=HKQJ&L<9gm#f$aQ*#lcaZP8ke9(qd%5OXJ6b?a6fpY{Qw06bZuo5Eht1po=0(# +zH~q9RAzsj|s$!nNB!kbKWZyFcQ&>Ke4AzUT5n;x(Z^#ai+HUlM;~}x-jD&@Opk`@V +zwv8va_JUIO>;(bpCHZZD3~ynK_)%65oz~^Nj$8lp0eyPhbT}HPLzKzabe+}@3LDul +zMm#^5Pr_Kum_N7` +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 +zlt#}v+vwe%deS)HBaD>#lBS@wX>|QZ +zc5IwQ;Tw1)77F05OevHXj*|7KWZ80qlfsGG+1|C@%CnPh4Ai~Qz`C9$gKWBwy<2M@vUUn*Lwumy?mec>WxD=@!R8; +zPu@*RmRnerOwe9ftoBB;%&ju!PW!MtG>-fUHz`K$9+x41fh+wRQ#!oQjd&Rw4 +z?f!*-h +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 +z|K5WH%#Ay(jv97Qv??)?!efA}Nb)W0v?TOPAO +zw}b+K6+?S9%lc$kWO(z9nA@6}#^Klx$Ab(Tj57%Hp}QSlGjG7-pdCcGu=V@bjmD`)|&p`~9H9Gb6@tAhy~W;LB&Uw5yBa6AQdz+_d@3bGCppyC +z1!Iv6nu&xf(nb!fWt*4r(u&S2;WJn*!ji#LSK$KU%3dN4iM!gFujXxe_iU2XbU1v9 +zk_^6A7F3CVey>aec4k{W{C?lFjYd%4$b(6StJ4j7b6*;J-^j;(Zt}ly*qLVQ?>=m`KSPW^l6HD}`vI~dy +zPZX)e4I3gJWEAQHsKu!1l`D=(_YI|zb-IWOg@HKv$sB%*gQ@pEq1j_aC|AiD#zPa= +za^b|_091BZM{C|!@vc~q2N!jMLn}LM$M@Klp3qb~L~8u1NfMXTUA4xi9<*NK*l4bB +z6|EQSG$WNJ6-4;7Wj;fhvy?6rm)8fdahMO|Yx4JVh%2yaFFFO%)urH;bcx4Y_kRFH +z&N$)3CM`%A^tH +z?E)@!iZIZdw%)v7-}}j)$CxjzqcjS9YxFvEljq=J1}+JzGd0a#B#L*;nK1s#^0mT-^(MUP+&zx>yMeAfltSSU>fuauyPWmuC82tLG2AP4ES8EBy;^!~KD`_28K( +z;!%dykv&SdSZbx%26#FjOWQn07~zAVIG?*t=80Kd#>+jKBGl9=hVK5r+bxS>sRvoD +z`2#aIJrl`s|G)4y1n#Tk|Ax1{{(-l#{tIt^q_Eci1#ct&2i~s!5#(2A-#ZphF8kVo +z%VWBw(W}3C%hx-3iVZu?)BxH^OqrJB02DWILciDUPC-TlTU?Q`4U_^Q$y?(&d5wAM +zJq%Joon@5H+wdXGm>-k5Vi2)2Sv@WYS++`apVSXxfT+{>uIAJNbE#~_s0lcIUyO|A +zm&499u}6TFjZ;h{KXUCom^~aBK)1*Gd!MQ|+Z^(0mL<(dPQFT!THkf5;H)RUIbbFB +z{s4dT+p-|&5sdh=(|!AnLmNgOJcVQC}Zt|Yawqxq;vZdF6`-AMR2sO~!tx@#wQ +za2W9AcD=u@EKTP^V#jP6m(_QZu(;|>4>Jy0pPO1KMo-HjY~3u(obwo=PG6R!4+|A& +zVT0x@13R5K)D%`_c})0%7)yrct!d#0mI=LDz)x)J=LprkRa~Vi(Nd_+a>QS5=Fh0b-%{DaKlTabb4 +z`_9j8|I7|m^-+q~VC=-DDIdZeCsKr~s1txUj>ne%aC*oy8$@AUO_%kDu*n-QKEvQv +zV~W*)+t@2OQoYvf?`AdNj`~Pmt?jv(dXB&KYXeVoh_{kXp>B{^(SJCPI-yuL%!g$> +z^~0Dan?&Z;AH|u*25?RoB-J3yg?J=7Hh6N +zl17W)x+{;ZY1ITuGl~E6uqwskjMY;Jj=N?Kq^<6NCYFX<5#aOImsN`%zIYYHPnyFr +zO%YTs_C|u-<|$CC^u_L@jb<$0QdMlNio3!tNB7d8L|M;e$#}q<kHn_`2%nJBV^aX{q!d?BS7e2Ft?IvA0+0gr#oo+4PFpF +z5*=0X##F&0ze6iX6EqFcNR9QpJRfhf&=_Ch3N%maZwRI)l{d-K$0N +zW~!_ivd={E0Wk2%xU1q)uNlEn&P|$GGu)yU0ww+b*nDCaYC1Tpht^6iP_Q%rKdq=y=~u?9Xf6&IKpC?33b`z-^bH7(ro`fiRixf|Il+ +zoMs)<9iUfRbC<_n5^xO23JSp+d27GgZmSB)Awz%AQhzrY=OXeD@BEPO+z+Iqc?fE| +zf8PsG_79t!tjE7J)@v%uMRQ9uDkAGttHcT5JS1wfBNe@b%bHEoU|fG-$D~n;#_dK` +zp(;vb1r(OxBRA~#I5Pcuj}Nc_-XGX>b#0_FbYA6QNT`*UUy*H-N|JWmt)H`_`9uJl +zdQAAM+jJqxvBfVBSXhT%!z2qz`Dc@1YA<#NyZSB +zWT|7C?yHeiP-Su9(rZ#QB1Zd_-Y(+X;be42(Rd<7ROuO;@JtnEqyYp0+HoQR7`hH$ +z>fd6oTcN>fJABiVBR1pD0YRoy`pEq9%%S>Yj5&0bn+0)EFu<4X=auWY@sI>CwXX`8 +zVa^uXV}Xe1#hfWvI60kzm`{!cZ#n`P`$>DZflHk=2PDfce9gq!V>m33G3$q)c5=Kc +z(0gx^LwRFwTpBIcUw(Q|ck`Z-4t&Ae2{qP$dAe^pOu5io2m-855KQz4 +zfs=})yy=DhucC-6mp+jis@6EvmGDRzVsg?4T{p4t-1&RM!GoG&tO@Kb0Otb3Hu2`> +z5)9h0hj;}(p)8`YcgSyW>HsR$bQFt_yJdWcDV1%YEVA_nuZb0ke9)^rYr;W$>ALm; +z`=@i~AQh(^EggJ6E367ABaI7qr?WYJh-`mIBc<$ywI>_)oEgojs2RMd2Q~jPdiE&@ +z;%_HE*Hfd-w7o}^rwIC$0BHo(7IZ%>o9GAxQ)EvCJL@al>hV#n?B;?LC^J2uw3~PR +zyaQ-jDQ51L3j5^!wGYXPzV*~PXjve8doqv}cc#nn0ZQ_t +zXc4LbBqq4k%oLM4khHYXF2;$)*h3=M07ewLXF#BiL`1L9^&35#Q;?5Jzn%yA#*X}e +zn@?f%YUHLCO_1S_t+Zm|H_M&k!!)q`U@lmUVfkFkNbUidW`nr1L5@b8Mcdbc5eP}f +z6HgK=2Rk)V*1*IHlAaJZ9gWLDt53&dF`OgD)p;lZBZjUTM +zS6>lGBb^L9Z9|cy!Gc^TKBXbQg;Hp1=dHJw)`NbiN^0;3M=EnFAKjuovJZUy0A->$|@Xq6H{jG#)_LyE1g(*1h^94vaeYZ*AaF8J6bF%sap +zLZA5_Jm=^mkEhXgG236E`pTxrT>dJ=or1A1(D*wRS0Wsp}1U14uk-)Yuiw*40usd&Gi-_6jW&xgZ1gvyb +z9EvY^+Z6|B?DGHu?F-(v|AMzi0gWFjY6*b;fwxg)zToWBstx7vn_Q|Asi~RiJDr +z9s$>OMroD{S%qE-T +zmDo1|=YFVs2{75*0@#tC3O?fU8)#x0M(>B6wr0{vVcd~KB8-jamW3q)>#&UJJCw}d +z@HWiZ=@-1+_!qpbUc +z&SAa|JUn`(QD~PXxV?<2u;1{Ip75Z6l)zNL%h8sd3bo?Pq?z6^h5wr?XEry+atz(f +z+eB=;1%HOxHzem%;!W-S*VS0VPP+2JSrxv+;As!S#p{BVA(eTfCVT*yxQH+!Pbg#x +z^_qSG6?@SDhaNodk(~35(!hH4-0}QTVyXsfUO$4_8Fh+gvi+L~ZfX*z)oa6{a90vY +z`BhvNUaLWpYLF2Nu<~>2Isz_nG_a+LJh=u2kBae&(xL-oJdmdZd4xJOCuZbOoFtIv +zU(9%S-H}TSh@%O^gJl*qL*YsV_f$8$c5wo*9<+G?9T1Gbg)%rHuf?ho-{8St&0((Q<{c1u +z4Q^q_NarhZg-{+$JYL@Y8{US--KN+o#Tp^}3*LUBMJc^T>jN@NwNaH*6#0U;UEWEP +zV^!H6^ORK`F=Y4>`Me~M033h0S3Gnmy4QF0AG`dZb`FxtLwy@4*5FjGR4q|*ll +zy*u$A2Ww$A5vEVrfl=569PExXa{3G2j=&)xr-={W=XnDCg11}$z}s<>i{Vnca^b=T +zU+}i=x4+=+Jt4`4c+EsuW@dI!cg-x5g|&8T!adxcndhK!U6|K*5x$^4YjFcoeR$0h +zQwcN%;IYXJUty5S{^n3X;WO+pOGLI?*AkC*uDrl(^xwC;OthpJ^GqWdzRTrrQAVsg +zMCG1jMsZT}B39_!qQP{aNf}8la^s%P=~|J4mRluqIn6nUevF^`tRkke(Fqy6I*qiD +zPr?X7ZHPocKcX-bqQ2?JF~*R}H^b@|owp(38Vt9uW6*h942PPo1;DkC!Bi!ZZw4y* +z=bmJz5xF`6u69ag29O1|G6Q_GAW%FQ&TdI;GOPX<-kzAnVTApHw*~Y9ivEVT`J(=U +zw^7zq@vrH<1By^c-`?B8&a?4F8+ZX5r3{5uT9xVSI-gyjqezYGUd-F+yy#E=fwv_B +zzToXC^nc)Oz?mAC)UQILFL;~(j-r@)?hD=?hyNe&_WY#HKk)WoHasT^LiRuKHk{cP +zyuIRZ9c?TLp_=~D{4cyM{1?0}H~u%go#gQsyiK$(jTlglt!3h9OaB+VO>V{m1VX+_ +z(`v(xvu9-sd8IEb>{Y+fAfo0Yb8(j|yF$(b^e +zKlMC|qvSNk^&r-jhh+w5BM0k~g$Y*z5^&ZMA_RYtOq`KN+Jxa|p@IsAWygyjV$C0| +zp_$+`V}KoyG5HtXPT~F!ylv(H{0H7H_!r(bqQ0Q-NJq$Qb{q*}*!iB?W!_lcqJftJ +zv!aaT6IGV=tdY2W7D$K*P9UKa7I^Jl4$ZBSD2DHsC86W;BmghhF2*GM3!}QeH0T-( +z#83HNuTMh>Bo1T?M+U6} +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 +z!>vBwM_iw0P1*`KDDP82OjI__wgz!9nP81V +zTs|p|Tj=6`rJ~Ev=Rce_!W0t?-@(eoYaUJFpF10jiXj>057V8nXFOjKCG8rILN-lk +z92VlayX&v`u3n7RSpvC_GlC@ReNv@8h>UbAYy-H!Bpdr|3ps!?{e5Lh(|e`t)~ybo +zMYb~kAhJrKR?W{7!KFa~kRm!zc2gpLwNm4kfERBHw#V>@9$FeMwcIzyLpv7bfzBHJ +z6J^`l^hQ-(Tw(dwR&tL(n?>IL@vngf?MDAAms*f|hT}>Wjm2_%%jvo5ok&^U&JbA#WX3L-WEYJb-tDk8^ZE)~RWzHpA`4L00a(OF +zR>HbNQ?NLSe*|f16t$$Tu=G*!to5~>kG5_^5WtQ_w9ElRWwL{7FuAsRx+IJ-=-LAf +zhc&)Gi>R8~hsM=AsHB$Se%A{b_VJ4BIwIz +zgJ*(CkTl81wFxHZyF}xwxj~Mf3fCE&U!Lx@N#kXL6T()$qBf+nn)5TLbCP^@ycN*g +zZB}%vwFArFXdC_K#p24FjJ$eC6{MCZkt7%tkvpn+E> +z6^m|eb7K|S=1u6}6AkzTD*Ppp-?ggRduU#L^6Sf$+J255hnxXPn79|nA0yw?<+TBr +zW5L2*z(5eU&|>Iz!96YTbs6Pbp#_y0y42>lU!`1f)WHJrhi_?nMp=~K +zUJz=wL{-u9d3Ej%(&)paXFkAZcj1HL=_GTs9WBQlKu>{y=xLYS-$dx+w&vhMHX~fZ +zd#%*B7eiz{y->R+E87V-0?SM<52A%21)P79#i1A&K-eFgeavyu#sAG4Qb6R2^E0q7zMB$lUf5sEt1A +z?eY#VCVCZ<@zYz3d*3kP5$AZBKcAi9xCC+j7C5TQ2rcUc^m&|<6@pJaw(ZSuNeP5OZ_2l*wM7cSWe{v)l`0%3ny>5TAa^EQ^KYL?M +z6>rA%&s{a^ZnLe`OfUB)K7V(xKUEGR)e`IPI59Fi>-(OYf67D7!MWTktDkR`+y~+S +z{`O1gIxOSM@%${PJu86mzRB?D!dfjyOV`GdD2o +zmDmflUA(ikKS0Qy*2Ci=#zH^_GUe06yZ+AL;sr;<=2+saomPvtCv5l-)vM>=vO_MF +z`!=*0{$iUx)W+j?e+$h4C+DX!H~xn-pF8hA@HQah=YPQ43qSBSpRL#_GwYYm(4CIQ +z@+IO*PF@PKn>|ALOvx;0bE6pshm;gew_jjhOISKYRxvNbqUg}$*~V4cKk)XptS?S- +zDYT8#{I7z`{I-|YtY2AHGf${#Y}HskCuBg~6;oqKq>(m8_7NYW?zTU#XW +zhhcjl=Oyl6e~%OGiv*p-1StwTqL*pV;>h933y1FI&o2|`%EbOj(1~$d%5omeAFsj!5IWK +zYat?%aW;>EvQ8&{pU+I}sVDVr!=r}cQ<#%-yW8Q!}QJvJoSuGG!YaLH$YK9&fAW`^urR_2~*BZ6R!D^yd-SvH# +zD8cvq((a-bbfOPokOV2L6zc}ce%bJpN65Gk?+Jokdr^3d&O;|TmFJg?^e9etg +z7?9$$)+JpBSIAD@4C)LSI*;iD?$gm;Q8lyOtq@^I3)gHt=FCz#3+_R)1InC*TSnOn +z>qLGD9G{(?Uwv%;=AW^UQ3UF1w#h}6s2>xxtVFVo+OkzA;&~)@IJu!c7k`YAmW}n= +z#aH$dq}?ty#J5s++z^Pxz4D=a41m{&`Kwrq3Vg0W)FLX_YTSecuYcimeP<_u5x%hD +z@o9L=>K*!pXA-wzey97{&Y?)O4LKC?#V+Edad!tR0g?83IX6mgf}iR}2VdZc&C9)| +zD)RxUD(cDR{3?ZDZP0XR^Q!fO~a$Iw2@2psjB +zY{r%`m(-8>)Z~LS$#>^-`1%vq;?H_mK`n@YH^AOLZepJ;0Fz6s^bI+}+8Z~i_;?z5 +z9*`q7BW_S?=;4HQ=FqYvWWhcB)|HB_0+aG$l@z!NZ3tYTQP+hV0A_jJ<|CMyi{mUm +z*8U^M;M_-FZgzh2djOW?tJCV1pY3n_bVLPIwz1HKd1Er!ZrU%P`s2-R6=?Rf!>%L~ +zZl7A(HB5b1cQzK~k5Fu(OZdW#a6@50dtzWvKN)#(g?xcU`S5J38U2=JGEFe&04uAv +zb+4wIr6+&}TUpm2qb_}O3{Ma1vo{rY +z42}4H6*)#({UE|pSL15^;++isFAM73>+RIf0QXe>uD5zLZoal6{WwZ@{qBV!HFER9u6E6t&AWjf +zK3kXrKdFyv8$*;<#r%4?50A|>8B2#Roi|xPzixT$xPcgI+m?2(KVH94hD{`G^6)l4 +zZi=}yw0iWcdOvRD6r8rnq;Yr}di0+piMQXa{YQ^oTcu&L%=^F2-b^(YpI$D}pQyK6 +zIok7%-TtDJ=vOAzRmQGF9J2GYrnmw`Mj4+{cZ$c_6!o!-Qa(f{^ksFzs1Ar +zk_!A#W`^wB8X82`jpzhP^u^y8thG7$!2iwlw_OhfpRs2NFQn(DnU{v%?vOf{LYeRd +z?_MD-V&?Nhb((L6Pkd^tUCQ`1?w#4)Qd|cfYW;?YzgPKyy5J&__MH9 +zU4eo9uR#X5V%tl=Af?P!jc@qZ0PcXw2SuN*_J`F8sYj=*&(K4#UPdwB%MBKP#9>F- +zdm26WAV_d*8uZ8Yk)XQA`DiS|Dc`XiSC$6T+8hZO +zkf3t#yp@KNlOEqY*M1VAW7#@@RQE;_>5fq=EAz8V#)o;ob-}`p7t{JlYCi84Qz(W7 +zx^@tRQ-3Wd +zfoyZd;J5d(wpDh4Q;eA`2xLX1*VK+e-UDM#jI~~`M`wk?bGCZ^3B*RTWAUD`dr0HSJ-kr(m*@*kL- +zMo!i6hP~tUN13Ti;P1g{vl=yjl~+B;%BH|xSi9o01jk2EN)U1C;NZcI471u-9d&7x +zr{xd>tD_}b;i2~YbQP65KSClyqBu7VAFRx@g1Wvb0mCKei}N^0iC*7S#(DQS=(#Tq +zdEtemYed{@I-HVhh``v17CI3E^Vi_h?p8(LlYw(&2HZ>Gk7|A@;Ec!Rdd@nK&()+m +z9|^kQ)vYHurm^s$QEwL{C-KT&PV~I-q&gsp7THF&h8rO9B9ZK3pNu_LBNrrSKcJz` +zInYDP@mJ(Om?>1?0sl#_`cxT_zO(LRG?FbD-0A&3H}wKj22ZRt=c3`9>b3{PMaK^2{L87T=Dwu+2vPIS7Ny0d#Pa*x$Q +zr6SaLk%{O^>0>8s>%QQ_9KTqu@h8=O!#nfZ{l)PVy#g%axf|v$4X1$dN=}9Tw`XZN +z=-w(Sv~Ev2e+#i<@W-nH&^U9}~Yp*f9oJ +zkv|xeCx4Jn{)M@EDIEKU(J|1nX&=ZRsa(wI96id9?wTrL&~uwKA7WWG(s+sT?i|UK +zvMh||Sk;fP2ke1b8Y0`Cxe%-db9BZyc=TyU#b{8jY!qlfMpFHe+pz6`&Yx*#Ja4um +zfaB5ZRktJHS;4Ic#AhKE{d7LhX+?!1XWhCIFTSG8$Ii +z8Xl^zqd*8Z7ZpZn@JmfAm9?o=G1 +zv_*rW0bM?Qs+<< +z3I{wznqPqR2y0`gW0LMrGyvlncQ(&Chv3W0sm>ckhFE-h@2er_h1VSy;OMwrP31rc +z=hI>J$d9>oiajC>!I0Vywy3!KVRDV7e0NIe+(ps?T;Q#W1o5ryk4L +z)S$NO6zP&g&a5nT^$QOi50uipIv;YgS|44D$96x_-F-JagAe_B*RTo?(p$?=<(i}* +zcv?RttCI=?9RJh%7cMXu7ALq$x%$aRFE{{)KhL+t?%Lz7v+eG*A%o0tQL1p6aB*X% +zK9gR`&yn1N+vkxu2qdXKz7=RA&krArbGMAo +z?<-{n<$&hmKTLHNPB=$uw +zVj4@kq4MS$A)Hnd;~2VHkCi-(h{Om@S~4TCdbnkWR4_J(eG^N121N6tZj;cZGyP9> +zTkA*N9{)!13L2<%(uNRCWp<*&Skd14HqD5qR*qHL?ER{=&)iSC{T%|?UFc5%sKTUy=lsA^DLtNG^9T)bOb0md +zLd6M3WNZXIK9X{)+~?Ew;A%XVe$Jn&j1RddD?}8478cS`CL$|<&7ZD3mDR7Tf_u0U +zNPaZlj?s+mLUIiLpeRj=J;JbV;+0ggd}Zy?kE`=vyAe3`99&hL!}>qyHcWBx5nf!& +z6NhT5CD=eC1x|Ru+PRRM=^%myuII{H(-l$gO+5~mqLa8J1kmq +zG;!)mGH=;mkS1Gzy&_)?O|>q)*8hoaH~ts8y~0qYW7Hlj(0DRD|vtpyM5mIRQF_N)VwaQr9>cE1YkG}iW*;0&MMRsSmdBp;E&+VQdrC8-+V^}X#Uft(KYsq|b>cG?#p!Pd&Q +zayT_LF}k0H_gfJlG4%N5t9-r~5PU|Y_Zk=RH8A;QP*D9-PW|A5?IHVA_l3(Xx+Lb- +z`1bq8HVXFM^5^ZA3!Z>)hZ%9-c8||{Z?B0@P_srAU#6m);v2oWQBo;$%E%^_wGot^Xd7Tng+jPrFAh^Ro>K?DqZKHwZap?SX +z>GPy+FIA>>1>BH=VGJif7k&W7Y=2c)%{MKDB1i)M?C)m)w4>cwdtRkdgPg&3;44qW?F|a4g#I98(V`*V>a7zAL;p|oZ8NR5wu +z2>w!cPhX_=r +z`ZT3@b$6t*dkBF6$!@h+rV+4+;F6KMHVOy429bXMu-kk;>^8RNSL#@+7*m0*BKkT;oIj7oxvD*Q)~kOwk#!jsdt!QSu|IPlPE8Ke-DmBy)J#R`Bj=S{&g{DFn*GT(84}6*VnBYxO +zG;*Ms{cF?=h?*auLV))AC_vixHDQ!Rl+LZlsB;C;9X4YnRC|uY7|k0xnsuCqB}A@H +zHFpRMkemX}84=qgpW|JJuAJ%zMHo~JZsiYzVx1MK9J+Vi3Qlf6FWI^EwD4e@LhI@H +zs3nsC)UF<^3VCTC4d(#OECj|6{m~n2%VVO7jI=~-Ojy%1c}PuzdM!;5FBE^`OE~H3 +zu;#S5P~uWyZKu_HSo4cZL|vh0FPavra}bnw-UJZqInn|ZowZ$N^oj^cG?;upviEX{ +z*YbM56t(1GFML0RmyDuxz=ki^*YE(b!@0#Q^o%YOl>-bjDF&lae851K3mB<6XX%*=ythe0Ilw+bq*bdkq +zmaN+%P(v^KZzbnx;#-?MUn%U~OKTuG2M>|UUOZ3G|Cu&pCOxw~fbP+`Utc@qsjcc( +zU^A+7+%~P-*3Fzl17UqC0jn&2G3u2f$RX(hxpdXB<~`)bE8^=7%^sVS*s9&zQ}5T> +zO5?Yc)(4azaf4H~VqL2vY6tbX5f#E;(8xvam7!hrek~OFwG@)@+(f0Pm`7!nwZ5Fv +zpDu?YrDOq>qt82DzrK5Gl*a!V(9mRBnB{v +zP(S^pb&!E%-eyG%spKetZ}3}s_Aw(f8#9|$S|A5M`!#Nh8}^Y+h?&5(noTz-L%$$= +z81g+>VxKrrc-j2@YP{~^QSpn+<}*TZYhVUJr34Y{NkLJa$xr_FQi?Ic@HO@-q5(TXtA3o=zwNK?n!2 +z+FjVYJKzday!J?#XaO)9rEogwYw`(-ONn<*>DWY&*#yV`>JS~v!rl+hZ4rBO&Sn5^ +zGdl%(dN(-LW|#hYtbb;#HZMXH`In@*Sy`d1V~yP$6d3201n~3x+M!7>t0xE`NU?y> +zORFwR?0p!FHIob=K|!gUO3!N%M~0VcUdp3obRqf>r-^~Qq5!<;dtUSpvZ%=O4*TDShO3vJWcqeKg0U!X&;cw?*nuzho)V+ChU_pm6b_v3inaf}lyc5zmv({z5Sbk>z56SXu3q1L(=D}bY&QNtF;LI;k9A@Z1J +zK*~-=e&KNl%7YmwDFH#bXT1nE9P%*}J~&G{=1-Yf@W}^}KTW=dePiD64F@b)yV1_M~zk+@5rU_bN~8(?ZnS*Km{HmVV;@by&p6O3b%&+KIOJjV%`FI_Wz%%`<3G0X9=?k;U~&Z?ZyKQg`r2DzIX7c|a*I7sF7*Z6Rd?N5bspulOP +z!i>oW`W?#}*Y8Df&!G>Of^!0P5P@v9XXu~?RyW&B<-wLH4pMZAmJJ7xbYq`3oe$TyDVZ&%GVi`5Xh>0!6(Ad!t-S

Z%ZJP!cQ@D4&aGnhnx6p +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 +zK83vBPEomxlwt^LcLJAqcPqhLJDf2 +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 +z_Z$>Y|8UyDPdR{B%Y4Do`ethHCIIq +zHG)mvrsqzc0nH8czHSG$%ug7`T^+h#*F*Z<+^WpDTAaJ&pA|wxB8&T%)g6zx8&!MFnk$HQo7o;em&CI=iRy`^{_nZj8l&2A7rjx1WQhyRY5A!L*PtJ_$GUT)vH>h=hE&wG&%GB8Qx!Ln#hO90AVTCb|r(uF0 +zFCB;AUVM*SNKl!G_c?{-?am9H)s(S>oc8YB9NN*rJU5<&KR15sVU+?Z4h8BW)W1sc +zhO*&v>_vM#jad(4dzVDARZ_XD>GRP`RAis=-YKb8tRuvgpGp^Gcm`QhddT>D?!(i( +zKfn4WFf&bY>hd2Zi&?L= +zEFsNg1SGNKl(JS99iC5A9#36;Ihns~att0|#WLVnC;}NsUE+zC5ZoRaX`0b>S@cXe +z0++nnu@SL|`A(daV-XglMj6qV^%+%h52N@d$=uAcR=6YH${_Z$^kusd(`k8x +z^sNggY1=sz0t0H>V~1Dy`O7-?6rIJgUJQfJY%p6(`x!g9Hoh{f)X)=*l0f!(_fnR@ +zc9y8BE1kVwnSf83S>81$UEslcmFOlg)cW&cjz%H~Ba-!;e(pQS*CFKIZPZ}x!U~;` +zl9FqObaTsXd_AtLs1x%ondv9tJf8NjfQ_mX$H7dP&R`#|*;$3cd5Mz}jProzH`X)7 +zh7DkYLiO!wUjEc$a;so5*1CB5{YtkdUm$`re;!$^us1;kj3QdpMzly7Ri+fzNQ=#4 +zR}}Y9SrSkAcYJ3-CSu}+rzz1i^$O`i$a)8zIGjdDm>CueXB&`CIJ4 +zqS@(6G8h^|FxOXkqxzwbLKe%1sD_9)O&Dbi2St0>WA*s)Ul4cY%lv&(X|vfmDkkIu +z`Jk=degTugHVjs#gRJrslaZSrf7v*^z;CPA!^M<>&wvzv3o^a=Hqa&WQ?>D-*?0e@ +zYf#SwRYF-m^ETz|DeEW1%mj5px~3MWT+)#UjxRBc$9H10h{Z?(bCg9Kkq-&1UCjKt +zTNJ2@zW0D%W3+1=wVQ5zdJmys`J+iB-Y4Rxzu3WZU5&K@iaFVIomWiQ3gR`In5JQfs?Hk<%)lZa3!x3rYZO6H*#KK- +z4m{RprEXcg%H42JmAw&@8^k#!e^R^WZ)X$Mytd6ki#7u5pBvH*!tNWPIZRTf3&h!i +z$kEpmp9q|96-Z15N7y_I7FnwtIH}5#ZG#y5ERC)d4M?z*%>Q7Ly!5UhzJPU*l?ldN +zuZ2u`TJ)u09U~plp{?VyVv7E0WuZw&X4~XJ&y*g#3KYn(!Gbb56&Z&1%toyK#wXV+ +zWoww%Z|VaGh}Db@Oq-E4=|lr=bBngkE*u6T%;5Ve`b?tt=ttkQ4_s$?9_$Q3>Kh4H +z>3G2k7=PDFVxSbwOR1S~R=0tW`?LdJY}#VgLX0dHZ^BQ<;CY)LHo_5-|2fk;7)xd; +zD6Lekq)N%`_Jrq~%`0{zla_=rjzACbz~v*4*~~S&7^d>2o0i7v;a%^!l4P-d*Nr0c +zSz~HUc?I>lBkw~Q1v0@j)>nisq511J3iWxfo(`VuBV{C^^2rD+MVikvPV8;oN;!SB +zq>mUZ&XY&-d~)#gFc!%py%?n9!@5MPW6HL +zEwG5NSyK2loH0hFarq|=@s{5x=92N8nbi4E0bhx=s&HxUwbAROgjczr4{eKOl>`(E +zn37GZkauy#UIxYIt};Y(iYIDO0XbUf>)<5suW;C2Y +zXYGzT>mz=xd$=1yn3S*8pFocV>bo8lHE5=}O)1dgwHz2zESoZw+|UR*Q=^q=D`Wq9P +zBSB3)@M}5E%QhYK1`5Kk!`CKkCTxCM`6MrLBe-K#tr8({%$;Cyik3NCt=_SJk9ens +zD8?wHSN^0HrCB88V-;VESp$yc70B^ZmaHYVFCP7Fz6#{?Qh}WQOYi3hwvBjJvslMW +z#fpLpeY?rgN66S;1tt2T2+_W=uPzpPy#|ptZC5xzXU%*xxihtZqqZNl3X|p5;PpZ> +zM7Wc=QSQf!8$+G#N;1kYX2QKfB#J{iaIr>(iYCOB(zqLKD2i6K@^2E7mgj`1x3Al^ +zAlKidq@z9$e4X2#o?oJ?6ve_+#-nmnobTe6_a)X_kBB*j>>H~|@y%8PZQOn*a>Y}n +zlEy}q<^2nrF`d!x72wuie}Ae;*y +z)mBQ>8s`bz=!ELNn1+?^YJeu`@mfha3I6LuWwn|a<2}&|XQ3r?0=(Mo$ +zEX$`b+fL8E(xaVpHcXTz>Q0y$BGXMHXh)#`NAY|T!^rP%8}(j52>drh}7c{GmhHZz2CD&?d$ +zhJ8iEoVv8~+v)W;)F9Gx$u=$DleO&~^l;Ujr~|CFxQH$|j)5Y~7IN&MYB$C_hh`)h +z9$rT09k5*olOP6gzeA)G>lP2Qh%sY~FIbADdBa_SF|*~uk>7`_WX?#l@M+SztyZ#z +zvm|xitlJ8#vK;W +zj~R!!z^2`oR+QC+8Uod09_da~dmUiqInMp*Gew%UudqDgU&ZObvr$o>$h3<^Xj4_q +z??MH)hH=jK@vDgeHl@hdi6_d%^a9s0<+vJv=|iuEk-Nt +zz$_vCNF8ajhZf^HpvCA4MWIFB3~VtTGO*TEPu#T_cR&lTtC4jvOJ1 +zN#tQB0C6OTh^<|)yJ+cOP-H^Gbv72iLhOEnT_{yLlAl(h&8|i%s2PR+$r@aoS$je{ +z)t*-I7)twn`tu;7orY=EJtrlMFv*wN^45$!A +zd=N5p4|3L5ezUz$o7WK4h_KUX<7+%@0^`{c-ID>xrltZuA=_3Rp!pcY=`|ejXWZ;1 +zCproEy3vLp1feaIgG8=BG^weG*^OwVIx^>DojD +z?xIm|D)R+sg(OrOKxAgMb?QOL<+VktK*yoMYw(18l*d}OX$k6zm4ZqK!`aydhb{GJ +zGJaN%x>e!;+|22R4w1X3aseVv_Qe@oW +zek3u$Nwol)@2G2z9Y1;-*|`B|*ySKgd;r%m{PXXF)HR8VN~{7DThBv5iby@HgWk4f +zT?R&CI=o;9HQZb=Z?|CN_Y&1Cg3s(z8?(?OzY#Zdx8?|wc>N~3h)(!i`L*}6h4tZ8 +z5p`269>rC+vP^~rwCB<}d$3UL%M{qOeHMIp#6|MYQ+zeds_@Z2ikynVRHB!((};na +z20wY4I~OOWn@UU!E$;t(RFQOE&x$c66X>wk+4~6;`xP1#@h)_s +zfeok`RxHMX6mr=YpWjaIGdTE4LUQ0MuiO@Yj^r{V9{=2Qa@)VrE2sb6Et2DA9tXF9 +zlY-3=)#(=Gdy}J@I1%1l=S8S8u~obYNbdIw-Zgj!G3q2G#Pw-mDD`G~9dVh7mw+4u +zvf=yDlMJ8Fq5=H5Pt6E0{id69@V~3FJiT%hpHT>E6Bm7s*4WgmeCq-r>NOOEW7?bb +zc#DKjJk;x*_Ub7mU7oFb6#Gls)JK?S92vN|HG%j3OfZj-{hrA~r`m2%U!N1wIvWYm +zYlQq3|7O@5WAJdKL}{1Lei)M`jEy8I7F3cWhnX-JuQ*cYu%^YGW)CSZms#TB^n_~>|VM;@b8J`gC;aHm*F(F;UI&E +zeYvxeO@&sz+YitvAR;sCk4K&gF*V73@1kDUTo4z9ICSJH57Cl?E6n=@t!0LSu=DYi +zQP|A5y$;dRQq82&Pfp$joVNmkq`D+D8gSBBVVVVK`@Pm*PPRiCl{+m8+PEY@eMr5* +zoJ3DO5I->-!rr9zOkcF(q`myUy)hN^;zKR!f}`*WSf(F^<7cw(6dHOBG|1z_TGMGN5Q-q&ekn(=g{QjT&&uJU%)~agK#A&6&66NSY2Pt7wO`8#VpBK)eZPL_8@wd}*@4Kd-YDI@+d; +z>Lp}dFTxpCmCE5Pb|n!f$`b4CU!MUDb1`632LHVpNgqEQ0!FlAKUH1XnalGO%FDx_$iMT2?AQ-c2xi7a)1igyKT|XzzG$Yw|i^y}O&(Vug&2GR!7F;?M +zGNwNznLikH8!)rRmyCt)_Zb!ilohaxYv8`M)Nfiz8_UC~oiy!#P$uruF~*IJ5DY26 +z^{n9=|M(17QEJ14Wb{3R1%`g~7B4SlpH)XNeAxJIq;q`MRQ?J>hFT6pO!4ZAh74qL +zIWq7Wx&iIu07jBg8!nKuH_GxAgh~`CExuq#mN*9Xlp9@y`h9*1WT>&Mu9)4u3L8I& +zraLA#jgxG_!*>KCqjpX6rzE?FpX#7#48-oePt~1r>-vEN^S%JArR2h$8|x+7RLKGe +z&K{l1Gsx>ju#`{<Yhd)!GdmIwKa?|JA&`*SC< +z;C1;*tn6B@3>k=11B5TCWRnz`zWJS;} +zo)$d+^Sm>ox`^{KfxlVZXjb5o*15`Qp@GAGX*@^iIpEsd)B?G~XIkU9 +zTR8KvRWNz>WbuaAY;fR+?gSR#yv=iOf52eV8{>kb@3Fr&*;wAEIa$)gqgvp7FR7}- +zY;E!4sO->`E)t>ySsqV7luTLs#R^}{c{ErOA^V9^a0q!h9Jh9oWoLmUTX~`)dM5XQ +z0zACE!%h1e3=de>kD>%1v$nTLdJLH6h&Wl!QSV!%gWk>t6UWnq&=kpqgLT=0XXm^Y +zHia98^!DLHT2jMn`;B(>+8$+LoD*1IYRSe5-$7VcQ^j!q3O +z#ts`q1jf;LDF{$+NTY)nc-nX>WxpjtAvVomz` +zB<()prKn42HJLA!xD#JTf{aWz7$S|q=_i@yNxly4M(G#Z{E5w;+hhx*gR3S&$I`}4RWs(B$wYKjR({zjF|QT*lBn#mtepgD +zD#n4BcV)6?S+qafFe_T~==iie)a*3+&Y2q(VX?+5W#re^AX>%Dc5*cMk~_Pw&7lFIQ0B1Q}CqJdkG218wlVL%V6q! +zUb@Im2L5n9C_9+S?^lQmkPIr*)EW;X&0h*@Ec6_5#C;fm9EOsv*ETXf(Sdh!P3C;Y +zvKS8^;Uv6~R_I)xPXi73$<>}gU-Cr6_bS};#0wU_K|*D0nQf814ST22^xAn#&7q@k +zY`x4GLKB8~O4tdT-N_&w^z7qwizatBicYFpg4LSY%Jbq&{5P0($9p#~-qbiS;hLD^ +zu^mW9GmUMxVY=urq|Y5*5H8(xw?}eqL_!!HXKyUwY;_toh4mC(h$7`h%#jI+7FjK5 +zLNs??EvD8Q#{VQ;h2@g0e+4UrzXjN(G6e6x(MxJvAU8?kFXTs=PdL6^w({i8e@n|S +z*zBAgn1uT=gbuAy#>)AP*WfA+JM;Wa560lqw{ymwh>L=s1aCqw{Wf5Bsc0PKJhv!7 +z^JJNv&a6@dIIqWDkBC!Bpr?nT_Z=GmEr0|uB!+^~;4h=Fv%{WE8xR^Sm8+u%svB06 +znSn!Xx(>Ug=y4}U@!XN@IFUYWbO>f^4nLYR`lx@VTN7#0QZZo-YiQO=*7BB~l@gY| +zY4Qt=L1AcoHOT}=OfLGvs*OiXDq|-V5e8voag|}Cn%nH7uQ~G*hsERfUX8ldSu4ZZ +zvNcQ!JsQ)Y6+>pYFwvMUU|hPBIX@w=NNy|Uzn11SRezHNXXg6U|3)6tNZVb27fzi7 +z;S&NN>Z=CrL;hryZ@9>Ju+KuGYQ3qQzk_VeuaU3{7Bb&z&45*5WlChQzAd%uM +zHs_-)1~}j(cKrLEp7ouPYd2-Xbm8QcOqgXY32|4iThxw*8lsT#d6qiYr8tXN_apWT +z-ns_kMtmDE@`YIYQUf+_Jt7v0UC#0pPwEYuzmpzVU6<~_M}m!kKZCi=*D7&H +z39Slye(q-z^D;%EUa1iI{dn!OxSVrs?D~U8(2izKfkmYwTc?kKagcYvG5b@ayE0-O +zg^eqe7k!+65&o3O$@h0qMtConC`j^LojP0DONd}m3=i$is4GB@NnSjtMRx;LF$8C1STv|S2VGs +zLUf@VCqgCob3Y?B@ju=FfYO&R4p-5@-^GrlY8jivLYP3%oSKJ)i+d3#Z&yo4Wq)XE +zlT5O!0jImi-T{VrD~C|Hdqd_HAI4;5N+-fOkNuMx9qv`G-oRUf$x)VT<4|UMRKY|1 +z#%IURKb33T7&nEzwd^2hVEXtg7AuC{t +zdlI_9{&9P)u~X33Dz^hAz|fdTJ^Mp`l&Hn=4A17tbsF6k5l=NHI>;wKIxrs2t*t7z +zrsoA`U-w$#Q5U7z-Y+~p^*{@(JYWqXfDknPWWMH8Oar*UZSJc6BHr;)+nvdA{l%?f$Dq_Wzofo6K3n0j +zLCZ@cBl>m7j>7~U2d!8&emo40jrvo|Qg05s +za-=w+T0xoKbyb>Bhs7?x=^B9z68uK2;WT?qd@Xy`8z>QT!XtR&iznw7{UhIB>ubsf +zE!|u-0gvqrnUsD9ix0J1Q8TYUG@J=lK7*63N}otl +z?F6&gdg}fRZ=YzGbNacuC+)6=&h;i&lWx72nsa9dssD=WISu~^a_Y5oz*=c0xfQa* +zrCgM3P;#Si2S89`JM(k2%dn$-BF<$Nmtio}m-tMu$SdCaEP8EZ$IXr$gCCQ-bj5Ol +zkO!SCJ7t|R#Ip6Q7rajuQtgGiD}OtV3tgA~{y{kmt`xX|TUJHEDp5R%K4@M%o;6p= +zBw}y9J}Pqnh|qz~hi)#fY7UV-^n$L&es7~Mn+M(t@HS`SDxPE}Vs`yH^s(7G8ctks +zjA!6}3G%kE8zuwmYzyyN)muPP-<^S#Eb#fAq&dh48k2ol3o5PEpG7l#0sEsLM*R5e +z8mSJ?)np-pGxSOb?RTwrpIU|OJdsv0BM@L%7K>81&Th_T2}s7_PQT^o(?Hi1 +zg7lTM=?|p9j6kL`Sr~y`6sR~-6%=@#GcKNsWZ;@D)r-2ng`L5-3NgJ-T +zM%bG3#W7=l$AnIYS&jQ4)qgqTRrA(o6P5!B1goaygk@>u+FeXuXARn1_MAdHRq+c_ +zC{aQb*V<`s +z`V@4?P+a&~7eexL-!wHnx&h&Sk?5OCW`~5uc*EH5^!gPZxnS61gQTD8{fT|8+eZQx +z1wVX?vOO1FIOe8bHDQPR*k^3$ChS`fWp&8(v1$oT%ggI6>do5Qh35Az +z_7M+oBUrkbp>&lf;*~nCBF*^(-&@4)DMNrhGIz*of_Vq_O?r1rr_N#}TglHk$hceE +zU#>&e;uUg<-$@zylm2BmP!k?ndK0%TsA>gmHnPc_r6A?V_g@K4le*{%bPt(<( +zKV60wm^C4@MO04ZlZvU|uNU80MJZ}HpjDg-czSjulYtH{B&{ro>ANu!f4pPPwt7*12kx)KZ#S>n3 +z0)SOKmmo47S_WE05aAPfZn$MOFxwRKJFECs=Q$3R9#d(~=iyFH4f|;spjD(G(1uWZ +z3$ThW0ag+1&MIn{j)0vr-CM;YtWS?taq!+Ma_GN{kE8N($zzSk*7O8eMRZ;#nUGJ^pAiye0k}HRR +zfMh>d#Q=a+oCR7%mE;7VRRjTA#g=sQCsK2FRxy!`^rf8BomK1vTE+R?0d=Krpj8A- +zyt9f)K&wbOe`WjuU==q_CcY+*w6`fK`;3oE9`hGYx5TFRnGP8ZPa{%B$mGy|ap-b{a#@FXISi +z1QA{?MoN`E16W0BfK_AzSjACRD)2aXvx>!d +z-G0>5NCJ@oWk9Rg|6moT?yREPomFh*ORR?znqRcb*9Ta|A)r-UxU-6*Y+P}@KQ)h$ +zS+LbwfL2i{Lx2ou6(g$=fmSgeU=>Sa7l2k#*|drL9AFi9)EJ%!&jGFC5{RcX$0fij +z&J_c!VssH@4H3cxDTN{~MTSVi0n{5618oQWMY_-z#tz<7nr +zR2bE6l=|b|fCT`pViy6OgIKuMNiO_JF6HkM8P)J>{J4@iU|O#IO8Vm +z46uqY4_2`gaUZ3~j5L+?^&-G3+VoNSDNU>A0IXv7JjC%F1JEjt8O{m4hyz;1Pazgb1}e53I3^*^j)vArJ9D#qVg#Sc|G +z(sx#o=a*HS0$N3gZ+}|FeSlTex@_43TE(vzCjhG`3bcy$_g0Y(XcbSS={77l`bez- +zR9jjxD2$4ijP+DwOy^TvIW2@w#Zv>Yh2H4QGN^lZ57QoYXDZU +z`Q9oj-CIQkGL=vm)PvQ*BTcoxTE$*o|69Zb|MD``la~_E?|xaulHXP_QIid56*KOv +z;`*aij4Y<91X@KWB!fhV@n2SPY4P4FQUR=@!(Xjp*gvh}EYK>d3!ORKTg6R8pjC_j +zSj8bNQ|txGN2>^ZXBEL12@oMfs1)z4B73Ejz`a#;)wO#Dw2EZN8XtjHF%MuB#nSuU#z13&-Y??R*@KB6<2{)5lplD!72)9zvoy}xwDGO0IP`cH8LD(%D!DFsE+vF +zDvkoIBA8529uCC4RSf-Q6}2t6Mt)nxi!D~02dg+28LfC{6)}KTkrux;4`3CUe_6$L +zYL#z)T19LlrKn$4@$H>eB!0At?H@oz<{~;L{$dqv09LWqTn^H-_s%NP0Ii}Hz$%_A +zJXpm%pjAWySVieSt>VnRRZP3Liei>5n)g-_Wctx6uK571;$A?Q1Xk#uR}F{<5L#oDuX^?D7)k5(~eA7B;P)bM*cwuDCJ0amf`Ppg=HXBB%d +z09FwiU=`PZR`K(rRU}I?lGii5w~8y|S7-pM*!gG`Q-M|y24EExfL3v~qK}PL2xGJr +z(TsOv`y<=F+IRKTH#DSj6O?msOsapeik<(oinIiH*$-Cn>fS0M>KZ**#g2p1zgk5H +zfK@!zJRtyDMWI{_vENn^|K2Jx^E>zgt)j=BRiyvBRa_v%CsPCgSVfmeP~Cg0xcA#C +z68^G^U>@NqtJzbwl@C^ty$WCz`GHmu9AFg_zlNqzo!?u<<$J4$NbCW$iu89@@#Al+ +z=<+^CM0^Qu@X;!Q0IXsn9xLPbsLDI5*q_$*PphaAZwR!Ctq)d_`rayzKSQ{)imi`U +zF*Z*s5#rG*f&s0f!=F}>#d3Jc +zanPqs;?61_Kz8U`wBK7rmpiKniGr>E%PK-j+#)&wt>Py8gH@FIi&cz+y-xnqDy9Lg +zV*hWesQqXa{qC${nLF47tig>EG{7pFSSk-`+yJa%>z!4!`qL`HuFb7)2epVHLRYZQYiee8|F-#N+ +z31Ai3S%FrO?ZGN)0O;QDk9ulMUOkH +zIQ`oyvf2EyigGatk5+NQBdCK1_Lo(p(UO+{SjEVv$_kHG5z_L`Dhl6QMe10Ov +z;slvQcD*Sj&??3Otzy@sRh$4?MNObpJp5%9D<7?5yTRbeORwKnv8c1?-YWWo-dn}^ +zUslom?^bawr5I`kp)i?qFvg==lGk3Htz +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 +z2u&~@qj2#tQjsAgGJ@3&XiAbWx +zpTmu2vE+{FTCodF<7CCWdZA@n9=OWcrnFE4C(3X^pZ*|awcuqSwe +zW7If_q)Pu?zScIy0ErF1^Eo`ycwadKmyk&pgNco>+^2r<`f6AMB}~^V^9sGB3b|Ow +zjTF!WRfw^+r{v6ynNuJV@KH*{%lP4XzDO|dByAS74*ZbK523vUN|Nc`zUmO2dOyS{ +zz184<6|vT|y`%Yd=~L&JfxLG?()EVepwP`J&dr!B*R=H-UpIOWjx5sfAj0rr{8I-- +z4y(eP*>8+7`vqh41YnGm;kVCqbIA`;vbBWOlf5TfH7v=N9!E@3uEMX#u%ZWF~%{7@K=m+=|3>W4b?)* +zXN<80O4~^sfH7W!AW6^wFh(b0Y5>OA(U_G=<%Xk876iZ;F`h9-j%SR~qgrw46=P(4 +z#Ta`;0T`q0UyRZ08DpIODg9~sv!VYe@(aeui6Rd2f-%N(rc%CQj5q*{5ea}X3PK5` +zb@br+l2lKwn*lIJI{?Orf)e{1V}zpB17M6IxuI_+f4pLh1&aWTQNd&W2H_cFWO~II +znNg^pF-FXx4*8B@&3|OL~E*1)S#TeC|F~&~-jFB%W-SN}=e=x@NXN=M8-xy;A +zi)I~%zuYs%cqDq#8=9$H`Ws^;&I#`ZV2pW~vj{I3qteVo3;<*F24IX}6jCo3BZC7e +z0Ar+6i2z`X-n^z(&luwl0Aq}Q!5HfS7^4)n`X7wZ5`Zys>_!@WxbmfV#u%$#F-FwC +z7^D0jjPd*xW8`4@sbfV-ZwbH{cQXHCjMVKoCNBI_tZ%B7D>{bNUol3g7mP6nfHCsE +zVvHEZJ-9V~dk7}F}D02pHe0ArN4+mwIB +z7{`8NjAQXQ_OP}n&lsb@3&vRfZ;Vm?1!I(Z!5Htzin2=4UNJ`cXN>XYUl^nNE5=9+ +zz!;HIO*o!0#xV~oWAg)#C)0}gHf+W*8D!~S55KxnzP +z{6;SrqvQ^`+P^Tyod%|d^1zb+!Wb7<{=pd602m|5E5=A9oeBOgjPdq2#t8o}jFIvg +zW1M}#7|H$vV>Ecd7)MC_OjXsNF-F^0j8U?!K;{)=bOT_FD`Nc57-Q&fj8XRA7~`!V +z0ApnRUopmG0LEDR9~fhyd*0e#jB%`7T(Wxc1!FvZ#Td={FzyR&fH4C78)J-r +z#u!7NF-C-cFh-#lj4>F1F@il~jQkSN0E|&#E}j{HF`8Tv^Zmvcr(ZF~oQP+P5s97f +z-xy2zMUNOe>pxgoFO4zkz3QABMx!)Kg+P^VIxMz$}_8DXJ +zdlxYMiZT8wbhcABBJARPZ!7+cG5(^vGRtS8jN^I17-In#BkpgE5$G9Xl=y=&O3X=6 +z9vdWtRp;puI~h^CMgcHJm=}zZ=zn00XQ0~uV2m9v7-Q{s^1m2kNhD3jZ;Ww98?N~U +zV-$bJ7&|jdd7d#w*)Q_Z&ln@e|BW#!+mM+2PmEFSH^yl4Ul=35Q+{2n`^GcIsHbp1 +zG<0^%q>hU~Yp^foW0WGsYNON{johg_0EF1!GKy^Zy?hW3VrJKfS-= +ze`Aat4ZktQDged^^$*6V@fTy^$7h@#(H^yl2|Hl|%{u^T?WXmOe!5G6CsZ2(R&FZ^JDRsRnpE1UL`M!Y5 +zq%w@odncLXMNj3Fp0VI_qMlI=5=1GnD2jh!jNkuajN-?@Y0ntr=8zr$V^ny-80`QU +z~G +zF?Pev{|ClM1Hc%;|BW$D;=N*w@1HTooQb~}WAI;$aS?zqBK*Y|EB}QtP69B->Hmo_ +zw*L!bEPlZl6^E$4{l*xJeq)U1=>UxJd~DCRbMHSf#;xurRC*3Ri9v%Y5_)Jt?GJGo +zs@<2(lOYY3ka0@ya&%mjV!pr^*=LYCm@%5OdAiC}o6HWsp{Ne``{kmOjiSnYi>r08 +z?a!@S7#eAtGNM^NsCRUstE~w7)sn}Rx2*nA@k(ub&V7sKd_yXsNl +zfM>Br^K2qgn|!rd=BENhH!O{p+xc9pG!`@H`vqEWGDrr9TSDYh>ly@&U8pclzl*R` +zgFFKhBu`cva~8$m5WEQ77@=|$8|X5`P#nBizOyKtFXrH+=Et&LD^v|38~(?$M&=o{ +zR$25@l0EP2H%>Z-q=HR$QE8+68wJ2DhbYB(KVV3oh?6XyI`JOZGdV#+M&(ZBIOrZ# +z5y7$C^%Do;?rt`}9!>9{e +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 +ztkKvPCX+mKSPSwJknFf7c}yz +zEhM&n*-TRHd-i_zyjNaR`ayyqf!`w_9{T-w?Se`iO$Ao~HhJgWQq0CILylv%Z2&mT +z$JEF9=`$g_GQHpmR8`5nd1t52zD@j(O3n+9iZIebnC6mp;PA+sLP2`QwroH*`-Vby +z%gix!iw|5U1OwPYy9Y37J$oks@0F8v1pCZe44u9?pt4N$ShOJ{<+K^qReQC%?T15V +zyM@s(!<*WECa-tQX`xc~6>StHYh?`*8;gzb~d?;y!tt#X| +z0*sc*`WH%tv?Mbw_BF+p)#;rf0YchPW%OV{LJRJA6Mk2DS;{_aF(ZAJ17j=MZ~GQ+ +z@oV&fSb&Otp4Y+Iql50E6 +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 +z8ow9>!fF0Ug9i9nD$~FeDT6?K){ke1VyL +zkA5VM3@A<rdPF!PIvIugdOv`XvW^>@$3vido)sITNH9z`Nm +z4M@W->F8@sA0y4ah4wlpNviFl2l*xqHS(yg_s-Z0+9o+H?i_Hpbnu^L +z?TgBWo|pkY13}6k$w4WLhN*$vn?Kyhw82im`SM`$E4wghI>9%pV@t;nG$>E&#E&t +zu^DHnq%=W7fKSpEgRfldqm}6+J~Q=LcQF_*!5z+F#=@1MkS`uB?itGK$W@LM9}QHU +zeDAtj#mJubYt)AdGw9heAS*PrnT~e3?A^dRwej#!Bf;$?7*;O1<=j$oN1IMdoEVwa +z$&2XURH6d2RncNLxYryW?~VcAzisu3)a6S|l}@vrP&OPl;L(MK6D0M}D>Gj~IP+$A +z5=q|5eSpwnG5LH$Heg*p_E9AZl8^K0gT+`fM;0zuq@G(~G<|<2!-s!I^&7XHja4h^0Kf8@`RmN%_!nocn*Ua-F9j*)?8I- +zDw0;|jBd!nmPN8hLf=0Z%R5g_y|XAcj7uzMu6*)fUcPXb*vLULR_n_9o-tXf1J|%o +z{R4TUZP1W66l@R8+7bx|`Z}8^&9_Bz?&{(SewM4im;CN(K+qN0SptW4jTO^r#bGSL +z9a|4GHQm{cA6vU}aTZ2^dI4Qdp7x5OQ)U7Nj*pF5VffDU=?ujgCeEQbJ++GpTD6Q*iZK3#S=*M7qsiCLo +zz0{bh+|T6R6Pq?^>OAo82+=oF4Qo}ay3`v8lUbEckBM<-xlpm6Rl2ZbkFL~nXDc1d +z8%kHhGwPE(=L3!O@;6i(u^(y10-qXvOb0QTci}A*;EPEvyJHWlXS->CEvrWg48|F; +zOHDe4TDKCj3AXGKB<#aH5(Slt>f4@&6ZQ}(ESN2&ET~$*Qo1A7T{y42zldS?UaB=( +z<~6)7P^ve|_UuAnEXln}GSmQO%|5%SZB7RNm3jptp#CWj+k`)^6ABOM+!gxMUAfUNeHlEHavATT?F^JkAGutX7B@JU67}D!d4GKnAP5scQq#eOT6jQWS4UG+1<$SFu-qWjTdZds +zd0PrcOReq2Li^zK=)uG0ZIh{AI|806%|_kvVW%OQc1qUW(b0yL^JBw`(LKLLJ7*ix +z_f1~$LP`w-qNMM{Z;QY5pn`~6_-v=CV_VBr7w}-#d!q1Gr%GIQ-oZJec9XleX(=qS +z3PWN_;_%?=n^QH;YKGYzOzA|Nqi2Ym)YeKdOf`8){VZ1uaTEt<%C3R7^q)FVdNcE2 +z?0N}e!upeQ-lAa)f@u5WxWkFhFXwQ1eeis^cf(h_zQ4``?3)AiXZOoyb4#hkmUh%N +zIK?m!%nTo}no)v+^2Rna1^o)-JTp!5LVki=@a}G1D5%9kut?czaQ;h=>)e +z={2{*B?q>(l4y_f*X}};9~I?yvz$GjrkEaz5I`+3N1D^HYvUXSyWefKG^9l}7H$Yf +z5Jh_>q#oC@%i*(s5mpoOu>rRn=A!26tD_6q^5}L)rP0$Zl5~$6wRD=!ne)@w{gQ_w +znyNn|DR4v(hl0xHMEKUxMRrkRyX(vC+{#)-ZYsHUQO*_(hqzE6e-X#(bezo@mMY3;-kh+ +zZkxx&Tr=oJ0Aq3P`*BCUi2;Gz+t8h;GrDxC)Z_rQ)`qDs_!vBoLdAjb=?iY#vTx_- +zUBZt8=-J@Jv! +zASjKp9pZQ~FC*UvO?diTE@okv4GBSv5!mX;xKc23b0_m!vL>k$&H+Tesxog+;7Er+ +zau_)H%w34cZhq@VZGueK-|Z(U3}t_{1irG>V+x69yK3wmSQ8nma0KAE9>Lmjn?4O6 +zh2U7#`$_Sh-hE!Nc1>1y|7v5u5}XPY$gTQ_GCmJ^|Xju}Gz?1xzV_jy`mPj4=R=gpTn3IO7%$iZBT$}U7HVA!9j#@<&2uPg*VvCSckHdBWwGPfZmBFqY{YGk#&O7q7D4`LXvu}w +zh3r!tfwZnp2}`obwbB$hWLxMJ +zmWx?f>!_0N*{U7M>ciWkD5=9U9D4q*@^$#$o``RA6HMffz}HKStQ`D$g)QU2Pa{n+ +zicgC|H3#eO<1L4ynp3FpvC5+DPt|(s@$5{04M}v#yIwcUkcsC~pyEo^&W9u*=5+{0 +zO)Bix!b&e>Q=iybabiAToXUZGFz6?f#kAp0+q-h+G>vuCF@5*Q?#v1o5?zy~z=Pz7 +zKv^>Y!Mbh7R!Hk$j5`}#Hw9NJDj;7znn$tT@ww$hevy9NA*I?325Y1L*05Uo?e&FF +z%#Z?L0wOsA=V +zXZVy8Y2wAC!<5cfJ{8+C`3+B;iB-}+lDRn$PRRy``}1u2uU?f>2x5$!w{uV$P};dd +zCu;aQb&HYpo)GW=(aexY$2}qrU311)KP?*w&KYO{kBl#s1jx$Z+N` +zk321oiFm0Pf^wY%Osw^3ZYlW3w}D66fLcB3TaWyFmJf)~Pf~j2{_!#+(qUDd!}4pR +z3TbZ#22wFp^h>U16k52aT*ccf5sL@nJg{nKyw5e0#Dg|M=CF#jwX~pYu0AxFR@h!y +zvJwYM)I=c63~H@tfq2uFrKkj$Lv0*I(S!#%xry|%2R&NFSoYeKL4x5Tq=|0ayr&mS +zAQ|~y0h6B(=JTiz%SM)ZPFrZurHAcvj>{S^b~Wm9i68I=n&w8G)XO#!lS8ItdZItU +zu4g^_Ji_)O +zoo?G1wbzloJbaaD+QV?Fn*|CJ +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 +zW6XKIKQCB@yt_ycs&S;A^cn!# +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 +z@T^&qM_A +zfDgk~w>t9(KN#9%{K-%_`85-%{XW9u0}ef>$iYGdLSvIop#G{1S~yyFGLF(rq@l(@ +zQ}X1Z>;5@849MqUb(*oAGcX)zgwR!yYLmm8?R_&_S`52-`^JQ%Z*DrAO@?}vWJ$rG +zSK$mu<{@ruIFPq4w0+elm_#Q|_i1X{M6?7%?VaicQe_0al8)>7j^rw8)2xV** +zNxT;fvYkt>XD3+tjxr|ER-)pPyCaULIt)yNd|I8B_?vJYu)G~tFN0<8*7W%cX9^^d +zHgHCxsAk<^A$LrA4+Br=nayFs-Wscww>{=pB3%a*1%XCGTIERldItPsS;dSySpF~# +zJSJK2^K2CYB^q9x;r-S*hhFl0aN2!K +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 +zDmcwA@>@ +z|gO|Ey1#=*?XTu1D;&bgaU)T0EmprKmxxfUmI& +zDj`Kqin?>|JN_UCCez>)Zu=*4DTw;XPcMZ-u;m%BW2Yzqq|;J2 +z^Pzqr0TZPqmc!Ksh9fF(@pg!nx`CjV^^s*fnrSQA +zO*agM5T19Qjcn&ssHk)B)`7Io=)U~ASiGCGk%+D~@;Hr~n)#G_Nguhj;hEtf3fqW} +zcU@%Lr{B|~N=I-b@bTn@x@AuUnaH}Tj5T}ptUCGAtK)O@e_P?a6~ +zi^e(ZFZ*B935>-nxQm52af-*G#4CnXp<2%!4Ol_*bYphO`A10K+{J8yU1kI*Pzhf| +zRMn#UH}}zn!bA$|k^31NY8EjRZwSoH-#XJgiR@omO|LtAhR>zSEXMesg7J-%Mb2n- +znn0}h_pVKy>0zIl&%oy!<*nE!{Yip!c!>7DqsS-fe4+|57(;6?!rV3_m1zRf?5Jln +zSB(ngx7f2R+>Cq(x%4Z2j)!NOJ*kF7kQFdH&HC!qBbAzxmd8K_m%)gYqyKU_&dO#Z +zlL0c%8K&U`4im_pRnaqet&qAG?)Vl +z-UkEQH6!G%gr@RND&H#y{?WUZipte$c&NRS6G5G8_MrZ;A}yOs#GpY8O8yj&W@F(f +zusP#2j%CQtXb=(+fvyzNOA^~=8fN;qZjJlxwxQ$NedAc6>e!m9yFV>7A5UI>xZAv} +za}AiJ!7^posQL>`+2TKy=G+_}u3M$^+IEdS1iX1W=aV#!_{2#oH4X~XNQvtzehQ~7 +zj9YvgXKi5nnrk4H$6N|R?rp%FcpP+(eM%7`cjMVs*lZn!!1RT~ovVLd*{-SuWoNOd +z3*&&EBXSemD#hT=`DgN_)-}RWoVFRiG3qkd)N&b3>C?pJG5Dm_rE~3)O%}ZHIB(9u +z=C9{7w1R#Zacs}zGasOz2atPC&;ykV8dV}{YOAeN4UJAQ40yA{kE~AQ(r98?r!B!C +zQhASDMP^`_gZy~b)+H)71@22Qo2+pItEi8di%_a?E^;GaS$0zsG6QW +z*$vM8a%sFw*VPj`f?)e9rbouCIa#^B&t)COvb3AX7B|?t{hAsYo09bzEvdi0Yrqg< +zc0wY@?``h**X!aQwC=^12vud%Ui3S)m(d&_xroS!RgCHLPy5G?Y+ohg!_Is|Wysfc +zwC<~%!xV}l9_7p-$XHXISwET<{74A(8g;d0t+AK6h`Z?|kx2yVv8ak0=7Xw&p3TZ$;AfzqVFRRI!m3Y%j=-NWQs<)FSD2IX=ZK7%xHt0+; +z@esSd2xbdsNhHdAap8D@JUgg|7Ro4b!7AKBk@cec8R +z`~>sw85w9D781^irkM4R60~G4Pzdl1(;j%O7O@5iv#9T!b7C(!^dqvt>u={t*MO-Z +zvnD1`11Tj3wH@?iQ|aP1Orqew!HOzW28+FY;`ZzS4zivRGD-j-jy?YaarFO(4xy6?+{GsZ=dh~KOv45Q%Bw_<;kL>Zo5=Te-KCX$-fatm{0nd<$Y-qQisT*{W&UpdJL26>A6IcP +zPyPdObo_6KBdt7gOM>MO@|9#St;Nc?BSjEXTE^#m)Z}aXeU1#d#8!u)HHcc}wZl +z1eeQB%|Ou)N-5~gC<@d^Dg+>oC~6mFMJ}HTzsGrhB#cY{7vd;Ajab8~2;SC;w0?ST +zGowv?wqhj;m1u;CUz(`Z*9P{Ysm@phv4AwVhO2=FdvX;KV-NGXMz9h=seuT^g~t*- +zc%7yfLm`pcq=POl0sZzefMFxebfEQRh-{ecZJ*nUEcP_x;`jput&!$cgXHrj7PCX9 +za!Fn+j!g79yQ|*ckM8+^Jw@1`!J!>Rx#Q>QBm3``s`c@jRrb_dHn|Jz)9z! +zQt)rY@y&6w%lKo+m`4aF&>aUy{xV)%g<06m^>)TDZvAf`F=R*xWEa*6ETMJpLA +zYTIlRX1!wDY<>a3B)c%Kbl-aRzrLZ<^;+13{}3zxs5gIRy011MhH#h-S)MkUt^G90 +ze`Gr@R{#my8WBuluU?=xhoZMHg(7Z6Kbx65NDGWgZnF4 +ziB4e7JG*wBI`v`#xsbNZZAyDuooc#l)+~8dAMkZ9E49 +z9N<>+ErL+!P(J#q@<~2mq-m`kUlt{nNZk6X=o9(EczK|5m!Z5?+(4s497NfAY$8aA +zCodWHQAG(Ix3tnBwv@DNQ#h0uE +zC#ne4yS{wE_yxpC#tEtKWMFZPe=Cj)OaR5v6mc*Us|27p7Nr|#v#Y)Qh +zFHqBWW)TUK4zf5~$=u~&h?TtS0ECZZ$r#>Lv?}+!bQ-V-R8>H0nWib3Gi6FotLgjO +zPH>>dg8S@BZ?$_p!e4;PkY$8WmVdo~3gh-}7VamgX$y!Z +z7$QCP=Yob6zk)ucT^H*W1t^ZLNZfS*#qs!$;>ZPeZ(2(o*9lM@YyT*YLIjZ|0LAgw +zyW*IZ`Iq9@1)@y)9XyPcr4y8DYfsvPD#h|$aU8-L11OI3$c$&KJ4ZH@r^_NcyuyeW +zalaMEus@0;i%c0j`JRgK+h-_$ntV!~e<_ZrNF19!5K)Ko4V*5Ye=Ckr%VP8TXd!5-isRV3;`l<3X5$8b|66fP_;8)HpZiB~%mXNn4Zwi_#qq@46ytBjQ6>*2QjN!Gs< +zN9w9~#ZlE@0D0*mr+*HhID%aKr8w@tD~=1XS$U3Ls9L`j$J!iR3ANvf<0%$+{@;pY +zH$ZVzhW?Bpk8h%gJVg>zh=xz~^dE{NkMXi0KyjoUuM=330w|8E7plkaisMD*Z^coF +z`?uoA4p1B~{wR)i)=r`==-DYS?t^CkQXF3dJepe@e^KuM6h|{_TF+H$ZfOI$--_cT +zKyloxgmIm|9kz*2kVK_{!*(zsh54;GmJadLrlcg;ex_a6Wb5+=&-qJn)Gh=lj$veW +zg6_W+M>i+ +z5$8XOW97nc#Ssu~NKwIDRd>Q9e5*JBcIsE;$NN9C6^W%b2~uie2xB{!$#>+%jRp +z*@cL%9qOUM{#5YD2{Q1y58DQpy|CMc>WZ%Cp)76#qsKT-G>I{>MzC7f^NI; +za%`z240lf61p0L7<3r&lKyjS+UZp~OR~+j_+;w}u3udA?9Rd_bg7N+to&ZkJy#HHq +z%qIjWjwJxaFFmxHTK7t|56;6 +z|5hAXn$g?;Q5^9i0`~uWAMB{@lUjiCF)Ez{V2 +z)K}~#PZkEdaOf+~GK}zh<3FZg13}&uK0lNjXggngVSvsdAK5r4EFWm9GVof?l5 +zwd!CDd5zqU`_}?qWpUA$UzXYtYzKwqxH48M9VnM~VH`^y9ZDE7SczB9ra!S;SmQ~= +z!H)V&ifkSaV3jpkfpj(RSxFho!Khxho%SdZ4QLzV#6=2(>f(Af@Xc=O;3$+{m_*NX +zfLWmH#q9I)QjA#jg}{c-9z{7Pr*`^+AXs7>*i-Bd5a^Bg$&;eQvAAIj4$JSp5Pn&m-!o3K1&ui5kBUAr +zMP8B^oMhETRUeBx?nu*Ra36Rm$2?%i}YuxKqtQv%hAK@;sHJFBEpcDv&V59XmoeQ~dTB>S`VT_84o +z9q^3aW+8D(nQ};$1vohw)MUi}I2K#AD$$YF$7?7wm&s%fNS +zA3Tmu$k{~{y6kBM@(nugk2?k=NGKMUIE#ABJtI9in(Eg$6EEInOIxni27}a+G$Mqt +z)LA(CDzj`1MmiiQ0So0W6y(Is9;-L!B*meRDWx-*$FvRgQO>=swtK;LnlMiEr~4k1 +zpceKccRQ?4=*b!Jc#c3#K#H*1>C +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 +zBPFuG!l2yzF^?B +zB~7md41+{Gcb&wWn18WupL-D7v1!eN=gj-18LpLBy57-2$r6-ihY{*h(j1LwWJB5d +zP3Lt)A6ZRiimuxhTL?G4Ty$3Fm%3L^K01+O5?H>R<~OS1F8sjxEklrA0|bjXz=^}< +zI=j-5nv>KBbV#4;QepjatvB^x +z@80Kh_c+~ef9SukzN|6Un)kf)qF)lU*Y<*Mmd|-m1wl48EnjM;uoQnx<|T7?w!^Hb +zK0wAUf2AeqDars|@qp2p7(b~cG0U1?l8ePKcDmfA_`=}^`lHKCrc9b_O}*39zRJO2xoRR=_EtvuFj#WuL^tSy%ate-O&rdej<&^jW;D8w-p9@mr(^Nn`291 +z2@T#)Y5hbyGCKBamvAJDa5m=+Hl?!KOIVXDl$!ERLs(=`wB(VwFFzm{%T(DZTPt4XqBfv&3b`(QrbkjK8c1SWq%{DXAjp3)nT8WY +zFV0tw;oFXL6r7Jpn4U^aji`0kh2x=)4v;pCcL_z%}~OED?+eW*Ns0!u+SXDy}wb&wpROU +zA~4-Ki3b2clOULU6V1_~-#oIY+0hgmsdZj?Vt<9j(+Gxp^^f66zCpRk^AAC7_dgj8 +zWYcA|vW_Ko=|pWk-8^&3suJHrxISpX{j441!yGs;h>MTYKWj&Ye^WcUNdB%JEo1m# +z!y1)dMSMYKlyj^X2qw*T=?Cl>gDB9JQH2KlS3gwj|e2k^RKC;Dsp1s+s5p$!(f +z2>hP7NQT2+k~rSoBFKRCw}sbpT8LeK$yCb*>Lo6whV?4j+HYSnDuVwAB=UI|`lELA +zQ~$qf$1=m4guiM>y+3Qm5Gj7*KWaxvSM4&Kf2ke)%F|CjD3^(U*N#s0eyIPb9Z&lH +ztQ}Xu;T(R~jSyh^$?!+*XixfQ?HC+h(zM&y +zS$>7yC}#GS@Jl!m1((4nhW(L-ynW;0b{|diyOO?_t$_6T(bTtVLmFC~e&t4M;sMwu +z2%z56`);d8TNd2aL+PymdqACjjBhOw{+G0x*WI^BSsjslK5PrLFGGgU0xmyEvb@at +zR09xx3afEWN9V8}qkAA!vFklT%IgY27oGD?F7+Wyn-?ri)R2KmFz3_)a}MsNfo}}f +zY3%InnO&h2oijao_@j2D{YUMX?H>vP9!Fd_ +zuDK&D+h6#pH8TFGH9CH3joayflb>26N!6#;X#AJfNTgxG`46p;OsPmS86Nky);J!) +z{i!v^|E)D{1OK5lmhVgl{MH(K{?HnK{HZm9rvBC%Q~seff(l9etu>yJ{;4%8&Noy4 +zsWpD7VE&J^M&sXFqh8RTT4TWN{69lQv7eN5e!Ck +z4&_s8tdp5v{99{u`crFsO!z}<>@*!eWH44K3 +zTKq$6B(wUhHKJ8xnD%035$^W*6YqY5Rt91(-~$!~DdTQ&Ri +zwc$o*CI@unY>wt=H|%ZEVJKuK6iAhZEm@h61D-BYELLcH{+X)4{< +z;)paqfHd%Z#s#9+1&sc-_xEqL6RHEZVhvgwA&UL0DA*g_SUtbk-Yp +zBX~EiEbT4L!Ax6HkHnHIuNoK;8dOJis}R*P^z|$8MMlVLr$kC5H<$`asKVaJ9(f8$ +z>V)KQJ^^_ct57c*+|!F>V)ZWlLj86uY2Ni4ATnrFJTOXyYZ!QKfMgq@2j7(*ad41r +z4Szn=r%j5j*aZ?_n>K@pL(;jY7|$hZj$nCChd=DXIXVENq;Oxb2WL$AJWh~CS00G* +zWma3*)RH#UR5}cP8aQkv;eEpXb5Lz+190WKox|FM@YA_dsZD@yq#^@%WjtewkZan` +zwufh)`B||{D>wQMws}jTv$f0&cc2Gr_blF?5jo@L&Tnd_JFs|Yld>|OD0uSj1EY@B +zSs`ue5!Wi>2!My}W1JuAKIZ^72VTJZOL*#zR@JN293qC^qO4^Wal}myW~bL;r>mUY +z&Te1cR+kE^%GAo57lsI|GXCPFVcwk329wD$HlCvCjb=Mm$x}qYoAx<;>RkgK(Yxr> +zi9LDOekE)v27v5Ckr)%T;mjevF#y6}4zT{hC8 +z7K1+me-OCdMR1-)|KMeNptsU5 +zieni+W+Dh32sTip@D_>Tou|c)99h>UL=>H;XqC(}Pz|k-vwa*1-Qb20+Ohaxd)5mHMr@Fdm6@9(8Q0=K`p(iQ1XMtX +z$|6DZ`6>9-k1vm;DR04VqJ8gxhS6-*6Mta3waw;9t +z7!Ye9@egT7Lk7hIj0r+8JF-W(eKP>MK03ibPFjk-8;950>LrXO=X%YHlFjINbcufR +z`bf;|xQ8fXE3%T8s1Lpr->R5p38HUH*7FU!x?!j@21F@I7!lTiAvM-p^`2qvz +z5Rve!|0Fl+RFSeNue1^#RB&up7{NC@x9=ne$$^wwTxVME!#5a1N+P@`{axbMk`W}a +zo%dJ*)O)DovS4u7$jDB&4ys=< +z-KDk?=l~cbU@9B1AQd;IbIHLv%Z0A-)SBSo>Qu6}-d6zUk(<_RRyc-}(7-OkbrZ>TM7~Gpk%_7SJW0fJmo7e6>!T+56~0mLS`t!=jUpzB9a!JJ +zT@ep5NUG#V?a39pnRxe_Sa1>@4rf1hK9bUDhOnI#%v*HD{eewbP#gvq-ggHn;z3Sh +zU#TtnEgpxp>P=eN>J#G{)u3h>jG~Bi{Wq-qSbddJqjWcHPl8eC(L~Hd+^0Kjef5u* +zojT4-Rv1Esh!m}&g4^+LlQU7B>fFGa-)!J5m5Cn>TPRuhf-@+i4LIW!Q&(1{9Isq5 +zDE+o3!YoCtye*$xA8QDBvYVo>PJt +ze)@zDCZK&lYGPM7{75|Pk(=zwN~D!hFy>osG7g#>$dO)KT9{UZSgkC_ +z+nr{g$+r)MHT}wH)Bvt+&n!SH{FAXj!hU7Hnr|U!P6}DvVYbuds6PZQSpTF+U|aS3 +z=v@fs=k&TDDfh1kq2r0#B_`vBHLYNq`8hvF6meV6N)R{GV6ECkdYnbW^hryy1f+D6 +zb#0KDv}5F#nC~}EokN!4Z#CiSK0{uS)y?g1_~ +z*D3JV0GxblSpA}YZ>Hj8`IUK2Zyuih4R91Wp88^~dU>IOU +zCb&2;qUh(14T3R}S)d6hmMG5Q1zs^2!_{4JFoRWKE^b1OJn9hr_;hZYP2w9&t__n7 +z229^e9a$|Cf*a8VMr$cT1K6HB{Fe`af|^~09x6#1_>-QZvg=(0oZv35sWHKWuOR28 +zdL~#jw25pDzETpC^$u2aC?uWLY-{Z +zK5kSrVT#oAuk|46uA;r(y+{?V6E4jqPG;LP@S*_LE@H9ohIa5$&9AD^PN?2}wTo|z +zgHI2Du~J??QSI|Kkb3-h;g#x4VYQKux8TRh#ShX7Zoo4+zL+$Ckqjqk(+JBFvf4$h +zL7e6JNRd{)ghy0nfpU*m10jTq9TnZ`9Pd>8%0J?sl38+NV&UC>wVO0>a*tW}r7(~5 +zWe@p#hy-j!)!8gm@l(W5@zLTL#%x)3 +z>aBZTwNXt?SJPbiB4HGd+wPX#1idmgdU_lo<q7S`$r)n@w%htUnNH +zmc0P5#u!s3q@OMO8ykm<6i6xt07X}kvkN|6~P +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 +zW6#o$9BZMick+)>)Bd0&pHE2QP&?gp9_Li~w +z49U*e&j$wu&`X1_#aaB;ou8#I5v~(`A>$`TSHT`^-bZKeu?2H +z;IqR)1yoNfE$C!2QQu;TIKYTsOBX(L-H5r$g8BhU;F!v{wZmu>BH)s|bbJBloI~#S +zE%1={5tAuS>aPl?VfJToP7`}Ws485j&uFloGN%VvVo!4-0F#qRF5IS(Yu0A&!h0$! +zqq%EoI5Xb@4-0|tYF22oTpRs2Hum8#KIF1!XwSVRE2RPbS60LD?lpOlFv58p?QfZG +zRLJYt$^)Y`oXiCd^a +zqfmQ-Bnrhw$npU0uVavko}A96Z%@TWoIkSzq&f4GL>1Nbw5L)}q(VXQd))WYOagSe +z=py~W&cfa8BEU2X+_A@a4sRH&Ym5$ySUt4ejAy`5k{efqua_!7pW==jMye{*W$tNZ +zGbJhe_VaArWc>Lx#5S;1oq|N0L?=}i0=KGTD4Dob7&1Tgc?SdZHuMs5IC7o^Yxe6h +z@-x$E>8U#tGw{RMzz^tCFZ05t-PIjX-Ve#0b+LP?@>Xjlyqwe;!Eb0{NMHTS1z+=& +zu#XgjOZ9&m3bU2Zlr`afHOet?0vNg+kw5*G!CHbd-^wY$SyuF^=bJ +zj>{ABGp@RMU@g}P_lKYX>~OyN3U~S5esmb*FPY<-1nSvo3TIf&$GBY?EXJckwQq@R +zBvQ|_qFuz8ZP1Vw4u7l;p|9#SFvC#LFTb@+~_yc +zt(2-1)4}ID(F}t0xM}(RiQNE_vnNWc>?I*5DLiD=m0u2^HwV=vOgVLz5m%kYU^V-H +zdY_V77q(X=fcy(F9 +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 +zJa(CSs_TFi&SYis0%{G~&@2F_m0o|XzZY +z74Z`lQoZJ$=m$GmVeeJFzru+uL_#NJvoDgNsMiR|BQq9n +z5TB+Tv)D7%AP?>qh1?;J#1(#Z6NQ4&9_+k_k&9bs>IJdhuQegH3Ln$60`4odm80}t +zl|;4|2G|N)pa`sr%ce5wv#n~4xCk`@DsXtTnhj)syru5^i0lRK>a@bFFKP_KK(Y(P +zf*iWSVC@GD)5aFSQ<0%z0SzQjD5e|-bdU2vte&^-XvBYs$U9{E?33=H_3%XJZ;#;ES|5MHTI4HQkYM!5AWCD`h8vD3>L3&R`hQ +zW8o6!fITFk!C)`Bo!px$atqZSJD1k3@=kPN{W7RP;R7&Hp}l0pgv=cj%iV<!A%ld{1sIQ#snPLvVaxY>?g|?vX|V$C;9H~HY>WaD3S1Ls<@GI5m_2Vf8)_cT@H8&@RYqGm +zkCiEhKsKNj)7p_wuKQ<;*v|t^?eJzu#wAw~i!3hv;JzV1O5C|YdNl&Vs|c_i_2>v59(sA^rwRUj^(jl_@Q +zrND=0(|#rrppV_04L6h9YQH_vHF<-IiA%J~9nmM?ljbubh;N!T%P}CaZeX?N&E_w1 +zy=e(7oPE4(24s1}JC;ZQI~on^5-j@c^bxoZ-Wrp!8V`y{im?U4BPv9pJ)>ykc=l1M +zPNov5!jVXE2n|90bQEImu9PG+KKlpP$gCn6hWbEr^L&RP23FeZ4nzx}Bf7g4AG5fo +zi(tAp5Jm;z_3)rg{17?8eGNSd7EZEAiD$8OAk~1*+|psW3`Aa9&+4v00fZdebk&n4 +zT~4LoUk-8WRUxgvR3{=j`y-lxNRM9+wftU5f|&3%qkE{E0@@R0jy@Q0h7REX5qn;7 +z`6b{O9uij5-fTmQNS)N95hwo)>B?8PnNokbiCyUkplXM?!g`-|6HPXx;=w +z+ue**YToR0f#g5hP<@y-9@CLVf(Hlqcu6l)Cyge&6Ws0UzslRBZ+itS!f(i4ig%(B +z4}dj62zGzwhvoOSEZXWm91VeQSMnf&Ep17VJV4?>fa6!lg<<)MX-(}d0+oEso$OXNzC|3lq`vu@IOn@AhroH>$WOnL; +zS*_eTjD}dIer$IYeU2ytd{@eGq42CUFL0PrsMxEn#o!Tji_-FGM3&=3&d^2OiaK`YvnrJnzY~1Zrj7$`IbOiC +zxjue;k(4-ask_4@O*3GPk)RSNj^mDgl>=}b?6gOf@1EhZ&7rrlL$;r}2)&^kP#)u-3F|19)Sq(A*7~wsebINA`)l8`PGMxla0AB$QUhK!3u*P?XDN~-u*a1(v +z`yl05?L!-kLUn-GWlLl@P$^t1U;Th$nzzl;D%ajQIWC+NS}73oqB%eiMpq(1bf%#k +zo4J2-X-KcK&Cgnxu%EPxxWu7DTM#OLJgT8%C!zB|mKm9;r|P2y)>>=KiaRZ7%am0y +z=PlF@s}eH-oWZp<=G9!hv)>n@sT~DJ-u)zvZSJ<8kPqoXZVlp8W>{WESG;{@_w)u6 +zw0P9nU3+Q&;@_*;N42n=BEPGc-xySUSteZH%57KW8@aPJgf-)KKY{Mv!N34Mt6Ahl +zdh6)86Whq;X!6o#$CAY$mt6vk;cwx1We`w!*?-Ill(Ad>1&_pDqAln%0J@z)aBEqAg*&QkJKQwFkYL>9_YH-!hezU;E#7_(yUH1zWRZ5PpP?l +z(!h= +zSP}%-Dik^ksAW?{S1ri^J95rteftG1<{-$4Aapn5T_*=E*}*BUo*rzDmadK;ijw9A +zdsCogAy7$r^b`CTFZx-$@J`Mnm*E(YkUtjpbG1qQ_k_(`>If`9abd@qv~mS`B19dj|A(gQ^O1c&}$-iP!g~D0p?#1c-|kb0fGo; +zZI9#IN2Yso))Dff$G{>-h2E2ibb#aXJK6ba6E~qo&{DpZUR`hjxCa|TF`j2x2i-S^ +zyq+G22+m{zV!4pqV+Df0@y0lXYM(naN$^TBM%IngIf01Xkq5Lf-e6Wvqr$ypIEYiq +ztNW0x44`sM|Mby8TcRyeAQq6@Tx2=5zKd|hFxs{AJDx{An6by}CXJ+WYv+CvYSS=j +zx>Bdy(QEXLyr5Leksq<}uv6Jg^S>TIU16XA&p%kXsYb>ixG%laxR{?g2dN_5>4rAUR>@m>C +zAxtH;CZN^C)zq%p0dGN;4r91&&UpgEwRBH^UucIJALYVd^EQiaN2W2!dKBUYph>}+ +zplw(3B1U3|pF-mzib3(yQJjHAlmID(-Wm2~;va*13i4Q>s8=8X&yCjKXC!8-D>yR= +z)00Kr4)n5R0mJjK_kJKakYDphFihHXD&E9J>;`jvux3A$=!qx4e80G8Aoz> +z?VeV5p(>l~s4ZjwT2LRR +zft250oz_TeDeAV0NRUtHhOW!FP!70A57IC6!l5%AF)^Vj0xur?gaCf%*#3=cL}8m% +z?d)rR!uM;HE>e4~D)OQ!5wNQjzEcgITYmRCtn6bq+{yiBtww`)&oKGVekUV@a9%&% +z2l%eYc)=sB+Cz(20&U=ELJJSt>LkMz%XsL4DA^Ogf8tEO0Czl-68`2>T#Pvg^YzVX +zEKI6S)RK)lX%7a=1mE3S>4{}MTZz964)vw4KS_lB}}kR3Y|Z)s=Qg*`H`dh*%m?u9Vcxe +z2Zdkf8uLaiHXcZX(p^g*qVUzwdX}5MC&CU^4|cL@GGkr7S#>vGx~Uvr8yzK|-xM +zqe+8_EM&k%gQS(<7@7rFmzM?wLo}BG^?$cHM4RA%mgTm^uQKjW=h@`ha99)!DuSsq +z$`#BAb$M#q0V8u>c2D`7gZ=F#UgS+ShI3X3Qz4;!CCXvC-W+hAgx`R~DdJXGj=g$1 +zer*_4I8dTrNRLYp5K9lcsFO5JAN>h@H}%T}C3M5oHoice@d7RNL6T52tNwELlyUw{ +zyV(StqY`2o)uh6;%xlq97+DM_2vR|`koR?=J7Cr&sojd6{+$fRGuElKFN9baDGvZ!P>2z3NR*b8`ih7?=2ZN +z5H$lc{dV0?dw8}q!HtE~VnHpN)zJ`Fb}+lW&(zOFCc5)W_zV1?gFcsLXxime&o>ln +zb;4@lMApe=a##Qbm~d7snCg7j!Kgm%HZ8R$mAXduyy~e_I1Dtb*O+mLh^kLw@m#nb +zDXJqe$I-1|s662bZ4G|=l)4^VHWrdYzARweeTBY^>gjb{%P;Bh6J69GXo0^yYcPr9 +z_6C}ehB5-0RGe6P8k~ze2OQ3+_t%5IB?BDRsvA<;gVY)3BoGXNd(mMB4_ON0s5&e= +z5ojWxjOzKQSxCkkNYtzlHg(^wbU;=N?qsmV2r0F-Iz8CCGnk8)P+o+d@>SwFU93m2 +z30u>>gknu#eQu9a^Pr+y?zP73mB|(h9ZVPjEY_pkRwfRgTI@+9wWz56*K|%Yp&1THadfbkVykr +zFJT&V-t_qmHB>>aq|=;^DC|2}ZMWYqsMS=Yd~~x>G`wh~J1pu~_?Ip`;qy1Tp*;~^ +z9vNB9uzJ$-aBvcsJzJt8FKiTo!ZAVL78CaJA1s+_bkG5FRQM2=s=GZz_w)B9(!Y3- +z$&>H$b*2)GEgfjO6ingn<$cAD?_UxH_>P5V` +z#jEv~l?M~(!7egg;F~F+mZp~204UgBoQfM3YDcr<{M5_2NApF<1y_j2xQy@iRNITX24(;K?TQ+&$!{=hylVnTQZy^q(4TGmoAT8PC?-R +zhFG8!uL1($;Am&v<fo%bUWLFtt;t>0cXqlm?Z-VT0k>T`Wv{_3%rd>9|3&*i%EdH+oxKRNje_nqb?p+He>tq$=b|MNNfFWoTbYZusO_4G(wc +ziv%5GhsM&#&|Ly_w|C0+RZfJ`2?M*#uQq*tF@wjFe6p_a_+hi^mK~`d{a^UmM?&X3 +zRWF&&pWmL}?!3=f=x$W6b(I`^L&Lvr5bJUFhe0cyJEy;AXZe}Z=ZPQXG!Qmkg>8XN +zBHwJmQcA;`;f_a9vBjR*mw@noVu}xB&~@JOMKH~&s(5tU%^Y$K<<$&7=<4Xc7V%2U +zZpzC6T +zzoxDO2CQdLmy*^$8byAoXuSp&+%e~zzI2<&d17$c +zh{{*Pg{j_4`8qu76X4HgCE<~SSC}~p25{uqgk)xAW40F@H>Yt0nMmX?AJ<*WMhyOq +zOBovSCr`#P{oDC7p^42*o+e#Pm(xx;bV=s{G}upcc+~!ghbw(4=Xl#DdH$ZFX^7)* +zeT845e0?gUlUse5KWjt>sQo@vA^KXUhCUIt=o{yhiG}2}>@n^&-yIIP^A`8w5<~7V +z#ks5j>B|!M%9WogZjWXJ51*(aKe&EWtg?z#SsZe813)DM8^!+zqd;80P+exlvO#4L +zy>P{+63NI?)#t`>q)g*3*X1c|Z{Dq@kkcldY(J>QjaPcR57Ej~l+H=`&0+-Mw=v>1 +zxQl1&dJJWXUQQcjxm=`FJ`h!=ctV-TqAtm7*(R#e$5w)my5a_DQ54VT%x$^^V{T)q +zDL0V2uqNo6PE~=cgoE;+a%b&XbD-30oklgP-`nOPQzT~MW|Unp?d+pD6GVGlE@7B; +z0IH2y$h13v#4<(;v4kv+lo{yH@55=d +zo#M1BujM`Y5To?+}02GU?tf98jh}c1j +zr&fF)j#YoUP){URFJSit5<<52Vx@LgHB>js1E|`fE6}Q%X^_N+ya5L7mjw6EzNU$7 +zDWuQ>mA`Ki7+v-Tg4$*PfBwZ(n9wZimW)~9t +zF3keG?v%GfLEhicQ&?8nqOEfn5a0MA*SgJIxm0-~6@T>6CRF#<(=?7CR*N6_961{L<#xm>AgU1o6H&G#~vQ!YS)wHcvk49uxZyG@;t6{s(l~ +z&nKv(@xYl2`w8-_7F-V#F#EDTjQ`}%Tp{7ImhvRB>C!IQffffL%FA;Cgarr+^=H&J +zOTfE@FDIOkWq`w2oKzD)pjat(eD3qn-R4VCq4+;?vUbA)*Y3xGXApeMOuC?!R-?^u +z0u!TsXh6LI(vPfHxDl_qq~R5t4e+zUCFOuQq$Xx1_e&D1jCBxK8RyL@<-y#x=q{R5 +z6w?R_+mm1&e^^pT%Re4-?kUUzP-w8)DEE?!iF{&m^iUJ8LO-a7qhT8DSC5v)O +zVr;5SeUgt7H}&NM%Z2F!ft#}Lh8OC^g=vcE3>{20!cXF?B6XXkza_bvErEc{F$@l* +z2}Uzfk5vg=GPFsHmVaqRp{iUxCOgq3l;nxI+mioNXCZW6!RY@ea-Or0_&7jMQFjPJQUHJr4llSy(Vd6~oM`2hTQc7XzH506{n7^@^ha`xWwGZ<>9dw7@h)r@D= +z>Cz)1t4eLpQu5Nj1Q7o*ddzs>Oy2jXEsY}OfD3MSPSNAw)nC9430R8l2`V=Kre#(S +zQ=;VR6%id0$oVmW^FA`T?WCBurja1mU>wAV22}9NLMz)z98O; +zlS{sa%U!~{DP&Ayho087S6oBZC;i2is%}+#iAP`6(=WhOt`W=&`s|0^n>_gDGX`{t +z>pbUyd5}bnl2qgJEDn+ic%C73qw7*XCz4qtOIwib4*)e2=ebSuo(Fb``6vw?4P^bC +zNzj?6UgS|!vRFe}mkU?+xD3IZ&dz{LmFk=rO{cdS3JuC64G%4_~l7oLQ2xWnF*4yCxZ +zY#Ou=7#+`Ius7|;(5IQ%hKz$!O%0b$-YJhezm2ZF1z28cMbvZLW($uQpk31I<;v^3 +z#QU?Y@C{MKxqOj0CQy7BsSlODkyMAyZMT +zj!j6_c!Y{AHP4mqj|(R_hxwS^7!KS=xWEODG5_GF*#NjY@R5LdToF +zWhYCGj)A2Bqa-^jUBa^_JLHJucAkJF)^x@}X9Xbe-+yez_~kKHKZE)b{@ayq0ii=X +z^(ctqE6SWjgY&ws>!2A|2I6c73Ua21av7|u%7@M}Vb!2mplIj^r--}T$!LkznZZ2j +zvz<76Nu2HWQzrvqC1yC14rI)WobvQC?J&1;#-u1NH_rkBgfKZ{^s-drKI%@4tEf?V +z(t4zyNiVsa+-)k;PA%TY+Cp$HJH!bJrh)qW%5+M;K7tU$gFUe>=Cs~tq)aUs74%*M +z&TW5i&%O!Ed02w(SO7 +zrJr)~_{iNnWD;kD#MIpQ&p*Ult>xe}g#`?T(+xIe5K%B6GS>#_xR3yu=|Wc*n1nBX +zr`sv%!9uJ-6_J1KD?`#!UQ-hccUu=%Nv3s1P?C6SfKW_uzQ>jNP_EO=@uB3S`qrxV +z2{77I&loR~eWP5wHJe<4rKsM^bJO?380Y{$q#{3$>1{j=>|>`N1=B`$x$>M8jhGz0 +zjwHp(Gz8>(o^a{?81C~WePLEvNyOfFw4W{06u;Zb-^sv4)JD@a`)P&rZX|&Y%xNu= +zZR7s*C|!)!)L)a|SGK5RiK0O^(XmRn*P+WOwPtEzqvXHU0( +zsxK=c^}wvA?#`or)Fg?aO$2_v1_>aDEte}X5W)A{eyo4TX!DF$Tmu&ihTo9m0dUZb +zb143vB|GB5F$iy;+}Ym&e}Mf)sRgIwApw*T37q%(}USd +z3Pv6W*^wz=aF+$1d2W-B^O(kcpG?5oBIBz!^|u?k3K98LG3;@a-OZ+PPs3hIGRpVb +zb&mJ!n@tE!{;dez{Ead!TpIkjn!Hq)BH(T05@gCC1fAnC`U@(hf3hfFSB@obtg7{t +zmGB3NOeeP`Q(}2Dh|N*bXF?Dm1D;4JTj6=2$_~W`OA&23o=23Vi^WB`(oax7+<;xR +zk|FX+&_H`%#0$I?YE5D2$2vEo{H>SVnEjzaa?GwbpeXj`b^?WWTw7hAU5}eB2p&@y<2I+pFd+dMjY#tX0L8cQr#%rIU`{DuRs75D!mIDaIu~Oi|0HIZp +zMs$f1W;+dRVp8A*H~-dCt%P)5Nxb>UwuVDvz`r|2li||o4=~i2m1V350-1|7a+JOq +zb49X)F;w0C9<#!d5P9|1{XO)8Ay^b~7T)=|_^;|XK9g!Zt?Qh1io^C>(h>g4Bud_U +zgA(d=ASW*r)JTlPl{*WAZP_Q|%zBQuPeYf%lVa5Kv{aFKBHs~2BP99N5JQ(`yVui& +z;;a`r)n*ZIh;}zz{hWW>bpmS~sFQRdO(V_5fpbwE(ptR*xqcanvSdN-+`_KuXWBSd +zh|*UsX^#Y^e58R|=#Uc~tn@{M?1_nlxA9c$4MYzlh;bpVo#ND^r)Z=uoiA)M0>sxHFx)2kEr{%bXuWOWiB3e1ZaIzA%8e#974ktz{frUAM24LgC;h+9=n1LES +zqcSC#U{j3}1rm(2%mfYM{yW4AIH-HdbxSlDX5bl`o;V_fTmR)44hjE3L38mbAMyuc +zK&C#0WO4AAfM0=}BLu+f6$X9J-A5{kF!CA5u-wO#5B;ie5A8md$lX^MPHkgFH2e@> +z+moz2r}RetVRKGgJr9|@#g=0bB{hA+N1%gkg)@F}Srp?THKHz}O +zqd^e2A)eKRzO2wdLxY8%AkLpdBvgp4z)*|qCDC=eV~F(jtHeWKXTTi6ir~0VN}$4` +z^e|?x5`-RaZU<3;!`VVDHJfkpF9uR1Jd|VYCXt;gW%?q5Ln?gvaW-}5??5QauRI4q +zGqy!p0@DK&at(QP+@Qqc$Ist?`s3K2nUr4f%^Okst5MKNlL`OqW5xc4hB_B3`g$8^ +zdOBQRFBOeI3*QoKbX77OBs`HohZV!HLR-?2b}PH4*1>7#MBcbCZSH*91DLwr4!|X- +zK2`|Bm;Y%MOr%y6f#rUzGIdo*X&T-8v|Ruy7tW?7s+EY +z=UO>Hf?S{~nIs&fDEoMdFZZ%yr@Yd2M8hhpb8Fskcc+j(i%!b-J}hLJJG2Aka}F#T +zUBARssRHdMxK>6aTxEtX!NbL- +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 +zQ`~QkD8my%|D8)NUTKF*dbkM%r +z(oV8_9Fj7*jZl#CNw-oSb +zuI$_9#=uQ6(I|+*6!l@KO!hqoJVV^^!IV%j(sPC$b}?)LdB{eUE)oJqKFt}R4(sPi +z*G4LFvS^yCdpNa>@w+*v2|5x$_pTOLDl +ztf?{_F*ax)nc|Q7AMPh393mj<4%t57=`Bo^UAtq{UP|+HeQcRd?7zs!aci=mHB{jb +zTW%d1V35**C(t&}Oe=CyeA>b2<%n_3Oy1CuO*0-w`R3w{Dk<|sf3 +z#Sdx|PceZjZgo)&Cvzwb+f6R4Dpo^zJ?NWIc7%Ok?pjsbnGvc0s2)*8J^lX?&DnYGh7CFB?|p{Wb`_~D|m2nr`I +zGNDFhM%f+KL3@87Z$iaf9f)*YyjeZusxscMw{F{~c&SqL?`WtmmFTK-ZFYOGc{ +zpT`FwifFcY_z1_Rrtt+H_c1d~l?q*aW>gM4f~UT=mdL=+Ulg +z%pE!$Esy0+yQt7oj&e+=X%I*!mOGF&Ta)p*KFu0=ooH|ZO+syXM=`F|xA-1e-7J{U +zbLbe?buk?=Nf))sblCCMYsp8P&p5tzL}>*GwRY&N1!|t{Ysa7vFK#uvkfQ+36BD}^ +zUoGTAY#kf|P+oMPUXYs#lFV(K5xxd)UEi*Y1YPloMY&Vv5WvU*Pb`h83HreYtZMo= +zHh7fx=rIMVqHD`y#xUeAFEzLvSAP-6Uili|CR+Ph=nN#U25&vdp`VSUgWPZ}Nd0II +zd=tB-9L!r-R7cit2pJZtfShErS=QRbLEY+AMtF8iZ?bg)Bz~vgP%~cI%RV@&@i4_e +zYyZ^#8~uPhVw99VAiEH+u^g$_nXaX&i-bhTFM +zM7(se+Z+A)5$CRX&N%2}nnFUFgCPb-QZu(eJyk@6HAW&Cqh=;Aqh9MZ2`t +zv5Y}z2!dm3;hq}DCZ2Nbq`X~s_3D~{Lyz|pNBSj3n__N|{|4uUlDUckxsH6ysAY(C +z97JaP>j8oTkutAB4WHC{a)VM#KWJlKx+>*)JEv$2b&iT&92`A=hyA$binP!xB{XsC +z@HWzzEm?6*sQ}}OS?5v|k$~Q;DO%*%SO9aJ8T89Bo&!Cr$EUWvL@Q9m$pFISS`(0y +zN7B9lgp0KT10yC>oT4+)+dpK@OElL&85Qr2h9KV#)8+DFcmXMatPqJnbDKzH$RCiq +z1GV*g^hlHs&$ZN3C5)bjFB{1eM~hb*kPtJx)PpUqjlPD9VQ1)xp!21gP9`O@J~iDRt3cbGEM#*B|&CW@O$Rh&F9^$dWs(B)xe_gf)OC_fBLs +zUYJ-~I^;qC8*-Y6jvpw#kk)4Tckaa44bg&aA)fbF`XPh!#tLVG1Pz%4h6;XKW0+LG +zZnc_03At6J~VXTp>+E^A~e$;hLE{a=jM-kibqpCfv0j!4s}lp@aCQ*4t>Y +zA#XAu1Jyfo4}byM?VDoQ-;#o|;9?n8YFqBIdhoARCFE0dEp&VW(V`*P=yGqqUg0AJ40)eCC;^{EPC+1$omATag~-9$i3AcN7_keZ9WPN0Y3M7?2M +z&_2RveJSibCtRrx%}D5uVy|X&DZn#5V<4MH=ZSrlD61>ge~xcWS+%xWqZB={87@S< +z5+J8d#vmB)08w$D8$~{HTWE=e=ZK2jgP{%Jd?p73=KdZQs>GWUru}LO36RBrBfWOL +zgHHp|K(n*TB9w7=b-(3_Re0)KgEb>@8b-3F8v-Ejbo3+1<(;~GuzQP4`>m6F7>DLC +zXAi(8?+yJFXojKh@!*T&51*AkbV*^Upw?%64}au^cXe|% +z88E^ZnpAZP{QRlaBa9E<-a{up?Ta~n@w*p)WNpeG&;I$J4+l~JRr|TzC8%r2@I`y~ +zNPNf=jhmO}uM!N7Qr%fokZM1CsnSa_t&NwI1$_WbAquxt`*W1Pc#xmeDoA;J35?B> +zCF)}2*l5fE8uXc;=s)Ms&4;J!+jh+eRq}~14+nZ9m8=$uIgz_65yK1fr7B&%LXQg# +z@YmCAz%nQ|l)9D0ISd8Pou%<{2Ry-X7-fru+~&prP72CsdWAMVoX2S4*4@Qy-t^J@ +z?VH!HK^DAOUEEw=TwSd`ypnyC)G^75Gv~*2Pc*uYWqP=@g_n?CKFDR(bjRT2{6^$M +zr%=Eu0(=4azW$f5&JKrCpdTZk(Dr+J2CHvR()O&0txLCh?`Tdzcg{hWUq84qugj1g{ +zlq0kE$$zz|m1+@sWbpFhPecc4jYN%)wnT?Zq7dI(6+DXg28F#t)MMywDN5uS4pJz2 +zkcvL`g7gr3Oi{C46HlYKZMqN<`ksUO_7{>)mVjKX$?CYEBn9%B+j&s7I`al&OOsu7 +zdA#U}uda?4UHe6|@puuvo~X2-N=WE~+|4KhZ4tXOd`fw_2>RLFDCb}Bc9OPMg^}vMD*xhiKPe4W#g%@^h5{cHH;O;RpX&UQJZ?ucQl8Tbq#9$t!19n +z4eyjh12V{&+lvM~S!1b3B6MJn`o?;&gj9-9nyi4@ouh?l)u5=`H=F|N=4WKfh&N7K +z6O~TcFzS4hy#AmYg08u4&x?q9LojnA7etw!&)4=mKF-S0j4T$N&xXYXCEC +zm5=Y#8?+!L3!n%*P6gr=^}ms{N3 +zAOzwMjVVjgi^*lBDlQdUK%LqXH|M$b5O!F1>gM#YepIUO1A+0H+t@H)mVXLDHAJ(Wz(xKlDR;y~2J3GK_tJDiHz>lh}w~jf@fkpA^MwO@aFd$>C +zqe}9+TG6jKl9#GBwV|{jx}~+$Bg~b?>acyt3tRW{LKoJTS1L1#uhj&|j1O@*6|K@L +z!T8YvwG&#CcGyPB4bNd4E5ZD*m5p7AYu$Fo9yHWC4YjD#V=L4h@S)l=*M%IgwO$hC +zS-x{j328Aejp_>LsOMHFMaF@IN(&zKAqtCCjZ#>x+%%R>x!*YP^`cYqA93qivvuv-c +zZM|I^wCA1bXj{c*U4T%babTe*>z_Whc5<*F1;#VdDAlpTPAH;>J7woP +zIy_)>YqW6zfH;G}efq|J8gH+z%#T~UGp=p96m|bd7r(=(l3Z=sCNK21-tP1;agk6p +zsrNKjMkE-((LfPV8L)DzBYYhCMn&AzGob(}gG&COd^~C!?n7J!SSN;IQP<>#)ody> +zP~Tcgj6PX`KP5-UJvpEx-y??#NWL09oD_fl@?X!$w351L)O8{rm*iXh9=MjtQmbNs +zCjL~zI?+)RC$PcM--L3(r0C@Ge2LFnQT(Kn4UZUK{>7!D+e5lSs)~c35%ELVW{|-~ +z6&6t&<}LcQp9O-Amu?C_{m_h>*atmvIqsPSJ|bd%z`>WH=+va2eT0q +zvx{p#FAe%s*cVJM586$F@&Fup@29Jv&n6gGD*SXC)K3EN=RrE&`)L-mFN69`kj{en +z=0UpL1#1^8@oj-xBi@pSgdahy5X|8aW2O`VbD?jlL1-np;Q8ASgQ)?LRh=dREL(QCQ~*%KxOTL3cpKqXO2G#jJgCZ +z^c3kdbL-*D%M|6X3E2zdEiduyK1hp$;3t>uc8&@eH9&OL#3#oBv--A9JMCqh`Bp+6Iy?Y-VJy=DuDx?v#R8q +zw(G*e@6aq`UZNgBB;QY$CZ;q+Peh_=Oz~%0M-k@ZSS}}X=URQtVVRZooINsi0fjL0 +zHP}CV?6vvI;RkB0*6(Q!Kj5t*DnAt?_d`|p8xTb!YG|U}|8aA&Yk-YIM{i5Xm>ljd +z_&yU#SSa{oU+73BqydZd01oPnSc#9PR0f5ak6B~P-jtHzs>48lP4ae|%Qvbs;^s)D +zY!$+u)UO_TP+(_b7A2Z1pkW>4n9GR;U=_UwCKP+0e2W&DEj769fZc=tj+s1kl-_G; +z&fHz9OMEp|bm*t}So9{);;hw1&2gKuQUccwNKLk;tf*tO=0zWXN^65wAomY})`k3F +zE2l$7Z;ezCSy`>GZSz15g6vb}A#N(R@%&(~L{ +zua>MqPi8JWQ8d8^FAVwKshh=vf3pZ!36jf0B{-USEsD*7h!@#xY4K-#J$jfJI7Mbd +z6Du;;@{(aON)JwwbzTx!el%THaif60e_*(QU|7I-(= +za`Gp4v>^nJn>momAFH`kiUec?->IJ>xx2l%eS7gaz4!h)x%(Wg%OLmi^7^%NqPrK> +zV8& +zl;J41xlX_6XQZOXZSb)T32YQt#FmLUn$=(yaBa?&`}qFt%qJBypEk^V$}#iFj(eHk +zJY@x-Fzd|Fmf7>&z7bE4uM^v|f@dtYcYg1aFOQUvNcJV&)VxoEGIcQy*@IbLJJYSFE+ +zzPmJLoq8i%KNfT1%bH9Z)e=i$sdW3-TDQ~9(7k&5J$X!9QA^ocRO$7f;Z +z4gsA$Hhx%(z0lGToZ0xI$vU3=bla)F@)*1!c&1ISo@ZJaNbAZt>->{i{M{eAUBmCJ +z>q*#||Dmic6ax4wHyjq2Lr>=x=pj`5?KLYt`U=s#nSIi?EE%Cok^swEtnJY_t^%Vz +zKRtg)7ll>-gP&ab$$2Tr0qeY~=gz4%w|=s^#||3>2w?$UPjvN~S9f0#+?{M> +zCT`H+ZIwhf$<692xiMhXRUk=kJMRX|tO#VzHHB3LNq9-6OFZN-(rCPB^5$K7ce(n! +zySse-=IRROr@DQ?s>J;K21KeC3VJWl3<04x7>}Wq9{}ycD{>|^!}p{|kl6W##cm5M +z@lxDN6<(_JQqoIxUTW{ABIc#M9-`DsWnM~nsRu9R^&WY>M>{taGe6~3jlIdo-e6*H +zFmdjsyrIP&m|_o1alK%5kP&TzjCdVpv_XbQ!i*x!sDca-jQor>4>Q7E3K?XSEX>#k +z8C96k~g#vG4YPDWqxc$71O81KTI^dZd2M$pJcaLz{U +zpSQODHX9SIM)K@tgVfi@98MRZfQO*d4)d(6@6XuNZxf!+G +z@KMgFuVw_FW(4PEgon*&ULQxjw<8>rqdIZ~c{v)PEJit-FsB>gSU1`Q-Dnow2ow6z +z2>a1YH=|t;k}JsZd-uod?byWoHu2_>cq@^3E1r0*aIY2a(e>2BrqpXC^y#@S61r +zi+|RxJCJ(S)OmLBj+4^XAo +zd+GP?ZJ~<$sQ^$urK`LFR33mUZ}ls00FC!u;|;v=2Hto;Y`q>@ucl9{T5nR)+wanw +zqV%Yz^cGZl;Fca+?LWz@e{)!j8%tdk%Lr!9d$vBB2UdBlbadS>$h?8>?L%f`m7~LiLd87EQ1r2c+I5&iz=B#tOze-cM@#z`FUGEU-%n{yIJoSc(5 +z;^myg5jW=~j;Pd09C1=7am1uf;)s(vi6crJp;!7RnZ#23lT4yBPBMv?ags^goRduA +zc4zf-= +z-$QYH6DP?kWpCM4auKcAGkPdqt=?R$&VKje3mvuDb4DEL%n$Zyy$WMcO_dxDCUco4 +z%R(-TcVGPR?wfD_?ecRYRGA9Y%8}X^LA>*Yi`I1G=a_b70J8X-l_9>r6 +z)1Q)0HeN4m&a!#;{)_wn`0qdepS$f;Psb`p(`_dupyFaDOXnlVv5vg8>u>)f3;^e6 +zFYk9ncX$53;7@;dzG#6qlIJ-8^6%$07O~D^;wQ9c0R7?oLjy?jK5-(cP1O%GgKdD( +z`Y0+jjZ9Szs;uiHg}*zqtx_C_@(}|oczMvcsMda7%30U9JfXSuf{68MNE +z^Ppt$Am_4cIVA@(fmw0Eq&&ZSsYdWc{rGLp +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 +zlo`ULZniuFUvKG* +zCUnTb;ZP%T3DN*GJGLkFTkt`M6OCAf0ui!a^A;~{RL1d|F~_GDPq!471|R>Ss=I%3 +z>;L}Dh1<~BC>!QW&%1(rv>4aV_T)Dt7Qw#uW^N6gTfV_}Vu&yz`Tp!D@8{#2$&Mp9 +zhJK+gJQ`*==gD*McQ3w1EgaDqrG~c2g{Xf-W}K+|QMOA2 +zkTfDF=-q>D*uLvq&A+m;&-w}pA*IvT!-s3u>f8PuuSCo;Qh9MHOiNu~&Z&B#zli%X +z?_04`H=k66udBMKA4ILWWEe8g3K)Z8v8hE}HU@~Dm)f-fTog#jE??#x$aIZ#?(YBw +za*odq0!U1P;I}{5P$->vF7O+kU9g6p-2EG!mOJcOFzlH->{&4EnKSH}9rkQ`*t2lh +zv(c~txdcZ0XW_7C-mquhu8$6<+n|685n +zF@_?XK{#lyOb^wum;m%mT`4BVElE5D9zF0ZcAH`mwk&0Cf}ude*!;+Ayf +z4Rq^2GP6V +zQx8gRL7Eh@+=+&g1&e!_sA}^O;J9X0($?yrIW)WzUD|iXm~JbPcg)&@WD&~^O-w`! +zQb-N*8Y`^TW7{<7Ee^(#lz@?4M^3g>4<*QmN>9g&hPR?lM63o2z}%=`WIX_1(CrZV +zA5)*|uXtQnbqSMVSoF|$tgRjdy7&T7Gpq5#tK^~QS*>PWw7U+3*P?@V0cAUuXbT4e +zK;Vl~3tE64T36tE7F7X&%gCldL8YznqMb}%RPzsD(^t!eidDefQ+!xD!77o#TUt4If^)?B0{6s3*kuJ4TGrgY&+N +zT3Geq(fP&O^v#>A+Z%Rq!LFj{IelteU9PU+P%|BCcN(=$66M;W(N(vEdBJ+S#?|I5 +zL(|u$*RL`Z5HJg^P_&&oL$fKh)c7<%(Ju$gQ;xwZRT)lxO7E**qIajQnQCk1wKW^s +znz?PwbX&8bttm%S4TBx#&936zwryfLh=W)); +z#@HK6|^w(pLGa={9#jz@p~v +z^89mk;c@rm9{BX(HxT_?_D;#Sd@V_GnoFVV4K;Ma4y +zcjwTjZ&(uNwTQX=^p7+A_wLF1z)vjB;eW$-)~0!)=8xAJF$Bjd`Yc0{ESo+mgv?P} +zlA%!KU$B2FYG*>0cpZSA^M^#V`{_u3WMoat0kIcPKjZ!d5Za$6u*mkZ^3!KFu_NVR +z!~P2oT3ZjvMc+oOnyc$T90LIP^7i)i)x~PH)X;s9Pu9M=xw&3lUM#81RE9m03RZP< +zbfucL4BxfLMOM@iD;81~i|GWS8>f+xval+nwyN|!j<7L)# +Y_pD0p)linyEF$Fp2Vv|m_Qne&09~= -@@ -969,7 +973,7 @@ void NavigationURLLoaderImpl::OnReceiveRedirect( +@@ -990,7 +994,7 @@ void NavigationURLLoaderImpl::OnReceiveRedirect( LogQueueTimeHistogram("Navigation.QueueTime.OnReceiveRedirect", resource_request_->is_outermost_main_frame); net::Error error = net::OK; @@ -164040,7 +154828,7 @@ diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/b #include "content/browser/renderer_host/render_frame_host_impl.h" -@@ -2592,6 +2596,12 @@ void RenderFrameHostImpl::ExecuteJavaScriptMethod( +@@ -2648,6 +2652,12 @@ void RenderFrameHostImpl::ExecuteJavaScriptMethod( std::move(callback)); } @@ -164053,7 +154841,7 @@ diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/b void RenderFrameHostImpl::ExecuteJavaScript(const std::u16string& javascript, JavaScriptResultCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); -@@ -10848,7 +10858,6 @@ bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal( +@@ -11145,7 +11155,6 @@ bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal( GetProcess()->CreateURLLoaderFactory(std::move(default_factory_receiver), std::move(params)); @@ -164075,7 +154863,7 @@ diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/br #ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_IMPL_H_ #define CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_IMPL_H_ -@@ -433,6 +437,10 @@ class CONTENT_EXPORT RenderFrameHostImpl +@@ -438,6 +442,10 @@ class CONTENT_EXPORT RenderFrameHostImpl const std::u16string& method_name, base::Value::List arguments, JavaScriptResultCallback callback) override; @@ -164100,7 +154888,7 @@ diff --git a/content/public/browser/render_frame_host.h b/content/public/browser #ifndef CONTENT_PUBLIC_BROWSER_RENDER_FRAME_HOST_H_ #define CONTENT_PUBLIC_BROWSER_RENDER_FRAME_HOST_H_ -@@ -497,6 +501,9 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener, +@@ -502,6 +506,9 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener, virtual void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level, const std::string& message) = 0; @@ -164124,12 +154912,14 @@ diff --git a/content/public/common/isolated_world_ids.h b/content/public/common/ #ifndef CONTENT_PUBLIC_COMMON_ISOLATED_WORLD_IDS_H_ #define CONTENT_PUBLIC_COMMON_ISOLATED_WORLD_IDS_H_ -@@ -11,6 +15,8 @@ enum IsolatedWorldIDs : int32_t { +@@ -11,6 +15,10 @@ enum IsolatedWorldIDs : int32_t { // The main world. Chrome cannot use ID 0 for an isolated world because 0 // represents the main world. ISOLATED_WORLD_ID_GLOBAL = 0, ++ + // Isolated world for eyeo ad blocking (element hiding) + ISOLATED_WORLD_ID_ADBLOCK, ++ // Custom isolated world ids used by other embedders should start from here. ISOLATED_WORLD_ID_CONTENT_END, // If any embedder has more than 10 custom isolated worlds that will be run @@ -164193,7 +154983,7 @@ diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_ #include "extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h" #include -@@ -454,6 +458,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnReceiveRedirect( +@@ -461,6 +465,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnReceiveRedirect( TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); if (redirect_url_ != redirect_info.new_url && @@ -164262,7 +155052,7 @@ diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blin module blink.mojom; -@@ -844,6 +848,10 @@ interface LocalFrame { +@@ -899,6 +903,10 @@ interface LocalFrame { // the given point in the view coordinate space. PluginActionAt(gfx.mojom.Point location, blink.mojom.PluginActionType action); @@ -164385,7 +155175,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b #include "third_party/blink/renderer/core/frame/local_frame_mojo_handler.h" -@@ -356,6 +360,14 @@ LocalFrameMojoHandler::LocalFrameMojoHandler(blink::LocalFrame& frame) +@@ -357,6 +361,14 @@ LocalFrameMojoHandler::LocalFrameMojoHandler(blink::LocalFrame& frame) WrapWeakPersistent(this))); } @@ -164445,434 +155235,30 @@ diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_ur !Platform::Current()->IsRedirectSafe(GURL(last_loaded_url_), redirect_info.new_url)) { OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT)); -diff --git a/tools/typescript/definitions/adblock_private.d.ts b/tools/typescript/definitions/adblock_private.d.ts -new file mode 100644 ---- /dev/null -+++ b/tools/typescript/definitions/adblock_private.d.ts -@@ -0,0 +1,191 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -+ -+/** @fileoverview Type definitions for chrome.adblockPrivate API. */ -+ -+import {ChromeEvent} from './chrome_event.js'; -+ -+declare global { -+ export namespace chrome { -+ export namespace adblockPrivate { -+ -+ export interface BuiltInSubscription { -+ url: string; -+ title: string; -+ languages: string[]; -+ } -+ -+ export interface Subscription { -+ url: string; -+ installation_state: string; -+ title: string; -+ current_version: string; -+ last_installation_time: string; -+ } -+ -+ export interface SessionStatsEntry { -+ url: string; -+ count: number; -+ } -+ -+ export interface AdInfo { -+ url: string; -+ parent_frame_urls: string[]; -+ subscription: string; -+ content_type: string; -+ tab_id: number; -+ window_id: number; -+ } -+ -+ export const onAdAllowed: ChromeEvent<( -+ info: AdInfo, -+ ) => void>; -+ -+ export const onAdBlocked: ChromeEvent<( -+ info: AdInfo, -+ ) => void>; -+ -+ export const onPageAllowed: ChromeEvent<( -+ info: AdInfo, -+ ) => void>; -+ -+ export const onPopupBlocked: ChromeEvent<( -+ info: AdInfo, -+ ) => void>; -+ -+ export const onPopupAllowed: ChromeEvent<( -+ info: AdInfo, -+ ) => void>; -+ -+ export const onSubscriptionUpdated: ChromeEvent<( -+ subscription_url: string, -+ ) => void>; -+ -+ export function setEnabled( -+ enabled: boolean, -+ ): void; -+ -+ export function isEnabled( -+ callback: ( -+ result: boolean, -+ ) => void, -+ ): void; -+ -+ export function setAcceptableAdsEnabled( -+ enabled: boolean, -+ ): void; -+ -+ export function isAcceptableAdsEnabled( -+ callback: ( -+ result: boolean, -+ ) => void, -+ ): void; -+ -+ export function getBuiltInSubscriptions( -+ callback: ( -+ result: BuiltInSubscription[], -+ ) => void, -+ ): void; -+ -+ export function getSelectedBuiltInSubscriptions( -+ callback: ( -+ result: Subscription[], -+ ) => void, -+ ): void; -+ -+ export function selectBuiltInSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ -+ export function unselectBuiltInSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ -+ export function getCustomSubscriptions( -+ callback: ( -+ result: Subscription[], -+ ) => void, -+ ): void; -+ -+ export function addCustomSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ -+ export function removeCustomSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ -+ export function addAllowedDomain( -+ domain: string, -+ ): void; -+ -+ export function removeAllowedDomain( -+ domain: string, -+ ): void; -+ -+ export function getAllowedDomains( -+ callback: ( -+ result: string[], -+ ) => void, -+ ): void; -+ -+ export function addCustomFilter( -+ filter: string, -+ ): void; -+ -+ export function removeCustomFilter( -+ filter: string, -+ ): void; -+ -+ export function getCustomFilters( -+ callback: ( -+ result: string[], -+ ) => void, -+ ): void; -+ -+ export function getSessionAllowedAdsCount( -+ callback: ( -+ result: SessionStatsEntry[], -+ ) => void, -+ ): void; -+ -+ export function getSessionBlockedAdsCount( -+ callback: ( -+ result: SessionStatsEntry[], -+ ) => void, -+ ): void; -+ -+ export function getInstalledSubscriptions( -+ callback: ( -+ result: Subscription[], -+ ) => void, -+ ): void; -+ -+ export function installSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ -+ export function uninstallSubscription( -+ url: string, -+ feedback?: () => void, -+ ): void; -+ } -+ } -+} -diff --git a/tools/typescript/definitions/eyeo_filtering_private.d.ts b/tools/typescript/definitions/eyeo_filtering_private.d.ts -new file mode 100644 ---- /dev/null -+++ b/tools/typescript/definitions/eyeo_filtering_private.d.ts -@@ -0,0 +1,228 @@ -+// This file is part of eyeo Chromium SDK, -+// Copyright (C) 2006-present eyeo GmbH -+// -+// eyeo Chromium SDK is free software: you can redistribute it and/or modify -+// it under the terms of the GNU General Public License version 3 as -+// published by the Free Software Foundation. -+// -+// eyeo Chromium SDK is distributed in the hope that it will be useful, -+// but WITHOUT ANY WARRANTY; without even the implied warranty of -+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+// GNU General Public License for more details. -+// -+// You should have received a copy of the GNU General Public License -+// along with eyeo Chromium SDK. If not, see . -+ -+/** @fileoverview Type definitions for chrome.eyeoFilteringPrivate API. */ -+ -+import {ChromeEvent} from './chrome_event.js'; -+ -+declare global { -+ export namespace chrome { -+ export namespace eyeoFilteringPrivate { -+ -+ export interface Subscription { -+ url: string; -+ installation_state: string; -+ title: string; -+ current_version: string; -+ last_installation_time: string; -+ } -+ -+ export interface SessionStatsEntry { -+ url: string; -+ count: number; -+ } -+ -+ export interface RequestInfo { -+ url: string; -+ parent_frame_urls: string[]; -+ subscription: string; -+ content_type: string; -+ tab_id: number; -+ window_id: number; -+ } -+ -+ export const onRequestAllowed: ChromeEvent<( -+ info: RequestInfo, -+ ) => void>; -+ -+ export const onRequestBlocked: ChromeEvent<( -+ info: RequestInfo, -+ ) => void>; -+ -+ export const onPageAllowed: ChromeEvent<( -+ info: RequestInfo, -+ ) => void>; -+ -+ export const onPopupBlocked: ChromeEvent<( -+ info: RequestInfo, -+ ) => void>; -+ -+ export const onPopupAllowed: ChromeEvent<( -+ info: RequestInfo, -+ ) => void>; -+ -+ export const onSubscriptionUpdated: ChromeEvent<( -+ subscription_url: string, -+ ) => void>; -+ -+ export function createConfiguration( -+ config_name: string, -+ ): void; -+ -+ export function getConfigurations(): Promise; -+ -+ export function getConfigurations( -+ callback?: ( -+ result: string[], -+ ) => void, -+ ): void; -+ -+ export function setEnabled( -+ configuration: string, -+ enabled: boolean, -+ ): Promise; -+ -+ export function setEnabled( -+ configuration: string, -+ enabled: boolean, -+ status?: () => void, -+ ): void; -+ -+ export function isEnabled( -+ configuration: string, -+ ): Promise; -+ -+ export function isEnabled( -+ configuration: string, -+ callback?: ( -+ result: boolean, -+ ) => void, -+ ): void; -+ -+ export function addAllowedDomain( -+ configuration: string, -+ domain: string, -+ ): Promise; -+ -+ export function addAllowedDomain( -+ configuration: string, -+ domain: string, -+ status?: () => void, -+ ): void; -+ -+ export function removeAllowedDomain( -+ configuration: string, -+ domain: string, -+ ): Promise; -+ -+ export function removeAllowedDomain( -+ configuration: string, -+ domain: string, -+ status?: () => void, -+ ): void; -+ -+ export function getAllowedDomains( -+ configuration: string, -+ ): Promise; -+ -+ export function getAllowedDomains( -+ configuration: string, -+ callback?: ( -+ result: string[], -+ ) => void, -+ ): void; -+ -+ export function addCustomFilter( -+ configuration: string, -+ filter: string, -+ ): Promise; -+ -+ export function addCustomFilter( -+ configuration: string, -+ filter: string, -+ status?: () => void, -+ ): void; -+ -+ export function removeCustomFilter( -+ configuration: string, -+ filter: string, -+ ): Promise; -+ -+ export function removeCustomFilter( -+ configuration: string, -+ filter: string, -+ status?: () => void, -+ ): void; -+ -+ export function getCustomFilters( -+ configuration: string, -+ ): Promise; -+ -+ export function getCustomFilters( -+ configuration: string, -+ callback?: ( -+ result: string[], -+ ) => void, -+ ): void; -+ -+ export function getFilterLists( -+ configuration: string, -+ ): Promise; -+ -+ export function getFilterLists( -+ configuration: string, -+ callback?: ( -+ result: Subscription[], -+ ) => void, -+ ): void; -+ -+ export function subscribeToFilterList( -+ configuration: string, -+ url: string, -+ ): Promise; -+ -+ export function subscribeToFilterList( -+ configuration: string, -+ url: string, -+ status?: () => void, -+ ): void; -+ -+ export function unsubscribeFromFilterList( -+ configuration: string, -+ url: string, -+ ): Promise; -+ -+ export function unsubscribeFromFilterList( -+ configuration: string, -+ url: string, -+ status?: () => void, -+ ): void; -+ -+ export function getSessionAllowedRequestsCount(): Promise; -+ -+ export function getSessionAllowedRequestsCount( -+ callback?: ( -+ result: SessionStatsEntry[], -+ ) => void, -+ ): void; -+ -+ export function getSessionBlockedRequestsCount(): Promise; -+ -+ export function getSessionBlockedRequestsCount( -+ callback?: ( -+ result: SessionStatsEntry[], -+ ) => void, -+ ): void; -+ -+ export function getAcceptableAdsUrl(): Promise; -+ -+ export function getAcceptableAdsUrl( -+ callback?: ( -+ result: string, -+ ) => void, -+ ): void; -+ } -+ } -+} +diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec +--- a/tools/gritsettings/resource_ids.spec ++++ b/tools/gritsettings/resource_ids.spec +@@ -2,6 +2,10 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + # ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the ++# components/adblock/LICENSE file. ++# + # This file is used to assign starting resource ids for resources and strings + # used by Chromium. This is done to ensure that resource ids are unique + # across all the grd files. If you are adding a new grd file, please add +@@ -635,6 +639,10 @@ + "META": {"sizes": {"includes": [20]}}, + "includes": [4960], + }, ++ "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/adblock_internals/resources.grd": { ++ "META": {"sizes": {"includes": [10],}}, ++ "includes": [4720], ++ }, + # END chrome/ WebUI resources section + + # START chrome/ miscellaneous section. -- 2.25.1 diff --git a/build/patches/eyeo-117.0.5938.0-chrome_integration.patch b/build/patches/eyeo-117.0.5938.0-chrome_integration.patch new file mode 100644 index 00000000..00cc59b6 --- /dev/null +++ b/build/patches/eyeo-117.0.5938.0-chrome_integration.patch @@ -0,0 +1,8165 @@ +From: chromium-sdk +Date: Mon, 21 Aug 2023 18:20:41 +0200 +Subject: eyeo Browser Ad filtering Solution: Chrome Integration Module + +Based on Chromium 117.0.5938.0 + +Pre-requisites: eyeo Browser Ad filtering Solution: Base Module +--- + chrome/app/chrome_main_delegate.cc | 7 +- + chrome/browser/BUILD.gn | 32 ++ + chrome/browser/adblock/README.md | 3 + + .../adblock/adblock_content_browser_client.cc | 322 ++++++++++++ + .../adblock/adblock_content_browser_client.h | 100 ++++ + ...adblock_content_browser_client_unittest.cc | 198 ++++++++ + .../adblock/adblock_controller_factory.cc | 67 +++ + .../adblock/adblock_controller_factory.h | 49 ++ + .../adblock_telemetry_service_factory.cc | 68 +++ + .../adblock_telemetry_service_factory.h | 53 ++ + ...ontent_security_policy_injector_factory.cc | 69 +++ + ...content_security_policy_injector_factory.h | 49 ++ + .../browser/adblock/element_hider_factory.cc | 63 +++ + .../browser/adblock/element_hider_factory.h | 47 ++ + .../resource_classification_runner_factory.cc | 71 +++ + .../resource_classification_runner_factory.h | 49 ++ + .../browser/adblock/session_stats_factory.cc | 64 +++ + .../browser/adblock/session_stats_factory.h | 47 ++ + .../adblock/sitekey_storage_factory.cc | 59 +++ + .../browser/adblock/sitekey_storage_factory.h | 47 ++ + ...ubscription_persistent_metadata_factory.cc | 63 +++ + ...subscription_persistent_metadata_factory.h | 49 ++ + .../adblock/subscription_service_factory.cc | 66 +++ + .../adblock/subscription_service_factory.h | 50 ++ + ...lock_content_browser_client_browsertest.cc | 122 +++++ + .../test/adblock_debug_url_browsertest.cc | 301 ++++++++++++ + .../test/adblock_filter_list_browsertest.cc | 246 ++++++++++ + ...ck_filtering_configurations_browsertest.cc | 460 +++++++++++++++++ + ...ock_frame_hierarchy_builder_browsertest.cc | 463 ++++++++++++++++++ + .../test/adblock_multiple_tabs_browsertest.cc | 159 ++++++ + .../test/adblock_non_ascii_browsertest.cc | 77 +++ + .../adblock/test/adblock_popup_browsertest.cc | 462 +++++++++++++++++ + ...dblock_subscription_service_browsertest.cc | 204 ++++++++ + .../adblock_telemetry_service_browsertest.cc | 256 ++++++++++ + .../test/adblock_web_bundle_browsertest.cc | 426 ++++++++++++++++ + .../chrome_browser_interface_binders.cc | 9 + + .../client_hints/client_hints_browsertest.cc | 12 + + chrome/browser/net/errorpage_browsertest.cc | 8 + + ..._page_load_metrics_observer_browsertest.cc | 7 +- + chrome/browser/preferences/BUILD.gn | 9 + + .../prefs/chrome_pref_service_factory.cc | 11 + + ...hrome_browser_main_extra_parts_profiles.cc | 26 + + .../profile_keyed_service_browsertest.cc | 31 +- + chrome/browser/resources/BUILD.gn | 5 + + .../resources/adblock_internals/BUILD.gn | 29 ++ + .../adblock_internals/adblock_internals.html | 38 ++ + .../adblock_internals/adblock_internals.ts | 43 ++ + .../safe_browsing_blocking_page_test.cc | 8 +- + ...subresource_filter_browser_test_harness.cc | 8 +- + chrome/browser/ui/BUILD.gn | 16 + + chrome/browser/ui/prefs/pref_watcher.cc | 13 + + chrome/browser/ui/tab_helpers.cc | 22 + + .../ui/webui/adblock_internals/BUILD.gn | 23 + + .../adblock_internals/adblock_internals.mojom | 20 + + .../adblock_internals_page_handler_impl.cc | 97 ++++ + .../adblock_internals_page_handler_impl.h | 47 ++ + .../adblock_internals/adblock_internals_ui.cc | 47 ++ + .../adblock_internals/adblock_internals_ui.h | 48 ++ + .../webui/chrome_web_ui_controller_factory.cc | 11 +- + chrome/common/BUILD.gn | 3 + + chrome/common/webui_url_constants.cc | 5 + + chrome/common/webui_url_constants.h | 5 + + chrome/test/BUILD.gn | 26 + + chrome/test/base/chrome_test_launcher.cc | 7 +- + chrome/test/base/in_process_browser_test.cc | 17 +- + .../filterlist_that_allows_resource.txt | 7 + + .../filterlist_that_blocks_resource.txt | 6 + + .../filterlist_that_hides_resource.txt | 6 + + chrome/test/data/adblock/innermost_frame.html | 39 ++ + chrome/test/data/adblock/middle_frame.html | 25 + + chrome/test/data/adblock/non-ascii.html | 26 + + chrome/test/data/adblock/outermost_frame.html | 37 ++ + .../outermost_frame_with_about_blank.html | 37 ++ + chrome/test/data/adblock/popup.html | 25 + + chrome/test/data/adblock/popup_opener.html | 26 + + chrome/test/data/adblock/popup_parent.html | 25 + + chrome/test/data/adblock/resource.png | Bin 0 -> 47293 bytes + chrome/test/data/adblock/tab-restore.html | 33 ++ + chrome/test/data/adblock/wbn/LICENSE | 14 + + .../data/adblock/wbn/blocked_bundle/LICENSE | 14 + + .../fetch_result_1_blocked_bundle.json | 1 + + .../fetch_result_2_blocked_bundle.json | 1 + + .../data/adblock/wbn/by_bundle_file/LICENSE | 14 + + .../fetch_result_2_subresource_loading.json | 1 + + .../green_subresource_loading.css | 1 + + .../green_subresource_loading.png | Bin 0 -> 772 bytes + .../purple_subresource_loading.css | 1 + + .../purple_subresource_loading.png | Bin 0 -> 773 bytes + .../xhr_result_2_subresource_loading.json | 1 + + .../test/data/adblock/wbn/by_resource/LICENSE | 14 + + .../by_resource/blue_subresource_loading.css | 1 + + .../by_resource/blue_subresource_loading.png | Bin 0 -> 773 bytes + .../fetch_result_1_subresource_loading.json | 1 + + .../by_resource/red_subresource_loading.css | 1 + + .../by_resource/red_subresource_loading.png | Bin 0 -> 772 bytes + .../xhr_result_1_subresource_loading.json | 1 + + chrome/test/data/adblock/wbn/by_scope/LICENSE | 14 + + .../fetch_result_3_subresource_loading.json | 1 + + .../by_scope/orange_subresource_loading.css | 1 + + .../by_scope/orange_subresource_loading.png | Bin 0 -> 774 bytes + .../wbn/by_scope/pink_subresource_loading.css | 1 + + .../wbn/by_scope/pink_subresource_loading.png | Bin 0 -> 775 bytes + .../xhr_result_3_subresource_loading.json | 1 + + .../test/data/adblock/wbn/index.html.mustache | 157 ++++++ + 104 files changed, 6042 insertions(+), 10 deletions(-) + create mode 100644 chrome/browser/adblock/README.md + create mode 100644 chrome/browser/adblock/adblock_content_browser_client.cc + create mode 100644 chrome/browser/adblock/adblock_content_browser_client.h + create mode 100644 chrome/browser/adblock/adblock_content_browser_client_unittest.cc + create mode 100644 chrome/browser/adblock/adblock_controller_factory.cc + create mode 100644 chrome/browser/adblock/adblock_controller_factory.h + create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.cc + create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.h + create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.cc + create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.h + create mode 100644 chrome/browser/adblock/element_hider_factory.cc + create mode 100644 chrome/browser/adblock/element_hider_factory.h + create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.cc + create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.h + create mode 100644 chrome/browser/adblock/session_stats_factory.cc + create mode 100644 chrome/browser/adblock/session_stats_factory.h + create mode 100644 chrome/browser/adblock/sitekey_storage_factory.cc + create mode 100644 chrome/browser/adblock/sitekey_storage_factory.h + create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.cc + create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.h + create mode 100644 chrome/browser/adblock/subscription_service_factory.cc + create mode 100644 chrome/browser/adblock/subscription_service_factory.h + create mode 100644 chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_debug_url_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_filter_list_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_popup_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc + create mode 100644 chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc + create mode 100644 chrome/browser/resources/adblock_internals/BUILD.gn + create mode 100644 chrome/browser/resources/adblock_internals/adblock_internals.html + create mode 100644 chrome/browser/resources/adblock_internals/adblock_internals.ts + create mode 100644 chrome/browser/ui/webui/adblock_internals/BUILD.gn + create mode 100644 chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom + create mode 100644 chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.cc + create mode 100644 chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h + create mode 100644 chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.cc + create mode 100644 chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h + create mode 100644 chrome/test/data/adblock/filterlist_that_allows_resource.txt + create mode 100644 chrome/test/data/adblock/filterlist_that_blocks_resource.txt + create mode 100644 chrome/test/data/adblock/filterlist_that_hides_resource.txt + create mode 100644 chrome/test/data/adblock/innermost_frame.html + create mode 100644 chrome/test/data/adblock/middle_frame.html + create mode 100644 chrome/test/data/adblock/non-ascii.html + create mode 100644 chrome/test/data/adblock/outermost_frame.html + create mode 100644 chrome/test/data/adblock/outermost_frame_with_about_blank.html + create mode 100644 chrome/test/data/adblock/popup.html + create mode 100644 chrome/test/data/adblock/popup_opener.html + create mode 100644 chrome/test/data/adblock/popup_parent.html + create mode 100644 chrome/test/data/adblock/resource.png + create mode 100644 chrome/test/data/adblock/tab-restore.html + create mode 100644 chrome/test/data/adblock/wbn/LICENSE + create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/LICENSE + create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json + create mode 100644 chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/LICENSE + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/purple_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/purple_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_bundle_file/xhr_result_2_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/by_resource/LICENSE + create mode 100644 chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_resource/fetch_result_1_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/by_resource/red_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_resource/red_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_resource/xhr_result_1_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/by_scope/LICENSE + create mode 100644 chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_scope/pink_subresource_loading.css + create mode 100644 chrome/test/data/adblock/wbn/by_scope/pink_subresource_loading.png + create mode 100644 chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json + create mode 100644 chrome/test/data/adblock/wbn/index.html.mustache + +diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc +--- a/chrome/app/chrome_main_delegate.cc ++++ b/chrome/app/chrome_main_delegate.cc +@@ -1,6 +1,10 @@ + // Copyright 2012 The Chromium Authors + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/app/chrome_main_delegate.h" + +@@ -40,6 +44,7 @@ + #include "base/trace_event/trace_event_impl.h" + #include "build/build_config.h" + #include "build/chromeos_buildflags.h" ++#include "chrome/browser/adblock/adblock_content_browser_client.h" + #include "chrome/browser/buildflags.h" + #include "chrome/browser/chrome_content_browser_client.h" + #include "chrome/browser/chrome_resource_bundle_helper.h" +@@ -1721,7 +1726,7 @@ content::ContentClient* ChromeMainDelegate::CreateContentClient() { + content::ContentBrowserClient* + ChromeMainDelegate::CreateContentBrowserClient() { + chrome_content_browser_client_ = +- std::make_unique(); ++ std::make_unique(); + return chrome_content_browser_client_.get(); + } + +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -1,6 +1,9 @@ + # Copyright 2014 The Chromium Authors + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. + + import("//base/allocator/allocator.gni") + import("//build/buildflag_header.gni") +@@ -158,6 +161,26 @@ static_library("browser") { + "accessibility/page_colors.h", + "accessibility/page_colors_factory.cc", + "accessibility/page_colors_factory.h", ++ "adblock/adblock_content_browser_client.cc", ++ "adblock/adblock_content_browser_client.h", ++ "adblock/adblock_controller_factory.cc", ++ "adblock/adblock_controller_factory.h", ++ "adblock/adblock_telemetry_service_factory.cc", ++ "adblock/adblock_telemetry_service_factory.h", ++ "adblock/content_security_policy_injector_factory.cc", ++ "adblock/content_security_policy_injector_factory.h", ++ "adblock/element_hider_factory.cc", ++ "adblock/element_hider_factory.h", ++ "adblock/resource_classification_runner_factory.cc", ++ "adblock/resource_classification_runner_factory.h", ++ "adblock/session_stats_factory.cc", ++ "adblock/session_stats_factory.h", ++ "adblock/sitekey_storage_factory.cc", ++ "adblock/sitekey_storage_factory.h", ++ "adblock/subscription_persistent_metadata_factory.cc", ++ "adblock/subscription_persistent_metadata_factory.h", ++ "adblock/subscription_service_factory.cc", ++ "adblock/subscription_service_factory.h", + "after_startup_task_utils.cc", + "after_startup_task_utils.h", + "app_mode/app_mode_utils.cc", +@@ -2042,6 +2065,7 @@ static_library("browser") { + "//chrome/browser/ui/color:color_headers", + "//chrome/browser/ui/color:mixers", + "//chrome/browser/ui/webui:configs", ++ "//chrome/browser/ui/webui/adblock_internals:mojo_bindings", + "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", + "//chrome/browser/ui/webui/feed:mojo_bindings", + "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", +@@ -2061,6 +2085,12 @@ static_library("browser") { + "//chrome/common/notifications", + "//chrome/installer/util:with_no_strings", + "//chrome/services/speech/buildflags", ++<<<<<<< HEAD ++======= ++ "//chromeos/components/kiosk", ++ "//components/adblock/content:browser", ++ "//components/adblock/core/converter", ++>>>>>>> 9402d5c48c0e8... Squashed commits + "//components/assist_ranker", + "//components/autofill/content/browser", + "//components/autofill/core/browser", +@@ -3296,7 +3326,9 @@ static_library("browser") { + "webauthn/android/chrome_webauthn_client_android.h", + "webauthn/android/webauthn_request_delegate_android.cc", + "webauthn/android/webauthn_request_delegate_android.h", ++ + ] ++ + public_deps += [ + "//chrome/android/features/dev_ui:buildflags", + "//components/image_fetcher/core", +diff --git a/chrome/browser/adblock/README.md b/chrome/browser/adblock/README.md +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/README.md +@@ -0,0 +1,3 @@ ++This folder contains the OS-agnostic, Chrome-specific source code of eyeo Chromium SDK. ++ ++For the full documentation, refer to [components/adblock](/components/adblock). +diff --git a/chrome/browser/adblock/adblock_content_browser_client.cc b/chrome/browser/adblock/adblock_content_browser_client.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_content_browser_client.cc +@@ -0,0 +1,322 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_content_browser_client.h" ++ ++#include "base/containers/unique_ptr_adapters.h" ++#include "base/ranges/algorithm.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/content_security_policy_injector_factory.h" ++#include "chrome/browser/adblock/element_hider_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser_navigator_params.h" ++#include "components/adblock/content/browser/adblock_url_loader_factory.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/embedder_support/user_agent_utils.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/browser/browser_thread.h" ++#include "content/public/browser/render_frame_host.h" ++#include "content/public/browser/render_process_host.h" ++#include "content/public/browser/render_view_host.h" ++#include "content/public/browser/web_contents.h" ++#include "mojo/public/cpp/bindings/self_owned_receiver.h" ++#include "services/network/public/mojom/websocket.mojom.h" ++#include "services/service_manager/public/cpp/binder_registry.h" ++#include "third_party/blink/public/common/loader/url_loader_throttle.h" ++ ++#ifdef EYEO_INTERCEPT_DEBUG_URL ++#include "components/adblock/content/browser/adblock_url_loader_factory_for_test.h" ++#endif ++ ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++#include "chrome/browser/extensions/extension_util.h" ++#endif ++ ++namespace { ++ ++bool IsFilteringNeeded(content::RenderFrameHost* frame) { ++ if (frame) { ++ auto* profile = ++ Profile::FromBrowserContext(frame->GetProcess()->GetBrowserContext()); ++ if (profile) { ++ // Filtering may be needed if there's at least one enabled ++ // FilteringConfiguration. ++ return base::ranges::any_of( ++ adblock::SubscriptionServiceFactory::GetForBrowserContext(profile) ++ ->GetInstalledFilteringConfigurations(), ++ &adblock::FilteringConfiguration::IsEnabled); ++ } ++ } ++ return false; ++} ++ ++// Owns all of the AdblockURLLoaderFactory for a given Profile. ++class AdblockContextData : public base::SupportsUserData::Data { ++ public: ++ AdblockContextData(const AdblockContextData&) = delete; ++ AdblockContextData& operator=(const AdblockContextData&) = delete; ++ ~AdblockContextData() override = default; ++ ++ static void StartProxying( ++ Profile* profile, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ mojo::PendingReceiver receiver, ++ mojo::PendingRemote target_factory, ++ bool use_test_loader) { ++ const void* const kAdblockContextUserDataKey = &kAdblockContextUserDataKey; ++ auto* self = static_cast( ++ profile->GetUserData(kAdblockContextUserDataKey)); ++ if (!self) { ++ self = new AdblockContextData(); ++ profile->SetUserData(kAdblockContextUserDataKey, base::WrapUnique(self)); ++ } ++ auto* browser_context = ++ content::WebContents::FromRenderFrameHost(frame)->GetBrowserContext(); ++ adblock::AdblockURLLoaderFactoryConfig config{ ++ adblock::SubscriptionServiceFactory::GetForBrowserContext( ++ browser_context), ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser_context), ++ adblock::ElementHiderFactory::GetForBrowserContext(browser_context), ++ adblock::SitekeyStorageFactory::GetForBrowserContext(browser_context), ++ adblock::ContentSecurityPolicyInjectorFactory::GetForBrowserContext( ++ browser_context)}; ++#ifdef EYEO_INTERCEPT_DEBUG_URL ++ if (use_test_loader) { ++ auto proxy = std::make_unique( ++ std::move(config), ++ content::GlobalRenderFrameHostId(render_process_id, ++ frame->GetRoutingID()), ++ std::move(receiver), std::move(target_factory), ++ embedder_support::GetUserAgent(), ++ base::BindOnce(&AdblockContextData::RemoveProxy, ++ self->weak_factory_.GetWeakPtr()), ++ adblock::AdblockControllerFactory::GetForBrowserContext( ++ Profile::FromBrowserContext( ++ frame->GetProcess()->GetBrowserContext()))); ++ self->proxies_.emplace(std::move(proxy)); ++ return; ++ } ++#endif ++ auto proxy = std::make_unique( ++ std::move(config), ++ content::GlobalRenderFrameHostId(render_process_id, ++ frame->GetRoutingID()), ++ std::move(receiver), std::move(target_factory), ++ embedder_support::GetUserAgent(), ++ base::BindOnce(&AdblockContextData::RemoveProxy, ++ self->weak_factory_.GetWeakPtr())); ++ self->proxies_.emplace(std::move(proxy)); ++ } ++ ++ private: ++ void RemoveProxy(adblock::AdblockURLLoaderFactory* proxy) { ++ auto it = proxies_.find(proxy); ++ DCHECK(it != proxies_.end()); ++ proxies_.erase(it); ++ } ++ ++ AdblockContextData() = default; ++ ++ std::set, ++ base::UniquePtrComparator> ++ proxies_; ++ ++ base::WeakPtrFactory weak_factory_{this}; ++}; ++ ++} // namespace ++ ++AdblockContentBrowserClient::AdblockContentBrowserClient() = default; ++ ++AdblockContentBrowserClient::~AdblockContentBrowserClient() = default; ++ ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++// static ++bool AdblockContentBrowserClient::force_adblock_proxy_for_testing_ = false; ++ ++// static ++void AdblockContentBrowserClient::ForceAdblockProxyForTesting() { ++ force_adblock_proxy_for_testing_ = true; ++} ++#endif ++ ++bool AdblockContentBrowserClient::WillInterceptWebSocket( ++ content::RenderFrameHost* frame) { ++ if (IsFilteringNeeded(frame)) { ++ return true; ++ } ++ ++ return ChromeContentBrowserClient::WillInterceptWebSocket(frame); ++} ++ ++void AdblockContentBrowserClient::CreateWebSocket( ++ content::RenderFrameHost* frame, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client) { ++ if (IsFilteringNeeded(frame)) { ++ CreateWebSocketInternal(frame->GetGlobalId(), std::move(factory), url, ++ site_for_cookies, user_agent, ++ std::move(handshake_client)); ++ } else { ++ DCHECK(ChromeContentBrowserClient::WillInterceptWebSocket(frame)); ++ ChromeContentBrowserClient::CreateWebSocket(frame, std::move(factory), url, ++ site_for_cookies, user_agent, ++ std::move(handshake_client)); ++ } ++} ++ ++void AdblockContentBrowserClient::CreateWebSocketInternal( ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client) { ++ auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); ++ if (!frame) { ++ return; ++ } ++ auto* browser_context = frame->GetProcess()->GetBrowserContext(); ++ auto* subscription_service = ++ adblock::SubscriptionServiceFactory::GetForBrowserContext( ++ browser_context); ++ auto* classification_runner = ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser_context); ++ classification_runner->CheckRequestFilterMatchForWebSocket( ++ subscription_service->GetCurrentSnapshot(), url, render_frame_host_id, ++ base::BindOnce( ++ &AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted, ++ weak_factory_.GetWeakPtr(), render_frame_host_id, std::move(factory), ++ url, site_for_cookies, user_agent, std::move(handshake_client))); ++} ++ ++void AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted( ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ ChromeContentBrowserClient::WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client, ++ adblock::FilterMatchResult result) { ++ auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); ++ if (!frame) { ++ return; ++ } ++ const bool has_blocking_filter = ++ result == adblock::FilterMatchResult::kBlockRule; ++ if (!has_blocking_filter) { ++ VLOG(1) << "[eyeo] Web socket allowed for " << url; ++ if (ChromeContentBrowserClient::WillInterceptWebSocket(frame)) { ++ ChromeContentBrowserClient::CreateWebSocket( ++ frame, std::move(factory), url, site_for_cookies, user_agent, ++ std::move(handshake_client)); ++ return; ++ } ++ ++ std::vector headers; ++ if (user_agent) { ++ headers.push_back(network::mojom::HttpHeader::New( ++ net::HttpRequestHeaders::kUserAgent, *user_agent)); ++ } ++ std::move(factory).Run(url, std::move(headers), std::move(handshake_client), ++ mojo::NullRemote(), mojo::NullRemote()); ++ } ++ ++ VLOG(1) << "[eyeo] Web socket blocked for " << url; ++} ++ ++bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( ++ content::BrowserContext* browser_context, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ URLLoaderFactoryType type, ++ const url::Origin& request_initiator, ++ absl::optional navigation_id, ++ ukm::SourceIdObj ukm_source_id, ++ mojo::PendingReceiver* factory_receiver, ++ mojo::PendingRemote* ++ header_client, ++ bool* bypass_redirect_checks, ++ bool* disable_secure_dns, ++ network::mojom::URLLoaderFactoryOverridePtr* factory_override, ++ scoped_refptr navigation_response_task_runner) { ++ // Create Chromium proxy first as WebRequestProxyingURLLoaderFactory logic ++ // depends on being first proxy ++ bool use_chrome_proxy = ++ ChromeContentBrowserClient::WillCreateURLLoaderFactory( ++ browser_context, frame, render_process_id, type, request_initiator, ++ navigation_id, ukm_source_id, factory_receiver, header_client, ++ bypass_redirect_checks, disable_secure_dns, factory_override, ++ navigation_response_task_runner); ++ auto* profile = frame ? Profile::FromBrowserContext( ++ frame->GetProcess()->GetBrowserContext()) ++ : nullptr; ++ ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ if (!force_adblock_proxy_for_testing_ && ++ request_initiator.scheme() == extensions::kExtensionScheme) { ++ VLOG(1) << "[eyeo] Do not use adblock proxy for extensions requests " ++ "[extension id:" ++ << request_initiator.host() << "]."; ++ return use_chrome_proxy; ++ } ++#endif ++ ++ bool use_adblock_proxy = ++ (type == URLLoaderFactoryType::kDocumentSubResource || ++ type == URLLoaderFactoryType::kNavigation) && ++ IsFilteringNeeded(frame); ++ ++ bool use_test_loader = false; ++#ifdef EYEO_INTERCEPT_DEBUG_URL ++ content::WebContents* wc = content::WebContents::FromRenderFrameHost(frame); ++ use_test_loader = ++ (type == ++ content::ContentBrowserClient::URLLoaderFactoryType::kNavigation) && ++ wc->GetVisibleURL().is_valid() && ++ wc->GetVisibleURL().host() == ++ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; ++ use_adblock_proxy |= use_test_loader; ++#endif ++ ++ if (use_adblock_proxy) { ++ auto proxied_receiver = std::move(*factory_receiver); ++ mojo::PendingRemote target_factory_remote; ++ *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver(); ++ AdblockContextData::StartProxying( ++ profile, frame, render_process_id, std::move(proxied_receiver), ++ std::move(target_factory_remote), use_test_loader); ++ } ++ return use_adblock_proxy || use_chrome_proxy; ++} +diff --git a/chrome/browser/adblock/adblock_content_browser_client.h b/chrome/browser/adblock/adblock_content_browser_client.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_content_browser_client.h +@@ -0,0 +1,100 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ ++ ++#include "build/buildflag.h" ++#include "chrome/browser/chrome_content_browser_client.h" ++ ++namespace adblock { ++enum class FilterMatchResult; ++} // namespace adblock ++ ++/** ++ * @brief Intercepts network and UI events to inject ad-filtering. ++ * Provides ad-filtering implementations of URLLoaderThrottles. ++ * Binds a mojo connection between Renderer processes and the ++ * Browser-process-based ResourceClassificationRunner. ++ * Lives in browser process UI thread. ++ */ ++class AdblockContentBrowserClient : public ChromeContentBrowserClient { ++ public: ++ AdblockContentBrowserClient(); ++ ~AdblockContentBrowserClient() override; ++ ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ // Enable ad filtering also for requests initiated by extensions. ++ // This allows implementing extension-driven browser tests. ++ // In production code, requests from extensions are not blocked. ++ static void ForceAdblockProxyForTesting(); ++#endif ++ ++ bool WillInterceptWebSocket(content::RenderFrameHost* frame) override; ++ void CreateWebSocket( ++ content::RenderFrameHost* frame, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client) override; ++ ++ bool WillCreateURLLoaderFactory( ++ content::BrowserContext* browser_context, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ URLLoaderFactoryType type, ++ const url::Origin& request_initiator, ++ absl::optional navigation_id, ++ ukm::SourceIdObj ukm_source_id, ++ mojo::PendingReceiver* factory_receiver, ++ mojo::PendingRemote* ++ header_client, ++ bool* bypass_redirect_checks, ++ bool* disable_secure_dns, ++ network::mojom::URLLoaderFactoryOverridePtr* factory_override, ++ scoped_refptr navigation_response_task_runner) ++ override; ++ ++ private: ++ void CreateWebSocketInternal( ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client); ++ void OnWebSocketFilterCheckCompleted( ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ ChromeContentBrowserClient::WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client, ++ adblock::FilterMatchResult result); ++ ++ base::WeakPtrFactory weak_factory_{this}; ++ ++#if BUILDFLAG(ENABLE_EXTENSIONS) ++ static bool force_adblock_proxy_for_testing_; ++#endif ++}; ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ +diff --git a/chrome/browser/adblock/adblock_content_browser_client_unittest.cc b/chrome/browser/adblock/adblock_content_browser_client_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_content_browser_client_unittest.cc +@@ -0,0 +1,198 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_content_browser_client.h" ++ ++#include "base/callback_list.h" ++#include "base/memory/raw_ptr.h" ++#include "base/run_loop.h" ++#include "base/test/gmock_move_support.h" ++#include "base/test/mock_callback.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/test/base/chrome_render_view_host_test_harness.h" ++#include "components/adblock/content/browser/test/mock_resource_classification_runner.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/common/content_type.h" ++#include "components/adblock/core/subscription/installed_subscription.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/adblock/core/subscription/test/mock_subscription_collection.h" ++#include "components/adblock/core/subscription/test/mock_subscription_service.h" ++#include "components/adblock/core/test/mock_adblock_controller.h" ++#include "components/keyed_service/core/keyed_service.h" ++#include "content/public/browser/content_browser_client.h" ++#include "content/public/test/mock_render_process_host.h" ++#include "content/public/test/test_renderer_host.h" ++#include "gmock/gmock.h" ++#include "services/network/public/mojom/network_context.mojom.h" ++#include "services/network/public/mojom/websocket.mojom.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++using testing::_; ++using testing::Return; ++ ++namespace adblock { ++ ++class AdblockContentBrowserClientUnitTest ++ : public ChromeRenderViewHostTestHarness { ++ public: ++ TestingProfile::TestingFactories GetTestingFactories() const override { ++ return {std::make_pair( ++ SubscriptionServiceFactory::GetInstance(), ++ base::BindRepeating([](content::BrowserContext* bc) ++ -> std::unique_ptr { ++ return std::make_unique(); ++ })), ++ std::make_pair( ++ ResourceClassificationRunnerFactory::GetInstance(), ++ base::BindRepeating([](content::BrowserContext* bc) ++ -> std::unique_ptr { ++ return std::make_unique(); ++ }))}; ++ } ++ ++ void SetUp() override { ++ RenderViewHostTestHarness::SetUp(); ++ ++ subscription_service_ = static_cast( ++ SubscriptionServiceFactory::GetForBrowserContext(profile())); ++ resource_classification_runner_ = ++ static_cast( ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ profile())); ++ } ++ ++ raw_ptr subscription_service_; ++ raw_ptr resource_classification_runner_; ++}; ++ ++TEST_F(AdblockContentBrowserClientUnitTest, ++ WillInterceptWebSocketWhenFilteringEnabled) { ++ AdblockContentBrowserClient content_client; ++ subscription_service_->WillRequireFiltering(true); ++ EXPECT_TRUE(content_client.WillInterceptWebSocket(main_rfh())); ++} ++ ++TEST_F(AdblockContentBrowserClientUnitTest, ++ WillNotInterceptWebSocketWhenFilteringDisabled) { ++ AdblockContentBrowserClient content_client; ++ subscription_service_->WillRequireFiltering(false); ++ EXPECT_FALSE(content_client.WillInterceptWebSocket(main_rfh())); ++} ++ ++TEST_F(AdblockContentBrowserClientUnitTest, ++ RenderFrameHostDiesBeforeClassificationFinished) { ++ const auto kSocketUrl = GURL("wss://domain.com/test"); ++ subscription_service_->WillRequireFiltering(true); ++ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { ++ SubscriptionService::Snapshot snapshot; ++ snapshot.push_back(std::make_unique()); ++ return snapshot; ++ }); ++ CheckFilterMatchCallback classification_callback; ++ EXPECT_CALL(*resource_classification_runner_, ++ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, ++ main_rfh()->GetGlobalId(), _)) ++ .WillOnce(MoveArg<3>(&classification_callback)); ++ ++ AdblockContentBrowserClient content_client; ++ base::MockCallback ++ web_socket_factory; ++ // The web_socket_factory callback will never be called because the ++ // associated RenderFrameHost will be dead. ++ EXPECT_CALL(web_socket_factory, Run(_, _, _, _, _)).Times(0); ++ ++ const net::SiteForCookies site_for_cookies; ++ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), ++ kSocketUrl, site_for_cookies, absl::nullopt, ++ {}); ++ // Tab is closed. ++ DeleteContents(); ++ ++ // Classification finishes now. It will not trigger a call to ++ // |web_socket_factory| because the RFH is dead. ++ std::move(classification_callback).Run(FilterMatchResult::kBlockRule); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockContentBrowserClientUnitTest, WebSocketAllowed) { ++ subscription_service_->WillRequireFiltering(true); ++ const auto kSocketUrl = GURL("wss://domain.com/test"); ++ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { ++ SubscriptionService::Snapshot snapshot; ++ snapshot.push_back(std::make_unique()); ++ return snapshot; ++ }); ++ CheckFilterMatchCallback classification_callback; ++ EXPECT_CALL(*resource_classification_runner_, ++ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, ++ main_rfh()->GetGlobalId(), _)) ++ .WillOnce(MoveArg<3>(&classification_callback)); ++ ++ AdblockContentBrowserClient content_client; ++ base::MockCallback ++ web_socket_factory; ++ // The web_socket_factory callback will be called to let the web socket ++ // continue connecting. ++ EXPECT_CALL(web_socket_factory, Run(kSocketUrl, _, _, _, _)); ++ ++ const net::SiteForCookies site_for_cookies; ++ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), ++ kSocketUrl, site_for_cookies, absl::nullopt, ++ {}); ++ ++ // Classification finishes now. It will trigger a call to |web_socket_factory| ++ std::move(classification_callback).Run(FilterMatchResult::kAllowRule); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockContentBrowserClientUnitTest, WebSocketBlocked) { ++ subscription_service_->WillRequireFiltering(true); ++ const auto kSocketUrl = GURL("wss://domain.com/test"); ++ EXPECT_CALL(*subscription_service_, GetCurrentSnapshot()).WillOnce([]() { ++ SubscriptionService::Snapshot snapshot; ++ snapshot.push_back(std::make_unique()); ++ return snapshot; ++ }); ++ CheckFilterMatchCallback classification_callback; ++ EXPECT_CALL(*resource_classification_runner_, ++ CheckRequestFilterMatchForWebSocket(_, kSocketUrl, ++ main_rfh()->GetGlobalId(), _)) ++ .WillOnce(MoveArg<3>(&classification_callback)); ++ ++ AdblockContentBrowserClient content_client; ++ base::MockCallback ++ web_socket_factory; ++ // The web_socket_factory callback will not be called as to disallow ++ // connection. ++ EXPECT_CALL(web_socket_factory, Run(kSocketUrl, _, _, _, _)).Times(0); ++ ++ const net::SiteForCookies site_for_cookies; ++ content_client.CreateWebSocket(main_rfh(), web_socket_factory.Get(), ++ kSocketUrl, site_for_cookies, absl::nullopt, ++ {}); ++ ++ // Classification finishes now. ++ std::move(classification_callback).Run(FilterMatchResult::kBlockRule); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_controller_factory.cc b/chrome/browser/adblock/adblock_controller_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_controller_factory.cc +@@ -0,0 +1,67 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/adblock_controller.h" ++ ++namespace adblock { ++ ++// static ++AdblockController* AdblockControllerFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++ ++// static ++AdblockControllerFactory* AdblockControllerFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockControllerFactory::AdblockControllerFactory() ++ : AdblockControllerFactoryBase() { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++AdblockControllerFactory::~AdblockControllerFactory() = default; ++ ++SubscriptionService* AdblockControllerFactory::GetSubscriptionService( ++ content::BrowserContext* context) const { ++ return SubscriptionServiceFactory::GetForBrowserContext(context); ++} ++ ++PrefService* AdblockControllerFactory::GetPrefs( ++ content::BrowserContext* context) const { ++ return Profile::FromBrowserContext(context)->GetPrefs(); ++} ++ ++const std::string& AdblockControllerFactory::GetLocale() const { ++ return g_browser_process->GetApplicationLocale(); ++} ++ ++content::BrowserContext* AdblockControllerFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_controller_factory.h b/chrome/browser/adblock/adblock_controller_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_controller_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/adblock/content/browser/adblock_controller_factory_base.h" ++ ++namespace adblock { ++ ++class AdblockController; ++class AdblockControllerFactory : public AdblockControllerFactoryBase { ++ public: ++ static AdblockController* GetForBrowserContext( ++ content::BrowserContext* context); ++ static AdblockControllerFactory* GetInstance(); ++ ++ protected: ++ PrefService* GetPrefs(content::BrowserContext* context) const override; ++ const std::string& GetLocale() const override; ++ SubscriptionService* GetSubscriptionService( ++ content::BrowserContext* context) const override; ++ ++ private: ++ friend class base::NoDestructor; ++ AdblockControllerFactory(); ++ ~AdblockControllerFactory() override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.cc b/chrome/browser/adblock/adblock_telemetry_service_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_telemetry_service_factory.cc +@@ -0,0 +1,68 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" ++ ++#include "base/no_destructor.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/adblock_telemetry_service.h" ++ ++namespace adblock { ++ ++// static ++AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile( ++ Profile* profile) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(profile, true)); ++} ++// static ++AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory() ++ : AdblockTelemetryServiceFactoryBase() { ++ DependsOn(AdblockControllerFactory::GetInstance()); ++} ++ ++AdblockTelemetryServiceFactory::~AdblockTelemetryServiceFactory() = default; ++ ++AdblockController* AdblockTelemetryServiceFactory::GetAdblockController( ++ content::BrowserContext* context) const { ++ return AdblockControllerFactory::GetForBrowserContext(context); ++} ++ ++SubscriptionService* AdblockTelemetryServiceFactory::GetSubscriptionService( ++ content::BrowserContext* context) const { ++ return SubscriptionServiceFactory::GetForBrowserContext(context); ++} ++ ++PrefService* AdblockTelemetryServiceFactory::GetPrefs( ++ content::BrowserContext* context) const { ++ return Profile::FromBrowserContext(context)->GetPrefs(); ++} ++ ++content::BrowserContext* AdblockTelemetryServiceFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.h b/chrome/browser/adblock/adblock_telemetry_service_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_telemetry_service_factory.h +@@ -0,0 +1,53 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/adblock/content/browser/adblock_telemetry_service_factory_base.h" ++ ++class Profile; ++ ++namespace adblock { ++class AdblockTelemetryService; ++class AdblockTelemetryServiceFactory ++ : public AdblockTelemetryServiceFactoryBase { ++ public: ++ static AdblockTelemetryService* GetForProfile(Profile* profile); ++ static AdblockTelemetryServiceFactory* GetInstance(); ++ ++ protected: ++ PrefService* GetPrefs(content::BrowserContext* context) const override; ++ AdblockController* GetAdblockController( ++ content::BrowserContext* context) const override; ++ SubscriptionService* GetSubscriptionService( ++ content::BrowserContext* context) const override; ++ ++ private: ++ friend class base::NoDestructor; ++ AdblockTelemetryServiceFactory(); ++ ~AdblockTelemetryServiceFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ +diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.cc b/chrome/browser/adblock/content_security_policy_injector_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/content_security_policy_injector_factory.cc +@@ -0,0 +1,69 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/content_security_policy_injector_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/content_security_policy_injector_impl.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ContentSecurityPolicyInjector* ++ContentSecurityPolicyInjectorFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ContentSecurityPolicyInjectorFactory* ++ContentSecurityPolicyInjectorFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ContentSecurityPolicyInjectorFactory::ContentSecurityPolicyInjectorFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ContentSecurityPolicyInjector", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++ContentSecurityPolicyInjectorFactory::~ContentSecurityPolicyInjectorFactory() = ++ default; ++ ++KeyedService* ContentSecurityPolicyInjectorFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ContentSecurityPolicyInjectorImpl( ++ SubscriptionServiceFactory::GetForBrowserContext(context), ++ std::make_unique()); ++} ++ ++content::BrowserContext* ++ContentSecurityPolicyInjectorFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.h b/chrome/browser/adblock/content_security_policy_injector_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/content_security_policy_injector_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class ContentSecurityPolicyInjector; ++class ContentSecurityPolicyInjectorFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static ContentSecurityPolicyInjector* GetForBrowserContext( ++ content::BrowserContext* context); ++ static ContentSecurityPolicyInjectorFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ContentSecurityPolicyInjectorFactory(); ++ ~ContentSecurityPolicyInjectorFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_FACTORY_H_ +diff --git a/chrome/browser/adblock/element_hider_factory.cc b/chrome/browser/adblock/element_hider_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/element_hider_factory.cc +@@ -0,0 +1,63 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/element_hider_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/element_hider_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ElementHider* ElementHiderFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ElementHiderFactory* ElementHiderFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ElementHiderFactory::ElementHiderFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ElementHider", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(adblock::SubscriptionServiceFactory::GetInstance()); ++} ++ ++ElementHiderFactory::~ElementHiderFactory() = default; ++ ++KeyedService* ElementHiderFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ElementHiderImpl( ++ adblock::SubscriptionServiceFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* ElementHiderFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/element_hider_factory.h b/chrome/browser/adblock/element_hider_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/element_hider_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class ElementHider; ++class ElementHiderFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static ElementHider* GetForBrowserContext(content::BrowserContext* context); ++ static ElementHiderFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ElementHiderFactory(); ++ ~ElementHiderFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ +diff --git a/chrome/browser/adblock/resource_classification_runner_factory.cc b/chrome/browser/adblock/resource_classification_runner_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/resource_classification_runner_factory.cc +@@ -0,0 +1,71 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/adblock/content/browser/resource_classification_runner_impl.h" ++#include "components/adblock/core/classifier/resource_classifier_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ResourceClassificationRunner* ++ResourceClassificationRunnerFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ResourceClassificationRunnerFactory* ++ResourceClassificationRunnerFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ResourceClassificationRunnerFactory::ResourceClassificationRunnerFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ResourceClassificationRunner", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SitekeyStorageFactory::GetInstance()); ++} ++ ++ResourceClassificationRunnerFactory::~ResourceClassificationRunnerFactory() = ++ default; ++ ++KeyedService* ResourceClassificationRunnerFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ResourceClassificationRunnerImpl( ++ base::MakeRefCounted(), ++ std::make_unique(), ++ SitekeyStorageFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* ++ResourceClassificationRunnerFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/resource_classification_runner_factory.h b/chrome/browser/adblock/resource_classification_runner_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/resource_classification_runner_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class ResourceClassificationRunner; ++class ResourceClassificationRunnerFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static ResourceClassificationRunner* GetForBrowserContext( ++ content::BrowserContext* context); ++ static ResourceClassificationRunnerFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ResourceClassificationRunnerFactory(); ++ ~ResourceClassificationRunnerFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ +diff --git a/chrome/browser/adblock/session_stats_factory.cc b/chrome/browser/adblock/session_stats_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/session_stats_factory.cc +@@ -0,0 +1,64 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/session_stats_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/session_stats_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SessionStats* SessionStatsFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++ ++// static ++SessionStatsFactory* SessionStatsFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SessionStatsFactory::SessionStatsFactory() ++ : BrowserContextKeyedServiceFactory( ++ "SessionStats", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(ResourceClassificationRunnerFactory::GetInstance()); ++} ++ ++SessionStatsFactory::~SessionStatsFactory() = default; ++ ++KeyedService* SessionStatsFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SessionStatsImpl( ++ ResourceClassificationRunnerFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* SessionStatsFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/session_stats_factory.h b/chrome/browser/adblock/session_stats_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/session_stats_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SessionStats; ++class SessionStatsFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SessionStats* GetForBrowserContext(content::BrowserContext* context); ++ static SessionStatsFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SessionStatsFactory(); ++ ~SessionStatsFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ +diff --git a/chrome/browser/adblock/sitekey_storage_factory.cc b/chrome/browser/adblock/sitekey_storage_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/sitekey_storage_factory.cc +@@ -0,0 +1,59 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++ ++#include ++ ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/sitekey_storage_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SitekeyStorage* SitekeyStorageFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SitekeyStorageFactory* SitekeyStorageFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SitekeyStorageFactory::SitekeyStorageFactory() ++ : BrowserContextKeyedServiceFactory( ++ "SitekeyStorage", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++SitekeyStorageFactory::~SitekeyStorageFactory() = default; ++ ++KeyedService* SitekeyStorageFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SitekeyStorageImpl(); ++} ++ ++content::BrowserContext* SitekeyStorageFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/sitekey_storage_factory.h b/chrome/browser/adblock/sitekey_storage_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/sitekey_storage_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SitekeyStorage; ++class SitekeyStorageFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SitekeyStorage* GetForBrowserContext(content::BrowserContext* context); ++ static SitekeyStorageFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SitekeyStorageFactory(); ++ ~SitekeyStorageFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.cc b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc +@@ -0,0 +1,63 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++ ++#include ++ ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/subscription/subscription_persistent_metadata_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SubscriptionPersistentMetadata* ++SubscriptionPersistentMetadataFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SubscriptionPersistentMetadataFactory* ++SubscriptionPersistentMetadataFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SubscriptionPersistentMetadataFactory::SubscriptionPersistentMetadataFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockSubscriptionPersistentMetadata", ++ BrowserContextDependencyManager::GetInstance()) {} ++SubscriptionPersistentMetadataFactory:: ++ ~SubscriptionPersistentMetadataFactory() = default; ++ ++KeyedService* SubscriptionPersistentMetadataFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SubscriptionPersistentMetadataImpl( ++ Profile::FromBrowserContext(context)->GetPrefs()); ++} ++ ++content::BrowserContext* ++SubscriptionPersistentMetadataFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.h b/chrome/browser/adblock/subscription_persistent_metadata_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SubscriptionPersistentMetadata; ++class SubscriptionPersistentMetadataFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static SubscriptionPersistentMetadata* GetForBrowserContext( ++ content::BrowserContext* context); ++ static SubscriptionPersistentMetadataFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SubscriptionPersistentMetadataFactory(); ++ ~SubscriptionPersistentMetadataFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_service_factory.cc b/chrome/browser/adblock/subscription_service_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_service_factory.cc +@@ -0,0 +1,66 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SubscriptionService* SubscriptionServiceFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SubscriptionServiceFactory* SubscriptionServiceFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SubscriptionServiceFactory::SubscriptionServiceFactory() ++ : SubscriptionServiceFactoryBase() { ++ DependsOn(SubscriptionPersistentMetadataFactory::GetInstance()); ++} ++ ++SubscriptionServiceFactory::~SubscriptionServiceFactory() = default; ++ ++SubscriptionPersistentMetadata* ++SubscriptionServiceFactory::GetSubscriptionPersistentMetadata( ++ content::BrowserContext* context) const { ++ return SubscriptionPersistentMetadataFactory::GetForBrowserContext(context); ++} ++ ++PrefService* SubscriptionServiceFactory::GetPrefs( ++ content::BrowserContext* context) const { ++ return Profile::FromBrowserContext(context)->GetPrefs(); ++} ++ ++content::BrowserContext* SubscriptionServiceFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/subscription_service_factory.h b/chrome/browser/adblock/subscription_service_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_service_factory.h +@@ -0,0 +1,50 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/adblock/content/browser/subscription_service_factory_base.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++class SubscriptionService; ++class SubscriptionServiceFactory : public SubscriptionServiceFactoryBase { ++ public: ++ static SubscriptionService* GetForBrowserContext( ++ content::BrowserContext* context); ++ static SubscriptionServiceFactory* GetInstance(); ++ ++ protected: ++ PrefService* GetPrefs(content::BrowserContext* context) const override; ++ SubscriptionPersistentMetadata* GetSubscriptionPersistentMetadata( ++ content::BrowserContext* context) const override; ++ ++ private: ++ friend class base::NoDestructor; ++ SubscriptionServiceFactory(); ++ ~SubscriptionServiceFactory() override; ++ ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ +diff --git a/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc b/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_content_browser_client_browsertest.cc +@@ -0,0 +1,122 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_content_browser_client.h" ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/browser/ui/browser_commands.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/adblock/core/subscription/test/mock_subscription_service.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "net/test/spawned_test_server/spawned_test_server.h" ++#include "net/test/test_data_directory.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace adblock { ++ ++class AdblockContentBrowserClientBrowserTest : public InProcessBrowserTest { ++ public: ++ void SetUpOnMainThread() override { ++ watcher_ = std::make_unique( ++ browser()->tab_strip_model()->GetActiveWebContents(), u"PASS"); ++ watcher_->AlsoWaitForTitle(u"FAIL"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ net::GetWebSocketTestDataDirectory()); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ } ++ ++ void TearDownOnMainThread() override { watcher_.reset(); } ++ ++ void NavigateToHTTP(const std::string& path) { ++ // Visit a HTTPS page for testing. ++ GURL::Replacements replacements; ++ replacements.SetSchemeStr("http"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), ws_server_.GetURL(path).ReplaceComponents(replacements))); ++ } ++ ++ std::string WaitAndGetTitle() { ++ return base::UTF16ToUTF8(watcher_->WaitAndGetTitle()); ++ } ++ ++ net::SpawnedTestServer ws_server_{net::SpawnedTestServer::TYPE_WS, ++ net::GetWebSocketTestDataDirectory()}; ++ ++ private: ++ std::unique_ptr watcher_; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, ++ WebSocketConnectionNotInterrupted) { ++ // Launch a WebSocket server. ++ ASSERT_TRUE(ws_server_.Start()); ++ ++ // Disable ad-filtering. ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()) ++ ->SetAdblockEnabled(false); ++ ++ NavigateToHTTP("split_packet_check.html"); ++ ++ // WebSocket connected. ++ EXPECT_EQ("PASS", WaitAndGetTitle()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, ++ WebSocketConnectionInterruptedButNotBlocked) { ++ // Launch a WebSocket server. ++ ASSERT_TRUE(ws_server_.Start()); ++ ++ // Enable ad-filtering. ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()) ++ ->SetAdblockEnabled(true); ++ ++ NavigateToHTTP("split_packet_check.html"); ++ ++ // WebSocket connected, there were no blocking filters. ++ EXPECT_EQ("PASS", WaitAndGetTitle()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockContentBrowserClientBrowserTest, ++ WebSocketConnectionInterruptedAndBlocked) { ++ // Launch a WebSocket server. ++ ASSERT_TRUE(ws_server_.Start()); ++ ++ // Intercept WebSocket and block connection via a filter. ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->SetAdblockEnabled(true); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ controller->AddCustomFilter({"*$websocket"}); ++ ++ NavigateToHTTP("split_packet_check.html"); ++ ++ // WebSocket did not connect. ++ EXPECT_EQ("FAIL", WaitAndGetTitle()); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc b/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_debug_url_browsertest.cc +@@ -0,0 +1,301 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/browser/adblock_url_loader_factory_for_test.h" ++#include "content/public/test/browser_test.h" ++#include "testing/gmock/include/gmock/gmock.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++using testing::_; ++using testing::HasSubstr; ++using testing::Mock; ++using testing::Return; ++using testing::StartsWith; ++ ++namespace adblock { ++ ++class AdblockDebugUrlTest : public InProcessBrowserTest { ++ public: ++ AdblockDebugUrlTest() {} ++ ~AdblockDebugUrlTest() override = default; ++ AdblockDebugUrlTest(const AdblockDebugUrlTest&) = delete; ++ AdblockDebugUrlTest& operator=(const AdblockDebugUrlTest&) = delete; ++ ++ protected: ++ std::string ExecuteScriptAndExtractString(const std::string& js_code) const { ++ content::WebContents* web_contents = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ return content::EvalJs(web_contents->GetPrimaryMainFrame(), js_code) ++ .ExtractString(); ++ } ++ ++ const std::string kReadPageBodyScript = ++ "document.getElementsByTagName('body')[0].firstChild.innerHTML"; ++ ++ const std::string kAdblockDebugUrl = ++ "http://" + ++ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestInvalidUrls) { ++ GURL no_command1(kAdblockDebugUrl); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), no_command1)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL no_command2(kAdblockDebugUrl + "/"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), no_command2)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_command_url(kAdblockDebugUrl + "/some_invalid_command"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_command_url)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_topic(kAdblockDebugUrl + "/filter/add/%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_topic)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_command(kAdblockDebugUrl + "/filters/ad/%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_command)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestFilterCommands) { ++ GURL clear_filters_url(kAdblockDebugUrl + "/filters/clear"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL list_filters_url(kAdblockDebugUrl + "/filters/list"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_no_filters = "OK"; ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL add_filters_url(kAdblockDebugUrl + ++ "/filters/add/%2FadsPlugin%2F%2A%0A%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); ++ ASSERT_THAT(response, StartsWith("OK\n\n")); ++ ASSERT_THAT(response, HasSubstr("adsPlugin/*")); ++ ASSERT_THAT(response, HasSubstr("adsponsor.")); ++ ++ GURL remove_filter_url(kAdblockDebugUrl + "/filters/remove/%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_filter_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_one_filter = "OK\n\n/adsPlugin/*\n"; ++ ASSERT_EQ(expected_one_filter, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestDomainCommands) { ++ GURL clear_domains_url(kAdblockDebugUrl + "/domains/clear"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_domains_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL list_domains_url(kAdblockDebugUrl + "/domains/list"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); ++ std::string expected_no_domains = "OK"; ++ ASSERT_EQ(expected_no_domains, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL add_domain_url(kAdblockDebugUrl + ++ "/domains/add/example.com%0Adomain.org"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_domain_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); ++ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); ++ ASSERT_THAT(response, StartsWith("OK\n\n")); ++ ASSERT_THAT(response, HasSubstr("example.com")); ++ ASSERT_THAT(response, HasSubstr("domain.org")); ++ ++ GURL remove_domain_url(kAdblockDebugUrl + "/domains/remove/example.com"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_domain_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); ++ std::string expected_one_domain = "OK\n\ndomain.org\n"; ++ ASSERT_EQ(expected_one_domain, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_domains_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_domains_url)); ++ ASSERT_EQ(expected_no_domains, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestSubscriptionCommands) { ++ GURL clear_subscriptions_url(kAdblockDebugUrl + "/subscriptions/clear"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_subscriptions_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL list_subscriptions_url(kAdblockDebugUrl + "/subscriptions/list"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); ++ std::string expected_no_subscriptions = "OK"; ++ ASSERT_EQ(expected_no_subscriptions, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL add_subscription_url(kAdblockDebugUrl + ++ "/subscriptions/add/" ++ "https%3A%2F%2Fexample.com%2Flist1.txt%0Ahttps%3A%" ++ "2F%2Fwww.domain.org%2Flist2.txt"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_subscription_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); ++ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); ++ ASSERT_THAT(response, StartsWith("OK\n\n")); ++ ASSERT_THAT(response, HasSubstr("https://example.com/list1.txt")); ++ ASSERT_THAT(response, HasSubstr("https://www.domain.org/list2.txt")); ++ ++ GURL remove_subscription_url( ++ kAdblockDebugUrl + ++ "/subscriptions/remove/https%3A%2F%2Fwww.domain.org%2Flist2.txt"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_subscription_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); ++ std::string expected_one_subscription = ++ "OK\n\nhttps://example.com/list1.txt\n"; ++ ASSERT_EQ(expected_one_subscription, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_subscriptions_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_subscriptions_url)); ++ ASSERT_EQ(expected_no_subscriptions, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestEnableAdblockCommands) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ ++ GURL enable_adblock__url(kAdblockDebugUrl + "/adblock/enable"); ++ GURL disable_adblock_url(kAdblockDebugUrl + "/adblock/disable"); ++ GURL adblock_state_url(kAdblockDebugUrl + "/adblock/state"); ++ ++ ASSERT_TRUE(controller->IsAdblockEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); ++ ASSERT_EQ("OK\n\nenabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), disable_adblock_url)); ++ ASSERT_FALSE(controller->IsAdblockEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); ++ ASSERT_EQ("OK\n\ndisabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), enable_adblock__url)); ++ ASSERT_TRUE(controller->IsAdblockEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), adblock_state_url)); ++ ASSERT_EQ("OK\n\nenabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestEnableAACommands) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ ++ GURL enable_aa_url(kAdblockDebugUrl + "/aa/enable"); ++ GURL disable_aa_url(kAdblockDebugUrl + "/aa/disable"); ++ GURL aa_state_url(kAdblockDebugUrl + "/aa/state"); ++ ++ ASSERT_TRUE(controller->IsAcceptableAdsEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); ++ ASSERT_EQ("OK\n\nenabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), disable_aa_url)); ++ ASSERT_FALSE(controller->IsAcceptableAdsEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); ++ ASSERT_EQ("OK\n\ndisabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), enable_aa_url)); ++ ASSERT_TRUE(controller->IsAcceptableAdsEnabled()); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), aa_state_url)); ++ ASSERT_EQ("OK\n\nenabled", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestFilterCommandsInOldFormat) { ++ GURL clear_filters_url(kAdblockDebugUrl + "/filters/clear"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL list_filters_url(kAdblockDebugUrl + "/filters/list"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_no_filters = "OK"; ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL add_filters_url(kAdblockDebugUrl + ++ "/add?payload=%2FadsPlugin%2F%2A%0A%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ auto response = ExecuteScriptAndExtractString(kReadPageBodyScript); ++ ASSERT_THAT(response, StartsWith("OK\n\n")); ++ ASSERT_THAT(response, HasSubstr("adsPlugin/*")); ++ ASSERT_THAT(response, HasSubstr("adsponsor.")); ++ ++ GURL remove_filter_url(kAdblockDebugUrl + "/remove?payload=%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_filter_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_one_filter = "OK\n\n/adsPlugin/*\n"; ++ ASSERT_EQ(expected_one_filter, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc b/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_filter_list_browsertest.cc +@@ -0,0 +1,246 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "base/environment.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "components/adblock/core/adblock_switches.h" ++#include "components/adblock/core/subscription/subscription_config.h" ++#include "components/version_info/version_info.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++ ++namespace adblock { ++ ++class AdblockFilterListDownloadTestBase : public InProcessBrowserTest { ++ public: ++ AdblockFilterListDownloadTestBase() ++ : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} ++ // We need to set server and request handler asap ++ void SetUpInProcessBrowserTestFixture() override { ++ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); ++ host_resolver()->AddRule("easylist-downloads.adblockplus.org", "127.0.0.1"); ++ https_server_.RegisterRequestHandler( ++ base::BindRepeating(&AdblockFilterListDownloadTestBase::RequestHandler, ++ base::Unretained(this))); ++ net::EmbeddedTestServer::ServerCertificateConfig cert_config; ++ cert_config.dns_names = {"easylist-downloads.adblockplus.org"}; ++ https_server_.SetSSLConfig(cert_config); ++ ASSERT_TRUE(https_server_.Start()); ++ SetFilterListServerPortForTesting(https_server_.port()); ++ } ++ ++ void CheckRequestParams(const net::test_server::HttpRequest& request, ++ std::string expected_disabled_value) { ++ std::string os; ++ base::ReplaceChars(version_info::GetOSType(), base::kWhitespaceASCII, "", ++ &os); ++ EXPECT_TRUE(request.relative_url.find("addonName=eyeo-chromium-sdk") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("addonVersion=1.0") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("platformVersion=1.0") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("platform=" + os) != ++ std::string::npos); ++ if (RunsOnEyeoCI()) { ++ // Those two checks below require "eyeo_application_name" and ++ // "eyeo_application_version" to be set as gn gen args. ++ EXPECT_TRUE( ++ request.relative_url.find("application=app_name_from_ci_config") != ++ std::string::npos) ++ << "Did you set \"eyeo_application_name\" gn gen arg?"; ++ EXPECT_TRUE(request.relative_url.find( ++ "applicationVersion=app_version_from_ci_config") != ++ std::string::npos) ++ << "Did you set \"eyeo_application_version\" gn gen arg?"; ++ } ++ EXPECT_TRUE( ++ request.relative_url.find("disabled=" + expected_disabled_value) != ++ std::string::npos); ++ } ++ ++ virtual std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) { ++ if (request.method == net::test_server::HttpMethod::METHOD_GET && ++ (base::StartsWith(request.relative_url, "/abp-filters-anti-cv.txt") || ++ base::StartsWith(request.relative_url, "/easylist.txt") || ++ base::StartsWith(request.relative_url, "/exceptionrules.txt"))) { ++ CheckRequestParams(request, "false"); ++ default_lists_.insert(request.relative_url.substr( ++ 1, request.relative_url.find_first_of("?") - 1)); ++ } ++ ++ // Unhandled requests result in the Embedded test server sending a 404. ++ return nullptr; ++ } ++ ++ void CloseBrowserFromAnyThread() { ++ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING}) ++ ->PostTask( ++ FROM_HERE, ++ base::BindOnce( ++ &AdblockFilterListDownloadTestBase::CloseBrowserAsynchronously, ++ base::Unretained(this), browser())); ++ } ++ ++ bool RunsOnEyeoCI() { ++ auto env = base::Environment::Create(); ++ std::string value; ++ env->GetVar("CI_PROJECT_NAME", &value); ++ return value == "chromium-sdk"; ++ } ++ ++ protected: ++ net::EmbeddedTestServer https_server_; ++ std::set default_lists_; ++}; ++ ++class AdblockEnabledFilterListDownloadTest ++ : public AdblockFilterListDownloadTestBase { ++ public: ++ std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) override { ++ auto return_value = ++ AdblockFilterListDownloadTestBase::RequestHandler(request); ++ // If we get all expected requests we simply finish the test by closing ++ // the browser, otherwise test will fail with a timeout. ++ if (default_lists_.size() == 3) { ++ CloseBrowserFromAnyThread(); ++ } ++ ++ return return_value; ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockEnabledFilterListDownloadTest, ++ TestInitialDownloads) { ++ RunUntilBrowserProcessQuits(); ++} ++ ++class AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest ++ : public AdblockFilterListDownloadTestBase { ++ public: ++ AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest() { ++ const auto testing_interval = base::Seconds(1); ++ SubscriptionServiceFactory::SetUpdateCheckAndDelayIntervalsForTesting( ++ testing_interval, testing_interval); ++ } ++ ++ std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) override { ++ // If we get expected HEAD request we simply finish the test by closing ++ // the browser, otherwise test will fail with a timeout. ++ if (request.method == net::test_server::HttpMethod::METHOD_HEAD && ++ base::StartsWith(request.relative_url, "/exceptionrules.txt")) { ++ CheckRequestParams(request, "true"); ++ CloseBrowserFromAnyThread(); ++ } ++ ++ return nullptr; ++ } ++ ++ void SetUpCommandLine(base::CommandLine* command_line) override { ++ command_line->AppendSwitch(adblock::switches::kDisableAcceptableAds); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F( ++ AdblockEnabledAcceptableAdsDisabledFilterListDownloadTest, ++ TestInitialDownloads) { ++ RunUntilBrowserProcessQuits(); ++} ++ ++enum class DisableSwitch { Adblock, Eyeo }; ++ ++class AdblockDisabledFilterListDownloadTest ++ : public AdblockFilterListDownloadTestBase, ++ public testing::WithParamInterface { ++ public: ++ void SetUpCommandLine(base::CommandLine* command_line) override { ++ command_line->AppendSwitch(GetParam() == DisableSwitch::Adblock ++ ? adblock::switches::kDisableAdblock ++ : adblock::switches::kDisableEyeoFiltering); ++ } ++ ++ void VerifyNoDownloads() { ++ ASSERT_EQ(0u, default_lists_.size()); ++ CloseBrowserFromAnyThread(); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_P(AdblockDisabledFilterListDownloadTest, ++ TestInitialDownloads) { ++ // This test assumes that inital downloads (for adblock enabled) will happen ++ // within 10 seconds. When tested locally it always happens within 3 seconds. ++ base::OneShotTimer timer; ++ timer.Start( ++ FROM_HERE, base::Seconds(10), ++ base::BindOnce(&AdblockDisabledFilterListDownloadTest::VerifyNoDownloads, ++ base::Unretained(this))); ++ RunUntilBrowserProcessQuits(); ++} ++ ++INSTANTIATE_TEST_SUITE_P(All, ++ AdblockDisabledFilterListDownloadTest, ++ testing::Values(DisableSwitch::Adblock, ++ DisableSwitch::Eyeo)); ++ ++#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ++class AdblockPtLocaleFilterListDownloadTest ++ : public AdblockFilterListDownloadTestBase { ++ public: ++ AdblockPtLocaleFilterListDownloadTest() ++ : AdblockFilterListDownloadTestBase() { ++ setenv("LANGUAGE", "pt_PT", 1); ++ } ++ ++ std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) override { ++ EXPECT_FALSE(base::StartsWith(request.relative_url, "/easylist.txt")); ++ if (request.method == net::test_server::HttpMethod::METHOD_GET && ++ (base::StartsWith(request.relative_url, "/abp-filters-anti-cv.txt") || ++ base::StartsWith(request.relative_url, ++ "/easylistportuguese+easylist.txt") || ++ base::StartsWith(request.relative_url, "/exceptionrules.txt"))) { ++ CheckRequestParams(request, "false"); ++ default_lists_.insert(request.relative_url.substr( ++ 1, request.relative_url.find_first_of("?") - 1)); ++ } ++ ++ // If we get all expected requests we simply finish the test by closing ++ // the browser, otherwise test will fail with a timeout. ++ if (default_lists_.size() == 3) { ++ CloseBrowserFromAnyThread(); ++ } ++ ++ // Unhandled requests result in the Embedded test server sending a 404. ++ return nullptr; ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockPtLocaleFilterListDownloadTest, ++ TestInitialDownloads) { ++ RunUntilBrowserProcessQuits(); ++} ++#endif ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc b/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_filtering_configurations_browsertest.cc +@@ -0,0 +1,460 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include ++#include "base/memory/raw_ptr.h" ++#include "base/ranges/algorithm.h" ++#include "base/run_loop.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/adblock_switches.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/adblock/core/configuration/filtering_configuration.h" ++#include "components/adblock/core/configuration/persistent_filtering_configuration.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/version_info/version_info.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "gmock/gmock.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "url/gurl.h" ++ ++namespace adblock { ++ ++class SubscriptionInstalledWaiter ++ : public SubscriptionService::SubscriptionObserver { ++ public: ++ explicit SubscriptionInstalledWaiter( ++ SubscriptionService* subscription_service) ++ : subscription_service_(subscription_service) { ++ subscription_service_->AddObserver(this); ++ } ++ ++ ~SubscriptionInstalledWaiter() override { ++ subscription_service_->RemoveObserver(this); ++ } ++ ++ void WaitUntilSubscriptionsInstalled(std::vector subscriptions) { ++ awaited_subscriptions_ = std::move(subscriptions); ++ run_loop_.Run(); ++ } ++ ++ void OnSubscriptionInstalled(const GURL& subscription_url) override { ++ awaited_subscriptions_.erase( ++ base::ranges::remove(awaited_subscriptions_, subscription_url), ++ awaited_subscriptions_.end()); ++ if (awaited_subscriptions_.empty()) { ++ run_loop_.Quit(); ++ } ++ } ++ ++ protected: ++ raw_ptr subscription_service_; ++ base::RunLoop run_loop_; ++ std::vector awaited_subscriptions_; ++}; ++ ++class AdblockFilteringConfigurationBrowserTest : public InProcessBrowserTest { ++ public: ++ void SetUpInProcessBrowserTestFixture() override { ++ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); ++ host_resolver()->AddRule("*", "127.0.0.1"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/adblock"); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ } ++ ++ void SetUpOnMainThread() override { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ } ++ ++ GURL BlockingFilterListUrl() { ++ return embedded_test_server()->GetURL( ++ "/filterlist_that_blocks_resource.txt"); ++ } ++ ++ GURL ElementHidingFilterListUrl() { ++ return embedded_test_server()->GetURL( ++ "/filterlist_that_hides_resource.txt"); ++ } ++ ++ GURL AllowingFilterListUrl() { ++ return embedded_test_server()->GetURL( ++ "/filterlist_that_allows_resource.txt"); ++ } ++ ++ GURL GetPageUrl() { ++ return embedded_test_server()->GetURL("test.org", "/innermost_frame.html"); ++ } ++ ++ void NavigateToPage() { ++ ASSERT_TRUE(NavigateToURL( ++ browser()->tab_strip_model()->GetActiveWebContents(), GetPageUrl())); ++ } ++ ++ std::unique_ptr MakeConfiguration( ++ std::string name) { ++ return std::make_unique( ++ browser()->profile()->GetPrefs(), name); ++ } ++ ++ void InstallFilteringConfiguration( ++ std::unique_ptr configuration) { ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->InstallFilteringConfiguration(std::move(configuration)); ++ } ++ ++ void UninstallFilteringConfiguration(const std::string& configuration_name) { ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->UninstallFilteringConfiguration(configuration_name); ++ } ++ ++ void WaitUntilSubscriptionsInstalled(std::vector subscriptions) { ++ SubscriptionInstalledWaiter waiter( ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile())); ++ waiter.WaitUntilSubscriptionsInstalled(std::move(subscriptions)); ++ } ++ ++ std::string GetResourcesComputedStyle() { ++ const std::string javascript = ++ "window.getComputedStyle(document.getElementById('subresource'))." ++ "display"; ++ return content::EvalJs(browser() ++ ->tab_strip_model() ++ ->GetActiveWebContents() ++ ->GetPrimaryMainFrame(), ++ javascript) ++ .ExtractString(); ++ } ++ ++ void ExpectResourceBlocked() { ++ EXPECT_EQ("none", GetResourcesComputedStyle()); ++ } ++ ++ void ExpectResourceShown() { ++ EXPECT_EQ("inline", GetResourcesComputedStyle()); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ NoBlockingByDefault) { ++ auto configuration = MakeConfiguration("config"); ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ResourceBlockedByFilteringConfigurationsList) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddFilterList(BlockingFilterListUrl()); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl()}); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ResourceHiddenByFilteringConfigurationsList) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddFilterList(ElementHidingFilterListUrl()); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ WaitUntilSubscriptionsInstalled({ElementHidingFilterListUrl()}); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ResourceAllowedByFilteringConfigurationsList) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddFilterList(BlockingFilterListUrl()); ++ configuration->AddFilterList(ElementHidingFilterListUrl()); ++ configuration->AddFilterList(AllowingFilterListUrl()); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl(), ++ AllowingFilterListUrl(), ++ ElementHidingFilterListUrl()}); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ BlockingTakesPrecedenceBetweenConfigurations) { ++ auto blocking_configuration = MakeConfiguration("blocking"); ++ blocking_configuration->AddFilterList(BlockingFilterListUrl()); ++ ++ auto allowing_configuration = MakeConfiguration("allowing"); ++ allowing_configuration->AddFilterList(AllowingFilterListUrl()); ++ ++ InstallFilteringConfiguration(std::move(blocking_configuration)); ++ InstallFilteringConfiguration(std::move(allowing_configuration)); ++ ++ WaitUntilSubscriptionsInstalled( ++ {BlockingFilterListUrl(), AllowingFilterListUrl()}); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ElementBlockedByCustomFilter) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddCustomFilter("*resource.png"); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ElementAllowedByCustomFilter) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddCustomFilter("*resource.png"); ++ configuration->AddCustomFilter("@@*resource.png"); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ElementAllowedByAllowedDomain) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddCustomFilter("*resource.png"); ++ configuration->AddAllowedDomain(GetPageUrl().host()); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ PRE_CustomFiltersPersist) { ++ auto configuration = MakeConfiguration("persistent"); ++ // This custom filter will survive browser restart. ++ configuration->AddCustomFilter("*resource.png"); ++ InstallFilteringConfiguration(std::move(configuration)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ CustomFiltersPersist) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration != configurations.end()); ++ EXPECT_THAT((*configuration)->GetCustomFilters(), ++ testing::UnorderedElementsAre("*resource.png")); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ DisabledConfigurationDoesNotBlock) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->AddCustomFilter("*resource.png"); ++ configuration->SetEnabled(false); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ConfigurationCanBeUsedAfterInstalling) { ++ auto configuration = MakeConfiguration("config"); ++ auto* configuration_ptr = configuration.get(); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ configuration_ptr->AddCustomFilter("*resource.png"); ++ ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ ConfigurationCanBeDisabledAfterInstalling) { ++ auto configuration = MakeConfiguration("config"); ++ auto* configuration_ptr = configuration.get(); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ configuration_ptr->AddCustomFilter("*resource.png"); ++ configuration_ptr->SetEnabled(false); ++ ++ NavigateToPage(); ++ ExpectResourceShown(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ SubscriptionsDownloadedAfterConfigurationEnabled) { ++ auto configuration = MakeConfiguration("config"); ++ configuration->SetEnabled(false); ++ configuration->AddFilterList(BlockingFilterListUrl()); ++ configuration->AddFilterList(ElementHidingFilterListUrl()); ++ configuration->AddFilterList(AllowingFilterListUrl()); ++ auto* configuration_ptr = configuration.get(); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ configuration_ptr->SetEnabled(true); ++ ++ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl(), ++ AllowingFilterListUrl(), ++ ElementHidingFilterListUrl()}); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ PRE_DownloadedSubscriptionsPersistOnDisk) { ++ auto configuration = MakeConfiguration("config"); ++ // This filter list setting will survive browser restart. ++ configuration->AddFilterList(BlockingFilterListUrl()); ++ ++ InstallFilteringConfiguration(std::move(configuration)); ++ ++ // This downloaded subscription won't need to be re-downloaded after restart. ++ WaitUntilSubscriptionsInstalled({BlockingFilterListUrl()}); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ DownloadedSubscriptionsPersistOnDisk) { ++ NavigateToPage(); ++ ExpectResourceBlocked(); ++} ++ ++// 1st run: create. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ PRE_PRE_CreateThenRemoveConfiguration) { ++ auto configuration = MakeConfiguration("persistent"); ++ InstallFilteringConfiguration(std::move(configuration)); ++} ++ ++// 2nd run: remove. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ PRE_CreateThenRemoveConfiguration) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration != configurations.end()); ++ UninstallFilteringConfiguration((*configuration)->GetName()); ++ configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration == configurations.end()); ++} ++ ++// 3rd run: verify not present. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationBrowserTest, ++ CreateThenRemoveConfiguration) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration == configurations.end()); ++} ++ ++class AdblockFilteringConfigurationDisableSwitchBrowserTest ++ : public AdblockFilteringConfigurationBrowserTest { ++ public: ++ void SetUpCommandLine(base::CommandLine* command_line) override { ++ if (base::StartsWith( ++ ::testing::UnitTest::GetInstance()->current_test_info()->name(), ++ "PRE_CreateConfigAndConfirmEnableStateAfterReset")) { ++ command_line->AppendSwitch(adblock::switches::kDisableEyeoFiltering); ++ } ++ } ++}; ++ ++// 1st run: create configuration and make sure it is enabled by default. ++IN_PROC_BROWSER_TEST_F( ++ AdblockFilteringConfigurationDisableSwitchBrowserTest, ++ PRE_PRE_PRE_CreateConfigAndConfirmEnableStateAfterReset) { ++ auto configuration = MakeConfiguration("persistent"); ++ ASSERT_TRUE(configuration->IsEnabled()); ++ InstallFilteringConfiguration(std::move(configuration)); ++} ++ ++// 2nd run: make sure configuration is enabled after restart. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationDisableSwitchBrowserTest, ++ PRE_PRE_CreateConfigAndConfirmEnableStateAfterReset) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration != configurations.end()); ++ ASSERT_TRUE((*configuration)->IsEnabled()); ++} ++ ++// 3rd run: after adding "--disable-eyeo-filtering" make sure configuration is ++// disabled. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationDisableSwitchBrowserTest, ++ PRE_CreateConfigAndConfirmEnableStateAfterReset) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration != configurations.end()); ++ ASSERT_FALSE((*configuration)->IsEnabled()); ++} ++ ++// 4th run: without "--disable-eyeo-filtering" make sure configuration is still ++// disabled. ++IN_PROC_BROWSER_TEST_F(AdblockFilteringConfigurationDisableSwitchBrowserTest, ++ CreateConfigAndConfirmEnableStateAfterReset) { ++ auto configurations = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()) ++ ->GetInstalledFilteringConfigurations(); ++ auto configuration = base::ranges::find(configurations, "persistent", ++ &FilteringConfiguration::GetName); ++ ASSERT_TRUE(configuration != configurations.end()); ++ ASSERT_FALSE((*configuration)->IsEnabled()); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc b/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc +@@ -0,0 +1,463 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include ++ ++#include "base/ranges/algorithm.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ssl/https_upgrades_util.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/browser/adblock_filter_match.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/blocked_content/popup_blocker_tab_helper.h" ++#include "components/embedder_support/switches.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace adblock { ++ ++namespace { ++class TabAddedRemovedObserver : public TabStripModelObserver { ++ public: ++ explicit TabAddedRemovedObserver(TabStripModel* tab_strip_model) { ++ tab_strip_model->AddObserver(this); ++ } ++ ++ void OnTabStripModelChanged( ++ TabStripModel* tab_strip_model, ++ const TabStripModelChange& change, ++ const TabStripSelectionChange& selection) override { ++ if (change.type() == TabStripModelChange::kInserted) { ++ inserted_ = true; ++ return; ++ } ++ if (change.type() == TabStripModelChange::kRemoved) { ++ EXPECT_TRUE(inserted_); ++ removed_ = true; ++ loop_.Quit(); ++ return; ++ } ++ NOTREACHED(); ++ } ++ ++ void Wait() { ++ if (inserted_ && removed_) { ++ return; ++ } ++ loop_.Run(); ++ } ++ ++ private: ++ bool inserted_ = false; ++ bool removed_ = false; ++ base::RunLoop loop_; ++}; ++} // namespace ++ ++class ResourceClassificationRunnerObserver ++ : public ResourceClassificationRunner::Observer { ++ public: ++ ~ResourceClassificationRunnerObserver() override { ++ VerifyNoUnexpectedNotifications(); ++ } ++ // ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ if (match_result == FilterMatchResult::kAllowRule) { ++ allowed_ads_notifications.push_back(url); ++ } else { ++ blocked_ads_notifications.push_back(url); ++ } ++ } ++ ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ allowed_pages_notifications.push_back(url); ++ } ++ ++ void OnPopupMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ auto& list = (match_result == FilterMatchResult::kBlockRule ++ ? blocked_popups_notifications ++ : allowed_popups_notifications); ++ auto it = std::find(list.begin(), list.end(), url.ExtractFileName()); ++ ASSERT_FALSE(it == list.end()) ++ << "Path " << url.ExtractFileName() << " not on list"; ++ list.erase(it); ++ if (popup_notifications_run_loop_ && allowed_popups_notifications.empty() && ++ blocked_popups_notifications.empty()) { ++ popup_notifications_run_loop_->Quit(); ++ } ++ } ++ ++ void VerifyNotificationSent(base::StringPiece path, std::vector& list) { ++ auto it = base::ranges::find(list, path, &GURL::ExtractFileName); ++ ASSERT_FALSE(it == list.end()) << "Path " << path << " not on list"; ++ // Remove expected notifications so that we can verify there are no ++ // unexpected notifications left by the end of each test. ++ list.erase(it); ++ } ++ ++ void VerifyNoUnexpectedNotifications() { ++ EXPECT_TRUE(blocked_ads_notifications.empty()); ++ EXPECT_TRUE(allowed_ads_notifications.empty()); ++ EXPECT_TRUE(blocked_popups_notifications.empty()); ++ EXPECT_TRUE(allowed_popups_notifications.empty()); ++ EXPECT_TRUE(allowed_pages_notifications.empty()); ++ } ++ ++ std::vector blocked_ads_notifications; ++ std::vector allowed_ads_notifications; ++ std::vector allowed_pages_notifications; ++ std::vector blocked_popups_notifications; ++ std::vector allowed_popups_notifications; ++ std::unique_ptr popup_notifications_run_loop_; ++}; ++ ++// Simulated setup: ++// http://outer.com/outermost_frame.html ++// has an iframe: http://middle.com/middle_frame.html ++// has an iframe: http://inner.com/innermost_frame.html ++// has a subresource http://inner.com/resource.png ++// ++// All of these files are in chrome/test/data/adblock. Cross-domain distribution ++// is simulated via SetupCrossSiteRedirector. ++// innermost_frame.html reports whether resource.png is visible via ++// window.top.postMessage to outermost_frame.html, which stores a global ++// subresource_visible JS variable. ++class AdblockFrameHierarchyBrowserTest : public InProcessBrowserTest { ++ public: ++ void SetUpOnMainThread() override { ++ InProcessBrowserTest::SetUpOnMainThread(); ++ host_resolver()->AddRule("*", "127.0.0.1"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/adblock"); ++ content::SetupCrossSiteRedirector(embedded_test_server()); ++ AllowHttpForHostnamesForTesting({"outer.com", "inner.com", "middle.com"}, ++ browser()->profile()->GetPrefs()); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ auto* classification_runner = ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()); ++ classification_runner->AddObserver(&observer); ++ } ++ ++ void TearDownOnMainThread() override { ++ auto* classification_runner = ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()); ++ classification_runner->RemoveObserver(&observer); ++ InProcessBrowserTest::TearDownOnMainThread(); ++ } ++ ++ void SetUpCommandLine(base::CommandLine* command_line) override { ++ command_line->AppendSwitch(embedder_support::kDisablePopupBlocking); ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ for (auto& filter : filters) { ++ controller->AddCustomFilter(filter); ++ } ++ } ++ ++ void NavigateToOutermostFrame() { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), embedded_test_server()->GetURL( ++ "/cross-site/outer.com/outermost_frame.html"))); ++ } ++ ++ void NavigateToOutermostFrameWithAboutBlank() { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), ++ embedded_test_server()->GetURL( ++ "/cross-site/outer.com/outermost_frame_with_about_blank.html"))); ++ } ++ ++ void NavigateToPopupParentFrameAndWaitForNotifications() { ++ observer.popup_notifications_run_loop_ = std::make_unique(); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), embedded_test_server()->GetURL( ++ "/cross-site/outer.com/popup_parent.html"))); ++ if (!(observer.allowed_popups_notifications.empty() && ++ observer.blocked_popups_notifications.empty())) { ++ observer.popup_notifications_run_loop_->Run(); ++ } ++ } ++ ++ void VerifyTargetResourceShown(bool expected_shown) { ++ // Since in one test we dynamically load (write) `about:blank` iframe after ++ // parent page is loaded, we need to have some wait & poll mechanism to wait ++ // until such a frame (and its resources) is completely loaded by JS. ++ std::string script = base::StringPrintf(R"( ++ (async () => { ++ let count = 10; ++ function waitFor(condition) { ++ const poll = resolve => { ++ if(condition() || !count--) resolve(); ++ else setTimeout(_ => poll(resolve), 200); ++ } ++ return new Promise(poll); ++ } ++ // Waits up to 2 seconds ++ await waitFor(_ => subresource_visible === %s); ++ return subresource_visible === true; ++ })() ++ )", ++ expected_shown ? "true" : "false"); ++ EXPECT_EQ( ++ expected_shown, ++ content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), ++ script)); ++ } ++ ++ int NumberOfOpenTabs() { return browser()->tab_strip_model()->GetTabCount(); } ++ ++ ResourceClassificationRunnerObserver observer; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceShownWithNoFilters) { ++ SetFilters({}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, SubresourceBlocked) { ++ SetFilters({"/resource.png"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(false); ++ observer.VerifyNotificationSent("resource.png", ++ observer.blocked_ads_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaInnerFrame) { ++ SetFilters({"/resource.png", "@@||inner.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++ observer.VerifyNotificationSent("resource.png", ++ observer.allowed_ads_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaMiddleFrame) { ++ SetFilters({"/resource.png", "@@||middle.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++ observer.VerifyNotificationSent("resource.png", ++ observer.allowed_ads_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaOutermostFrame) { ++ SetFilters({"/resource.png", "@@||outer.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++ observer.VerifyNotificationSent("resource.png", ++ observer.allowed_ads_notifications); ++ observer.VerifyNotificationSent("outermost_frame.html", ++ observer.allowed_pages_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceBlockedWhenInvalidAllowRule) { ++ SetFilters({"/resource.png", "@@||bogus.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(false); ++ observer.VerifyNotificationSent("resource.png", ++ observer.blocked_ads_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ DISABLED_PopupHandledByChromiumWithoutFilters) { ++ // Without any popup-specific filters, blocking popups is handed over to ++ // Chromium, which has it's own heuristics that are not based on filters. ++ SetFilters({}); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ // The popup was not opened: ++ EXPECT_EQ(1, NumberOfOpenTabs()); ++ // Because Chromium's built-in popup blocker stopped it: ++ EXPECT_EQ(1u, blocked_content::PopupBlockerTabHelper::FromWebContents( ++ browser()->tab_strip_model()->GetActiveWebContents()) ++ ->GetBlockedPopupsCount()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, PopupBlockedByFilter) { ++ SetFilters({"http://inner.com*/popup.html$popup"}); ++ observer.blocked_popups_notifications.emplace_back("popup.html"); ++ TabAddedRemovedObserver observer(browser()->tab_strip_model()); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ observer.Wait(); ++ EXPECT_EQ(1, NumberOfOpenTabs()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, PopupAllowedByFilter) { ++ SetFilters({"http://inner.com*/popup.html$popup", ++ "@@http://inner.com*/popup.html$popup"}); ++ observer.allowed_popups_notifications.emplace_back("popup.html"); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ // Popup was allowed to open in a new tab ++ EXPECT_EQ(2, NumberOfOpenTabs()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ PopupAllowedByDomainSpecificFilter) { ++ // The frame that wants to open the popup is hosted on middle.com. ++ // The $popup allow rule applies to that frame. ++ SetFilters({"http://inner.com*/popup.html$popup", ++ "@@http://inner.com*/popup.html$popup,domain=middle.com"}); ++ observer.allowed_popups_notifications.emplace_back("popup.html"); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ // Popup was allowed to open in a new tab ++ EXPECT_EQ(2, NumberOfOpenTabs()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ PopupNotAllowedByDomainSpecificFilter) { ++ // The frame that wants to open the popup is hosted on middle.com. ++ // The $popup allow rule does not apply because it is specific to outer.com. ++ // outer.com is not the frame that is opening the popup. ++ SetFilters({"http://inner.com*/popup.html$popup", ++ "@@http://inner.com*/popup.html$popup,domain=outer.com"}); ++ observer.blocked_popups_notifications.emplace_back("popup.html"); ++ TabAddedRemovedObserver observer(browser()->tab_strip_model()); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ observer.Wait(); ++ EXPECT_EQ(1, NumberOfOpenTabs()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ PopupAllowedByParentDocument) { ++ // The outermost frame has a blanket allowing rule of $document type. ++ SetFilters({"http://inner.com*/popup.html$popup", ++ "@@||outer.com^$document,domain=outer.com"}); ++ observer.allowed_popups_notifications.emplace_back("popup.html"); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ // Popup was allowed to open in a new tab ++ EXPECT_EQ(2, NumberOfOpenTabs()); ++ observer.VerifyNotificationSent("popup_parent.html", ++ observer.allowed_pages_notifications); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ PopupAllowedByIntermediateParentDocument) { ++ // The middle frame has a blanket allowing rule of $document type. ++ SetFilters({"http://inner.com*/popup.html$popup", ++ "@@||middle.com^$document,domain=outer.com"}); ++ observer.allowed_popups_notifications.emplace_back("popup.html"); ++ NavigateToPopupParentFrameAndWaitForNotifications(); ++ // Popup was allowed to open in a new tab ++ EXPECT_EQ(2, NumberOfOpenTabs()); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, BlankFrameHiding) { ++ SetFilters({"##.about_blank_div"}); ++ NavigateToOutermostFrameWithAboutBlank(); ++ std::string script = R"( ++ function writeIframe() { ++ let frameDocument = document.getElementById("about_blank").contentWindow.document; ++ frameDocument.open("text/html"); ++ frameDocument.write(` ++ ++ ++

++ ++ `); ++ frameDocument.close(); ++ } ++ if (document.readyState == "complete") { ++ writeIframe(); ++ } else { ++ document.getElementById("about_blank").addEventListener("load", writeIframe); ++ } ++ )"; ++ EXPECT_TRUE(content::ExecJs( ++ browser()->tab_strip_model()->GetActiveWebContents(), script)); ++ VerifyTargetResourceShown(false); ++ SetFilters({"@@^eyeo=true$document"}); ++ NavigateToOutermostFrameWithAboutBlank(); ++ EXPECT_TRUE(content::ExecJs( ++ browser()->tab_strip_model()->GetActiveWebContents(), script)); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, BlankFrameBlocking) { ++ SetFilters({"/resource.png"}); ++ NavigateToOutermostFrameWithAboutBlank(); ++ std::string script = R"( ++ function writeIframe() { ++ let frameDocument = document.getElementById("about_blank").contentWindow.document; ++ frameDocument.open("text/html"); ++ frameDocument.write(` ++ ++ ++ ++ ++ `); ++ frameDocument.close(); ++ } ++ if (document.readyState == "complete") { ++ writeIframe(); ++ } else { ++ document.getElementById("about_blank").addEventListener("load", writeIframe); ++ } ++ )"; ++ EXPECT_TRUE(content::ExecJs( ++ browser()->tab_strip_model()->GetActiveWebContents(), script)); ++ VerifyTargetResourceShown(false); ++ observer.VerifyNotificationSent("resource.png", ++ observer.blocked_ads_notifications); ++ SetFilters({"@@^eyeo=true$document"}); ++ NavigateToOutermostFrameWithAboutBlank(); ++ EXPECT_TRUE(content::ExecJs( ++ browser()->tab_strip_model()->GetActiveWebContents(), script)); ++ VerifyTargetResourceShown(true); ++ observer.VerifyNotificationSent("resource.png", ++ observer.allowed_ads_notifications); ++} ++ ++// More tests can be added / parametrized, e.g.: ++// - elemhide blocking filters (in conjunction with $elemhide allow rules) ++// - $subdocument-based allow rules ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc b/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_multiple_tabs_browsertest.cc +@@ -0,0 +1,159 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/browser/ui/browser_list.h" ++#include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/sessions/content/session_tab_helper.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++ ++namespace adblock { ++ ++class AdblockMultipleTabsBrowserTest ++ : public InProcessBrowserTest, ++ public ResourceClassificationRunner::Observer { ++ public: ++ void SetUpOnMainThread() override { ++ host_resolver()->AddRule(kTestDomain, "127.0.0.1"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/adblock"); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->AddObserver(this); ++ SetFilters({"blocked.png", "allowed.png", "@@allowed.png"}); ++ } ++ ++ void TearDownInProcessBrowserTestFixture() override { ++ ASSERT_EQ(kTabsCount, static_cast(tabs_with_blocked_resource_.size())); ++ ASSERT_EQ(kTabsCount, static_cast(tabs_with_allowed_resource_.size())); ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ for (auto& filter : filters) { ++ controller->AddCustomFilter(filter); ++ } ++ } ++ ++ void RestoreTabs(Browser* browser) { ++ content::DOMMessageQueue queue; ++ RecentTabsSubMenuModel menu(nullptr, browser); ++ menu.ExecuteCommand(menu.GetFirstRecentTabsCommandId(), 0); ++ for (int i = 0; i < kTabsCount; ++i) { ++ std::string message; ++ EXPECT_TRUE(queue.WaitForMessage(&message)); ++ EXPECT_EQ("\"READY\"", message); ++ } ++ } ++ ++ // ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ const content::WebContents* wc = ++ content::WebContents::FromRenderFrameHost(render_frame_host); ++ if (match_result == FilterMatchResult::kBlockRule && ++ url.path() == "/blocked.png") { ++ tabs_with_blocked_resource_.insert( ++ sessions::SessionTabHelper::IdForTab(wc).id()); ++ } else if (match_result == FilterMatchResult::kAllowRule && ++ url.path() == "/allowed.png") { ++ tabs_with_allowed_resource_.insert( ++ sessions::SessionTabHelper::IdForTab(wc).id()); ++ } ++ } ++ ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ void OnPopupMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ protected: ++ const int kTabsCount = 4; ++ const char* kTestDomain = "example.com"; ++ std::set tabs_with_blocked_resource_; ++ std::set tabs_with_allowed_resource_; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockMultipleTabsBrowserTest, PRE_OpenManyTabs) { ++ // Load page in already opened tab ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), ++ embedded_test_server()->GetURL(kTestDomain, "/tab-restore.html"))); ++ // Open more tabs ++ for (int i = 0; i < kTabsCount - 1; ++i) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( ++ browser(), ++ embedded_test_server()->GetURL(kTestDomain, "/tab-restore.html"), ++ WindowOpenDisposition::NEW_FOREGROUND_TAB, ++ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); ++ } ++ EXPECT_EQ(kTabsCount, browser()->tab_strip_model()->count()); ++ EXPECT_EQ(kTabsCount, static_cast(tabs_with_blocked_resource_.size())); ++ EXPECT_EQ(kTabsCount, static_cast(tabs_with_allowed_resource_.size())); ++ ++ // Open a new browser instance ++ ui_test_utils::NavigateToURLWithDisposition( ++ browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::NEW_WINDOW, ++ ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER); ++ BrowserList* active_browser_list = BrowserList::GetInstance(); ++ EXPECT_EQ(2u, active_browser_list->size()); ++ ++ // Close the 1st browser and clear tabs test data ++ CloseBrowserSynchronously(browser()); ++ EXPECT_EQ(1u, active_browser_list->size()); ++ tabs_with_blocked_resource_.clear(); ++ tabs_with_allowed_resource_.clear(); ++ ++ Browser* browser = active_browser_list->get(0); ++ // Restore tabs from1 st browser instance (already closed) in 2nd instance ++ RestoreTabs(browser); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockMultipleTabsBrowserTest, OpenManyTabs) { ++ ASSERT_EQ(0u, tabs_with_blocked_resource_.size()); ++ ASSERT_EQ(0u, tabs_with_allowed_resource_.size()); ++ // Restore tabs from previous session (previous test) ++ RestoreTabs(browser()); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc b/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_non_ascii_browsertest.cc +@@ -0,0 +1,77 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace adblock { ++ ++class AdblockNonASCIIBrowserTest : public InProcessBrowserTest { ++ public: ++ void SetUpOnMainThread() override { ++ host_resolver()->AddRule("xn----dtbfdbwspgnceulm.xn--p1ai", "127.0.0.1"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/adblock"); ++ content::SetupCrossSiteRedirector(embedded_test_server()); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ for (auto& filter : filters) { ++ controller->AddCustomFilter(filter); ++ } ++ } ++ ++ std::string ExecuteScriptAndExtractString(const std::string& js_code) const { ++ content::WebContents* web_contents = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ return content::EvalJs(web_contents->GetPrimaryMainFrame(), js_code) ++ .ExtractString(); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockNonASCIIBrowserTest, BlockNonASCII) { ++ static constexpr char kCheckVisibility[] = ++ R"(getComputedStyle(document.getElementsByClassName("форум")[0]).display)"; ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), ++ embedded_test_server()->GetURL("форум-трейдеров.рф", "/non-ascii.html"))); ++ EXPECT_EQ("block", ExecuteScriptAndExtractString(kCheckVisibility)); ++ ++ SetFilters({"xn----dtbfdbwspgnceulm.xn--p1ai##.форум"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), ++ embedded_test_server()->GetURL("форум-трейдеров.рф", "/non-ascii.html"))); ++ ++ EXPECT_EQ("none", ExecuteScriptAndExtractString(kCheckVisibility)); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_popup_browsertest.cc b/chrome/browser/adblock/test/adblock_popup_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_popup_browsertest.cc +@@ -0,0 +1,462 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "base/run_loop.h" ++#include "chrome/app/chrome_command_ids.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" ++#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/browser/ui/browser_list.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "content/public/browser/render_view_host.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "gmock/gmock.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "url/gurl.h" ++ ++namespace adblock { ++ ++namespace { ++class TabAddedRemovedObserver : public TabStripModelObserver { ++ public: ++ explicit TabAddedRemovedObserver(TabStripModel* tab_strip_model) { ++ tab_strip_model->AddObserver(this); ++ } ++ ++ void OnTabStripModelChanged( ++ TabStripModel* tab_strip_model, ++ const TabStripModelChange& change, ++ const TabStripSelectionChange& selection) override { ++ if (change.type() == TabStripModelChange::kInserted) { ++ inserted_ = true; ++ return; ++ } ++ if (change.type() == TabStripModelChange::kRemoved) { ++ EXPECT_TRUE(inserted_); ++ removed_ = true; ++ loop_.Quit(); ++ return; ++ } ++ NOTREACHED(); ++ } ++ ++ void Wait() { ++ if (inserted_ && removed_) { ++ return; ++ } ++ loop_.Run(); ++ } ++ ++ private: ++ bool inserted_ = false; ++ bool removed_ = false; ++ base::RunLoop loop_; ++}; ++ ++enum class Redirection { ClientSide, ServerSide }; ++ ++} // namespace ++ ++class AdblockPopupBrowserTest ++ : public InProcessBrowserTest, ++ public ResourceClassificationRunner::Observer, ++ public testing::WithParamInterface { ++ public: ++ void SetUpOnMainThread() override { ++ InProcessBrowserTest::SetUpOnMainThread(); ++ host_resolver()->AddRule("*", "127.0.0.1"); ++ embedded_test_server()->RegisterRequestHandler(base::BindRepeating( ++ &AdblockPopupBrowserTest::RequestHandler, base::Unretained(this))); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->AddObserver(this); ++ } ++ ++ void TearDownOnMainThread() override { ++ VerifyNoUnexpectedNotifications(); ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->RemoveObserver(this); ++ InProcessBrowserTest::TearDownOnMainThread(); ++ } ++ ++ void VerifyNoUnexpectedNotifications() { ++ EXPECT_TRUE(blocked_popups_notifications_expectations_.empty()); ++ EXPECT_TRUE(allowed_popups_notifications_expectations_.empty()); ++ } ++ ++ bool IsServerSideRedirection() { ++ return GetParam() == Redirection::ServerSide; ++ } ++ ++ virtual std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) { ++ if (base::StartsWith("/main_page.html", request.relative_url)) { ++ static constexpr char kPopupFrameParent[] = ++ R"( ++ ++ ++ ++ ++ ++ ++ )"; ++ std::unique_ptr http_response( ++ new net::test_server::BasicHttpResponse); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(kPopupFrameParent); ++ http_response->set_content_type("text/html"); ++ return std::move(http_response); ++ } ++ if (base::StartsWith("/popup_frame.html", request.relative_url)) { ++ static constexpr char kPopupFrame[] = ++ R"( ++ ++ ++ ++ ++ ++ ++ Trigger link based popup with redirect ++ Trigger link based popup without redirect ++ Trigger script based popup (tab) with redirect ++ Trigger script based popup (window) with redirect ++ ++ )"; ++ std::unique_ptr http_response( ++ new net::test_server::BasicHttpResponse); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(kPopupFrame); ++ http_response->set_content_type("text/html"); ++ return std::move(http_response); ++ } ++ if (base::StartsWith("/popup_no_redirect.html", request.relative_url) || ++ base::StartsWith("/popup_redirected.html", request.relative_url)) { ++ std::unique_ptr http_response( ++ new net::test_server::BasicHttpResponse); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(""); ++ http_response->set_content_type("text/html"); ++ return std::move(http_response); ++ } ++ if (base::StartsWith("/popup_will_redirect.html", request.relative_url)) { ++ static constexpr char kClientSideRedirectingPopup[] = ++ R"( ++ ++ ++ ++ ++ ++ ++ )"; ++ std::unique_ptr http_response( ++ new net::test_server::BasicHttpResponse); ++ if (IsServerSideRedirection()) { ++ http_response->set_code(net::HTTP_MOVED_PERMANENTLY); ++ http_response->AddCustomHeader( ++ "Location", GetPageUrl("/popup_redirected.html").spec()); ++ } else { ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(kClientSideRedirectingPopup); ++ http_response->set_content_type("text/html"); ++ } ++ return std::move(http_response); ++ } ++ return nullptr; ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ for (auto& filter : filters) { ++ controller->AddCustomFilter(filter); ++ } ++ } ++ ++ void TriggerPopup(const std::string& popup_id) { ++ std::string script = base::StringPrintf( ++ R"( ++ let doc = document.querySelector('iframe[id="popup_frame"]').contentWindow.document; ++ let element = doc.getElementById('%s'); ++ element.click(); ++ )", ++ popup_id.c_str()); ++ EXPECT_TRUE(content::ExecJs( ++ browser()->tab_strip_model()->GetActiveWebContents(), script)); ++ } ++ ++ GURL GetPageUrl(const std::string& page) { ++ return embedded_test_server()->GetURL("popup_frame.org", page); ++ } ++ ++ void NavigateToPage() { ++ ASSERT_TRUE( ++ NavigateToURL(browser()->tab_strip_model()->GetActiveWebContents(), ++ GetPageUrl("/main_page.html"))); ++ } ++ ++ void WaitForTabToLoad() { ++ content::WebContents* popup = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ WaitForLoadStop(popup); ++ } ++ ++ void SetupNotificationsWaiter(base::RunLoop* run_loop) { ++ run_loop_ = run_loop; ++ } ++ ++ // ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ void OnPopupMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ auto& list = (match_result == FilterMatchResult::kBlockRule ++ ? blocked_popups_notifications_expectations_ ++ : allowed_popups_notifications_expectations_); ++ auto it = std::find(list.begin(), list.end(), url.ExtractFileName()); ++ ASSERT_FALSE(it == list.end()) ++ << "Path " << url.ExtractFileName() << " not on list"; ++ list.erase(it); ++ if (run_loop_ && allowed_popups_notifications_expectations_.empty() && ++ blocked_popups_notifications_expectations_.empty()) { ++ run_loop_->Quit(); ++ } ++ } ++ ++ std::vector allowed_popups_notifications_expectations_; ++ std::vector blocked_popups_notifications_expectations_; ++ raw_ptr run_loop_ = nullptr; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockPopupBrowserTest, PopupLinkBlocked) { ++ SetFilters({"popup_no_redirect.html^$popup"}); ++ blocked_popups_notifications_expectations_.emplace_back( ++ "popup_no_redirect.html"); ++ NavigateToPage(); ++ TabAddedRemovedObserver observer(browser()->tab_strip_model()); ++ TriggerPopup("popup_link_no_redirect"); ++ observer.Wait(); ++ EXPECT_EQ(1, browser()->tab_strip_model()->count()); ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ PopupScriptTabWithRedirectBlocked) { ++ SetFilters({"popup_redirected.html^$popup"}); ++ blocked_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ TabAddedRemovedObserver observer(browser()->tab_strip_model()); ++ TriggerPopup("popup_script_tab"); ++ observer.Wait(); ++ EXPECT_EQ(1, browser()->tab_strip_model()->count()); ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ PopupScriptWindowWithRedirectBlocked) { ++ SetFilters({"popup_redirected.html^$popup"}); ++ blocked_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ TriggerPopup("popup_script_window"); ++ // Wait for 2nd browser to get closed (new window popup blocked) ++ EXPECT_EQ(2u, BrowserList::GetInstance()->size()); ++ ui_test_utils::WaitForBrowserToClose(BrowserList::GetInstance()->get(1)); ++ EXPECT_EQ(1u, BrowserList::GetInstance()->size()); ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, PopupLinkWithRedirectBlocked) { ++ SetFilters({"popup_redirected.html^$popup"}); ++ blocked_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ TabAddedRemovedObserver observer(browser()->tab_strip_model()); ++ TriggerPopup("popup_link_will_redirect"); ++ observer.Wait(); ++ EXPECT_EQ(1, browser()->tab_strip_model()->count()); ++} ++ ++IN_PROC_BROWSER_TEST_P( ++ AdblockPopupBrowserTest, ++ PopupScriptTabWithRedirectAllowedByIntermediateParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/popup_frame.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ ui_test_utils::TabAddedWaiter waiter(browser()); ++ TriggerPopup("popup_script_tab"); ++ waiter.Wait(); ++ WaitForTabToLoad(); ++ EXPECT_EQ(2, browser()->tab_strip_model()->count()); ++} ++ ++IN_PROC_BROWSER_TEST_P( ++ AdblockPopupBrowserTest, ++ PopupScriptWindowWithRedirectAllowedByIntermediateParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/popup_frame.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ base::RunLoop run_loop; ++ SetupNotificationsWaiter(&run_loop); ++ TriggerPopup("popup_script_window"); ++ run_loop.Run(); ++ EXPECT_EQ(2u, BrowserList::GetInstance()->size()); ++} ++ ++IN_PROC_BROWSER_TEST_P( ++ AdblockPopupBrowserTest, ++ PopupLinkWithRedirectAllowedByIntermediateParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/popup_frame.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ ui_test_utils::TabAddedWaiter waiter(browser()); ++ TriggerPopup("popup_link_will_redirect"); ++ waiter.Wait(); ++ WaitForTabToLoad(); ++ EXPECT_EQ(2, browser()->tab_strip_model()->count()); ++ ; ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ PopupScriptTabWithRedirectAllowedByParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/main_page.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ ui_test_utils::TabAddedWaiter waiter(browser()); ++ TriggerPopup("popup_script_tab"); ++ waiter.Wait(); ++ WaitForTabToLoad(); ++ EXPECT_EQ(2, browser()->tab_strip_model()->count()); ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ PopupScriptWindowWithRedirectAllowedByParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/main_page.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ base::RunLoop run_loop; ++ SetupNotificationsWaiter(&run_loop); ++ TriggerPopup("popup_script_window"); ++ run_loop.Run(); ++ EXPECT_EQ(2u, BrowserList::GetInstance()->size()); ++} ++ ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ PopupLinkWithRedirectAllowedByParentDocument) { ++ SetFilters({"popup_redirected.html^$popup", "@@/main_page.html^$document"}); ++ allowed_popups_notifications_expectations_.emplace_back( ++ "popup_redirected.html"); ++ NavigateToPage(); ++ ui_test_utils::TabAddedWaiter waiter(browser()); ++ TriggerPopup("popup_link_will_redirect"); ++ waiter.Wait(); ++ WaitForTabToLoad(); ++ EXPECT_EQ(2, browser()->tab_strip_model()->count()); ++} ++ ++// Make sure that we correctly recognize and apply blocking of ++// redirected popups only for real popups. ++IN_PROC_BROWSER_TEST_P(AdblockPopupBrowserTest, ++ LinkOpenedByContextMenuInNewTabNotBlocked) { ++ SetFilters({"popup_redirected.html^$popup"}); ++ ContextMenuNotificationObserver menu_observer( ++ IDC_CONTENT_CONTEXT_OPENLINKNEWTAB); ++ ui_test_utils::AllBrowserTabAddedWaiter add_tab; ++ ++ std::string script = base::StringPrintf( ++ "data:text/html,link", ++ GetPageUrl("/popup_will_redirect.html").spec().c_str()); ++ // Go to a page with a link ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(script))); ++ ++ // Opens a link in a new tab via a "real" context menu. ++ blink::WebMouseEvent mouse_event( ++ blink::WebInputEvent::Type::kMouseDown, ++ blink::WebInputEvent::kNoModifiers, ++ blink::WebInputEvent::GetStaticTimeStampForTests()); ++ mouse_event.button = blink::WebMouseEvent::Button::kRight; ++ mouse_event.SetPositionInWidget(15, 15); ++ content::WebContents* tab = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ gfx::Rect offset = tab->GetContainerBounds(); ++ mouse_event.SetPositionInScreen(15 + offset.x(), 15 + offset.y()); ++ mouse_event.click_count = 1; ++ tab->GetPrimaryMainFrame() ++ ->GetRenderViewHost() ++ ->GetWidget() ++ ->ForwardMouseEvent(mouse_event); ++ mouse_event.SetType(blink::WebInputEvent::Type::kMouseUp); ++ tab->GetPrimaryMainFrame() ++ ->GetRenderViewHost() ++ ->GetWidget() ++ ->ForwardMouseEvent(mouse_event); ++ ++ // The menu_observer will select "Open in new tab", wait for the new tab to ++ // be added. ++ tab = add_tab.Wait(); ++ EXPECT_TRUE(content::WaitForLoadStop(tab)); ++ ++ // Verify that it's the correct tab. ++ EXPECT_EQ(GetPageUrl("/popup_redirected.html"), tab->GetLastCommittedURL()); ++} ++ ++INSTANTIATE_TEST_SUITE_P(All, ++ AdblockPopupBrowserTest, ++ testing::Values(Redirection::ClientSide, ++ Redirection::ServerSide)); ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc b/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_subscription_service_browsertest.cc +@@ -0,0 +1,204 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "base/files/file_util.h" ++#include "base/files/scoped_temp_dir.h" ++#include "base/ranges/algorithm.h" ++#include "base/run_loop.h" ++#include "base/strings/string_split.h" ++#include "base/test/bind.h" ++#include "base/threading/thread_restrictions.h" ++#include "base/time/time.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/subscription/subscription_config.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/version_info/version_info.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/http/http_request_headers.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++ ++namespace adblock { ++ ++class AdblockSubscriptionServiceBrowserTest ++ : public InProcessBrowserTest, ++ public SubscriptionService::SubscriptionObserver { ++ public: ++ AdblockSubscriptionServiceBrowserTest() { ++ SubscriptionServiceFactory::SetUpdateCheckAndDelayIntervalsForTesting( ++ base::Seconds(1), base::Seconds(1)); ++ } ++ void SetUpOnMainThread() override { ++ InProcessBrowserTest::SetUpOnMainThread(); ++ https_server_ = std::make_unique( ++ net::EmbeddedTestServer::TYPE_HTTPS); ++ https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK); ++ } ++ ++ bool RequestHeadersContainAcceptLanguage( ++ const net::test_server::HttpRequest& request) { ++ const auto accept_language_it = ++ request.headers.find(net::HttpRequestHeaders::kAcceptLanguage); ++ return accept_language_it != request.headers.end() && ++ !accept_language_it->second.empty(); ++ } ++ ++ bool RequestHeadersContainAcceptEncodingBrotli( ++ const net::test_server::HttpRequest& request) { ++ const auto accept_encoding_it = ++ request.headers.find(net::HttpRequestHeaders::kAcceptEncoding); ++ if (accept_encoding_it == request.headers.end()) { ++ return false; ++ } ++ const auto split_encodings = ++ base::SplitString(accept_encoding_it->second, ",", ++ base::WhitespaceHandling::TRIM_WHITESPACE, ++ base::SplitResult::SPLIT_WANT_NONEMPTY); ++ return base::ranges::find(split_encodings, "br") != split_encodings.end(); ++ } ++ ++ std::unique_ptr ++ HandleSubscriptionUpdateRequestWithUrlCheck( ++ std::string expected_url_part, ++ const net::test_server::HttpRequest& request) { ++ static const char kSubscriptionHeader[] = ++ "[Adblock Plus 2.0]\n" ++ "! Checksum: X5A8vtJDBW2a9EgS9glqbg\n" ++ "! Version: 202202061935\n" ++ "! Last modified: 06 Feb 2022 19:35 UTC\n" ++ "! Expires: 1 days (update frequency)\n\n"; ++ if (base::StartsWith(request.relative_url, kSubscription, ++ base::CompareCase::SENSITIVE) && ++ !request_already_handled_) { ++ request_already_handled_ = true; ++ EXPECT_TRUE(RequestHeadersContainAcceptLanguage(request)); ++ EXPECT_TRUE(RequestHeadersContainAcceptEncodingBrotli(request)); ++ std::string os; ++ base::ReplaceChars(version_info::GetOSType(), base::kWhitespaceASCII, "", ++ &os); ++ EXPECT_TRUE(request.relative_url.find(expected_url_part) != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("addonName=eyeo-chromium-sdk") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("addonVersion=1.0") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("platformVersion=1.0") != ++ std::string::npos); ++ EXPECT_TRUE(request.relative_url.find("platform=" + os) != ++ std::string::npos); ++ auto http_response = ++ std::make_unique(); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(kSubscriptionHeader); ++ http_response->set_content_type("text/plain"); ++ return std::move(http_response); ++ } ++ ++ // Unhandled requests result in the Embedded test server sending a 404. ++ return nullptr; ++ } ++ ++ void ExpectFilterListRequestMadeWithLastVersion(std::string last_version) { ++ https_server_->RegisterRequestHandler( ++ base::BindRepeating(&AdblockSubscriptionServiceBrowserTest:: ++ HandleSubscriptionUpdateRequestWithUrlCheck, ++ base::Unretained(this), last_version)); ++ ASSERT_TRUE(https_server_->Start(kPort)); ++ } ++ ++ // adblock::SubscriptionService::SubscriptionObserver ++ void OnSubscriptionInstalled(const GURL& url) override { ++ if (base::StartsWith(url.spec(), ++ https_server_->GetURL(kSubscription).spec())) { ++ // In order to ensure next run requests an update, mark the subscription ++ // as almost expired. ++ SubscriptionPersistentMetadataFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->SetExpirationInterval(url, base::Milliseconds(1)); ++ CloseBrowserAsynchronously(browser()); ++ } ++ } ++ ++ std::unique_ptr https_server_; ++ bool request_already_handled_ = false; ++ static const std::string kSubscription; ++ // Port is hardcoded so the server url is the same across tests ++ static const int kPort = 65432; ++}; ++ ++const std::string AdblockSubscriptionServiceBrowserTest::kSubscription = ++ "/subscription.txt"; ++ ++IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, PRE_LastVersion) { ++ ExpectFilterListRequestMadeWithLastVersion("&lastVersion=0&"); ++ // Downloading a filter list and setting its expiry time to almost zero, so ++ // the next run will have to update it ASAP. ++ ++ auto* subscription_service = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()); ++ subscription_service->AddObserver(this); ++ // Using a custom subscription URL here because before test sets ++ // up the server then SubscriptionService already started fetching default ++ // subscriptions. ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->InstallSubscription(https_server_->GetURL(kSubscription)); ++ // Wait until subscription is downloaded and stored. ++ RunUntilBrowserProcessQuits(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, LastVersion) { ++ ExpectFilterListRequestMadeWithLastVersion("&lastVersion=202202061935&"); ++ auto* subscription_service = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()); ++ subscription_service->AddObserver(this); ++ // Wait for subscription update to trigger a network request. ++ RunUntilBrowserProcessQuits(); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockSubscriptionServiceBrowserTest, ++ FilterFileDeletedAfterConversion) { ++ base::ScopedAllowBlockingForTesting allow_blocking; ++ ConversionExecutors* conversion_executors = ++ SubscriptionServiceFactory::GetInstance(); ++ DCHECK(conversion_executors); ++ base::ScopedTempDir temp_dir; ++ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ++ const auto filter_list_path = temp_dir.GetPath().AppendASCII("easylist.txt"); ++ std::vector filter_list_contents = { ++ "[\"Adblock Plus 2.0\"]\n", "invalid file"}; ++ for (const auto& file_content : filter_list_contents) { ++ base::WriteFile(filter_list_path, file_content); ++ ASSERT_TRUE(base::PathExists(filter_list_path)); ++ base::RunLoop run_loop; ++ conversion_executors->ConvertFilterListFile( ++ DefaultSubscriptionUrl(), filter_list_path, ++ base::BindLambdaForTesting( ++ [&run_loop](ConversionResult result) { run_loop.Quit(); })); ++ run_loop.Run(); ++ ASSERT_FALSE(base::PathExists(filter_list_path)); ++ } ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc b/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_telemetry_service_browsertest.cc +@@ -0,0 +1,256 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include "base/json/json_reader.h" ++#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "components/adblock/core/activeping_telemetry_topic_provider.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++ ++namespace adblock { ++ ++class AdblockTelemetryServiceBrowserTestBase : public InProcessBrowserTest { ++ public: ++ // We need to set server and request handler asap ++ void SetUpInProcessBrowserTestFixture() override { ++ InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); ++ host_resolver()->AddRule( ++ ActivepingTelemetryTopicProvider::DefaultBaseUrl().host(), "127.0.0.1"); ++ http_server_.RegisterRequestHandler(base::BindRepeating( ++ &AdblockTelemetryServiceBrowserTestBase::RequestHandler, ++ base::Unretained(this))); ++ ASSERT_TRUE(http_server_.Start()); ++ ActivepingTelemetryTopicProvider::SetHttpPortForTesting( ++ http_server_.port()); ++ auto testing_interval = base::Seconds(2); ++ ActivepingTelemetryTopicProvider::SetIntervalsForTesting(testing_interval); ++ AdblockTelemetryServiceFactory::GetInstance() ++ ->SetCheckAndDelayIntervalsForTesting(testing_interval, ++ testing_interval); ++ } ++ ++ base::Value* GetFirstPing(absl::optional& parsed) { ++ return GetPayload(parsed)->Find("first_ping"); ++ } ++ ++ base::Value* GetLastPing(absl::optional& parsed) { ++ return GetPayload(parsed)->Find("last_ping"); ++ } ++ ++ base::Value* GetLastPingTag(absl::optional& parsed) { ++ return GetPayload(parsed)->Find("last_ping_tag"); ++ } ++ ++ base::Value* GetPreviousLastPing(absl::optional& parsed) { ++ return GetPayload(parsed)->Find("previous_last_ping"); ++ } ++ ++ void CloseBrowserFromAnyThread() { ++ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING}) ++ ->PostTask(FROM_HERE, ++ base::BindOnce(&AdblockTelemetryServiceBrowserTestBase:: ++ CloseBrowserAsynchronously, ++ base::Unretained(this), browser())); ++ } ++ ++ std::unique_ptr CreateResponse( ++ const std::string& token) { ++ auto http_response = ++ std::make_unique(); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content("{\"token\": \"" + token + "\"}"); ++ http_response->set_content_type("text/plain"); ++ return std::move(http_response); ++ } ++ ++ virtual std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) = 0; ++ ++ private: ++ base::Value::Dict* GetPayload(absl::optional& parsed) { ++ EXPECT_TRUE(parsed && parsed->is_dict()); ++ base::Value::Dict* parsed_dict = parsed->GetIfDict(); ++ EXPECT_TRUE(parsed_dict); ++ base::Value::Dict* payload = parsed_dict->FindDict("payload"); ++ EXPECT_TRUE(payload); ++ return payload; ++ } ++ ++ net::EmbeddedTestServer http_server_; ++}; ++ ++// Test three initial pings each after startup and each fails for the 1st time ++class AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest ++ : public AdblockTelemetryServiceBrowserTestBase { ++ public: ++ std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) override { ++ EXPECT_TRUE(base::StartsWith(request.relative_url, ++ "/topic/eyeochromium_activeping/version/1")); ++ EXPECT_TRUE(request.has_content); ++ absl::optional parsed = ++ base::JSONReader::Read(request.content); ++ base::Value* first_ping = GetFirstPing(parsed); ++ base::Value* last_ping = GetLastPing(parsed); ++ base::Value* previous_last_ping = GetPreviousLastPing(parsed); ++ ++ if (expected_first_ping_.empty()) { ++ EXPECT_FALSE(first_ping); ++ } else { ++ EXPECT_EQ(expected_first_ping_, *first_ping); ++ } ++ ++ if (expected_last_ping_.empty()) { ++ EXPECT_FALSE(last_ping); ++ } else { ++ EXPECT_EQ(expected_last_ping_, *last_ping); ++ } ++ ++ if (expected_previous_last_ping_.empty()) { ++ EXPECT_FALSE(previous_last_ping); ++ } else { ++ EXPECT_EQ(expected_previous_last_ping_, *previous_last_ping); ++ } ++ ++ if (!attempt_++) { ++ // Force retry by 404 response but 1st save last_ping_tag if any ++ base::Value* last_ping_tag = GetLastPingTag(parsed); ++ if (last_ping_tag) { ++ previous_last_ping_tag_ = last_ping_tag->GetString(); ++ } ++ return nullptr; ++ } ++ ++ // Verifies that retried ping has the same last_ping_tag ++ if (!previous_last_ping_tag_.empty()) { ++ base::Value* last_ping_tag = GetLastPingTag(parsed); ++ EXPECT_EQ(previous_last_ping_tag_, *last_ping_tag); ++ } ++ ++ // If we get expected telemetry ping with retry we simply finish the test ++ // by closing the browser, otherwise test will fail with a timeout. ++ CloseBrowserFromAnyThread(); ++ ++ // This will be still processed before CloseBrowserFromAnyThread() applies ++ return CreateResponse(server_response_); ++ } ++ ++ void TearDownInProcessBrowserTestFixture() override { ++ // Make sure we called RequestHandler exactly twice: 1st ping failed, 2nd ++ // was successful ++ EXPECT_EQ(2, attempt_); ++ } ++ ++ protected: ++ std::string server_response_; ++ std::string expected_first_ping_; ++ std::string expected_last_ping_; ++ std::string expected_previous_last_ping_; ++ ++ private: ++ int attempt_ = 0; ++ std::string previous_last_ping_tag_ = ""; ++}; ++ ++IN_PROC_BROWSER_TEST_F( ++ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, ++ PRE_PRE_TestPing) { ++ // Sets the ping to be returned by the server and checked in the next test ++ server_response_ = "11111"; ++ RunUntilBrowserProcessQuits(); ++} ++ ++IN_PROC_BROWSER_TEST_F( ++ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, ++ PRE_TestPing) { ++ // Sets the ping to be returned by the server and checked in the next test ++ server_response_ = "22222"; ++ expected_first_ping_ = expected_last_ping_ = "11111"; ++ RunUntilBrowserProcessQuits(); ++} ++ ++IN_PROC_BROWSER_TEST_F( ++ AdblockTelemetryServiceFirstPingAfterRestartWithRetryBrowserTest, ++ TestPing) { ++ expected_first_ping_ = "11111"; ++ expected_last_ping_ = "22222"; ++ expected_previous_last_ping_ = "11111"; ++ RunUntilBrowserProcessQuits(); ++} ++ ++// Test three inital pings ++class AdblockTelemetryServiceSubsequentPingsBrowserTest ++ : public AdblockTelemetryServiceBrowserTestBase { ++ public: ++ std::unique_ptr RequestHandler( ++ const net::test_server::HttpRequest& request) override { ++ EXPECT_TRUE(base::StartsWith(request.relative_url, ++ "/topic/eyeochromium_activeping/version/1")); ++ EXPECT_TRUE(request.has_content); ++ absl::optional parsed = ++ base::JSONReader::Read(request.content); ++ base::Value* first_ping = GetFirstPing(parsed); ++ base::Value* last_ping = GetLastPing(parsed); ++ base::Value* previous_last_ping = GetPreviousLastPing(parsed); ++ ++ if (count_ == 1) { ++ // No ping payload in the very 1st ping ++ EXPECT_FALSE(first_ping); ++ EXPECT_FALSE(last_ping); ++ } else if (count_ == 2) { ++ // For 2nd ping `first_ping` == `last_ping` ++ EXPECT_EQ(first_ping_, *first_ping); ++ EXPECT_EQ(first_ping_, *last_ping); ++ } else if (count_ == 3) { ++ // From 3rd ping onward `first_ping` != `last_ping` and we also get ++ // `previous_last_ping` ++ EXPECT_EQ(first_ping_, *first_ping); ++ EXPECT_EQ(second_ping_, *last_ping); ++ EXPECT_EQ(first_ping_, *previous_last_ping); ++ } ++ ++ // If we get three expected telemetry pings we simply finish the test by ++ // closing the browser, otherwise test will fail with a timeout. ++ if (count_ == 3) { ++ CloseBrowserFromAnyThread(); ++ return nullptr; ++ } ++ return CreateResponse(count_++ == 1 ? first_ping_ : second_ping_); ++ } ++ ++ void TearDownInProcessBrowserTestFixture() override { ++ // Make sure we called RequestHandler exactly three times ++ EXPECT_EQ(3, count_); ++ } ++ ++ private: ++ const std::string first_ping_ = "11111"; ++ const std::string second_ping_ = "22222"; ++ int count_ = 1; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockTelemetryServiceSubsequentPingsBrowserTest, ++ TestPing) { ++ RunUntilBrowserProcessQuits(); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc b/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/test/adblock_web_bundle_browsertest.cc +@@ -0,0 +1,426 @@ ++/* ++ * This file is part of eyeo Chromium SDK, ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ * ++ * eyeo Chromium SDK is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with eyeo Chromium SDK. If not, see . ++ */ ++ ++#include ++#include ++#include "base/files/file_path.h" ++#include "base/files/file_util.h" ++#include "base/files/scoped_temp_dir.h" ++#include "base/functional/bind.h" ++#include "base/path_service.h" ++#include "base/strings/string_util.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/web_package/web_bundle_builder.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "net/test/embedded_test_server/request_handler_util.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace adblock { ++ ++class AdblockWebBundleBrowserTest ++ : public InProcessBrowserTest, ++ public ResourceClassificationRunner::Observer { ++ public: ++ void SetUpOnMainThread() override { ++ InProcessBrowserTest::SetUpOnMainThread(); ++ host_resolver()->AddRule("*", "127.0.0.1"); ++ embedded_test_server()->RegisterDefaultHandler( ++ base::BindRepeating(&AdblockWebBundleBrowserTest::HandleFileRequest, ++ base::Unretained(this))); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ PrepareTempDirWithContent(); ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->AddObserver(this); ++ } ++ ++ void TearDownOnMainThread() override { ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->RemoveObserver(this); ++ InProcessBrowserTest::TearDownOnMainThread(); ++ } ++ ++ void PrepareTempDirWithContent() { ++ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); ++ CreateIndexFile(); ++ CreateByResourceWebBundle(); ++ CreateByBundleFileWebBundle(); ++ CreateByScopeFileWebBundle(); ++ } ++ ++ std::string GetFileContentFromTestDir( ++ base::FilePath::StringType relative_path) { ++ base::FilePath root; ++ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root)); ++ root = root.AppendASCII("chrome/test/data/adblock/wbn"); ++ std::string content; ++ CHECK(base::ReadFileToString(root.Append(relative_path), &content)); ++ return content; ++ } ++ ++ // In order for an html file to use absolute URLs in 'src' attributes to ++ // resources hosted by the embedded_test_server(), we need to replace ++ // {{{baseUrl}}} with the server's URL. It changes for every run. ++ std::string GetHtmlContentWithReplacements( ++ base::FilePath::StringType relative_path) { ++ std::string content = GetFileContentFromTestDir(relative_path); ++ base::ReplaceSubstringsAfterOffset( ++ &content, 0, "{{{baseUrl}}}", ++ embedded_test_server()->GetURL("example.org", "/").spec()); ++ return content; ++ } ++ ++ void CreateByResourceWebBundle() { ++ web_package::WebBundleBuilder builder; ++ builder.AddExchange("by_resource/blue_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/blue_subresource_loading.css"))); ++ builder.AddExchange("by_resource/blue_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/blue_subresource_loading.png"))); ++ builder.AddExchange("by_resource/red_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/red_subresource_loading.css"))); ++ builder.AddExchange("by_resource/red_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/red_subresource_loading.png"))); ++ builder.AddExchange( ++ "by_resource/xhr_result_1_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/xhr_result_1_subresource_loading.json"))); ++ builder.AddExchange( ++ "by_resource/fetch_result_1_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_resource/fetch_result_1_subresource_loading.json"))); ++ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); ++ const auto binary_data = builder.CreateBundle(); ++ ASSERT_TRUE(base::WriteFile( ++ temp_dir_.GetPath().AppendASCII("by_resource.wbn"), binary_data)); ++ } ++ ++ void CreateByBundleFileWebBundle() { ++ web_package::WebBundleBuilder builder; ++ builder.AddExchange("by_bundle_file/green_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/green_subresource_loading.css"))); ++ builder.AddExchange("by_bundle_file/green_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/green_subresource_loading.png"))); ++ builder.AddExchange("by_bundle_file/purple_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/purple_subresource_loading.css"))); ++ builder.AddExchange("by_bundle_file/purple_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/purple_subresource_loading.png"))); ++ builder.AddExchange( ++ "by_bundle_file/xhr_result_2_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/xhr_result_2_subresource_loading.json"))); ++ builder.AddExchange( ++ "by_bundle_file/fetch_result_2_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_bundle_file/fetch_result_2_subresource_loading.json"))); ++ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); ++ const auto binary_data = builder.CreateBundle(); ++ ASSERT_TRUE(base::WriteFile( ++ temp_dir_.GetPath().AppendASCII("by_bundle_file.wbn"), binary_data)); ++ } ++ ++ void CreateByScopeFileWebBundle() { ++ web_package::WebBundleBuilder builder; ++ builder.AddExchange("by_scope/orange_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/orange_subresource_loading.css"))); ++ builder.AddExchange("by_scope/orange_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/orange_subresource_loading.png"))); ++ builder.AddExchange("by_scope/pink_subresource_loading.css", ++ {{":status", "200"}, {"content-type", "text/css"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/pink_subresource_loading.css"))); ++ builder.AddExchange("by_scope/pink_subresource_loading.png", ++ {{":status", "200"}, {"content-type", "image/png"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/pink_subresource_loading.png"))); ++ builder.AddExchange( ++ "by_scope/xhr_result_3_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/xhr_result_3_subresource_loading.json"))); ++ builder.AddExchange( ++ "by_scope/fetch_result_3_subresource_loading.json", ++ {{":status", "200"}, {"content-type", "application/json"}}, ++ GetFileContentFromTestDir(FILE_PATH_LITERAL( ++ "by_scope/fetch_result_3_subresource_loading.json"))); ++ builder.AddPrimaryURL(embedded_test_server()->GetURL("example.org", "/")); ++ const auto binary_data = builder.CreateBundle(); ++ ASSERT_TRUE(base::WriteFile(temp_dir_.GetPath().AppendASCII("by_scope.wbn"), ++ binary_data)); ++ } ++ ++ void CreateIndexFile() { ++ const auto html = GetHtmlContentWithReplacements( ++ FILE_PATH_LITERAL("index.html.mustache")); ++ ASSERT_TRUE( ++ base::WriteFile(temp_dir_.GetPath().AppendASCII("index.html"), html)); ++ } ++ ++ std::unique_ptr HandleFileRequest( ++ const net::test_server::HttpRequest& request) { ++ auto response = ++ net::test_server::HandleFileRequest(temp_dir_.GetPath(), request); ++ if (response) { ++ auto* basic = ++ static_cast(response.get()); ++ if (temp_dir_.GetPath() ++ .AppendASCII(request.GetURL().path().substr(1)) ++ .MatchesExtension(FILE_PATH_LITERAL(".wbn"))) { ++ basic->set_content_type("application/webbundle"); ++ } ++ basic->AddCustomHeader("X-Content-Type-Options", "nosniff"); ++ basic->AddCustomHeader("Access-Control-Allow-Origin", "*"); ++ } ++ return response; ++ } ++ ++ GURL GetUrl() { ++ return embedded_test_server()->GetURL("example.org", "/index.html"); ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* controller = ++ AdblockControllerFactory::GetForBrowserContext(browser()->profile()); ++ controller->RemoveCustomFilter(kAllowlistEverythingFilter); ++ for (auto& filter : filters) { ++ controller->AddCustomFilter(filter); ++ } ++ } ++ ++ bool EvaluateJs(std::string value) { ++ return content::EvalJs(browser() ++ ->tab_strip_model() ++ ->GetActiveWebContents() ++ ->GetPrimaryMainFrame(), ++ value) ++ .ExtractBool(); ++ } ++ ++ bool IsImageLoaded(std::string selector) { ++ return EvaluateJs( ++ "(function(){ node = document.querySelector('" + selector + ++ "'); return node.complete && node.naturalHeight !== 0; })()"); ++ } ++ ++ bool IsCssBlocked(std::string selector) { ++ // On the test page, a box with this |id| is grey if element-specific CSS ++ // was blocked. Grey is the default color for divs, and gets overridden ++ // to element-specific colors by blockable CSS files. ++ return EvaluateJs( ++ "(function(){ return " ++ "window.getComputedStyle(document.querySelector('" + ++ selector + "')).backgroundColor == 'rgb(128, 128, 128)'; })()"); ++ } ++ ++ // Waits until the textContent of the selected item stops being "Pending" and ++ // returns whatever it's final value is. ++ // This asynchronous wait is because scripts that change the textContent may ++ // execute with a delay. ++ std::string GetSelectorTextContent(std::string selector) { ++ return content::EvalJs(browser() ++ ->tab_strip_model() ++ ->GetActiveWebContents() ++ ->GetPrimaryMainFrame(), ++ R"( ++ (async function (selector) { ++ return new Promise(resolve => { ++ if (!document.querySelector(selector).textContent.includes('Pending')) { ++ return resolve(document.querySelector(selector).textContent); ++ } ++ ++ const observer = new MutationObserver(mutations => { ++ if (!document.querySelector(selector).textContent.includes('Pending')) { ++ resolve(document.querySelector(selector).textContent); ++ observer.disconnect(); ++ } ++ }); ++ ++ observer.observe(document.body, { ++ childList: true, ++ subtree: true ++ }); ++ }); ++})(' )" + selector + "');") ++ .ExtractString(); ++ } ++ ++ bool IsXhrOrFetchRequestBlocked(std::string selector) { ++ return GetSelectorTextContent(selector).find("Error") != std::string::npos; ++ } ++ ++ bool IsXhrOrFetchRequestAllowed(std::string selector) { ++ return GetSelectorTextContent(selector).find("succeeded") != ++ std::string::npos; ++ } ++ ++ // ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ if (match_result == FilterMatchResult::kBlockRule) { ++ blocked_ads_notifications_.push_back(url); ++ } ++ } ++ ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ void OnPopupMatched(const GURL& url, ++ FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription, ++ const std::string& configuration_name) override {} ++ ++ base::ScopedTempDir temp_dir_; ++ std::vector blocked_ads_notifications_; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockImageByResource) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ const auto* blocked_image_selector = ++ R"(img[src="by_resource/blue_subresource_loading.png"])"; ++ const auto* other_image_selector = ++ R"(img[src="by_resource/red_subresource_loading.png"])"; ++ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_TRUE(IsImageLoaded(other_image_selector)); ++ SetFilters({"/blue_subresource_loading.png"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_TRUE(IsImageLoaded(other_image_selector)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockCssByResource) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_FALSE(IsCssBlocked("div.blue")); ++ SetFilters({"blue_subresource_loading.css"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_TRUE(IsCssBlocked("div.blue")); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockXhrByResource) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ const auto* blocked_selector = "code#xhr_result_by_resource"; ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed(blocked_selector)); ++ SetFilters({"/xhr_result_1_subresource_loading.json"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_TRUE(IsXhrOrFetchRequestBlocked(blocked_selector)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockFetchByResource) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ const auto* blocked_selector = "code#fetch_result_by_resource"; ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed(blocked_selector)); ++ SetFilters({"/fetch_result_1_subresource_loading.json"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_TRUE(IsXhrOrFetchRequestBlocked(blocked_selector)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockByBundle) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ const auto* blocked_image_selector = ++ R"(img[src="by_bundle_file/green_subresource_loading.png"])"; ++ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_FALSE(IsCssBlocked("div.green")); ++ EXPECT_FALSE(IsCssBlocked("div.purple")); ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#xhr_result_by_bundle_file")); ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#fetch_result_by_bundle_file")); ++ ++ SetFilters({"by_bundle_file.wbn$webbundle"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_TRUE(IsCssBlocked("div.green")); ++ EXPECT_TRUE(IsCssBlocked("div.purple")); ++ EXPECT_THAT(blocked_ads_notifications_, ++ testing::Contains(embedded_test_server()->GetURL( ++ "example.org", "/by_bundle_file.wbn"))); ++ // FIXME the following two expectations fail because the state of the requests ++ // is "pending" rather than allowed or blocked: DPD-1887 ++ // EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#xhr_result_by_bundle_file")); ++ // EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#fetch_result_by_bundle_file")); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockWebBundleBrowserTest, BlockByScope) { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ const auto* blocked_image_selector = ++ R"(img[src="by_scope/orange_subresource_loading.png"])"; ++ EXPECT_TRUE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_FALSE(IsCssBlocked("div.orange")); ++ EXPECT_FALSE(IsCssBlocked("div.pink")); ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#xhr_result_by_scope")); ++ EXPECT_TRUE(IsXhrOrFetchRequestAllowed("code#fetch_result_by_scope")); ++ ++ SetFilters({"by_scope/"}); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl())); ++ EXPECT_FALSE(IsImageLoaded(blocked_image_selector)); ++ EXPECT_TRUE(IsCssBlocked("div.orange")); ++ EXPECT_TRUE(IsCssBlocked("div.pink")); ++ EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#xhr_result_by_scope")); ++ EXPECT_TRUE(IsXhrOrFetchRequestBlocked("code#fetch_result_by_scope")); ++} ++ ++// TODO: ++// - Mixed origins ++// - Signed bundles. including case of navigation between signed and unsigned ++// content. ++// - If you block the whole bundle, all resources requests to components ++// declared in ++ ++ ++ ++ ++ ++ ++ ++
++ ++

++
++
++
+diff --git a/chrome/browser/resources/adblock_internals/adblock_internals.ts b/chrome/browser/resources/adblock_internals/adblock_internals.ts
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/resources/adblock_internals/adblock_internals.ts
+@@ -0,0 +1,43 @@
++// This file is part of eyeo Chromium SDK,
++// Copyright (C) 2006-present eyeo GmbH
++//
++// eyeo Chromium SDK is free software: you can redistribute it and/or modify
++// it under the terms of the GNU General Public License version 3 as
++// published by the Free Software Foundation.
++//
++// eyeo Chromium SDK is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++//
++// You should have received a copy of the GNU General Public License
++// along with eyeo Chromium SDK.  If not, see .
++
++import {getRequiredElement} from 'chrome://resources/js/util_ts.js';
++import {AdblockInternalsPageHandler} from './adblock_internals.mojom-webui.js';
++
++async function debugInfo(): Promise {
++  const info = await AdblockInternalsPageHandler.getRemote().getDebugInfo();
++  return info.debugInfo;
++}
++
++async function refresh() {
++  getRequiredElement('content').innerText = await debugInfo();
++}
++
++getRequiredElement('copy-button').addEventListener('click', async () => {
++  navigator.clipboard.writeText(await debugInfo());
++});
++
++getRequiredElement('download-button').addEventListener('click', async () => {
++  const url = URL.createObjectURL(new Blob([await debugInfo()], {type: 'text/plain'}));
++  const a = document.createElement('a');
++  a.href = url;
++  a.download = 'adblock-internals.txt';
++  a.click();
++  URL.revokeObjectURL(url);
++});
++
++getRequiredElement('refresh').addEventListener('click', refresh);
++
++document.addEventListener('DOMContentLoaded', refresh);
+diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
++++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+@@ -5,6 +5,10 @@
+ // This test creates a fake safebrowsing service, where we can inject known-
+ // threat urls.  It then uses a real browser to go to these urls, and sends
+ // "goback" or "proceed" commands and verifies they work.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include 
+ #include 
+@@ -60,6 +64,7 @@
+ #include "chrome/common/url_constants.h"
+ #include "chrome/test/base/in_process_browser_test.h"
+ #include "chrome/test/base/ui_test_utils.h"
++#include "components/adblock/core/features.h"
+ #include "components/google/core/common/google_util.h"
+ #include "components/omnibox/browser/omnibox_prefs.h"
+ #include "components/page_info/core/features.h"
+@@ -579,7 +584,8 @@ class SafeBrowsingBlockingPageBrowserTest
+         {kTagAndAttributeParamName, "div,foo,div,baz"}};
+     base::test::FeatureRefAndParams tag_and_attribute(
+         safe_browsing::kThreatDomDetailsTagAndAttributeFeature, parameters);
+-    scoped_feature_list_.InitWithFeaturesAndParameters({tag_and_attribute}, {});
++    scoped_feature_list_.InitWithFeaturesAndParameters(
++        {tag_and_attribute}, {adblock::kAdblockPlusFeature});
+   }
+ 
+   SafeBrowsingBlockingPageBrowserTest(
+diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
+--- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
++++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
+@@ -1,6 +1,10 @@
+ // Copyright 2017 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
+ 
+@@ -22,6 +26,7 @@
+ #include "chrome/common/chrome_features.h"
+ #include "chrome/common/chrome_paths.h"
+ #include "chrome/test/base/chrome_test_utils.h"
++#include "components/adblock/core/features.h"
+ #include "components/blocked_content/safe_browsing_triggered_popup_blocker.h"
+ #include "components/content_settings/browser/page_specific_content_settings.h"
+ #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h"
+@@ -71,7 +76,8 @@ MockSubresourceFilterObserver::~MockSubresourceFilterObserver() = default;
+ SubresourceFilterBrowserTest::SubresourceFilterBrowserTest() {
+   scoped_feature_list_.InitWithFeatures(
+       /*enabled_features=*/{kAdTagging},
+-      /*disabled_features=*/{features::kHttpsUpgrades});
++      /*disabled_features=*/{features::kHttpsUpgrades,
++                             adblock::kAdblockPlusFeature});
+ }
+ 
+ SubresourceFilterBrowserTest::~SubresourceFilterBrowserTest() = default;
+diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
+--- a/chrome/browser/ui/BUILD.gn
++++ b/chrome/browser/ui/BUILD.gn
+@@ -1,6 +1,10 @@
+ # Copyright 2014 The Chromium Authors
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
++#
++# This source code is a part of eyeo Chromium SDK.
++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file.
++
+ 
+ import("//build/config/buildflags_paint_preview.gni")
+ import("//build/config/chromebox_for_meetings/buildflags.gni")
+@@ -233,6 +237,10 @@ static_library("ui") {
+     "webid/identity_dialog_controller.h",
+     "webui/about_ui.cc",
+     "webui/about_ui.h",
++    "webui/adblock_internals/adblock_internals_page_handler_impl.cc",
++    "webui/adblock_internals/adblock_internals_page_handler_impl.h",
++    "webui/adblock_internals/adblock_internals_ui.cc",
++    "webui/adblock_internals/adblock_internals_ui.h",
+     "webui/autofill_and_password_manager_internals/autofill_internals_ui.cc",
+     "webui/autofill_and_password_manager_internals/autofill_internals_ui.h",
+     "webui/autofill_and_password_manager_internals/internals_ui_handler.cc",
+@@ -439,7 +447,11 @@ static_library("ui") {
+     "//chrome/browser/storage_access_api",
+     "//chrome/browser/ui/side_panel:side_panel_enums",
+     "//chrome/browser/ui/webui:configs",
++<<<<<<< HEAD
+     "//chrome/browser/ui/webui/location_internals:mojo_bindings",
++=======
++    "//chrome/browser/ui/webui/adblock_internals:mojo_bindings",
++>>>>>>> 9402d5c48c0e8... Squashed commits
+     "//chrome/browser/ui/webui/omnibox:mojo_bindings",
+     "//chrome/browser/ui/webui/segmentation_internals:mojo_bindings",
+     "//chrome/browser/ui/webui/suggest_internals:mojo_bindings",
+@@ -455,7 +467,11 @@ static_library("ui") {
+     "//components/about_ui",
+     "//components/access_code_cast/common:metrics",
+     "//components/account_id",
++<<<<<<< HEAD
+     "//components/autofill/content/browser",
++=======
++    "//components/adblock/content:browser",
++>>>>>>> 9402d5c48c0e8... Squashed commits
+     "//components/autofill/content/browser:risk_proto",
+     "//components/autofill/core/browser",
+     "//components/blocked_content",
+diff --git a/chrome/browser/ui/prefs/pref_watcher.cc b/chrome/browser/ui/prefs/pref_watcher.cc
+--- a/chrome/browser/ui/prefs/pref_watcher.cc
++++ b/chrome/browser/ui/prefs/pref_watcher.cc
+@@ -2,6 +2,10 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
++
+ #include "chrome/browser/ui/prefs/pref_watcher.h"
+ 
+ #include "base/functional/bind.h"
+@@ -12,6 +16,7 @@
+ #include "chrome/browser/renderer_preferences_util.h"
+ #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
+ #include "chrome/common/pref_names.h"
++#include "components/adblock/core/common/adblock_prefs.h"
+ #include "components/language/core/browser/pref_names.h"
+ #include "components/live_caption/pref_names.h"
+ #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
+@@ -64,6 +69,14 @@ const char* const kWebPrefsToObserve[] = {
+ #else
+     prefs::kAccessibilityFocusHighlightEnabled,
+ #endif
++
++    adblock::common::prefs::kAdblockAllowedDomainsLegacy,
++    adblock::common::prefs::kAdblockCustomFiltersLegacy,
++    adblock::common::prefs::kAdblockCustomSubscriptionsLegacy,
++    adblock::common::prefs::kAdblockSubscriptionsLegacy,
++    adblock::common::prefs::kEnableAcceptableAdsLegacy,
++    adblock::common::prefs::kEnableAdblockLegacy,
++
+ };
+ 
+ const int kWebPrefsToObserveLength = std::size(kWebPrefsToObserve);
+diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
+--- a/chrome/browser/ui/tab_helpers.cc
++++ b/chrome/browser/ui/tab_helpers.cc
+@@ -1,6 +1,10 @@
+ // Copyright 2014 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include "chrome/browser/ui/tab_helpers.h"
+ 
+@@ -13,7 +17,14 @@
+ #include "base/trace_event/trace_event.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++<<<<<<< HEAD
+ #include "chrome/browser/3pcd/heuristics/opener_heuristic_tab_helper.h"
++=======
++#include "chrome/browser/3pcd_heuristics/opener_heuristic_tab_helper.h"
++#include "chrome/browser/adblock/element_hider_factory.h"
++#include "chrome/browser/adblock/sitekey_storage_factory.h"
++#include "chrome/browser/adblock/subscription_service_factory.h"
++>>>>>>> 9402d5c48c0e8... Squashed commits
+ #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+ #include "chrome/browser/breadcrumbs/breadcrumb_manager_tab_helper.h"
+ #include "chrome/browser/browser_process.h"
+@@ -109,6 +120,7 @@
+ #include "chrome/common/chrome_features.h"
+ #include "chrome/common/chrome_isolated_world_ids.h"
+ #include "chrome/common/chrome_switches.h"
++#include "components/adblock/content/browser/adblock_webcontents_observer.h"
+ #include "components/autofill/content/browser/content_autofill_client.h"
+ #include "components/autofill/content/browser/content_autofill_driver_factory.h"
+ #include "components/autofill/core/browser/browser_autofill_manager.h"
+@@ -340,6 +352,16 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) {
+           web_contents, optimization_guide_decider, about_this_site_service);
+   }
+ #endif
++
++  AdblockWebContentObserver::CreateForWebContents(
++      web_contents,
++      adblock::SubscriptionServiceFactory::GetForBrowserContext(
++          web_contents->GetBrowserContext()),
++      adblock::ElementHiderFactory::GetForBrowserContext(
++          web_contents->GetBrowserContext()),
++      adblock::SitekeyStorageFactory::GetForBrowserContext(
++          web_contents->GetBrowserContext()),
++      std::make_unique());
+   autofill::ChromeAutofillClient::CreateForWebContents(web_contents);
+   if (breadcrumbs::IsEnabled())
+     BreadcrumbManagerTabHelper::CreateForWebContents(web_contents);
+diff --git a/chrome/browser/ui/webui/adblock_internals/BUILD.gn b/chrome/browser/ui/webui/adblock_internals/BUILD.gn
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/BUILD.gn
+@@ -0,0 +1,23 @@
++#
++# This file is part of eyeo Chromium SDK,
++# Copyright (C) 2006-present eyeo GmbH
++#
++# eyeo Chromium SDK is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License version 3 as
++# published by the Free Software Foundation.
++#
++# eyeo Chromium SDK is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with eyeo Chromium SDK.  If not, see .
++
++import("//mojo/public/tools/bindings/mojom.gni")
++
++mojom("mojo_bindings") {
++  sources = [ "adblock_internals.mojom" ]
++  webui_module_path = "/"
++  use_typescript_sources = true
++}
+diff --git a/chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom b/chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom
+@@ -0,0 +1,20 @@
++// This file is part of eyeo Chromium SDK,
++// Copyright (C) 2006-present eyeo GmbH
++//
++// eyeo Chromium SDK is free software: you can redistribute it and/or modify
++// it under the terms of the GNU General Public License version 3 as
++// published by the Free Software Foundation.
++//
++// eyeo Chromium SDK is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++//
++// You should have received a copy of the GNU General Public License
++// along with eyeo Chromium SDK.  If not, see .
++
++module mojom.adblock_internals;
++
++interface AdblockInternalsPageHandler {
++  GetDebugInfo() => (string debug_info);
++};
+diff --git a/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.cc b/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.cc
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.cc
+@@ -0,0 +1,97 @@
++/*
++ * This file is part of eyeo Chromium SDK,
++ * Copyright (C) 2006-present eyeo GmbH
++ *
++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * eyeo Chromium SDK is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with eyeo Chromium SDK.  If not, see .
++ */
++
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h"
++
++#include "base/time/time_to_iso8601.h"
++#include "chrome/browser/adblock/session_stats_factory.h"
++#include "chrome/browser/adblock/subscription_service_factory.h"
++#include "components/adblock/core/session_stats.h"
++#include "components/adblock/core/subscription/subscription_config.h"
++#include "components/adblock/core/subscription/subscription_service.h"
++
++namespace {
++
++std::string SubscriptionInstallationStateToString(
++    adblock::Subscription::InstallationState state) {
++  using State = adblock::Subscription::InstallationState;
++  switch (state) {
++    case State::Installed:
++      return "Installed";
++    case State::Installing:
++      return "Installing";
++    case State::Preloaded:
++      return "Preloaded";
++    case State::Unknown:
++      return "Unknown";
++  }
++  NOTREACHED();
++  return "";
++}
++
++std::string DebugLine(std::string name, std::string value, int level) {
++  return std::string(2 * level, ' ') + name + ": " + value + '\n';
++}
++
++std::string DebugLine(std::string name, int value, int level) {
++  return DebugLine(name, std::to_string(value), level);
++}
++
++}  // namespace
++
++AdblockInternalsPageHandlerImpl::AdblockInternalsPageHandlerImpl(
++    Profile* profile,
++    mojo::PendingReceiver
++        receiver)
++    : profile_(profile), receiver_(this, std::move(receiver)) {}
++
++AdblockInternalsPageHandlerImpl::~AdblockInternalsPageHandlerImpl() = default;
++
++void AdblockInternalsPageHandlerImpl::GetDebugInfo(
++    GetDebugInfoCallback callback) {
++  CHECK(profile_);
++  std::string result;
++  auto* service =
++      adblock::SubscriptionServiceFactory::GetForBrowserContext(profile_);
++  auto* stats = adblock::SessionStatsFactory::GetForBrowserContext(profile_);
++  auto allowed = stats->GetSessionAllowedAdsCount();
++  auto blocked = stats->GetSessionBlockedAdsCount();
++  for (auto* config : service->GetInstalledFilteringConfigurations()) {
++    result += DebugLine("Configuration", config->GetName(), 0);
++    result += DebugLine("Enabled", config->IsEnabled(), 1);
++    for (const auto& it : config->GetAllowedDomains()) {
++      result += DebugLine("Allowed domain", it, 1);
++    }
++    for (const auto& it : config->GetCustomFilters()) {
++      result += DebugLine("Custom filter", it, 1);
++    }
++    for (auto it : service->GetCurrentSubscriptions(config)) {
++      auto url = it->GetSourceUrl();
++      result += DebugLine("Subscription", url.spec(), 1);
++      result += DebugLine(
++          "State",
++          SubscriptionInstallationStateToString(it->GetInstallationState()), 2);
++      result += DebugLine("Title", it->GetTitle(), 2);
++      result += DebugLine("Version", it->GetCurrentVersion(), 2);
++      result += DebugLine("Last update",
++                          base::TimeToISO8601(it->GetInstallationTime()), 2);
++      result += DebugLine("Total allowed", allowed[url], 2);
++      result += DebugLine("Total blocked", blocked[url], 2);
++    }
++  }
++  std::move(callback).Run(std::move(result));
++}
+diff --git a/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h b/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h
+@@ -0,0 +1,47 @@
++/*
++ * This file is part of eyeo Chromium SDK,
++ * Copyright (C) 2006-present eyeo GmbH
++ *
++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * eyeo Chromium SDK is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with eyeo Chromium SDK.  If not, see .
++ */
++
++#ifndef CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_PAGE_HANDLER_IMPL_H_
++#define CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_PAGE_HANDLER_IMPL_H_
++
++#include "base/memory/raw_ptr.h"
++#include "chrome/browser/profiles/profile.h"
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom.h"
++#include "mojo/public/cpp/bindings/receiver.h"
++
++class AdblockInternalsPageHandlerImpl
++    : public mojom::adblock_internals::AdblockInternalsPageHandler {
++ public:
++  explicit AdblockInternalsPageHandlerImpl(
++      Profile* profile,
++      mojo::PendingReceiver<
++          mojom::adblock_internals::AdblockInternalsPageHandler> receiver);
++  AdblockInternalsPageHandlerImpl(const AdblockInternalsPageHandlerImpl&) =
++      delete;
++  AdblockInternalsPageHandlerImpl& operator=(
++      const AdblockInternalsPageHandlerImpl&) = delete;
++  ~AdblockInternalsPageHandlerImpl() override;
++
++  // mojom::adblock_internals::AdblockInternalsPageHandler:
++  void GetDebugInfo(GetDebugInfoCallback callback) override;
++
++ private:
++  raw_ptr profile_;
++  mojo::Receiver
++      receiver_;
++};
++#endif  // CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_PAGE_HANDLER_IMPL_H_
+diff --git a/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.cc b/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.cc
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.cc
+@@ -0,0 +1,47 @@
++/*                                                                            \
++ * This file is part of eyeo Chromium SDK,                                    \
++ * Copyright (C) 2006-present eyeo GmbH                                       \
++ *                                                                            \
++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify  \
++ * it under the terms of the GNU General Public License version 3 as          \
++ * published by the Free Software Foundation.                                 \
++ *                                                                            \
++ * eyeo Chromium SDK is distributed in the hope that it will be useful,       \
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of             \
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              \
++ * GNU General Public License for more details.                               \
++ *                                                                            \
++ * You should have received a copy of the GNU General Public License          \
++ * along with eyeo Chromium SDK.  If not, see . \
++ */
++
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h"
++
++#include "chrome/browser/profiles/profile.h"
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals_page_handler_impl.h"
++#include "chrome/browser/ui/webui/webui_util.h"
++#include "chrome/common/url_constants.h"
++#include "chrome/grit/adblock_internals_resources.h"
++#include "chrome/grit/adblock_internals_resources_map.h"
++#include "content/public/browser/web_ui_data_source.h"
++
++AdblockInternalsUI::AdblockInternalsUI(content::WebUI* web_ui)
++    : ui::MojoWebUIController(web_ui), profile_(Profile::FromWebUI(web_ui)) {
++  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
++      profile_, chrome::kChromeUIAdblockInternalsHost);
++  webui::SetupWebUIDataSource(source,
++                              base::make_span(kAdblockInternalsResources,
++                                              kAdblockInternalsResourcesSize),
++                              IDR_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_HTML);
++}
++
++AdblockInternalsUI::~AdblockInternalsUI() = default;
++
++WEB_UI_CONTROLLER_TYPE_IMPL(AdblockInternalsUI)
++
++void AdblockInternalsUI::BindInterface(
++    mojo::PendingReceiver
++        receiver) {
++  handler_ = std::make_unique(
++      profile_, std::move(receiver));
++}
+diff --git a/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h b/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h
+new file mode 100644
+--- /dev/null
++++ b/chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h
+@@ -0,0 +1,48 @@
++/*
++ * This file is part of eyeo Chromium SDK,
++ * Copyright (C) 2006-present eyeo GmbH
++ *
++ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * eyeo Chromium SDK is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with eyeo Chromium SDK.  If not, see .
++ */
++
++#ifndef CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_UI_H_
++#define CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_UI_H_
++
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals.mojom.h"
++#include "mojo/public/cpp/bindings/pending_receiver.h"
++#include "ui/webui/mojo_web_ui_controller.h"
++
++class Profile;
++
++class AdblockInternalsUI : public ui::MojoWebUIController {
++ public:
++  explicit AdblockInternalsUI(content::WebUI* web_ui);
++
++  AdblockInternalsUI(const AdblockInternalsUI&) = delete;
++  AdblockInternalsUI& operator=(const AdblockInternalsUI&) = delete;
++
++  ~AdblockInternalsUI() override;
++
++  void BindInterface(
++      mojo::PendingReceiver<
++          mojom::adblock_internals::AdblockInternalsPageHandler> receiver);
++
++ private:
++  WEB_UI_CONTROLLER_TYPE_DECL();
++
++  raw_ptr profile_;
++  std::unique_ptr
++      handler_;
++};
++
++#endif  // CHROME_BROWSER_UI_WEBUI_ADBLOCK_INTERNALS_ADBLOCK_INTERNALS_UI_H_
+diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
++++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+@@ -1,6 +1,10 @@
+ // Copyright 2012 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
+ 
+@@ -32,6 +36,7 @@
+ #include "chrome/browser/profiles/profile.h"
+ #include "chrome/browser/signin/signin_features.h"
+ #include "chrome/browser/ui/webui/about_ui.h"
++#include "chrome/browser/ui/webui/adblock_internals/adblock_internals_ui.h"
+ #include "chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h"
+ #include "chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h"
+ #include "chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.h"
+@@ -438,8 +443,12 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
+   // print dialog.
+   if (url.host_piece() == chrome::kChromeUIAccessibilityHost)
+     return &NewWebUI;
+-  if (url.host_piece() == chrome::kChromeUIAutofillInternalsHost)
++  if (url.host_piece() == chrome::kChromeUIAdblockInternalsHost) {
++    return &NewWebUI;
++  }
++  if (url.host_piece() == chrome::kChromeUIAutofillInternalsHost) {
+     return &NewWebUI;
++  }
+ 
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+   if (url.host_piece() == chrome::kChromeUIAppDisabledHost)
+diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
+--- a/chrome/common/BUILD.gn
++++ b/chrome/common/BUILD.gn
+@@ -1,6 +1,9 @@
+ # Copyright 2014 The Chromium Authors
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
++#
++# This source code is a part of eyeo Chromium SDK.
++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file.
+ 
+ import("//build/buildflag_header.gni")
+ import("//build/config/chrome_build.gni")
+diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
+--- a/chrome/common/webui_url_constants.cc
++++ b/chrome/common/webui_url_constants.cc
+@@ -1,6 +1,10 @@
+ // Copyright 2017 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include "chrome/common/webui_url_constants.h"
+ 
+@@ -32,6 +36,7 @@ const char kChromeUIAboutURL[] = "chrome://about/";
+ const char kChromeUIActivateSafetyCheckSettingsURL[] =
+     "chrome://settings/safetyCheck?activateSafetyCheck";
+ const char kChromeUIAccessibilityHost[] = "accessibility";
++const char kChromeUIAdblockInternalsHost[] = "adblock-internals";
+ const char kChromeUIAllSitesPath[] = "/content/all";
+ const char kChromeUIAppIconHost[] = "app-icon";
+ const char kChromeUIAppIconURL[] = "chrome://app-icon/";
+diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
+--- a/chrome/common/webui_url_constants.h
++++ b/chrome/common/webui_url_constants.h
+@@ -1,6 +1,10 @@
+ // Copyright 2017 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ // Contains constants for WebUI UI/Host/SubPage constants. Anything else go in
+ // chrome/common/url_constants.h.
+@@ -33,6 +37,7 @@ extern const char kChromeUIAboutHost[];
+ extern const char kChromeUIAboutURL[];
+ extern const char kChromeUIActivateSafetyCheckSettingsURL[];
+ extern const char kChromeUIAccessibilityHost[];
++extern const char kChromeUIAdblockInternalsHost[];
+ extern const char kChromeUIAllSitesPath[];
+ extern const char kChromeUIAppIconHost[];
+ extern const char kChromeUIAppIconURL[];
+diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
+--- a/chrome/test/BUILD.gn
++++ b/chrome/test/BUILD.gn
+@@ -1,6 +1,9 @@
+ # Copyright 2014 The Chromium Authors
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
++#
++# This source code is a part of eyeo Chromium SDK.
++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file.
+ 
+ import("//build/cipd/cipd.gni")
+ import("//build/config/buildflags_paint_preview.gni")
+@@ -24,6 +27,7 @@ import("//chrome/test/base/js2gtest.gni")
+ import("//chrome/test/include_js_tests.gni")
+ import("//chrome/version.gni")
+ import("//chromeos/ash/components/assistant/assistant.gni")
++import("//components/adblock/features.gni")
+ import("//components/captive_portal/core/features.gni")
+ import("//components/enterprise/buildflags/buildflags.gni")
+ import("//components/feed/features.gni")
+@@ -1135,6 +1139,7 @@ if (is_android) {
+ 
+     deps += [
+       ":persisted_tab_data_test_proto",
++      "//components/adblock/content:browser",
+       "//components/autofill/content/browser:test_support",
+       "//components/back_forward_cache:back_forward_cache",
+       "//components/browsing_data/core:core",
+@@ -1511,6 +1516,7 @@ if (!is_android) {
+       "//chrome/test/data/webui/mojo:mojo_bindings",
+       "//chrome/test/media_router/access_code_cast:access_code_cast_integration_base",
+       "//chrome/test/payments:test_support",
++      "//components/adblock/content:browser",
+       "//components/autofill/content/browser:risk_proto",
+       "//components/autofill/content/browser:test_support",
+       "//components/autofill/content/common/mojom",
+@@ -1836,6 +1842,7 @@ if (!is_android) {
+       "data/",
+       "//ash/components/arc/test/data/icons",
+       "//chrome/browser/page_load_metrics/integration_tests/data/",
++      "//chrome/test/data/adblock/",
+       "//chrome/test/data/cart/",
+       "//components/test/data/ad_tagging/",
+       "//components/test/data/ads_observer/",
+@@ -1928,6 +1935,16 @@ if (!is_android) {
+       "../browser/accessibility/image_annotation_browsertest.cc",
+       "../browser/accessibility/interstitial_accessibility_browsertest.cc",
+       "../browser/accessibility/page_colors_browsertest.cc",
++      "../browser/adblock/test/adblock_content_browser_client_browsertest.cc",
++      "../browser/adblock/test/adblock_filter_list_browsertest.cc",
++      "../browser/adblock/test/adblock_filtering_configurations_browsertest.cc",
++      "../browser/adblock/test/adblock_frame_hierarchy_builder_browsertest.cc",
++      "../browser/adblock/test/adblock_multiple_tabs_browsertest.cc",
++      "../browser/adblock/test/adblock_non_ascii_browsertest.cc",
++      "../browser/adblock/test/adblock_popup_browsertest.cc",
++      "../browser/adblock/test/adblock_subscription_service_browsertest.cc",
++      "../browser/adblock/test/adblock_telemetry_service_browsertest.cc",
++      "../browser/adblock/test/adblock_web_bundle_browsertest.cc",
+       "../browser/apps/guest_view/app_view_browsertest.cc",
+       "../browser/apps/guest_view/web_view_browsertest.cc",
+       "../browser/apps/platform_apps/app_browsertest.cc",
+@@ -2653,6 +2670,10 @@ if (!is_android) {
+       sources += [ "../browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc" ]
+     }
+ 
++    if (eyeo_intercept_debug_url) {
++      sources += [ "../browser/adblock/test/adblock_debug_url_browsertest.cc" ]
++    }
++
+     if (enable_reporting) {
+       sources += [ "../browser/net/reporting_browsertest.cc" ]
+     }
+@@ -3472,6 +3493,7 @@ if (!is_android) {
+         ]
+       }
+ 
++
+       if (is_chromeos_ash && enable_extensions) {
+         deps +=
+             [ "//chromeos/ash/components/network/portal_detector:test_support" ]
+@@ -5750,6 +5772,7 @@ test("unit_tests") {
+     # All unittests in browser, common, renderer and service.
+     "../browser/about_flags_unittest.cc",
+     "../browser/active_use_util_unittest.cc",
++    "../browser/adblock/adblock_content_browser_client_unittest.cc",
+     "../browser/after_startup_task_utils_unittest.cc",
+     "../browser/apps/icon_standardizer_unittest.cc",
+     "../browser/apps/user_type_filter_unittest.cc",
+@@ -6396,6 +6419,8 @@ test("unit_tests") {
+     "//chrome/services/file_util:unit_tests",
+     "//chrome/services/qrcode_generator/public/cpp",
+     "//components/account_id",
++    "//components/adblock/content/browser:test_support",
++    "//components/adblock/core:test_support",
+     "//components/assist_ranker/proto",
+     "//components/autofill/content/browser:test_support",
+     "//components/background_sync",
+@@ -9819,6 +9844,7 @@ if (!is_android) {
+ 
+     public_deps = [
+       "//chrome/browser:test_support_ui",
++      "//components/adblock/core:test_support",
+       "//content/public/browser",
+       "//content/test:test_support",
+       "//google_apis:test_support",
+diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
+--- a/chrome/test/base/chrome_test_launcher.cc
++++ b/chrome/test/base/chrome_test_launcher.cc
+@@ -1,6 +1,10 @@
+ // Copyright 2012 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
++//
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
+ 
+ #include "chrome/test/base/chrome_test_launcher.h"
+ 
+@@ -26,6 +30,7 @@
+ #include "base/time/time.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "chrome/browser/adblock/adblock_content_browser_client.h"
+ #include "chrome/browser/chrome_content_browser_client.h"
+ #include "chrome/browser/metrics/chrome_feature_list_creator.h"
+ #include "chrome/common/chrome_constants.h"
+@@ -154,7 +159,7 @@ ChromeTestLauncherDelegate::GetUserDataDirectoryCommandLineSwitch() {
+ // watch for long-running tasks and produce a useful timeout message in order to
+ // find the cause of flaky timeout tests.
+ class BrowserTestChromeContentBrowserClient
+-    : public ChromeContentBrowserClient {
++    : public AdblockContentBrowserClient {
+  public:
+   bool CreateThreadPool(base::StringPiece name) override {
+     base::test::TaskEnvironment::CreateThreadPool();
+diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
+--- a/chrome/test/base/in_process_browser_test.cc
++++ b/chrome/test/base/in_process_browser_test.cc
+@@ -2,6 +2,10 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
++// This source code is a part of eyeo Chromium SDK.
++// Use of this source code is governed by the GPLv3 that can be found in the
++// components/adblock/LICENSE file.
++
+ #include "chrome/test/base/in_process_browser_test.h"
+ 
+ #include 
+@@ -156,6 +160,10 @@
+ #include "content/public/test/network_connection_change_simulator.h"
+ #endif
+ 
++#include "chrome/browser/adblock/adblock_controller_factory.h"
++#include "components/adblock/core/adblock_controller.h"
++#include "components/adblock/core/common/adblock_constants.h"
++
+ namespace {
+ 
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+@@ -562,8 +570,15 @@ void InProcessBrowserTest::CreatedBrowserMainParts(
+ 
+ void InProcessBrowserTest::SelectFirstBrowser() {
+   const BrowserList* browser_list = BrowserList::GetInstance();
+-  if (!browser_list->empty())
++  if (!browser_list->empty()) {
+     browser_ = browser_list->get(0);
++    // Adding an allowing filter that overrides and disables all blocking
++    // filters in order to avoid unwanted interactions with simulated network
++    // loads. This custom filter is removed for tests that specifically verify
++    // ad-filtering.
++    adblock::AdblockControllerFactory::GetForBrowserContext(browser_->profile())
++        ->AddCustomFilter(adblock::kAllowlistEverythingFilter);
++  }
+ }
+ 
+ void InProcessBrowserTest::RecordPropertyFromMap(
+diff --git a/chrome/test/data/adblock/filterlist_that_allows_resource.txt b/chrome/test/data/adblock/filterlist_that_allows_resource.txt
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/filterlist_that_allows_resource.txt
+@@ -0,0 +1,7 @@
++  [Adblock Plus 2.0]
++! Version: 202212191158
++! Title: Allow resource.png
++! Expires: 1 days
++
++@@*resource.png
++#@##subresource
+diff --git a/chrome/test/data/adblock/filterlist_that_blocks_resource.txt b/chrome/test/data/adblock/filterlist_that_blocks_resource.txt
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/filterlist_that_blocks_resource.txt
+@@ -0,0 +1,6 @@
++ [Adblock Plus 2.0]
++! Version: 202212191158
++! Title: Block resource.png
++! Expires: 1 days
++
++*resource.png
+diff --git a/chrome/test/data/adblock/filterlist_that_hides_resource.txt b/chrome/test/data/adblock/filterlist_that_hides_resource.txt
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/filterlist_that_hides_resource.txt
+@@ -0,0 +1,6 @@
++ [Adblock Plus 2.0]
++! Version: 202212191158
++! Title: Hide resource.png
++! Expires: 1 days
++
++###subresource
+diff --git a/chrome/test/data/adblock/innermost_frame.html b/chrome/test/data/adblock/innermost_frame.html
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/innermost_frame.html
+@@ -0,0 +1,39 @@
++
++
++
++
++
++
++  
++
++
++
++  
++
++
++
+diff --git a/chrome/test/data/adblock/middle_frame.html b/chrome/test/data/adblock/middle_frame.html
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/middle_frame.html
+@@ -0,0 +1,25 @@
++
++
++
++
++
++
++  
++
++
++
+diff --git a/chrome/test/data/adblock/non-ascii.html b/chrome/test/data/adblock/non-ascii.html
+new file mode 100644
+--- /dev/null
++++ b/chrome/test/data/adblock/non-ascii.html
+@@ -0,0 +1,26 @@
++
++
++
++
++
++  
++
++
++    
Should be shidden
++ ++ +diff --git a/chrome/test/data/adblock/outermost_frame.html b/chrome/test/data/adblock/outermost_frame.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/outermost_frame.html +@@ -0,0 +1,37 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/outermost_frame_with_about_blank.html b/chrome/test/data/adblock/outermost_frame_with_about_blank.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/outermost_frame_with_about_blank.html +@@ -0,0 +1,37 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/popup.html b/chrome/test/data/adblock/popup.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/popup.html +@@ -0,0 +1,25 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/popup_opener.html b/chrome/test/data/adblock/popup_opener.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/popup_opener.html +@@ -0,0 +1,26 @@ ++ ++ ++ ++ ++ ++ ++ Trigger link based popup ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/popup_parent.html b/chrome/test/data/adblock/popup_parent.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/popup_parent.html +@@ -0,0 +1,25 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/resource.png b/chrome/test/data/adblock/resource.png +new file mode 100644 +index 0000000000000000000000000000000000000000..39f3630072b2677debf4aac66b20096852453a7f +GIT binary patch +literal 47293 +zcmeFZWl&z-k|>M?3&Ab8L(m6zcXxMp*Py}O-Q6u{aCevBP67cE9D>8Q$$QS3ckZ1# +z_nWG@|Au;~diGx3y?V8GFN$ylIq`S!IPhR#VDBU)M3lh5z?*?zGFWKfjc_SC2N)Pu +zg{O*!i;|%`k%N=HnWc>>k;_L1QzBCjOEWMqkJZTx^ZHCqw~!ZO3_XZBK@CKsWcTg8 +zhmXBpdnsR;Ps$IewUZAWo|W89=bq;T +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 +z*apMuKnvugUmYLvJi~U2+-j80_;uecizG( +zaA(gs_I&NP3p;L3vwcP|+oQNU)sRcG@;DY3O{iKqvifdq~+h|q-O=H$7>R(-_V-hURX+AeJ_MdnrA3xwjWyE*8E>_fGH0V5swObbhj +z9dz<(DMAE^j34Jo!krmb>Yk*uvV%?PiTPbD$2yY$WqUk!`V});4%SiFGTl@qT2?f! +z1e+k%lK_0#yYVY0e>?SL%wq0YnXm1ElqeNnDx=v6f)nypI8ju;ED&UeDc%~~^mL89 +z&t}Zsfqagy)8CwaGJ__(tVLk?CcL>8@7}^t^CzG4wCPi$wCZ3kOl>u&?-5zc+lE2LLLkE +zg(2%jtQGS0zT09%(`hIbf!a|xMM2@~9SOs}-A9}$G{lxb=F7lbD<}CL^ko@x`%PUA +zGnebBXv=wWwRIqL`VkfG6+#G-WNhH|0rt9|;Bb=b`E6WlK7+^b-8+;Lh=V22KlWaPGacuo<9uJhqwc6yknnqiW7`W5mGY67`KmO=Y$_U=Z{x2 +zso2s+K1Z|#DJxbF#ML3gkp*Uc@JgBu^5QlfCQfAY$44Ze(nY~Qs@+a4W+E9%J_<;n +z3OY+-g?HCOM$L3Y34I@Obnz9pUnE*jgeCyvmdrvXCra%r-zUk)xiKyA9%QD4Y%pc< +z5@;XA(q%Ev#l{@Swg46yJ=hR4x^452k7P2Vy3Mkp1u3JKyqVNhOLvVuMAcFjmWFp0 +zL@bB+P8kwQ$y#5j-&VAUDRd2SBO5DS!Rkh_k`SP;$&C@KzNBbw6-X=w*bTWNB4N*D +zXb?Jl!B6I4GjK~6-%=1Nyd69g1pSIi5faUttS==7AFLDE;skRs7#b`NOb*jT;1^h; +zLi4An{xV5Omt@%J<=Saw3Q5@9WQ2x8ZJGRry|`u%*$Vc}aP}F|^1S&ZEK-YlT$duR +zu?aLxIeDYdI=89S25I%#yRW?W#s&-V+hM9YD+78F@l}zD2(jco;_P`uicbBmqtCxF +zkx-*)g|k}O?GW+?+wEbgjm*H8n$xgN@QG`|IF;_91;>#;iKjH4h+c6ihms$x#r`(A +zKX-2-FH{GCW9lWlXM~L8)#6ElP5w^OCS2V~fDn`rARP&nB+8Q)d9#iT-#^R~#8({; +z7Mwqm!)sK6AH8_M5P?@LTN*fC=q`urXuQaciAoftOG<&C8LCfYV4-3LehC(V@r}q? +z=VnfdXZM97d@^s3Ikf*sahA& +zM>2vG#E)1_3f%8{N}&3V%Su1+^bNS+nGGJ0G0i6?2{>MGjw}k+Y`bbg5+&0>?9K?fLkd=E9_mgMpjqqR&ctafcO7hlw9RVpN3?Ro(l(T8}ohd-Mq!29K(E;a8*kW$=8KyB^55@ +zN-M-J4~1HY{jR<@bQ@~b{HRL1%zdC%TyJVt_`Og>?s&zVIyDWjbb)ZiJ-0IT$n>d_ +zMKBZ>L+P-ZN?rRrs1?{8OH(UrDDg3Tn!!AT60Vr8pcQ7Ev3WiRxdmuh&m~Z_G^*10 +zp#qERWR;;-W6n4ZdAc274)*lMYE5{8D<%`**Dp?H+L#7tu@5IHi{ +z$-&fHS&85RaTH6*O!Na!4MfvK=37KFYajIJ2&_cR(helgOr;^r)3rnJQd7;N+pb&i +z+jY47DJUiGdXX9A##r{=m@T#NuVO|xv?14l!*hYgR`Uo2sxp`1%tCBpJh21}!9e_~#xJVd3~-!*hA~NMd=~Bq9eZ0lQ;ffjOAX%C +z-lQFtF=Q$aJ)x*@*Z_Hkb0c)l7Bf2~eqKM0Up_|nzWF_Qvup=@9>nw9sqkCHCks_9 +zb-4FuqKj5uEm<>V)kVb|$0*Wh`xHCjXxcCvV8I*yv^05#;IW8G^zbk21C)h*e#i3Ve@g +zAlKR8s2BTQ?Z{7K(i_*cBVCIifA$lU1lU=SPa~D&9nlLXzEYOfffVl&?a!KwB*VOL +z3uuUV{5L$G8+D}+^#nEju`KPCr#%uY)uzE#eBBRt#wwP}N+VvA>1`9(Vd1fu4Nc9+OC){gTQgs9YB%{P#lul8%-a)0lEUEgk23S9~cnNd#kc +z19QW&1UG%;{0&1G0jDsH6QQmW+4xUn8(*iXOv+3A2H|;OtGJPA7Zruv#peswez*|& +zd}6rq_IwI~qc6-e4mW|SW6B8eveNWd18=}J(#SkOi(x!@i+{?vPEc@NGiWJ>bRXEJ +zb&WT+V{=aj%bS;M90xl?A()w0@!~a8A#EW$1s{aqV6`~y-e^Au@^kQ7IJMsI1w+z` +zLHOoLwY|e +zmj8gDMHz}QD7)H0T+?+~yh81cri@(Hjh7qxl?R_ddCbuli&YG!vK{AkR!??aADt#A9_#WF$((Y5_l6aLhNS=}?O9uNGqv+|80YLnAwVL6Y73QiOCs{|1f +z`8^6aoGdA>l;l@++G4m=5S--CFM8cgGeW^w&4v<=SmTTqI6-zL^ao}v9r1nDTT|OE +z7FAyzTHn|l2`L$2T8nY1$G=%9B}Vn7%G82sP(Y1)hn4_>VmOE0)wNyz@L_IkbwhZb +zuW#uTB5IgbR#S8v5#6Ur1$XP{jlx^D>pSe=00zx93ry*qgdk|9yeJ6Sx-{sET(x5~ +zhMkg>s5*?#VdBHi=A-uaO+u$wICT&c5II!Zbf=qnv$G8B7#aleMkKt{xaL9XHLFyj +zCc!Jg8{)(;bW;lK#*;Z?HCXPxJUU9AqHDw`@Yd4=qf+UK( +zw91^C!CZj$ZIpR%#m^@TCkaTsfW3Epb9Z)_uPN-pL5v+hAi9IHh4Wb*{|M*$C(g}J +z99Qc)WR`nAF@Dj$DJ6WJGOJmcZg~>MkRLueF~_~?)v_Ysm<*&5J3JN&MarrVG1bo@ +z^o{p|lMptVCp&1_F>m|A*|&GK)DX)bu#s7JK;YU2B*|fq>6YUThX(WYBJGHuO9`Q; +z4pRb3hvJ+B#PW~C^=5n{%Py{{Aw%I$ew0r-%g_~Q^Gi!y^>xZcIzBzFbsOWH*xw6& +zeYt$AINjd<0IIDOgDr)H6(og)|2ee>X7yP<@w^iK0(gV^+D+6LFx*MI +zars=D$QX`asnPR=$}qHCL9JJBGg!zz(8mN=_x8pPRs=>i)F9Rb5Z!|B?(Y{JkdQw! +zd}s_i-)fms1b-F_E;n1^$g@g`m!k->u~UWZDu6+`B918=knxd2S3bkjzd1X< +zrk`r)n114fPU;v1%N5`mcj+hDB+A)rbeVb>FjPxG-*w()45XKM9C2OQW1kWYed1xZ +zF`2s@Ff__v?sbA`NXSQ(M;S&}E%f$VG!4GQG;dNeuJ*dX3b|MvV_LFABn=m(6$}D< +z&zhv@FY1$=4>*bJ100gy*Yn8l38Sjeq{9#u3dEegXZ*Jt)tYHp4v9i=c@Kll{9>QB +z>1V3ee&5vDvde$!VRk5PdRl-6T}pa(Ru9H}>b2e8ZL1#j>e)j?{y0Z2>{J9M>z5DK +zkvq%2_bFdH&u{X$x+!)ZhDcbq*zQxHutB55%1?sRljC2YCPE{-|6enO{ +z$dQ)7HHwC;441LJExno9-!|&l>Xl!ljLS$rWZfVC$a@yWaLS$*e +zOQOyy3zBsZHnp&n@N_a&_LNgG_Ov$UG$G;VgXi(!0tncex)>69*xJ}Rb9wNR{GrPQ +ze1Cn-Ktl8f#KoGIL_=1ANZ8)Vl!%3%g&ssF>S5`|M8XG8#N%XQ#-$`8_74)k6EBH{ +zi;Dvn1B1J}JH0zIy}gq;10yFVCj*Fyfr*I@fS_~!Xy;<+L1*Vo`by$28X~67#!i+F +zE|&IoM6WarjqF`rcu7crb)tU|2Ud+mJ%E@0*x>c~4|!)769!4(fdx1Z0KmWm0&&oR +znCO@|8UBtBtjfy%3){~5A5sM5$>3q=z`#fkVz9OScNoqtqHh1T-+zeVtODF-F({cj +z+q*g$n~J)b+PRSaeNzV;SLeU)>FR9y`sxqgHYR2a08@W<{yUDiq^!cfa9+h|ZfWcA +z2jdm`?~o?O|AKRHb+Y*bV`9u;YGY~(FyahQX8d>XueWah!uWURd0qM67;&*Q`#*rc +zuKaJ{0C)c}@qdc<59@!_z$IdD?E1>1qzEs`>+!fu?2Ro=xc+=KWMnsG0Wq7>v9Ys& +z=vde}ndyu;nN8>nO<363m<>5t7+K8zMoQAo*~QS#*z}bYK%CwZpkrvv&dADX%1md% +z%EV5`!fI$l$H~HBOb23NWi>JaF|o0lu>6gLyptv1IEFTV=jxS|2|$XS%?t#P;-oWW +z<6r_v8MD%HG6F0a1Iz%#KxXV9lRu=hQ>tl +z%Kx^aVrgrt>|*#THAXfj7FH$>5F-a8BZ!5C{ojDpOr4wor+6jG2%=|V`m)2l)=Hy{LjLx8o3lKJxpyhL;&h`f1$E4bNnx>ntxkm;{1!~t4_H9NdQ_g +zeDy>{m|3Ul%Y-;lA+yC%x +zAwzS9KaV^N{~7TAMoHPi-res1ADw>#{TCHMCl_~nCu?~pc_S-RW0(J&&VK~_FG@;4 +zTy=JF`Y8E-In@6G$Mcu1O8~g`P9Oiazp|<0Ur&DpKO4(Gq9P*t6L0|I{Y(7LhHj>R +znHC_&zm|+G4DHNKfyn+3xBlmQ%m2U!*o+xLAY%|49gB&PAsq_`$e50U)0l~l*^JG^ +zjEU9M$Q1OKg8xO`+1|{>-O$NY&>XMXx6s0w7qcbrzGjz3aA>mUtb}|L_ +zw6J&iOUO2s|Df?l~V17`E +zkv{{>9-xh+#YO&1A;9j0+x>uVa1Iih&R}4eG*{=+>NF@Om6zv1IRtmMPjK=not8S205vm=kJzVY9|+usl9(29KX1@860 +z65{`4H0W&@S%d&`kaYI+4;nCP@YC?zWC3&!0*}p~*J2_c!VS=%1X~n@ClFe|=fiWI +zOG-*ktZi(HT3gd&Vh}?@LPkbM4d+W_Cvtcn;A@xKRg2Q!$x@+?7ArK|8%y@SuGBYue!Pn%mzI`BgbHUoBiKAHmNG6yl5BRfLr)ex@s54H$M(yHn4#g$ +zmrlLY8xhHf*OPMO8k#{9oE{#oyl(&dcum~Pi~H&6iEI~z=e=3Pg%0{&`>5mEtfeWJ +zkFm|xQV4(A_H@^+=<_baGeqjRYxUAkAHAfqKO(rqusBhnW?h__>8a6eUv4l*vbC*- +zqI@!GtwP`D`Y_?FnD&!|a$YQCQiddbfBT#-XUiAek7F{LeRJga%T`RU0rI6K$ueM4 +zQ`&hLMM~wH#=|k^N0qhpwrgznKAi`q$&bGfq&n@)QuY*+e)QQf6Iru>1(CubvR$7~ +zG#AQwmkn6%X2uR +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 +zOxom>x{+IRdWWf)hA5FBvYueE-x$ieSTz; +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 +z_xh_{^QnFR-q`n-=O;QC!P!OqvS)*_FI6= +zhNb_xSUImk13&#hMy>CexXKLwA?6Ci!Zfuz7j$_v9;&!iHYren9RcCr($dc8 +za9ybe`1crUG(yKtSkc8Ct9%3JzloiA-Pmf%cu6}kRkNRe!Q^@;>b}zjg3)EC-y?Kx +z*Rz()&}Db2Oad93PHPI`%bC80UUwKUqJCU*_ByzV&Ry)j+vuJu7NMO;@`D8;@cvXG +z$Chl}Qgm%?Xh;aO_y0%JS%yW`eQjI?1(XH>=@#kk5a|ZVp*x4}R#Lj8OF+82JBA*5 +zKspB;x{-R%^S`e53m@T}!#;bj`@Vl`9ntk>N&El)U5J4Q| +z?{+6C_;A)MiVsk=fVeJ+snHp +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 +zH6%qI4}Gvk7dKwyo4iqogAvH +zzG^1Ra!*dK`g-r(r7pGFQ9MOBkH7iQJS*SS|IN^jx{`5VORle1Ef(vt#xsz3%+66& +zU!y0e)qRdF1G>@%+JRdHZrtQ2TdX*IY~(6mI{ycZRa7)?&QSh4$txv*Qzys*7~S$_ +zVt~qKHtcBmDoh33LdaT%K!WVbC2${jE7|UuepX4U5+enG%Zm!>Wm1x^2x83_UNK +zF^?+4=E(Ae%KR!z`X(%X%|Ua{TI*g?!=4T1fRM%HmmHIdPTflGLavl+3=+bhaf9i;H)1|_XDJU~;&i=C$4>VA4a}M@6 +zy=b41)O5ZEVa1lJW{nt!BnFB38)b=$`6tRTBn(lY#%FE|AS{UAhA*}HQanEdQ*dw! +zORh%yiFWz$O0`a6t$faYr$OMWBiJ1BnOz!C@9nW}(|-iUgR!0otHH~?MuB$(TGcx8 +z4zVbY&u#x8V9pw^O?_@+3^M=i0X(@4^DgK?XOK^27;`g*rY1m|5&Z8K&Jfy0{>hTm +zLqTuZ1S>6lCM5|(csCz|l;}vKXl!UJ2xxve)kP(2M{xVoy!9R1!l`KEKIMa(2c*zA2#X7aWvY_@lw+X2m-JPcvCiYZ7 +zod|HByP(8w9;=&k3e*fq#$Jg#q?F)?G$ +zchsS-JJvMw76L2h5k7}n+n+=N=?h}p%7mYe-<7u<;6>FEH9qWls+>0)J@X2A9?_7i +zbbZ8DlBRKQ4m0d_SPqyUJt`NKhYbY5dx5|gSInj +zSr#%M6^84yfF$dwx2WuQ(pypJY|McR58kQ8kZ#uTIfOL82 +ze;^R1pjxD!=I>R-FPN59_SggYV`^v?ZhFxGy-bYC?GbEX9k;Etn%R5(BsECc>-T;L +zCT(@~1jyNtbXNe})BCVHmyR@|qrAD$!f;g)sKLtvqpgLVZF}kMYV=}4`f-3ZvH!By +zEji$dMIZNv6KH5napYY%<5kAV>>B>d_EEx@Bkq#b(RjXfnTUNi#%~_`vJjr-P{6=g +z`cq!e-=#CcIWSGeXb}p)0ZFO5#wJR=;SLJ2MKjT_`v%n63p&t)pAHS@xdnN9yMn{h +z0pg>%?ORYsG}rlx9PYjw@wqE!%TfJUX|BQez%9}9^@$iD9kZ!&%LaJxlK?a_T2w?&OhPh^Fz-m`)sV|@XlY1nVbQzoksf!-f2mA6^D9SR +zDjhZC1K_3C6Mq_UJu?Z^P3-vv`#r)tT=y$3hO>ZM@07B#87_8lfZNX*Ck3iGL4?K9(yT(YBd}p99)O4w=Vfu1 +z9E7x4%B8E5yf2Iiv7WEdE`3CdI?lL$5_ofDDn+Zjj>xi&Q=%~utX+3>al!3j%E8A0 +z!v&`TM7X)#W~11;h5?G{i;4;seP@bd`$0B&CcyF20xLfz4KV4V%E~0o(B_i#-wSZ_ +zh6XY!7LCa_Ek7kZMT@fmDb4_R#*BMkV2$H5Q1eggWSMg+aaQItFzRCHut+mT)|WDl +zSU!!v5@u!cSqx*Vh`~-nS2c|P-v9KZa70r}TlzC- +zutGv~kcB@Hc`4mvfw@dlb2H|V?BP6b9q7oqT`3k7H*~;+kUUCm$>B?h9EemT(wfX6 +zR5g=T8IUO*=m~l~l=~_^YtFA-UwZ`Hw6E6!t$nd%BBOv*FM0bq)Iss&Pgd#l4*}jy +zByx68pDE|BGWPeec{%2Bm5z%l?1{h127<=UrX4F%b`KuEBE)!u1vI_guoS0+xW$bb +zcPE-b{8x^fZ>sf~ +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 +zM;LqdYJuW!K4tjl +z_}fxbRjs-S04+i+ehA;^L9D>e?2P!_>xEl{{CBB-(JKA*$-?rzgb~dlx>UBj0|LxR +zHFLj3HQ$2WLsG;*jt0?J7)zZ121xDh53FklU?sF08yo$LOG_hCjRMj?Q+{SAlEe;q +ze!+_rjvFD_NV{SBvB{j%`vmA*dpf3g-lSOUvS+$L1g~^-WqZ39YrmtN3`vqy<3AQ| +zvWNft==HuH&tlb-QJq$sp}wRtr+&bWp>8-bmOe-nOJoFpDM;G>a9~FDJ?Bp+1OD`Y +zl-O<4G+x~$%Ix_?Z}yQ%B)NZK#R;^)b@b%NO6mK~@9GCm&@WWzNYmm9+M6k2>pzIH +zMN)4s7E?qLzKCO<#y-cp@g1=i6jAp!^s^z!{dc&2aa8S>P#7ho`cqrDu4qW`X1^r39OlDMaxzf +z1ED&4N@);d?^D{st#fc*|PB5kJ?abatl! +zK#R1;A$8(ew?*U+19MGX?k8Z*%fPD^Fd^T!NolpM_bIY3agdCghmV6pSW%4+%^O-l +zk;xn}5G)!*9x7t?;rd8yIPhtoO7sj8_}NTiRn25#Z_h{cxjC0!KzOuj(qH)U)?v;4 +zLRXjA&Jd=&UTxvVGHLvV9R*-D;WYzq$=xnjgDn}jQi-lv7n=ARUXtOy|3C>QP +zC~j)v<4g6`RG7(*bF!4s$B%>ftHx&ad>0$pM&2X-q{B#sKEez0DeD4kn6Sb;W`y_$ +zhs|Rp%`QW<0)>gcB)@j?j!CrKxL{0gkame)~km9 +zQ6h;L%)fm!>>!5<2;JM;IBdk~IqodMjZA9-zilceq{wbW!!nOrqT$@6kiynl@;LZy +zSSfRqTSN0%py;!})7I>B6x`!-OO4K<+h_1YDDgTf-9%55y&pLn`PE#LY9*LmI7M2` +zLU3=sfN@6c#t2gZ8HxN4o^#b&4fdGJFagiMu%g9fF8PxUTHl*PO8^)9k5&L03&0S* +zt}~3|mhD*XnxenG2A>Cb3&x+>{;SBAfF|t=#3NXDMv?hY%+88dG){7=JRYWqzARF9 +zJkdl7hE+1kL)E~mB0WiZ?JZz;5+(xPJO;QljS@EH{!LAQH1dghFJ`6UM(Emq&`vn3P@FRa7*^J6`#x-Iee3_agpz#DO+7O>y`TW2pn +z1Ak7iUv6sU)R=YMq_tH`l*1?fmxa81)4q9q +zeC-kC_AI!2XTv;f7emdj%ujx2uZ@+i-;_b!JYSU_H|o4p#qXzkx%QTSaJ^7B6vCtJ +zu%q&{AN;TkJBBaWuQJpP*lV-U0Pz#mF1RaXcM%>VbpMZ +zQiuhk`c5~+dIV*UCPJtrDr{0=L|V`FXRNpTA%FbudaIvO_U@3?Z*~RZ)KqN#{pyFJ +z-15TYaA3UDR+$n>EBH~Dz_Vfd=1%#O(lZ#yVRi9h9?oP$fdGsaYVVzpQ%d^IuK)ID +z5)I$1$FQv+O)Kt){vvNfrohuD&x_;s6W}my_5F&6<_uxsQ)R%v+w<&(&a!!KUNNpT +zIHSGn_R;FTFfaOH(K^ugU7eHu>j5>259G}Iy%vkDC`)w{HKI_JP#ySxTB{6z+J1dU +z>fAmQj^7DofzB*1j{%iJ3jm-+jhLU?M@Vj^YMN&H-mczsKl=ltctER$W1~%fJ}~_~ +zq<0;zlcoJdtw8NP@#{dd^CcOi*C%_tkCupp30BsRfPrx;;ZAwgxphQX&6Aw?FCmWMO4n+l>7$DIb1#Otp +zXq$4+iT^4T7)Hiy)bvB_d66PvY*)amyMagSJ%rxL|klcJvTq(1zC0|s6YT^m)J%#)NSjgOusXLid=IKyu@sl1X3)Y +zdAKr%E~3wxnp2P6YUB+4!G4F^Xa$x;3;G5vuc>KFxtrifY38f3@Dy7X48PsP>QVvb +zBvCx>%LFDU(mx9)$b!4l7H+e&E|ln#v`K}%PO+Zu-Wm09@EmuTa@590x?u|HzWc1! +zOq9)vd+94X5GP8grtvxs8pWU)Vc#Ud2gbaNz34Zx2l7{f;}*-;dG$Zd-Re;PiJ-?= +z?32k;MZQuXNG;kN=EQX^Q`oF}QvEvGb5oSy*x&#rn4FYsUZ +zit~lLmonD@9sb*yKP%`xu_7pop4LCY{;<2(Vkf%o`QwqncCF%$=#yYAPj!P0jRVT^ +z$IQu}&M(IdXd(6bu5u`LsSQrN>KamNl*DJV(^@M2%mZGG{cHZ=i>-Ei3aPA}SMQ8& +z`<{SW-cu{W9`k?0>cYB!9_RC0vu?AAJ|9-26*pzsqaUF*?Z3}0xL3`c6)yLcWO2{# +zI%VZ~Ld|*mo%M&l0^f!}9Q|zI40Jou94PqiD(Dy+-cK$G+n`N45LR+G$w1IRz#WMU +zGf9dZoC$?I)8lPC<&z{YnGykk?zjDfk|tYN5(80v{~DBt6U$|oNLy>J2DE+CW4c|% +zXQk1Xe~=COMvca$n}9i6$mu`(I#B?lciZA@3-bvgvj(LI+<9a+nsFW)Ad3jGwp02= +z@`ml?&>YrFMbI#Zi*cVod)5Gfx*N#TCFKgY;el{lfyc!?AF5(Ic_hF+uCCXP_D^Fi +z;E^~V&QL3rAO&3RxLpO6-rWAm`q)Bhv-9A4?Ujq0z~`HFV0?sYl{~n9S?|Kr-Q9n0 +z{rPcy`W&?8VSbtFr(;QJ +zU|jLbjCy8fWk5#s*7sq;$S<0tsw+{I!RdO47uR%Y3v(tNoy~r^|NEL6LF2qS-Z^!) +zrN&?r8RoUp>3EZaE-|%!t>sIeO+NY(zv+#LRLt6L$1LFZX}KGoD&i<9_hF|JDtdqD8+dE9{!xu&=Z|J( +z76LVfHX^O5KX20}rFl@zDEXJE(8iVb>20Ux#4zYB%w1qgXi|k@RUBvGX&QJt!O=GD9QKKf&V3aD!QN}@MQi~;Q!>^F0F#VQ9d`rW)NefjQv +zA)t2J-amzC4_$o9ic3wN@em_nN&fxaNrd(+HWt~zTPN0=NaG#}31LYWa0b$9@M05L +z+r#--CGhfz1>{v<3HVa}M*L%Ia$JvPe8+4b<189WCP}%IY!i#}A%}6Jty)pO*L`YC +zu*pR0gL#UnDI+wh{oa{0Rj67o6n4Lt@CWC_(vVEM(jLMNCii`M(QlS+Hj_g@|5vB0 +z2A~4fo)8eRes<^yX_7^H(}HE!ouko4W%FuJ-m&4+Ki6D%4wm1~z&{V~Jr4gw-DTL} +z(tVd@7!dL7Oh)OtaumMV2imchbI(@_u$&lBaZP#7&u%{f=_?gi3e!IaiN}99*FRiLHsak@3&FGW@ +z8KKp=tDck1M&j7k74KYON_Gj7sV6{4^n3Q8TaG>{s+@e8c@StZyJ!}>?Zp}{{@7v) +zdN=K=ALwS@`!>1%bhA|W9dVxwi+t~UwN7&UYWer|?_#&>Tmut}4Ueg(iFS|pDx@{n +zA1+iuxM%ko^s}$q-l+c^ePfr}MEagp9Uo`RuMOJccI|`WkxhE#g%j?Tk={g|or~L)5x^w!A{@ +zXC6`k;0xFv4Fx6XtIw_xFm^GV-1jg#)K`X@bo)0mJnYKrr`)wQaeMz5&e2={J8lb9 +zr`)c|6*-e9U6z$#zsml4XItenU`K@LO!3CeGo|98-x85!{%Q`42YRzSj+P+xY#rmS +zdQCH{Fcn^-o+dCLrwV+mh~09Y-Kl=OsL~uG8I-Jf<}vmiO(-g!C|T10HumZ^W6F`y(NPwa)(;r~{mNEA_laUG$6jx*2!q +z$Ecx4`{J6K|LGNluFFEUM<`?M#20q@Jh#tKg#W^w;SWwg$h7x6=IT2M0=nZCQlwK@K;wy0?`$fn2R%sX>A$+& +zT)Nbhhj-p%)!9QFnvNDHuCsj?+fQEjKT1R^{T{Zwz*nGiTODxL@5#3L>kSs{LcDDO +zzIK(KEfbM1E8))q{0Y*-W3#}U7Z&~bg{&^P{%86#OSo8~ZAorT1FOvyW&sKhX+{0j +z*K;#V)M5eVC@BAifL$TcGJetq@Z6o3lgA=tkl;rF5&7S=HND)%#L@dV3{HFqjqXOZ +zS*=YoliD3Q(=P*oP`0ol8FgV0JLICgqIwuNDzo7CTVj)3pP$~wf8XfVhHR;q8!j`8 +zcm1kww!=sMjxh$u!Su0O|(g8;N_ly)!gdu72J3R5qy=rfJT +z+B38^pMUI1@8V?W2r8)vV!jf_scDnY5kvviHXiz$v-=LOPVx?NHsHw{vw!9%qQynS +zLkmZJ9V~NYE>!7W&YR8&+n +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

7cOc&DF@xl^-3}B(kApb +z`7sOiU(VM2n3FyYN0QCw{@CU~VaPoQ{_ZCjRoLxp#J<|FPdrk?jZ;319Wmp*NJJI} +zsppTCVBV2Qpktoxo5K)(d6Jd6^C}sAnC{)*xCG>KTJ07tWMioL2Q5x?XCpPwR9X|u +z{?vH7muk2;DpN1--K%$**MuOYL~^l+E&liKv6lZMO7Lc14;8rptXF#4WRg5#`Y6FC +ze0Sz$aeQP+=RGP^FU@p-e+394rT^Y2i8&dGIY`g|wK%@iPEh!}CJPQ8-ifj7V6Ygs +zw7No2od2O2ATikparU@t>2M?duf4N;i?R#Xz6A;hBGM_{J(7bwG}0XcLzfIlr-C3M +zEj2Vq!_c50-OW&gbax{S67J>ue%k-T=HTE99K*ftT5Da`d7i(bwl<(pI@zDQh%7(Z +zYi6h|HU8v>r)O$aH#lA>Q>T`nPb;$P#z@tZ70>xKeJI#b&SfA%{l@%i>7yTFcj!EtKI{HHB#azJREico%6-`Z<| +z0L5YY7y7bHd=Ul5xh~|0eaau^I8QD=vVn2n{-7marQNZkhjdFqCW1m`9uy)^k-2!w +zzca%z^KJRW`1<@8oM0k65v-n|Tp~L4-4-pv#W(0BZb;arOmnmJIP>qes&D&H8P)_R +zoZ;#?>6jIqk};-AuEX;KO*q=&l8;!iIjj{fR7V*m}XC=Fk2J+!hb70(k^?PdDJdFZ*k^KR5(Zb_+?XIeP&y7MGRS4lhiMzUl7g1MgRp+- +zxicUPq#qWR^p#{>JDmZ^_5yuY;rwpu<;a3+s_)ss#*^w|89PIs`3p&wah&mF$-N-1 +zqpS5d1oVG`vL)2fqpmm-_)o61cg#%5?buB_{@8qR90?!ZrCmxm@+53T1|SuBH!C=n +zBm>MvN!R(Ni=gY-vI52{qg1z)3io<}1rM-_=t-7Hnm5Q}&#>?C`1`xtIN2JUomwzn1(_AFLTLT9ad0@+hz +zPubB8c^XmWpG84hA8Prwr&LZVQ4jI)q2~C+rA;Wt^XRYPLAEVJq?8A;T$JbE +zVMjls{tSg+9S9w&vl$R#uLJ8#Qe$M53a{pWMdbnkVx_phoRa$ENy(MbacLHg5ESTK +zD%Av9={;(~9!>K6WGXx +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 +zBQXTJ8WHx9l|F{Y�ECN!%-TBQwoYFsV*9D@||TI@CMShZDOmxz{Iuk^cE{_hFzU +zJ$$w?En!k%#eI6%HI>9{ziD&JRK?ET-!{JN?D(d9Og4YxyH0{bfGwgP=esF!*}Z#s +z&^OW&T5UY1Co1p>WvY3W5;^3qb^W2+y!0>E<6wWCw47v4E|IVOMY&a88gnHk +z+Su00naRs;v<|hYAg%v*-SEe#;SU@9dZjvxaNHloOjBXY8yL-3E8*O)&&M@YomM)r +zK#fsuL5$T3v-np)OM91nOWh|s^4m+pr~wgGb#>hCY*u%-XU^}S5|cl0JWr$jG9z~Z +z1RNRW$k6WBe6HDi@tK(nFRH@Al-chxfg42A^%RyA3hn+lzJlhMzqr}76JPiHyA&dw +zqd7kL_~-2g3f{CUP%lEVWAI-%CPY!4ErvGqy#=Y_(R(;Y7PWT8Ix{ +zKk+EPXqrN%z$$$X^!b%XaLjX%4)M%F1ukscB??H-bZzWK?i(-D8^u%^3@yBn&-L{p +z|FDXaEq89fZc1%yYkOr}eS6o;w(HZ-(12pj@C*RbbY>vv`zmIQeod@$do3*^5Qs00 +zqPj=aVgP%(eze-tkm9fTMz1j*Z8gPf-Km&7JdJQ+@Ryc+qWGnZmSKhW@w-vbZX6oUlIig +z`ZY)QwA_l-KRZ*?HRup*J}2_MKA0^+mfR%V|8ZSvd~EG^ClnG*ZEjkesmwlOi>qat +zdJc;xe#oP&7TNwbXB(bj!DY-+-@AcR%F3w9r2DjNML2O%&22S|H6*jBr5LQVCnj|M +zh2m3tZ_xr;4!7Mm6vBi(h~hU2#FEdSti`ETnfKrkga+P}hkI1&8fw+LdCUOVwZeozrfxf#qfh@7-!j_Ko1=zk8nkqWH2eAvRJ_*&N3dHK565Ay835>J-* +zz56jXJ>3VQT2O%dQ&?L1@t$W>UY@1iLb^U7yvyx_2nA0+N$|>qj#BYVRp@!&uGu0D>`@6HEHr097RVNpm$*GpVJ} +zwlGDOt6+pju=Vroq51V8yz8*scTzc3!P4`O-0;b*-<@u35n-lY3*tTWm}sN6Hba}% +zHiaovI&3*cUFH0l<5|`lal?g>{qD++mXtQIn{I5T&kna23Lr)3bOQ +z@bI38o+S-Ii-hxe*4jAbb;uP}w +zHk=96bV&=)Z_Lf<|1qv==bUjsu0JjQlg9fup^s7?&H4n*DQ2nJpht7$rd#~PL0H1( +zco7htDfcOJ4Xsq@7yTCcU6-!qP31YS!Zxq+!QnBi_F*(S812yEP-|M9raw&+X5`pa +zRzLQ~-&Q6MTtIoca9fSEMq`#D?u1{P$K;i+V8_xFD))D5fCDxq!BoscNtv~o4qG@l +z$U3wTF9-<;lw1`uQW5Z5!35LK3-HL?`Aeug!{dKV%>?0n!yqEVLCqZ3r;ztM;g8RT +zBag>{Au;FM&a+A5VWf8P*3M3LRn_tRrMhXuX70B0HYta6Q&JyqA0H5W`Y$o~^!%KU +zhvz>I;<#t`ofe4G=dHRdYgb+MoTluj?1|wMl8Na-l9qYuc(wf6{`scag+L*;e9`}o +zQ;QHWaXVhXsW(3{GiYvn%?1{pq~v7ldhcn(adA1JXtgJ>B7l={u6cWVPt}4? +z6BB#-?AZ(KAOJvL%N>yY5QyM{_2Sx*X9#8azezE*}(Gsnn(RmjV| +zls43GZz%oQ7!OrK%}q36)Xpl)$YA{X^=o{5yu$OyOaMOh56GvBgvUF`V$}=~yUv35 +zZuR{9{N6%SDoCe&jvdr%Rm~C>kj)aL-JK`H+*yLh7t-NBu-?A!zIt-CwYO&h)RZMg +z4G7Bt#QjT#UWTc%@oxqsk+K(i^9_mMBPv1qd~ire-@5an*Wkswrt|Y#+nz +z?X9ba2O5p;=!;_}qoib@j#m7UhtL0|WBDcilYhdbf0orsGmL+{@}eTF^2y?RqMs7K +zCj7@RWhF87OGEE$Eyj?mmLpjS#4iImS$=J8;=%$9jEjtlijfj82Z{WC5co5qM28)i +z`vKb(;MS7C(hrA(E4R2f9MC}k1`04LJFTk4o_(O1Vqdi+fD^a}Rm@_3V5W|4$R1^h +zkq-^dzUHfdd_YJf!8S8uQdsR>lS5KZt<97)Z_c@d2?&${=Pz +z-M~N*{03O?ahHz3bUL|~9%u4`hU2%0|Di?oG*DSRSzTQXl%$o+!hiAN1z1ji)@-P3 +zPUork5)DZ_8iKCDU)J*g}DiQdxqG*@GO0#8Y19 +zdmKE+3jtx!U=CJ7L+y^QP9J(sPMWzt(%y#N3SIc<6cZKy3Ija){QO`5-8m-J1uq(X +zbC}EKP?uTd98M!c79+z{XNc{z*Qc>M_ZheCIV|W`pq6f5=2>=30=E&kDF5yrf>8WO +z+2oWII`T+x-^%A{tmCpPGVGO=y?h8Bn4j|wZ0zhu*SFwp5FZWJqdPl0;5t8g;D3CH +z7+Ckl@WlOcPyeOMkXy~=D}r~D0m_E`_ewZ}VYWXKwl~Lqw2UVdv0xWzg?U1U#>WXO +z^-4ZuG=FtvOQ1_vNeqW6gk-Z6BE1(v_XxhWz(|$z1;Er+@X!VL|Gd8OC5x{Z78ebo%?f +zB0}jryO0j`*ZCy+V9JM5KZBLmQtH9VNdSJi8Ne3TB_lL=5`1CXn@ZOilBS`Bt6eVJ +zU%wF$z$HI?GC6g&;vCv;n|haGrOEo0i!h3WEif5|&wqQV?eAU`us`>SJ;FF3gIQe)Fe7%uT +KkuH-o3HTopq;ALn + +literal 0 +HcmV?d00001 + +diff --git a/chrome/test/data/adblock/tab-restore.html b/chrome/test/data/adblock/tab-restore.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/tab-restore.html +@@ -0,0 +1,33 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/test/data/adblock/wbn/LICENSE b/chrome/test/data/adblock/wbn/LICENSE +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/LICENSE +@@ -0,0 +1,14 @@ ++// This file is part of eyeo Chromium SDK, ++// Copyright (C) 2006-present eyeo GmbH ++// ++// eyeo Chromium SDK is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License version 3 as ++// published by the Free Software Foundation. ++// ++// eyeo Chromium SDK is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with eyeo Chromium SDK. If not, see . +diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE b/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/blocked_bundle/LICENSE +@@ -0,0 +1,14 @@ ++// This file is part of eyeo Chromium SDK, ++// Copyright (C) 2006-present eyeo GmbH ++// ++// eyeo Chromium SDK is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License version 3 as ++// published by the Free Software Foundation. ++// ++// eyeo Chromium SDK is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with eyeo Chromium SDK. If not, see . +diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_1_blocked_bundle.json +@@ -0,0 +1 @@ ++{ "method": "fetch", "result": 1 } +diff --git a/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/blocked_bundle/fetch_result_2_blocked_bundle.json +@@ -0,0 +1 @@ ++{ "method": "fetch", "result": 2 } +diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE b/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_bundle_file/LICENSE +@@ -0,0 +1,14 @@ ++// This file is part of eyeo Chromium SDK, ++// Copyright (C) 2006-present eyeo GmbH ++// ++// eyeo Chromium SDK is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License version 3 as ++// published by the Free Software Foundation. ++// ++// eyeo Chromium SDK is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with eyeo Chromium SDK. If not, see . +diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json b/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_bundle_file/fetch_result_2_subresource_loading.json +@@ -0,0 +1 @@ ++{ "method": "fetch", "result": 2 } +diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.css +@@ -0,0 +1 @@ ++.green { background-color: green } +diff --git a/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png b/chrome/test/data/adblock/wbn/by_bundle_file/green_subresource_loading.png +new file mode 100644 +index 0000000000000000000000000000000000000000..2040a0a2b2cd006f3ade7be290ff37ad8fd0452e +GIT binary patch +literal 772 +zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm. +diff --git a/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.css +@@ -0,0 +1 @@ ++.blue { background-color: blue } +diff --git a/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png b/chrome/test/data/adblock/wbn/by_resource/blue_subresource_loading.png +new file mode 100644 +index 0000000000000000000000000000000000000000..7a0773bec90118a4a83069ee0900449dcc511a49 +GIT binary patch +literal 773 +zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLmZZ}T. +diff --git a/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json b/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_scope/fetch_result_3_subresource_loading.json +@@ -0,0 +1 @@ ++{ "method": "fetch", "result": 3 } +diff --git a/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.css +@@ -0,0 +1 @@ ++.orange { background-color: orange } +diff --git a/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png b/chrome/test/data/adblock/wbn/by_scope/orange_subresource_loading.png +new file mode 100644 +index 0000000000000000000000000000000000000000..348f1275fa97592546d48a3f5a339625c231ba2e +GIT binary patch +literal 774 +zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLmkF2lAmzQji)bo59o7&t;ucLK6V>Gl+EDj>gTe~DWM4fjk(;R + +literal 0 +HcmV?d00001 + +diff --git a/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json b/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/by_scope/xhr_result_3_subresource_loading.json +@@ -0,0 +1 @@ ++{ "method": "xhr", "result": 3 } +diff --git a/chrome/test/data/adblock/wbn/index.html.mustache b/chrome/test/data/adblock/wbn/index.html.mustache +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/adblock/wbn/index.html.mustache +@@ -0,0 +1,157 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++

Chromium Web bundles test

++ ++

Identified by resource

++ ++
    ++
  • Resources in by_resource.wbn ++
      ++
    • Shows blue box with by_resource/blue_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_resource/blue_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows red box with by_resource/red_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_resource/red_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows xhr result for by_resource/xhr_result_1_subresource_loading.json: ++
      Pending
    • ++
    • Shows fetch result for by_resource/fetch_result_1_subresource_loading.json: ++
      Pending
    • ++
    ++
  • ++
++ ++

Identified by bundle file

++ ++
    ++
  • Resources in by_bundle_file.wbn (Please click here to check fetch behavior with blocked bundle) ++
      ++
    • Shows green box with by_bundle_file/green_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_bundle_file/green_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows purple box with by_bundle_file/purple_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_bundle_file/purple_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows xhr result for by_bundle_file/xhr_result_2_subresource_loading.json: ++
      Pending
    • ++
    • Shows fetch result for by_bundle_file/fetch_result_2_subresource_loading.json: ++
      Pending
    • ++
    ++
  • ++
++ ++

Identified by scope

++ ++
    ++
  • Resources in by_scope.wbn ++
      ++
    • Shows orange box with by_scope/orange_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_scope/orange_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows pink box with by_scope/pink_subresource_loading.css, grey box after the css blocked: ++
    • ++
    • Shows by_scope/pink_subresource_loading.png, nothing after the png blocked: ++
    • ++
    • Shows xhr result for by_scope/xhr_result_3_subresource_loading.json: ++
      Pending
    • ++
    • Shows fetch result for by_scope/fetch_result_3_subresource_loading.json: ++
      Pending
    • ++
    ++
  • ++
++ ++

++To navigate to {{{navigation_to_unsigned_bundles_baseUrl}}} within a bundle file, download the bundle file by clicking here. ++

++ ++ +-- +2.25.1 diff --git a/build/patches/eyeo-beta-114.0.5735.53-v1-extension_api.patch b/build/patches/eyeo-117.0.5938.0-extension_api.patch similarity index 87% rename from build/patches/eyeo-beta-114.0.5735.53-v1-extension_api.patch rename to build/patches/eyeo-117.0.5938.0-extension_api.patch index a6af4313..3effce35 100644 --- a/build/patches/eyeo-beta-114.0.5735.53-v1-extension_api.patch +++ b/build/patches/eyeo-117.0.5938.0-extension_api.patch @@ -1,44 +1,47 @@ -From: vanilla-chromium-builder -Date: Fri, 26 May 2023 09:20:37 +0000 -Subject: Eyeo Chromium SDK Desktop Settings UI Patch +From: chromium-sdk +Date: Mon, 21 Aug 2023 18:20:45 +0200 +Subject: eyeo Browser Ad filtering Solution: Extension API Module -Based on Chromium 114.0.5735.53 +Based on Chromium 117.0.5938.0 -Pre-requisites: Eyeo Chromium SDK Base Patch +Pre-requisites: eyeo Browser Ad filtering Solution: Base Module --- - chrome/browser/extensions/BUILD.gn | 9 + + chrome/browser/extensions/BUILD.gn | 13 + chrome/browser/extensions/api/BUILD.gn | 5 + - .../adblock_private/adblock_private_api.cc | 797 +++++++++++++++ - .../api/adblock_private/adblock_private_api.h | 431 ++++++++ - .../adblock_private_apitest.cc | 948 ++++++++++++++++++ + .../adblock_private/adblock_private_api.cc | 621 +++++++++++ + .../api/adblock_private/adblock_private_api.h | 328 ++++++ + .../adblock_private_apitest.cc | 984 ++++++++++++++++++ ...browser_context_keyed_service_factories.cc | 8 + - .../eyeo_filtering_private_api.cc | 738 ++++++++++++++ - .../eyeo_filtering_private_api.h | 342 +++++++ - .../eyeo_filtering_private_apitest.cc | 154 +++ + .../eyeo_filtering_private_api.cc | 770 ++++++++++++++ + .../eyeo_filtering_private_api.h | 360 +++++++ + .../eyeo_filtering_private_apitest.cc | 155 +++ .../api/settings_private/prefs_util.cc | 19 + ...browser_context_keyed_service_factories.cc | 4 + .../extension_function_registration_test.cc | 10 + - .../common/extensions/api/_api_features.json | 24 + + .../common/extensions/api/_api_features.json | 22 + .../extensions/api/_permission_features.json | 12 + - .../common/extensions/api/adblock_private.idl | 197 ++++ + .../common/extensions/api/adblock_private.idl | 174 ++++ chrome/common/extensions/api/api_sources.gni | 6 + - .../extensions/api/eyeo_filtering_private.idl | 191 ++++ + .../extensions/api/eyeo_filtering_private.idl | 201 ++++ .../permissions/chrome_api_permissions.cc | 8 + .../permissions/permission_set_unittest.cc | 8 + chrome/test/BUILD.gn | 6 + .../api_test/adblock_private/empty.js | 14 + .../api_test/adblock_private/main.html | 29 + .../api_test/adblock_private/manifest.json | 32 + - .../api_test/adblock_private/test.html | 24 + - .../api_test/adblock_private/test.js | 737 ++++++++++++++ + .../api_test/adblock_private/some-popup.html | 24 + + .../api_test/adblock_private/test.html | 25 + + .../api_test/adblock_private/test.js | 538 ++++++++++ .../api_test/eyeo_filtering_private/empty.js | 14 + .../api_test/eyeo_filtering_private/main.html | 29 + .../eyeo_filtering_private/manifest.json | 31 + - .../api_test/eyeo_filtering_private/test.js | 448 +++++++++ + .../api_test/eyeo_filtering_private/test.js | 460 ++++++++ .../browser/extension_event_histogram_value.h | 7 +- - .../common/mojom/api_permission_id.mojom | 6 + + .../common/mojom/api_permission_id.mojom | 9 + tools/metrics/histograms/enums.xml | 5 +- - 32 files changed, 5291 insertions(+), 2 deletions(-) + .../definitions/adblock_private.d.ts | 172 +++ + .../definitions/eyeo_filtering_private.d.ts | 249 +++++ + 35 files changed, 5350 insertions(+), 2 deletions(-) create mode 100644 chrome/browser/extensions/api/adblock_private/adblock_private_api.cc create mode 100644 chrome/browser/extensions/api/adblock_private/adblock_private_api.h create mode 100644 chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc @@ -50,12 +53,15 @@ Pre-requisites: Eyeo Chromium SDK Base Patch create mode 100644 chrome/test/data/extensions/api_test/adblock_private/empty.js create mode 100644 chrome/test/data/extensions/api_test/adblock_private/main.html create mode 100644 chrome/test/data/extensions/api_test/adblock_private/manifest.json + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/some-popup.html create mode 100644 chrome/test/data/extensions/api_test/adblock_private/test.html create mode 100644 chrome/test/data/extensions/api_test/adblock_private/test.js create mode 100644 chrome/test/data/extensions/api_test/eyeo_filtering_private/empty.js create mode 100644 chrome/test/data/extensions/api_test/eyeo_filtering_private/main.html create mode 100644 chrome/test/data/extensions/api_test/eyeo_filtering_private/manifest.json create mode 100644 chrome/test/data/extensions/api_test/eyeo_filtering_private/test.js + create mode 100644 tools/typescript/definitions/adblock_private.d.ts + create mode 100644 tools/typescript/definitions/eyeo_filtering_private.d.ts diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn --- a/chrome/browser/extensions/BUILD.gn @@ -89,11 +95,15 @@ diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUIL "api/favicon/favicon_util.cc", "api/favicon/favicon_util.h", "api/feedback_private/chrome_feedback_private_delegate.cc", -@@ -811,6 +819,7 @@ static_library("extensions") { +@@ -813,6 +821,11 @@ static_library("extensions") { + "//chrome/browser/safe_browsing:metrics_collector", "//chrome/browser/ui/tabs:tab_enums", "//chrome/browser/web_applications", - "//chromeos/components/kiosk", ++<<<<<<< HEAD ++======= ++ "//chromeos/components/kiosk", + "//components/adblock/content:browser", ++>>>>>>> 9402d5c48c0e8... Squashed commits "//components/cbor:cbor", "//components/commerce/core:pref_names", "//components/device_reauth", @@ -123,7 +133,7 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.c new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc -@@ -0,0 +1,797 @@ +@@ -0,0 +1,621 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -165,68 +175,6 @@ new file mode 100644 + +namespace { + -+enum class BuiltInSubscriptionAction { kSelect, kUnselect }; -+ -+std::string RunBuiltInSubscriptionAction( -+ BuiltInSubscriptionAction action, -+ content::BrowserContext* browser_context, -+ const GURL& url) { -+ if (!url.is_valid()) { -+ return "Invalid URL"; -+ } -+ auto* controller = -+ adblock::AdblockControllerFactory::GetForBrowserContext(browser_context); -+ auto recommended = controller->GetKnownSubscriptions(); -+ if (!recommended.empty()) { -+ auto item = -+ std::find_if(recommended.begin(), recommended.end(), -+ [&url](const adblock::KnownSubscriptionInfo& recommended) { -+ return recommended.url == url; -+ }); -+ if (item == recommended.end()) { -+ return "Not a built-in subscription"; -+ } -+ } -+ -+ switch (action) { -+ case BuiltInSubscriptionAction::kSelect: -+ controller->SelectBuiltInSubscription(url); -+ break; -+ case BuiltInSubscriptionAction::kUnselect: -+ controller->UnselectBuiltInSubscription(url); -+ break; -+ default: -+ NOTREACHED(); -+ } -+ -+ return {}; -+} -+ -+enum class CustomSubscriptionAction { kAdd, kRemove }; -+ -+std::string RunCustomSubscriptionAction( -+ CustomSubscriptionAction action, -+ content::BrowserContext* browser_context, -+ const GURL& url) { -+ if (!url.is_valid()) { -+ return "Invalid URL"; -+ } -+ auto* controller = -+ adblock::AdblockControllerFactory::GetForBrowserContext(browser_context); -+ switch (action) { -+ case CustomSubscriptionAction::kAdd: -+ controller->AddCustomSubscription(url); -+ break; -+ case CustomSubscriptionAction::kRemove: -+ controller->RemoveCustomSubscription(url); -+ break; -+ default: -+ NOTREACHED(); -+ } -+ -+ return {}; -+} -+ +enum class SubscriptionAction { kInstall, kUninstall }; + +std::string RunSubscriptionAction(SubscriptionAction action, @@ -347,10 +295,11 @@ new file mode 100644 + const std::vector& parent_frame_urls, + adblock::ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { ++ const GURL& subscription, ++ const std::string& configuration_name) override { + std::unique_ptr event; -+ api::adblock_private::AdInfo info = -+ CreateAdInfoObject(url, subscription, render_frame_host); ++ api::adblock_private::AdInfo info = CreateAdInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = adblock::utils::ConvertURLs(parent_frame_urls); + info.content_type = adblock::ContentTypeToString(content_type); + @@ -370,9 +319,10 @@ new file mode 100644 + + void OnPageAllowed(const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ api::adblock_private::AdInfo info = -+ CreateAdInfoObject(url, subscription, render_frame_host); ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ api::adblock_private::AdInfo info = CreateAdInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = std::vector{}; + info.content_type = ""; + @@ -387,10 +337,11 @@ new file mode 100644 + adblock::FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { ++ const GURL& subscription, ++ const std::string& configuration_name) override { + std::unique_ptr event; -+ api::adblock_private::AdInfo info = -+ CreateAdInfoObject(url, subscription, render_frame_host); ++ api::adblock_private::AdInfo info = CreateAdInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = std::vector{opener_url.spec()}; + info.content_type = ""; + @@ -456,11 +407,13 @@ new file mode 100644 + api::adblock_private::AdInfo CreateAdInfoObject( + const GURL& url, + const GURL& subscription, ++ const std::string& configuration_name, + content::RenderFrameHost* render_frame_host) { + DCHECK(render_frame_host); + api::adblock_private::AdInfo info; + info.url = url.spec(); + info.subscription = subscription.spec(); ++ info.configuration_name = configuration_name; + info.tab_id = api::tabs::TAB_ID_NONE; + info.window_id = SessionID::InvalidValue().id(); + const content::WebContents* wc = @@ -615,125 +568,6 @@ new file mode 100644 + api::adblock_private::GetBuiltInSubscriptions::Results::Create(result))); +} + -+AdblockPrivateSelectBuiltInSubscriptionFunction:: -+ AdblockPrivateSelectBuiltInSubscriptionFunction() {} -+ -+AdblockPrivateSelectBuiltInSubscriptionFunction:: -+ ~AdblockPrivateSelectBuiltInSubscriptionFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateSelectBuiltInSubscriptionFunction::Run() { -+ absl::optional -+ params = api::adblock_private::SelectBuiltInSubscription::Params::Create( -+ args()); -+ EXTENSION_FUNCTION_VALIDATE(params); -+ auto url = GURL{params->url}; -+ auto status = RunBuiltInSubscriptionAction(BuiltInSubscriptionAction::kSelect, -+ browser_context(), url); -+ if (!status.empty()) { -+ return RespondNow(Error(status)); -+ } -+ -+ return RespondNow(NoArguments()); -+} -+ -+AdblockPrivateUnselectBuiltInSubscriptionFunction:: -+ AdblockPrivateUnselectBuiltInSubscriptionFunction() {} -+ -+AdblockPrivateUnselectBuiltInSubscriptionFunction:: -+ ~AdblockPrivateUnselectBuiltInSubscriptionFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateUnselectBuiltInSubscriptionFunction::Run() { -+ absl::optional -+ params = -+ api::adblock_private::UnselectBuiltInSubscription::Params::Create( -+ args()); -+ EXTENSION_FUNCTION_VALIDATE(params); -+ auto url = GURL{params->url}; -+ auto status = RunBuiltInSubscriptionAction( -+ BuiltInSubscriptionAction::kUnselect, browser_context(), url); -+ if (!status.empty()) { -+ return RespondNow(Error(status)); -+ } -+ -+ return RespondNow(NoArguments()); -+} -+ -+AdblockPrivateGetSelectedBuiltInSubscriptionsFunction:: -+ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() {} -+ -+AdblockPrivateGetSelectedBuiltInSubscriptionsFunction:: -+ ~AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateGetSelectedBuiltInSubscriptionsFunction::Run() { -+ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( -+ browser_context()); -+ -+ return RespondNow(ArgumentList( -+ api::adblock_private::GetSelectedBuiltInSubscriptions::Results::Create( -+ CopySubscriptions(controller->GetSelectedBuiltInSubscriptions())))); -+} -+ -+AdblockPrivateAddCustomSubscriptionFunction:: -+ AdblockPrivateAddCustomSubscriptionFunction() {} -+ -+AdblockPrivateAddCustomSubscriptionFunction:: -+ ~AdblockPrivateAddCustomSubscriptionFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateAddCustomSubscriptionFunction::Run() { -+ absl::optional params = -+ api::adblock_private::AddCustomSubscription::Params::Create(args()); -+ EXTENSION_FUNCTION_VALIDATE(params); -+ auto url = GURL{params->url}; -+ auto status = RunCustomSubscriptionAction(CustomSubscriptionAction::kAdd, -+ browser_context(), url); -+ if (!status.empty()) { -+ return RespondNow(Error(status)); -+ } -+ -+ return RespondNow(NoArguments()); -+} -+ -+AdblockPrivateRemoveCustomSubscriptionFunction:: -+ AdblockPrivateRemoveCustomSubscriptionFunction() {} -+ -+AdblockPrivateRemoveCustomSubscriptionFunction:: -+ ~AdblockPrivateRemoveCustomSubscriptionFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateRemoveCustomSubscriptionFunction::Run() { -+ absl::optional -+ params = api::adblock_private::RemoveCustomSubscription::Params::Create( -+ args()); -+ EXTENSION_FUNCTION_VALIDATE(params); -+ auto url = GURL{params->url}; -+ auto status = RunCustomSubscriptionAction(CustomSubscriptionAction::kRemove, -+ browser_context(), url); -+ if (!status.empty()) { -+ return RespondNow(Error(status)); -+ } -+ -+ return RespondNow(NoArguments()); -+} -+ -+AdblockPrivateGetCustomSubscriptionsFunction:: -+ AdblockPrivateGetCustomSubscriptionsFunction() {} -+ -+AdblockPrivateGetCustomSubscriptionsFunction:: -+ ~AdblockPrivateGetCustomSubscriptionsFunction() {} -+ -+ExtensionFunction::ResponseAction -+AdblockPrivateGetCustomSubscriptionsFunction::Run() { -+ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( -+ browser_context()); -+ return RespondNow(ArgumentList( -+ api::adblock_private::GetCustomSubscriptions::Results::Create( -+ CopySubscriptions(controller->GetCustomSubscriptions())))); -+} -+ +AdblockPrivateInstallSubscriptionFunction:: + AdblockPrivateInstallSubscriptionFunction() {} + @@ -925,7 +759,7 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.h new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/adblock_private/adblock_private_api.h -@@ -0,0 +1,431 @@ +@@ -0,0 +1,328 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -1067,109 +901,6 @@ new file mode 100644 + const AdblockPrivateGetBuiltInSubscriptionsFunction&) = delete; +}; + -+class AdblockPrivateSelectBuiltInSubscriptionFunction -+ : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.selectBuiltInSubscription", -+ UNKNOWN) -+ AdblockPrivateSelectBuiltInSubscriptionFunction(); -+ -+ private: -+ ~AdblockPrivateSelectBuiltInSubscriptionFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateSelectBuiltInSubscriptionFunction( -+ const AdblockPrivateSelectBuiltInSubscriptionFunction&) = delete; -+ AdblockPrivateSelectBuiltInSubscriptionFunction& operator=( -+ const AdblockPrivateSelectBuiltInSubscriptionFunction&) = delete; -+}; -+ -+class AdblockPrivateUnselectBuiltInSubscriptionFunction -+ : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.unselectBuiltInSubscription", -+ UNKNOWN) -+ AdblockPrivateUnselectBuiltInSubscriptionFunction(); -+ -+ private: -+ ~AdblockPrivateUnselectBuiltInSubscriptionFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateUnselectBuiltInSubscriptionFunction( -+ const AdblockPrivateUnselectBuiltInSubscriptionFunction&) = delete; -+ AdblockPrivateUnselectBuiltInSubscriptionFunction& operator=( -+ const AdblockPrivateUnselectBuiltInSubscriptionFunction&) = delete; -+}; -+ -+class AdblockPrivateGetSelectedBuiltInSubscriptionsFunction -+ : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getSelectedBuiltInSubscriptions", -+ UNKNOWN) -+ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction(); -+ -+ private: -+ ~AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction( -+ const AdblockPrivateGetSelectedBuiltInSubscriptionsFunction&) = delete; -+ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction& operator=( -+ const AdblockPrivateGetSelectedBuiltInSubscriptionsFunction&) = delete; -+}; -+ -+class AdblockPrivateAddCustomSubscriptionFunction : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.addCustomSubscription", UNKNOWN) -+ AdblockPrivateAddCustomSubscriptionFunction(); -+ -+ private: -+ ~AdblockPrivateAddCustomSubscriptionFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateAddCustomSubscriptionFunction( -+ const AdblockPrivateAddCustomSubscriptionFunction&) = delete; -+ AdblockPrivateAddCustomSubscriptionFunction& operator=( -+ const AdblockPrivateAddCustomSubscriptionFunction&) = delete; -+}; -+ -+class AdblockPrivateRemoveCustomSubscriptionFunction -+ : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.removeCustomSubscription", UNKNOWN) -+ AdblockPrivateRemoveCustomSubscriptionFunction(); -+ -+ private: -+ ~AdblockPrivateRemoveCustomSubscriptionFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateRemoveCustomSubscriptionFunction( -+ const AdblockPrivateRemoveCustomSubscriptionFunction&) = delete; -+ AdblockPrivateRemoveCustomSubscriptionFunction& operator=( -+ const AdblockPrivateRemoveCustomSubscriptionFunction&) = delete; -+}; -+ -+class AdblockPrivateGetCustomSubscriptionsFunction : public ExtensionFunction { -+ public: -+ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getCustomSubscriptions", UNKNOWN) -+ AdblockPrivateGetCustomSubscriptionsFunction(); -+ -+ private: -+ ~AdblockPrivateGetCustomSubscriptionsFunction() override; -+ -+ ResponseAction Run() override; -+ -+ AdblockPrivateGetCustomSubscriptionsFunction( -+ const AdblockPrivateGetCustomSubscriptionsFunction&) = delete; -+ AdblockPrivateGetCustomSubscriptionsFunction& operator=( -+ const AdblockPrivateGetCustomSubscriptionsFunction&) = delete; -+}; -+ +class AdblockPrivateInstallSubscriptionFunction : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("adblockPrivate.installSubscription", UNKNOWN) @@ -1361,7 +1092,7 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_apite new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc -@@ -0,0 +1,948 @@ +@@ -0,0 +1,984 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -1384,6 +1115,8 @@ new file mode 100644 +#include "chrome/browser/adblock/adblock_content_browser_client.h" +#include "chrome/browser/adblock/adblock_controller_factory.h" +#include "chrome/browser/extensions/extension_apitest.h" ++#include "chrome/browser/ssl/https_upgrades_interceptor.h" ++#include "chrome/browser/ssl/https_upgrades_util.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/api/adblock_private.h" +#include "chrome/common/extensions/api/tabs.h" @@ -1559,40 +1292,6 @@ new file mode 100644 + EXPECT_TRUE(RunTest("getBuiltInSubscriptions")) << message_; +} + -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, SelectedSubscriptionsDataSchema) { -+ EXPECT_TRUE(RunTest("selectedSubscriptionsDataSchema")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, -+ SelectBuiltInSubscriptionsInvalidURL) { -+ EXPECT_TRUE(RunTest("selectBuiltInSubscriptionsInvalidURL")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, -+ SelectBuiltInSubscriptionsNotBuiltIn) { -+ EXPECT_TRUE(RunTest("selectBuiltInSubscriptionsNotBuiltIn")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, -+ UnselectBuiltInSubscriptionsInvalidURL) { -+ EXPECT_TRUE(RunTest("unselectBuiltInSubscriptionsInvalidURL")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, -+ UnselectBuiltInSubscriptionsNotBuiltIn) { -+ EXPECT_TRUE(RunTest("unselectBuiltInSubscriptionsNotBuiltIn")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, BuiltInSubscriptionsManagement) { -+ auto params = SubscriptionsManagementSetup(); -+ if (params.empty()) { -+ // Since default configuration has been changed let's skip this test -+ return; -+ } -+ EXPECT_TRUE(RunTestWithParams("builtInSubscriptionsManagement", params)) -+ << message_; -+} -+ +IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, + InstalledSubscriptionsDataSchema) { + EXPECT_TRUE(RunTest("installedSubscriptionsDataSchema")) << message_; @@ -1686,18 +1385,6 @@ new file mode 100644 + EXPECT_TRUE(RunTestWithParams("subscriptionsManagement", params)) << message_; +} + -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, CustomSubscriptionInvalidURL) { -+ EXPECT_TRUE(RunTest("addCustomSubscriptionInvalidURL")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, RemoveSubscriptionInvalidURL) { -+ EXPECT_TRUE(RunTest("removeCustomSubscriptionInvalidURL")) << message_; -+} -+ -+IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, CustomSubscriptionsManagement) { -+ EXPECT_TRUE(RunTest("customSubscriptionsManagement")) << message_; -+} -+ +IN_PROC_BROWSER_TEST_P(AdblockPrivateApiTest, AllowedDomainsManagement) { + EXPECT_TRUE(RunTest("allowedDomainsManagement")) << message_; +} @@ -1811,6 +1498,21 @@ new file mode 100644 + void SetUpOnMainThread() override { + ExtensionApiTest::SetUpOnMainThread(); + ++ https_test_server_ = std::make_unique( ++ net::EmbeddedTestServer::TYPE_HTTPS); ++ https_test_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK); ++ https_test_server_->ServeFilesFromSourceDirectory( ++ "chrome/test/data/extensions/api_test/adblock_private"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/extensions/api_test/adblock_private"); ++ HttpsUpgradesInterceptor::SetHttpsPortForTesting( ++ https_test_server_->port()); ++ HttpsUpgradesInterceptor::SetHttpPortForTesting( ++ embedded_test_server()->port()); ++ ASSERT_TRUE(https_test_server_->Start()); ++ AllowHttpForHostnamesForTesting({"example.com"}, ++ browser()->profile()->GetPrefs()); ++ + // Map example.com to localhost. + host_resolver()->AddRule("example.com", "127.0.0.1"); + ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1825,7 +1527,7 @@ new file mode 100644 + + void ExecuteScript(const std::string& js_code) const { + content::WebContents* web_contents = -+ browser()->tab_strip_model()->GetActiveWebContents(); ++ browser()->tab_strip_model()->GetWebContentsAt(0); + ASSERT_TRUE(content::ExecJs(web_contents->GetPrimaryMainFrame(), js_code)); + } + @@ -1856,6 +1558,8 @@ new file mode 100644 + } + ExecuteScriptInBackgroundPage(extension_id, setup_script); + } ++ ++ std::unique_ptr https_test_server_; +}; + +IN_PROC_BROWSER_TEST_P(AdblockPrivateApiBackgroundPageTest, PageAllowedEvents) { @@ -1885,7 +1589,7 @@ new file mode 100644 + chrome.test.sendScriptResult(''); + )"; + -+ const GURL test_url = embedded_test_server()->GetURL( ++ const GURL test_url = https_test_server_->GetURL( + "example.com", "/extensions/api_test/adblock_private/test.html"); + + SetupApiObjectAndMethods(extension->id()); @@ -1927,7 +1631,7 @@ new file mode 100644 + chrome.test.sendScriptResult(''); + )"; + -+ const GURL test_url = embedded_test_server()->GetURL( ++ const GURL test_url = https_test_server_->GetURL( + "example.com", "/extensions/api_test/adblock_private/test.html"); + + SetupApiObjectAndMethods(extension->id()); @@ -1969,10 +1673,39 @@ new file mode 100644 + chrome.test.sendScriptResult(''); + )"; + -+ constexpr char kReadCountersScript[] = R"( -+ chrome.test.sendScriptResult(testData.popupBlockedCount + -+ '-' + testData.popupAllowedCount); -+ )"; ++ auto read_allowed_stats_script = [](int expected) { ++ std::string script = base::StringPrintf( ++ R"( ++ var intervalAllowedId = setInterval(function() { ++ if (testData.popupAllowedCount == %d) { ++ if (intervalAllowedId) { ++ clearInterval(intervalAllowedId); ++ intervalAllowedId = null; ++ } ++ chrome.test.sendScriptResult( ++ testData.popupAllowedCount.toString()); ++ } ++ }, 100))", ++ expected); ++ return script; ++ }; ++ ++ auto read_blocked_stats_script = [](int expected) { ++ std::string script = base::StringPrintf( ++ R"( ++ var intervalBlockedId = setInterval(function() { ++ if (testData.popupBlockedCount == %d) { ++ if (intervalBlockedId) { ++ clearInterval(intervalBlockedId); ++ intervalBlockedId = null; ++ } ++ chrome.test.sendScriptResult( ++ testData.popupBlockedCount.toString()); ++ } ++ }, 100))", ++ expected); ++ return script; ++ }; + + constexpr char kBlockPopupScript[] = R"( + apiObject.addCustomFilter(%s'some-popup.html^$popup'); @@ -1984,28 +1717,30 @@ new file mode 100644 + chrome.test.sendScriptResult(''); + )"; + -+ const GURL test_url = embedded_test_server()->GetURL( -+ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ const GURL test_url = ++ embedded_test_server()->GetURL("example.com", "/test.html"); ++ constexpr char kOpenPopupScript[] = ++ "document.getElementById('popup_id').click()"; + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); + SetupApiObjectAndMethods(extension->id()); + + ExecuteScriptInBackgroundPage(extension->id(), kSetListenersScript); -+ ASSERT_EQ("0-0", ExecuteScriptInBackgroundPage(extension->id(), -+ kReadCountersScript)); + + ExecuteScriptInBackgroundPage( + extension->id(), + base::StringPrintf(kBlockPopupScript, IsOldApi() ? "" : "'adblock', ")); -+ ExecuteScript("window.open('some-popup.html');"); -+ ASSERT_EQ("1-0", ExecuteScriptInBackgroundPage(extension->id(), -+ kReadCountersScript)); ++ ExecuteScript(kOpenPopupScript); ++ ASSERT_EQ(1, std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), read_blocked_stats_script(1)))); + + ExecuteScriptInBackgroundPage( + extension->id(), + base::StringPrintf(kAllowPopupScript, IsOldApi() ? "" : "'adblock', ")); -+ ExecuteScript("window.open('some-popup.html');"); -+ ASSERT_EQ("1-1", ExecuteScriptInBackgroundPage(extension->id(), -+ kReadCountersScript)); ++ ExecuteScript(kOpenPopupScript); ++ ASSERT_EQ(1, std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), read_allowed_stats_script(1)))); ++ ASSERT_EQ(1, std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), read_blocked_stats_script(1)))); +} + +IN_PROC_BROWSER_TEST_P(AdblockPrivateApiBackgroundPageTest, PopupStats) { @@ -2014,29 +1749,53 @@ new file mode 100644 + {.allow_in_incognito = IsIncognito()}); + ASSERT_TRUE(extension); + -+ constexpr char kReadAllowedStatsScript[] = R"( -+ apiObject[sessionAllowedCount](function(sessionStats) { -+ let count = 0; -+ for (const entry of sessionStats) { -+ if (entry.url === 'adblock:custom') { -+ count = entry.count; -+ } -+ } -+ chrome.test.sendScriptResult(count.toString()); -+ }); -+ )"; ++ auto read_allowed_stats_script = [](int expected) { ++ std::string script = base::StringPrintf( ++ R"( ++ var intervalAllowedId = setInterval(function() { ++ apiObject[sessionAllowedCount](function(sessionStats) { ++ let count = 0; ++ for (const entry of sessionStats) { ++ if (entry.url === 'adblock:custom') { ++ count = entry.count; ++ } ++ } ++ if (%d == 0 || count == %d) { ++ if (intervalAllowedId) { ++ clearInterval(intervalAllowedId); ++ intervalAllowedId = null; ++ } ++ chrome.test.sendScriptResult(count.toString()); ++ } ++ } ++ )}, 100))", ++ expected, expected); ++ return script; ++ }; + -+ constexpr char kReadBlockedStatsScript[] = R"( -+ apiObject[sessionBlockedCount](function(sessionStats) { -+ let count = 0; -+ for (const entry of sessionStats) { -+ if (entry.url === 'adblock:custom') { -+ count = entry.count; -+ } -+ } -+ chrome.test.sendScriptResult(count.toString()); -+ }); -+ )"; ++ auto read_blocked_stats_script = [](int expected) { ++ std::string script = base::StringPrintf( ++ R"( ++ var intervalBlockedId = setInterval(function() { ++ apiObject[sessionBlockedCount](function(sessionStats) { ++ let count = 0; ++ for (const entry of sessionStats) { ++ if (entry.url === 'adblock:custom') { ++ count = entry.count; ++ } ++ } ++ if (%d == 0 || count == %d) { ++ if (intervalBlockedId) { ++ clearInterval(intervalBlockedId); ++ intervalBlockedId = null; ++ } ++ chrome.test.sendScriptResult(count.toString()); ++ } ++ } ++ )}, 100))", ++ expected, expected); ++ return script; ++ }; + + constexpr char kBlockPopupScript[] = R"( + apiObject.addCustomFilter(%s'some-popup.html^$popup'); @@ -2048,31 +1807,39 @@ new file mode 100644 + chrome.test.sendScriptResult(''); + )"; + -+ const GURL test_url = embedded_test_server()->GetURL( -+ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ const GURL test_url = ++ embedded_test_server()->GetURL("example.com", "/test.html"); ++ constexpr char kOpenPopupScript[] = ++ "document.getElementById('popup_id').click()"; + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); + SetupApiObjectAndMethods(extension->id()); + -+ int initial_allowed_value = std::stoi( -+ ExecuteScriptInBackgroundPage(extension->id(), kReadAllowedStatsScript)); -+ int initial_blocked_value = std::stoi( -+ ExecuteScriptInBackgroundPage(extension->id(), kReadBlockedStatsScript)); ++ int initial_allowed_value = std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), read_allowed_stats_script(0))); ++ int initial_blocked_value = std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), read_blocked_stats_script(0))); + + ExecuteScriptInBackgroundPage( + extension->id(), + base::StringPrintf(kBlockPopupScript, IsOldApi() ? "" : "'adblock', ")); -+ ExecuteScript("window.open('some-popup.html');"); ++ ExecuteScript(kOpenPopupScript); + ASSERT_EQ(initial_blocked_value + 1, -+ std::stoi(ExecuteScriptInBackgroundPage(extension->id(), -+ kReadBlockedStatsScript))); ++ std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), ++ read_blocked_stats_script(initial_blocked_value + 1)))); + + ExecuteScriptInBackgroundPage( + extension->id(), + base::StringPrintf(kAllowPopupScript, IsOldApi() ? "" : "'adblock', ")); -+ ExecuteScript("window.open('some-popup.html');"); ++ ExecuteScript(kOpenPopupScript); + ASSERT_EQ(initial_allowed_value + 1, -+ std::stoi(ExecuteScriptInBackgroundPage(extension->id(), -+ kReadAllowedStatsScript))); ++ std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), ++ read_allowed_stats_script(initial_allowed_value + 1)))); ++ ASSERT_EQ(initial_blocked_value + 1, ++ std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), ++ read_blocked_stats_script(initial_blocked_value + 1)))); +} + +INSTANTIATE_TEST_SUITE_P( @@ -2359,7 +2126,7 @@ diff --git a/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering_private_api.cc -@@ -0,0 +1,738 @@ +@@ -0,0 +1,770 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -2529,10 +2296,11 @@ new file mode 100644 + const std::vector& parent_frame_urls, + adblock::ContentType content_type, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { ++ const GURL& subscription, ++ const std::string& configuration_name) override { + std::unique_ptr event; -+ api::eyeo_filtering_private::RequestInfo info = -+ CreateRequestInfoObject(url, subscription, render_frame_host); ++ api::eyeo_filtering_private::RequestInfo info = CreateRequestInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = adblock::utils::ConvertURLs(parent_frame_urls); + info.content_type = adblock::ContentTypeToString(content_type); + @@ -2554,9 +2322,10 @@ new file mode 100644 + + void OnPageAllowed(const GURL& url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { -+ api::eyeo_filtering_private::RequestInfo info = -+ CreateRequestInfoObject(url, subscription, render_frame_host); ++ const GURL& subscription, ++ const std::string& configuration_name) override { ++ api::eyeo_filtering_private::RequestInfo info = CreateRequestInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = std::vector{}; + info.content_type = ""; + @@ -2572,10 +2341,11 @@ new file mode 100644 + adblock::FilterMatchResult match_result, + const GURL& opener_url, + content::RenderFrameHost* render_frame_host, -+ const GURL& subscription) override { ++ const GURL& subscription, ++ const std::string& configuration_name) override { + std::unique_ptr event; -+ api::eyeo_filtering_private::RequestInfo info = -+ CreateRequestInfoObject(url, subscription, render_frame_host); ++ api::eyeo_filtering_private::RequestInfo info = CreateRequestInfoObject( ++ url, subscription, configuration_name, render_frame_host); + info.parent_frame_urls = std::vector{opener_url.spec()}; + info.content_type = ""; + @@ -2652,11 +2422,13 @@ new file mode 100644 + api::eyeo_filtering_private::RequestInfo CreateRequestInfoObject( + const GURL& url, + const GURL& subscription, ++ const std::string& configuration_name, + content::RenderFrameHost* render_frame_host) { + DCHECK(render_frame_host); + api::eyeo_filtering_private::RequestInfo info; + info.url = url.spec(); + info.subscription = subscription.spec(); ++ info.configuration_name = configuration_name; + info.tab_id = api::tabs::TAB_ID_NONE; + info.window_id = SessionID::InvalidValue().id(); + const content::WebContents* wc = @@ -2744,10 +2516,10 @@ new file mode 100644 +namespace api { + +EyeoFilteringPrivateCreateConfigurationFunction:: -+ EyeoFilteringPrivateCreateConfigurationFunction() {} ++ EyeoFilteringPrivateCreateConfigurationFunction() = default; + +EyeoFilteringPrivateCreateConfigurationFunction:: -+ ~EyeoFilteringPrivateCreateConfigurationFunction() {} ++ ~EyeoFilteringPrivateCreateConfigurationFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateCreateConfigurationFunction::Run() { @@ -2774,11 +2546,38 @@ new file mode 100644 + return RespondNow(NoArguments()); +} + -+EyeoFilteringPrivateGetConfigurationsFunction:: -+ EyeoFilteringPrivateGetConfigurationsFunction() {} ++EyeoFilteringPrivateRemoveConfigurationFunction:: ++ EyeoFilteringPrivateRemoveConfigurationFunction() = default; ++ ++EyeoFilteringPrivateRemoveConfigurationFunction:: ++ ~EyeoFilteringPrivateRemoveConfigurationFunction() = default; ++ ++ExtensionFunction::ResponseAction ++EyeoFilteringPrivateRemoveConfigurationFunction::Run() { ++ absl::optional ++ params(api::eyeo_filtering_private::RemoveConfiguration::Params::Create( ++ args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto* subscription_service = ++ adblock::SubscriptionServiceFactory::GetForBrowserContext( ++ browser_context()); ++ const auto installed_configurations = ++ subscription_service->GetInstalledFilteringConfigurations(); ++ auto configuration_it = ++ base::ranges::find(installed_configurations, params->config_name, ++ &adblock::FilteringConfiguration::GetName); ++ if (configuration_it != installed_configurations.end()) { ++ subscription_service->UninstallFilteringConfiguration( ++ (*configuration_it)->GetName()); ++ } ++ return RespondNow(NoArguments()); ++} + +EyeoFilteringPrivateGetConfigurationsFunction:: -+ ~EyeoFilteringPrivateGetConfigurationsFunction() {} ++ EyeoFilteringPrivateGetConfigurationsFunction() = default; ++ ++EyeoFilteringPrivateGetConfigurationsFunction:: ++ ~EyeoFilteringPrivateGetConfigurationsFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetConfigurationsFunction::Run() { @@ -2799,10 +2598,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateSetEnabledFunction:: -+ EyeoFilteringPrivateSetEnabledFunction() {} ++ EyeoFilteringPrivateSetEnabledFunction() = default; + +EyeoFilteringPrivateSetEnabledFunction:: -+ ~EyeoFilteringPrivateSetEnabledFunction() {} ++ ~EyeoFilteringPrivateSetEnabledFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateSetEnabledFunction::Run() { @@ -2823,7 +2622,7 @@ new file mode 100644 +} + +EyeoFilteringPrivateIsEnabledFunction:: -+ ~EyeoFilteringPrivateIsEnabledFunction() {} ++ ~EyeoFilteringPrivateIsEnabledFunction() = default; + +ExtensionFunction::ResponseAction EyeoFilteringPrivateIsEnabledFunction::Run() { + absl::optional params( @@ -2841,10 +2640,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateGetAcceptableAdsUrlFunction:: -+ EyeoFilteringPrivateGetAcceptableAdsUrlFunction() {} ++ EyeoFilteringPrivateGetAcceptableAdsUrlFunction() = default; + +EyeoFilteringPrivateGetAcceptableAdsUrlFunction:: -+ ~EyeoFilteringPrivateGetAcceptableAdsUrlFunction() {} ++ ~EyeoFilteringPrivateGetAcceptableAdsUrlFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetAcceptableAdsUrlFunction::Run() { @@ -2854,10 +2653,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateSubscribeToFilterListFunction:: -+ EyeoFilteringPrivateSubscribeToFilterListFunction() {} ++ EyeoFilteringPrivateSubscribeToFilterListFunction() = default; + +EyeoFilteringPrivateSubscribeToFilterListFunction:: -+ ~EyeoFilteringPrivateSubscribeToFilterListFunction() {} ++ ~EyeoFilteringPrivateSubscribeToFilterListFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateSubscribeToFilterListFunction::Run() { @@ -2882,10 +2681,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateUnsubscribeFromFilterListFunction:: -+ EyeoFilteringPrivateUnsubscribeFromFilterListFunction() {} ++ EyeoFilteringPrivateUnsubscribeFromFilterListFunction() = default; + +EyeoFilteringPrivateUnsubscribeFromFilterListFunction:: -+ ~EyeoFilteringPrivateUnsubscribeFromFilterListFunction() {} ++ ~EyeoFilteringPrivateUnsubscribeFromFilterListFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateUnsubscribeFromFilterListFunction::Run() { @@ -2910,10 +2709,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateGetFilterListsFunction:: -+ EyeoFilteringPrivateGetFilterListsFunction() {} ++ EyeoFilteringPrivateGetFilterListsFunction() = default; + +EyeoFilteringPrivateGetFilterListsFunction:: -+ ~EyeoFilteringPrivateGetFilterListsFunction() {} ++ ~EyeoFilteringPrivateGetFilterListsFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetFilterListsFunction::Run() { @@ -2936,10 +2735,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateAddAllowedDomainFunction:: -+ EyeoFilteringPrivateAddAllowedDomainFunction() {} ++ EyeoFilteringPrivateAddAllowedDomainFunction() = default; + +EyeoFilteringPrivateAddAllowedDomainFunction:: -+ ~EyeoFilteringPrivateAddAllowedDomainFunction() {} ++ ~EyeoFilteringPrivateAddAllowedDomainFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateAddAllowedDomainFunction::Run() { @@ -2957,10 +2756,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateRemoveAllowedDomainFunction:: -+ EyeoFilteringPrivateRemoveAllowedDomainFunction() {} ++ EyeoFilteringPrivateRemoveAllowedDomainFunction() = default; + +EyeoFilteringPrivateRemoveAllowedDomainFunction:: -+ ~EyeoFilteringPrivateRemoveAllowedDomainFunction() {} ++ ~EyeoFilteringPrivateRemoveAllowedDomainFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateRemoveAllowedDomainFunction::Run() { @@ -2979,10 +2778,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateGetAllowedDomainsFunction:: -+ EyeoFilteringPrivateGetAllowedDomainsFunction() {} ++ EyeoFilteringPrivateGetAllowedDomainsFunction() = default; + +EyeoFilteringPrivateGetAllowedDomainsFunction:: -+ ~EyeoFilteringPrivateGetAllowedDomainsFunction() {} ++ ~EyeoFilteringPrivateGetAllowedDomainsFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetAllowedDomainsFunction::Run() { @@ -3001,10 +2800,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateAddCustomFilterFunction:: -+ EyeoFilteringPrivateAddCustomFilterFunction() {} ++ EyeoFilteringPrivateAddCustomFilterFunction() = default; + +EyeoFilteringPrivateAddCustomFilterFunction:: -+ ~EyeoFilteringPrivateAddCustomFilterFunction() {} ++ ~EyeoFilteringPrivateAddCustomFilterFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateAddCustomFilterFunction::Run() { @@ -3022,10 +2821,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateRemoveCustomFilterFunction:: -+ EyeoFilteringPrivateRemoveCustomFilterFunction() {} ++ EyeoFilteringPrivateRemoveCustomFilterFunction() = default; + +EyeoFilteringPrivateRemoveCustomFilterFunction:: -+ ~EyeoFilteringPrivateRemoveCustomFilterFunction() {} ++ ~EyeoFilteringPrivateRemoveCustomFilterFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateRemoveCustomFilterFunction::Run() { @@ -3060,16 +2859,16 @@ new file mode 100644 +} + +EyeoFilteringPrivateGetCustomFiltersFunction:: -+ EyeoFilteringPrivateGetCustomFiltersFunction() {} ++ EyeoFilteringPrivateGetCustomFiltersFunction() = default; + +EyeoFilteringPrivateGetCustomFiltersFunction:: -+ ~EyeoFilteringPrivateGetCustomFiltersFunction() {} ++ ~EyeoFilteringPrivateGetCustomFiltersFunction() = default; + +EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction:: -+ EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction() {} ++ EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction() = default; + +EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction:: -+ ~EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction() {} ++ ~EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetSessionAllowedRequestsCountFunction::Run() { @@ -3082,10 +2881,10 @@ new file mode 100644 +} + +EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction:: -+ EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction() {} ++ EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction() = default; + +EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction:: -+ ~EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction() {} ++ ~EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction() = default; + +ExtensionFunction::ResponseAction +EyeoFilteringPrivateGetSessionBlockedRequestsCountFunction::Run() { @@ -3102,7 +2901,7 @@ diff --git a/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering_private_api.h -@@ -0,0 +1,342 @@ +@@ -0,0 +1,360 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -3180,6 +2979,24 @@ new file mode 100644 + const EyeoFilteringPrivateCreateConfigurationFunction&) = delete; +}; + ++class EyeoFilteringPrivateRemoveConfigurationFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("eyeoFilteringPrivate.removeConfiguration", ++ UNKNOWN) ++ EyeoFilteringPrivateRemoveConfigurationFunction(); ++ ++ private: ++ ~EyeoFilteringPrivateRemoveConfigurationFunction() override; ++ ++ ResponseAction Run() override; ++ ++ EyeoFilteringPrivateRemoveConfigurationFunction( ++ const EyeoFilteringPrivateRemoveConfigurationFunction&) = delete; ++ EyeoFilteringPrivateRemoveConfigurationFunction& operator=( ++ const EyeoFilteringPrivateRemoveConfigurationFunction&) = delete; ++}; ++ +class EyeoFilteringPrivateGetConfigurationsFunction : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("eyeoFilteringPrivate.getConfigurations", UNKNOWN) @@ -3449,7 +3266,7 @@ diff --git a/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering new file mode 100644 --- /dev/null +++ b/chrome/browser/extensions/api/eyeo_filtering_private/eyeo_filtering_private_apitest.cc -@@ -0,0 +1,154 @@ +@@ -0,0 +1,155 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -3521,13 +3338,14 @@ new file mode 100644 +}; + +IN_PROC_BROWSER_TEST_P(EyeoFilteringPrivateApiTest, -+ CreateAndGetConfigurations) { -+ EXPECT_TRUE(RunTest("createAndGetConfigurations")) << message_; ++ CreateRemoveAndGetConfigurations) { ++ EXPECT_TRUE(RunTest("createRemoveAndGetConfigurations")) << message_; +} + +IN_PROC_BROWSER_TEST_P(EyeoFilteringPrivateApiTest, -+ CreateAndGetConfigurationsWithPromises) { -+ EXPECT_TRUE(RunTest("createAndGetConfigurationsWithPromises")) << message_; ++ CreateRemoveAndGetConfigurationsWithPromises) { ++ EXPECT_TRUE(RunTest("createRemoveAndGetConfigurationsWithPromises")) ++ << message_; +} + +IN_PROC_BROWSER_TEST_P(EyeoFilteringPrivateApiTest, @@ -3626,22 +3444,22 @@ diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chro #include "components/autofill/core/common/autofill_prefs.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/browsing_data/core/pref_names.h" -@@ -175,6 +180,20 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { +@@ -176,6 +181,20 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { return *s_allowlist; s_allowlist = new PrefsUtil::TypedPrefMap(); + // Adblock settings -+ (*s_allowlist)[adblock::prefs::kEnableAdblockLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kEnableAdblockLegacy] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; -+ (*s_allowlist)[adblock::prefs::kEnableAcceptableAdsLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kEnableAcceptableAdsLegacy] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; -+ (*s_allowlist)[adblock::prefs::kAdblockSubscriptionsLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kAdblockSubscriptionsLegacy] = + settings_api::PrefType::PREF_TYPE_LIST; -+ (*s_allowlist)[adblock::prefs::kAdblockCustomSubscriptionsLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kAdblockCustomSubscriptionsLegacy] = + settings_api::PrefType::PREF_TYPE_LIST; -+ (*s_allowlist)[adblock::prefs::kAdblockAllowedDomainsLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kAdblockAllowedDomainsLegacy] = + settings_api::PrefType::PREF_TYPE_LIST; -+ (*s_allowlist)[adblock::prefs::kAdblockCustomFiltersLegacy] = ++ (*s_allowlist)[adblock::common::prefs::kAdblockCustomFiltersLegacy] = + settings_api::PrefType::PREF_TYPE_LIST; + // Miscellaneous @@ -3719,7 +3537,7 @@ diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/ext "app": { "blocklist": [ "2FC374607C2DF285634B67C64A2E356C607091C3", // Quickoffice -@@ -487,6 +501,16 @@ +@@ -487,6 +501,14 @@ "channel": "stable", "contexts": [] }, @@ -3729,9 +3547,7 @@ diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/ext + }, { + "channel": "stable", + "contexts": ["webui"], -+ "matches": [ -+ "chrome://settings/*" -+ ] ++ "matches": ["chrome://settings/*"] + }], "fileBrowserHandler": { "dependencies": ["permission:fileBrowserHandler"], @@ -3761,7 +3577,7 @@ diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/com "autofillPrivate": { "channel": "trunk", "extension_types": ["extension", "platform_app"], -@@ -337,6 +345,10 @@ +@@ -333,6 +341,10 @@ "extension", "legacy_packaged_app", "hosted_app", "platform_app" ] }, @@ -3776,7 +3592,7 @@ diff --git a/chrome/common/extensions/api/adblock_private.idl b/chrome/common/ex new file mode 100644 --- /dev/null +++ b/chrome/common/extensions/api/adblock_private.idl -@@ -0,0 +1,197 @@ +@@ -0,0 +1,174 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -3795,6 +3611,10 @@ new file mode 100644 +// DEPRECATED: Prefer eyeoFilteringPrivate. +// adblockPrivate API. +// This is a private API exposing ability to control AdblockPlus. ++// ++// Devs: when modifying this file, ensure you update ++// tools/typescript/definitions/adblock_private.d.ts as well. ++// See DPD-1870 for more information. +namespace adblockPrivate { + +dictionary BuiltInSubscription { @@ -3838,6 +3658,8 @@ new file mode 100644 + DOMString[] parent_frame_urls; + // URL of subscription having the filter which matched for the ad. + DOMString subscription; ++ // Configuration name containing subscription with matched filer. ++ DOMString configuration_name; + // A string representation of matched ad's resource type. + // Possible values are: + // - "SCRIPT" @@ -3880,35 +3702,6 @@ new file mode 100644 + static void isAcceptableAdsEnabled(StateCallback callback); + // Gets the list of built-in subscriptions. + static void getBuiltInSubscriptions(BuiltInSubscriptionsCallback callback); -+ // Returns a list of built-in subscriptions a user is subscribed to. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use getInstalledSubscriptions() instead"] -+ static void getSelectedBuiltInSubscriptions(SubscriptionsCallback callback); -+ // Subscribes to a built-in subscription. -+ // |url| must be one from the built-in subscriptions list. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use installSubscription() instead"] -+ static void selectBuiltInSubscription(DOMString url, -+ optional CompletionCallback feedback); -+ // Unsubscribes from a built-in subscription. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use uninstallSubscription() instead"] -+ static void unselectBuiltInSubscription(DOMString url, -+ optional CompletionCallback feedback); -+ // Returns a list of custom subscriptions a user is subscribed to. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use getInstalledSubscriptions() instead"] -+ static void getCustomSubscriptions(SubscriptionsCallback callback); -+ // Subscribes to a custom subscription. |url| may point to any URL. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use installSubscription() instead"] -+ static void addCustomSubscription(DOMString url, -+ optional CompletionCallback feedback); -+ // Unsubscribes from a custom subscription. -+ // Deprecated, to be removed in version 115. -+ [deprecated="Use uninstallSubscription() instead"] -+ static void removeCustomSubscription(DOMString url, -+ optional CompletionCallback feedback); + // Adds a domain ads should not be blocked on. + static void addAllowedDomain(DOMString domain); + // Removes a domain ads should not be blocked on. @@ -4008,7 +3801,7 @@ diff --git a/chrome/common/extensions/api/eyeo_filtering_private.idl b/chrome/co new file mode 100644 --- /dev/null +++ b/chrome/common/extensions/api/eyeo_filtering_private.idl -@@ -0,0 +1,191 @@ +@@ -0,0 +1,201 @@ +// This file is part of eyeo Chromium SDK, +// Copyright (C) 2006-present eyeo GmbH +// @@ -4026,6 +3819,10 @@ new file mode 100644 + +// eyeoFilteringPrivate API. +// This is a private API exposing control over resource filtering. ++// ++// Devs: when modifying this file, ensure you update ++// tools/typescript/definitions/eyeo_filtering_private.d.ts as well. ++// See DPD-1870 for more information. +namespace eyeoFilteringPrivate { + + dictionary Subscription { @@ -4060,6 +3857,8 @@ new file mode 100644 + DOMString[] parent_frame_urls; + // URL of subscription having the filter which matched for the request. + DOMString subscription; ++ // Configuration name containing subscription with matched filer. ++ DOMString configuration_name; + // A string representation of matched request's resource type. + // Possible values are: + // - "SCRIPT" @@ -4099,6 +3898,10 @@ new file mode 100644 + // Creates new filtering configuration. It is a no-op call if configuration + // already exists. + static void createConfiguration(DOMString config_name); ++ // Removes existing configuration, no-op when configuration does not exist. ++ // Use it only when |configuration| is no longer needed, otherwise prefer ++ // to disable |configuration| using (ref:setEnabled). ++ static void removeConfiguration(DOMString config_name); + // Returns a list of existing configurations. + [supportsPromises] static void getConfigurations(ListCallback callback); + // Allows to turn filtering configuration on or off. @@ -4223,7 +4026,7 @@ diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/ch {APIPermissionID::kBackground, "background", APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning}, {APIPermissionID::kDeclarativeContent, "declarativeContent"}, -@@ -81,6 +87,8 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = { +@@ -80,6 +86,8 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = { {APIPermissionID::kEnterpriseNetworkingAttributes, "enterprise.networkingAttributes", APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning}, @@ -4246,7 +4049,7 @@ diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/c #include #include -@@ -862,6 +866,10 @@ TEST(PermissionsTest, PermissionMessages) { +@@ -860,6 +864,10 @@ TEST(PermissionsTest, PermissionMessages) { skip.insert(APIPermissionID::kWmDesksPrivate); skip.insert(APIPermissionID::kSystemLog); @@ -4260,16 +4063,16 @@ diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/c diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn -@@ -3355,6 +3355,12 @@ if (!is_android) { - "//chrome/browser/extensions/api:native_messaging_test_echo_&_host", +@@ -3493,6 +3493,12 @@ if (!is_android) { ] } -+ ### Desktop UI patch start + ++ ### Extension API module start + sources += [ + "../browser/extensions/api/adblock_private/adblock_private_apitest.cc", + "../browser/extensions/api/eyeo_filtering_private/eyeo_filtering_private_apitest.cc", + ] -+ ### Desktop UI patch end ++ ### Extension API module end if (is_chromeos_ash && enable_extensions) { deps += @@ -4363,11 +4166,40 @@ new file mode 100644 + "" + ] +} +diff --git a/chrome/test/data/extensions/api_test/adblock_private/some-popup.html b/chrome/test/data/extensions/api_test/adblock_private/some-popup.html +new file mode 100644 +--- /dev/null ++++ b/chrome/test/data/extensions/api_test/adblock_private/some-popup.html +@@ -0,0 +1,24 @@ ++ ++ ++ ++ Popup content ++ ++ ++

I am a popup

++ ++ diff --git a/chrome/test/data/extensions/api_test/adblock_private/test.html b/chrome/test/data/extensions/api_test/adblock_private/test.html new file mode 100644 --- /dev/null +++ b/chrome/test/data/extensions/api_test/adblock_private/test.html -@@ -0,0 +1,24 @@ +@@ -0,0 +1,25 @@ + -@@ -34793,7 +34796,7 @@ Called by update_extension_histograms.py.--> +@@ -35117,7 +35120,7 @@ Called by update_extension_histograms.py.--> @@ -5745,5 +5395,436 @@ diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums +diff --git a/tools/typescript/definitions/adblock_private.d.ts b/tools/typescript/definitions/adblock_private.d.ts +new file mode 100644 +--- /dev/null ++++ b/tools/typescript/definitions/adblock_private.d.ts +@@ -0,0 +1,172 @@ ++// This file is part of eyeo Chromium SDK, ++// Copyright (C) 2006-present eyeo GmbH ++// ++// eyeo Chromium SDK is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License version 3 as ++// published by the Free Software Foundation. ++// ++// eyeo Chromium SDK is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with eyeo Chromium SDK. If not, see . ++ ++/** @fileoverview Type definitions for chrome.adblockPrivate API. */ ++ ++import {ChromeEvent} from './chrome_event.js'; ++ ++declare global { ++ export namespace chrome { ++ export namespace adblockPrivate { ++ ++ export interface BuiltInSubscription { ++ url: string; ++ title: string; ++ languages: string[]; ++ } ++ ++ export interface Subscription { ++ url: string; ++ installation_state: string; ++ title: string; ++ current_version: string; ++ last_installation_time: string; ++ } ++ ++ export interface SessionStatsEntry { ++ url: string; ++ count: number; ++ } ++ ++ export interface AdInfo { ++ url: string; ++ parent_frame_urls: string[]; ++ subscription: string; ++ configuration_name: string; ++ content_type: string; ++ tab_id: number; ++ window_id: number; ++ } ++ ++ export const onAdAllowed: ChromeEvent<( ++ info: AdInfo, ++ ) => void>; ++ ++ export const onAdBlocked: ChromeEvent<( ++ info: AdInfo, ++ ) => void>; ++ ++ export const onPageAllowed: ChromeEvent<( ++ info: AdInfo, ++ ) => void>; ++ ++ export const onPopupBlocked: ChromeEvent<( ++ info: AdInfo, ++ ) => void>; ++ ++ export const onPopupAllowed: ChromeEvent<( ++ info: AdInfo, ++ ) => void>; ++ ++ export const onSubscriptionUpdated: ChromeEvent<( ++ subscription_url: string, ++ ) => void>; ++ ++ export const onEnabledStateChanged: ChromeEvent<( ++ ) => void>; ++ ++ export const onFilterListsChanged: ChromeEvent<( ++ ) => void>; ++ ++ export const onAllowedDomainsChanged: ChromeEvent<( ++ ) => void>; ++ ++ export const onCustomFiltersChanged: ChromeEvent<( ++ ) => void>; ++ ++ export function setEnabled( ++ enabled: boolean, ++ ): void; ++ ++ export function isEnabled( ++ callback: ( ++ result: boolean, ++ ) => void, ++ ): void; ++ ++ export function setAcceptableAdsEnabled( ++ enabled: boolean, ++ ): void; ++ ++ export function isAcceptableAdsEnabled( ++ callback: ( ++ result: boolean, ++ ) => void, ++ ): void; ++ ++ export function getBuiltInSubscriptions( ++ callback: ( ++ result: BuiltInSubscription[], ++ ) => void, ++ ): void; ++ ++ export function addAllowedDomain( ++ domain: string, ++ ): void; ++ ++ export function removeAllowedDomain( ++ domain: string, ++ ): void; ++ ++ export function getAllowedDomains( ++ callback: ( ++ result: string[], ++ ) => void, ++ ): void; ++ ++ export function addCustomFilter( ++ filter: string, ++ ): void; ++ ++ export function removeCustomFilter( ++ filter: string, ++ ): void; ++ ++ export function getCustomFilters( ++ callback: ( ++ result: string[], ++ ) => void, ++ ): void; ++ ++ export function getSessionAllowedAdsCount( ++ callback: ( ++ result: SessionStatsEntry[], ++ ) => void, ++ ): void; ++ ++ export function getSessionBlockedAdsCount( ++ callback: ( ++ result: SessionStatsEntry[], ++ ) => void, ++ ): void; ++ ++ export function getInstalledSubscriptions( ++ callback: ( ++ result: Subscription[], ++ ) => void, ++ ): void; ++ ++ export function installSubscription( ++ url: string, ++ feedback?: () => void, ++ ): void; ++ ++ export function uninstallSubscription( ++ url: string, ++ feedback?: () => void, ++ ): void; ++ } ++ } ++} +diff --git a/tools/typescript/definitions/eyeo_filtering_private.d.ts b/tools/typescript/definitions/eyeo_filtering_private.d.ts +new file mode 100644 +--- /dev/null ++++ b/tools/typescript/definitions/eyeo_filtering_private.d.ts +@@ -0,0 +1,249 @@ ++// This file is part of eyeo Chromium SDK, ++// Copyright (C) 2006-present eyeo GmbH ++// ++// eyeo Chromium SDK is free software: you can redistribute it and/or modify ++// it under the terms of the GNU General Public License version 3 as ++// published by the Free Software Foundation. ++// ++// eyeo Chromium SDK is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with eyeo Chromium SDK. If not, see . ++ ++/** @fileoverview Type definitions for chrome.eyeoFilteringPrivate API. */ ++ ++import {ChromeEvent} from './chrome_event.js'; ++ ++declare global { ++ export namespace chrome { ++ export namespace eyeoFilteringPrivate { ++ ++ export interface Subscription { ++ url: string; ++ installation_state: string; ++ title: string; ++ current_version: string; ++ last_installation_time: string; ++ } ++ ++ export interface SessionStatsEntry { ++ url: string; ++ count: number; ++ } ++ ++ export interface RequestInfo { ++ url: string; ++ parent_frame_urls: string[]; ++ subscription: string; ++ configuration_name: string; ++ content_type: string; ++ tab_id: number; ++ window_id: number; ++ } ++ ++ export const onRequestAllowed: ChromeEvent<( ++ info: RequestInfo, ++ ) => void>; ++ ++ export const onRequestBlocked: ChromeEvent<( ++ info: RequestInfo, ++ ) => void>; ++ ++ export const onPageAllowed: ChromeEvent<( ++ info: RequestInfo, ++ ) => void>; ++ ++ export const onPopupBlocked: ChromeEvent<( ++ info: RequestInfo, ++ ) => void>; ++ ++ export const onPopupAllowed: ChromeEvent<( ++ info: RequestInfo, ++ ) => void>; ++ ++ export const onSubscriptionUpdated: ChromeEvent<( ++ subscription_url: string, ++ ) => void>; ++ ++ export const onEnabledStateChanged: ChromeEvent<( ++ config_name: string, ++ ) => void>; ++ ++ export const onFilterListsChanged: ChromeEvent<( ++ config_name: string, ++ ) => void>; ++ ++ export const onAllowedDomainsChanged: ChromeEvent<( ++ config_name: string, ++ ) => void>; ++ ++ export const onCustomFiltersChanged: ChromeEvent<( ++ config_name: string, ++ ) => void>; ++ ++ export function createConfiguration( ++ config_name: string, ++ ): void; ++ ++ export function removeConfiguration( ++ config_name: string, ++ ): void; ++ ++ export function getConfigurations(): Promise; ++ ++ export function getConfigurations( ++ callback?: ( ++ result: string[], ++ ) => void, ++ ): void; ++ ++ export function setEnabled( ++ configuration: string, ++ enabled: boolean, ++ ): Promise; ++ ++ export function setEnabled( ++ configuration: string, ++ enabled: boolean, ++ status?: () => void, ++ ): void; ++ ++ export function isEnabled( ++ configuration: string, ++ ): Promise; ++ ++ export function isEnabled( ++ configuration: string, ++ callback?: ( ++ result: boolean, ++ ) => void, ++ ): void; ++ ++ export function addAllowedDomain( ++ configuration: string, ++ domain: string, ++ ): Promise; ++ ++ export function addAllowedDomain( ++ configuration: string, ++ domain: string, ++ status?: () => void, ++ ): void; ++ ++ export function removeAllowedDomain( ++ configuration: string, ++ domain: string, ++ ): Promise; ++ ++ export function removeAllowedDomain( ++ configuration: string, ++ domain: string, ++ status?: () => void, ++ ): void; ++ ++ export function getAllowedDomains( ++ configuration: string, ++ ): Promise; ++ ++ export function getAllowedDomains( ++ configuration: string, ++ callback?: ( ++ result: string[], ++ ) => void, ++ ): void; ++ ++ export function addCustomFilter( ++ configuration: string, ++ filter: string, ++ ): Promise; ++ ++ export function addCustomFilter( ++ configuration: string, ++ filter: string, ++ status?: () => void, ++ ): void; ++ ++ export function removeCustomFilter( ++ configuration: string, ++ filter: string, ++ ): Promise; ++ ++ export function removeCustomFilter( ++ configuration: string, ++ filter: string, ++ status?: () => void, ++ ): void; ++ ++ export function getCustomFilters( ++ configuration: string, ++ ): Promise; ++ ++ export function getCustomFilters( ++ configuration: string, ++ callback?: ( ++ result: string[], ++ ) => void, ++ ): void; ++ ++ export function getFilterLists( ++ configuration: string, ++ ): Promise; ++ ++ export function getFilterLists( ++ configuration: string, ++ callback?: ( ++ result: Subscription[], ++ ) => void, ++ ): void; ++ ++ export function subscribeToFilterList( ++ configuration: string, ++ url: string, ++ ): Promise; ++ ++ export function subscribeToFilterList( ++ configuration: string, ++ url: string, ++ status?: () => void, ++ ): void; ++ ++ export function unsubscribeFromFilterList( ++ configuration: string, ++ url: string, ++ ): Promise; ++ ++ export function unsubscribeFromFilterList( ++ configuration: string, ++ url: string, ++ status?: () => void, ++ ): void; ++ ++ export function getSessionAllowedRequestsCount(): Promise; ++ ++ export function getSessionAllowedRequestsCount( ++ callback?: ( ++ result: SessionStatsEntry[], ++ ) => void, ++ ): void; ++ ++ export function getSessionBlockedRequestsCount(): Promise; ++ ++ export function getSessionBlockedRequestsCount( ++ callback?: ( ++ result: SessionStatsEntry[], ++ ) => void, ++ ): void; ++ ++ export function getAcceptableAdsUrl(): Promise; ++ ++ export function getAcceptableAdsUrl( ++ callback?: ( ++ result: string, ++ ) => void, ++ ): void; ++ } ++ } ++} -- 2.25.1 diff --git a/build/patches/first_run-deactivate-autoupdate-globally.patch b/build/patches/first_run-deactivate-autoupdate-globally.patch index 2fc7f89e..f40794c4 100644 --- a/build/patches/first_run-deactivate-autoupdate-globally.patch +++ b/build/patches/first_run-deactivate-autoupdate-globally.patch @@ -17,7 +17,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc --- a/chrome/browser/extensions/extension_system_impl.cc +++ b/chrome/browser/extensions/extension_system_impl.cc -@@ -201,8 +201,7 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { +@@ -198,8 +198,7 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { user_script_manager_ = std::make_unique(profile_); diff --git a/build/patches/kill-Vision.patch b/build/patches/kill-Vision.patch index 2e9eca86..fac76ee6 100644 --- a/build/patches/kill-Vision.patch +++ b/build/patches/kill-Vision.patch @@ -15,7 +15,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -280,8 +280,6 @@ if (current_toolchain == default_toolchain) { +@@ -288,8 +288,6 @@ if (current_toolchain == default_toolchain) { "$google_play_services_package:google_play_services_gcm_java", "$google_play_services_package:google_play_services_iid_java", "$google_play_services_package:google_play_services_tasks_java", @@ -27,7 +27,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn --- a/services/shape_detection/BUILD.gn +++ b/services/shape_detection/BUILD.gn -@@ -111,21 +111,13 @@ if (is_android) { +@@ -110,21 +110,13 @@ if (is_android) { android_library("shape_detection_java") { sources = [ diff --git a/build/patches/openH264-enable-ARM-ARM64-optimizations.patch b/build/patches/openH264-enable-ARM-ARM64-optimizations.patch index 7685c84f..8050fe4f 100644 --- a/build/patches/openH264-enable-ARM-ARM64-optimizations.patch +++ b/build/patches/openH264-enable-ARM-ARM64-optimizations.patch @@ -7,25 +7,24 @@ Limit threads auto-detect only for iOS License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../modules/mediarecorder/h264_encoder.cc | 8 +++---- + .../modules/mediarecorder/h264_encoder.cc | 6 ++--- third_party/openh264/BUILD.gn | 24 ++++++++++++++----- - 2 files changed, 22 insertions(+), 10 deletions(-) + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc --- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc -@@ -212,11 +212,11 @@ bool H264Encoder::ConfigureEncoder(const gfx::Size& size) { +@@ -223,11 +223,11 @@ bool H264Encoder::ConfigureEncoder(const gfx::Size& size) { init_params.iRCMode = RC_OFF_MODE; } -#if BUILDFLAG(IS_CHROMEOS) - init_params.iMultipleThreadIdc = 0; -+#if BUILDFLAG(OS_MACOSX) -+ // Threading model: Set to 1 due to https://crbug.com/583348. -+ init_params.iMultipleThreadIdc = 1; - #else -- // Threading model: Set to 1 due to https://crbug.com/583348. -- init_params.iMultipleThreadIdc = 1; +-#else ++#if BUILDFLAG(IS_MAC) + // Threading model: Set to 1 due to https://crbug.com/583348. + init_params.iMultipleThreadIdc = 1; ++#else + init_params.iMultipleThreadIdc = 0; #endif diff --git a/build/patches/ungoogled-chromium-Disable-profile-avatar.patch b/build/patches/ungoogled-chromium-Disable-profile-avatar.patch index a793cd5b..64b43d7f 100644 --- a/build/patches/ungoogled-chromium-Disable-profile-avatar.patch +++ b/build/patches/ungoogled-chromium-Disable-profile-avatar.patch @@ -6,14 +6,15 @@ Added some Bromite-specific further improvements License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/browser/BUILD.gn | 2 -- - chrome/browser/profiles/profile_attributes_entry.cc | 6 ------ - 2 files changed, 8 deletions(-) + chrome/browser/BUILD.gn | 2 -- + chrome/browser/profiles/profile_attributes_entry.cc | 6 ------ + chrome/browser/profiles/profile_attributes_storage.cc | 2 +- + 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -1423,8 +1423,6 @@ static_library("browser") { +@@ -1448,8 +1448,6 @@ static_library("browser") { "profiles/profile_attributes_storage.cc", "profiles/profile_attributes_storage.h", "profiles/profile_attributes_storage_observer.h", @@ -38,5 +39,17 @@ diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browse #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) // TODO(crbug.com/1100835): After launch, remove the treatment of placeholder // avatars from GetHighResAvatar() and from any other places. +diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc +--- a/chrome/browser/profiles/profile_attributes_storage.cc ++++ b/chrome/browser/profiles/profile_attributes_storage.cc +@@ -973,7 +973,7 @@ void ProfileAttributesStorage::DownloadHighResAvatarIfNeeded( + void ProfileAttributesStorage::DownloadHighResAvatar( + size_t icon_index, + const base::FilePath& profile_path) { +-#if !BUILDFLAG(IS_ANDROID) ++#if false + const char* file_name = + profiles::GetDefaultAvatarIconFileNameAtIndex(icon_index); + DCHECK(file_name); -- 2.25.1 diff --git a/build/patches/ungoogled-chromium-Disable-translate-integration.patch b/build/patches/ungoogled-chromium-Disable-translate-integration.patch index 4ee2d6db..03b6fc62 100644 --- a/build/patches/ungoogled-chromium-Disable-translate-integration.patch +++ b/build/patches/ungoogled-chromium-Disable-translate-integration.patch @@ -94,7 +94,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse private static final String TAG = "LanguageSettings"; -@@ -107,27 +101,6 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -106,27 +100,6 @@ public class LanguageSettings extends PreferenceFragmentCompat ContentLanguagesPreference mLanguageListPref = (ContentLanguagesPreference) findPreference(PREFERRED_LANGUAGES_KEY); mLanguageListPref.registerActivityLauncher(this); @@ -122,7 +122,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse } /** -@@ -142,8 +115,6 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -141,8 +114,6 @@ public class LanguageSettings extends PreferenceFragmentCompat ContentLanguagesPreference mLanguageListPref = (ContentLanguagesPreference) findPreference(CONTENT_LANGUAGES_KEY); mLanguageListPref.registerActivityLauncher(this); @@ -131,7 +131,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse } /** -@@ -173,7 +144,7 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -172,7 +143,7 @@ public class LanguageSettings extends PreferenceFragmentCompat * @param contentLanguagesPreference ContentLanguagesPreference reference to update about state * changes. */ @@ -140,7 +140,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse // Setup expandable advanced settings section. PreferenceCategory translationAdvancedSection = (PreferenceCategory) findPreference(TRANSLATION_ADVANCED_SECTION); -@@ -235,9 +206,7 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -234,9 +205,7 @@ public class LanguageSettings extends PreferenceFragmentCompat return true; } }); @@ -151,7 +151,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse @Override public void onStart() { -@@ -275,12 +244,6 @@ public class LanguageSettings extends PreferenceFragmentCompat +@@ -274,12 +243,6 @@ public class LanguageSettings extends PreferenceFragmentCompat // Set the default target language to match the new app language. TranslateBridge.setDefaultTargetLanguage(code); } else if (requestCode == REQUEST_CODE_CHANGE_TARGET_LANGUAGE) { @@ -167,7 +167,7 @@ diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browse diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1790,9 +1790,6 @@ Your Google account may have other forms of browsing history like searches and a +@@ -1826,9 +1826,6 @@ Your Google account may have other forms of browsing history like searches and a Websites will show text in your preferred language, when possible. @@ -180,7 +180,7 @@ diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chro diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc -@@ -834,8 +834,9 @@ void TranslateManager::FilterIsTranslatePossible( +@@ -825,8 +825,9 @@ void TranslateManager::FilterIsTranslatePossible( TriggerDecision::kDisabledOffline); } diff --git a/build/patches/ungoogled-chromium-Disable-untraceable-URLs.patch b/build/patches/ungoogled-chromium-Disable-untraceable-URLs.patch index 007dbd07..b2917ef2 100644 --- a/build/patches/ungoogled-chromium-Disable-untraceable-URLs.patch +++ b/build/patches/ungoogled-chromium-Disable-untraceable-URLs.patch @@ -7,10 +7,10 @@ Disable additional URLs that are not caught by the "trk" scheme License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- chrome/browser/android/rlz/rlz_ping_handler.cc | 2 +- - rlz/lib/financial_ping.cc | 4 ++-- + rlz/lib/financial_ping.cc | 5 +++-- rlz/lib/lib_values.cc | 1 - rlz/lib/lib_values.h | 1 - - 4 files changed, 3 insertions(+), 5 deletions(-) + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/chrome/browser/android/rlz/rlz_ping_handler.cc b/chrome/browser/android/rlz/rlz_ping_handler.cc --- a/chrome/browser/android/rlz/rlz_ping_handler.cc @@ -27,18 +27,24 @@ diff --git a/chrome/browser/android/rlz/rlz_ping_handler.cc b/chrome/browser/and diff --git a/rlz/lib/financial_ping.cc b/rlz/lib/financial_ping.cc --- a/rlz/lib/financial_ping.cc +++ b/rlz/lib/financial_ping.cc -@@ -336,7 +336,7 @@ FinancialPing::PingResponse FinancialPing::PingServer(const char* request, +@@ -237,6 +237,7 @@ bool FinancialPing::SetURLLoaderFactory( - // Open network connection. - InternetHandle connection_handle = InternetConnectA(inet_handle, -- kFinancialServer, kFinancialPort, "", "", INTERNET_SERVICE_HTTP, -+ "about:blank", kFinancialPort, "", "", INTERNET_SERVICE_HTTP, - INTERNET_FLAG_NO_CACHE_WRITE, 0); - if (!connection_handle) + void PingRlzServer(std::string url, + scoped_refptr event) { ++ if ((true)) return; + // Copy the pointer to stack because g_URLLoaderFactory may be set to NULL + // in different thread. The instance is guaranteed to exist while + // the method is running. +@@ -293,13 +294,13 @@ void PingRlzServer(std::string url, + + FinancialPing::PingResponse FinancialPing::PingServer(const char* request, + std::string* response) { +- if (!response) ++ if ((true)) return PING_FAILURE; -@@ -380,7 +380,7 @@ FinancialPing::PingResponse FinancialPing::PingServer(const char* request, - return PING_SUCCESSFUL; - #else + + response->clear(); + std::string url = - base::StringPrintf("https://%s%s", kFinancialServer, request); + base::StringPrintf("about:blank"); diff --git a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch index 28873f6c..2dfb9dc5 100644 --- a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch +++ b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch @@ -34,7 +34,6 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../webui/settings/reset_settings_handler.cc | 1 - .../upgrade_detector/upgrade_detector_impl.cc | 2 +- chrome/common/BUILD.gn | 2 - - chrome/common/chrome_features.cc | 6 +- .../google_accounts_private_api_util.cc | 1 + .../url_loader_throttle_provider_impl.cc | 11 - chrome/test/BUILD.gn | 1 - @@ -58,12 +57,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html content/public/common/content_features.cc | 12 +- net/base/url_util.cc | 21 -- services/network/network_context.cc | 2 +- - 51 files changed, 64 insertions(+), 801 deletions(-) + 50 files changed, 61 insertions(+), 798 deletions(-) diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -1000,10 +1000,6 @@ static_library("browser") { +@@ -1029,10 +1029,6 @@ static_library("browser") { "page_load_metrics/observers/foreground_duration_ukm_observer.h", "page_load_metrics/observers/formfill_page_load_metrics_observer.cc", "page_load_metrics/observers/formfill_page_load_metrics_observer.h", @@ -74,7 +73,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "page_load_metrics/observers/histogram_suffixes.cc", "page_load_metrics/observers/histogram_suffixes.h", "page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc", -@@ -1894,7 +1890,6 @@ static_library("browser") { +@@ -1922,7 +1918,6 @@ static_library("browser") { "//chrome/browser/autofill", "//chrome/browser/devtools", "//chrome/browser/favicon", @@ -82,7 +81,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "//chrome/browser/profiling_host", # TODO(crbug.com/1335199): break this dep when favicon is in its own target -@@ -1918,7 +1913,6 @@ static_library("browser") { +@@ -1946,7 +1941,6 @@ static_library("browser") { public_deps = [ "//base", @@ -90,7 +89,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "//chrome/browser/headless", "//chrome/common", "//chrome/common:buildflags", -@@ -7557,8 +7551,6 @@ static_library("browser") { +@@ -7670,8 +7664,6 @@ static_library("browser") { "supervised_user/kids_chrome_management/kids_profile_manager.h", "supervised_user/supervised_user_browser_utils.cc", "supervised_user/supervised_user_browser_utils.h", @@ -102,7 +101,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn diff --git a/chrome/browser/android/metrics/uma_session_stats.cc b/chrome/browser/android/metrics/uma_session_stats.cc --- a/chrome/browser/android/metrics/uma_session_stats.cc +++ b/chrome/browser/android/metrics/uma_session_stats.cc -@@ -257,16 +257,6 @@ static void JNI_UmaSessionStats_ChangeMetricsReportingConsent( +@@ -256,16 +256,6 @@ static void JNI_UmaSessionStats_ChangeMetricsReportingConsent( jint called_from) { UpdateMetricsPrefsOnPermissionChange( consent, static_cast(called_from)); @@ -159,7 +158,7 @@ diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/br diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc -@@ -1098,7 +1098,6 @@ BrowserProcessImpl::component_updater() { +@@ -1120,7 +1120,6 @@ BrowserProcessImpl::component_updater() { std::make_unique(); std::string brand; @@ -170,7 +169,7 @@ diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_pro diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -2919,7 +2919,6 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( +@@ -2939,7 +2939,6 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( switches::kForcePNaClSubzero, #endif switches::kForceUIDirection, @@ -178,8 +177,8 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch switches::kJavaScriptHarmony, switches::kEnableExperimentalWebAssemblyFeatures, embedder_support::kOriginTrialDisabledFeatures, -@@ -4975,12 +4974,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( - &throttles); +@@ -5058,12 +5057,6 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( + } #endif -#if BUILDFLAG(ENABLE_SUPERVISED_USERS) @@ -191,7 +190,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch if (auto* throttle_manager = subresource_filter::ContentSubresourceFilterThrottleManager:: FromNavigationHandle(*handle)) { -@@ -5514,7 +5507,8 @@ GetClientDataHeader(int frame_tree_node_id) { +@@ -5584,7 +5577,8 @@ GetClientDataHeader(int frame_tree_node_id) { } #endif @@ -201,7 +200,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch #if BUILDFLAG(IS_ANDROID) const std::string& client_data_header, #endif -@@ -5553,7 +5547,7 @@ std::unique_ptr CreateGoogleURLLoaderThrottle( +@@ -5623,7 +5617,7 @@ std::unique_ptr CreateGoogleURLLoaderThrottle( std::move(bound_session_request_throttled_listener), #endif std::move(dynamic_params)); @@ -210,7 +209,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch std::vector> ChromeContentBrowserClient::CreateURLLoaderThrottles( -@@ -5599,15 +5593,6 @@ ChromeContentBrowserClient::CreateURLLoaderThrottles( +@@ -5669,15 +5663,6 @@ ChromeContentBrowserClient::CreateURLLoaderThrottles( GetClientDataHeader(frame_tree_node_id); #endif @@ -226,7 +225,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch { auto* factory = ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context); -@@ -5661,20 +5646,6 @@ ChromeContentBrowserClient::CreateURLLoaderThrottlesForKeepAlive( +@@ -5731,20 +5716,6 @@ ChromeContentBrowserClient::CreateURLLoaderThrottlesForKeepAlive( } #endif @@ -296,7 +295,7 @@ diff --git a/chrome/browser/domain_reliability/service_factory.cc b/chrome/brows diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn -@@ -798,7 +798,6 @@ static_library("extensions") { +@@ -808,7 +808,6 @@ static_library("extensions") { "//chrome/browser/devtools", "//chrome/browser/extensions:cws_item_service_proto", "//chrome/browser/favicon", @@ -307,7 +306,7 @@ diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUIL diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc --- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc +++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc -@@ -114,7 +114,6 @@ constexpr char kOsVersionTag[] = "OS VERSION"; +@@ -115,7 +115,6 @@ constexpr char kOsVersionTag[] = "OS VERSION"; #if BUILDFLAG(IS_WIN) constexpr char kUsbKeyboardDetected[] = "usb_keyboard_detected"; constexpr char kIsEnrolledToDomain[] = "enrolled_to_domain"; @@ -315,7 +314,7 @@ diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log #if BUILDFLAG(GOOGLE_CHROME_BRANDING) constexpr char kUpdateErrorCode[] = "update_error_code"; constexpr char kUpdateHresult[] = "update_hresult"; -@@ -599,10 +598,6 @@ void ChromeInternalLogSource::PopulateEnrolledToDomain( +@@ -602,10 +601,6 @@ void ChromeInternalLogSource::PopulateEnrolledToDomain( void ChromeInternalLogSource::PopulateInstallerBrandCode( SystemLogsResponse* response) { @@ -369,7 +368,7 @@ diff --git a/chrome/browser/google/BUILD.gn b/chrome/browser/google/BUILD.gn diff --git a/chrome/browser/long_screenshots/long_screenshots_tab_service.cc b/chrome/browser/long_screenshots/long_screenshots_tab_service.cc --- a/chrome/browser/long_screenshots/long_screenshots_tab_service.cc +++ b/chrome/browser/long_screenshots/long_screenshots_tab_service.cc -@@ -35,13 +35,11 @@ constexpr size_t kMaxPerCaptureSizeBytes = 50 * 1000L * 1000L; // 50 MB. +@@ -34,13 +34,11 @@ constexpr size_t kMaxPerCaptureSizeBytes = 50 * 1000L * 1000L; // 50 MB. // Host/regex pattern for Google AMP Cache URLs. // See https://developers.google.com/amp/cache/overview#amp-cache-url-format // for a definition of the format of AMP Cache URLs. @@ -383,7 +382,7 @@ diff --git a/chrome/browser/long_screenshots/long_screenshots_tab_service.cc b/c const char kGoogleNewsPathPattern[] = "/articles/(.*)"; } // namespace -@@ -229,26 +227,6 @@ bool LongScreenshotsTabService::IsAmpUrl(const GURL& url) { +@@ -228,26 +226,6 @@ bool LongScreenshotsTabService::IsAmpUrl(const GURL& url) { return false; } @@ -413,7 +412,7 @@ diff --git a/chrome/browser/long_screenshots/long_screenshots_tab_service.cc b/c diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc -@@ -623,7 +623,7 @@ ChromeMetricsServiceClient::GetNetworkTimeTracker() { +@@ -628,7 +628,7 @@ ChromeMetricsServiceClient::GetNetworkTimeTracker() { } bool ChromeMetricsServiceClient::GetBrand(std::string* brand_code) { @@ -549,7 +548,7 @@ diff --git a/chrome/browser/metrics/metrics_reporting_state.cc b/chrome/browser/ diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc -@@ -722,7 +722,6 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams( +@@ -772,7 +772,6 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams( void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams( network::mojom::NetworkContextParams* network_context_params) { variations::UpdateCorsExemptHeaderForVariations(network_context_params); @@ -630,7 +629,7 @@ diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metri diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc -@@ -122,8 +122,6 @@ void PageLoadMetricsEmbedder::RegisterEmbedderObservers( +@@ -123,8 +123,6 @@ void PageLoadMetricsEmbedder::RegisterEmbedderObservers( tracker->AddObserver(std::make_unique()); tracker->AddObserver(std::make_unique()); tracker->AddObserver(std::make_unique()); @@ -667,7 +666,7 @@ diff --git a/chrome/browser/search_engines/ui_thread_search_terms_data.cc b/chro diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -519,7 +519,6 @@ static_library("ui") { +@@ -429,7 +429,6 @@ static_library("ui") { "//chrome/browser/companion/core", "//chrome/browser/devtools", "//chrome/browser/favicon", @@ -678,7 +677,7 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc -@@ -601,11 +601,6 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { +@@ -621,11 +621,6 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { // chrome-untrusted://new-tab-page for other external content and resources. // NOTE: Use caution when overriding content security policies as that cean // lead to subtle security bugs such as https://crbug.com/1251541. @@ -704,7 +703,7 @@ diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc --- a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc +++ b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc -@@ -209,7 +209,7 @@ void UpgradeDetectorImpl::StartOutdatedBuildDetector() { +@@ -207,7 +207,7 @@ void UpgradeDetectorImpl::StartOutdatedBuildDetector() { // an outdated build is being simulated by command line switches. if (!simulating_outdated_) { std::string brand; @@ -716,7 +715,7 @@ diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc b/chrome/b diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn -@@ -138,8 +138,6 @@ static_library("common_lib") { +@@ -140,8 +140,6 @@ static_library("common_lib") { "content_restriction.h", "crash_keys.cc", "crash_keys.h", @@ -725,22 +724,6 @@ diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn "logging_chrome.cc", "logging_chrome.h", "media/cdm_registration.cc", -diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc ---- a/chrome/common/chrome_features.cc -+++ b/chrome/common/chrome_features.cc -@@ -1539,9 +1539,9 @@ BASE_FEATURE(kSupportsRtcWakeOver24Hours, - base::FEATURE_ENABLED_BY_DEFAULT); - #endif // BUILDFLAG(IS_CHROMEOS_ASH) - --BASE_FEATURE(kWebAuthFlowInBrowserTab, -- "WebAuthFlowInBrowserTab", -- base::FeatureState::FEATURE_ENABLED_BY_DEFAULT); -+BASE_FEATURE(kWebAuthFlowInBrowserTab, // disable by -+ "WebAuthFlowInBrowserTab", // default -+ base::FeatureState::FEATURE_DISABLED_BY_DEFAULT); // in bromite - const base::FeatureParam::Option - web_auth_flow_modes[] = { - {WebAuthFlowInBrowserTabMode::kNewTab, "new_tab"}, diff --git a/chrome/renderer/google_accounts_private_api_util.cc b/chrome/renderer/google_accounts_private_api_util.cc --- a/chrome/renderer/google_accounts_private_api_util.cc +++ b/chrome/renderer/google_accounts_private_api_util.cc @@ -776,14 +759,14 @@ diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/rende diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn -@@ -6182,7 +6182,6 @@ test("unit_tests") { +@@ -6374,7 +6374,6 @@ test("unit_tests") { "//chrome/browser/favicon", "//chrome/browser/feature_guide/notifications:unit_tests", "//chrome/browser/first_party_sets", - "//chrome/browser/google:unit_tests", + "//chrome/browser/media/effects:unittests", "//chrome/browser/media/router", "//chrome/browser/media/router:media_router_feature", - "//chrome/browser/media/router:unittests", diff --git a/components/domain_reliability/BUILD.gn b/components/domain_reliability/BUILD.gn --- a/components/domain_reliability/BUILD.gn +++ b/components/domain_reliability/BUILD.gn @@ -1444,7 +1427,7 @@ diff --git a/components/search_engines/search_terms_data.cc b/components/search_ diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc -@@ -558,11 +558,7 @@ std::u16string TemplateURLRef::SearchTermToString16( +@@ -561,11 +561,7 @@ std::u16string TemplateURLRef::SearchTermToString16( bool TemplateURLRef::HasGoogleBaseURLs( const SearchTermsData& search_terms_data) const { ParseIfNecessary(search_terms_data); @@ -1622,7 +1605,7 @@ diff --git a/components/url_matcher/url_util.cc b/components/url_matcher/url_uti diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -448,15 +448,15 @@ BASE_FEATURE(kFedCmLoginHint, +@@ -416,15 +416,15 @@ BASE_FEATURE(kFedCmSelectiveDisclosure, // Enables metrics collection for signin status mismatches. Also enables // parsing the signin status HTTP headers. // kFedCmIdpSigninStatusEnabled takes precedence over this feature flag. @@ -1642,12 +1625,12 @@ diff --git a/content/public/common/content_features.cc b/content/public/common/c + "FedCmIdpSigninStatusEnabled", // by default + base::FEATURE_DISABLED_BY_DEFAULT); // on bromite - // Enables the MDocs API in the IdentityCredential. - BASE_FEATURE(kWebIdentityMDocs, + // Enables bypassing the well-known file enforcement. + BASE_FEATURE(kFedCmWithoutWellKnownEnforcement, diff --git a/net/base/url_util.cc b/net/base/url_util.cc --- a/net/base/url_util.cc +++ b/net/base/url_util.cc -@@ -486,27 +486,6 @@ bool HasGoogleHost(const GURL& url) { +@@ -489,27 +489,6 @@ bool HasGoogleHost(const GURL& url) { } bool IsGoogleHost(base::StringPiece host) { @@ -1678,7 +1661,7 @@ diff --git a/net/base/url_util.cc b/net/base/url_util.cc diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -2674,7 +2674,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( +@@ -2734,7 +2734,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( } #endif // BUILDFLAG(IS_CT_SUPPORTED) diff --git a/build/patches/webview-Hard-no-to-persistent-histograms.patch b/build/patches/webview-Hard-no-to-persistent-histograms.patch index 7e36c28f..8a763779 100644 --- a/build/patches/webview-Hard-no-to-persistent-histograms.patch +++ b/build/patches/webview-Hard-no-to-persistent-histograms.patch @@ -18,7 +18,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/android_webview/browser/aw_field_trials.cc b/android_webview/browser/aw_field_trials.cc --- a/android_webview/browser/aw_field_trials.cc +++ b/android_webview/browser/aw_field_trials.cc -@@ -47,13 +47,6 @@ class AwFeatureOverrides { +@@ -48,13 +48,6 @@ class AwFeatureOverrides { } // namespace void AwFieldTrials::OnVariationsSetupComplete() { From a5b8c1f1ba50dd65c7cbe7bacbb79ed71cc78ac7 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 5 Sep 2023 16:26:54 +0200 Subject: [PATCH 02/17] v117 to be checked --- build/patches/00Disable-WebGPU.patch | 32 +- ...e-privacy-issues-in-password-manager.patch | 37 +- ...ct-the-entire-FrameTree-like-desktop.patch | 11 +- ...00Eyeo-Adblock-Remove-Privacy-Issues.patch | 737 +++++++----------- ...0Remove-GoogleAccountsPrivateApiHost.patch | 48 ++ 5 files changed, 375 insertions(+), 490 deletions(-) create mode 100644 build/patches/00Remove-GoogleAccountsPrivateApiHost.patch diff --git a/build/patches/00Disable-WebGPU.patch b/build/patches/00Disable-WebGPU.patch index e06ee423..f9a17b6e 100644 --- a/build/patches/00Disable-WebGPU.patch +++ b/build/patches/00Disable-WebGPU.patch @@ -2,15 +2,16 @@ From: uazo Date: Mon, 1 May 2023 12:07:49 +0000 Subject: Disable WebGPU +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - gpu/config/gpu_finch_features.cc | 2 +- - .../blink/renderer/platform/runtime_enabled_features.json5 | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) + gpu/config/gpu_finch_features.cc | 2 +- + third_party/blink/renderer/modules/webgpu/gpu.cc | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc -@@ -273,7 +273,7 @@ BASE_FEATURE(kEnableDrDcVulkan, +@@ -284,7 +284,7 @@ BASE_FEATURE(kEnableDrDcVulkan, // Enable WebGPU on gpu service side only. This is used with origin trial and // enabled by default on supported platforms. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) @@ -19,17 +20,16 @@ diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc #else #define WEBGPU_ENABLED base::FEATURE_DISABLED_BY_DEFAULT #endif -diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 ---- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 -+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -3975,7 +3975,7 @@ - // Note that this isn't enough to enable WebGPU and that access to - // WebGPU is further gated on the "WebGPUService" feature exposing GPU - // process access to WebGPU to the renderer process. -- status: "stable", -+ status: "test", - }, - { - // WebGPU developer features are deliberately not enabled by experimental +diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc +--- a/third_party/blink/renderer/modules/webgpu/gpu.cc ++++ b/third_party/blink/renderer/modules/webgpu/gpu.cc +@@ -357,6 +357,7 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state, + "WebGPU is experimental on this platform. See " + "https://github.com/gpuweb/gpuweb/wiki/" + "Implementation-Status#implementation-status")); ++ (UAZO) add exception + } + + auto* resolver = MakeGarbageCollected(script_state); -- 2.25.1 diff --git a/build/patches/00Disable-privacy-issues-in-password-manager.patch b/build/patches/00Disable-privacy-issues-in-password-manager.patch index 76f0951b..d8f810f1 100644 --- a/build/patches/00Disable-privacy-issues-in-password-manager.patch +++ b/build/patches/00Disable-privacy-issues-in-password-manager.patch @@ -2,21 +2,22 @@ From: uazo Date: Tue, 14 Mar 2023 15:59:38 +0000 Subject: Disable privacy issues in password manager +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/android/java/AndroidManifest.xml | 9 -------- .../generated_password_leak_detection_pref.cc | 3 +-- .../affiliation/affiliation_backend.cc | 1 + .../affiliation/affiliation_service_impl.cc | 4 ++++ .../core/browser/affiliation/facet_manager.cc | 23 +++---------------- + .../browser/features/password_features.cc | 4 ++-- .../leak_detection_check_factory_impl.cc | 5 ++++ .../leak_detection_check_impl.cc | 4 +--- - .../core/common/password_manager_features.cc | 4 ++-- 8 files changed, 17 insertions(+), 36 deletions(-) diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml -@@ -458,15 +458,6 @@ by a child template that "extends" this file. +@@ -445,15 +445,6 @@ by a child template that "extends" this file. @@ -48,7 +49,7 @@ diff --git a/chrome/browser/password_manager/generated_password_leak_detection_p diff --git a/components/password_manager/core/browser/affiliation/affiliation_backend.cc b/components/password_manager/core/browser/affiliation/affiliation_backend.cc --- a/components/password_manager/core/browser/affiliation/affiliation_backend.cc +++ b/components/password_manager/core/browser/affiliation/affiliation_backend.cc -@@ -403,6 +403,7 @@ void AffiliationBackend::OnMalformedResponse( +@@ -405,6 +405,7 @@ void AffiliationBackend::OnMalformedResponse( } bool AffiliationBackend::OnCanSendNetworkRequest() { @@ -59,7 +60,7 @@ diff --git a/components/password_manager/core/browser/affiliation/affiliation_ba diff --git a/components/password_manager/core/browser/affiliation/affiliation_service_impl.cc b/components/password_manager/core/browser/affiliation/affiliation_service_impl.cc --- a/components/password_manager/core/browser/affiliation/affiliation_service_impl.cc +++ b/components/password_manager/core/browser/affiliation/affiliation_service_impl.cc -@@ -138,6 +138,10 @@ void AffiliationServiceImpl::Shutdown() { +@@ -135,6 +135,10 @@ void AffiliationServiceImpl::Shutdown() { void AffiliationServiceImpl::PrefetchChangePasswordURLs( const std::vector& urls, base::OnceClosure callback) { @@ -110,6 +111,20 @@ diff --git a/components/password_manager/core/browser/affiliation/facet_manager. } // static +diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc +--- a/components/password_manager/core/browser/features/password_features.cc ++++ b/components/password_manager/core/browser/features/password_features.cc +@@ -58,8 +58,8 @@ BASE_FEATURE(kFillingAcrossGroupedSites, + // Enables the experiment for the password manager to only fill on account + // selection, rather than autofilling on page load, with highlighting of fields. + BASE_FEATURE(kFillOnAccountSelect, +- "fill-on-account-select", +- base::FEATURE_DISABLED_BY_DEFAULT); ++ "fill-on-account-select", // always enabled ++ base::FEATURE_ENABLED_BY_DEFAULT); // by default + + // Enables the notification UI that is displayed to the user when visiting a + // website for which a stored password has been shared by another user. diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc b/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc --- a/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc +++ b/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc @@ -139,19 +154,5 @@ diff --git a/components/password_manager/core/browser/leak_detection/leak_detect } void LeakDetectionCheckImpl::Start(LeakDetectionInitiator initiator, -diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc ---- a/components/password_manager/core/common/password_manager_features.cc -+++ b/components/password_manager/core/common/password_manager_features.cc -@@ -87,8 +87,8 @@ BASE_FEATURE(kFillingAcrossGroupedSites, - // Enables the experiment for the password manager to only fill on account - // selection, rather than autofilling on page load, with highlighting of fields. - BASE_FEATURE(kFillOnAccountSelect, -- "fill-on-account-select", -- base::FEATURE_DISABLED_BY_DEFAULT); -+ "fill-on-account-select", // always enabled -+ base::FEATURE_ENABLED_BY_DEFAULT); // in bromite - - // Enables logging the content of chrome://password-manager-internals to the - // terminal. -- 2.25.1 diff --git a/build/patches/00Evict-the-entire-FrameTree-like-desktop.patch b/build/patches/00Evict-the-entire-FrameTree-like-desktop.patch index 9973b4bd..d93d50a4 100644 --- a/build/patches/00Evict-the-entire-FrameTree-like-desktop.patch +++ b/build/patches/00Evict-the-entire-FrameTree-like-desktop.patch @@ -1,7 +1,8 @@ -From: Your Name +From: uazo Date: Tue, 14 Feb 2023 16:23:08 +0000 Subject: Evict the entire FrameTree like desktop +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- components/viz/common/features.cc | 2 +- content/public/common/content_features.cc | 4 ++-- @@ -10,19 +11,19 @@ Subject: Evict the entire FrameTree like desktop diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc -@@ -231,7 +231,7 @@ BASE_FEATURE(kRendererAllocatesImages, +@@ -233,7 +233,7 @@ BASE_FEATURE(kRendererAllocatesImages, // evicts itself. This differs from Destkop platforms which evict the entire // FrameTree along with the topmost viz::Surface. When this feature is enabled, // Android will begin also evicting the entire FrameTree. --BASE_FEATURE(kEvictSubtree, "EvictSubtree", base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kEvictSubtree, "EvictSubtree", base::FEATURE_ENABLED_BY_DEFAULT); +-BASE_FEATURE(kEvictSubtree, "EvictSubtree", base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kEvictSubtree, "EvictSubtree", base::FEATURE_ENABLED_BY_DEFAULT); // enabled by default // If enabled, CompositorFrameSinkClient::OnBeginFrame is also treated as the // DidReceiveCompositorFrameAck. Both in providing the Ack for the previous diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc -@@ -564,8 +564,8 @@ BASE_FEATURE(kInMemoryCodeCache, +@@ -537,8 +537,8 @@ BASE_FEATURE(kInMemoryCodeCache, // frames. Otherwise only toplevel frames and OOPIF are handled, and other // cases, e.g. PDF tiles are ignored. See https://crbug.com/1360351 for details. BASE_FEATURE(kInnerFrameCompositorSurfaceEviction, diff --git a/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch index 27c139fc..b2fe6fb2 100644 --- a/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch +++ b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch @@ -8,13 +8,9 @@ suit Bromite logic .../android/java/res/xml/main_preferences.xml | 11 +- chrome/browser/BUILD.gn | 2 - .../adblock/adblock_content_browser_client.cc | 26 +- - .../adblock/adblock_controller_factory.cc | 3 +- - .../adblock_telemetry_service_factory.cc | 127 - - .../adblock_telemetry_service_factory.h | 56 - - .../adblock/subscription_service_factory.cc | 11 +- .../adblock/subscription_service_factory.h | 1 + chrome/browser/android/adblock/adblock_jni.cc | 50 +- - .../adblock_private/adblock_private_api.cc | 70 +- + .../adblock_private/adblock_private_api.cc | 68 +- .../api/adblock_private/adblock_private_api.h | 49 + .../eyeo_filtering_private_api.cc | 20 +- ...hrome_browser_main_extra_parts_profiles.cc | 2 - @@ -45,11 +41,15 @@ suit Bromite logic .../settings/AdblockFilterListsAdapter.java | 6 + .../settings/AdblockSettingsFragment.java | 45 +- components/adblock/content/browser/BUILD.gn | 16 +- + .../adblock_controller_factory_base.cc | 2 +- + .../adblock_telemetry_service_factory_base.cc | 49 - + .../adblock_telemetry_service_factory_base.h | 24 - .../browser/adblock_webcontents_observer.cc | 25 +- .../browser/adblock_webcontents_observer.h | 5 +- .../content_security_policy_injector_impl.cc | 1 + + .../subscription_service_factory_base.cc | 10 +- components/adblock/core/BUILD.gn | 39 - - .../activeping_telemetry_topic_provider.cc | 242 -- + .../activeping_telemetry_topic_provider.cc | 243 -- .../activeping_telemetry_topic_provider.h | 84 - components/adblock/core/adblock_controller.h | 6 + .../adblock/core/adblock_controller_impl.cc | 35 +- @@ -95,7 +95,6 @@ suit Bromite logic .../subscription/subscription_service_impl.h | 3 + .../subscription/subscription_updater_impl.cc | 8 +- .../subscription_validator_impl.cc | 4 +- - components/adblock/features.gni | 44 - .../browser/bromite_content_settings/ads.inc | 3 + components/resources/BUILD.gn | 1 - components/resources/adblock_resources.grdp | 3 - @@ -109,9 +108,7 @@ suit Bromite logic .../blink/renderer/core/css/style_engine.h | 1 + .../renderer/core/exported/web_document.cc | 13 +- .../definitions/adblock_private.d.ts | 14 + - 104 files changed, 5041 insertions(+), 1296 deletions(-) - delete mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.cc - delete mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.h + 103 files changed, 5038 insertions(+), 1142 deletions(-) create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.html create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.ts rename components/adblock/android/java/res/xml/{adblock_preferences.xml => eyeo_adblock_preferences.xml} (56%) @@ -120,7 +117,6 @@ suit Bromite logic delete mode 100644 components/adblock/core/adblock_telemetry_service.cc delete mode 100644 components/adblock/core/adblock_telemetry_service.h create mode 100644 components/adblock/core/converter/parser/test/test_rules.txt - delete mode 100644 components/adblock/features.gni create mode 100644 components/content_settings/core/browser/bromite_content_settings/ads.inc create mode 100755 components/resources/adblocking/snippets/dist/isolated-first.jst create mode 100755 components/resources/adblocking/snippets/dist/isolated-first.source.jst @@ -142,7 +138,7 @@ diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/j -@@ -101,7 +92,7 @@ Use of this source code is governed by the GPLv3 that can be found in the compon +@@ -106,7 +97,7 @@ Use of this source code is governed by the GPLv3 that can be found in the compon android:title="@string/prefs_accessibility"/> ( std::move(config), content::GlobalRenderFrameHostId(render_process_id, -diff --git a/chrome/browser/adblock/adblock_controller_factory.cc b/chrome/browser/adblock/adblock_controller_factory.cc ---- a/chrome/browser/adblock/adblock_controller_factory.cc -+++ b/chrome/browser/adblock/adblock_controller_factory.cc -@@ -65,8 +65,7 @@ KeyedService* AdblockControllerFactory::BuildServiceInstanceFor( - std::make_unique( - prefs, kAdblockFilteringConfigurationName); - -- if (base::CommandLine::ForCurrentProcess()->HasSwitch( -- adblock::switches::kDisableAcceptableAds)) { -+ if ((true)) { - adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); - } - if (base::CommandLine::ForCurrentProcess()->HasSwitch( -diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.cc b/chrome/browser/adblock/adblock_telemetry_service_factory.cc -deleted file mode 100644 ---- a/chrome/browser/adblock/adblock_telemetry_service_factory.cc -+++ /dev/null -@@ -1,127 +0,0 @@ --/* -- * This file is part of eyeo Chromium SDK, -- * Copyright (C) 2006-present eyeo GmbH -- * -- * eyeo Chromium SDK is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 3 as -- * published by the Free Software Foundation. -- * -- * eyeo Chromium SDK is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with eyeo Chromium SDK. If not, see . -- */ -- --#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" -- --#include -- --#include "base/no_destructor.h" --#include "chrome/browser/adblock/adblock_controller_factory.h" --#include "chrome/browser/adblock/subscription_service_factory.h" --#include "chrome/browser/profiles/incognito_helpers.h" --#include "chrome/browser/profiles/profile.h" --#include "chrome/common/pref_names.h" --#include "components/adblock/core/activeping_telemetry_topic_provider.h" --#include "components/adblock/core/adblock_telemetry_service.h" --#include "components/adblock/core/common/adblock_utils.h" --#include "components/adblock/core/configuration/filtering_configuration.h" --#include "components/keyed_service/content/browser_context_dependency_manager.h" --#include "content/public/browser/storage_partition.h" -- --namespace adblock { --namespace { --std::optional g_check_interval_for_testing; --std::optional g_initial_delay_for_testing; -- --base::TimeDelta GetInitialDelay() { -- static base::TimeDelta kInitialDelay = -- g_initial_delay_for_testing ? g_initial_delay_for_testing.value() -- : base::Seconds(30); -- return kInitialDelay; --} -- --base::TimeDelta GetCheckInterval() { -- static base::TimeDelta kCheckInterval = -- g_check_interval_for_testing ? g_check_interval_for_testing.value() -- : base::Minutes(5); -- return kCheckInterval; --} -- --} // namespace -- --// static --AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile( -- Profile* profile) { -- return static_cast( -- GetInstance()->GetServiceForBrowserContext(profile, true)); --} --// static --AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() { -- static base::NoDestructor instance; -- return instance.get(); --} -- --AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory() -- : BrowserContextKeyedServiceFactory( -- "AdblockTelemetryService", -- BrowserContextDependencyManager::GetInstance()) { -- // AdblockController creates Adblock Filtering Configuration required by -- // AdblockTelemetryService -- DependsOn(AdblockControllerFactory::GetInstance()); --} -- --AdblockTelemetryServiceFactory::~AdblockTelemetryServiceFactory() = default; -- --KeyedService* AdblockTelemetryServiceFactory::BuildServiceInstanceFor( -- content::BrowserContext* context) const { -- // Need to use a URLLoaderFactory specific to the browser context, not from -- // system_network_context_manager(), because the required Accept-Language -- // header depends on user's language settings and is not present in requests -- // made from the System network context. -- scoped_refptr url_loader_factory = -- context->GetDefaultStoragePartition() -- ->GetURLLoaderFactoryForBrowserProcess(); -- auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); -- auto service = std::make_unique( -- SubscriptionServiceFactory::GetForBrowserContext(context) -- ->GetAdblockFilteringConfiguration(), -- url_loader_factory, GetInitialDelay(), GetCheckInterval()); -- service->AddTopicProvider(std::make_unique( -- utils::GetAppInfo(), prefs, -- AdblockControllerFactory::GetForBrowserContext(context), -- ActivepingTelemetryTopicProvider::DefaultBaseUrl(), -- ActivepingTelemetryTopicProvider::DefaultAuthToken())); -- -- if (url_loader_factory) { -- service->Start(); -- } -- -- return service.release(); --} -- --content::BrowserContext* AdblockTelemetryServiceFactory::GetBrowserContextToUse( -- content::BrowserContext* context) const { -- return chrome::GetBrowserContextRedirectedInIncognito(context); --} -- --bool AdblockTelemetryServiceFactory::ServiceIsNULLWhileTesting() const { -- return true; --} -- --bool AdblockTelemetryServiceFactory::ServiceIsCreatedWithBrowserContext() -- const { -- return true; --} -- --void AdblockTelemetryServiceFactory::SetCheckAndDelayIntervalsForTesting( -- base::TimeDelta check_interval, -- base::TimeDelta initial_delay) { -- g_check_interval_for_testing = check_interval; -- g_initial_delay_for_testing = initial_delay; --} -- --} // namespace adblock -diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.h b/chrome/browser/adblock/adblock_telemetry_service_factory.h -deleted file mode 100644 ---- a/chrome/browser/adblock/adblock_telemetry_service_factory.h -+++ /dev/null -@@ -1,56 +0,0 @@ --/* -- * This file is part of eyeo Chromium SDK, -- * Copyright (C) 2006-present eyeo GmbH -- * -- * eyeo Chromium SDK is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 3 as -- * published by the Free Software Foundation. -- * -- * eyeo Chromium SDK is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with eyeo Chromium SDK. If not, see . -- */ -- --#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ --#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ -- --#include "base/no_destructor.h" --#include "base/time/time.h" --#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -- --class Profile; -- --namespace adblock { --class AdblockTelemetryService; --class AdblockTelemetryServiceFactory -- : public BrowserContextKeyedServiceFactory { -- public: -- static AdblockTelemetryService* GetForProfile(Profile* profile); -- static AdblockTelemetryServiceFactory* GetInstance(); -- -- // Sets the initial delay and interval checks required for browser tests. -- // Must be called before BuildServiceInstanceFor(). -- void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval, -- base::TimeDelta initial_delay); -- -- private: -- friend class base::NoDestructor; -- AdblockTelemetryServiceFactory(); -- ~AdblockTelemetryServiceFactory() override; -- -- // BrowserContextKeyedServiceFactory: -- KeyedService* BuildServiceInstanceFor( -- content::BrowserContext* context) const override; -- content::BrowserContext* GetBrowserContextToUse( -- content::BrowserContext* context) const override; -- bool ServiceIsNULLWhileTesting() const override; -- bool ServiceIsCreatedWithBrowserContext() const override; --}; -- --} // namespace adblock -- --#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ -diff --git a/chrome/browser/adblock/subscription_service_factory.cc b/chrome/browser/adblock/subscription_service_factory.cc ---- a/chrome/browser/adblock/subscription_service_factory.cc -+++ b/chrome/browser/adblock/subscription_service_factory.cc -@@ -25,6 +25,7 @@ - #include "base/functional/bind.h" - #include "base/task/thread_pool.h" - #include "base/trace_event/trace_event.h" -+#include "base/rand_util.h" - #include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" - #include "chrome/browser/profiles/incognito_helpers.h" - #include "chrome/browser/profiles/profile.h" -@@ -66,7 +67,7 @@ base::TimeDelta GetUpdateCheckInterval() { - static base::TimeDelta kCheckInterval = - g_update_check_interval_for_testing - ? g_update_check_interval_for_testing.value() -- : base::Hours(1); -+ : base::Hours(24) + base::Minutes(base::RandInt(-60,60)); - return kCheckInterval; - } - -@@ -87,7 +88,8 @@ std::unique_ptr MakeOngoingSubscriptionRequest( - } - - ConversionResult ConvertFilterFile(const GURL& subscription_url, -- const base::FilePath& path) { -+ const base::FilePath& path, -+ bool allow_privileged_filter) { - TRACE_EVENT1("eyeo", "ConvertFileToFlatbuffer", "url", - subscription_url.spec()); - ConversionResult result; -@@ -97,7 +99,7 @@ ConversionResult ConvertFilterFile(const GURL& subscription_url, - } else { - result = FlatbufferConverter::Convert( - input_stream, subscription_url, -- config::AllowPrivilegedFilters(subscription_url)); -+ allow_privileged_filter && config::AllowPrivilegedFilters(subscription_url)); - } - base::DeleteFile(path); - return result; -@@ -162,10 +164,11 @@ SubscriptionServiceFactory::ConvertCustomFilters( - void SubscriptionServiceFactory::ConvertFilterListFile( - const GURL& subscription_url, - const base::FilePath& path, -+ bool allow_privileged_filter, - base::OnceCallback result_callback) const { - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, -- base::BindOnce(&ConvertFilterFile, subscription_url, path), -+ base::BindOnce(&ConvertFilterFile, subscription_url, path, allow_privileged_filter), - std::move(result_callback)); - } - diff --git a/chrome/browser/adblock/subscription_service_factory.h b/chrome/browser/adblock/subscription_service_factory.h --- a/chrome/browser/adblock/subscription_service_factory.h +++ b/chrome/browser/adblock/subscription_service_factory.h -@@ -42,6 +42,7 @@ class SubscriptionServiceFactory : public BrowserContextKeyedServiceFactory, - void ConvertFilterListFile( - const GURL& subscription_url, - const base::FilePath& path, +@@ -34,6 +34,7 @@ class SubscriptionServiceFactory : public SubscriptionServiceFactoryBase { + protected: + PrefService* GetPrefs(content::BrowserContext* context) const override; + SubscriptionPersistentMetadata* GetSubscriptionPersistentMetadata( + bool allow_privileged_filter, - base::OnceCallback) const override; + content::BrowserContext* context) const override; private: diff --git a/chrome/browser/android/adblock/adblock_jni.cc b/chrome/browser/android/adblock/adblock_jni.cc @@ -586,7 +324,7 @@ diff --git a/chrome/browser/android/adblock/adblock_jni.cc b/chrome/browser/andr diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc b/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc --- a/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc +++ b/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc -@@ -137,26 +137,12 @@ std::vector CopySessionsStats( +@@ -75,26 +75,12 @@ std::vector CopySessionsStats( return result; } @@ -616,7 +354,7 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.c std::vector result; for (auto& sub : current_subscriptions) { api::adblock_private::Subscription js_sub; -@@ -164,9 +150,13 @@ std::vector CopySubscriptions( +@@ -102,9 +88,13 @@ std::vector CopySubscriptions( js_sub.title = sub->GetTitle(); js_sub.current_version = sub->GetCurrentVersion(); js_sub.installation_state = @@ -631,7 +369,7 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.c result.emplace_back(std::move(js_sub)); } return result; -@@ -402,6 +392,44 @@ void AdblockPrivateAPI::OnListenerAdded( +@@ -345,6 +335,44 @@ void AdblockPrivateAPI::OnListenerAdded( namespace api { @@ -676,25 +414,16 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.c AdblockPrivateSetEnabledFunction::AdblockPrivateSetEnabledFunction() {} AdblockPrivateSetEnabledFunction::~AdblockPrivateSetEnabledFunction() {} -@@ -547,7 +575,7 @@ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction::Run() { - - return RespondNow(ArgumentList( - api::adblock_private::GetSelectedBuiltInSubscriptions::Results::Create( -- CopySubscriptions(controller->GetSelectedBuiltInSubscriptions())))); -+ CopySubscriptions(controller, controller->GetSelectedBuiltInSubscriptions())))); - } - - AdblockPrivateAddCustomSubscriptionFunction:: -@@ -605,7 +633,7 @@ AdblockPrivateGetCustomSubscriptionsFunction::Run() { +@@ -403,7 +431,7 @@ AdblockPrivateIsAcceptableAdsEnabledFunction::Run() { browser_context()); return RespondNow(ArgumentList( - api::adblock_private::GetCustomSubscriptions::Results::Create( -- CopySubscriptions(controller->GetCustomSubscriptions())))); -+ CopySubscriptions(controller, controller->GetCustomSubscriptions())))); + api::adblock_private::IsAcceptableAdsEnabled::Results::Create( +- controller->IsAcceptableAdsEnabled()))); ++ controller, controller->IsAcceptableAdsEnabled()))); } - AdblockPrivateInstallSubscriptionFunction:: -@@ -662,7 +690,7 @@ AdblockPrivateGetInstalledSubscriptionsFunction::Run() { + AdblockPrivateGetBuiltInSubscriptionsFunction:: +@@ -486,7 +514,7 @@ AdblockPrivateGetInstalledSubscriptionsFunction::Run() { browser_context()); return RespondNow(ArgumentList( api::adblock_private::GetInstalledSubscriptions::Results::Create( @@ -817,7 +546,7 @@ diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc #include "chrome/browser/adblock/content_security_policy_injector_factory.h" #include "chrome/browser/adblock/element_hider_factory.h" #include "chrome/browser/adblock/resource_classification_runner_factory.h" -@@ -683,7 +682,6 @@ void ChromeBrowserMainExtraPartsProfiles:: +@@ -721,7 +720,6 @@ void ChromeBrowserMainExtraPartsProfiles:: ExitTypeServiceFactory::GetInstance(); #endif adblock::AdblockControllerFactory::GetInstance(); @@ -828,7 +557,7 @@ diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn -@@ -70,6 +70,7 @@ build_webui("build") { +@@ -72,6 +72,7 @@ build_webui("build") { web_component_files = [ "a11y_page/a11y_page.ts", "about_page/about_page.ts", @@ -836,7 +565,7 @@ diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resourc "appearance_page/appearance_fonts_page.ts", "appearance_page/appearance_page.ts", "appearance_page/home_url_input.ts", -@@ -381,6 +382,7 @@ build_webui("build") { +@@ -365,6 +366,7 @@ build_webui("build") { ts_composite = true ts_definitions = [ "//tools/typescript/definitions/autofill_private.d.ts", @@ -1389,7 +1118,7 @@ diff --git a/chrome/browser/resources/settings/page_visibility.ts b/chrome/brows diff --git a/chrome/browser/resources/settings/route.ts b/chrome/browser/resources/settings/route.ts --- a/chrome/browser/resources/settings/route.ts +++ b/chrome/browser/resources/settings/route.ts -@@ -176,6 +176,10 @@ function createBrowserSettingsRoutes(): SettingsRoutes { +@@ -178,6 +178,10 @@ function createBrowserSettingsRoutes(): SettingsRoutes { r.FONTS = r.APPEARANCE.createChild('/fonts'); } @@ -1414,12 +1143,12 @@ diff --git a/chrome/browser/resources/settings/router.ts b/chrome/browser/resour diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts --- a/chrome/browser/resources/settings/settings.ts +++ b/chrome/browser/resources/settings/settings.ts -@@ -42,6 +42,7 @@ export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_p +@@ -47,6 +47,7 @@ export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_p export {SettingsAppearancePageElement, SystemTheme} from './appearance_page/appearance_page.js'; export {HomeUrlInputElement} from './appearance_page/home_url_input.js'; export {SettingsAutofillPageElement} from './autofill_page/autofill_page.js'; +export {SettingsAdblockPageElement} from './adblock_page/adblock_page.js'; - export {AccountStorageOptInStateChangedListener, CredentialsChangedListener, PasswordCheckInteraction, PasswordCheckReferrer, PasswordCheckStatusChangedListener, PasswordExceptionListChangedListener, PasswordManagerAuthTimeoutListener, PasswordManagerImpl, PasswordManagerPage, PasswordManagerProxy, PasswordsFileExportProgressListener, SavedPasswordListChangedListener} from './autofill_page/password_manager_proxy.js'; + export {PasswordCheckReferrer, PasswordManagerImpl, PasswordManagerPage, PasswordManagerProxy} from './autofill_page/password_manager_proxy.js'; export {BaseMixin} from './base_mixin.js'; export {SettingsBasicPageElement} from './basic_page/basic_page.js'; diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html @@ -1440,7 +1169,7 @@ diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc -@@ -345,6 +345,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { +@@ -353,6 +353,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { } #endif @@ -1449,7 +1178,7 @@ diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc AdblockWebContentObserver::CreateForWebContents( web_contents, adblock::SubscriptionServiceFactory::GetForBrowserContext( -@@ -353,7 +355,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { +@@ -361,7 +363,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { web_contents->GetBrowserContext()), adblock::SitekeyStorageFactory::GetForBrowserContext( web_contents->GetBrowserContext()), @@ -1473,7 +1202,7 @@ diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/com "autofillPrivate": { "channel": "trunk", "extension_types": ["extension", "platform_app"], -@@ -345,10 +341,6 @@ +@@ -341,10 +337,6 @@ "extension", "legacy_packaged_app", "hosted_app", "platform_app" ] }, @@ -1487,7 +1216,7 @@ diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/com diff --git a/chrome/common/extensions/api/adblock_private.idl b/chrome/common/extensions/api/adblock_private.idl --- a/chrome/common/extensions/api/adblock_private.idl +++ b/chrome/common/extensions/api/adblock_private.idl -@@ -43,6 +43,8 @@ dictionary Subscription { +@@ -47,6 +47,8 @@ dictionary Subscription { // Time of last successful installation or update, in ISO 8601 format. // May be passed directly to the Date constructor. DOMString last_installation_time; @@ -1496,7 +1225,7 @@ diff --git a/chrome/common/extensions/api/adblock_private.idl b/chrome/common/ex }; dictionary SessionStatsEntry { -@@ -91,6 +93,12 @@ callback ListCallback = void(DOMString[] result); +@@ -97,6 +99,12 @@ callback ListCallback = void(DOMString[] result); callback SessionStatsCallback = void(SessionStatsEntry[] result); interface Functions { @@ -1520,7 +1249,7 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn import("//components/captive_portal/core/features.gni") import("//components/enterprise/buildflags/buildflags.gni") import("//components/feed/features.gni") -@@ -2545,10 +2544,6 @@ if (!is_android) { +@@ -2670,10 +2669,6 @@ if (!is_android) { sources += [ "../browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc" ] } @@ -1799,7 +1528,7 @@ diff --git a/components/adblock/android/java/src/org/chromium/components/adblock break; } } -@@ -190,6 +217,27 @@ public final class AdblockController extends FilteringConfiguration { +@@ -182,6 +209,27 @@ public final class AdblockController extends FilteringConfiguration { removeFilterList(url); } @@ -1827,7 +1556,7 @@ diff --git a/components/adblock/android/java/src/org/chromium/components/adblock @UiThread public List getInstalledSubscriptions() { return (List) (List) Arrays.asList( -@@ -259,6 +307,10 @@ public final class AdblockController extends FilteringConfiguration { +@@ -251,6 +299,10 @@ public final class AdblockController extends FilteringConfiguration { @NativeMethods interface Natives { @@ -2144,8 +1873,8 @@ diff --git a/components/adblock/content/browser/BUILD.gn b/components/adblock/co } source_set("browser_impl") { -@@ -51,15 +44,10 @@ source_set("browser_impl") { - "session_stats_impl.h", +@@ -62,15 +55,10 @@ source_set("browser_impl") { + ] - if (eyeo_intercept_debug_url) { @@ -2159,14 +1888,117 @@ diff --git a/components/adblock/content/browser/BUILD.gn b/components/adblock/co "//base", + "//components/content_settings/browser", + "//components/content_settings/core/browser", + "//components/adblock/core/converter:converter", + "//components/keyed_service/content:content", "//components/resources:components_resources_grit", - "//url:url", - ] +diff --git a/components/adblock/content/browser/adblock_controller_factory_base.cc b/components/adblock/content/browser/adblock_controller_factory_base.cc +--- a/components/adblock/content/browser/adblock_controller_factory_base.cc ++++ b/components/adblock/content/browser/adblock_controller_factory_base.cc +@@ -47,7 +47,7 @@ KeyedService* AdblockControllerFactoryBase::BuildServiceInstanceFor( + std::make_unique( + prefs, kAdblockFilteringConfigurationName); + +- if (base::CommandLine::ForCurrentProcess()->HasSwitch( ++ if ((true) && base::CommandLine::ForCurrentProcess()->HasSwitch( + adblock::switches::kDisableAcceptableAds)) { + adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); + } +diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc +--- a/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc ++++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc +@@ -48,53 +48,4 @@ base::TimeDelta GetCheckInterval() { + + } // namespace + +-AdblockTelemetryServiceFactoryBase::AdblockTelemetryServiceFactoryBase() +- : BrowserContextKeyedServiceFactory( +- "AdblockTelemetryService", +- BrowserContextDependencyManager::GetInstance()) {} +- +-AdblockTelemetryServiceFactoryBase::~AdblockTelemetryServiceFactoryBase() = +- default; +- +-KeyedService* AdblockTelemetryServiceFactoryBase::BuildServiceInstanceFor( +- content::BrowserContext* context) const { +- // Need to use a URLLoaderFactory specific to the browser context, not from +- // system_network_context_manager(), because the required Accept-Language +- // header depends on user's language settings and is not present in requests +- // made from the System network context. +- scoped_refptr url_loader_factory = +- context->GetDefaultStoragePartition() +- ->GetURLLoaderFactoryForBrowserProcess(); +- auto* prefs = GetPrefs(context); +- auto service = std::make_unique( +- GetSubscriptionService(context)->GetAdblockFilteringConfiguration(), +- url_loader_factory, GetInitialDelay(), GetCheckInterval()); +- service->AddTopicProvider(std::make_unique( +- utils::GetAppInfo(), prefs, GetAdblockController(context), +- ActivepingTelemetryTopicProvider::DefaultBaseUrl(), +- ActivepingTelemetryTopicProvider::DefaultAuthToken())); +- +- if (url_loader_factory) { +- service->Start(); +- } +- +- return service.release(); +-} +- +-bool AdblockTelemetryServiceFactoryBase::ServiceIsNULLWhileTesting() const { +- return true; +-} +- +-bool AdblockTelemetryServiceFactoryBase::ServiceIsCreatedWithBrowserContext() +- const { +- return true; +-} +- +-void AdblockTelemetryServiceFactoryBase::SetCheckAndDelayIntervalsForTesting( +- base::TimeDelta check_interval, +- base::TimeDelta initial_delay) { +- g_check_interval_for_testing = check_interval; +- g_initial_delay_for_testing = initial_delay; +-} +- + } // namespace adblock +diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.h b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h +--- a/components/adblock/content/browser/adblock_telemetry_service_factory_base.h ++++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h +@@ -27,30 +27,6 @@ namespace adblock { + + class AdblockController; + class SubscriptionService; +-class AdblockTelemetryServiceFactoryBase +- : public BrowserContextKeyedServiceFactory { +- public: +- // Sets the initial delay and interval checks required for browser tests. +- // Must be called before BuildServiceInstanceFor(). +- void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval, +- base::TimeDelta initial_delay); +- +- protected: +- virtual PrefService* GetPrefs(content::BrowserContext* context) const = 0; +- virtual AdblockController* GetAdblockController( +- content::BrowserContext* context) const = 0; +- virtual SubscriptionService* GetSubscriptionService( +- content::BrowserContext* context) const = 0; +- AdblockTelemetryServiceFactoryBase(); +- ~AdblockTelemetryServiceFactoryBase() override; +- +- private: +- // BrowserContextKeyedServiceFactory: +- KeyedService* BuildServiceInstanceFor( +- content::BrowserContext* context) const override; +- bool ServiceIsNULLWhileTesting() const override; +- bool ServiceIsCreatedWithBrowserContext() const override; +-}; + + } // namespace adblock + diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc b/components/adblock/content/browser/adblock_webcontents_observer.cc --- a/components/adblock/content/browser/adblock_webcontents_observer.cc +++ b/components/adblock/content/browser/adblock_webcontents_observer.cc -@@ -20,10 +20,14 @@ - #include "base/trace_event/trace_event.h" +@@ -21,6 +21,8 @@ + #include "components/adblock/content/browser/frame_opener_info.h" #include "components/adblock/core/common/sitekey.h" #include "components/adblock/core/subscription/subscription_service.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" @@ -2174,13 +2006,16 @@ diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc #include "content/public/browser/navigation_handle.h" #include "net/base/url_util.h" #include "third_party/blink/public/common/frame/frame_owner_element_type.h" - -+namespace { +@@ -56,7 +58,7 @@ const char* WindowOpenDispositionToString(WindowOpenDisposition value) { + return ""; + } + } +-} // namespace + + void TraceHandleLoadComplete( content::RenderFrameHost* frame_host, - const adblock::ElementHider::ElemhideInjectionData&) { -@@ -32,18 +36,32 @@ void TraceHandleLoadComplete( +@@ -66,18 +68,32 @@ void TraceHandleLoadComplete( TRACE_ID_LOCAL(frame_host)); } @@ -2194,7 +2029,7 @@ diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc + return true; +} + -+} ++} // namespace + AdblockWebContentObserver::AdblockWebContentObserver( content::WebContents* web_contents, @@ -2215,7 +2050,7 @@ diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc AdblockWebContentObserver::~AdblockWebContentObserver() = default; -@@ -63,6 +81,9 @@ void AdblockWebContentObserver::DidFinishNavigation( +@@ -122,6 +138,9 @@ void AdblockWebContentObserver::DidFinishNavigation( if (!navigation_handle->GetRenderFrameHost()) { return; } @@ -2246,7 +2081,7 @@ diff --git a/components/adblock/content/browser/adblock_webcontents_observer.h b ~AdblockWebContentObserver() override; AdblockWebContentObserver(const AdblockWebContentObserver&) = delete; AdblockWebContentObserver& operator=(const AdblockWebContentObserver&) = -@@ -71,5 +73,6 @@ class AdblockWebContentObserver +@@ -81,5 +83,6 @@ class AdblockWebContentObserver raw_ptr sitekey_storage_; std::unique_ptr frame_hierarchy_builder_; @@ -2264,6 +2099,54 @@ diff --git a/components/adblock/content/browser/content_security_policy_injector for (const auto& collection : subscription_collections) { const auto injection = collection->GetCspInjections(request_url, frame_hierarchy_chain); +diff --git a/components/adblock/content/browser/subscription_service_factory_base.cc b/components/adblock/content/browser/subscription_service_factory_base.cc +--- a/components/adblock/content/browser/subscription_service_factory_base.cc ++++ b/components/adblock/content/browser/subscription_service_factory_base.cc +@@ -21,6 +21,7 @@ + #include + #include + ++#include "base/rand_util.h" + #include "base/command_line.h" + #include "base/files/file_util.h" + #include "base/functional/bind.h" +@@ -65,7 +66,7 @@ base::TimeDelta GetUpdateCheckInterval() { + static base::TimeDelta kCheckInterval = + g_update_check_interval_for_testing + ? g_update_check_interval_for_testing.value() +- : base::Hours(1); ++ : base::Hours(24) + base::Minutes(base::RandInt(-60,60)); + return kCheckInterval; + } + +@@ -86,7 +87,8 @@ std::unique_ptr MakeOngoingSubscriptionRequest( + } + + ConversionResult ConvertFilterFile(const GURL& subscription_url, +- const base::FilePath& path) { ++ const base::FilePath& path, ++ bool allow_privileged_filter) { + TRACE_EVENT1("eyeo", "ConvertFileToFlatbuffer", "url", + subscription_url.spec()); + ConversionResult result; +@@ -96,7 +98,7 @@ ConversionResult ConvertFilterFile(const GURL& subscription_url, + } else { + result = FlatbufferConverter::Convert( + input_stream, subscription_url, +- config::AllowPrivilegedFilters(subscription_url)); ++ allow_privileged_filter && config::AllowPrivilegedFilters(subscription_url)); + } + base::DeleteFile(path); + return result; +@@ -205,7 +207,7 @@ void SubscriptionServiceFactoryBase::ConvertFilterListFile( + base::OnceCallback result_callback) const { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, +- base::BindOnce(&ConvertFilterFile, subscription_url, path), ++ base::BindOnce(&ConvertFilterFile, subscription_url, path, allow_privileged_filter), + std::move(result_callback)); + } + diff --git a/components/adblock/core/BUILD.gn b/components/adblock/core/BUILD.gn --- a/components/adblock/core/BUILD.gn +++ b/components/adblock/core/BUILD.gn @@ -2344,7 +2227,7 @@ diff --git a/components/adblock/core/activeping_telemetry_topic_provider.cc b/co deleted file mode 100644 --- a/components/adblock/core/activeping_telemetry_topic_provider.cc +++ /dev/null -@@ -1,242 +0,0 @@ +@@ -1,243 +0,0 @@ -/* - * This file is part of eyeo Chromium SDK, - * Copyright (C) 2006-present eyeo GmbH @@ -2364,11 +2247,11 @@ deleted file mode 100644 - -#include "components/adblock/core/activeping_telemetry_topic_provider.h" - --#include "base/guid.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/system/sys_info.h" -#include "base/time/time.h" +-#include "base/uuid.h" -#include "components/adblock/core/common/adblock_prefs.h" - -namespace adblock { @@ -2406,10 +2289,10 @@ deleted file mode 100644 -void AppendStringIfPresent(PrefService* pref_service, - const std::string& pref_name, - base::StringPiece payload_key, -- base::Value& payload) { +- base::Value::Dict& payload) { - auto str = pref_service->GetString(pref_name); - if (!str.empty()) { -- payload.SetStringKey(payload_key, std::move(str)); +- payload.Set(payload_key, std::move(str)); - } -} -} // namespace @@ -2443,8 +2326,8 @@ deleted file mode 100644 -// static -std::string ActivepingTelemetryTopicProvider::DefaultAuthToken() { -#if defined(EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN) -- VLOG(1) << "[eyeo] Using " << EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN -- << " as Telemetry authentication token"; +- DVLOG(1) << "[eyeo] Using " << EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN +- << " as Telemetry authentication token"; - return EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN; -#else - LOG(WARNING) @@ -2464,29 +2347,28 @@ deleted file mode 100644 -} - -void ActivepingTelemetryTopicProvider::GetPayload(PayloadCallback callback) { -- base::Value payload(base::Value::Type::DICT); -- payload.SetStringKey("addon_name", "eyeo-chromium-sdk"); -- payload.SetStringKey("addon_version", "2.0.0"); -- payload.SetStringKey("application", app_info_.name); -- payload.SetStringKey("application_version", app_info_.version); -- payload.SetBoolKey("aa_active", -- adblock_controller_->IsAcceptableAdsEnabled()); -- payload.SetStringKey("platform", base::SysInfo::OperatingSystemName()); -- payload.SetStringKey("platform_version", -- base::SysInfo::OperatingSystemVersion()); +- base::Value::Dict payload; +- payload.Set("addon_name", "eyeo-chromium-sdk"); +- payload.Set("addon_version", "2.0.0"); +- payload.Set("application", app_info_.name); +- payload.Set("application_version", app_info_.version); +- payload.Set("aa_active", adblock_controller_->IsAcceptableAdsEnabled()); +- payload.Set("platform", base::SysInfo::OperatingSystemName()); +- payload.Set("platform_version", base::SysInfo::OperatingSystemVersion()); - // Server requires the following parameters to either have a correct, - // non-empty value, or not be present at all. We shall not send empty strings. -- AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTag, +- AppendStringIfPresent(pref_service_, common::prefs::kTelemetryLastPingTag, - "last_ping_tag", payload); -- AppendStringIfPresent(pref_service_, prefs::kTelemetryFirstPingTime, +- AppendStringIfPresent(pref_service_, common::prefs::kTelemetryFirstPingTime, - "first_ping", payload); -- AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTime, +- AppendStringIfPresent(pref_service_, common::prefs::kTelemetryLastPingTime, - "last_ping", payload); -- AppendStringIfPresent(pref_service_, prefs::kTelemetryPreviousLastPingTime, +- AppendStringIfPresent(pref_service_, +- common::prefs::kTelemetryPreviousLastPingTime, - "previous_last_ping", payload); - -- base::Value root(base::Value::Type::DICT); -- root.SetKey("payload", std::move(payload)); +- base::Value::Dict root; +- root.Set("payload", std::move(payload)); - std::string serialized; - // The only way JSONWriter::Write() can return fail is then the Value - // contains lists or dicts that are too deep (200 levels). We just built the @@ -2498,7 +2380,7 @@ deleted file mode 100644 - -base::Time ActivepingTelemetryTopicProvider::GetTimeOfNextRequest() const { - const auto next_ping_time = -- pref_service_->GetTime(prefs::kTelemetryNextPingTime); +- pref_service_->GetTime(common::prefs::kTelemetryNextPingTime); - // Next ping time may be unset if this is a first run. Next request should - // happen ASAP. - if (next_ping_time.is_null()) { @@ -2517,15 +2399,15 @@ deleted file mode 100644 - } - - VLOG(1) << "[eyeo] Response from Telemetry server: " << *response_content; -- auto parsed = base::JSONReader::Read(*response_content); -- if (!parsed || !parsed->is_dict()) { +- auto parsed = base::JSONReader::ReadDict(*response_content); +- if (!parsed) { - VLOG(1) - << "[eyeo] Telemetry ping failed, response could not be parsed as JSON"; - ScheduleNextPing(GetRetryPingInterval()); - return; - } - -- auto* error_message = parsed->FindStringKey("error"); +- auto* error_message = parsed->FindString("error"); - if (error_message) { - VLOG(1) << "[eyeo] Telemetry ping failed, error message: " - << *error_message; @@ -2537,7 +2419,7 @@ deleted file mode 100644 - // should be the server time of when the ping was handled, possibly truncated - // for anonymity. We don't parse it or interpret it, just send it back with - // next ping. -- auto* ping_response_time = parsed->FindStringKey("token"); +- auto* ping_response_time = parsed->FindString("token"); - if (!ping_response_time) { - VLOG(1) << "[eyeo] Telemetry ping failed, response did not contain a last " - "ping / token value"; @@ -2551,26 +2433,28 @@ deleted file mode 100644 -} - -void ActivepingTelemetryTopicProvider::ScheduleNextPing(base::TimeDelta delay) { -- pref_service_->SetTime(prefs::kTelemetryNextPingTime, +- pref_service_->SetTime(common::prefs::kTelemetryNextPingTime, - base::Time::Now() + delay); -} - -void ActivepingTelemetryTopicProvider::UpdatePrefs( - const std::string& ping_response_time) { - // First ping is only set once per client. -- if (pref_service_->GetString(prefs::kTelemetryFirstPingTime).empty()) { -- pref_service_->SetString(prefs::kTelemetryFirstPingTime, +- if (pref_service_->GetString(common::prefs::kTelemetryFirstPingTime) +- .empty()) { +- pref_service_->SetString(common::prefs::kTelemetryFirstPingTime, - ping_response_time); - } - // Previous-to-last becomes last, last becomes current. - pref_service_->SetString( -- prefs::kTelemetryPreviousLastPingTime, -- pref_service_->GetString(prefs::kTelemetryLastPingTime)); -- pref_service_->SetString(prefs::kTelemetryLastPingTime, ping_response_time); +- common::prefs::kTelemetryPreviousLastPingTime, +- pref_service_->GetString(common::prefs::kTelemetryLastPingTime)); +- pref_service_->SetString(common::prefs::kTelemetryLastPingTime, +- ping_response_time); - // Generate a new random tag that wil be sent along with ping times in the - // next request. -- const auto tag = base::GUID::GenerateRandomV4(); -- pref_service_->SetString(prefs::kTelemetryLastPingTag, +- const auto tag = base::Uuid::GenerateRandomV4(); +- pref_service_->SetString(common::prefs::kTelemetryLastPingTag, - tag.AsLowercaseString()); -} - @@ -2687,7 +2571,7 @@ diff --git a/components/adblock/core/adblock_controller.h b/components/adblock/c #include "components/keyed_service/core/keyed_service.h" class GURL; -@@ -57,6 +58,11 @@ class AdblockController : public KeyedService { +@@ -43,6 +44,11 @@ class AdblockController : public KeyedService { virtual void SetAcceptableAdsEnabled(bool enabled) = 0; virtual bool IsAcceptableAdsEnabled() const = 0; @@ -2702,7 +2586,7 @@ diff --git a/components/adblock/core/adblock_controller.h b/components/adblock/c diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adblock/core/adblock_controller_impl.cc --- a/components/adblock/core/adblock_controller_impl.cc +++ b/components/adblock/core/adblock_controller_impl.cc -@@ -129,6 +129,7 @@ bool AdblockControllerImpl::IsAdblockEnabled() const { +@@ -103,6 +103,7 @@ bool AdblockControllerImpl::IsAdblockEnabled() const { } void AdblockControllerImpl::SetAcceptableAdsEnabled(bool enabled) { @@ -2710,7 +2594,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb if (enabled) { InstallSubscription(AcceptableAdsUrl()); } else { -@@ -142,7 +143,33 @@ bool AdblockControllerImpl::IsAcceptableAdsEnabled() const { +@@ -116,7 +117,33 @@ bool AdblockControllerImpl::IsAcceptableAdsEnabled() const { [&](const auto& url) { return url == AcceptableAdsUrl(); }); } @@ -2744,8 +2628,8 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb adblock_filtering_configuration_->AddFilterList(url); } -@@ -241,10 +268,8 @@ void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) { - if (pref_service->GetBoolean(prefs::kInstallFirstStartSubscriptions)) { +@@ -165,10 +192,8 @@ void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) { + common::prefs::kInstallFirstStartSubscriptions)) { // On first run, install additional subscriptions. for (const auto& cur : known_subscriptions_) { - if (cur.first_run == SubscriptionFirstRunBehavior::Subscribe) { @@ -2757,7 +2641,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb // Do not install Acceptable Ads on first run because a command line // switch forbids it. Mostly used for testing. continue; -@@ -307,7 +332,7 @@ void AdblockControllerImpl::InstallLanguageBasedRecommendedSubscriptions() { +@@ -236,7 +261,7 @@ void AdblockControllerImpl::InstallLanguageBasedRecommendedSubscriptions() { SubscriptionFirstRunBehavior::SubscribeIfLocaleMatch && std::find(subscription.languages.begin(), subscription.languages.end(), language_) != subscription.languages.end()) { @@ -2769,7 +2653,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb diff --git a/components/adblock/core/adblock_controller_impl.h b/components/adblock/core/adblock_controller_impl.h --- a/components/adblock/core/adblock_controller_impl.h +++ b/components/adblock/core/adblock_controller_impl.h -@@ -62,6 +62,11 @@ class AdblockControllerImpl : public AdblockController, +@@ -58,6 +58,11 @@ class AdblockControllerImpl : public AdblockController { void SetAcceptableAdsEnabled(bool enabled) override; bool IsAcceptableAdsEnabled() const override; @@ -2778,9 +2662,9 @@ diff --git a/components/adblock/core/adblock_controller_impl.h b/components/adbl + void SetPrivilegedFiltersEnabled(bool enabled) override; + bool IsPrivilegedFiltersEnabled() override; + - void SelectBuiltInSubscription(const GURL& url) override; - void UnselectBuiltInSubscription(const GURL& url) override; - std::vector> GetSelectedBuiltInSubscriptions() + void InstallSubscription(const GURL& url) override; + void UninstallSubscription(const GURL& url) override; + std::vector> GetInstalledSubscriptions() diff --git a/components/adblock/core/adblock_switches.cc b/components/adblock/core/adblock_switches.cc --- a/components/adblock/core/adblock_switches.cc +++ b/components/adblock/core/adblock_switches.cc @@ -2790,7 +2674,7 @@ diff --git a/components/adblock/core/adblock_switches.cc b/components/adblock/co -const char kDisableAcceptableAds[] = "disable-aa"; const char kDisableAdblock[] = "disable-adblock"; - const char kDisableWebUiCompatibility[] = "disable-webui-compatibility"; + const char kDisableEyeoFiltering[] = "disable-eyeo-filtering"; diff --git a/components/adblock/core/adblock_switches.h b/components/adblock/core/adblock_switches.h --- a/components/adblock/core/adblock_switches.h @@ -2801,8 +2685,8 @@ diff --git a/components/adblock/core/adblock_switches.h b/components/adblock/cor -extern const char kDisableAcceptableAds[]; extern const char kDisableAdblock[]; - // TODO(mpawlowski) remove in 111, when this becomes standard: - extern const char kDisableWebUiCompatibility[]; + extern const char kDisableEyeoFiltering[]; + diff --git a/components/adblock/core/adblock_telemetry_service.cc b/components/adblock/core/adblock_telemetry_service.cc deleted file mode 100644 --- a/components/adblock/core/adblock_telemetry_service.cc @@ -3173,10 +3057,10 @@ diff --git a/components/adblock/core/common/BUILD.gn b/components/adblock/core/c -import("//components/adblock/features.gni") - - source_set("common") { - sources = [ - "adblock_constants.cc", -@@ -47,14 +45,6 @@ source_set("common") { + config("eyeo_filtering_config") { + defines = [] + +@@ -59,14 +57,6 @@ source_set("common") { config("eyeo_application_config") { defines = [] @@ -3206,7 +3090,7 @@ diff --git a/components/adblock/core/common/adblock_constants.cc b/components/ad diff --git a/components/adblock/core/common/adblock_constants.h b/components/adblock/core/common/adblock_constants.h --- a/components/adblock/core/common/adblock_constants.h +++ b/components/adblock/core/common/adblock_constants.h -@@ -27,7 +27,6 @@ namespace flat { +@@ -28,7 +28,6 @@ namespace flat { enum AbpResource : int8_t; } @@ -3218,7 +3102,7 @@ diff --git a/components/adblock/core/common/adblock_prefs.cc b/components/adbloc --- a/components/adblock/core/common/adblock_prefs.cc +++ b/components/adblock/core/common/adblock_prefs.cc @@ -23,7 +23,9 @@ - namespace adblock::prefs { + namespace adblock::common::prefs { // Whether to block ads -const char kEnableAdblockLegacy[] = "adblock.enable"; @@ -3291,7 +3175,7 @@ diff --git a/components/adblock/core/common/adblock_prefs.h b/components/adblock --- a/components/adblock/core/common/adblock_prefs.h +++ b/components/adblock/core/common/adblock_prefs.h @@ -23,6 +23,7 @@ class PrefRegistrySimple; - namespace adblock::prefs { + namespace adblock::common::prefs { extern const char kEnableAdblockLegacy[]; +extern const char kAllowPrivilegedFilters[]; @@ -3354,15 +3238,15 @@ diff --git a/components/adblock/core/configuration/filtering_configuration.h b/c diff --git a/components/adblock/core/configuration/persistent_filtering_configuration.cc b/components/adblock/core/configuration/persistent_filtering_configuration.cc --- a/components/adblock/core/configuration/persistent_filtering_configuration.cc +++ b/components/adblock/core/configuration/persistent_filtering_configuration.cc -@@ -24,6 +24,7 @@ - #include "base/strings/string_util.h" +@@ -25,6 +25,7 @@ + #include "components/adblock/core/configuration/filtering_configuration_prefs.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/adblock/core/common/adblock_prefs.h" - namespace adblock { - namespace { -@@ -134,6 +135,7 @@ const std::string& PersistentFilteringConfiguration::GetName() const { + #include "base/logging.h" + +@@ -135,6 +136,7 @@ const std::string& PersistentFilteringConfiguration::GetName() const { } void PersistentFilteringConfiguration::SetEnabled(bool enabled) { @@ -3370,7 +3254,7 @@ diff --git a/components/adblock/core/configuration/persistent_filtering_configur if (IsEnabled() == enabled) { return; } -@@ -142,6 +144,14 @@ void PersistentFilteringConfiguration::SetEnabled(bool enabled) { +@@ -143,6 +145,14 @@ void PersistentFilteringConfiguration::SetEnabled(bool enabled) { NotifyEnabledStateChanged(); } @@ -3383,7 +3267,7 @@ diff --git a/components/adblock/core/configuration/persistent_filtering_configur +} + bool PersistentFilteringConfiguration::IsEnabled() const { - const auto pref_value = dictionary_.GetDict().FindBool(kEnabledKey); + const auto pref_value = dictionary_.FindBool(kEnabledKey); DCHECK(pref_value); diff --git a/components/adblock/core/configuration/persistent_filtering_configuration.h b/components/adblock/core/configuration/persistent_filtering_configuration.h --- a/components/adblock/core/configuration/persistent_filtering_configuration.h @@ -3413,7 +3297,7 @@ diff --git a/components/adblock/core/converter/flatbuffer_converter.cc b/compone diff --git a/components/adblock/core/converter/parser/metadata.cc b/components/adblock/core/converter/parser/metadata.cc --- a/components/adblock/core/converter/parser/metadata.cc +++ b/components/adblock/core/converter/parser/metadata.cc -@@ -57,13 +57,6 @@ absl::optional Metadata::FromStream(std::istream& filter_stream) { +@@ -58,13 +58,6 @@ absl::optional Metadata::FromStream(std::istream& filter_stream) { if (key == "homepage") { homepage = value; } else if (key == "redirect") { @@ -3427,7 +3311,7 @@ diff --git a/components/adblock/core/converter/parser/metadata.cc b/components/a } else if (key == "title") { title = value; } else if (key == "version") { -@@ -106,6 +99,7 @@ Metadata::~Metadata() = default; +@@ -107,6 +100,7 @@ Metadata::~Metadata() = default; // static bool Metadata::IsValidAdblockHeader(const std::string& adblock_header) { @@ -3435,7 +3319,7 @@ diff --git a/components/adblock/core/converter/parser/metadata.cc b/components/a static re2::RE2 adblock_header_re("^\\[Adblock.*\\]"); std::string adblock_header_trimmed; -@@ -130,7 +124,7 @@ base::TimeDelta Metadata::ParseExpirationTime( +@@ -131,7 +125,7 @@ base::TimeDelta Metadata::ParseExpirationTime( if (!re2::RE2::FullMatch(expiration_value, expiration_time_re, &expiration_time, &expiration_unit)) { @@ -3635,7 +3519,7 @@ diff --git a/components/adblock/core/converter/serializer/flatbuffer_serializer. class Buffer : public FlatbufferData { public: explicit Buffer(flatbuffers::DetachedBuffer&& buffer) -@@ -119,9 +174,25 @@ void FlatbufferSerializer::SerializeContentFilter( +@@ -118,9 +173,25 @@ void FlatbufferSerializer::SerializeContentFilter( void FlatbufferSerializer::SerializeSnippetFilter( const SnippetFilter snippet_filter) { if (!allow_privileged_) { @@ -3662,7 +3546,7 @@ diff --git a/components/adblock/core/converter/serializer/flatbuffer_serializer. std::vector> offsets; offsets.reserve(snippet_filter.snippet_script.size()); -@@ -143,7 +214,7 @@ void FlatbufferSerializer::SerializeSnippetFilter( +@@ -141,7 +212,7 @@ void FlatbufferSerializer::SerializeSnippetFilter( void FlatbufferSerializer::SerializeUrlFilter(const UrlFilter url_filter) { const auto& options = url_filter.options; if (!allow_privileged_ && options.Headers().has_value()) { @@ -3744,7 +3628,7 @@ diff --git a/components/adblock/core/subscription/filtering_configuration_mainta diff --git a/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc --- a/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc +++ b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc -@@ -250,6 +250,19 @@ void FilteringConfigurationMaintainerImpl::RemoveDuplicateSubscriptions() { +@@ -254,6 +254,19 @@ void FilteringConfigurationMaintainerImpl::RemoveDuplicateSubscriptions() { unique_subscriptions.end()); } @@ -3764,7 +3648,7 @@ diff --git a/components/adblock/core/subscription/filtering_configuration_mainta void FilteringConfigurationMaintainerImpl::RunUpdateCheck() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); VLOG(1) << "[eyeo] Running update check"; -@@ -282,7 +295,6 @@ void FilteringConfigurationMaintainerImpl::RunUpdateCheck() { +@@ -286,7 +299,6 @@ void FilteringConfigurationMaintainerImpl::RunUpdateCheck() { AcceptableAdsUrl(); }) && persistent_metadata_->IsExpired(AcceptableAdsUrl())) { @@ -3772,7 +3656,7 @@ diff --git a/components/adblock/core/subscription/filtering_configuration_mainta } } -@@ -374,15 +386,6 @@ void FilteringConfigurationMaintainerImpl::SubscriptionAddedToStorage( +@@ -378,15 +390,6 @@ void FilteringConfigurationMaintainerImpl::SubscriptionAddedToStorage( subscription_updated_callback_.Run(subscription->GetSourceUrl()); } @@ -3788,7 +3672,7 @@ diff --git a/components/adblock/core/subscription/filtering_configuration_mainta void FilteringConfigurationMaintainerImpl::OnHeadRequestDone( const std::string version) { if (version.empty()) { -@@ -395,20 +398,20 @@ void FilteringConfigurationMaintainerImpl::OnHeadRequestDone( +@@ -399,20 +402,20 @@ void FilteringConfigurationMaintainerImpl::OnHeadRequestDone( void FilteringConfigurationMaintainerImpl::UninstallSubscription( const GURL& subscription_url) { @@ -3991,7 +3875,7 @@ diff --git a/components/adblock/core/subscription/subscription.h b/components/ad diff --git a/components/adblock/core/subscription/subscription_collection_impl.cc b/components/adblock/core/subscription/subscription_collection_impl.cc --- a/components/adblock/core/subscription/subscription_collection_impl.cc +++ b/components/adblock/core/subscription/subscription_collection_impl.cc -@@ -426,6 +426,7 @@ std::set SubscriptionCollectionImpl::GetHeaderFilters( +@@ -342,6 +342,7 @@ std::set SubscriptionCollectionImpl::GetHeaderFilters( ContentType content_type, FilterCategory category) const { std::set filters{}; @@ -4197,7 +4081,7 @@ diff --git a/components/adblock/core/subscription/subscription_persistent_metada namespace adblock { @@ -146,6 +147,12 @@ void SubscriptionPersistentMetadataImpl::UpdatePrefs() { - prefs_->SetDict(prefs::kSubscriptionMetadata, std::move(dict)); + prefs_->SetDict(common::prefs::kSubscriptionMetadata, std::move(dict)); } +bool SubscriptionPersistentMetadataImpl::AllowPrivilegedFilters( @@ -4207,8 +4091,8 @@ diff --git a/components/adblock/core/subscription/subscription_persistent_metada +} + void SubscriptionPersistentMetadataImpl::LoadFromPrefs() { - const base::Value& dict = prefs_->GetValue(prefs::kSubscriptionMetadata); - DCHECK(dict.is_dict()); + const base::Value& dict = + prefs_->GetValue(common::prefs::kSubscriptionMetadata); diff --git a/components/adblock/core/subscription/subscription_persistent_metadata_impl.h b/components/adblock/core/subscription/subscription_persistent_metadata_impl.h --- a/components/adblock/core/subscription/subscription_persistent_metadata_impl.h +++ b/components/adblock/core/subscription/subscription_persistent_metadata_impl.h @@ -4271,7 +4155,7 @@ diff --git a/components/adblock/core/subscription/subscription_persistent_storag diff --git a/components/adblock/core/subscription/subscription_service.h b/components/adblock/core/subscription/subscription_service.h --- a/components/adblock/core/subscription/subscription_service.h +++ b/components/adblock/core/subscription/subscription_service.h -@@ -69,6 +69,9 @@ class SubscriptionService : public KeyedService { +@@ -77,6 +77,9 @@ class SubscriptionService : public KeyedService { // concurrently, and future changes to the installed subscriptions will not // impact it. virtual Snapshot GetCurrentSnapshot() const = 0; @@ -4284,8 +4168,8 @@ diff --git a/components/adblock/core/subscription/subscription_service.h b/compo diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b/components/adblock/core/subscription/subscription_service_impl.cc --- a/components/adblock/core/subscription/subscription_service_impl.cc +++ b/components/adblock/core/subscription/subscription_service_impl.cc -@@ -113,6 +113,18 @@ void SubscriptionServiceImpl::InstallFilteringConfiguration( - } +@@ -133,6 +133,18 @@ void SubscriptionServiceImpl::UninstallFilteringConfiguration( + maintainers_.erase(it); } +raw_ptr SubscriptionServiceImpl::GetMetadataFor( @@ -4303,7 +4187,7 @@ diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b std::vector SubscriptionServiceImpl::GetInstalledFilteringConfigurations() { std::vector result; -@@ -143,6 +155,15 @@ SubscriptionService::Snapshot SubscriptionServiceImpl::GetCurrentSnapshot() +@@ -163,6 +175,15 @@ SubscriptionService::Snapshot SubscriptionServiceImpl::GetCurrentSnapshot() return snapshot; } @@ -4319,7 +4203,7 @@ diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b void SubscriptionServiceImpl::AddObserver(SubscriptionObserver* o) { observers_.AddObserver(o); } -@@ -158,7 +179,7 @@ void SubscriptionServiceImpl::OnEnabledStateChanged( +@@ -178,7 +199,7 @@ void SubscriptionServiceImpl::OnEnabledStateChanged( }); DCHECK(it != maintainers_.end()) << "Received OnEnabledStateChanged from " "unregistered FilteringConfiguration"; @@ -4331,7 +4215,7 @@ diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b diff --git a/components/adblock/core/subscription/subscription_service_impl.h b/components/adblock/core/subscription/subscription_service_impl.h --- a/components/adblock/core/subscription/subscription_service_impl.h +++ b/components/adblock/core/subscription/subscription_service_impl.h -@@ -65,6 +65,9 @@ class SubscriptionServiceImpl final : public SubscriptionService, +@@ -70,6 +70,9 @@ class SubscriptionServiceImpl final : public SubscriptionService, final; FilteringConfiguration* GetAdblockFilteringConfiguration() const final; Snapshot GetCurrentSnapshot() const final; @@ -4388,55 +4272,6 @@ diff --git a/components/adblock/core/subscription/subscription_validator_impl.cc return false; } return true; -diff --git a/components/adblock/features.gni b/components/adblock/features.gni -deleted file mode 100644 ---- a/components/adblock/features.gni -+++ /dev/null -@@ -1,44 +0,0 @@ --# --# This file is part of eyeo Chromium SDK, --# Copyright (C) 2006-present eyeo GmbH --# --# eyeo Chromium SDK is free software: you can redistribute it and/or modify --# it under the terms of the GNU General Public License version 3 as --# published by the Free Software Foundation. --# --# eyeo Chromium SDK is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with eyeo Chromium SDK. If not, see . -- --declare_args() { -- # eyeo Chromium SDK telemetry client id, provided on per-partner basis by eyeo. Used to -- # attribute usage reports to specific browsers. -- eyeo_telemetry_client_id = "" -- -- # eyeo Chromium SDK telemetry server address, by default evaluated to -- # "https://${eyeo_telemetry_client_id}.telemetry.eyeo.com/". -- # Override only for testing. -- eyeo_telemetry_server_url = "" -- -- # eyeo Chromium SDK telemetry authentication token, provided on per-partner basis by eyeo. -- eyeo_telemetry_activeping_auth_token = "" -- -- # eyeo Chromium SDK application name to be used in telemetry and -- # filter list download requests. If not set the value returned by -- # version_info::GetProductName() will be used instead. -- eyeo_application_name = "" -- -- # eyeo Chromium SDK application version to be used in telemetry and -- # filter list download requests. If not set the value returned by -- # version_info::GetVersionNumber() will be used instead. -- eyeo_application_version = "" -- -- # If true then requests to "adblock.test.data" domain will be intercepted -- # in order to allow installing/removing/listing filter lists via navigating to -- # special URLs. This is used for internal automated testing (see DPD-1407). -- eyeo_intercept_debug_url = false --} diff --git a/components/content_settings/core/browser/bromite_content_settings/ads.inc b/components/content_settings/core/browser/bromite_content_settings/ads.inc new file mode 100644 --- /dev/null @@ -8247,7 +8082,7 @@ new file mode 100755 diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc -@@ -600,6 +600,14 @@ void StyleEngine::UpdateActiveStyleSheetsInShadow( +@@ -623,6 +623,14 @@ void StyleEngine::UpdateActiveStyleSheetsInShadow( } } diff --git a/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch b/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch new file mode 100644 index 00000000..8eedb271 --- /dev/null +++ b/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch @@ -0,0 +1,48 @@ +From: uazo +Date: Tue, 5 Sep 2023 12:55:40 +0000 +Subject: Remove GoogleAccountsPrivateApiHost + +--- + .../browser/chrome_content_browser_client_receiver_bindings.cc | 2 +- + chrome/browser/signin/google_accounts_private_api_host.cc | 2 +- + chrome/renderer/chrome_content_renderer_client.cc | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc +--- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc ++++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc +@@ -543,7 +543,7 @@ void ChromeContentBrowserClient:: + chrome::mojom::GoogleAccountsPrivateApiExtension>(base::BindRepeating( + [](content::RenderFrameHost* render_frame_host, + mojo::PendingAssociatedReceiver< +- chrome::mojom::GoogleAccountsPrivateApiExtension> receiver) { ++ chrome::mojom::GoogleAccountsPrivateApiExtension_UAZO_REMOVE_IT> receiver) { + GoogleAccountsPrivateApiHost::BindHost(std::move(receiver), + render_frame_host); + }, +diff --git a/chrome/browser/signin/google_accounts_private_api_host.cc b/chrome/browser/signin/google_accounts_private_api_host.cc +--- a/chrome/browser/signin/google_accounts_private_api_host.cc ++++ b/chrome/browser/signin/google_accounts_private_api_host.cc +@@ -9,7 +9,7 @@ + #include "content/public/browser/navigation_handle.h" + #include "content/public/browser/render_frame_host.h" + +-GoogleAccountsPrivateApiHost::GoogleAccountsPrivateApiHost( ++GoogleAccountsPrivateApiHost::GoogleAccountsPrivateApiHost_UAZO_REMOVE_IT( + content::RenderFrameHost* rfh, + base::RepeatingCallback + on_consent_result_callback) +diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc +--- a/chrome/renderer/chrome_content_renderer_client.cc ++++ b/chrome/renderer/chrome_content_renderer_client.cc +@@ -644,7 +644,7 @@ void ChromeContentRendererClient::RenderFrameCreated( + #endif + + TrustedVaultEncryptionKeysExtension::Create(render_frame); +- GoogleAccountsPrivateApiExtension::Create(render_frame); ++ GoogleAccountsPrivateApiExtension::Create(render_frame); (UAZO) REMOVE IT + + if (render_frame->IsMainFrame()) + new webapps::WebPageMetadataAgent(render_frame); +-- +2.25.1 From 250b213a99ca257dc1812b840165d6b1dcd56836 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 5 Sep 2023 16:27:22 +0200 Subject: [PATCH 03/17] bump to 117.0.5938.35 --- build/RELEASE | 2 +- build/bromite_patches_list.txt | 29 +++++++++-------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/build/RELEASE b/build/RELEASE index 73a11681..4be02e71 100644 --- a/build/RELEASE +++ b/build/RELEASE @@ -1 +1 @@ -116.0.5845.163 \ No newline at end of file +117.0.5938.35 \ No newline at end of file diff --git a/build/bromite_patches_list.txt b/build/bromite_patches_list.txt index bbdb0d26..ab34ba92 100644 --- a/build/bromite_patches_list.txt +++ b/build/bromite_patches_list.txt @@ -1,3 +1,10 @@ +eyeo-117.0.5938.0-base.patch +eyeo-117.0.5938.0-chrome_integration.patch +eyeo-117.0.5938.0-android_api.patch +eyeo-117.0.5938.0-android_settings.patch +eyeo-117.0.5938.0-extension_api.patch +00Eyeo-Adblock-Remove-Privacy-Issues.patch + Remove-EV-certificates.patch do-not-hide-.orig-files.patch Do-not-link-with-libatomic.patch @@ -74,7 +81,6 @@ translate-disable-fetching-of-languages-from-server.patch Offer-builtin-autocomplete-for-chrome-flags.patch Use-4-tile-rows-never-show-logo.patch Disable-various-metrics.patch - Enable-StrictOriginIsolation-and-SitePerProcess.patch Use-64-bit-WebView-processes.patch prefs-always-prompt-for-download-directory.patch @@ -184,24 +190,6 @@ Enable-third-party-storage-partitioning.patch Restore-adaptive-button-in-top-toolbar-customization.patch Add-kill-switch-for-unsupported-clangd-flags.patch -eyeo-beta-114.0.5735.53-v1-base.patch -eyeo-beta-114.0.5735.53-v1-android_settings.patch -eyeo-beta-114.0.5735.53-v1-extension_api.patch -00Eyeo-Adblock-Remove-Privacy-Issues.patch - -00WIN-ADDTO-Experimental-user-scripts-support.patch -00WIN-ADDTO-ungoogled-chr--Disable-profile-avatar.patch -00WIN-ADDTO-Add-a-proxy-configuration-page.patch -00WIN-ADDTO-Add-bookmark-import-export-actions.patch -00WIN-ADDTO-openH264--enable-ARM-ARM64-optimizati.patch -00WIN-ADDTO-AImageReader-CFI-crash-mitigations.patch -00WIN-ADDTO-Disable-various-metrics.patch -00WIN-ADDTO-Do-not-build-API-keys-infobar.patch -00WIN-ADDTO-Revert-flags--remove-num-raster-thre.patch -00WIN-ADDTO-Restore-Search-Ready-Omnibox-flag.patch -00WIN-ADDTO-Disable-requests-for-single-word-Omni.patch -00WIN-ADDTO-Logcat-crash-reports-UI.patch -00WIN-ADDTO-Add-AllowUserCertificates-flag.patch 00WIN-enable-pdf-plugin.patch 00WIN-disable-annotate-downloads.patch 00WIN-enable-HighEfficiencyMode-by-default.patch @@ -287,4 +275,5 @@ Timezone-customization.patch 00Temp-disable-predictive-back-gesture.patch 00Add-option-to-disable-snapshots.patch 00Disable-PartnerCustomizations.patch -00Enable-Android-Dynamic-Performance-Framework.patch \ No newline at end of file +00Enable-Android-Dynamic-Performance-Framework.patch +00Remove-GoogleAccountsPrivateApiHost.patch \ No newline at end of file From d5133f33d342b2f052592296975b499112e0945f Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Thu, 7 Sep 2023 12:58:57 +0200 Subject: [PATCH 04/17] v117 final patches --- build/bromite_patches_list.txt | 16 +- ...le-find-bad-constructs-external-repo.patch | 59 -- ...Plus-add-blocking-in-service-workers.patch | 732 ++++++++++++++++++ .../00Add-setting-to-clear-data-on-exit.patch | 2 +- build/patches/00Disable-WebGPU.patch | 2 +- ...00Eyeo-Adblock-Remove-Privacy-Issues.patch | 368 +++++---- build/patches/00Fix-chromium-build-bugs.patch | 374 +++++++++ .../00Fix-crash-on-customize-profile-ui.patch | 23 + ...ix-eyeo-Browser-Ad-filtering-patches.patch | 147 ++++ build/patches/00Internal-firewall.patch | 2 +- ...ulti-Screen-Window-Placement-API-fix.patch | 17 +- ...0Remove-GoogleAccountsPrivateApiHost.patch | 116 ++- .../00Restore-LastTabStandingTracker.patch | 4 +- build/patches/00v113-temp-fix-build.patch | 37 - .../Add-bookmark-import-export-actions.patch | 2 +- ...Add-lifetime-options-for-permissions.patch | 28 +- .../Add-option-to-use-home-page-as-NTP.patch | 55 +- ...ow-building-without-supervised-users.patch | 202 ++++- ...Block-gateway-attacks-via-websockets.patch | 45 +- .../Bromite-subresource-adblocker.patch | 10 +- .../Content-settings-infrastructure.patch | 226 ++---- build/patches/Disable-all-promo-dialogs.patch | 47 +- .../Disable-conversion-measurement-api.patch | 14 +- build/patches/Disable-safety-check.patch | 6 +- .../Do-not-build-API-keys-infobar.patch | 2 +- .../Enable-Certificate-Transparency.patch | 14 +- .../Enable-native-Android-autofill.patch | 2 +- .../Experimental-user-scripts-support.patch | 13 +- build/patches/Logcat-crash-reports-UI.patch | 2 +- .../Move-navigation-bar-to-bottom.patch | 16 +- .../Multiple-fingerprinting-mitigations.patch | 2 +- .../Remove-binary-blob-integrations.patch | 78 +- build/patches/Site-setting-for-images.patch | 9 +- build/patches/Timezone-customization.patch | 18 +- ...ed-chromium-no-special-hosts-domains.patch | 2 +- 35 files changed, 2096 insertions(+), 596 deletions(-) delete mode 100644 build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch create mode 100644 build/patches/00AdblockPlus-add-blocking-in-service-workers.patch create mode 100644 build/patches/00Fix-chromium-build-bugs.patch create mode 100644 build/patches/00Fix-crash-on-customize-profile-ui.patch create mode 100644 build/patches/00Fix-eyeo-Browser-Ad-filtering-patches.patch delete mode 100644 build/patches/00v113-temp-fix-build.patch diff --git a/build/bromite_patches_list.txt b/build/bromite_patches_list.txt index ab34ba92..d5159d45 100644 --- a/build/bromite_patches_list.txt +++ b/build/bromite_patches_list.txt @@ -3,7 +3,9 @@ eyeo-117.0.5938.0-chrome_integration.patch eyeo-117.0.5938.0-android_api.patch eyeo-117.0.5938.0-android_settings.patch eyeo-117.0.5938.0-extension_api.patch +00Fix-eyeo-Browser-Ad-filtering-patches.patch 00Eyeo-Adblock-Remove-Privacy-Issues.patch +00AdblockPlus-add-blocking-in-service-workers.patch Remove-EV-certificates.patch do-not-hide-.orig-files.patch @@ -202,7 +204,6 @@ Add-kill-switch-for-unsupported-clangd-flags.patch 00WIN-Add-some-prefs-to-secure-preferences.patch 00WIN-Disable-search-for-image.patch -00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch 00Remove-experimental-relative-c---abi-vtables.patch AudioBuffer-AnalyserNode-fp-mitigations.patch 00Disable-Component-Updates.patch @@ -244,10 +245,6 @@ AudioBuffer-AnalyserNode-fp-mitigations.patch 00Disallow-Android-App-Scheme-as-referrer.patch 00Deprecate-Data-URL-in-SVGUseElement.patch -00TEMP-Add-a-log-to-track-strange-behavior.patch -00v113-temp-fix-build.patch -00114-temp-disable-find-bad-constructs-external-repo.patch - bromite-build-utils.patch Content-settings-infrastructure.patch Add-autoplay-site-setting.patch @@ -272,8 +269,13 @@ Timezone-customization.patch 00do-not-block-build-incompatible-profiles.patch 00Allow-DocumentPiP-if-PopupsAndRedirects-are-active.patch 00allow-the-download-of-clang-for-windows-crossbuild.patch -00Temp-disable-predictive-back-gesture.patch 00Add-option-to-disable-snapshots.patch 00Disable-PartnerCustomizations.patch 00Enable-Android-Dynamic-Performance-Framework.patch -00Remove-GoogleAccountsPrivateApiHost.patch \ No newline at end of file +00Remove-GoogleAccountsPrivateApiHost.patch +00Fix-crash-on-customize-profile-ui.patch + +00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch +00Temp-disable-predictive-back-gesture.patch +00TEMP-Add-a-log-to-track-strange-behavior.patch +00Fix-chromium-build-bugs.patch \ No newline at end of file diff --git a/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch b/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch deleted file mode 100644 index bf37cee2..00000000 --- a/build/patches/00114-temp-disable-find-bad-constructs-external-repo.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: uazo -Date: Tue, 30 May 2023 15:45:59 +0000 -Subject: 114 temp disable find_bad_constructs external repo - -License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html ---- - build/config/android/rules.gni | 1 + - crypto/BUILD.gn | 1 + - net/BUILD.gn | 1 + - third_party/libevent/BUILD.gn | 2 ++ - 4 files changed, 5 insertions(+) - -diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni ---- a/build/config/android/rules.gni -+++ b/build/config/android/rules.gni -@@ -4989,6 +4989,7 @@ if (enable_java_templates && is_android) { - _module_build_config = _module.build_config - _module_build_config_target = _module.build_config_target - _module_target_name = get_label_info(_module_target, "name") -+ not_needed(["_module_target_name"]) - - if (!_proguard_enabled) { - _dex_target = "${_module_target_name}__final_dex" -diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn ---- a/crypto/BUILD.gn -+++ b/crypto/BUILD.gn -@@ -14,6 +14,7 @@ buildflag_header("buildflags") { - } - - component("crypto") { -+ configs -= [ "//build/config/clang:find_bad_constructs" ] - output_name = "crcrypto" # Avoid colliding with OpenSSL's libcrypto. - sources = [ - "aead.cc", -diff --git a/net/BUILD.gn b/net/BUILD.gn ---- a/net/BUILD.gn -+++ b/net/BUILD.gn -@@ -1657,6 +1657,7 @@ component("net") { - configs -= [ "//build/config/compiler:default_optimization" ] - configs += [ "//build/config/compiler:optimize_max" ] - } -+ configs -= [ "//build/config/clang:find_bad_constructs" ] - } - - # net_export.h has its own build target so that code (eg -diff --git a/third_party/libevent/BUILD.gn b/third_party/libevent/BUILD.gn ---- a/third_party/libevent/BUILD.gn -+++ b/third_party/libevent/BUILD.gn -@@ -69,6 +69,8 @@ static_library("libevent") { - configs += [ "//build/config/compiler:optimize_max" ] - } - -+ configs -= [ "//build/config/clang:find_bad_constructs" ] -+ - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] - } --- -2.25.1 diff --git a/build/patches/00AdblockPlus-add-blocking-in-service-workers.patch b/build/patches/00AdblockPlus-add-blocking-in-service-workers.patch new file mode 100644 index 00000000..fba22ba8 --- /dev/null +++ b/build/patches/00AdblockPlus-add-blocking-in-service-workers.patch @@ -0,0 +1,732 @@ +From: uazo +Date: Thu, 7 Sep 2023 07:25:25 +0000 +Subject: AdblockPlus add blocking in service workers + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html +--- + .../adblock/adblock_content_browser_client.cc | 184 ++++++++++++------ + .../adblock/adblock_content_browser_client.h | 27 ++- + .../browser/chrome_content_browser_client.cc | 6 +- + .../browser/chrome_content_browser_client.h | 6 +- + .../browser/adblock_url_loader_factory.cc | 10 +- + .../browser/adblock_url_loader_factory.h | 3 + + .../browser/frame_hierarchy_builder.cc | 3 +- + .../browser/resource_classification_runner.h | 8 + + .../resource_classification_runner_impl.cc | 30 ++- + .../resource_classification_runner_impl.h | 8 + + .../websockets/websocket_connector_impl.cc | 6 +- + .../public/browser/content_browser_client.cc | 4 +- + .../public/browser/content_browser_client.h | 4 +- + 13 files changed, 216 insertions(+), 83 deletions(-) + +diff --git a/chrome/browser/adblock/adblock_content_browser_client.cc b/chrome/browser/adblock/adblock_content_browser_client.cc +--- a/chrome/browser/adblock/adblock_content_browser_client.cc ++++ b/chrome/browser/adblock/adblock_content_browser_client.cc +@@ -45,6 +45,7 @@ + #include "content/public/browser/web_contents.h" + #include "mojo/public/cpp/bindings/self_owned_receiver.h" + #include "services/network/public/mojom/websocket.mojom.h" ++#include "services/network/public/mojom/web_transport.mojom.h" + #include "services/service_manager/public/cpp/binder_registry.h" + #include "third_party/blink/public/common/loader/url_loader_throttle.h" + +@@ -58,6 +59,29 @@ + + namespace { + ++bool IsFilteringNeeded(Profile* profile, const GURL& embedder_url) { ++ DCHECK(profile); ++ ++ if(embedder_url.is_empty()) { ++ // in android can be empty because it was created by ++ // RenderFrameHostImpl::CreateSubresourceLoaderFactoriesForInitialEmptyDocument ++ return true; ++ } ++ ++ HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile); ++ if (settings_map && settings_map->GetContentSetting(embedder_url, GURL(), ContentSettingsType::ADS) ++ == CONTENT_SETTING_ALLOW) { ++ return false; ++ } ++ // Filtering may be needed if there's at least one enabled ++ // FilteringConfiguration. ++ bool ret = base::ranges::any_of( ++ adblock::SubscriptionServiceFactory::GetForBrowserContext(profile) ++ ->GetInstalledFilteringConfigurations(), ++ &adblock::FilteringConfiguration::IsEnabled); ++ return ret; ++} ++ + bool IsFilteringNeeded(content::RenderFrameHost* frame) { + if (frame) { + auto* profile = +@@ -65,17 +89,7 @@ bool IsFilteringNeeded(content::RenderFrameHost* frame) { + if (profile) { + content::RenderFrameHost* embedder = frame->GetOutermostMainFrameOrEmbedder(); + const auto& embedder_url = embedder->GetLastCommittedURL(); +- HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile); +- if (settings_map && settings_map->GetContentSetting(embedder_url, GURL(), ContentSettingsType::ADS) +- == CONTENT_SETTING_ALLOW) { +- return false; +- } +- // Filtering may be needed if there's at least one enabled +- // FilteringConfiguration. +- return base::ranges::any_of( +- adblock::SubscriptionServiceFactory::GetForBrowserContext(profile) +- ->GetInstalledFilteringConfigurations(), +- &adblock::FilteringConfiguration::IsEnabled); ++ return IsFilteringNeeded(profile, embedder_url); + } + } + return false; +@@ -90,6 +104,8 @@ class AdblockContextData : public base::SupportsUserData::Data { + + static void StartProxying( + Profile* profile, ++ content::BrowserContext* browser_context, ++ const url::Origin& request_initiator, + content::RenderFrameHost* frame, + int render_process_id, + mojo::PendingReceiver receiver, +@@ -102,8 +118,6 @@ class AdblockContextData : public base::SupportsUserData::Data { + self = new AdblockContextData(); + profile->SetUserData(kAdblockContextUserDataKey, base::WrapUnique(self)); + } +- auto* browser_context = +- content::WebContents::FromRenderFrameHost(frame)->GetBrowserContext(); + adblock::AdblockURLLoaderFactoryConfig config{ + adblock::SubscriptionServiceFactory::GetForBrowserContext( + browser_context), +@@ -115,8 +129,9 @@ class AdblockContextData : public base::SupportsUserData::Data { + browser_context)}; + auto proxy = std::make_unique( + std::move(config), ++ request_initiator.GetURL(), + content::GlobalRenderFrameHostId(render_process_id, +- frame->GetRoutingID()), ++ frame ? frame->GetRoutingID() : MSG_ROUTING_NONE), + std::move(receiver), std::move(target_factory), + embedder_support::GetUserAgent(), + base::BindOnce(&AdblockContextData::RemoveProxy, +@@ -157,47 +172,50 @@ void AdblockContentBrowserClient::ForceAdblockProxyForTesting() { + #endif + + bool AdblockContentBrowserClient::WillInterceptWebSocket( +- content::RenderFrameHost* frame) { ++ content::RenderFrameHost* frame, ++ content::RenderProcessHost* process, ++ const url::Origin& origin) { + if (IsFilteringNeeded(frame)) { + return true; ++ } else { ++ auto* browser_context = process->GetBrowserContext(); ++ auto* profile = Profile::FromBrowserContext(browser_context); ++ if (IsFilteringNeeded(profile, origin.GetURL().GetAsReferrer())) { ++ return true; ++ } + } + +- return ChromeContentBrowserClient::WillInterceptWebSocket(frame); ++ return ChromeContentBrowserClient::WillInterceptWebSocket(frame, process, origin); + } + + void AdblockContentBrowserClient::CreateWebSocket( ++ content::RenderProcessHost* process, + content::RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client) { +- if (IsFilteringNeeded(frame)) { +- CreateWebSocketInternal(frame->GetGlobalId(), std::move(factory), url, +- site_for_cookies, user_agent, +- std::move(handshake_client)); +- } else { +- DCHECK(ChromeContentBrowserClient::WillInterceptWebSocket(frame)); +- ChromeContentBrowserClient::CreateWebSocket(frame, std::move(factory), url, +- site_for_cookies, user_agent, +- std::move(handshake_client)); +- } ++ CreateWebSocketInternal(process, ++ frame ? frame->GetGlobalId() : content::GlobalRenderFrameHostId(), ++ std::move(factory), url, initiator_origin, ++ site_for_cookies, user_agent, ++ std::move(handshake_client)); + } + + void AdblockContentBrowserClient::CreateWebSocketInternal( ++ content::RenderProcessHost* process, + content::GlobalRenderFrameHostId render_frame_host_id, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client) { +- auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); +- if (!frame) { +- return; +- } +- auto* browser_context = frame->GetProcess()->GetBrowserContext(); ++ auto* browser_context = process->GetBrowserContext(); + auto* subscription_service = + adblock::SubscriptionServiceFactory::GetForBrowserContext( + browser_context); +@@ -205,33 +223,33 @@ void AdblockContentBrowserClient::CreateWebSocketInternal( + adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( + browser_context); + classification_runner->CheckRequestFilterMatchForWebSocket( +- subscription_service->GetCurrentSnapshot(), url, render_frame_host_id, ++ subscription_service->GetCurrentSnapshot(), url, ++ std::move(initiator_origin.GetURL().GetAsReferrer()), render_frame_host_id, + base::BindOnce( + &AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted, +- weak_factory_.GetWeakPtr(), render_frame_host_id, std::move(factory), +- url, site_for_cookies, user_agent, std::move(handshake_client))); ++ weak_factory_.GetWeakPtr(), process, render_frame_host_id, std::move(factory), ++ url, initiator_origin, site_for_cookies, user_agent, std::move(handshake_client))); + } + + void AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted( ++ content::RenderProcessHost* process, + content::GlobalRenderFrameHostId render_frame_host_id, + ChromeContentBrowserClient::WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client, + adblock::FilterMatchResult result) { + auto* frame = content::RenderFrameHost::FromID(render_frame_host_id); +- if (!frame) { +- return; +- } + const bool has_blocking_filter = + result == adblock::FilterMatchResult::kBlockRule; + if (!has_blocking_filter) { + VLOG(1) << "[eyeo] Web socket allowed for " << url; +- if (ChromeContentBrowserClient::WillInterceptWebSocket(frame)) { ++ if (ChromeContentBrowserClient::WillInterceptWebSocket(frame, process, initiator_origin)) { + ChromeContentBrowserClient::CreateWebSocket( +- frame, std::move(factory), url, site_for_cookies, user_agent, ++ process, frame, std::move(factory), url, initiator_origin, site_for_cookies, user_agent, + std::move(handshake_client)); + return; + } +@@ -248,6 +266,72 @@ void AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted( + VLOG(1) << "[eyeo] Web socket blocked for " << url; + } + ++void AdblockContentBrowserClient::WillCreateWebTransport( ++ int process_id, ++ int frame_routing_id, ++ const GURL& url, ++ const url::Origin& initiator_origin, ++ mojo::PendingRemote ++ handshake_client, ++ WillCreateWebTransportCallback callback) { ++ auto* process = content::RenderProcessHost::FromID(process_id); ++ DCHECK(process); ++ ++ auto* browser_context = process->GetBrowserContext(); ++ auto* profile = Profile::FromBrowserContext(browser_context); ++ if (IsFilteringNeeded(profile, initiator_origin.GetURL().GetAsReferrer())) { ++ auto* subscription_service = ++ adblock::SubscriptionServiceFactory::GetForBrowserContext( ++ browser_context); ++ auto* classification_runner = ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ browser_context); ++ ++ classification_runner->CheckRequestFilterMatchForWebTransport( ++ subscription_service->GetCurrentSnapshot(), url, ++ std::move(initiator_origin.GetURL().GetAsReferrer()), ++ content::GlobalRenderFrameHostId(), ++ base::BindOnce( ++ &AdblockContentBrowserClient::OnWebTransportFilterCheckCompleted, ++ weak_factory_.GetWeakPtr(), ++ process_id, frame_routing_id, url, ++ std::move(initiator_origin), std::move(handshake_client), ++ std::move(callback))); ++ return; ++ } ++ ++ ChromeContentBrowserClient::WillCreateWebTransport( ++ process_id, frame_routing_id, ++ url, std::move(initiator_origin), ++ std::move(handshake_client), std::move(callback)); ++} ++ ++void AdblockContentBrowserClient::OnWebTransportFilterCheckCompleted( ++ int process_id, ++ int frame_routing_id, ++ const GURL& url, ++ const url::Origin& initiator_origin, ++ mojo::PendingRemote ++ handshake_client, ++ WillCreateWebTransportCallback callback, ++ adblock::FilterMatchResult result) { ++ const bool has_blocking_filter = ++ result == adblock::FilterMatchResult::kBlockRule; ++ if (!has_blocking_filter) { ++ VLOG(1) << "[eyeo] Web transport allowed for " << url; ++ ChromeContentBrowserClient::WillCreateWebTransport( ++ process_id, frame_routing_id, ++ url, std::move(initiator_origin), ++ std::move(handshake_client), std::move(callback)); ++ return; ++ } ++ VLOG(1) << "[eyeo] Web transport blocked for " << url; ++ std::move(callback).Run(std::move(handshake_client), ++ network::mojom::WebTransportError::New( ++ net::ERR_BLOCKED_BY_ADMINISTRATOR, quic::QUIC_INTERNAL_ERROR, ++ "Blocked", false)); ++} ++ + bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( + content::BrowserContext* browser_context, + content::RenderFrameHost* frame, +@@ -271,24 +355,12 @@ bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( + navigation_id, ukm_source_id, factory_receiver, header_client, + bypass_redirect_checks, disable_secure_dns, factory_override, + navigation_response_task_runner); +- auto* profile = frame ? Profile::FromBrowserContext( +- frame->GetProcess()->GetBrowserContext()) +- : nullptr; +- +-#if BUILDFLAG(ENABLE_EXTENSIONS) +- if (!force_adblock_proxy_for_testing_ && +- request_initiator.scheme() == extensions::kExtensionScheme) { +- VLOG(1) << "[eyeo] Do not use adblock proxy for extensions requests " +- "[extension id:" +- << request_initiator.host() << "]."; +- return use_chrome_proxy; +- } +-#endif ++ auto* profile = Profile::FromBrowserContext(browser_context); + + bool use_adblock_proxy = +- (type == URLLoaderFactoryType::kDocumentSubResource || +- type == URLLoaderFactoryType::kNavigation) && +- IsFilteringNeeded(frame); ++ type != URLLoaderFactoryType::kDownload && ++ (frame ? IsFilteringNeeded(frame) ++ : IsFilteringNeeded(profile, request_initiator.GetURL().GetAsReferrer())); + + bool use_test_loader = false; + #ifdef EYEO_INTERCEPT_DEBUG_URL +@@ -307,7 +379,7 @@ bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( + mojo::PendingRemote target_factory_remote; + *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver(); + AdblockContextData::StartProxying( +- profile, frame, render_process_id, std::move(proxied_receiver), ++ profile, browser_context, request_initiator, frame, render_process_id, std::move(proxied_receiver), + std::move(target_factory_remote), use_test_loader); + } + return use_adblock_proxy || use_chrome_proxy; +diff --git a/chrome/browser/adblock/adblock_content_browser_client.h b/chrome/browser/adblock/adblock_content_browser_client.h +--- a/chrome/browser/adblock/adblock_content_browser_client.h ++++ b/chrome/browser/adblock/adblock_content_browser_client.h +@@ -44,16 +44,27 @@ class AdblockContentBrowserClient : public ChromeContentBrowserClient { + static void ForceAdblockProxyForTesting(); + #endif + +- bool WillInterceptWebSocket(content::RenderFrameHost* frame) override; ++ bool WillInterceptWebSocket(content::RenderFrameHost* frame, content::RenderProcessHost* process, const url::Origin& origin) override; + void CreateWebSocket( ++ content::RenderProcessHost* process, + content::RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client) override; + ++ void WillCreateWebTransport( ++ int process_id, ++ int frame_routing_id, ++ const GURL& url, ++ const url::Origin& initiator_origin, ++ mojo::PendingRemote ++ handshake_client, ++ WillCreateWebTransportCallback callback) override; ++ + bool WillCreateURLLoaderFactory( + content::BrowserContext* browser_context, + content::RenderFrameHost* frame, +@@ -73,23 +84,35 @@ class AdblockContentBrowserClient : public ChromeContentBrowserClient { + + private: + void CreateWebSocketInternal( ++ content::RenderProcessHost* process, + content::GlobalRenderFrameHostId render_frame_host_id, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client); + void OnWebSocketFilterCheckCompleted( ++ content::RenderProcessHost* process, + content::GlobalRenderFrameHostId render_frame_host_id, + ChromeContentBrowserClient::WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote + handshake_client, + adblock::FilterMatchResult result); +- ++ void OnWebTransportFilterCheckCompleted( ++ int process_id, ++ int frame_routing_id, ++ const GURL& url, ++ const url::Origin& initiator_origin, ++ mojo::PendingRemote ++ handshake_client, ++ WillCreateWebTransportCallback callback, ++ adblock::FilterMatchResult result); + base::WeakPtrFactory weak_factory_{this}; + + #if BUILDFLAG(ENABLE_EXTENSIONS) +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -6252,7 +6252,9 @@ ChromeContentBrowserClient:: + } + + bool ChromeContentBrowserClient::WillInterceptWebSocket( +- content::RenderFrameHost* frame) { ++ content::RenderFrameHost* frame, ++ content::RenderProcessHost* process, ++ const url::Origin& origin) { + #if BUILDFLAG(ENABLE_EXTENSIONS) + if (!frame) { + return false; +@@ -6273,9 +6275,11 @@ bool ChromeContentBrowserClient::WillInterceptWebSocket( + } + + void ChromeContentBrowserClient::CreateWebSocket( ++ content::RenderProcessHost* process, + content::RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote +diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h +--- a/chrome/browser/chrome_content_browser_client.h ++++ b/chrome/browser/chrome_content_browser_client.h +@@ -610,11 +610,15 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { + CreateURLLoaderHandlerForServiceWorkerNavigationPreload( + int frame_tree_node_id, + const network::ResourceRequest& resource_request) override; +- bool WillInterceptWebSocket(content::RenderFrameHost* frame) override; ++ bool WillInterceptWebSocket(content::RenderFrameHost* frame, ++ content::RenderProcessHost* process, ++ const url::Origin& origin) override; + void CreateWebSocket( ++ content::RenderProcessHost* process, + content::RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote +diff --git a/components/adblock/content/browser/adblock_url_loader_factory.cc b/components/adblock/content/browser/adblock_url_loader_factory.cc +--- a/components/adblock/content/browser/adblock_url_loader_factory.cc ++++ b/components/adblock/content/browser/adblock_url_loader_factory.cc +@@ -342,12 +342,6 @@ void AdblockURLLoaderFactory::InProgressRequest::OnRequestError( + + void AdblockURLLoaderFactory::InProgressRequest::CheckFilterMatch( + CheckFilterMatchCallback callback) { +- if (!factory_->CheckHostValid()) { +- PostFilterMatchCallbackToUI(std::move(callback), +- FilterMatchResult::kNoRule); +- return; +- } +- + auto subscription_service = factory_->config_.subscription_service; + if (is_document_request_) { + auto* host = content::RenderFrameHost::FromID(factory_->host_id_); +@@ -386,7 +380,7 @@ void AdblockURLLoaderFactory::InProgressRequest::CheckFilterMatch( + } else { + factory_->config_.resource_classifier->CheckRequestFilterMatch( + subscription_service->GetCurrentSnapshot(), request_url_, +- adblock_resource_type_, factory_->host_id_, ++ factory_->request_initiator_, adblock_resource_type_, factory_->host_id_, + base::BindOnce( + &AdblockURLLoaderFactory::InProgressRequest::OnRequestUrlClassified, + weak_factory_.GetWeakPtr(), +@@ -675,12 +669,14 @@ void AdblockURLLoaderFactory::InProgressRequest::OnRequestFilterMatchResult( + + AdblockURLLoaderFactory::AdblockURLLoaderFactory( + AdblockURLLoaderFactoryConfig config, ++ GURL request_initiator, + content::GlobalRenderFrameHostId host_id, + mojo::PendingReceiver receiver, + mojo::PendingRemote target_factory, + std::string user_agent_string, + DisconnectCallback on_disconnect) + : config_(std::move(config)), ++ request_initiator_(std::move(request_initiator)), + host_id_(host_id), + user_agent_string_(std::move(user_agent_string)), + on_disconnect_(std::move(on_disconnect)) { +diff --git a/components/adblock/content/browser/adblock_url_loader_factory.h b/components/adblock/content/browser/adblock_url_loader_factory.h +--- a/components/adblock/content/browser/adblock_url_loader_factory.h ++++ b/components/adblock/content/browser/adblock_url_loader_factory.h +@@ -25,6 +25,7 @@ + #include "mojo/public/cpp/bindings/receiver_set.h" + #include "mojo/public/cpp/bindings/remote.h" + #include "services/network/public/mojom/url_loader_factory.mojom.h" ++#include "url/gurl.h" + + namespace adblock { + +@@ -49,6 +50,7 @@ class AdblockURLLoaderFactory : public network::mojom::URLLoaderFactory { + + AdblockURLLoaderFactory( + AdblockURLLoaderFactoryConfig config, ++ GURL request_initiator, + content::GlobalRenderFrameHostId host_id, + mojo::PendingReceiver receiver, + mojo::PendingRemote target_factory, +@@ -78,6 +80,7 @@ class AdblockURLLoaderFactory : public network::mojom::URLLoaderFactory { + void MaybeDestroySelf(); + + AdblockURLLoaderFactoryConfig config_; ++ const GURL request_initiator_; + content::GlobalRenderFrameHostId host_id_; + mojo::ReceiverSet proxy_receivers_; + std::set, base::UniquePtrComparator> +diff --git a/components/adblock/content/browser/frame_hierarchy_builder.cc b/components/adblock/content/browser/frame_hierarchy_builder.cc +--- a/components/adblock/content/browser/frame_hierarchy_builder.cc ++++ b/components/adblock/content/browser/frame_hierarchy_builder.cc +@@ -76,9 +76,8 @@ std::vector FrameHierarchyBuilder::BuildFrameHierarchy( + content::RenderFrameHost* host) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + +- DCHECK(host) << "RenderFrameHost is needed to build frame hierarchy"; +- + std::vector referrers_chain; ++ if (!host) return referrers_chain; + for (auto* iter = host; iter; iter = iter->GetParent()) { + auto last_commited_referrer = GetUrlAsReferrer(iter); + if (IsValidForFrameHierarchy(last_commited_referrer)) { +diff --git a/components/adblock/content/browser/resource_classification_runner.h b/components/adblock/content/browser/resource_classification_runner.h +--- a/components/adblock/content/browser/resource_classification_runner.h ++++ b/components/adblock/content/browser/resource_classification_runner.h +@@ -81,14 +81,22 @@ class ResourceClassificationRunner : public KeyedService { + virtual void CheckRequestFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + ContentType adblock_resource_type, + content::GlobalRenderFrameHostId render_frame_host_id, + CheckFilterMatchCallback callback) = 0; + virtual void CheckRequestFilterMatchForWebSocket( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + content::GlobalRenderFrameHostId render_frame_host_id, + CheckFilterMatchCallback callback) = 0; ++ virtual void CheckRequestFilterMatchForWebTransport( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const GURL& request_initiator, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback); + // No callback, just notify observers + virtual void CheckDocumentAllowlisted( + SubscriptionService::Snapshot subscription_collection, +diff --git a/components/adblock/content/browser/resource_classification_runner_impl.cc b/components/adblock/content/browser/resource_classification_runner_impl.cc +--- a/components/adblock/content/browser/resource_classification_runner_impl.cc ++++ b/components/adblock/content/browser/resource_classification_runner_impl.cc +@@ -169,15 +169,28 @@ void ResourceClassificationRunnerImpl::CheckPopupFilterMatch( + void ResourceClassificationRunnerImpl::CheckRequestFilterMatchForWebSocket( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + content::GlobalRenderFrameHostId render_frame_host_id, + CheckFilterMatchCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(request_url.SchemeIsWSOrWSS()); +- CheckRequestFilterMatch(std::move(subscription_collections), request_url, ++ CheckRequestFilterMatch(std::move(subscription_collections), request_url, request_initiator, + ContentType::Websocket, render_frame_host_id, + std::move(callback)); + } + ++void ResourceClassificationRunnerImpl::CheckRequestFilterMatchForWebTransport( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const GURL& request_initiator, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ CheckRequestFilterMatch(std::move(subscription_collections), request_url, request_initiator, ++ ContentType::Other, render_frame_host_id, ++ std::move(callback)); ++} ++ + void ResourceClassificationRunnerImpl::CheckDocumentAllowlisted( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, +@@ -212,6 +225,7 @@ void ResourceClassificationRunnerImpl::ProcessDocumentAllowlistedResponse( + void ResourceClassificationRunnerImpl::CheckRequestFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + ContentType adblock_resource_type, + content::GlobalRenderFrameHostId frame_host_id, + CheckFilterMatchCallback callback) { +@@ -220,14 +234,10 @@ void ResourceClassificationRunnerImpl::CheckRequestFilterMatch( + DVLOG(1) << "[eyeo] CheckRequestFilterMatchImpl for " << request_url.spec(); + + auto* host = content::RenderFrameHost::FromID(frame_host_id); +- if (!host) { +- // Host has died, likely because this is a deferred execution. It does not +- // matter anymore whether the resource is blocked, the page is gone. +- std::move(callback).Run(FilterMatchResult::kNoRule); +- return; +- } +- const std::vector frame_hierarchy_chain = ++ std::vector frame_hierarchy_chain = + frame_hierarchy_builder_->BuildFrameHierarchy(host); ++ if (!host && frame_hierarchy_chain.size() == 0) ++ frame_hierarchy_chain.emplace_back(request_initiator.GetAsReferrer()); + + DVLOG(1) << "[eyeo] Got " << frame_hierarchy_chain.size() + << " frame_hierarchy for " << request_url.spec(); +@@ -275,7 +285,8 @@ ResourceClassificationRunnerImpl::CheckRequestFilterMatchInternal( + adblock_resource_type, sitekey); + + if (classification_result.decision == ClassificationDecision::Allowed) { +- VLOG(1) << "[eyeo] Document allowed due to allowing filter " << request_url; ++ VLOG(1) << "[eyeo] Document allowed due to allowing filter " << request_url ++ << " " << classification_result.decisive_subscription.spec(); + return CheckResourceFilterMatchResult{ + FilterMatchResult::kAllowRule, + classification_result.decisive_subscription, +@@ -290,6 +301,7 @@ ResourceClassificationRunnerImpl::CheckRequestFilterMatchInternal( + classification_result.decisive_configuration_name}; + } + ++ VLOG(1) << "[eyeo] No Rule for " << request_url; + return CheckResourceFilterMatchResult{FilterMatchResult::kNoRule, {}, {}}; + } + +diff --git a/components/adblock/content/browser/resource_classification_runner_impl.h b/components/adblock/content/browser/resource_classification_runner_impl.h +--- a/components/adblock/content/browser/resource_classification_runner_impl.h ++++ b/components/adblock/content/browser/resource_classification_runner_impl.h +@@ -55,12 +55,14 @@ class ResourceClassificationRunnerImpl final + void CheckRequestFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + ContentType adblock_resource_type, + content::GlobalRenderFrameHostId render_frame_host_id, + CheckFilterMatchCallback callback) final; + void CheckRequestFilterMatchForWebSocket( + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, ++ const GURL& request_initiator, + content::GlobalRenderFrameHostId render_frame_host_id, + CheckFilterMatchCallback callback) final; + // No callback, just notify observers +@@ -68,6 +70,12 @@ class ResourceClassificationRunnerImpl final + SubscriptionService::Snapshot subscription_collections, + const GURL& request_url, + content::GlobalRenderFrameHostId render_frame_host_id) final; ++ void CheckRequestFilterMatchForWebTransport( ++ SubscriptionService::Snapshot subscription_collections, ++ const GURL& request_url, ++ const GURL& request_initiator, ++ content::GlobalRenderFrameHostId render_frame_host_id, ++ CheckFilterMatchCallback callback) final; + void CheckResponseFilterMatch( + SubscriptionService::Snapshot subscription_collections, + const GURL& response_url, +diff --git a/content/browser/websockets/websocket_connector_impl.cc b/content/browser/websockets/websocket_connector_impl.cc +--- a/content/browser/websockets/websocket_connector_impl.cc ++++ b/content/browser/websockets/websocket_connector_impl.cc +@@ -87,14 +87,14 @@ void WebSocketConnectorImpl::Connect( + const uint32_t options = + GetContentClient()->browser()->GetWebSocketOptions(frame); + +- if (GetContentClient()->browser()->WillInterceptWebSocket(frame)) { ++ if (GetContentClient()->browser()->WillInterceptWebSocket(frame, process, origin_)) { + GetContentClient()->browser()->CreateWebSocket( +- frame, ++ process, frame, + base::BindOnce(ConnectCalledByContentBrowserClient, requested_protocols, + site_for_cookies, isolation_info_, process_id_, + frame_id_, origin_, options, + std::move(throttling_profile_id)), +- url, site_for_cookies, user_agent, std::move(handshake_client)); ++ url, origin_, site_for_cookies, user_agent, std::move(handshake_client)); + return; + } + std::vector headers; +diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc +--- a/content/public/browser/content_browser_client.cc ++++ b/content/public/browser/content_browser_client.cc +@@ -967,7 +967,7 @@ bool ContentBrowserClient::WillCreateURLLoaderFactory( + return false; + } + +-bool ContentBrowserClient::WillInterceptWebSocket(RenderFrameHost*) { ++bool ContentBrowserClient::WillInterceptWebSocket(RenderFrameHost*, RenderProcessHost*, const url::Origin& origin) { + return false; + } + +@@ -976,9 +976,11 @@ uint32_t ContentBrowserClient::GetWebSocketOptions(RenderFrameHost* frame) { + } + + void ContentBrowserClient::CreateWebSocket( ++ RenderProcessHost* process, + RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote +diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h +--- a/content/public/browser/content_browser_client.h ++++ b/content/public/browser/content_browser_client.h +@@ -1746,7 +1746,7 @@ class CONTENT_EXPORT ContentBrowserClient { + scoped_refptr navigation_response_task_runner); + + // Returns true when the embedder wants to intercept a websocket connection. +- virtual bool WillInterceptWebSocket(RenderFrameHost* frame); ++ virtual bool WillInterceptWebSocket(RenderFrameHost* frame, RenderProcessHost* process, const url::Origin& origin); + + // Returns the WebSocket creation options. + virtual uint32_t GetWebSocketOptions(RenderFrameHost* frame); +@@ -1768,9 +1768,11 @@ class CONTENT_EXPORT ContentBrowserClient { + // Always called on the UI thread and only when the Network Service is + // enabled. + virtual void CreateWebSocket( ++ RenderProcessHost* process, + RenderFrameHost* frame, + WebSocketFactory factory, + const GURL& url, ++ const url::Origin& initiator_origin, + const net::SiteForCookies& site_for_cookies, + const absl::optional& user_agent, + mojo::PendingRemote +-- +2.25.1 diff --git a/build/patches/00Add-setting-to-clear-data-on-exit.patch b/build/patches/00Add-setting-to-clear-data-on-exit.patch index c483feee..4490154d 100644 --- a/build/patches/00Add-setting-to-clear-data-on-exit.patch +++ b/build/patches/00Add-setting-to-clear-data-on-exit.patch @@ -384,7 +384,7 @@ diff --git a/chrome/browser/profiles/android/profile_manager_utils.cc b/chrome/b diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc -@@ -1449,6 +1449,19 @@ void ProfileManager::DoFinalInit(ProfileInfo* profile_info, +@@ -1451,6 +1451,19 @@ void ProfileManager::DoFinalInit(ProfileInfo* profile_info, } } diff --git a/build/patches/00Disable-WebGPU.patch b/build/patches/00Disable-WebGPU.patch index f9a17b6e..c2b5a83e 100644 --- a/build/patches/00Disable-WebGPU.patch +++ b/build/patches/00Disable-WebGPU.patch @@ -27,7 +27,7 @@ diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blin "WebGPU is experimental on this platform. See " "https://github.com/gpuweb/gpuweb/wiki/" "Implementation-Status#implementation-status")); -+ (UAZO) add exception ++ //(UAZO) add site setting } auto* resolver = MakeGarbageCollected(script_state); diff --git a/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch index b2fe6fb2..ae26bf09 100644 --- a/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch +++ b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch @@ -5,12 +5,11 @@ Subject: Eyeo Adblock for Bromite Change the normal behaviour of Eyeo Chromium SDK to suit Bromite logic --- - .../android/java/res/xml/main_preferences.xml | 11 +- + .../android/java/res/xml/main_preferences.xml | 19 +- chrome/browser/BUILD.gn | 2 - .../adblock/adblock_content_browser_client.cc | 26 +- - .../adblock/subscription_service_factory.h | 1 + chrome/browser/android/adblock/adblock_jni.cc | 50 +- - .../adblock_private/adblock_private_api.cc | 68 +- + .../adblock_private/adblock_private_api.cc | 66 +- .../api/adblock_private/adblock_private_api.h | 49 + .../eyeo_filtering_private_api.cc | 20 +- ...hrome_browser_main_extra_parts_profiles.cc | 2 - @@ -24,12 +23,12 @@ suit Bromite logic chrome/browser/resources/settings/router.ts | 1 + chrome/browser/resources/settings/settings.ts | 1 + .../settings/settings_menu/settings_menu.html | 5 + - chrome/browser/ui/tab_helpers.cc | 5 +- + chrome/browser/ui/tab_helpers.cc | 6 +- .../extensions/api/_permission_features.json | 8 - .../common/extensions/api/adblock_private.idl | 8 + chrome/test/BUILD.gn | 5 - - components/adblock/android/BUILD.gn | 2 +- - .../adblock/android/adblock_strings.grd | 48 +- + components/adblock/android/BUILD.gn | 4 +- + .../adblock/android/adblock_strings.grd | 54 +- .../java/res/layout/adblock_custom_item.xml | 14 +- .../layout/adblock_filter_lists_list_item.xml | 15 + ...ences.xml => eyeo_adblock_preferences.xml} | 39 +- @@ -40,25 +39,24 @@ suit Bromite logic .../settings/AdblockCustomItemFragment.java | 20 +- .../settings/AdblockFilterListsAdapter.java | 6 + .../settings/AdblockSettingsFragment.java | 45 +- - components/adblock/content/browser/BUILD.gn | 16 +- - .../adblock_controller_factory_base.cc | 2 +- - .../adblock_telemetry_service_factory_base.cc | 49 - - .../adblock_telemetry_service_factory_base.h | 24 - + components/adblock/content/browser/BUILD.gn | 18 +- + .../adblock_controller_factory_base.cc | 5 +- .../browser/adblock_webcontents_observer.cc | 25 +- .../browser/adblock_webcontents_observer.h | 5 +- .../content_security_policy_injector_impl.cc | 1 + - .../subscription_service_factory_base.cc | 10 +- + .../subscription_service_factory_base.cc | 11 +- + .../subscription_service_factory_base.h | 1 + components/adblock/core/BUILD.gn | 39 - .../activeping_telemetry_topic_provider.cc | 243 -- .../activeping_telemetry_topic_provider.h | 84 - - components/adblock/core/adblock_controller.h | 6 + - .../adblock/core/adblock_controller_impl.cc | 35 +- - .../adblock/core/adblock_controller_impl.h | 5 + + components/adblock/core/adblock_controller.h | 8 + + .../adblock/core/adblock_controller_impl.cc | 58 +- + .../adblock/core/adblock_controller_impl.h | 7 + components/adblock/core/adblock_switches.cc | 1 - components/adblock/core/adblock_switches.h | 1 - .../adblock/core/adblock_telemetry_service.cc | 244 -- .../adblock/core/adblock_telemetry_service.h | 107 - - components/adblock/core/common/BUILD.gn | 10 - + components/adblock/core/common/BUILD.gn | 8 - .../adblock/core/common/adblock_constants.cc | 2 - .../adblock/core/common/adblock_constants.h | 1 - .../adblock/core/common/adblock_prefs.cc | 47 +- @@ -107,8 +105,9 @@ suit Bromite logic .../blink/renderer/core/css/style_engine.cc | 8 + .../blink/renderer/core/css/style_engine.h | 1 + .../renderer/core/exported/web_document.cc | 13 +- + tools/gritsettings/resource_ids.spec | 9 +- .../definitions/adblock_private.d.ts | 14 + - 103 files changed, 5038 insertions(+), 1142 deletions(-) + 102 files changed, 5079 insertions(+), 1083 deletions(-) create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.html create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.ts rename components/adblock/android/java/res/xml/{adblock_preferences.xml => eyeo_adblock_preferences.xml} (56%) @@ -138,15 +137,30 @@ diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/j -@@ -106,7 +97,7 @@ Use of this source code is governed by the GPLv3 that can be found in the compon - android:title="@string/prefs_accessibility"/> - ++ ++ android:order="13" ++ android:title="@string/adblock_settings_title" /> +- + ( std::move(config), content::GlobalRenderFrameHostId(render_process_id, -diff --git a/chrome/browser/adblock/subscription_service_factory.h b/chrome/browser/adblock/subscription_service_factory.h ---- a/chrome/browser/adblock/subscription_service_factory.h -+++ b/chrome/browser/adblock/subscription_service_factory.h -@@ -34,6 +34,7 @@ class SubscriptionServiceFactory : public SubscriptionServiceFactoryBase { - protected: - PrefService* GetPrefs(content::BrowserContext* context) const override; - SubscriptionPersistentMetadata* GetSubscriptionPersistentMetadata( -+ bool allow_privileged_filter, - content::BrowserContext* context) const override; - - private: diff --git a/chrome/browser/android/adblock/adblock_jni.cc b/chrome/browser/android/adblock/adblock_jni.cc --- a/chrome/browser/android/adblock/adblock_jni.cc +++ b/chrome/browser/android/adblock/adblock_jni.cc @@ -414,15 +417,6 @@ diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.c AdblockPrivateSetEnabledFunction::AdblockPrivateSetEnabledFunction() {} AdblockPrivateSetEnabledFunction::~AdblockPrivateSetEnabledFunction() {} -@@ -403,7 +431,7 @@ AdblockPrivateIsAcceptableAdsEnabledFunction::Run() { - browser_context()); - return RespondNow(ArgumentList( - api::adblock_private::IsAcceptableAdsEnabled::Results::Create( -- controller->IsAcceptableAdsEnabled()))); -+ controller, controller->IsAcceptableAdsEnabled()))); - } - - AdblockPrivateGetBuiltInSubscriptionsFunction:: @@ -486,7 +514,7 @@ AdblockPrivateGetInstalledSubscriptionsFunction::Run() { browser_context()); return RespondNow(ArgumentList( @@ -1169,7 +1163,15 @@ diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc -@@ -353,6 +353,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { +@@ -21,6 +21,7 @@ + #include "chrome/browser/adblock/element_hider_factory.h" + #include "chrome/browser/adblock/sitekey_storage_factory.h" + #include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" + #include "chrome/browser/bookmarks/bookmark_model_factory.h" + #include "chrome/browser/breadcrumbs/breadcrumb_manager_tab_helper.h" + #include "chrome/browser/browser_process.h" +@@ -349,6 +350,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { } #endif @@ -1178,7 +1180,7 @@ diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc AdblockWebContentObserver::CreateForWebContents( web_contents, adblock::SubscriptionServiceFactory::GetForBrowserContext( -@@ -361,7 +363,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { +@@ -357,7 +360,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { web_contents->GetBrowserContext()), adblock::SitekeyStorageFactory::GetForBrowserContext( web_contents->GetBrowserContext()), @@ -1263,6 +1265,15 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BUILD.gn --- a/components/adblock/android/BUILD.gn +++ b/components/adblock/android/BUILD.gn +@@ -53,7 +53,7 @@ android_library("adblock_java") { + "//third_party/androidx:androidx_preference_preference_java", + ] + +- annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] ++ srcjar_deps = [ ":jni_headers" ] + resources_package = "org.chromium.components.adblock" + } + @@ -91,7 +91,7 @@ android_resources("java_resources") { "java/res/layout/adblock_custom_item_settings.xml", "java/res/layout/adblock_filter_lists_list_item.xml", @@ -1275,10 +1286,13 @@ diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BU diff --git a/components/adblock/android/adblock_strings.grd b/components/adblock/android/adblock_strings.grd --- a/components/adblock/android/adblock_strings.grd +++ b/components/adblock/android/adblock_strings.grd -@@ -188,8 +188,50 @@ +@@ -186,10 +186,52 @@ + + - Ad blocking - +- Ad blocking ++ Adblock Plus settings ++ + + Enable Adblock Plus + @@ -1320,31 +1334,39 @@ diff --git a/components/adblock/android/adblock_strings.grd b/components/adblock + + + Custom Filters (%s selected) -+ + - Allow ad blocking on websites in this app + Block ads on websites Filter lists -@@ -219,7 +261,7 @@ - Custom ad filtering settings +@@ -216,10 +258,10 @@ + More blocking options + + +- Custom ad filtering settings ++ Custom ad filtering urls - Add custom filter lists -+ Add custom filter commands ++ Add custom filter urls https://example.org/myFilterList.txt -@@ -228,7 +270,7 @@ +@@ -228,10 +270,10 @@ Custom Filters - Add custom filters -+ Add custom filter urls ++ Add custom filter commands - Enter filter +- Enter filter ++ Enter filter command + + + diff --git a/components/adblock/android/java/res/layout/adblock_custom_item.xml b/components/adblock/android/java/res/layout/adblock_custom_item.xml --- a/components/adblock/android/java/res/layout/adblock_custom_item.xml +++ b/components/adblock/android/java/res/layout/adblock_custom_item.xml @@ -1873,7 +1895,16 @@ diff --git a/components/adblock/content/browser/BUILD.gn b/components/adblock/co } source_set("browser_impl") { -@@ -62,15 +55,10 @@ source_set("browser_impl") { +@@ -34,8 +27,6 @@ source_set("browser_impl") { + "adblock_controller_factory_base.cc", + "adblock_controller_factory_base.h", + "adblock_filter_match.h", +- "adblock_telemetry_service_factory_base.cc", +- "adblock_telemetry_service_factory_base.h", + "adblock_url_loader_factory.cc", + "adblock_url_loader_factory.h", + "adblock_webcontents_observer.cc", +@@ -62,15 +53,10 @@ source_set("browser_impl") { ] @@ -1894,106 +1925,18 @@ diff --git a/components/adblock/content/browser/BUILD.gn b/components/adblock/co diff --git a/components/adblock/content/browser/adblock_controller_factory_base.cc b/components/adblock/content/browser/adblock_controller_factory_base.cc --- a/components/adblock/content/browser/adblock_controller_factory_base.cc +++ b/components/adblock/content/browser/adblock_controller_factory_base.cc -@@ -47,7 +47,7 @@ KeyedService* AdblockControllerFactoryBase::BuildServiceInstanceFor( +@@ -47,10 +47,7 @@ KeyedService* AdblockControllerFactoryBase::BuildServiceInstanceFor( std::make_unique( prefs, kAdblockFilteringConfigurationName); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( -+ if ((true) && base::CommandLine::ForCurrentProcess()->HasSwitch( - adblock::switches::kDisableAcceptableAds)) { - adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); - } -diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc ---- a/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc -+++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.cc -@@ -48,53 +48,4 @@ base::TimeDelta GetCheckInterval() { - - } // namespace - --AdblockTelemetryServiceFactoryBase::AdblockTelemetryServiceFactoryBase() -- : BrowserContextKeyedServiceFactory( -- "AdblockTelemetryService", -- BrowserContextDependencyManager::GetInstance()) {} -- --AdblockTelemetryServiceFactoryBase::~AdblockTelemetryServiceFactoryBase() = -- default; -- --KeyedService* AdblockTelemetryServiceFactoryBase::BuildServiceInstanceFor( -- content::BrowserContext* context) const { -- // Need to use a URLLoaderFactory specific to the browser context, not from -- // system_network_context_manager(), because the required Accept-Language -- // header depends on user's language settings and is not present in requests -- // made from the System network context. -- scoped_refptr url_loader_factory = -- context->GetDefaultStoragePartition() -- ->GetURLLoaderFactoryForBrowserProcess(); -- auto* prefs = GetPrefs(context); -- auto service = std::make_unique( -- GetSubscriptionService(context)->GetAdblockFilteringConfiguration(), -- url_loader_factory, GetInitialDelay(), GetCheckInterval()); -- service->AddTopicProvider(std::make_unique( -- utils::GetAppInfo(), prefs, GetAdblockController(context), -- ActivepingTelemetryTopicProvider::DefaultBaseUrl(), -- ActivepingTelemetryTopicProvider::DefaultAuthToken())); -- -- if (url_loader_factory) { -- service->Start(); +- adblock::switches::kDisableAcceptableAds)) { +- adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); - } -- -- return service.release(); --} -- --bool AdblockTelemetryServiceFactoryBase::ServiceIsNULLWhileTesting() const { -- return true; --} -- --bool AdblockTelemetryServiceFactoryBase::ServiceIsCreatedWithBrowserContext() -- const { -- return true; --} -- --void AdblockTelemetryServiceFactoryBase::SetCheckAndDelayIntervalsForTesting( -- base::TimeDelta check_interval, -- base::TimeDelta initial_delay) { -- g_check_interval_for_testing = check_interval; -- g_initial_delay_for_testing = initial_delay; --} -- - } // namespace adblock -diff --git a/components/adblock/content/browser/adblock_telemetry_service_factory_base.h b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h ---- a/components/adblock/content/browser/adblock_telemetry_service_factory_base.h -+++ b/components/adblock/content/browser/adblock_telemetry_service_factory_base.h -@@ -27,30 +27,6 @@ namespace adblock { - - class AdblockController; - class SubscriptionService; --class AdblockTelemetryServiceFactoryBase -- : public BrowserContextKeyedServiceFactory { -- public: -- // Sets the initial delay and interval checks required for browser tests. -- // Must be called before BuildServiceInstanceFor(). -- void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval, -- base::TimeDelta initial_delay); -- -- protected: -- virtual PrefService* GetPrefs(content::BrowserContext* context) const = 0; -- virtual AdblockController* GetAdblockController( -- content::BrowserContext* context) const = 0; -- virtual SubscriptionService* GetSubscriptionService( -- content::BrowserContext* context) const = 0; -- AdblockTelemetryServiceFactoryBase(); -- ~AdblockTelemetryServiceFactoryBase() override; -- -- private: -- // BrowserContextKeyedServiceFactory: -- KeyedService* BuildServiceInstanceFor( -- content::BrowserContext* context) const override; -- bool ServiceIsNULLWhileTesting() const override; -- bool ServiceIsCreatedWithBrowserContext() const override; --}; - - } // namespace adblock - ++ adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl()); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableAdblock) || + base::CommandLine::ForCurrentProcess()->HasSwitch( diff --git a/components/adblock/content/browser/adblock_webcontents_observer.cc b/components/adblock/content/browser/adblock_webcontents_observer.cc --- a/components/adblock/content/browser/adblock_webcontents_observer.cc +++ b/components/adblock/content/browser/adblock_webcontents_observer.cc @@ -2138,7 +2081,11 @@ diff --git a/components/adblock/content/browser/subscription_service_factory_bas } base::DeleteFile(path); return result; -@@ -205,7 +207,7 @@ void SubscriptionServiceFactoryBase::ConvertFilterListFile( +@@ -202,10 +204,11 @@ SubscriptionServiceFactoryBase::ConvertCustomFilters( + void SubscriptionServiceFactoryBase::ConvertFilterListFile( + const GURL& subscription_url, + const base::FilePath& path, ++ bool allow_privileged_filter, base::OnceCallback result_callback) const { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, @@ -2147,6 +2094,17 @@ diff --git a/components/adblock/content/browser/subscription_service_factory_bas std::move(result_callback)); } +diff --git a/components/adblock/content/browser/subscription_service_factory_base.h b/components/adblock/content/browser/subscription_service_factory_base.h +--- a/components/adblock/content/browser/subscription_service_factory_base.h ++++ b/components/adblock/content/browser/subscription_service_factory_base.h +@@ -39,6 +39,7 @@ class SubscriptionServiceFactoryBase : public BrowserContextKeyedServiceFactory, + void ConvertFilterListFile( + const GURL& subscription_url, + const base::FilePath& path, ++ bool allow_privileged_filter, + base::OnceCallback) const override; + + protected: diff --git a/components/adblock/core/BUILD.gn b/components/adblock/core/BUILD.gn --- a/components/adblock/core/BUILD.gn +++ b/components/adblock/core/BUILD.gn @@ -2571,7 +2529,7 @@ diff --git a/components/adblock/core/adblock_controller.h b/components/adblock/c #include "components/keyed_service/core/keyed_service.h" class GURL; -@@ -43,6 +44,11 @@ class AdblockController : public KeyedService { +@@ -43,10 +44,17 @@ class AdblockController : public KeyedService { virtual void SetAcceptableAdsEnabled(bool enabled) = 0; virtual bool IsAcceptableAdsEnabled() const = 0; @@ -2583,10 +2541,32 @@ diff --git a/components/adblock/core/adblock_controller.h b/components/adblock/c virtual void InstallSubscription(const GURL& url) = 0; virtual void UninstallSubscription(const GURL& url) = 0; virtual std::vector> GetInstalledSubscriptions() + const = 0; ++ virtual std::vector> GetCustomSubscriptions() ++ const = 0; + + virtual void AddAllowedDomain(const std::string& domain) = 0; + virtual void RemoveAllowedDomain(const std::string& domain) = 0; diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adblock/core/adblock_controller_impl.cc --- a/components/adblock/core/adblock_controller_impl.cc +++ b/components/adblock/core/adblock_controller_impl.cc -@@ -103,6 +103,7 @@ bool AdblockControllerImpl::IsAdblockEnabled() const { +@@ -73,6 +73,15 @@ absl::optional MigrateBoolFromPrefs(PrefService* pref_service, + return absl::nullopt; + } + ++bool IsKnownSubscription( ++ const std::vector& known_subscriptions, ++ const GURL& url) { ++ return base::ranges::any_of(known_subscriptions, ++ [&](const auto& known_subscription) { ++ return known_subscription.url == url; ++ }); ++} ++ + } // namespace + + AdblockControllerImpl::AdblockControllerImpl( +@@ -103,6 +112,7 @@ bool AdblockControllerImpl::IsAdblockEnabled() const { } void AdblockControllerImpl::SetAcceptableAdsEnabled(bool enabled) { @@ -2594,7 +2574,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb if (enabled) { InstallSubscription(AcceptableAdsUrl()); } else { -@@ -116,7 +117,33 @@ bool AdblockControllerImpl::IsAcceptableAdsEnabled() const { +@@ -116,7 +126,33 @@ bool AdblockControllerImpl::IsAcceptableAdsEnabled() const { [&](const auto& url) { return url == AcceptableAdsUrl(); }); } @@ -2628,7 +2608,28 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb adblock_filtering_configuration_->AddFilterList(url); } -@@ -165,10 +192,8 @@ void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) { +@@ -129,6 +165,20 @@ AdblockControllerImpl::GetInstalledSubscriptions() const { + return GetSubscriptionsThatMatchConfiguration(); + } + ++std::vector> ++AdblockControllerImpl::GetCustomSubscriptions() const { ++ auto selected = GetInstalledSubscriptions(); ++ std::vector known = GetKnownSubscriptions(); ++ selected.erase(base::ranges::remove_if(selected, ++ [&](const auto& subscription) { ++ return IsKnownSubscription( ++ known, ++ subscription->GetSourceUrl()); ++ }), ++ selected.end()); ++ return selected; ++} ++ + void AdblockControllerImpl::AddAllowedDomain(const std::string& domain) { + adblock_filtering_configuration_->AddAllowedDomain(domain); + } +@@ -165,10 +215,8 @@ void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) { common::prefs::kInstallFirstStartSubscriptions)) { // On first run, install additional subscriptions. for (const auto& cur : known_subscriptions_) { @@ -2641,7 +2642,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb // Do not install Acceptable Ads on first run because a command line // switch forbids it. Mostly used for testing. continue; -@@ -236,7 +261,7 @@ void AdblockControllerImpl::InstallLanguageBasedRecommendedSubscriptions() { +@@ -236,7 +284,7 @@ void AdblockControllerImpl::InstallLanguageBasedRecommendedSubscriptions() { SubscriptionFirstRunBehavior::SubscribeIfLocaleMatch && std::find(subscription.languages.begin(), subscription.languages.end(), language_) != subscription.languages.end()) { @@ -2653,7 +2654,7 @@ diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adb diff --git a/components/adblock/core/adblock_controller_impl.h b/components/adblock/core/adblock_controller_impl.h --- a/components/adblock/core/adblock_controller_impl.h +++ b/components/adblock/core/adblock_controller_impl.h -@@ -58,6 +58,11 @@ class AdblockControllerImpl : public AdblockController { +@@ -58,10 +58,17 @@ class AdblockControllerImpl : public AdblockController { void SetAcceptableAdsEnabled(bool enabled) override; bool IsAcceptableAdsEnabled() const override; @@ -2665,6 +2666,12 @@ diff --git a/components/adblock/core/adblock_controller_impl.h b/components/adbl void InstallSubscription(const GURL& url) override; void UninstallSubscription(const GURL& url) override; std::vector> GetInstalledSubscriptions() + const override; ++ std::vector> GetCustomSubscriptions() ++ const override; + + void AddAllowedDomain(const std::string& domain) override; + void RemoveAllowedDomain(const std::string& domain) override; diff --git a/components/adblock/core/adblock_switches.cc b/components/adblock/core/adblock_switches.cc --- a/components/adblock/core/adblock_switches.cc +++ b/components/adblock/core/adblock_switches.cc @@ -3051,16 +3058,7 @@ deleted file mode 100644 diff --git a/components/adblock/core/common/BUILD.gn b/components/adblock/core/common/BUILD.gn --- a/components/adblock/core/common/BUILD.gn +++ b/components/adblock/core/common/BUILD.gn -@@ -14,8 +14,6 @@ - # You should have received a copy of the GNU General Public License - # along with eyeo Chromium SDK. If not, see . - --import("//components/adblock/features.gni") -- - config("eyeo_filtering_config") { - defines = [] - -@@ -59,14 +57,6 @@ source_set("common") { +@@ -59,14 +59,6 @@ source_set("common") { config("eyeo_application_config") { defines = [] @@ -3250,7 +3248,7 @@ diff --git a/components/adblock/core/configuration/persistent_filtering_configur } void PersistentFilteringConfiguration::SetEnabled(bool enabled) { -+ pref_service_->SetBoolean(prefs::kEnableAdblockLegacy, enabled); ++ pref_service_->SetBoolean(common::prefs::kEnableAdblockLegacy, enabled); if (IsEnabled() == enabled) { return; } @@ -3259,11 +3257,11 @@ diff --git a/components/adblock/core/configuration/persistent_filtering_configur } +bool PersistentFilteringConfiguration::IsPrivilegedFiltersEnabled() { -+ return pref_service_->GetBoolean(prefs::kAllowPrivilegedFilters); ++ return pref_service_->GetBoolean(common::prefs::kAllowPrivilegedFilters); +} + +void PersistentFilteringConfiguration::SetPrivilegedFiltersEnabled(bool enabled) { -+ pref_service_->SetBoolean(prefs::kAllowPrivilegedFilters, enabled); ++ pref_service_->SetBoolean(common::prefs::kAllowPrivilegedFilters, enabled); +} + bool PersistentFilteringConfiguration::IsEnabled() const { @@ -4086,7 +4084,7 @@ diff --git a/components/adblock/core/subscription/subscription_persistent_metada +bool SubscriptionPersistentMetadataImpl::AllowPrivilegedFilters( + const GURL& subscription_url) { -+ return prefs_ && prefs_->GetBoolean(prefs::kAllowPrivilegedFilters) ++ return prefs_ && prefs_->GetBoolean(common::prefs::kAllowPrivilegedFilters) + && config::AllowPrivilegedFilters(subscription_url); +} + @@ -8138,6 +8136,32 @@ diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_pa document->GetStyleEngine().InjectSheet(injection_key, parsed_sheet, origin); return injection_key; } +diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec +--- a/tools/gritsettings/resource_ids.spec ++++ b/tools/gritsettings/resource_ids.spec +@@ -639,10 +639,6 @@ + "META": {"sizes": {"includes": [20]}}, + "includes": [4960], + }, +- "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/adblock_internals/resources.grd": { +- "META": {"sizes": {"includes": [10],}}, +- "includes": [4720], +- }, + # END chrome/ WebUI resources section + + # START chrome/ miscellaneous section. +@@ -1205,6 +1201,11 @@ + "includes": [7440], + }, + ++ "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/adblock_internals/resources.grd": { ++ "META": {"sizes": {"includes": [10],}}, ++ "includes": [8000], ++ }, ++ + # END "everything else" section. + # Everything but chrome/, components/, content/, and ios/ + diff --git a/tools/typescript/definitions/adblock_private.d.ts b/tools/typescript/definitions/adblock_private.d.ts --- a/tools/typescript/definitions/adblock_private.d.ts +++ b/tools/typescript/definitions/adblock_private.d.ts diff --git a/build/patches/00Fix-chromium-build-bugs.patch b/build/patches/00Fix-chromium-build-bugs.patch new file mode 100644 index 00000000..74526f6d --- /dev/null +++ b/build/patches/00Fix-chromium-build-bugs.patch @@ -0,0 +1,374 @@ +From: Your Name +Date: Wed, 6 Sep 2023 17:55:01 +0000 +Subject: Fix chromium build bugs + +--- + android_webview/system_webview_bundle.gni | 4 ++++ + build/config/android/rules.gni | 1 + + .../chromium/chrome/browser/tab/TabImpl.java | 2 +- + chrome/browser/download/download_ui_model.cc | 2 ++ + .../api/autofill_private/autofill_util.cc | 2 ++ + chrome/browser/extensions/extension_util.cc | 2 ++ + chrome/browser/safe_browsing/BUILD.gn | 1 + + .../safe_browsing/user_interaction_observer.cc | 17 ----------------- + ...ction_consented_debugging_infobar_delegate.h | 2 +- + chrome/browser/ui/views/tabs/tab.cc | 2 +- + .../browser/ui/views/tabs/tab_group_header.cc | 2 +- + .../app_management_page_handler.cc | 2 ++ + chrome/browser/usb/chrome_usb_delegate.cc | 2 ++ + .../autofill/core/browser/form_structure.cc | 2 ++ + .../core/browser/ui/suggestion_selection.cc | 12 +----------- + .../core/browser/webdata/autofill_table.cc | 12 ++++++------ + .../omnibox/browser/omnibox_field_trial.cc | 4 ++-- + .../phishing_image_embedder.cc | 14 +++----------- + crypto/BUILD.gn | 1 + + net/BUILD.gn | 1 + + third_party/libevent/BUILD.gn | 2 ++ + 21 files changed, 38 insertions(+), 51 deletions(-) + +diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_webview_bundle.gni +--- a/android_webview/system_webview_bundle.gni ++++ b/android_webview/system_webview_bundle.gni +@@ -84,6 +84,10 @@ template("system_webview_bundle") { + custom_assertion_handler = crash_reporting_assertion_handler + } + } ++ } else { ++ not_needed(["_base_target_name", "_base_target_gen_dir", ++ "_base_module_build_config", "_rebased_base_module_build_config", ++ "_base_module_version_code"]) + } + + android_app_bundle(target_name) { +diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni +--- a/build/config/android/rules.gni ++++ b/build/config/android/rules.gni +@@ -4993,6 +4993,7 @@ if (enable_java_templates && is_android) { + _module_build_config = _module.build_config + _module_build_config_target = _module.build_config_target + _module_target_name = get_label_info(_module_target, "name") ++ not_needed(["_module_target_name"]) + + if (!_proguard_enabled) { + _dex_target = "${_module_target_name}__final_dex" +diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +@@ -377,7 +377,7 @@ public class TabImpl implements Tab { + } + + @Override +- @CalledByNative ++ // @CalledByNative + public int getId() { + return mId; + } +diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc +--- a/chrome/browser/download/download_ui_model.cc ++++ b/chrome/browser/download/download_ui_model.cc +@@ -176,6 +176,7 @@ bool ShouldShowWarningForNoSafeBrowsing(Profile* profile) { + #endif + } + ++#if !BUILDFLAG(IS_ANDROID) + bool CanUserTurnOnSafeBrowsing(Profile* profile) { + #if BUILDFLAG(FULL_SAFE_BROWSING) + return !safe_browsing::IsSafeBrowsingPolicyManaged(*profile->GetPrefs()); +@@ -183,6 +184,7 @@ bool CanUserTurnOnSafeBrowsing(Profile* profile) { + return false; + #endif + } ++#endif + + } // namespace + +diff --git a/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chrome/browser/extensions/api/autofill_private/autofill_util.cc +--- a/chrome/browser/extensions/api/autofill_private/autofill_util.cc ++++ b/chrome/browser/extensions/api/autofill_private/autofill_util.cc +@@ -42,6 +42,7 @@ namespace { + // Get the multi-valued element for |type| and return it as a |vector|. + // TODO(khorimoto): remove this function since multi-valued types are + // deprecated. ++#if BUILDFLAG(IS_ANDROID) + std::vector GetList(const autofill::AutofillProfile& profile, + autofill::ServerFieldType type) { + std::vector list; +@@ -65,6 +66,7 @@ std::vector GetList(const autofill::AutofillProfile& profile, + + return list; + } ++#endif + + // Gets the string corresponding to |type| from |profile|. + std::string GetStringFromProfile(const autofill::AutofillProfile& profile, +diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc +--- a/chrome/browser/extensions/extension_util.cc ++++ b/chrome/browser/extensions/extension_util.cc +@@ -71,6 +71,7 @@ std::string ReloadExtensionIfEnabled(const std::string& extension_id, + return ReloadExtension(extension_id, context); + } + ++#if BUILDFLAG(IS_CHROMEOS_ASH) + // Returns true if the extension ID is found in the InstallForceList policy. Is + // checked by HasIsolatedStorage() when the extension is not found in the + // registry. +@@ -91,6 +92,7 @@ bool IsForceInstalledExtension(const ExtensionId& extension_id, + } + return false; + } ++#endif + + // Returns true if the profile is a sign-in profile and the extension is policy + // installed. `is_policy_installed` can be passed to the method if its value is +diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn +--- a/chrome/browser/safe_browsing/BUILD.gn ++++ b/chrome/browser/safe_browsing/BUILD.gn +@@ -210,6 +210,7 @@ static_library("safe_browsing") { + "//components/version_info", + "//content/public/browser", + "//services/preferences/public/mojom:mojom", ++ "//third_party/flatbuffers:flatbuffers", + ] + if (safe_browsing_mode == 1) { + # "Safe Browsing Full" files in addition to the "basic" ones to use for +diff --git a/chrome/browser/safe_browsing/user_interaction_observer.cc b/chrome/browser/safe_browsing/user_interaction_observer.cc +--- a/chrome/browser/safe_browsing/user_interaction_observer.cc ++++ b/chrome/browser/safe_browsing/user_interaction_observer.cc +@@ -36,23 +36,6 @@ WEB_CONTENTS_USER_DATA_KEY_IMPL(SafeBrowsingUserInteractionObserver); + + namespace { + +-bool IsUrlElisionDisabled(Profile* profile, +- const char* suspicious_site_reporter_extension_id) { +- if (profile && +- profile->GetPrefs()->GetBoolean(omnibox::kPreventUrlElisionsInOmnibox)) { +- return true; +- } +-#if BUILDFLAG(ENABLE_EXTENSIONS) +- DCHECK(suspicious_site_reporter_extension_id); +- if (profile && extensions::ExtensionRegistry::Get(profile) +- ->enabled_extensions() +- .Contains(suspicious_site_reporter_extension_id)) { +- return true; +- } +-#endif +- return false; +-} +- + } // namespace + + // static +diff --git a/chrome/browser/ui/startup/bidding_and_auction_consented_debugging_infobar_delegate.h b/chrome/browser/ui/startup/bidding_and_auction_consented_debugging_infobar_delegate.h +--- a/chrome/browser/ui/startup/bidding_and_auction_consented_debugging_infobar_delegate.h ++++ b/chrome/browser/ui/startup/bidding_and_auction_consented_debugging_infobar_delegate.h +@@ -12,7 +12,7 @@ + + namespace content { + class WebContents; +-}; ++} + + // An infobar for Chrome for Testing, which displays a message saying that this + // flavor of chrome is unsupported and does not auto-update. +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -524,7 +524,7 @@ bool Tab::OnMousePressed(const ui::MouseEvent& event) { + } + + bool Tab::OnMouseDragged(const ui::MouseEvent& event) { +- controller_->ContinueDrag(this, event); ++ (void)controller_->ContinueDrag(this, event); + return true; + } + +diff --git a/chrome/browser/ui/views/tabs/tab_group_header.cc b/chrome/browser/ui/views/tabs/tab_group_header.cc +--- a/chrome/browser/ui/views/tabs/tab_group_header.cc ++++ b/chrome/browser/ui/views/tabs/tab_group_header.cc +@@ -207,7 +207,7 @@ bool TabGroupHeader::OnMousePressed(const ui::MouseEvent& event) { + } + + bool TabGroupHeader::OnMouseDragged(const ui::MouseEvent& event) { +- tab_slot_controller_->ContinueDrag(this, event); ++ (void)tab_slot_controller_->ContinueDrag(this, event); + return true; + } + +diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +--- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc ++++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +@@ -134,6 +134,7 @@ bool CanShowDefaultAppAssociationsUi() { + #endif + } + ++#if BUILDFLAG(IS_CHROMEOS) + // Returns a list of intent filters that support http/https given an app ID. + apps::IntentFilters GetSupportedLinkIntentFilters(Profile* profile, + const std::string& app_id) { +@@ -167,6 +168,7 @@ std::vector GetSupportedLinks(Profile* profile, + return std::vector(supported_links.begin(), + supported_links.end()); + } ++#endif + + #if !BUILDFLAG(IS_CHROMEOS) + std::vector GetSupportedLinksForPWAs( +diff --git a/chrome/browser/usb/chrome_usb_delegate.cc b/chrome/browser/usb/chrome_usb_delegate.cc +--- a/chrome/browser/usb/chrome_usb_delegate.cc ++++ b/chrome/browser/usb/chrome_usb_delegate.cc +@@ -46,6 +46,7 @@ UsbChooserContext* GetChooserContext(content::BrowserContext* browser_context) { + return profile ? UsbChooserContextFactory::GetForProfile(profile) : nullptr; + } + ++#if !BUILDFLAG(IS_ANDROID) + UsbConnectionTracker* GetConnectionTracker( + content::BrowserContext* browser_context, + bool create) { +@@ -55,6 +56,7 @@ UsbConnectionTracker* GetConnectionTracker( + return profile ? UsbConnectionTrackerFactory::GetForProfile(profile, create) + : nullptr; + } ++#endif + + #if BUILDFLAG(ENABLE_EXTENSIONS) + // These extensions can claim the smart card USB class and automatically gain +diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc +--- a/components/autofill/core/browser/form_structure.cc ++++ b/components/autofill/core/browser/form_structure.cc +@@ -219,6 +219,7 @@ void EncodeRandomizedValue(const RandomizedEncoder& encoder, + // In that case, use the server prediction instead. In the special case that + // the last specified manual override is a pass through, copy all server + // predictions. ++#if !BUILDFLAG(IS_ANDROID) + std::deque MergeManualAndServerOverrides( + std::deque manual_overrides, + std::deque server_overrides) { +@@ -244,6 +245,7 @@ std::deque MergeManualAndServerOverrides( + + return result; + } ++#endif + + void PopulateRandomizedFormMetadata(const RandomizedEncoder& encoder, + const FormStructure& form, +diff --git a/components/autofill/core/browser/ui/suggestion_selection.cc b/components/autofill/core/browser/ui/suggestion_selection.cc +--- a/components/autofill/core/browser/ui/suggestion_selection.cc ++++ b/components/autofill/core/browser/ui/suggestion_selection.cc +@@ -101,17 +101,7 @@ Suggestion GetFillFullNameSuggestion(Suggestion::BackendId backend_id) { + // whole form. + // TODO(crbug.com/1459990): Use this once the new popup with submenus + // implementation is complete. +-Suggestion GetFillEverythingFromAddressProfileSuggestion( +- Suggestion::BackendId backend_id) { +- Suggestion suggestion(l10n_util::GetStringUTF16( +- IDS_AUTOFILL_FILL_EVERYTHING_FROM_ADDRESS_PROFILE_POPUP_OPTION_SELECTED)); +- suggestion.popup_item_id = PopupItemId::kFillEverythingFromAddressProfile; +- suggestion.icon = "magicIcon"; +- suggestion.payload = backend_id; +- suggestion.acceptance_a11y_announcement = l10n_util::GetStringUTF16( +- IDS_AUTOFILL_A11Y_ANNOUNCE_FILL_EVERYTHING_FROM_ADDRESS_PROFILE_POPUP_OPTION_SELECTED); +- return suggestion; +-} ++// (UAZO) removed due error: unused function + // Append new suggestions to `suggestions` based on the `ServerFieldType` list + // provided. Suggestions are not added if their info is not found in the + // provided `profile`. Returns true if any suggestion was added. +diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc +--- a/components/autofill/core/browser/webdata/autofill_table.cc ++++ b/components/autofill/core/browser/webdata/autofill_table.cc +@@ -412,12 +412,12 @@ void InsertBuilder(sql::Database* db, + } + + // Renames the table `from` into `to` and returns true if successful. +-bool RenameTable(sql::Database* db, +- std::string_view from, +- std::string_view to) { +- return db->Execute( +- base::StrCat({"ALTER TABLE ", from, " RENAME TO ", to}).c_str()); +-} ++// bool RenameTable(sql::Database* db, ++// std::string_view from, ++// std::string_view to) { ++// return db->Execute( ++// base::StrCat({"ALTER TABLE ", from, " RENAME TO ", to}).c_str()); ++// } + + // Wrapper around `sql::Database::DoesColumnExist()`, because that function + // only accepts const char* parameters. +diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc +--- a/components/omnibox/browser/omnibox_field_trial.cc ++++ b/components/omnibox/browser/omnibox_field_trial.cc +@@ -1079,11 +1079,11 @@ MLConfig::MLConfig(const MLConfig&) = default; + + ScopedMLConfigForTesting::ScopedMLConfigForTesting() + : original_config_(std::make_unique(GetMLConfig())) { +- GetMLConfigInternal() = {}; ++ //GetMLConfigInternal() = {}; + } + + ScopedMLConfigForTesting::~ScopedMLConfigForTesting() { +- GetMLConfigInternal() = *original_config_; ++ //GetMLConfigInternal() = *original_config_; + } + + MLConfig& ScopedMLConfigForTesting::GetMLConfig() { +diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_image_embedder.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_image_embedder.cc +--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_image_embedder.cc ++++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_image_embedder.cc +@@ -52,17 +52,9 @@ void PhishingImageEmbedder::BeginImageEmbedding(DoneCallback done_callback) { + } + + void PhishingImageEmbedder::OnPlaybackDone(std::unique_ptr bitmap) { +- if (bitmap) { +- bitmap_ = std::move(bitmap); +- ScorerStorage::GetInstance() +- ->GetScorer() +- ->ApplyVisualTfLiteModelImageEmbedding( +- *bitmap_, +- base::BindOnce(&PhishingImageEmbedder::OnImageEmbeddingDone, +- weak_factory_.GetWeakPtr())); +- } else { +- RunFailureCallback(); +- } ++ // (UAZO) removed due error: ++ // no member named 'ApplyVisualTfLiteModelImageEmbedding' in 'safe_browsing::Scorer' ++ RunFailureCallback(); + } + + void PhishingImageEmbedder::CancelPendingImageEmbedding() { +diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn +--- a/crypto/BUILD.gn ++++ b/crypto/BUILD.gn +@@ -14,6 +14,7 @@ buildflag_header("buildflags") { + } + + component("crypto") { ++ configs -= [ "//build/config/clang:find_bad_constructs" ] + output_name = "crcrypto" # Avoid colliding with OpenSSL's libcrypto. + sources = [ + "aead.cc", +diff --git a/net/BUILD.gn b/net/BUILD.gn +--- a/net/BUILD.gn ++++ b/net/BUILD.gn +@@ -1657,6 +1657,7 @@ component("net") { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_max" ] + } ++ configs -= [ "//build/config/clang:find_bad_constructs" ] + } + + # net_export.h has its own build target so that code (eg +diff --git a/third_party/libevent/BUILD.gn b/third_party/libevent/BUILD.gn +--- a/third_party/libevent/BUILD.gn ++++ b/third_party/libevent/BUILD.gn +@@ -69,6 +69,8 @@ static_library("libevent") { + configs += [ "//build/config/compiler:optimize_max" ] + } + ++ configs -= [ "//build/config/clang:find_bad_constructs" ] ++ + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + } +-- +2.25.1 diff --git a/build/patches/00Fix-crash-on-customize-profile-ui.patch b/build/patches/00Fix-crash-on-customize-profile-ui.patch new file mode 100644 index 00000000..71de2fb9 --- /dev/null +++ b/build/patches/00Fix-crash-on-customize-profile-ui.patch @@ -0,0 +1,23 @@ +From: uazo +Date: Thu, 7 Sep 2023 06:15:28 +0000 +Subject: Fix crash on customize profile ui + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html +--- + .../webui/customize_themes/chrome_customize_themes_handler.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.cc b/chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.cc +--- a/chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.cc ++++ b/chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.cc +@@ -79,7 +79,7 @@ void ChromeCustomizeThemesHandler::GetChromeThemes( + auto theme_colors = GetAutogeneratedThemeColors(color_info.color); + auto theme = customize_themes::mojom::ChromeTheme::New(); + theme->id = color_info.id; +- theme->label = l10n_util::GetStringUTF8(color_info.label_id); ++ //theme->label = l10n_util::GetStringUTF8(color_info.label_id); + auto colors = customize_themes::mojom::ThemeColors::New(); + colors->frame = theme_colors.frame_color; + colors->active_tab = theme_colors.active_tab_color; +-- +2.25.1 diff --git a/build/patches/00Fix-eyeo-Browser-Ad-filtering-patches.patch b/build/patches/00Fix-eyeo-Browser-Ad-filtering-patches.patch new file mode 100644 index 00000000..8e950d8a --- /dev/null +++ b/build/patches/00Fix-eyeo-Browser-Ad-filtering-patches.patch @@ -0,0 +1,147 @@ +From: uazo +Date: Wed, 6 Sep 2023 15:25:18 +0000 +Subject: Fix eyeo Browser Ad filtering patches + +--- + chrome/browser/BUILD.gn | 4 ---- + chrome/browser/client_hints/client_hints_browsertest.cc | 9 ++------- + chrome/browser/extensions/BUILD.gn | 4 ---- + chrome/browser/preferences/BUILD.gn | 4 ---- + chrome/browser/ui/BUILD.gn | 6 ------ + chrome/browser/ui/tab_helpers.cc | 4 ---- + extensions/common/mojom/api_permission_id.mojom | 3 --- + 7 files changed, 2 insertions(+), 32 deletions(-) + +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -2085,12 +2085,8 @@ static_library("browser") { + "//chrome/common/notifications", + "//chrome/installer/util:with_no_strings", + "//chrome/services/speech/buildflags", +-<<<<<<< HEAD +-======= +- "//chromeos/components/kiosk", + "//components/adblock/content:browser", + "//components/adblock/core/converter", +->>>>>>> 9402d5c48c0e8... Squashed commits + "//components/assist_ranker", + "//components/autofill/content/browser", + "//components/autofill/core/browser", +diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc +--- a/chrome/browser/client_hints/client_hints_browsertest.cc ++++ b/chrome/browser/client_hints/client_hints_browsertest.cc +@@ -652,17 +652,12 @@ class ClientHintsBrowserTest : public policy::PolicyTest { + // Force-enable the ClientHintsFormFactor feature, so that the header is + // represented in the various header counts. + feature_list->InitializeFromCommandLine( +-<<<<<<< HEAD +- "UserAgentClientHint,CriticalClientHint,AcceptCHFrame," +- "ClientHintsFormFactor", +- ""); +-======= + "UserAgentClientHint,CriticalClientHint,AcceptCHFrame", +- // Disabling AdblockPlus because the async implementation of ++ "ClientHintsFormFactor", ++ // Disabling AdblockPlus because the async implementation of + // AdblockURLLoaderThrottle::WillStartRequest confuses + // ThirdPartyURLLoaderInterceptor. + "AdblockPlus"); +->>>>>>> 9402d5c48c0e8... Squashed commits + return feature_list; + } + +diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn +--- a/chrome/browser/extensions/BUILD.gn ++++ b/chrome/browser/extensions/BUILD.gn +@@ -821,11 +821,7 @@ static_library("extensions") { + "//chrome/browser/safe_browsing:metrics_collector", + "//chrome/browser/ui/tabs:tab_enums", + "//chrome/browser/web_applications", +-<<<<<<< HEAD +-======= +- "//chromeos/components/kiosk", + "//components/adblock/content:browser", +->>>>>>> 9402d5c48c0e8... Squashed commits + "//components/cbor:cbor", + "//components/commerce/core:pref_names", + "//components/device_reauth", +diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn +--- a/chrome/browser/preferences/BUILD.gn ++++ b/chrome/browser/preferences/BUILD.gn +@@ -38,12 +38,8 @@ android_library("java") { + # TODO(chouinard,estade): Consider breaking this target up into a different target for each pref file. + java_cpp_strings("java_pref_names_srcjar") { + sources = [ +-<<<<<<< HEAD + "//chrome/common/pref_names.h", +-======= +- "//chrome/common/pref_names.cc", + "//components/adblock/core/common/adblock_prefs.cc", +->>>>>>> 9402d5c48c0e8... Squashed commits + "//components/autofill/core/common/autofill_prefs.cc", + "//components/commerce/core/pref_names.cc", + "//components/dom_distiller/core/pref_names.cc", +diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn +--- a/chrome/browser/ui/BUILD.gn ++++ b/chrome/browser/ui/BUILD.gn +@@ -447,11 +447,8 @@ static_library("ui") { + "//chrome/browser/storage_access_api", + "//chrome/browser/ui/side_panel:side_panel_enums", + "//chrome/browser/ui/webui:configs", +-<<<<<<< HEAD + "//chrome/browser/ui/webui/location_internals:mojo_bindings", +-======= + "//chrome/browser/ui/webui/adblock_internals:mojo_bindings", +->>>>>>> 9402d5c48c0e8... Squashed commits + "//chrome/browser/ui/webui/omnibox:mojo_bindings", + "//chrome/browser/ui/webui/segmentation_internals:mojo_bindings", + "//chrome/browser/ui/webui/suggest_internals:mojo_bindings", +@@ -467,11 +464,8 @@ static_library("ui") { + "//components/about_ui", + "//components/access_code_cast/common:metrics", + "//components/account_id", +-<<<<<<< HEAD + "//components/autofill/content/browser", +-======= + "//components/adblock/content:browser", +->>>>>>> 9402d5c48c0e8... Squashed commits + "//components/autofill/content/browser:risk_proto", + "//components/autofill/core/browser", + "//components/blocked_content", +diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc +--- a/chrome/browser/ui/tab_helpers.cc ++++ b/chrome/browser/ui/tab_helpers.cc +@@ -17,14 +17,10 @@ + #include "base/trace_event/trace_event.h" + #include "build/build_config.h" + #include "build/chromeos_buildflags.h" +-<<<<<<< HEAD + #include "chrome/browser/3pcd/heuristics/opener_heuristic_tab_helper.h" +-======= +-#include "chrome/browser/3pcd_heuristics/opener_heuristic_tab_helper.h" + #include "chrome/browser/adblock/element_hider_factory.h" + #include "chrome/browser/adblock/sitekey_storage_factory.h" + #include "chrome/browser/adblock/subscription_service_factory.h" +->>>>>>> 9402d5c48c0e8... Squashed commits + #include "chrome/browser/bookmarks/bookmark_model_factory.h" + #include "chrome/browser/breadcrumbs/breadcrumb_manager_tab_helper.h" + #include "chrome/browser/browser_process.h" +diff --git a/extensions/common/mojom/api_permission_id.mojom b/extensions/common/mojom/api_permission_id.mojom +--- a/extensions/common/mojom/api_permission_id.mojom ++++ b/extensions/common/mojom/api_permission_id.mojom +@@ -278,12 +278,9 @@ enum APIPermissionID { + kSmartCardProviderPrivate = 247, + kChromeOSEvents = 248, + kChromeOSAttachedDeviceInfo = 249, +-<<<<<<< HEAD + kReadingList = 250, +-======= + kAdblockPrivate = 999, + kEyeoFilteringPrivate = 1000, +->>>>>>> 9402d5c48c0e8... Squashed commits + + // Add new entries at the end of the enum and be sure to update the + // "ExtensionPermission3" enum in tools/metrics/histograms/enums.xml +-- +2.25.1 diff --git a/build/patches/00Internal-firewall.patch b/build/patches/00Internal-firewall.patch index 7fa92859..c4fb4a71 100644 --- a/build/patches/00Internal-firewall.patch +++ b/build/patches/00Internal-firewall.patch @@ -55,7 +55,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -2472,6 +2472,7 @@ static_library("browser") { +@@ -2468,6 +2468,7 @@ static_library("browser") { "//third_party/ungoogled:switches", "//services/device/public/mojom", "//services/device/public/mojom:usb", diff --git a/build/patches/00Multi-Screen-Window-Placement-API-fix.patch b/build/patches/00Multi-Screen-Window-Placement-API-fix.patch index 7b35c2cb..e64945fe 100644 --- a/build/patches/00Multi-Screen-Window-Placement-API-fix.patch +++ b/build/patches/00Multi-Screen-Window-Placement-API-fix.patch @@ -8,8 +8,8 @@ granted by user License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../blink/renderer/core/frame/screen.cc | 25 +++++++++++++++++-- - .../blink/renderer/core/frame/screen.h | 8 ++++++ - 2 files changed, 31 insertions(+), 2 deletions(-) + .../blink/renderer/core/frame/screen.h | 10 ++++++++ + 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink/renderer/core/frame/screen.cc --- a/third_party/blink/renderer/core/frame/screen.cc @@ -70,7 +70,7 @@ diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink diff --git a/third_party/blink/renderer/core/frame/screen.h b/third_party/blink/renderer/core/frame/screen.h --- a/third_party/blink/renderer/core/frame/screen.h +++ b/third_party/blink/renderer/core/frame/screen.h -@@ -33,12 +33,20 @@ +@@ -33,10 +33,14 @@ #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -80,16 +80,23 @@ diff --git a/third_party/blink/renderer/core/frame/screen.h b/third_party/blink/ #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "ui/gfx/geometry/rect.h" ++#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" ++ namespace display { struct ScreenInfo; + } +@@ -91,6 +95,12 @@ class CORE_EXPORT Screen : public EventTarget, + + // The internal id of the underlying display, to support multi-screen devices. + int64_t display_id_; + + private: + void DidGetPermissionState(mojom::blink::PermissionStatus status); + + bool has_permission_ = false; + HeapMojoRemote permission_service_; - } + }; - namespace blink { + } // namespace blink -- 2.25.1 diff --git a/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch b/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch index 8eedb271..705d32d4 100644 --- a/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch +++ b/build/patches/00Remove-GoogleAccountsPrivateApiHost.patch @@ -2,47 +2,89 @@ From: uazo Date: Tue, 5 Sep 2023 12:55:40 +0000 Subject: Remove GoogleAccountsPrivateApiHost +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - .../browser/chrome_content_browser_client_receiver_bindings.cc | 2 +- - chrome/browser/signin/google_accounts_private_api_host.cc | 2 +- - chrome/renderer/chrome_content_renderer_client.cc | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) + .../google_accounts_private_api_util.cc | 20 +------------------ + ...rusted_vault_encryption_keys_tab_helper.cc | 6 ++---- + .../google_accounts_private_api_util.cc | 11 ---------- + 3 files changed, 3 insertions(+), 34 deletions(-) -diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc ---- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc -+++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc -@@ -543,7 +543,7 @@ void ChromeContentBrowserClient:: - chrome::mojom::GoogleAccountsPrivateApiExtension>(base::BindRepeating( - [](content::RenderFrameHost* render_frame_host, - mojo::PendingAssociatedReceiver< -- chrome::mojom::GoogleAccountsPrivateApiExtension> receiver) { -+ chrome::mojom::GoogleAccountsPrivateApiExtension_UAZO_REMOVE_IT> receiver) { - GoogleAccountsPrivateApiHost::BindHost(std::move(receiver), - render_frame_host); - }, -diff --git a/chrome/browser/signin/google_accounts_private_api_host.cc b/chrome/browser/signin/google_accounts_private_api_host.cc ---- a/chrome/browser/signin/google_accounts_private_api_host.cc -+++ b/chrome/browser/signin/google_accounts_private_api_host.cc -@@ -9,7 +9,7 @@ - #include "content/public/browser/navigation_handle.h" - #include "content/public/browser/render_frame_host.h" +diff --git a/chrome/browser/signin/google_accounts_private_api_util.cc b/chrome/browser/signin/google_accounts_private_api_util.cc +--- a/chrome/browser/signin/google_accounts_private_api_util.cc ++++ b/chrome/browser/signin/google_accounts_private_api_util.cc +@@ -9,25 +9,7 @@ + #include "content/public/browser/site_instance.h" + #include "google_apis/gaia/gaia_urls.h" --GoogleAccountsPrivateApiHost::GoogleAccountsPrivateApiHost( -+GoogleAccountsPrivateApiHost::GoogleAccountsPrivateApiHost_UAZO_REMOVE_IT( - content::RenderFrameHost* rfh, - base::RepeatingCallback - on_consent_result_callback) -diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc ---- a/chrome/renderer/chrome_content_renderer_client.cc -+++ b/chrome/renderer/chrome_content_renderer_client.cc -@@ -644,7 +644,7 @@ void ChromeContentRendererClient::RenderFrameCreated( - #endif +-const url::Origin& GetAllowedGoogleAccountsOrigin() { +- const url::Origin& origin = GaiaUrls::GetInstance()->gaia_origin(); +- CHECK(!origin.opaque()); +- return origin; +-} +- + bool ShouldExposeGoogleAccountsPrivateApi( + content::NavigationHandle* navigation_handle) { +- if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage()) { +- return false; +- } +- +- content::RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost(); +- const url::Origin rfh_origin = rfh->GetLastCommittedOrigin(); +- // Restrict to allowed origin and only if site isolation requires a dedicated +- // process. The host is compared explicitly to confirm that the allowed origin +- // uses a dedicated process, rather than sharing process with eTLD+1. +- return rfh_origin == GetAllowedGoogleAccountsOrigin() && +- rfh->GetSiteInstance()->RequiresDedicatedProcess() && +- rfh->GetSiteInstance()->GetSiteURL().host() == +- GetAllowedGoogleAccountsOrigin().host(); ++ return false; + } +diff --git a/chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper.cc b/chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper.cc +--- a/chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper.cc ++++ b/chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper.cc +@@ -56,8 +56,7 @@ class EncryptionKeyApi + trusted_vault_keys, + SetEncryptionKeysCallback callback) override { + // Extra safeguard. +- if (receivers_.GetCurrentTargetFrame()->GetLastCommittedOrigin() != +- GetAllowedGoogleAccountsOrigin()) { ++ if ((true)) { + return; + } - TrustedVaultEncryptionKeysExtension::Create(render_frame); -- GoogleAccountsPrivateApiExtension::Create(render_frame); -+ GoogleAccountsPrivateApiExtension::Create(render_frame); (UAZO) REMOVE IT +@@ -90,8 +89,7 @@ class EncryptionKeyApi + int method_type_hint, + AddTrustedRecoveryMethodCallback callback) override { + // Extra safeguard. +- if (receivers_.GetCurrentTargetFrame()->GetLastCommittedOrigin() != +- GetAllowedGoogleAccountsOrigin()) { ++ if ((true)) { + return; + } - if (render_frame->IsMainFrame()) - new webapps::WebPageMetadataAgent(render_frame); +diff --git a/chrome/renderer/google_accounts_private_api_util.cc b/chrome/renderer/google_accounts_private_api_util.cc +--- a/chrome/renderer/google_accounts_private_api_util.cc ++++ b/chrome/renderer/google_accounts_private_api_util.cc +@@ -12,20 +12,9 @@ + + namespace { + +-const url::Origin& GetAllowedGoogleAccountsOrigin() { +- const url::Origin& origin = GaiaUrls::GetInstance()->gaia_origin(); +- CHECK(!origin.opaque()); +- return origin; +-} +- + } // namespace + + bool ShouldExposeGoogleAccountsJavascriptApi( + content::RenderFrame* render_frame) { + if ((true)) return false; +- DCHECK(render_frame); +- +- const url::Origin origin = render_frame->GetWebFrame()->GetSecurityOrigin(); +- return origin == GetAllowedGoogleAccountsOrigin() && +- blink::Platform::Current()->IsLockedToSite(); + } -- 2.25.1 diff --git a/build/patches/00Restore-LastTabStandingTracker.patch b/build/patches/00Restore-LastTabStandingTracker.patch index 6258d0bb..6de08b77 100644 --- a/build/patches/00Restore-LastTabStandingTracker.patch +++ b/build/patches/00Restore-LastTabStandingTracker.patch @@ -397,7 +397,7 @@ diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc -@@ -66,6 +66,7 @@ +@@ -63,6 +63,7 @@ #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" @@ -405,7 +405,7 @@ diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc #include "chrome/browser/permissions/one_time_permissions_tracker_helper.h" #include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/predictors/loading_predictor_tab_helper.h" -@@ -399,6 +400,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { +@@ -396,6 +397,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { HistoryClustersTabHelper::CreateForWebContents(web_contents); HttpsOnlyModeTabHelper::CreateForWebContents(web_contents); webapps::InstallableManager::CreateForWebContents(web_contents); diff --git a/build/patches/00v113-temp-fix-build.patch b/build/patches/00v113-temp-fix-build.patch deleted file mode 100644 index 8a9c88f8..00000000 --- a/build/patches/00v113-temp-fix-build.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: uazo -Date: Mon, 1 May 2023 12:08:46 +0000 -Subject: v113 temp fix build - -License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html ---- - android_webview/system_webview_bundle.gni | 4 ++++ - chrome/browser/safe_browsing/BUILD.gn | 1 + - 2 files changed, 5 insertions(+) - -diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_webview_bundle.gni ---- a/android_webview/system_webview_bundle.gni -+++ b/android_webview/system_webview_bundle.gni -@@ -84,6 +84,10 @@ template("system_webview_bundle") { - custom_assertion_handler = crash_reporting_assertion_handler - } - } -+ } else { -+ not_needed(["_base_target_name", "_base_target_gen_dir", -+ "_base_module_build_config", "_rebased_base_module_build_config", -+ "_base_module_version_code"]) - } - - android_app_bundle(target_name) { -diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn ---- a/chrome/browser/safe_browsing/BUILD.gn -+++ b/chrome/browser/safe_browsing/BUILD.gn -@@ -210,6 +210,7 @@ static_library("safe_browsing") { - "//components/version_info", - "//content/public/browser", - "//services/preferences/public/mojom:mojom", -+ "//third_party/flatbuffers:flatbuffers", - ] - if (safe_browsing_mode == 1) { - # "Safe Browsing Full" files in addition to the "basic" ones to use for --- -2.25.1 diff --git a/build/patches/Add-bookmark-import-export-actions.patch b/build/patches/Add-bookmark-import-export-actions.patch index db8874e9..3c72f694 100644 --- a/build/patches/Add-bookmark-import-export-actions.patch +++ b/build/patches/Add-bookmark-import-export-actions.patch @@ -825,7 +825,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn configs += [ "//build/config/compiler:wexit_time_destructors", "//build/config:precompiled_headers", -@@ -3587,8 +3596,6 @@ static_library("browser") { +@@ -3583,8 +3592,6 @@ static_library("browser") { "badging/badge_manager_factory.h", "banners/app_banner_manager_desktop.cc", "banners/app_banner_manager_desktop.h", diff --git a/build/patches/Add-lifetime-options-for-permissions.patch b/build/patches/Add-lifetime-options-for-permissions.patch index 8d09942a..a16b5d4b 100644 --- a/build/patches/Add-lifetime-options-for-permissions.patch +++ b/build/patches/Add-lifetime-options-for-permissions.patch @@ -52,8 +52,8 @@ See also: https://github.com/bromite/bromite/issues/1549 Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../permissions/last_tab_standing_tracker.cc | 33 ++++++++ - .../one_time_permissions_tracker.cc | 34 +++++++- + .../permissions/last_tab_standing_tracker.cc | 32 ++++++++ + .../one_time_permissions_tracker.cc | 33 +++++++- .../one_time_permissions_tracker.h | 5 +- .../one_time_permissions_tracker_factory.cc | 2 +- .../permission_prompt_bubble_base_view.cc | 2 +- @@ -87,12 +87,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/permissions/permission_request.h | 18 ++++- .../permissions/permission_request_manager.cc | 45 +++++++---- .../permissions/permission_request_manager.h | 11 ++- - 35 files changed, 523 insertions(+), 60 deletions(-) + 35 files changed, 521 insertions(+), 60 deletions(-) diff --git a/chrome/browser/permissions/last_tab_standing_tracker.cc b/chrome/browser/permissions/last_tab_standing_tracker.cc --- a/chrome/browser/permissions/last_tab_standing_tracker.cc +++ b/chrome/browser/permissions/last_tab_standing_tracker.cc -@@ -7,6 +7,33 @@ +@@ -7,6 +7,32 @@ #include "base/observer_list.h" #include "url/gurl.h" @@ -105,10 +105,9 @@ diff --git a/chrome/browser/permissions/last_tab_standing_tracker.cc b/chrome/br + void RemoveSessionSettings(HostContentSettingsMap* content_settings, + const url::Origin& origin, + ContentSettingsType type) { -+ ContentSettingsForOneType session_settings; -+ content_settings->GetSettingsForOneType( -+ type, &session_settings, -+ content_settings::SessionModel::UserSession); ++ ContentSettingsForOneType session_settings = ++ content_settings->GetSettingsForOneType( ++ type, content_settings::SessionModel::UserSession); + + GURL url = origin.GetURL(); + for (ContentSettingPatternSource& entry : session_settings) { @@ -126,7 +125,7 @@ diff --git a/chrome/browser/permissions/last_tab_standing_tracker.cc b/chrome/br LastTabStandingTracker::LastTabStandingTracker(content::BrowserContext* context) : context_(context) {} -@@ -56,4 +83,10 @@ void LastTabStandingTracker::WebContentsUnloadedOrigin( +@@ -56,4 +82,10 @@ void LastTabStandingTracker::WebContentsUnloadedOrigin( for (auto& observer : observer_list_) { observer.OnLastPageFromOriginClosed(origin); } @@ -140,7 +139,7 @@ diff --git a/chrome/browser/permissions/last_tab_standing_tracker.cc b/chrome/br diff --git a/chrome/browser/permissions/one_time_permissions_tracker.cc b/chrome/browser/permissions/one_time_permissions_tracker.cc --- a/chrome/browser/permissions/one_time_permissions_tracker.cc +++ b/chrome/browser/permissions/one_time_permissions_tracker.cc -@@ -18,8 +18,35 @@ +@@ -18,8 +18,34 @@ #include "components/permissions/features.h" #include "content/public/browser/visibility.h" #include "url/gurl.h" @@ -153,10 +152,9 @@ diff --git a/chrome/browser/permissions/one_time_permissions_tracker.cc b/chrome + void RemoveSessionSettings(HostContentSettingsMap* content_settings, + const url::Origin& origin, + ContentSettingsType type) { -+ ContentSettingsForOneType session_settings; -+ content_settings->GetSettingsForOneType( -+ type, &session_settings, -+ content_settings::SessionModel::UserSession); ++ ContentSettingsForOneType session_settings = ++ content_settings->GetSettingsForOneType( ++ type, content_settings::SessionModel::UserSession); + + GURL url = origin.GetURL(); + for (ContentSettingPatternSource& entry : session_settings) { @@ -177,7 +175,7 @@ diff --git a/chrome/browser/permissions/one_time_permissions_tracker.cc b/chrome OneTimePermissionsTracker::~OneTimePermissionsTracker() = default; OneTimePermissionsTracker::OriginTrackEntry::OriginTrackEntry() = default; -@@ -93,6 +120,11 @@ void OneTimePermissionsTracker::WebContentsUnloadedOrigin( +@@ -93,6 +119,11 @@ void OneTimePermissionsTracker::WebContentsUnloadedOrigin( observer.OnLastPageFromOriginClosed(origin); } } diff --git a/build/patches/Add-option-to-use-home-page-as-NTP.patch b/build/patches/Add-option-to-use-home-page-as-NTP.patch index ea5bc375..d0976db6 100644 --- a/build/patches/Add-option-to-use-home-page-as-NTP.patch +++ b/build/patches/Add-option-to-use-home-page-as-NTP.patch @@ -6,6 +6,8 @@ And allow use about:blank as default homepage License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- + .../tab_management/TabGridDialogMediator.java | 7 ++++++- + .../tasks/tab_management/TabGroupUiMediator.java | 7 ++++++- .../java/res/xml/homepage_preferences.xml | 5 +++++ .../chrome/browser/homepage/HomepageManager.java | 16 ++++++++++++++++ .../homepage/settings/HomepageSettings.java | 12 ++++++++++++ @@ -16,8 +18,59 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../android/strings/android_chrome_strings.grd | 3 +++ chrome/browser/ui/browser_ui_prefs.cc | 2 ++ chrome/common/pref_names.h | 4 ++++ - 10 files changed, 51 insertions(+), 1 deletion(-) + 12 files changed, 63 insertions(+), 3 deletions(-) +diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java ++++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +@@ -18,6 +18,7 @@ import org.chromium.base.Callback; + import org.chromium.base.ResettersForTesting; + import org.chromium.base.metrics.RecordUserAction; + import org.chromium.base.supplier.Supplier; ++import org.chromium.chrome.browser.homepage.HomepageManager; + import org.chromium.chrome.browser.tab.Tab; + import org.chromium.chrome.browser.tab.TabCreationState; + import org.chromium.chrome.browser.tab.TabLaunchType; +@@ -578,9 +579,13 @@ public class TabGridDialogMediator + + assert relatedTabs.size() > 0; + ++ String url = UrlConstants.NTP_URL; ++ if (HomepageManager.getInstance().getPrefNTPIsHomepageEnabled()) { ++ url = HomepageManager.getInstance().getHomepageUri(); ++ } + Tab parentTabToAttach = relatedTabs.get(relatedTabs.size() - 1); + mTabCreatorManager.getTabCreator(currentTab.isIncognito()) +- .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL), ++ .createNewTab(new LoadUrlParams(url), + TabLaunchType.FROM_TAB_GROUP_UI, parentTabToAttach); + RecordUserAction.record("MobileNewTabOpened." + mComponentName); + }; +diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java ++++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +@@ -17,6 +17,7 @@ import org.chromium.base.metrics.RecordUserAction; + import org.chromium.base.supplier.ObservableSupplier; + import org.chromium.base.supplier.ObservableSupplierImpl; + import org.chromium.base.supplier.OneshotSupplier; ++import org.chromium.chrome.browser.homepage.HomepageManager; + import org.chromium.chrome.browser.layouts.LayoutStateProvider; + import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver; + import org.chromium.chrome.browser.layouts.LayoutType; +@@ -350,8 +351,12 @@ public class TabGroupUiMediator implements BackPressHandler { + + parentTabToAttach = relatedTabs.get(relatedTabs.size() - 1); + } ++ String url = UrlConstants.NTP_URL; ++ if (HomepageManager.getInstance().getPrefNTPIsHomepageEnabled()) { ++ url = HomepageManager.getInstance().getHomepageUri(); ++ } + mTabCreatorManager.getTabCreator(currentTab.isIncognito()) +- .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL), ++ .createNewTab(new LoadUrlParams(url), + TabLaunchType.FROM_TAB_GROUP_UI, parentTabToAttach); + RecordUserAction.record("MobileNewTabOpened." + TabGroupUiCoordinator.COMPONENT_NAME); + }; diff --git a/chrome/android/java/res/xml/homepage_preferences.xml b/chrome/android/java/res/xml/homepage_preferences.xml --- a/chrome/android/java/res/xml/homepage_preferences.xml +++ b/chrome/android/java/res/xml/homepage_preferences.xml diff --git a/build/patches/Allow-building-without-supervised-users.patch b/build/patches/Allow-building-without-supervised-users.patch index 5604a17d..3825350a 100644 --- a/build/patches/Allow-building-without-supervised-users.patch +++ b/build/patches/Allow-building-without-supervised-users.patch @@ -4,11 +4,19 @@ Subject: Allow building without supervised users License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - chrome/android/BUILD.gn | 1 - - chrome/android/chrome_java_sources.gni | 1 - - chrome/browser/BUILD.gn | 6 ------ - components/supervised_user/buildflags.gni | 6 +----- - 4 files changed, 1 insertion(+), 13 deletions(-) + chrome/android/BUILD.gn | 1 - + chrome/android/chrome_java_sources.gni | 1 - + chrome/browser/BUILD.gn | 6 ------ + .../browser/extensions/api/settings_private/prefs_util.cc | 2 ++ + chrome/browser/profiles/profile_impl.cc | 4 ++++ + chrome/browser/profiles/profile_manager.cc | 4 ++++ + chrome/browser/ui/webui/managed_ui_handler.cc | 2 ++ + .../browser/ui/webui/management/management_ui_handler.cc | 2 ++ + components/supervised_user/buildflags.gni | 6 +----- + components/supervised_user/core/common/pref_names.h | 4 ++++ + .../core/common/supervised_user_constants.cc | 2 ++ + .../supervised_user/core/common/supervised_user_utils.cc | 8 ++++++++ + 12 files changed, 29 insertions(+), 13 deletions(-) diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn @@ -35,7 +43,7 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -3074,8 +3074,6 @@ static_library("browser") { +@@ -3070,8 +3070,6 @@ static_library("browser") { "feed/android/refresh_task_scheduler_impl.cc", "feed/android/refresh_task_scheduler_impl.h", "feed/android/web_feed_bridge.cc", @@ -44,7 +52,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "file_select_helper_contacts_android.cc", "file_select_helper_contacts_android.h", "first_run/android/first_run_prefs.cc", -@@ -3290,10 +3288,6 @@ static_library("browser") { +@@ -3286,10 +3284,6 @@ static_library("browser") { "ssl/chrome_security_state_model_delegate.h", "ssl/known_interception_disclosure_infobar.cc", "ssl/known_interception_disclosure_infobar.h", @@ -55,6 +63,112 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "sync/glue/synced_tab_delegate_android.cc", "sync/glue/synced_tab_delegate_android.h", "sync/glue/synced_window_delegate_android.cc", +diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc +--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc ++++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc +@@ -1006,9 +1006,11 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { + settings_api::PrefType::PREF_TYPE_BOOLEAN; + #endif + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + // Supervised Users. This setting is queried in our Tast tests (b/241943380). + (*s_allowlist)[::prefs::kSupervisedUserExtensionsMayRequestPermissions] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; ++#endif + + #if BUILDFLAG(IS_CHROMEOS_LACROS) + (*s_allowlist)[::prefs::kUseAshProxy] = +diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc +--- a/chrome/browser/profiles/profile_impl.cc ++++ b/chrome/browser/profiles/profile_impl.cc +@@ -691,10 +691,12 @@ void ProfileImpl::DoFinalInit(CreateMode create_mode) { + prefs->SetTime(prefs::kProfileCreationTime, path_creation_time_); + + pref_change_registrar_.Init(prefs); ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + pref_change_registrar_.Add( + prefs::kSupervisedUserId, + base::BindRepeating(&ProfileImpl::UpdateSupervisedUserIdInStorage, + base::Unretained(this))); ++#endif + + // Changes in the profile avatar. + pref_change_registrar_.Add( +@@ -1614,11 +1616,13 @@ GURL ProfileImpl::GetHomePage() { + } + + void ProfileImpl::UpdateSupervisedUserIdInStorage() { ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + ProfileManager* profile_manager = g_browser_process->profile_manager(); + ProfileAttributesEntry* entry = profile_manager->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(GetPath()); + if (entry) + entry->SetSupervisedUserId(GetPrefs()->GetString(prefs::kSupervisedUserId)); ++#endif + } + + void ProfileImpl::UpdateNameInStorage() { +diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc +--- a/chrome/browser/profiles/profile_manager.cc ++++ b/chrome/browser/profiles/profile_manager.cc +@@ -1178,6 +1178,7 @@ void ProfileManager::InitProfileUserPrefs(Profile* profile) { + profile->GetPrefs()->SetString(prefs::kProfileName, profile_name); + } + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + bool force_supervised_user_id = + #if BUILDFLAG(IS_CHROMEOS_ASH) +@@ -1199,6 +1200,7 @@ void ProfileManager::InitProfileUserPrefs(Profile* profile) { + profile->GetPrefs()->SetString(prefs::kSupervisedUserId, + supervised_user_id); + } ++#endif + #if !BUILDFLAG(IS_ANDROID) + if (profile->IsNewProfile()) { + profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, false); +@@ -1966,8 +1968,10 @@ void ProfileManager::AddProfileToStorage(Profile* profile) { + init_params.icon_index = + profile->GetPrefs()->GetInteger(prefs::kProfileAvatarIndex); + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + init_params.supervised_user_id = + profile->GetPrefs()->GetString(prefs::kSupervisedUserId); ++#endif + + #if BUILDFLAG(IS_CHROMEOS_ASH) + user_manager::User* user = +diff --git a/chrome/browser/ui/webui/managed_ui_handler.cc b/chrome/browser/ui/webui/managed_ui_handler.cc +--- a/chrome/browser/ui/webui/managed_ui_handler.cc ++++ b/chrome/browser/ui/webui/managed_ui_handler.cc +@@ -90,9 +90,11 @@ void ManagedUIHandler::AddObservers() { + policy_service->AddObserver(domain, this); + } + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + pref_registrar_.Add(prefs::kSupervisedUserId, + base::BindRepeating(&ManagedUIHandler::NotifyIfChanged, + base::Unretained(this))); ++#endif + } + + void ManagedUIHandler::RemoveObservers() { +diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc +--- a/chrome/browser/ui/webui/management/management_ui_handler.cc ++++ b/chrome/browser/ui/webui/management/management_ui_handler.cc +@@ -1423,10 +1423,12 @@ void ManagementUIHandler::AddObservers() { + + pref_registrar_.Init(profile->GetPrefs()); + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + pref_registrar_.Add( + prefs::kSupervisedUserId, + base::BindRepeating(&ManagementUIHandler::UpdateManagedState, + base::Unretained(this))); ++#endif + + #if BUILDFLAG(IS_CHROMEOS_ASH) + pref_registrar_.Add( diff --git a/components/supervised_user/buildflags.gni b/components/supervised_user/buildflags.gni --- a/components/supervised_user/buildflags.gni +++ b/components/supervised_user/buildflags.gni @@ -69,5 +183,79 @@ diff --git a/components/supervised_user/buildflags.gni b/components/supervised_u - is_ios || is_linux || is_mac || is_win + enable_supervised_users = false } +diff --git a/components/supervised_user/core/common/pref_names.h b/components/supervised_user/core/common/pref_names.h +--- a/components/supervised_user/core/common/pref_names.h ++++ b/components/supervised_user/core/common/pref_names.h +@@ -5,8 +5,10 @@ + #ifndef COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_ + #define COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_ + ++#include "components/supervised_user/core/common/buildflags.h" + #include "extensions/buildflags/buildflags.h" + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + namespace prefs { + + // A bool pref that keeps whether the child status for this profile was already +@@ -124,4 +126,6 @@ inline constexpr char kFirstTimeInterstitialBannerState[] = + + } // namespace prefs + ++#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) ++ + #endif // COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_ +diff --git a/components/supervised_user/core/common/supervised_user_constants.cc b/components/supervised_user/core/common/supervised_user_constants.cc +--- a/components/supervised_user/core/common/supervised_user_constants.cc ++++ b/components/supervised_user/core/common/supervised_user_constants.cc +@@ -68,6 +68,7 @@ const char kChromeOSAvatarIndex[] = "chromeos-avatar-index"; + + const char kChromeOSPasswordData[] = "chromeos-password-data"; + ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + const char* const kCustodianInfoPrefs[] = { + prefs::kSupervisedUserCustodianName, + prefs::kSupervisedUserCustodianEmail, +@@ -80,6 +81,7 @@ const char* const kCustodianInfoPrefs[] = { + prefs::kSupervisedUserSecondCustodianProfileURL, + prefs::kSupervisedUserSecondCustodianProfileImageURL, + }; ++#endif + + const base::FilePath::CharType kSupervisedUserSettingsFilename[] = + FILE_PATH_LITERAL("Managed Mode Settings"); +diff --git a/components/supervised_user/core/common/supervised_user_utils.cc b/components/supervised_user/core/common/supervised_user_utils.cc +--- a/components/supervised_user/core/common/supervised_user_utils.cc ++++ b/components/supervised_user/core/common/supervised_user_utils.cc +@@ -76,11 +76,15 @@ GURL NormalizeUrl(const GURL& url) { + } + + bool AreWebFilterPrefsDefault(const PrefService& pref_service) { ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + return pref_service + .FindPreference(prefs::kDefaultSupervisedUserFilteringBehavior) + ->IsDefaultValue() || + pref_service.FindPreference(prefs::kSupervisedUserSafeSites) + ->IsDefaultValue(); ++#else ++ return true; ++#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) + } + + bool EmitLogSegmentHistogram(const std::vector& primary_accounts) { +@@ -107,10 +111,14 @@ bool EmitLogSegmentHistogram(const std::vector& primary_accounts) { + } + + bool IsSubjectToParentalControls(const PrefService* pref_service) { ++#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + return pref_service && + pref_service->GetString(prefs::kSupervisedUserId) == + kChildAccountSUID && + IsChildAccountSupervisionEnabled(); ++#else ++ return false; ++#endif + } + + } // namespace supervised_user -- 2.25.1 diff --git a/build/patches/Block-gateway-attacks-via-websockets.patch b/build/patches/Block-gateway-attacks-via-websockets.patch index 672e7513..d91db1bb 100644 --- a/build/patches/Block-gateway-attacks-via-websockets.patch +++ b/build/patches/Block-gateway-attacks-via-websockets.patch @@ -14,11 +14,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../core/loader/frame_fetch_context.h | 1 + .../core/loader/worker_fetch_context.cc | 21 +++++++++++++ .../core/loader/worker_fetch_context.h | 1 + + .../core/workers/installed_scripts_manager.cc | 4 +-- .../background_fetch_manager.cc | 31 +++++++++++++++++++ .../websockets/websocket_channel_impl.cc | 5 +++ - .../modules/websockets/websocket_common.cc | 29 +++++++++++++++++ + .../modules/websockets/websocket_common.cc | 30 ++++++++++++++++++ .../modules/websockets/websocket_common.h | 4 +++ - 11 files changed, 130 insertions(+) + 12 files changed, 133 insertions(+), 2 deletions(-) diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc --- a/third_party/blink/renderer/core/execution_context/execution_context.cc @@ -33,8 +34,8 @@ diff --git a/third_party/blink/renderer/core/execution_context/execution_context + case network::mojom::IPAddressSpace::kUnknown: + return "public"; + -+ case network::mojom::IPAddressSpace::kLoopback: -+ return "loopback"; ++ case network::mojom::IPAddressSpace::kPrivate: ++ return "private"; + + case network::mojom::IPAddressSpace::kLocal: + return "local"; @@ -82,9 +83,9 @@ diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/thi + network::mojom::IPAddressSpace target_space = + network::mojom::IPAddressSpace::kPublic; + if (network_utils::IsReservedIPAddress(request_url.Host())) -+ target_space = network::mojom::IPAddressSpace::kLocal; ++ target_space = network::mojom::IPAddressSpace::kPrivate; + if (SecurityOrigin::Create(request_url)->IsLocalhost()) -+ target_space = network::mojom::IPAddressSpace::kLoopback; ++ target_space = network::mojom::IPAddressSpace::kLocal; + + bool is_external_request = requestor_space > target_space; + if (is_external_request) @@ -131,9 +132,9 @@ diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/th + network::mojom::IPAddressSpace target_space = + network::mojom::IPAddressSpace::kPublic; + if (network_utils::IsReservedIPAddress(request_url.Host())) -+ target_space = network::mojom::IPAddressSpace::kLocal; ++ target_space = network::mojom::IPAddressSpace::kPrivate; + if (SecurityOrigin::Create(request_url)->IsLocalhost()) -+ target_space = network::mojom::IPAddressSpace::kLoopback; ++ target_space = network::mojom::IPAddressSpace::kLocal; + + bool is_external_request = requestor_space > target_space; + if (is_external_request) @@ -156,6 +157,21 @@ diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/thi bool ShouldBlockFetchByMixedContentCheck( mojom::blink::RequestContextType request_context, network::mojom::blink::IPAddressSpace target_address_space, +diff --git a/third_party/blink/renderer/core/workers/installed_scripts_manager.cc b/third_party/blink/renderer/core/workers/installed_scripts_manager.cc +--- a/third_party/blink/renderer/core/workers/installed_scripts_manager.cc ++++ b/third_party/blink/renderer/core/workers/installed_scripts_manager.cc +@@ -33,9 +33,9 @@ InstalledScriptsManager::ScriptData::ScriptData( + // place so that this is shareable out of worker code. + response_address_space_ = network::mojom::IPAddressSpace::kPublic; + if (network_utils::IsReservedIPAddress(script_url_.Host())) +- response_address_space_ = network::mojom::IPAddressSpace::kLocal; ++ response_address_space_ = network::mojom::IPAddressSpace::kPrivate; + if (SecurityOrigin::Create(script_url_)->IsLocalhost()) +- response_address_space_ = network::mojom::IPAddressSpace::kLoopback; ++ response_address_space_ = network::mojom::IPAddressSpace::kLocal; + } + + ContentSecurityPolicyResponseHeaders diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc @@ -176,9 +192,9 @@ diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetc + network::mojom::IPAddressSpace target_space = + network::mojom::IPAddressSpace::kPublic; + if (network_utils::IsReservedIPAddress(request_url.Host())) -+ target_space = network::mojom::IPAddressSpace::kLocal; ++ target_space = network::mojom::IPAddressSpace::kPrivate; + if (SecurityOrigin::Create(request_url)->IsLocalhost()) -+ target_space = network::mojom::IPAddressSpace::kLoopback; ++ target_space = network::mojom::IPAddressSpace::kLocal; + + bool is_external_request = requestor_space > target_space; + if (is_external_request) @@ -222,7 +238,7 @@ diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_imp diff --git a/third_party/blink/renderer/modules/websockets/websocket_common.cc b/third_party/blink/renderer/modules/websockets/websocket_common.cc --- a/third_party/blink/renderer/modules/websockets/websocket_common.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_common.cc -@@ -125,9 +125,38 @@ WebSocketCommon::ConnectResult WebSocketCommon::Connect( +@@ -125,9 +125,39 @@ WebSocketCommon::ConnectResult WebSocketCommon::Connect( return ConnectResult::kException; } @@ -231,7 +247,8 @@ diff --git a/third_party/blink/renderer/modules/websockets/websocket_common.cc b + if (ShouldBlockGateWayAttacks(requestor_space, url_)) { + state_ = kClosed; + exception_state.ThrowSecurityError( -+ "Access to address of '" + url_.Host() + "' is not allowed from '" + execution_context->addressSpaceForBindings() + "' address space."); ++ "Access to address of '" + url_.Host() + ++ "' is not allowed from current address space."); + return ConnectResult::kException; + } + @@ -247,9 +264,9 @@ diff --git a/third_party/blink/renderer/modules/websockets/websocket_common.cc b + network::mojom::IPAddressSpace target_space = + network::mojom::IPAddressSpace::kPublic; + if (network_utils::IsReservedIPAddress(request_url.Host())) -+ target_space = network::mojom::IPAddressSpace::kLocal; ++ target_space = network::mojom::IPAddressSpace::kPrivate; + if (SecurityOrigin::Create(request_url)->IsLocalhost()) -+ target_space = network::mojom::IPAddressSpace::kLoopback; ++ target_space = network::mojom::IPAddressSpace::kLocal; + + bool is_external_request = requestor_space > target_space; + if (is_external_request) diff --git a/build/patches/Bromite-subresource-adblocker.patch b/build/patches/Bromite-subresource-adblocker.patch index 0e9301eb..182d5def 100644 --- a/build/patches/Bromite-subresource-adblocker.patch +++ b/build/patches/Bromite-subresource-adblocker.patch @@ -248,10 +248,10 @@ new file mode 100644 diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml -@@ -66,6 +66,11 @@ - android:key="safety_check" - android:order="12" - android:title="@string/prefs_safety_check"/> +@@ -71,6 +71,11 @@ + android:key="eyeo_adblock" + android:order="13" + android:title="@string/adblock_settings_title" /> + + -+ AdBlock settings ++ Legacy Adblock settings + + + Edit filters URL diff --git a/build/patches/Content-settings-infrastructure.patch b/build/patches/Content-settings-infrastructure.patch index c9c49f7a..a547c73b 100644 --- a/build/patches/Content-settings-infrastructure.patch +++ b/build/patches/Content-settings-infrastructure.patch @@ -24,13 +24,13 @@ Require: bromite-build-utils.patch chrome/browser/ui/BUILD.gn | 1 + .../views/page_info/page_info_view_factory.cc | 13 + .../settings_localized_strings_provider.cc | 39 +++ - .../ui/webui/settings/site_settings_helper.cc | 33 +- - .../browser_ui/site_settings/android/BUILD.gn | 15 + + .../ui/webui/settings/site_settings_helper.cc | 34 +- + .../browser_ui/site_settings/android/BUILD.gn | 16 + .../BromiteCustomContentSetting.java | 139 ++++++++ .../BromiteCustomContentSettingImpl.java | 307 ++++++++++++++++++ - .../BromiteCustomContentSetting_README.md | 151 +++++++++ + ...tomTriStateSiteSettingsPreferenceImpl.java | 24 ++ .../ContentSettingsResources.java | 14 +- - .../site_settings/SingleCategorySettings.java | 42 ++- + .../site_settings/SingleCategorySettings.java | 47 ++- .../site_settings/SingleWebsiteSettings.java | 26 +- .../site_settings/SiteSettings.java | 14 +- .../site_settings/SiteSettingsCategory.java | 18 +- @@ -72,10 +72,10 @@ Require: bromite-build-utils.patch .../execution_context/execution_context.cc | 16 + .../execution_context/execution_context.h | 5 + .../WebLayerSiteSettingsDelegate.java | 3 + - 61 files changed, 1310 insertions(+), 41 deletions(-) + 61 files changed, 1189 insertions(+), 42 deletions(-) create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java - create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl create mode 100644 components/browser_ui/strings/bromite_content_settings/placeholder.txt @@ -391,7 +391,7 @@ diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn -@@ -1927,6 +1927,7 @@ static_library("ui") { +@@ -1921,6 +1921,7 @@ static_library("ui") { "//components/commerce/core:shopping_service", "//components/commerce/core/mojom:mojo_bindings", "//components/commerce/core/webui", @@ -527,7 +527,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b return false; } -@@ -500,7 +509,13 @@ ContentSettingsType ContentSettingsTypeFromGroupName(base::StringPiece name) { +@@ -500,11 +509,24 @@ ContentSettingsType ContentSettingsTypeFromGroupName(base::StringPiece name) { return entry.type; } } @@ -542,10 +542,7 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b return ContentSettingsType::DEFAULT; } -@@ -520,6 +535,13 @@ base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { - } - } - + base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { @@ -553,10 +550,18 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b + return cs->name(); + } + } + for (const auto& entry : kContentSettingsTypeGroupNames) { + if (type == entry.type) { + // Content setting types that aren't represented in the settings UI +@@ -519,7 +541,6 @@ base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { + return entry.name ? entry.name : base::StringPiece(); + } + } +- NOTREACHED() << static_cast(type) << " is not a recognized content settings type."; return base::StringPiece(); -@@ -588,6 +610,13 @@ const std::vector& GetVisiblePermissionCategories() { +@@ -588,6 +609,13 @@ const std::vector& GetVisiblePermissionCategories() { base_types->push_back(ContentSettingsType::PRIVATE_NETWORK_GUARD); } @@ -573,13 +578,14 @@ diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/b diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn -@@ -145,6 +145,20 @@ android_library("java") { +@@ -145,6 +145,21 @@ android_library("java") { ":site_settings_jni_headers", "//components/content_settings/android:java_pref_names_srcjar", ] + sources += [ + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java", + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java", ++ "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java", + "java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java", + ] + deps += [ @@ -594,7 +600,7 @@ diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/b } android_library("javatests") { -@@ -190,6 +204,7 @@ robolectric_library("junit") { +@@ -190,6 +205,7 @@ robolectric_library("junit") { } android_resources("java_resources") { @@ -1058,162 +1064,35 @@ new file mode 100644 + return null; + } +} -diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java new file mode 100644 --- /dev/null -+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md -@@ -0,0 +1,151 @@ -+# Content Settings and Site Settings in Bromite ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java +@@ -0,0 +1,24 @@ ++/* ++ This file is part of Bromite. + -+[TOC] ++ Bromite is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. + -+## Overview ++ Bromite is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. + -+To simplify the addition and management of content settings ui in Bromite, you can use this method: automatically the new menus in the site settings and the item in page info management will be added. ++ You should have received a copy of the GNU General Public License ++ along with Bromite. If not, see . ++*/ + -+## How to use ++package org.chromium.components.browser_ui.site_settings; + -+* Add a class derived from [BromiteCustomContentSettingImpl](BromiteCustomContentSettingImpl.java) ++import org.chromium.components.content_settings.ContentSettingValues; + -+``` -+public class NewContentSetting extends BromiteCustomContentSetting { -+ public BromiteWebGLContentSetting() { -+ super(/*contentSettingsType*/ ContentSettingsType.NEW_CONTENT_SETTING, -+ /*siteSettingsCategory*/ SiteSettingsCategory.Type.NEW_CONTENT_SETTING, -+ /*defaultEnabledValue*/ ContentSettingValues.ALLOW, -+ /*defaultDisabledValue*/ ContentSettingValues.BLOCK, -+ /*allowException*/ true, -+ /*preferenceKey*/ "new_content_setting", -+ /*profilePrefKey*/ "new_content_setting"); -+ } -+ -+ @Override -+ public ContentSettingsResources.ResourceItem getResourceItem() { -+ return new ContentSettingsResources.ResourceItem( -+ /*icon*/ R.drawable.web_asset, -+ /*title*/ R.string.new_content_setting_permission_title, -+ /*defaultEnabledValue*/ getDefaultEnabledValue(), -+ /*defaultDisabledValue*/ getDefaultDisabledValue(), -+ /*enabledSummary*/ R.string.new_content_setting_enabled, -+ /*disabledSummary*/ R.string.new_content_setting_disabled); -+ } -+ -+ @Override -+ public int getCategorySummary(@Nullable @ContentSettingValues int value) { -+ switch (value) { -+ case ContentSettingValues.ALLOW: -+ return R.string.new_content_setting_allow; -+ case ContentSettingValues.ASK: -+ return R.string.new_content_setting_ask; -+ case ContentSettingValues.BLOCK: -+ return R.string.new_content_setting_disabled; -+ default: -+ return 0; -+ } -+ } -+ -+ @Override -+ public boolean requiresTriStateContentSetting() { -+ return true; // or false if is a on/off content setting -+ } -+ -+ @Override -+ public int[] getTriStateSettingDescriptionIDs() { -+ // only needed if is a tristate setting -+ int[] descriptionIDs = { -+ R.string.website_settings_category_webgl_enabled_antifingerprint, // ALLOWED -+ R.string.website_settings_category_webgl_enabled, // ASK -+ R.string.website_settings_category_webgl_disabled }; // BLOCKED -+ return descriptionIDs; -+ } -+ -+ @Override -+ public boolean showOnlyDescriptions() { -+ // true will remove ALLOWED/ASK/BLOCKED from UI -+ // leaving only the descriptions -+ return true; -+ } -+ -+ @Override -+ public int getAddExceptionDialogMessage() { -+ return R.string.new_content_setting_exception_dialog_message; -+ } -+ -+ @Override -+ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value) { -+ // indicate when the value should be considered an exception -+ return value != ContentSettingValues.BLOCK; -+ } ++public interface BromiteCustomTriStateSiteSettingsPreferenceImpl { ++ public @ContentSettingValues int getCheckedSetting(); +} -+``` -+ -+* Add the new class to `BromiteCustomContentSettingImpl` `cctor` -+ -+``` -+ static { -+ mItemList = new ArrayList(); -+ mItemList.add(new NewContentSetting()); -+ } -+``` -+ -+* Register the new content setting as usual in `ContentSettingsRegistry::Init()` -+ -+``` -+ Register(ContentSettingsType::NEW_CONTENT_SETTING, "new_content_setting", CONTENT_SETTING_BLOCK, -+ WebsiteSettingsInfo::SYNCABLE, -+ AllowlistedSchemes(), -+ ValidSettings(CONTENT_SETTING_ALLOW, // allow -+ CONTENT_SETTING_ASK, // ask -+ CONTENT_SETTING_BLOCK), // block -+ WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE, -+ WebsiteSettingsRegistry::PLATFORM_ANDROID, -+ ContentSettingsInfo::INHERIT_IN_INCOGNITO, -+ ContentSettingsInfo::PERSISTENT, -+ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS, -+ /*show_into_info_page*/ true, -+ /*permission_type_ui*/ IDS_NEW_CONTENT_SETTING, -+ /*permission_type_ui_mid_sentence*/ IDS_NEW_CONTENT_SETTING_MID_SENTENCE); -+``` -+ -+* Add your content setting in `@IntDef()` and `Type` in `SiteSettingsCategory` as usual -+ -+* Add your strings in a new file in `components/browser_ui/strings/android/` -+ -+``` -+ -+ -+ -+ your content type -+ -+ -+ your content type -+ -+ -+ your content type -+ -+ -+ your content type is enabled -+ -+ -+ ask before activate your content type -+ -+ -+ your content type is disabled -+ -+ -+``` -+ -+* Reference it in `components/components_strings.grd` to have strings in native -+ -+``` -+ -+``` -+ -+* Reference it in `components/browser_ui/strings/android/browser_ui_strings.grd` to have the strings in java -+ -+``` -+ -+``` diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java @@ -1340,17 +1219,24 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (allowSpecifyingExceptions) { getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(), ADD_EXCEPTION_KEY, getAddExceptionDialogMessage(), mCategory, this)); -@@ -1087,6 +1107,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1085,8 +1105,16 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + private boolean isBlocked() { + switch (mGlobalToggleLayout) { case GlobalToggleLayout.TRI_STATE_TOGGLE: ++ Preference triStateToggleImpl = ++ getPreferenceScreen().findPreference(TRI_STATE_TOGGLE_KEY); ++ if (triStateToggleImpl instanceof BromiteCustomTriStateSiteSettingsPreferenceImpl) { ++ Boolean blocked = BromiteCustomContentSettingImpl.considerException(mCategory, ++ ((BromiteCustomTriStateSiteSettingsPreferenceImpl)triStateToggleImpl).getCheckedSetting()); ++ if (blocked != null) return (boolean)blocked; ++ } TriStateSiteSettingsPreference triStateToggle = getPreferenceScreen().findPreference(TRI_STATE_TOGGLE_KEY); + if (triStateToggle == null) return true; -+ Boolean blocked = BromiteCustomContentSettingImpl.considerException(mCategory, triStateToggle.getCheckedSetting()); -+ if (blocked != null) return (boolean)blocked; return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK); case GlobalToggleLayout.FOUR_STATE_COOKIE_TOGGLE: FourStateCookieSettingsPreference fourStateCookieToggle = -@@ -1165,7 +1188,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1165,7 +1193,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment } else if (mCategory.getType() == SiteSettingsCategory.Type.THIRD_PARTY_COOKIES) { infoText.setSummary(R.string.website_settings_third_party_cookies_page_description); } else { @@ -1363,7 +1249,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } // Hide the anti-abuse text preferences, as needed. -@@ -1189,6 +1216,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1189,6 +1221,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment screen.removePreference(antiAbuseThingsToConsiderHeader); screen.removePreference(antiAbuseThingsToConsiderSectionOne); } @@ -1371,7 +1257,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c if (permissionBlockedByOs) { maybeShowOsWarning(screen); -@@ -1352,7 +1380,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1352,7 +1385,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment getSiteSettingsDelegate().getBrowserContextHandle(), contentType); int[] descriptionIds = ContentSettingsResources.getTriStateSettingDescriptionIDs(contentType); @@ -1380,7 +1266,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c } private void configureBinaryToggle(ChromeSwitchPreference binaryToggle, int contentType) { -@@ -1478,6 +1506,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment +@@ -1478,6 +1511,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment @ContentSettingValues Integer value = site.getContentSetting(browserContextHandle, contentSettingsType); @@ -1864,7 +1750,7 @@ diff --git a/components/content_settings/core/browser/content_settings_utils.cc + if (info->is_renderer_content_setting()) { + ContentSettingRuleSource rule; + rule.type = (int32_t)info->type(); -+ map->GetSettingsForOneType(info->type(), &rule.rules); ++ rule.rules = map->GetSettingsForOneType(info->type()); + rules->settings_rules.push_back(rule); + } + } diff --git a/build/patches/Disable-all-promo-dialogs.patch b/build/patches/Disable-all-promo-dialogs.patch index 44f674c9..dd38a580 100644 --- a/build/patches/Disable-all-promo-dialogs.patch +++ b/build/patches/Disable-all-promo-dialogs.patch @@ -2,11 +2,15 @@ From: uazo Date: Tue, 12 Jun 2018 15:09:26 +0200 Subject: Disable all promo dialogs +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- - .../chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java | 1 + - .../ui/views/user_education/browser_feature_promo_controller.cc | 1 + - components/user_education/common/feature_promo_registry.cc | 1 + - 3 files changed, 3 insertions(+) + .../chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java | 1 + + chrome/browser/ui/browser_ui_prefs.cc | 2 +- + chrome/browser/ui/ui_features.cc | 2 +- + .../ui/views/user_education/browser_feature_promo_controller.cc | 1 + + .../chrome/browser/user_education/UserEducationHelper.java | 1 + + components/user_education/common/feature_promo_registry.cc | 1 + + 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java @@ -19,6 +23,30 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab // Only one promo can be shown in one run to avoid nagging users too much. if (FullScreenSyncPromoUtil.launchPromoIfNeeded(mActivity, SyncConsentActivityLauncherImpl.get(), VersionInfo.getProductMajorVersion())) { +diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc +--- a/chrome/browser/ui/browser_ui_prefs.cc ++++ b/chrome/browser/ui/browser_ui_prefs.cc +@@ -143,7 +143,7 @@ void RegisterBrowserUserPrefs(user_prefs::PrefRegistrySyncable* registry) { + + registry->RegisterBooleanPref(prefs::kEnterpriseHardwarePlatformAPIEnabled, + false); +- registry->RegisterBooleanPref(prefs::kUserFeedbackAllowed, true); ++ registry->RegisterBooleanPref(prefs::kUserFeedbackAllowed, false); + registry->RegisterBooleanPref( + prefs::kExternalProtocolDialogShowAlwaysOpenCheckbox, true); + registry->RegisterBooleanPref(prefs::kScreenCaptureAllowed, true); +diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc +--- a/chrome/browser/ui/ui_features.cc ++++ b/chrome/browser/ui/ui_features.cc +@@ -25,7 +25,7 @@ BASE_FEATURE(kDesktopPWAsAppHomePage, + #endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) + + // Enables Chrome Labs menu in the toolbar. See https://crbug.com/1145666 +-BASE_FEATURE(kChromeLabs, "ChromeLabs", base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kChromeLabs, "ChromeLabs", base::FEATURE_DISABLED_BY_DEFAULT); + const char kChromeLabsActivationParameterName[] = + "chrome_labs_activation_percentage"; + const base::FeatureParam kChromeLabsActivationPercentage{ diff --git a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc --- a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc +++ b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc @@ -30,6 +58,17 @@ diff --git a/chrome/browser/ui/views/user_education/browser_feature_promo_contro // Temporarily turn off IPH in incognito as a concern was raised that // the IPH backend ignores incognito and writes to the parent profile. // See https://bugs.chromium.org/p/chromium/issues/detail?id=1128728#c30 +diff --git a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelper.java b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelper.java +--- a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelper.java ++++ b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelper.java +@@ -71,6 +71,7 @@ public class UserEducationHelper { + } + + private void showIPH(Tracker tracker, IPHCommand iphCommand) { ++ if ((true)) return; + // Activity was destroyed; don't show IPH. + View anchorView = iphCommand.anchorView; + if (mActivity.isFinishing() || mActivity.isDestroyed() || anchorView == null) { diff --git a/components/user_education/common/feature_promo_registry.cc b/components/user_education/common/feature_promo_registry.cc --- a/components/user_education/common/feature_promo_registry.cc +++ b/components/user_education/common/feature_promo_registry.cc diff --git a/build/patches/Disable-conversion-measurement-api.patch b/build/patches/Disable-conversion-measurement-api.patch index 68b4a107..9249968b 100644 --- a/build/patches/Disable-conversion-measurement-api.patch +++ b/build/patches/Disable-conversion-measurement-api.patch @@ -23,18 +23,18 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../attribution_storage_sql.cc | 8 +- content/browser/storage_partition_impl.cc | 8 +- content/public/android/BUILD.gn | 2 - - .../browser/AttributionOsLevelManager.java | 219 ++---------------- + .../browser/AttributionOsLevelManager.java | 225 ++---------------- .../public/browser/navigation_controller.cc | 1 - content/public/common/content_features.cc | 4 +- content/renderer/render_thread_impl.cc | 5 +- .../attribution/request_headers_internal.cc | 1 + .../network/public/cpp/attribution_utils.cc | 2 + services/network/public/cpp/features.cc | 6 +- - third_party/blink/common/features.cc | 26 +-- + third_party/blink/common/features.cc | 26 +- .../platform/runtime_enabled_features.json5 | 7 + ui/base/ui_base_features.cc | 2 +- ui/events/android/motion_event_android.cc | 6 +- - 23 files changed, 89 insertions(+), 255 deletions(-) + 23 files changed, 89 insertions(+), 261 deletions(-) diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml @@ -498,10 +498,16 @@ diff --git a/content/public/android/java/src/org/chromium/content/browser/Attrib if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); return; -@@ -356,32 +195,6 @@ public class AttributionOsLevelManager { +@@ -350,38 +189,6 @@ public class AttributionOsLevelManager { AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); return; } +- MeasurementManagerFutures mm = +- MeasurementManagerFutures.from(ContextUtils.getApplicationContext()); +- if (mm == null) { +- AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0); +- return; +- } - - ListenableFuture future = null; - try { diff --git a/build/patches/Disable-safety-check.patch b/build/patches/Disable-safety-check.patch index 4bf596b5..fa834c88 100644 --- a/build/patches/Disable-safety-check.patch +++ b/build/patches/Disable-safety-check.patch @@ -66,8 +66,8 @@ diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/j - android:order="12" - android:title="@string/prefs_safety_check"/> dialogControllerSupplier, @@ -243,7 +243,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mContext = context; mResetHandler = resetHandler; mModel = model; -@@ -143,10 +156,29 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -144,10 +157,29 @@ public class TabGroupUiMediator implements BackPressHandler { mIsShowingOverViewMode = true; } @@ -273,7 +273,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mContext) && getTabsToShowForId(lastId).contains(tab)) { return; -@@ -199,6 +231,7 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -200,6 +232,7 @@ public class TabGroupUiMediator implements BackPressHandler { return; } resetTabStripWithRelatedTabsForId(currentTab.getId()); @@ -281,7 +281,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser } @Override -@@ -314,6 +347,8 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -315,6 +348,8 @@ public class TabGroupUiMediator implements BackPressHandler { resetTabStripWithRelatedTabsForId(tab.getId()); } @@ -290,7 +290,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser mBackPressStateSupplier = new ObservableSupplierImpl<>(); if (mTabGridDialogControllerSupplier != null) { mTabGridDialogControllerSupplier.onAvailable(controller -> { -@@ -327,6 +362,18 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -328,6 +363,18 @@ public class TabGroupUiMediator implements BackPressHandler { mModel.set(TabGroupUiProperties.LEFT_BUTTON_DRAWABLE_ID, drawableId); } @@ -309,7 +309,7 @@ diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser void setupLeftButtonOnClickListener(View.OnClickListener listener) { mModel.set(TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER, listener); } -@@ -437,6 +484,7 @@ public class TabGroupUiMediator implements BackPressHandler { +@@ -442,6 +489,7 @@ public class TabGroupUiMediator implements BackPressHandler { } public void destroy() { diff --git a/build/patches/Multiple-fingerprinting-mitigations.patch b/build/patches/Multiple-fingerprinting-mitigations.patch index 05ed9ee5..4bdd1a89 100644 --- a/build/patches/Multiple-fingerprinting-mitigations.patch +++ b/build/patches/Multiple-fingerprinting-mitigations.patch @@ -62,7 +62,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -2450,6 +2450,7 @@ static_library("browser") { +@@ -2446,6 +2446,7 @@ static_library("browser") { "//services/device/public/cpp:device_features", "//services/device/public/cpp/geolocation", "//services/device/public/cpp/usb", diff --git a/build/patches/Remove-binary-blob-integrations.patch b/build/patches/Remove-binary-blob-integrations.patch index 8fa472e1..a7807419 100644 --- a/build/patches/Remove-binary-blob-integrations.patch +++ b/build/patches/Remove-binary-blob-integrations.patch @@ -89,7 +89,8 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html components/signin/public/android/BUILD.gn | 3 - .../signin/AccountRenameChecker.java | 16 - components/webauthn/android/BUILD.gn | 11 - - .../webauthn/AuthenticatorImpl.java | 89 +-- + .../webauthn/AuthenticatorImpl.java | 93 +-- + .../webauthn/CredManMetricsHelper.java | 17 - .../webauthn/Fido2ApiCallHelper.java | 58 +- .../push_messaging/push_messaging_manager.cc | 2 +- content/public/android/BUILD.gn | 4 - @@ -105,7 +106,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html third_party/cardboard/BUILD.gn | 4 - weblayer/browser/java/BUILD.gn | 1 - weblayer/public/java/BUILD.gn | 1 - - 81 files changed, 96 insertions(+), 1991 deletions(-) + 82 files changed, 96 insertions(+), 2012 deletions(-) diff --git a/android_webview/expectations/system_webview_bundle.AndroidManifest.expected b/android_webview/expectations/system_webview_bundle.AndroidManifest.expected --- a/android_webview/expectations/system_webview_bundle.AndroidManifest.expected @@ -1085,7 +1086,7 @@ diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn "webui/internals/internals_ui.cc", "webui/internals/internals_ui.h", "webui/interstitials/interstitial_ui.cc", -@@ -520,7 +518,6 @@ static_library("ui") { +@@ -514,7 +512,6 @@ static_library("ui") { "//components/feedback/redaction_tool", "//components/find_in_page", "//components/flags_ui", @@ -3124,23 +3125,22 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut private MakeCredential_Response mMakeCredentialCallback; private GetAssertion_Response mGetAssertionCallback; // A queue is used to store pending IsUserVerifyingPlatformAuthenticatorAvailable request -@@ -70,15 +66,8 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -70,14 +66,6 @@ public final class AuthenticatorImpl implements Authenticator { // situation does not matter because all pending requests will return the same value. private Queue> mIsUserVerifyingPlatformAuthenticatorAvailableCallbackQueue = new LinkedList<>(); - private Fido2CredentialRequest mPendingFido2CredentialRequest; - private Set mUnclosedFido2CredentialRequests = new HashSet<>(); - +- private Set mUnclosedFido2CredentialRequests = new HashSet<>(); +- - // StaticFieldLeak complains that this is a memory leak because - // `Fido2CredentialRequest` contains a `Context`. But this field is only - // used in tests so a memory leak is irrelevent. - @SuppressLint("StaticFieldLeak") - private static Fido2CredentialRequest sFido2CredentialRequestOverrideForTesting; -- + /** * Builds the Authenticator service implementation. - * -@@ -97,21 +86,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -97,21 +85,6 @@ public final class AuthenticatorImpl implements Authenticator { mRenderFrameHost = renderFrameHost; mOrigin = mRenderFrameHost.getLastCommittedOrigin(); mTopOrigin = topOrigin; @@ -3162,7 +3162,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -141,17 +115,9 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -141,17 +114,9 @@ public final class AuthenticatorImpl implements Authenticator { mMakeCredentialCallback = callback; mIsOperationPending = true; @@ -3182,7 +3182,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } @Override -@@ -165,16 +131,8 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -165,16 +130,8 @@ public final class AuthenticatorImpl implements Authenticator { mGetAssertionCallback = callback; mIsOperationPending = true; @@ -3201,7 +3201,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } @Override -@@ -186,15 +144,8 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -186,15 +143,8 @@ public final class AuthenticatorImpl implements Authenticator { callback.call(isUvpaa); }; @@ -3219,7 +3219,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -203,7 +154,7 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -203,7 +153,7 @@ public final class AuthenticatorImpl implements Authenticator { * version. */ public boolean isGetMatchingCredentialIdsSupported() { @@ -3228,7 +3228,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -217,32 +168,13 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -217,32 +167,13 @@ public final class AuthenticatorImpl implements Authenticator { */ public void getMatchingCredentialIds(String relyingPartyId, byte[][] credentialIds, boolean requireThirdPartyPayment, GetMatchingCredentialIdsResponseCallback callback) { @@ -3263,7 +3263,7 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } @Override -@@ -254,8 +186,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -254,8 +185,6 @@ public final class AuthenticatorImpl implements Authenticator { if (!mIsOperationPending || mGetAssertionCallback == null) { return; } @@ -3272,7 +3272,15 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } /** -@@ -305,7 +235,6 @@ public final class AuthenticatorImpl implements Authenticator { +@@ -297,7 +226,6 @@ public final class AuthenticatorImpl implements Authenticator { + } else if (mGetAssertionCallback != null) { + mGetAssertionCallback.call(status, null, null); + } +- if (mPendingFido2CredentialRequest != null) mPendingFido2CredentialRequest.destroyBridge(); + cleanupRequest(); + } + +@@ -305,13 +233,10 @@ public final class AuthenticatorImpl implements Authenticator { mIsOperationPending = false; mMakeCredentialCallback = null; mGetAssertionCallback = null; @@ -3280,6 +3288,44 @@ diff --git a/components/webauthn/android/java/src/org/chromium/components/webaut } @Override + public void close() { +- mUnclosedFido2CredentialRequests.forEach(Fido2CredentialRequest::destroyBridge); +- mUnclosedFido2CredentialRequests.clear(); + cleanupRequest(); + } + +diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/CredManMetricsHelper.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/CredManMetricsHelper.java +--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/CredManMetricsHelper.java ++++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/CredManMetricsHelper.java +@@ -7,7 +7,6 @@ package org.chromium.components.webauthn; + import androidx.annotation.IntDef; + + import org.chromium.base.metrics.RecordHistogram; +-import org.chromium.components.webauthn.Fido2CredentialRequest.ConditionalUiState; + + /** + * This class is responsible for emitting histograms regarding CredMan usage in +@@ -77,20 +76,4 @@ public class CredManMetricsHelper { + RecordHistogram.recordTimesHistogram( + "WebAuthentication.Android.CredManPrepareRequestDuration", durationMs); + } +- +- public void reportGetCredentialMetrics( +- @CredManGetRequestEnum int value, ConditionalUiState conditionalUiState) { +- assert !(conditionalUiState == ConditionalUiState.NONE) +- || !(value == CredManGetRequestEnum.SUCCESS_PASSWORD) +- : "Passwords cannot be received from modal requests!"; +- if (conditionalUiState == ConditionalUiState.NONE) { +- RecordHistogram.recordEnumeratedHistogram( +- "WebAuthentication.Android.CredManModalRequests", value, +- CredManGetRequestEnum.NUM_ENTRIES); +- return; +- } +- RecordHistogram.recordEnumeratedHistogram( +- "WebAuthentication.Android.CredManConditionalRequest", value, +- CredManGetRequestEnum.NUM_ENTRIES); +- } + } diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java diff --git a/build/patches/Site-setting-for-images.patch b/build/patches/Site-setting-for-images.patch index c2398d63..7db2dbc7 100644 --- a/build/patches/Site-setting-for-images.patch +++ b/build/patches/Site-setting-for-images.patch @@ -15,8 +15,8 @@ Require: Content-settings-infrastructure.patch .../bromite_content_settings/images.grdp | 23 +++++ .../bromite_content_settings/images.inc | 6 ++ .../core/browser/content_settings_registry.cc | 2 +- - .../core/browser/content_settings_utils.cc | 8 +- - 10 files changed, 124 insertions(+), 7 deletions(-) + .../core/browser/content_settings_utils.cc | 7 +- + 10 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-hdpi/permission_images.png create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-mdpi/permission_images.png create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-xhdpi/permission_images.png @@ -259,7 +259,7 @@ diff --git a/components/content_settings/core/browser/content_settings_registry. diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc -@@ -145,12 +145,8 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, +@@ -145,12 +145,7 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, ContentSettingToValue(CONTENT_SETTING_ALLOW), std::string(), map->IsOffTheRecord())); #else @@ -269,8 +269,7 @@ diff --git a/components/content_settings/core/browser/content_settings_utils.cc - ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), - ContentSettingToValue(CONTENT_SETTING_ALLOW), std::string(), - map->IsOffTheRecord())); -+ map->GetSettingsForOneType(ContentSettingsType::IMAGES, -+ &(rules->image_rules)); ++ rules->image_rules = map->GetSettingsForOneType(ContentSettingsType::IMAGES); // In Android active mixed content is hard blocked, with no option to allow // it. rules->mixed_content_rules.push_back(ContentSettingPatternSource( diff --git a/build/patches/Timezone-customization.patch b/build/patches/Timezone-customization.patch index 3a0cd9ed..1c92fd33 100644 --- a/build/patches/Timezone-customization.patch +++ b/build/patches/Timezone-customization.patch @@ -13,12 +13,12 @@ Require: Content-settings-infrastructure.patch .../browser_ui/site_settings/android/BUILD.gn | 3 + .../res/layout/time_zone_select_dialog.xml | 36 ++++ ...ezoneoverride_site_settings_preference.xml | 68 ++++++ - ...imezoneOverrideSiteSettingsPreference.java | 194 ++++++++++++++++++ + ...imezoneOverrideSiteSettingsPreference.java | 196 ++++++++++++++++++ .../WebsitePreferenceBridge.java | 10 + ...BromiteTimezoneOverrideContentSetting.java | 147 +++++++++++++ .../android/website_preference_bridge.cc | 16 ++ .../bromite_content_settings/timezone.grdp | 39 ++++ - .../timezone_override.inc | 23 +++ + .../timezone_override.inc | 23 ++ .../browser/content_settings_pref_provider.cc | 16 ++ .../browser/content_settings_pref_provider.h | 4 + .../core/browser/content_settings_utils.cc | 5 + @@ -31,9 +31,9 @@ Require: Content-settings-infrastructure.patch .../common/content_settings_mojom_traits.h | 5 + .../core/common/pref_names.cc | 3 + .../content_settings/core/common/pref_names.h | 2 + - .../renderer/content_settings_agent_impl.cc | 80 ++++++++ + .../renderer/content_settings_agent_impl.cc | 80 +++++++ .../renderer/content_settings_agent_impl.h | 11 + - 23 files changed, 679 insertions(+), 1 deletion(-) + 23 files changed, 681 insertions(+), 1 deletion(-) create mode 100755 components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml create mode 100755 components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml create mode 100755 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java @@ -53,7 +53,7 @@ diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/b ] resources_package = "org.chromium.components.browser_ui.site_settings" -@@ -272,6 +273,8 @@ android_resources("java_resources") { +@@ -273,6 +274,8 @@ android_resources("java_resources") { "java/res/xml/site_settings_preferences.xml", "java/res/xml/site_settings_preferences_with_categories.xml", "java/res/xml/website_preferences.xml", @@ -181,7 +181,7 @@ diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/c new file mode 100755 --- /dev/null +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java -@@ -0,0 +1,194 @@ +@@ -0,0 +1,196 @@ +/* + This file is part of Bromite. + @@ -235,7 +235,8 @@ new file mode 100755 + * TimezoneOverride Preference for SiteSettings. + */ +public class TimezoneOverrideSiteSettingsPreference -+ extends Preference implements RadioGroup.OnCheckedChangeListener, ++ extends Preference implements BromiteCustomTriStateSiteSettingsPreferenceImpl, ++ RadioGroup.OnCheckedChangeListener, + RadioButtonWithEditText.OnTextChangeListener { + private @ContentSettingValues int mSetting = ContentSettingValues.DEFAULT; + private RadioButtonWithDescription mAllowed; @@ -260,6 +261,7 @@ new file mode 100755 + mBrowserContextHandle = browserContextHandle; + } + ++ @Override + public @ContentSettingValues int getCheckedSetting() { + return mSetting; + } @@ -711,7 +713,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc -@@ -160,6 +160,11 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, +@@ -159,6 +159,11 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, map->GetSettingsForOneType(ContentSettingsType::JAVASCRIPT); rules->popup_redirect_rules = map->GetSettingsForOneType(ContentSettingsType::POPUPS); diff --git a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch index 2dfb9dc5..63a1d091 100644 --- a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch +++ b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch @@ -89,7 +89,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn "//chrome/browser/headless", "//chrome/common", "//chrome/common:buildflags", -@@ -7670,8 +7664,6 @@ static_library("browser") { +@@ -7666,8 +7660,6 @@ static_library("browser") { "supervised_user/kids_chrome_management/kids_profile_manager.h", "supervised_user/supervised_user_browser_utils.cc", "supervised_user/supervised_user_browser_utils.h", From 98f1112f6596c6c52d4e95f90f17f289e3650a34 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Thu, 7 Sep 2023 15:01:03 +0200 Subject: [PATCH 05/17] Disable cardboard --- build/bromite.gn_args | 1 + 1 file changed, 1 insertion(+) diff --git a/build/bromite.gn_args b/build/bromite.gn_args index 48e3dc4f..293db8eb 100644 --- a/build/bromite.gn_args +++ b/build/bromite.gn_args @@ -48,6 +48,7 @@ enable_arcore=false enable_openxr=false enable_gvr_services=false enable_feed_v2=false +enable_cardboard=false is_high_end_android=true # Do not compile libmonochrome.so with RELR relocations From 009240be1ed978db40520451a9fae882891f0cf8 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Fri, 8 Sep 2023 08:35:42 +0200 Subject: [PATCH 06/17] Bump to 117.0.5938.48 --- build/RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/RELEASE b/build/RELEASE index 4be02e71..0711676e 100644 --- a/build/RELEASE +++ b/build/RELEASE @@ -1 +1 @@ -117.0.5938.35 \ No newline at end of file +117.0.5938.48 \ No newline at end of file From 00f399d8aa020462a13bae148e06cc44022e5e2e Mon Sep 17 00:00:00 2001 From: uazo Date: Fri, 8 Sep 2023 06:43:57 +0000 Subject: [PATCH 07/17] AUTOMATED - git apply results --- .../patches/00Add-setting-to-clear-data-on-exit.patch | 2 +- .../00Enable-Document-Open-Inheritance-Removal.patch | 2 +- build/patches/00Fix-chromium-build-bugs.patch | 2 +- .../00Fix-eyeo-Browser-Ad-filtering-patches.patch | 7 +++---- ...Log-dangling-attributes-in-some-html-elements.patch | 6 +++--- build/patches/AImageReader-CFI-crash-mitigations.patch | 2 +- build/patches/Add-an-always-incognito-mode.patch | 4 ++-- build/patches/Add-exit-menu-item.patch | 2 +- build/patches/Add-flag-to-disable-vibration.patch | 2 +- build/patches/Add-menu-item-to-bookmark-all-tabs.patch | 4 ++-- build/patches/Add-menu-item-to-view-source.patch | 2 +- ...dd-option-to-not-persist-tabs-across-sessions.patch | 2 +- .../Allow-building-without-enable_reporting.patch | 2 +- build/patches/Client-hints-overrides.patch | 2 +- build/patches/Content-settings-infrastructure.patch | 2 +- .../Disable-Accessibility-service-by-default.patch | 2 +- build/patches/Disable-all-predictors-code.patch | 10 +++++----- build/patches/Disable-text-fragments-by-default.patch | 4 ++-- ...Inject-scripts-for-AMP-tracking-ads-and-video.patch | 4 ++-- .../patches/Multiple-fingerprinting-mitigations.patch | 2 +- build/patches/Remove-binary-blob-integrations.patch | 2 +- build/patches/Remove-help-menu-item.patch | 2 +- .../Revert-Delete-block-external-form-redirects.patch | 4 ++-- build/patches/eyeo-117.0.5938.0-base.patch | 4 ++-- 24 files changed, 38 insertions(+), 39 deletions(-) diff --git a/build/patches/00Add-setting-to-clear-data-on-exit.patch b/build/patches/00Add-setting-to-clear-data-on-exit.patch index 4490154d..c782ef73 100644 --- a/build/patches/00Add-setting-to-clear-data-on-exit.patch +++ b/build/patches/00Add-setting-to-clear-data-on-exit.patch @@ -53,7 +53,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.read_later.ReadingListBackPressHandler; import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.chrome.browser.reengagement.ReengagementNotificationController; -@@ -1264,7 +1265,11 @@ public class ChromeTabbedActivity extends ChromeActivityGetSecurityOrigin()->CanRequest( base_element_url)) { UseCounter::Count(*this, WebFeature::kBaseWithCrossOriginHref); @@ -72,7 +72,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink } } -@@ -4562,6 +4578,8 @@ void Document::ProcessBaseElement() { +@@ -4564,6 +4580,8 @@ void Document::ProcessBaseElement() { if (target->Contains('<')) UseCounter::Count(*this, WebFeature::kBaseWithOpenBracketInTarget); base_target_ = *target; diff --git a/build/patches/AImageReader-CFI-crash-mitigations.patch b/build/patches/AImageReader-CFI-crash-mitigations.patch index 515bce43..2ded0593 100644 --- a/build/patches/AImageReader-CFI-crash-mitigations.patch +++ b/build/patches/AImageReader-CFI-crash-mitigations.patch @@ -177,7 +177,7 @@ diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt --- a/gpu/config/gpu_workaround_list.txt +++ b/gpu/config/gpu_workaround_list.txt -@@ -15,6 +15,7 @@ decode_encode_srgb_for_generatemipmap +@@ -16,6 +16,7 @@ decode_encode_srgb_for_generatemipmap depth_stencil_renderbuffer_resize_emulation disable_2d_canvas_auto_flush disable_accelerated_av1_decode diff --git a/build/patches/Add-an-always-incognito-mode.patch b/build/patches/Add-an-always-incognito-mode.patch index 8ee5ed5c..968c9675 100644 --- a/build/patches/Add-an-always-incognito-mode.patch +++ b/build/patches/Add-an-always-incognito-mode.patch @@ -251,7 +251,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout; -@@ -579,9 +583,14 @@ public class ChromeTabbedActivity extends ChromeActivity getTabModelSelector().closeAllTabs()); RecordUserAction.record("MobileMenuCloseAllTabs"); @@ -73,7 +73,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct } else if (id == R.id.close_all_incognito_tabs_menu_id) { // Close only incognito tabs CloseAllTabsDialog.show(this, getModalDialogManagerSupplier(), -@@ -2343,6 +2346,27 @@ public class ChromeTabbedActivity extends ChromeActivity urls_to_fetch; + InsertionOrderedSet hosts_to_fetch; +@@ -1363,6 +1365,9 @@ OptimizationTypeDecision HintsManager::CanApplyOptimization( bool skip_cache, OptimizationMetadata* optimization_metadata) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); diff --git a/build/patches/Disable-text-fragments-by-default.patch b/build/patches/Disable-text-fragments-by-default.patch index 2ec77920..cbd80797 100644 --- a/build/patches/Disable-text-fragments-by-default.patch +++ b/build/patches/Disable-text-fragments-by-default.patch @@ -129,7 +129,7 @@ diff --git a/third_party/blink/public/common/features.h b/third_party/blink/publ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc -@@ -4410,9 +4410,14 @@ void Document::SetURL(const KURL& url) { +@@ -4412,9 +4412,14 @@ void Document::SetURL(const KURL& url) { TRACE_EVENT1("navigation", "Document::SetURL", "url", new_url.GetString().Utf8()); @@ -147,7 +147,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 -@@ -3536,10 +3536,9 @@ +@@ -3537,10 +3537,9 @@ }, { name: "TextFragmentIdentifiers", diff --git a/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch b/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch index 698a8a7a..a23dbd65 100644 --- a/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch +++ b/build/patches/Inject-scripts-for-AMP-tracking-ads-and-video.patch @@ -52,7 +52,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink #ifndef NDEBUG using WeakDocumentSet = blink::HeapHashSet>; static WeakDocumentSet& LiveDocumentSet(); -@@ -7440,6 +7443,64 @@ void Document::OnPrepareToStopParsing() { +@@ -7442,6 +7445,64 @@ void Document::OnPrepareToStopParsing() { MilestoneForDelayedAsyncScript::kFinishedParsing); } @@ -117,7 +117,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink void Document::FinishedParsing() { DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing()); DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading); -@@ -7506,6 +7567,9 @@ void Document::FinishedParsing() { +@@ -7508,6 +7569,9 @@ void Document::FinishedParsing() { } frame->Loader().FinishedParsing(); diff --git a/build/patches/Multiple-fingerprinting-mitigations.patch b/build/patches/Multiple-fingerprinting-mitigations.patch index 4bdd1a89..23e92b38 100644 --- a/build/patches/Multiple-fingerprinting-mitigations.patch +++ b/build/patches/Multiple-fingerprinting-mitigations.patch @@ -478,7 +478,7 @@ diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_c #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/stroke_data.h" #include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h" -@@ -2186,6 +2187,10 @@ ImageData* BaseRenderingContext2D::getImageDataInternal( +@@ -2185,6 +2186,10 @@ ImageData* BaseRenderingContext2D::getImageDataInternal( snapshot->PaintImageForCurrentFrame().GetSkImageInfo().bounds(); DCHECK(!bounds.intersect(SkIRect::MakeXYWH(sx, sy, sw, sh))); } diff --git a/build/patches/Remove-binary-blob-integrations.patch b/build/patches/Remove-binary-blob-integrations.patch index a7807419..4fe7fd0c 100644 --- a/build/patches/Remove-binary-blob-integrations.patch +++ b/build/patches/Remove-binary-blob-integrations.patch @@ -1249,7 +1249,7 @@ diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java -@@ -2494,14 +2494,6 @@ public class ExternalNavigationHandler { +@@ -2504,14 +2504,6 @@ public class ExternalNavigationHandler { * @return Whether the given intent is going to open an Instant App. */ private static boolean isIntentToInstantApp(Intent intent) { diff --git a/build/patches/Remove-help-menu-item.patch b/build/patches/Remove-help-menu-item.patch index 88aa35d5..0d5c5e8a 100644 --- a/build/patches/Remove-help-menu-item.patch +++ b/build/patches/Remove-help-menu-item.patch @@ -60,7 +60,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java -@@ -567,7 +567,7 @@ public abstract class BaseCustomTabActivity extends ChromeActivityCreateURLLoaderFactory(std::move(default_factory_receiver), std::move(params)); From a45ab18f8fca9e5b58b97f3fac45e568959a0cc4 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:49:44 +0200 Subject: [PATCH 08/17] #282 Fix crash with ImprovedBookmarks enabled --- .../Add-bookmark-import-export-actions.patch | 27 ++++++++++++++++++- .../Bookmarks-select-all-menu-entry.patch | 20 +++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/build/patches/Add-bookmark-import-export-actions.patch b/build/patches/Add-bookmark-import-export-actions.patch index 3c72f694..f2392e45 100644 --- a/build/patches/Add-bookmark-import-export-actions.patch +++ b/build/patches/Add-bookmark-import-export-actions.patch @@ -12,6 +12,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- chrome/android/java/AndroidManifest.xml | 1 - .../java/res/menu/bookmark_toolbar_menu.xml | 14 + + .../menu/bookmark_toolbar_menu_improved.xml | 14 + .../browser/TabbedModeTabDelegateFactory.java | 5 +- .../app/bookmarks/BookmarkActivity.java | 32 ++ .../browser/bookmarks/BookmarkBridge.java | 278 +++++++++++++++++ @@ -51,7 +52,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../select_file_dialog_android.cc | 6 + ui/shell_dialogs/select_file_dialog_android.h | 2 + ui/shell_dialogs/select_file_dialog_win.cc | 5 + - 41 files changed, 901 insertions(+), 29 deletions(-) + 42 files changed, 915 insertions(+), 29 deletions(-) diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml @@ -84,6 +85,30 @@ diff --git a/chrome/android/java/res/menu/bookmark_toolbar_menu.xml b/chrome/and + android:title="@string/export_bookmarks" + android:visible="true" + app:showAsAction="ifRoom" ++ app:iconTint="@color/default_icon_color_tint_list" /> + ++ ++ + ++ Date: Tue, 12 Sep 2023 15:53:33 +0200 Subject: [PATCH 09/17] Changed the accessibility item in settings --- build/patches/00Cromite-Branding.patch | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/build/patches/00Cromite-Branding.patch b/build/patches/00Cromite-Branding.patch index b75ce82c..6cf1a5c4 100644 --- a/build/patches/00Cromite-Branding.patch +++ b/build/patches/00Cromite-Branding.patch @@ -39,13 +39,14 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html .../settings/settings_menu/settings_menu.html | 5 ++- .../strings/android_chrome_strings.grd | 2 +- chrome/common/url_constants.cc | 4 +- + .../strings/android/browser_ui_strings.grd | 2 +- .../drawable-hdpi/fre_product_logo.png | Bin 3912 -> 22295 bytes .../drawable-mdpi/fre_product_logo.png | Bin 2490 -> 12171 bytes .../drawable-xhdpi/fre_product_logo.png | Bin 5151 -> 34576 bytes .../drawable-xxhdpi/fre_product_logo.png | Bin 7720 -> 60959 bytes .../drawable-xxxhdpi/fre_product_logo.png | Bin 10740 -> 93273 bytes tools/grit/grit/grd_reader.py | 35 +++++++++++++++++ - 41 files changed, 101 insertions(+), 55 deletions(-) + 42 files changed, 102 insertions(+), 56 deletions(-) diff --git a/build/BUILD.gn b/build/BUILD.gn --- a/build/BUILD.gn @@ -13215,6 +13216,18 @@ diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc const char kContentSettingsExceptionsLearnMoreURL[] = "https://support.google.com/chrome/?p=settings_manage_exceptions"; +diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd +--- a/components/browser_ui/strings/android/browser_ui_strings.grd ++++ b/components/browser_ui/strings/android/browser_ui_strings.grd +@@ -978,7 +978,7 @@ + + + +- Accessibility ++ Accessibility and UI + + + Text scaling diff --git a/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/fre_product_logo.png b/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/fre_product_logo.png index 2353496bafc8f8559a8fcbf6d609302327dc820c..9d123a8918eea5e93f6139534d7dc01a88c4278f 100644 GIT binary patch From 39981ed61001b6f4684ceae90c3f93d613d1b718 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:54:09 +0200 Subject: [PATCH 10/17] Fix crash in android suggestion host --- build/patches/00Fix-chromium-build-bugs.patch | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/build/patches/00Fix-chromium-build-bugs.patch b/build/patches/00Fix-chromium-build-bugs.patch index 1e45a086..31380971 100644 --- a/build/patches/00Fix-chromium-build-bugs.patch +++ b/build/patches/00Fix-chromium-build-bugs.patch @@ -21,10 +21,11 @@ Subject: Fix chromium build bugs .../core/browser/webdata/autofill_table.cc | 12 ++++++------ .../omnibox/browser/omnibox_field_trial.cc | 4 ++-- .../phishing_image_embedder.cc | 14 +++----------- + content/browser/browser_interface_binders.cc | 1 + crypto/BUILD.gn | 1 + net/BUILD.gn | 1 + third_party/libevent/BUILD.gn | 2 ++ - 21 files changed, 38 insertions(+), 51 deletions(-) + 22 files changed, 39 insertions(+), 51 deletions(-) diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_webview_bundle.gni --- a/android_webview/system_webview_bundle.gni @@ -276,7 +277,7 @@ diff --git a/components/autofill/core/browser/ui/suggestion_selection.cc b/compo diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc -@@ -413,12 +413,12 @@ void InsertBuilder(sql::Database* db, +@@ -412,12 +412,12 @@ void InsertBuilder(sql::Database* db, } // Renames the table `from` into `to` and returns true if successful. @@ -336,6 +337,17 @@ diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phish } void PhishingImageEmbedder::CancelPendingImageEmbedding() { +diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc +--- a/content/browser/browser_interface_binders.cc ++++ b/content/browser/browser_interface_binders.cc +@@ -350,6 +350,7 @@ void BindDateTimeChooserForFrame( + void BindTextSuggestionHostForFrame( + RenderFrameHost* host, + mojo::PendingReceiver receiver) { ++ if ((true)) return; + auto* view = static_cast(host->GetView()); + if (!view || !view->text_suggestion_host()) + return; diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn From 9e26c7ccb987334ec7f246a1d4bf562887d73802 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:55:03 +0200 Subject: [PATCH 11/17] modernise the user interface --- .../Add-option-to-force-tablet-UI.patch | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/build/patches/Add-option-to-force-tablet-UI.patch b/build/patches/Add-option-to-force-tablet-UI.patch index 2e8d722d..4bf38584 100644 --- a/build/patches/Add-option-to-force-tablet-UI.patch +++ b/build/patches/Add-option-to-force-tablet-UI.patch @@ -12,11 +12,11 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../toolbar/top/ToolbarControlContainer.java | 5 ++--- components/BUILD.gn | 6 +++--- .../res/xml/accessibility_preferences.xml | 5 +++++ - .../accessibility/AccessibilitySettings.java | 11 +++++++++++ + .../accessibility/AccessibilitySettings.java | 10 ++++++++++ .../AccessibilitySettingsDelegate.java | 2 ++ ui/android/BUILD.gn | 2 ++ .../chromium/ui/base/DeviceFormFactor.java | 5 +++++ - 12 files changed, 58 insertions(+), 7 deletions(-) + 12 files changed, 57 insertions(+), 7 deletions(-) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java @@ -149,7 +149,7 @@ diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibil android:summary="@string/accessibility_tab_switcher_summary" android:title="@string/accessibility_tab_switcher_title" /> -+ @@ -160,15 +160,7 @@ diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibil diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java -@@ -14,6 +14,7 @@ import androidx.preference.PreferenceFragmentCompat; - import org.chromium.base.ContextUtils; - import org.chromium.components.browser_ui.accessibility.AccessibilitySettingsDelegate.BooleanPreferenceDelegate; - import org.chromium.components.browser_ui.accessibility.FontSizePrefs.FontSizePrefsObserver; -+import org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference; - import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; - import org.chromium.components.browser_ui.settings.CustomDividerFragment; - import org.chromium.components.browser_ui.settings.SettingsUtils; -@@ -30,6 +31,8 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -30,6 +30,8 @@ public class AccessibilitySettings extends PreferenceFragmentCompat public static final String PREF_READER_FOR_ACCESSIBILITY = "reader_for_accessibility"; public static final String PREF_CAPTIONS = "captions"; @@ -177,12 +169,12 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c private TextScalePreference mTextScalePref; private PageZoomPreference mPageZoomDefaultZoomPref; private ChromeSwitchPreference mPageZoomAlwaysShowPref; -@@ -109,6 +112,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -109,6 +111,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat getPreferenceScreen().removePreference(readerForAccessibilityPref); } -+ ChromeBaseCheckBoxPreference forceTabletUiPref = -+ (ChromeBaseCheckBoxPreference) findPreference(PREF_FORCE_TABLET_UI); ++ ChromeSwitchPreference forceTabletUiPref = ++ (ChromeSwitchPreference) findPreference(PREF_FORCE_TABLET_UI); + mForceTabletUIDelegate = mDelegate.getForceTabletUIDelegate(); + forceTabletUiPref.setChecked(mForceTabletUIDelegate.isEnabled()); + forceTabletUiPref.setOnPreferenceChangeListener(this); @@ -190,7 +182,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c ChromeSwitchPreference accessibilityTabSwitcherPref = (ChromeSwitchPreference) findPreference( AccessibilityConstants.ACCESSIBILITY_TAB_SWITCHER); -@@ -165,6 +174,8 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -165,6 +173,8 @@ public class AccessibilitySettings extends PreferenceFragmentCompat mFontSizePrefs.setUserFontScaleFactor((Float) newValue); } else if (PREF_FORCE_ENABLE_ZOOM.equals(preference.getKey())) { mFontSizePrefs.setForceEnableZoomFromUser((Boolean) newValue); From 5b80336a7dccfde968540728f7b9adac312a1926 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:55:49 +0200 Subject: [PATCH 12/17] Fix OmniboxSuggestionsDropdown offsets --- .../Move-navigation-bar-to-bottom.patch | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/build/patches/Move-navigation-bar-to-bottom.patch b/build/patches/Move-navigation-bar-to-bottom.patch index b8f7963d..4b472259 100644 --- a/build/patches/Move-navigation-bar-to-bottom.patch +++ b/build/patches/Move-navigation-bar-to-bottom.patch @@ -69,7 +69,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../suggestions/AutocompleteCoordinator.java | 16 +++- .../suggestions/AutocompleteMediator.java | 7 +- .../DropdownItemViewInfoListManager.java | 15 +++- - .../OmniboxSuggestionsDropdown.java | 28 ++++++- + .../OmniboxSuggestionsDropdown.java | 30 +++++-- .../OmniboxSuggestionsDropdownEmbedder.java | 9 +++ .../strings/android_chrome_strings.grd | 6 ++ chrome/browser/ui/android/toolbar/BUILD.gn | 1 + @@ -88,7 +88,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../accessibility/AccessibilitySettings.java | 16 ++++ .../AccessibilitySettingsDelegate.java | 6 ++ .../render_widget_host_view_android.cc | 3 + - 76 files changed, 899 insertions(+), 64 deletions(-) + 76 files changed, 900 insertions(+), 65 deletions(-) diff --git a/cc/base/features.cc b/cc/base/features.cc --- a/cc/base/features.cc @@ -2265,12 +2265,13 @@ diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/brow TimingMetric metric = OmniboxMetrics.recordSuggestionListMeasureTime()) { OmniboxAlignment omniboxAlignment = mEmbedder.getCurrentAlignment(); - maybeUpdateLayoutParams(omniboxAlignment.top); +- boolean useAlignmentSpecifiedHeight = OmniboxFeatures.omniboxConsumesImeInsets(); + int top = omniboxAlignment.top; + if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) { + top = 0; + } + maybeUpdateLayoutParams(top); - boolean useAlignmentSpecifiedHeight = OmniboxFeatures.omniboxConsumesImeInsets(); ++ boolean useAlignmentSpecifiedHeight = false; int availableViewportHeight = useAlignmentSpecifiedHeight ? omniboxAlignment.height - : calculateAvailableViewportHeight() - omniboxAlignment.top; @@ -2663,7 +2664,7 @@ diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibil android:key="captions" android:title="@string/accessibility_captions_title"/> -+ @@ -2671,7 +2672,7 @@ diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibil diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java -@@ -36,6 +36,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -35,6 +35,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat private BooleanPreferenceDelegate mForceTabletUIDelegate; static final String PREF_FORCE_TABLET_UI = "force_tablet_ui"; @@ -2679,7 +2680,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c private TextScalePreference mTextScalePref; private PageZoomPreference mPageZoomDefaultZoomPref; private ChromeSwitchPreference mPageZoomAlwaysShowPref; -@@ -45,6 +46,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -44,6 +45,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat private BooleanPreferenceDelegate mReaderForAccessibilityDelegate; private BooleanPreferenceDelegate mAccessibilityTabSwitcherDelegate; private double mPageZoomLatestDefaultZoomPrefValue; @@ -2687,7 +2688,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c private FontSizePrefs mFontSizePrefs; private FontSizePrefsObserver mFontSizePrefsObserver = new FontSizePrefsObserver() { -@@ -64,6 +66,10 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -63,6 +65,10 @@ public class AccessibilitySettings extends PreferenceFragmentCompat mFontSizePrefs = FontSizePrefs.getInstance(delegate.getBrowserContextHandle()); } @@ -2698,12 +2699,12 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); -@@ -131,6 +137,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -130,6 +136,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat getPreferenceScreen().removePreference(accessibilityTabSwitcherPref); } -+ ChromeBaseCheckBoxPreference mMoveToolbarToBottomPref = -+ (ChromeBaseCheckBoxPreference) findPreference(PREF_MOVE_TOOLBAR_TO_BOTTOM); ++ ChromeSwitchPreference mMoveToolbarToBottomPref = ++ (ChromeSwitchPreference) findPreference(PREF_MOVE_TOOLBAR_TO_BOTTOM); + mMoveTopToolbarToBottomDelegate = mDelegate.getMoveTopToolbarToBottomDelegate(); + mMoveToolbarToBottomPref.setChecked(mMoveTopToolbarToBottomDelegate.isEnabled()); + mMoveToolbarToBottomPref.setOnPreferenceChangeListener(this); @@ -2711,7 +2712,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c Preference captions = findPreference(PREF_CAPTIONS); captions.setOnPreferenceClickListener(preference -> { Intent intent = new Intent(Settings.ACTION_CAPTIONING_SETTINGS); -@@ -190,7 +202,11 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -189,7 +201,11 @@ public class AccessibilitySettings extends PreferenceFragmentCompat mDelegate.getBrowserContextHandle(), (Integer) newValue); } else if (PREF_PAGE_ZOOM_ALWAYS_SHOW.equals(preference.getKey())) { PageZoomUtils.setShouldAlwaysShowZoomMenuItem((Boolean) newValue); From 42771130fe904dd826171f15c30477c0fe64b21b Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:56:34 +0200 Subject: [PATCH 13/17] Changing the setting caption --- build/patches/Add-an-always-incognito-mode.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/patches/Add-an-always-incognito-mode.patch b/build/patches/Add-an-always-incognito-mode.patch index 968c9675..9711dd89 100644 --- a/build/patches/Add-an-always-incognito-mode.patch +++ b/build/patches/Add-an-always-incognito-mode.patch @@ -251,7 +251,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout; -@@ -580,9 +584,14 @@ public class ChromeTabbedActivity extends ChromeActivity + + -+ Incognito mode ++ Always incognito mode + + + Incognito navigation settings From bdf0c6a1955e7178cee1bdf348864094d2d61066 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 12 Sep 2023 15:57:35 +0200 Subject: [PATCH 14/17] #282 #262 Enable ImprovedBookmarks by default --- build/bromite_patches_list.txt | 1 + ...0Enable-ImprovedBookmarks-by-default.patch | 113 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 build/patches/00Enable-ImprovedBookmarks-by-default.patch diff --git a/build/bromite_patches_list.txt b/build/bromite_patches_list.txt index d5159d45..7367e28d 100644 --- a/build/bromite_patches_list.txt +++ b/build/bromite_patches_list.txt @@ -274,6 +274,7 @@ Timezone-customization.patch 00Enable-Android-Dynamic-Performance-Framework.patch 00Remove-GoogleAccountsPrivateApiHost.patch 00Fix-crash-on-customize-profile-ui.patch +00Enable-ImprovedBookmarks-by-default.patch 00Temp-Disable-kAutomaticLazyFrameLoadingToEmbeds.patch 00Temp-disable-predictive-back-gesture.patch diff --git a/build/patches/00Enable-ImprovedBookmarks-by-default.patch b/build/patches/00Enable-ImprovedBookmarks-by-default.patch new file mode 100644 index 00000000..3e068a90 --- /dev/null +++ b/build/patches/00Enable-ImprovedBookmarks-by-default.patch @@ -0,0 +1,113 @@ +From: uazo +Date: Tue, 12 Sep 2023 12:39:23 +0000 +Subject: Enable ImprovedBookmarks by default + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html +--- + chrome/android/java/res/layout/bookmark_search_box_row.xml | 6 +++--- + .../chromium/chrome/browser/bookmarks/BookmarkFeatures.java | 2 +- + .../browser/bookmarks/BookmarkSearchBoxRowViewBinder.java | 2 ++ + .../chromium/chrome/browser/bookmarks/BookmarkUiPrefs.java | 2 +- + .../chromium/chrome/browser/bookmarks/BookmarkUtils.java | 3 ++- + chrome/browser/flags/android/chrome_feature_list.cc | 2 +- + 6 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/chrome/android/java/res/layout/bookmark_search_box_row.xml b/chrome/android/java/res/layout/bookmark_search_box_row.xml +--- a/chrome/android/java/res/layout/bookmark_search_box_row.xml ++++ b/chrome/android/java/res/layout/bookmark_search_box_row.xml +@@ -31,9 +31,9 @@ found in the LICENSE file. + android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + + + + + +- +\ No newline at end of file ++ +diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFeatures.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFeatures.java +--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFeatures.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFeatures.java +@@ -14,7 +14,7 @@ import org.chromium.chrome.browser.flags.MutableFlagWithSafeDefault; + */ + public class BookmarkFeatures { + private static final MutableFlagWithSafeDefault sAndroidImprovedBookmarksFlag = +- new MutableFlagWithSafeDefault(ChromeFeatureList.ANDROID_IMPROVED_BOOKMARKS, false); ++ new MutableFlagWithSafeDefault(ChromeFeatureList.ANDROID_IMPROVED_BOOKMARKS, true); + + /** Returns whether an additional "add bookmark" item should be in the overflow menu. */ + public static boolean isBookmarkMenuItemAsDedicatedRowEnabled() { +diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchBoxRowViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchBoxRowViewBinder.java +--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchBoxRowViewBinder.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchBoxRowViewBinder.java +@@ -5,6 +5,7 @@ + package org.chromium.chrome.browser.bookmarks; + + import android.view.View; ++import android.view.ViewGroup; + + import androidx.annotation.DrawableRes; + import androidx.annotation.StringRes; +@@ -20,6 +21,7 @@ class BookmarkSearchBoxRowViewBinder { + static void bind(PropertyModel model, View view, PropertyKey key) { + BookmarkSearchBoxRow row = (BookmarkSearchBoxRow) view; + ChipView shoppingChip = view.findViewById(R.id.shopping_filter_chip); ++ shoppingChip.setVisibility(ViewGroup.GONE); + if (key == BookmarkSearchBoxRowProperties.QUERY_CALLBACK) { + row.setQueryCallback(model.get(BookmarkSearchBoxRowProperties.QUERY_CALLBACK)); + } else if (key == BookmarkSearchBoxRowProperties.SHOPPING_CHIP_VISIBILITY) { +diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUiPrefs.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUiPrefs.java +--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUiPrefs.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUiPrefs.java +@@ -18,7 +18,7 @@ import java.lang.annotation.RetentionPolicy; + */ + public class BookmarkUiPrefs { + private static final @BookmarkRowDisplayPref int INITIAL_BOOKMARK_ROW_DISPLAY_PREF = +- BookmarkRowDisplayPref.VISUAL; ++ BookmarkRowDisplayPref.COMPACT; + private static final @BookmarkRowSortOrder int INITIAL_BOOKMARK_ROW_SORT_ORDER = + BookmarkRowSortOrder.REVERSE_CHRONOLOGICAL; + +diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.app.bookmarks.BookmarkAddEditFolderActivity; + import org.chromium.chrome.browser.app.bookmarks.BookmarkEditActivity; + import org.chromium.chrome.browser.app.bookmarks.BookmarkFolderPickerActivity; + import org.chromium.chrome.browser.app.bookmarks.BookmarkFolderSelectActivity; ++import org.chromium.chrome.browser.bookmarks.BookmarkFeatures; + import org.chromium.chrome.browser.bookmarks.BookmarkUiPrefs.BookmarkRowDisplayPref; + import org.chromium.chrome.browser.commerce.ShoppingServiceFactory; + import org.chromium.chrome.browser.document.ChromeLauncherActivity; +@@ -405,7 +406,7 @@ public class BookmarkUtils { + RecordUserAction.record("MobileBookmarkManagerReopenBookmarksInSameSession"); + } + +- if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)) { ++ if (BookmarkFeatures.isAndroidImprovedBookmarksEnabled() || DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)) { + showBookmarkManagerOnTablet(context, + activity == null ? null : activity.getComponentName(), url, isIncognito); + } else { +diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc +--- a/chrome/browser/flags/android/chrome_feature_list.cc ++++ b/chrome/browser/flags/android/chrome_feature_list.cc +@@ -495,7 +495,7 @@ BASE_FEATURE(kAndroidSearchEngineChoiceNotification, + + BASE_FEATURE(kAndroidImprovedBookmarks, + "AndroidImprovedBookmarks", +- base::FEATURE_DISABLED_BY_DEFAULT); ++ base::FEATURE_ENABLED_BY_DEFAULT); + + BASE_FEATURE(kAnimatedImageDragShadow, + "AnimatedImageDragShadow", +-- +2.25.1 From 339db134a0d18c29beea7ec94686787a7c3dd464 Mon Sep 17 00:00:00 2001 From: uazo Date: Tue, 12 Sep 2023 14:00:27 +0000 Subject: [PATCH 15/17] AUTOMATED - git apply results --- .../00Add-setting-to-invert-tap-and-long-tap.patch | 8 ++++---- build/patches/00Fix-chromium-build-bugs.patch | 2 +- build/patches/Add-an-always-incognito-mode.patch | 4 ++-- .../Disable-Accessibility-service-by-default.patch | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch b/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch index 329c1ecb..d0b537d6 100644 --- a/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch +++ b/build/patches/00Add-setting-to-invert-tap-and-long-tap.patch @@ -279,7 +279,7 @@ diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibil diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java -@@ -37,6 +37,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -36,6 +36,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat private BooleanPreferenceDelegate mForceTabletUIDelegate; static final String PREF_FORCE_TABLET_UI = "force_tablet_ui"; static final String PREF_MOVE_TOOLBAR_TO_BOTTOM = "move_toolbar_bottom"; @@ -287,7 +287,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c private TextScalePreference mTextScalePref; private PageZoomPreference mPageZoomDefaultZoomPref; private ChromeSwitchPreference mPageZoomAlwaysShowPref; -@@ -47,6 +48,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -46,6 +47,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat private BooleanPreferenceDelegate mAccessibilityTabSwitcherDelegate; private double mPageZoomLatestDefaultZoomPrefValue; private BooleanPreferenceDelegate mMoveTopToolbarToBottomDelegate; @@ -295,7 +295,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c private FontSizePrefs mFontSizePrefs; private FontSizePrefsObserver mFontSizePrefsObserver = new FontSizePrefsObserver() { -@@ -143,6 +145,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -142,6 +144,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat mMoveToolbarToBottomPref.setChecked(mMoveTopToolbarToBottomDelegate.isEnabled()); mMoveToolbarToBottomPref.setOnPreferenceChangeListener(this); @@ -308,7 +308,7 @@ diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/c Preference captions = findPreference(PREF_CAPTIONS); captions.setOnPreferenceClickListener(preference -> { Intent intent = new Intent(Settings.ACTION_CAPTIONING_SETTINGS); -@@ -205,6 +213,9 @@ public class AccessibilitySettings extends PreferenceFragmentCompat +@@ -204,6 +212,9 @@ public class AccessibilitySettings extends PreferenceFragmentCompat } else if (PREF_MOVE_TOOLBAR_TO_BOTTOM.equals(preference.getKey())) { mMoveTopToolbarToBottomDelegate.setEnabled((Boolean) newValue); mDelegate.requestRestart(getActivity()); diff --git a/build/patches/00Fix-chromium-build-bugs.patch b/build/patches/00Fix-chromium-build-bugs.patch index 31380971..7ee078b5 100644 --- a/build/patches/00Fix-chromium-build-bugs.patch +++ b/build/patches/00Fix-chromium-build-bugs.patch @@ -277,7 +277,7 @@ diff --git a/components/autofill/core/browser/ui/suggestion_selection.cc b/compo diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc -@@ -412,12 +412,12 @@ void InsertBuilder(sql::Database* db, +@@ -413,12 +413,12 @@ void InsertBuilder(sql::Database* db, } // Renames the table `from` into `to` and returns true if successful. diff --git a/build/patches/Add-an-always-incognito-mode.patch b/build/patches/Add-an-always-incognito-mode.patch index 9711dd89..370ad359 100644 --- a/build/patches/Add-an-always-incognito-mode.patch +++ b/build/patches/Add-an-always-incognito-mode.patch @@ -251,7 +251,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout; -@@ -579,9 +583,14 @@ public class ChromeTabbedActivity extends ChromeActivity Date: Wed, 13 Sep 2023 09:07:06 +0200 Subject: [PATCH 16/17] bump to 117.0.5938.63 --- build/RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/RELEASE b/build/RELEASE index 0711676e..483f0a18 100644 --- a/build/RELEASE +++ b/build/RELEASE @@ -1 +1 @@ -117.0.5938.48 \ No newline at end of file +117.0.5938.63 \ No newline at end of file From 13d590317929234bd98bee3a4b3ccc92dfb9fc78 Mon Sep 17 00:00:00 2001 From: uazo Date: Wed, 13 Sep 2023 07:11:18 +0000 Subject: [PATCH 17/17] AUTOMATED - git apply results --- build/patches/eyeo-117.0.5938.0-chrome_integration.patch | 4 ++-- .../patches/ungoogled-chromium-no-special-hosts-domains.patch | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/patches/eyeo-117.0.5938.0-chrome_integration.patch b/build/patches/eyeo-117.0.5938.0-chrome_integration.patch index 00cc59b6..03da0bdf 100644 --- a/build/patches/eyeo-117.0.5938.0-chrome_integration.patch +++ b/build/patches/eyeo-117.0.5938.0-chrome_integration.patch @@ -6456,7 +6456,7 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn "../browser/after_startup_task_utils_unittest.cc", "../browser/apps/icon_standardizer_unittest.cc", "../browser/apps/user_type_filter_unittest.cc", -@@ -6396,6 +6419,8 @@ test("unit_tests") { +@@ -6397,6 +6420,8 @@ test("unit_tests") { "//chrome/services/file_util:unit_tests", "//chrome/services/qrcode_generator/public/cpp", "//components/account_id", @@ -6465,7 +6465,7 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn "//components/assist_ranker/proto", "//components/autofill/content/browser:test_support", "//components/background_sync", -@@ -9819,6 +9844,7 @@ if (!is_android) { +@@ -9820,6 +9845,7 @@ if (!is_android) { public_deps = [ "//chrome/browser:test_support_ui", diff --git a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch index 63a1d091..9d7c32df 100644 --- a/build/patches/ungoogled-chromium-no-special-hosts-domains.patch +++ b/build/patches/ungoogled-chromium-no-special-hosts-domains.patch @@ -759,7 +759,7 @@ diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/rende diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn -@@ -6374,7 +6374,6 @@ test("unit_tests") { +@@ -6375,7 +6375,6 @@ test("unit_tests") { "//chrome/browser/favicon", "//chrome/browser/feature_guide/notifications:unit_tests", "//chrome/browser/first_party_sets",

gwPc~}r1EkwlYXQ}rJMSNzBBL}k?z2D`rVV-wuuaI7M-d?84q^ukvn5=x6M9$Z+ +z1W|2#XHFHds5u?!-Jyr~sLH9F>E&ibiTL+A#VW!s=3Knh(0Vtr$=*sZ)BR!)u0vF< +z5r7ZCc=GZwTkmf)%@8`{h033g%(DsOKpNI;# +z1$J!jn@bt~V<9{hZF!2!nr3bCj@iG+?F`_5k=sv5(KC7&|B%~e|01^$K}F)L`QVFE +z9Cr+v|4nXRg(0@3?4XKSH8uRQAm9l%3QYIFNunhEA-5&}gWT5qhuqfvhuk(pkc;^t +zw{8AKZs)CdQDgst4l}RC(e>X~)m1)-M(WGs3Q>$^^`JxZ!z-VUNxZYgh`>GImrYF* +zAt8m-S4-C@cMn7gdJ@P6!B#D1Iyr4UeO-)uAqrA?l8evhBlRCWZ0X|7-`)Ho)T9|> +z$t$BCB}z=aKlMD+!dwbx69!uEhVxNvQ-t>6Du=*|ndp#DpRHyPF_7Bgd9Lg$S!t?e +z39w?^>vudvV)nNRemSj9@P({5d;K9gf{%6g?<0|5$hLUIg4~l_vB&o3ziiZ}v{A9Q +zRcVLx;eZBI@kejWZ-S3sg(j6o3?uiGWd>WoAy|PFO(d0|W%HdhzO!@PkEXG`=TCCT +zNmkl52$y@QB8xrAYKuAL&|CR{|8gY$IKSlq(z>@a7LFSxgc~t7w314HE_Em?jgoj! +z(A7+lmYWGt8pchbxN}*V5?j96!~#VQZb7O(?E{u^eC19nlHuTJjG=^q3wsHU*wlWr +zgRn$kSjSe4k|m9#nRP~xVti5>C(9D`xNgT51{?Yb0bw>=*t=$`wK`(kL6?cGkq4ye +z%K5CWyz{wa+XV_~WKuzkmoh(TF_8Dv?@qpCWdbfdMkl8UU$m;1+)zYPk)_NeH>h?+ +zVVDI1W$ywbbel5-xII}&{*6hauXeR<(=KaGL$TU^U?I|O9H9(rZJ5-{VFDq(Zcaz? +zuhvx~Y&J4qE-Y&(e$OSn>%u|^)$dGT|2y|5i!~2Tk;_i?$zET6jILY37838-Kn|s3VERQoINIr-`0SQ-*Z7jtlf>U +zzjg3p@C~Bbt|O+Qq-;Q61l$lbP(3z4qks+;{gpfoOj*hsXvgDE0msa5Q=zyzCG63U +z>k8T^9a_2mQ$RnyvGPQG0g%qG2Ys$xf +z^Wi0c*wV^}6$xky*IiLUX>En*-dG**z-V{RR(AbzAWL>HrIb!Z +z^HfWj=WaX|;M{={Gzg9kYJUsH-)rr$OGHY>NR5-bcRLfZx&5p>MbDlH_=7;olgecr +z;-n*W*>|0pT=5b&_cp!$W_7r<1Ze{5VVsN;GpC+*fXnr?NKuu6D1d76_O(Y{I@IY_ +zEqo94dbn_AEBf@n*k%SA@jum9_vD8*4!^E2ub#->zp@Dj4`>Y&t4cDF +zu-BuQG#EHA4wWi<9F)D#0V}$sgFniF+%{ +zBCsQ&REz~79tFb1o&QGYFTP=V# +zc|GYxG&5oZ!Z(KC#4Yqzw4Js*(D@#7g00b--a<=>q?ERL(z<~c2ZFI^aZl1ju~UpH +zMZn2SxI7D%1Elkg_kzPluWwgi3s@i*5SoK&@5hyYel~+nMC1TrSWxS@6HK;NPt0)D +z_?mFa@3DltjWLkb9cTiOjrFVs@}`xir_;NYFIWK_?lB`3({S9pc?j?!?AO@PyD=>? +zP^`c=2-jL#{_gys2m9>TA@tpI_PuS40Mnc+xxpDGg1!aJ +z0?PJ0E2a6q&>UsCC^4JV3JNSP_ArqiCdftyJ}S{r0(7M41k^|Vih^X`#QZt5oUe4v +zK@U@jI$M4f1C63HahFA;9xwmrkCJ8%k=>NwE6+M+B`LJO;zY0`b^xGJ?JuWOq~+O5 +zjtK<+zn@tL_aV(Ot6&oH8XAa6uCw$uCxjm54AdKafNC +zPNY(&$>ZRGERRHFt&HY!xFky$YT7F#b@uq_L)_15E;2vkk;+}MrX+VR9|2y=Y%XF* +z-pA&gGp%^mDD#KcKc2(jcb%`j`x>p0aslbgUcp>oIpz;IPwVEd4)}vnP~y|hDofHG +zGb%fndYrO#t=a?s{EazB0CgW_0#foCx(2)of8QF#nQG +zCaa6UwD{8DKf+}wte$}#bV_=*obJ)&)SY*MjX;eLgq%F0G0J7H*+&MOwy-nwegjif +zV4H6o`|#KDaoHQ4ZJP5kLl$1QHj7a-^1mO-G=tKBjh{p4j-nT2iM_O&E}cgHaF +zAE8bOU~CO*U|a|MiEX%VxF*&VmMg?Ch1&%@f~zgcM_8{wk36QhrQvV!JtkHkWc*gP +zQribh$S~gOwB?=h1IGb*u-gNV6rIynb!wlft4Mtg +zcS$9WbxbrIzRCve-~4NEg%Zu02Yx35?Px1zGFho6+_8fSAy;7!NEe(AyV^cjfdeFU6 +zUQ*DyR^T2ZJe7-d+XhG>_H5Qb`Rv?qFzRACs7rsG7|;i{1~z}}cU8{%paYVra{-Eo +z5s5nkP8s=khFdizWBhHd)qb`#(-3KtWs1l!NF!b4e2rhi2!a4MRh$V#9A9E$hgpubI>-rB +z<8qg3?>Slp51ID*MIqF@XA1N*=`Ul-d?d>fe$)%%$}vvnRiSELQe%$ndJyXQR6WLM +z^b51wTMSNImDqGgDjArC}T^tEVJISy3KNrDkFd0jc-YCxK~3U+?sq^}Q@ +zIv(mTJhN$envPPsBV40!C0>m>8?SxUzZW+)O}K(mk0*bnYv$8dn3E3x$Ri5fre7tK +z1D!$cAkrAS3ppMnJg%8snkrYX3)+`x_5l|HB4${%v_&SbISWW4H|(d})VL`v32M4K +zcAo}2^mj_xf-Kb49u|l@fVR4f*<%t2?)-K_ZZN)WEtH}}`&(c0n*b&&c9+mS+Hp6_ +z%CE3~waG%Tqz%Oo_gbJFLp +zRqGu--mb9tLq%k!edVM+fgqyEFF0QuGf7%-W>~5tuRa8PyyT)BO2#)xS(b^mP}C5T5p0r +z?Zq&Pr^VbPz34&<5`(&oiIqmTrV-7F+Qkgvc$ghqT@DcpNbbMfrk}iMcN4TmOL~+_ +z6FuobMUZzh0P|R{w*>v6hRT@A0~lRyd%Qba0ZRZ*N{|Gw2y45#OIm8L(n<(XDdO!- +ztDE9V +zWT_GtoR&5YB8PvdfPy(Y5W4aEtco?NHuEnS+`1NUFA!>63Gu5jrWeneq*k%xg}K8& +zMVE7vx-vELMXYiA*R60dMP1ZJhs@0pwcLS=6R#P@XGcS#eTq=1-b`381c()7G&beR +zGYOU_VbgLZB@S9HCGC7P`Zo+RfnXdMM1Ci+}Xjyjc%;dj?N?F=;L?>P+V +zAE7Igei15!93L@h?a@D9<;+L%WH(zF8*z^Y$mRL2D~&it!fpmIcQ<1WYvwvRJ?$R_ +zd!7j^V%a^g$cRcZ%zhaXsiHx2zEkX&uRp%Op5NnlPSMqve^oJmusE>bwTt&ThohpG +zu3xi#`gKBG3ED@&!D(R|;nG9c?(ozaYE!GEQz6Nh!CI)*!t=Xs29ffk1qT +zY94+?8ea1t{wJNy$78CN7uf%AI=kzCPiIs7f1@lSO +zH#)mvOm0aS=>K;*+wtOu&W8J+bT;R|>1?$BMrT+4o6cVTZ*=z2k`NR?_WzmAX8Lb* +zHn?NL51l=!^?#$YbMl6M0qQ<|ORx6Ya>f!%0`F8^e8C@$jgDvL`r_P>DH1`V2}%j_ +zes*MZ1}T{MG@6%oG7~uy3ij0=nS~Y_@^L9K^;yy$LMxh{#q#9p7rp&qQ%vAnM)FQZ +zWpA&69lqCi-!FJ+`L!63HY#h5yexR9FY|T;w1NpY9x|TMY&8|2l!6uWi%4UElw+gu +zuu_4~6Yx|#5?C`}nG5)F>)9}x3qX}yN#*GljwE%hpJh{*2V{@pA8>n75guJelanTG +zgg5~@SN7Gw_tPhw)WqQ+JD|r0U#{p9rA(KAT&<~TxzL#SIA6V?>5|YD-n%4yX7K4D +zF;whaMN;Ai+=luAw-*?f_|7U2-%VL3m~HlZ&Z_QndtmqsXRe?zF0C(zrEIEyIsfm$ +zZFS(3-TmPtC{=BVaFN{Hsf +zu@m)Iedp7!4iuyB*q%@mP#xia3MgeOPEWJolDnBI`DpQZ)#PYdQ*CB=G6%8^~X_H8DiS{&Br|>gHYDvGp +zvo&iz%Pi8+9qPf3J@tyGR3FeIbqGE??v0wU?jBHA)xm=AjW=}vtT-&od#M|H)h{1% +zN$nAT)^s~>PZyakT>z2wxdG8?tgr(!-A5Duk00$?SwP6-p`^)zd8Y}mmQJAm)gdR~ +z01!yX8&>la(oN~jArE>3j6KH04ka;56$)rRm~oVsQw%RA#B0{~==3@av`z;;c@}`sB-$rnuqfXmvRx3L +zp((VDm4x&$3#Y!dU&W^WF>XjCWp`T9T)<$@9>Ys9l5C|RYw%<$YF>C@=;0=$%*|@H +zeE1Edo->+{Y=m;%E@32p*wvAfYLVC<4}mAhA2EU0!Gv3Hgu30wxx-IkaAg<=@&uOp +z&GX&PBIQa`MEY$Vsu?&E9DIsCwf_n2v!Ah#qrIYAxS-q=+M1>>1rKq +zKii`$Hd<+fw;ZUu_|j{^H)Cc12vt=${b7&S!S>zDqU{;(MC&1uVuhQis~08fFKrDl +z(ilI2$$~v1sxhHE&Qqo%rxS>k!`mmf*cj*OGqY2Cq|@?M6y398-{iv`QOZ+aCrN%T +zphA_u)>VYoRSOdWgCiI-L-UV{@dR@!JD7zwMxsO6C%B}-2UuUvR=hKh)bH2TUIaL>n-4zRD?ZAl_m +z&jl(-7u|Jc&*BJBefFEtjJ58`q$md=`VNmqrawgZt0kkdv1x$P2(nY|i^RpU)~6Dq +zR=4x@w`vV_Bz{$e+n{a?!sp> +zOwi<3@(vTj?`51e@A~K%@y&(Bfi<_yk(`ez(A!Z`lo#UBs6hdyL$4G^5hhH8_|**%L_zsY3z|D(4ZjuWQ&|Ma%O{_SnA+Z#0)`t$zvyK3D{X|DU1w+;Va +z-ge1fLHb6S;k2`&F=z?S+ObWCJ~2YwWIuCWt)UINh6>-@KWpE +zlw{h$_hc;@H2`Pc+u#uWv=|v?&TuetaLQ3*=Z{=QvIe7kXphS)M^uB!Mi6(KOlih4 +z^5ycB+Kyv|r|%;h;C5W;nLK{}%Sj-=P-UO?H;9{_Efb#^V!j%E4RGd9o;EQq*Vt@T +zIhqjupnCF7e&lM}LM#NjKh@OJj6?Sm>lG%77Bq@7o~cZ?8CRmSK9QdX&ECYPJQaVP +zcNN-l;6j$OM{yqXw-;&DF3JOruJz%OPqX_#K$LW$ABN6Frq$Ou&2R}`W^1M-@KNvH +zsEQQ590_nz{uf*K)SOw{uxmTEJGO1xHafO#b&@M~(qYGT(s9SOZQC|GSCTLH{k+dx +zbI$r!#t#@(qsF;#oZHT8e1D)x<${EbQA*II2(nQ3DN1Bvp(9_VA{Qe7Q-A;Ce!Xl> +zSNO14U7Ux{tiJUSJN~i%yqHXtIxB1zhoje!hYz{}%kM +zDeWR2UWk^z81m=EEOn?@RR8?gium_PA?yb(g1w}BKM`{-?BoYkyG%^N%(D~-Hpz*RtPR}zfE9ND+7w}w#Tu=?d~U+M+# +z{(6Fg`}XB+doH;w*w(FuYrl<{StfQwDb`sfo3{m0FcK$Kqils<9UR(x>Y^z4HsgEG +znPt0Pp(2KU%8K%WyQHwu%TKTehk_8)#{n +z+K6iR!2iB@G1LD<8zOBzZX@^^Yn6@DQAoHR5u7T%`c=&h{th=VF_Z_6jk1;&mMXK- +zlFW7_?)=B=2{|u#wGlO?82ehq(_}*&V_fw&{;p-B+!du~=2)c~H)ItB#BsHlUfvFl +zRYn^s-s>IcQp%Wak=YzSE+*+fZg9Dw(wKPnzK +zxEDwNLiV3R;jx8N$H%4X20!RZ|Cn&gkA_F+OWmG-jCV64Y08V}>269UInh>B`-b4D +zi>W4)Yw}QO4^!y7=@ed)d}TBGpC`xqpXa6IMW0ro%KK5 +zcA+I=xuFn^`u;{q@-~c=7C@AC>aKyhUMAhc7 +zJ`e_iZfFa}S4vBZRB_KPHBYIlKX`K6X3+jYOFk`r*(8Z1NFPkv{IL*SE@EOOFlJPk +z3KFE{!h=SJ>NEZD=VRXev&F(`?y?^!4-B(I4)_}X^WDDj*ONHl2VZ2=BFYv7@b&l= +zHUw?n#)FJS1S1nz8m&(iqoa7SWQa|UdS&2csVE^Aq@w(!X9U9`VlEpGQvCV2v(MLN +zJs^@f6(KQ%<+!KT1Cmn8ez8fe#FaT@kKIXdxn6Hz>N(x@mA=S0w3IkF63XiDwGzy7QIJgZ-T{366Ow{=$}r)76%1kfNW5$b2V?9fRBiD=w+M_l;R3 +z&xQ2Lxy%=FN&WJ+Q7^_XA>c0m^|s;c@@dY@zP#;HZam4|58W?sdtPs>#n9uAbvZrr +zXGO1Ut(Kt83AgfyTvJ)9CPrGde2jOD`TUXa!F;*ToU#z+!k@j1NbbUE^=dhsTbnj +zBvlg&J{)-0rp!2$cBo{ZZhhTP3=!;k-F?Z^3>GPJrCN9iuI@p*f4uFg|9IO$-@`j^ +zrn(1nqb^^>B^oih8+D-ir+OV_q+aGH@~0g;g<;)s;}dd|<`+EASkHq5>hSg_TpXGS +zhA4w62Fs35%Vw>0lDA<@$`gT@cg`f6M8AoVJl&v8Z +zeNvSmY^>5@jkK8>=Y`U&xRrYM#?!tvY3}ZiDy0M?_d{Y9#ls(=HMUf*;+BUn{ez;I +zda&MuTsgbnBxwSDS7+ZX3ww8S{M^&LGWZMO*c3!+X(S`TV7s(QMS{3Lkxs#`P6ZEm +zDKI1g49m(!O>WM*3F=99g{Up-@M&JbSWwiiMC&+z$oFgu^SMc1(;>9ww8trZbFzuVm;p&XN;%lzDdws}&a~Y-^BOr|Xv7bujy%O91hcPr +z6on)u(?m3dC&gH`o!$S%lde6DhtKTA4$;Q$A?2K>u&47x*)5VK6fW6AlmU11%O*e2 +zY>-9F`>*;ON$oeISR)B1fU0y}Ux6F5MNJqSuag6`N?`w%=p}om;~fK(Dk*=G8e*Te +z(%I(=X%HJN;MGI2Zd-(OpWwypHTjs>s%wc_&PWHOF^c10(K&eTk|?+P^KSf4TzazN +z?Ia#3H8w3|`uFsm=`M{6$FefpKdN2$4g83)HK|dQdBHW{c5W)H_!RsJ!r>VGwW11> +z3GQ_5MN5Bv?+fQ}ukKy}&IqvEmNQj8j)>f?Oth+d#1rPuB+0`ep(WY#4y5{M|4|`4Wi2pH +z=BPm2yO=U=c@0>~^<5^qhr~xvdFpL3ojv(WAviuT8Uq$niMVOJAoSqXAGz2%0Wz*L +z8+eIls%6pn^;*4f7}pKnSdvNw$O`OZ6>&K2BV}Xrf)W?EDEzLGnkuzLzvF{Ds($5k +zo}v$PX(Nq08G}UH5y@;y9lPX!>OId|6sa(sRlbyWi(o_$?W0==EA&|7+BsRc#iVcD(L5Fsa-Nlrx3k+;j&13ox@9B_>(!#0(}yZ#_D$4a@Wafvi{HVB{J23zJNM~33=jJ>j*ZPhe|`D)STU5_T4cLaFkWyP5jJVpaUbnjRl!FJyH0B*Van{N3izIkRSByY$!;g0Mzl#B6j +zRa?InpI2ABrq_?TB6Z08k +zQ!011pQp1!?OA@1i?&l*pck_lkMc9yw +zPRJxc|F>cFRO!xX=rgco!Zs4VQQpOv$b<2-Kr6-}d4b=x&U0*4Jmt&V7H5G}%laR0 +z+v&^O&MS-U{ExS-gj-NYIW#gsSiPD8LrvO3vH_DYvFRQoJ>Fev8l@(qZST5b#Yb5H +zjv$_j*KdxDxLRw+$K1ap9-@ACpc@ZAqn2H$W~Rb;lc_1gHY0xH0kwmSxG;uaG_R4k +zRCLDhqalcA-7lVD5_O&$m4p2NLkzAmfGB3>A{smUTf>ZpN&8vh+ql6_fCQ|+(3LTt +zluUx%bU=-2q4LvZRy3ZY;AWr6D0bzCc6IcY+}cd*K>rOT&gu*(+^vc!Lmk)RIyn8z +zT5_zrMNy7}ifja7sJD4XVPB+5P(>!_pQJ9po@x&Ej`l=g-p);u@SOBR{!g%KwQ$5p +zG2zm6XM4aI6$@jIv!;s}Mu||eWSAAnK><^b^<=ZI=_*efIj1nlyoI1r1<>nBWCrk? +ziuu_zn!cKVJmhYuM0QACD&R>x6C>3gP=7~02?tdN2pg7#E(bqpnPNFSiQ}}riZz(? +ztLiD2dzkzEBQL}0*G9|%ceI?Rd@JVwO)yQJI-r846o_e)`S@%4Nv2vaMJ8r-q#2-L%4A%YmYE#f!{-Mr5YU8v_B-p=(jVJ6ocCfQi_%9ebM{x5G^_eHB<<08uI|M9kS +zgEL2s-Cpee^|nn1#H&!tf`L$aey;y`+osU6--!Ez&G=n&s$rh-pA@7B*mH68K*zG8 +z&c;WV)JApDr8(T8%QS&(x;u7^rUUjC#n$g6cz^f5T#P_ef`7ejdHH|6?T(S0CO`a? +z0BA=(sSi#bN)ULtkLv=XDt?t#`;l78LH*;IpN)yldd&llXq2E^?~15Kb`GOR(1|imh-{DXuxv2gc+&(!ZgY~Ya?Fe$<$MKakLjs#b__5w*m +zi_R_TNKNOggn68E)|*O^eiSGMeV>)%1%~v&@+e>&M?CISosi}uavA9AdnUa5z9*za +zly~UHJ(VVgPE96pDVwX>jLuz-zOBL2qY!LGUf>dagn&`-DcK@+NeP=EOPvojrw&rc +zXa+YD5tGP>Ad--45NwxStEppaDw7paBKrog>3tz)I20=0$;v+I6m}1iB}ZGG-_nMP +z3rcD|Ivpvx=b$W^IduN@D}QXyq)wVB|M{y(xtd$)99gG=9O8>Mf6Sqd?*nR*n;2LA +z87Xf0BBUq1u=cUT_Pw>gaU22)g+jm-te+p6?%)CY5GD)Vnbx8%mrUMOa`x)>-v5C~ +zty0B`)sp$T6YGdtTC_8-(U(qsC-PWlVGi|QZyV|V$J?&%gsQ21l1{nV@T1>^t|g8) +z^*P9iuHva}n?QQFt-Ad^mRe;?BesvW?v59Ht3P&!j4zK&OBw@!rjP8u*Z^G;QFs$b +zlN=`IQTFG>ut2`i7%;FXb%%~-ANM(7!yC<_GE~m2K}D79ltzcgNW4|&C+;rj!n;HmSZ^el-{&TmNO0%g(HJ5Yg*aK +zigws>d2NA~a=w2Qz9%{yrd94N(3baSVqYCTMFATg +z`KnATk}85{(DY;`!>Q+gz3q%IZ+n91%iAtK`l2{hWtU0*s8r1C24!<)#vT2gHE#RY +z+a_~r3TbQaFaf0&-(Ttrr9-=^cCRv!XV6n(AkYiaGC(PbD=Id!$Z?lwYZpIX(kIeU +zzD5)(5!*#U8x|M-(v5ItLDR2Jt)qr!xsW0_h=tYsmOb(pm=WEVu?<> +zt-mu*^kO*iPV8Z#J0`}B1s{*Qy3wz&;N4}&k99wSC8<@02YMyge+f-lG$Us&v!R06axEj;xY+p4me#xJh-r2Iv7()G|*h$ +zuhQGD;Vy=VSPye3>Q8ZLE1~GIKuVX7f`iCXQPcfyL{HA$_43p%+8t>6fL*ouO*s#D +zbR?`*hhj$-YR)$Saaju#91hl1ii2|MF9~}t$g*&3)YdG`nLdQRIei$E8Ct#QH_#RZ +z0X-C=_$}eM40m +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 +zS=pV*Kr*Z1Cjis~*FUIp3N`YFhBLS +z$P>icuF;es&S~A%7U^Iv=0;VgkhP~OK12bCXxK1EF?`vi +z@G$V928-7rw~6f_vSD=oqUTVFiw@`56n=xn)lY9n6a{jSKYRzsA^}oG^J93WF +z>yKNCjKpMceIz2*`5A|bR}K%{4Y~ay$Lc#ySx$@!asYn{P`z223G#({>7L|A!$DQS +z-_mEZfWY>@`qr5up))+m^3i3`E=dXj#(P)tVJ9u&rTh(8!!S5|tj!nn{E$=a;H9bE +zS-8 +zcc8L8dFL%Jh&>7-GN{>KxGB$QS8E!5yeKdT^TK4uX^fo2wXw +zan$xL`~J&muzu-2( +z9|9-wEc*}f|AN~V!$v^hAY~(oOxyU$_^IO_y>V|mW)cy+P{01IZX(kizN&87d&TXO@aZyk +z!(q`L1Lc_U=B9wUI}Xeg+xq+ZD#xmJ(ohCYuc1gk6Ev3_4j9pKEwwl +zY6gD?>a`Z1et^4A1O6DKHKhZ%cJL#n`7q{?@*WNBrMyQlpYrd#wqE5wXB!#?iH8$e +z@I#L&&;GiU2V>t$(4T9BiekQNnR>u5@en(0>zY`GY`HfeNRU3W`1vAkKi2}>k8t?e +zELI3PX3Ewgk|h{^pL_e|ZH(Nn4;sIm17%2eNXc=pe%O2yIS4ahHQ+YbK%B1wb+*`2 +zU$JUX!>U!d9i|Hbr`TD_z27C0%xyd0;S#pL_4Q#O<2B-(#;3|#Czdlgu!(E +zwk1CPcUnL`k+g`L)eGTwNqw)M!#DK3=hS43yTa@?+74#medFN}?hNCCLd)@?MU323 +zkja(T;x$mls6EPJS9)v(Va1a-&%ZF%{n?(j^4Sqb3Z#~ufz2nd9)`W{4CJ@*{ae30 +z9 +zMx7r(dl<+$xBE>vzE(7J4CHy2{o9fU$+3}>B*SsqFdYqxFA^AJ;!S`JslWDynn2|` +zhCB8<`-NY!qe)n-(KApbaSA;pO^!Y_zLksSB{Eb%Q?_@5u??De(MhAZ0rQ1=F>39{ +zXsEV440N5L?{>Da&l_sm1F=s}(F~qom0b4kPHx^P?15X^j8GFI64&{vUh91oLTbx$ +z2BpIRTd|-6{pzKpoS_xq$x(RMykIE0WnEx)RbdOipv9#43&mx;-P$Tz){%lZ?#Z-w +zH{dgY#`S{*=Y_efLyW(umNU7y*JUsA7s?6w(7kOjvQK2atAqy!Ly8xhTQ*_ +zYoy2`V-RHU?kbg6w*Q`8Hn3fGu#g{)60Y*SyPKF%3fz1CzUqb9`R}VN0g-N32?5d# +zAJ&5~rWLq0l1SuUW5`!073-YbYk3AZZXTp{JKb*KT=v4jc*GjS^F3eiczB1&gMa%< +z+^<RuX^IL?lxuH&KS&|kc`b_&{FgKtI$RvU6q8$z$@MGIwNuioP +zQ4g4ZD-sWNKu_I#EEGrqn`Bo0Y<~W;1Nor=d1_?M(?cM~gRa~9%Dg7JJ3{tJ<6~?4 +zgK}%e{+;MrVH}2VAt?sL|Ly7W^CR&A%Jz@Ox0~)4)2m|NG7pZWP_g~jJMUsi(8KQr +z#Vc)%sq&7U`2HIV4f$@7)7vy8Q$$RmlsNt2j_^2$WKAim(Mf_QLEAsOBowJwfJeQ` +ztPOFzu%?&BuR-WUqkjDruB}cfq3`b#Q*);p56__``aTobQ2>`GoQqpKY>PF@E`E>iwlu)iy>Jg0YIP1EruZkI!U +ziQBGtaohKXgb-(;x!e}i0%M^&5iJVQg +zqTH8DVN<37XiNu&7cofH27(%g4q>(}2&1LOtQCv=0sDonhTAqoRHJSPcEu +z;m{8E!>(N44wvexJI;;pWqv+tx@=6janduFk4pe%(zXInpuS`mzppvi;|*2cjG7Kj +z7;%1RK?LN^YS8rO45V#;irUu-1Ih@dht_MM$m))MVK3ZeO-aOHkm&#-F}H>p}T+q2meRNUG{IsUX>T&$~3$z1mR2<7W5#jsMA*Y;j +z`DvM=H4VJ=U77$@rOIF}G&D4>jWWj%xE2w7mqp^xhLEyw5!R0zcwd8dhY7DEu#3%5 +z31LLkb?_h)Z#jD9af@v|wrGBt#FN#KXmTy(3aBfpTvi?d#jzS5bz+s8*NRtbSkB-F +zL}rjoh2NUy0Z<=)B))N6aEvHl&Spn^3~$~K^F>1^$)@mo1!=1)F^BZIqqWB`a9jF+ +z!0ljULq_7@4Uw@gaC?I3Kj8Mjzu%&}G-&*2s*q=w#o +zL>qFvlRllHugzmR%s`04IO{l>ldu|3s|!t}F!K|fRT8rlY;s2&GcAJt18fqcg~=wU +z7;tVpWd*l+DK7CqUFe|ewixBmX;QFeUroP)cCU)so?gxmA@6|XWMF~BEz`{!+NwW= +z@k$*AH$g!AD}u$ToFX_%drN`#?4`2}tlbJXUgey_Ik;iA8^}j;9qdNY&>3__Y2(4ZgeXnW5C1*Gb_{XV5|1UYKo-ihF_bq`o+9hRq_ +zAXbE%O+$_-mKb^Iu)_pbcUH6d+_G5=BSr~+xDG_(q~S>-;sry<&-Zz~D^@uFonkkr +zK7i_+!2UbtPpm)?xbEq{D?mj0{iV9vs_DzM796Dd!&w+-Ng*;$EXZ5^k-ux|S5z^Y +zbD5L{dtS)LNlNk^k|VE%;}mkx9)3EgSR~=31Xa_Z{1WO<9We^FJVeH0ucXH{l89h; +z2#2VuG+=JRuN!D`X3wcsa3$Hbv(8bv#dz$c@Fcn#(L3gwI_u|YO{t5ru(FI>mbe%F +zP8;Z!c!P$pv1xNovwfTP@XAr7WFdLyhk?}%w{+L_?yMUQCrsMvnx<1R8WwVZDc^?$ +z>nrczrTxy@Xmo!WO{%S-DY@mU+EE~=KEc^o6&=EoO)XwLgU;LSooL!v%7}YWD_BaZ +zp@}Df5&W{YnGO@^ccEVuAP!QFtcIC|MeIX}gi}P#OGjlPl2JhqIyQzGo2MPz)y$&Y +zu=zP!fAjhNxih^I@fnAO-z%XIovV#+Af^C5?T$9@!2=-|N%r{vRBfN(u|5hBOkdSm1osbf2eq}D{dC@#CTjnMn +z>-}BHM0n7j7GwROmEQh3PO)$()(By3%-G%;VUIBNg}ddK{fD9qEts=&tg#PFZQa%FL=uS9IW*uaY$ +zFhl;f{<_BQT5qv~)d366Y;l7(iU?Lj8a_re&abB>!{*>{YYmlpNp=lj2i4{2h)VEb +zod!=Mc;-oM=RUn2_($4Srf6Fr##9IiY73xJS~XTj&{@|0mQt~QeVG5yuNj;CC2h~e +zf=9tMKb85lh%H+s(}wfF2n`Kd`Eo$9zfK!e)(M(l$&XB`l4{K`tbTtO?>EgV(DUu-D6y8;XigX-DUHrB{=vgl?GZD)Xu&wtn2eWy^hoF^XAeu +zg>%RVt$PFNj-t18n;AJ92$MWxU@Tl_M>}bM%&H%gGxz$IiBMt)X?HCG1<@?708UaW +z@p?r5I!J*bIHD~mZK$*Dsn1+`E3v2S?Sdf~h%;UU3w-rzGTr%1gQfzWS!^frF5$UA +zZp!fNOq2)$_VBkyynqnS$0Jeq*If$~?g`*MlRJ0hLjsI7*Qo0y`obTFr^(g600sV0 +zk)ShGU)p8gTIZcJ2r6y!N +zP7+SL8%!@ct +z`e31jcM(*@3sbAq$cDOYU7vVb!-REIX}^*n(oF=)Q1gD*6I*^*ql2x=|*vW;fxXCM_ITDv%{tyXxvB7#^mSCC6qmIGRy4s5f#EHh4bIewmG_BZ(H@+a* +zO04|+lD3nr%lT{LID@{VZD6;i1Pt{5NZY4h()Kt`kCioFPiuNUK +zyEzAm_cW7FLQzoV%6>`P=WDDMUB?T@aIjOP*5Awjk+w0+pB2;#h9<4V6}-efh4y6! +z36D%-(TsdQfb{IOD$ZF0NrAE356pP4j&5_&N7Q4t#EJzF7-4XF`@PaTnAOR)-}`G& +zaNUD+bwL1nb7IM9$2-e;{Q{lIVpvvYh$C*6_Yn)pd3Cwj9NKpAo~l>ULZB2Yl)8D` +zlOXaq17;^)?2g)wR#J=Uh*S4qul8?sIdkic*kOO<7UG;Nw>_0jII^GW;OMy8#oC1F +zndRL_6~Lc3B5bqfYn(+hyMYD=WV9vA!KXEM=L@@yy +z#6$&4K>rU)D^Uk<^a|ZASHrz}cDRzd))Zv^+WMFDju&tFC_BTsJV0%_V(~`CFFDOi +z_tkYvevt0aK8j!o0i1)eOi_p0@|8`^7CEoCw8?e4;t*#SOZQMI6dr^YvnAiAJ +z0#=5&F_clLeKE>2etwD)GRUbFILsA}8)E$>WEB@4w*KACOs(sBT*A|6|Ath007l`- +z7c1;h6h6*bRDlYUYfzg&(1qXQ1M+Evmy}8l8>v~>TStYtiFUtsWGZslD9Tg9;To&F +zmJ2p(Q5w#UIu`kL(7@SYX%StqKQc=3a%M?HYnHas3~js`&{{Gj76?GfC5Ql$Wm8$B +zBF%8Let?4UrUYFck-RQtM!&U_^^(tnu{G#tcFBm!Bq5m=`l?5hFr!|@PXMK9@NCAQ +z?oG8CA4x>o;Jgo2NgGc_qR!1Px<8&d-MA`tgXukGw9T~bG0c?)DZH61h`#NCN#fBCe4nvb$IVRhie#=>ze$qUR4p +z_zeqq!3_R=bPrBAIyFPvyc&q=#QI=0`POySNJE`Do6z~!+j>xsNnRAK6f2qC;86uz +z_RPX)nD|)Z5!73m$XB%LYZd(~VtPA6v#T$p0FMd-oNK?qZVP-3iyt4I^1}OyMaIJB +zj3vUQ-1lifstH%cL;gcvAmQ)0_HU)-@xm@zOWE-qMS4lm_s*XTw^gX0C!7~LEu>X@ +zI`Nc*Z?(Y=3CU+6hb42UOyF628BFR0t(l*9bX4to4UmRHIyiG@6lFALuA33TV+(0tQcd?%$K)$&Y&EE +z-8fSc)|ThcR_HU-Vj2PIOC-DDQQ}wXlU=*zR@ur+mn9*T69R5kn;@825IN5@x?xHi_OWe7 +zfyFwUK%uKYx<=xH5cNsc2ERCEPAe>UE{g{?)Tj%cYWQPyB+=iTQR>sU{lUs<3HDf$ +zB`Q429YZ}H=!^|E%@J3lIO)VB3vRVY%T;5f!4Q@71Xk7oQPox%gW-BHu{k*Y;@EIR +z51w92e(k)Z{%KCWwSL}pK9}5QkC$ZoVSm2`sEbhqMS^2N4$r0sY8d@ +zU2`%0l%(~$auV)5!#|(OQ1C<*2MdWZ?wTXr5c_3<{pWoEs-I!VKBhuxDLZfPk{737 +z-Od}H6AdpjbHt3To;VI~R8v;Vl|thWI?R0&;sOJ)BT|ckxLF$`YwIPmL2V&fG~m +zVjyyINLD+);Uf&s^flN1Z~)$aWlVcw8tbHv=*D%zpCexAI%OM6&l&T><${2;*X0B= +z40+?wJ;>F@il(`R^nbt%+v90Zf#enXV;cXut>lC@JeEy}%IRP;g0UNY9-E)dtT&?A +zm*q2dm?i*tkgf$wgLOgvi85! +zwp*)n$nOR?rs(K@_)0@`5quW16}Mm^mQ +zzuM$!9S(VC;F`u2{W79gQ9bU6v;U>G1vyVXM}H)*f2r-@|4`eEx<4ZmN?uH3l%<(x +zCnOI|Mk|{PzDJM%az(ohO*{Z6!g5^^qp1b5_2hZL1E(>#oF5h%3N$uNaE^uZ1vDwc +zsM&7$qThDt4K9EZTU14Z2__PWkqIsq28_o^>Fu3HWqJvID0-57^nLn7AMg#Wf}{%L +zHUw8ARw+@f`o7nM3mLXroHUr6Dgx9n7VsPkgtMA7EeIxkp{lSVa9LUn$b}s{S8?SE +zfQ&^Vh^t_1<8l+Ly(`y&3zIue(bfU8<4Ts7d%d>;pc=;cFah(>nHPXXPm45}7`QZ$ +z1m6D2&dX&lNgdzk-J7Z`i6x0&_N<3%QJ4lC?LfD~-d%-n2*cp!)f +zxFSVji<|g!aWR1{35E49XinS`Kc(4u8(eLaX(yOpI%9k2AK_FQc8{7@a1szP +z<_%96`e=3v3?)cZ7|Z8ZN{WDKUP*rNSQw4nPW*wJ#X(J3nAS1;T$k4+Xi4O*Q2Ke5 +z_PYTL+lfnhE;2vXw)S4uKi0OX!qNYBgf$p +zV~;_~vy@enE~(#x3;gCZ1M*o@)$f*Vh_p`omRS8xbj3DT@o`(YO8z9U3UXc;Yx_hv +zbn+6UEOZFGNuD#yu*hkp(9NyuAVdYO9Az>)QWjfiA@=&Y4h7;Z`c>*vu2Y1wA +z5rU0CYl}gML4ocXzDfsBccUxnRLx2Um7ElMWZc4y#()f#={mN=3<4J_Hgr0DSZ%l^ +zI6z}w?!N=OYMN#n0l84nRGrhV%(;H7ZLoi=?FhuAA8UIm^}ns{FzZ;iiYaVV+wHNFnZ=1;T&R)p)DTxPL;bL?T2`D}&-|~o9f>ax@MCRnpqdOZFR+ed +z5AF^jPrd~PG&n1XvL4sBF^{DRz@d&H;dHhf2DyXw<8Ppxsg(+jGO7Wha_`TS%y9}y +z1DrLN)K?3`ZMhLhF;&9r7LG3`LjWmK_iKFB1TI$d^{p!Nd_~lx^FyK0O +z@4OihcZD0ZpyK%|sTC-Zo#bZuI=~g)jyp`Va_b>4=w`(LP +z&N2)g^owiob!+qS@CKUksrYdbw6Kt7r%Im1LI#Db{=CV;E3*#`x4wu*Gj`}P+4X#u +zPrYMX;W-u(H38^;+N8z+kDaC&B}~@rR^P(|>>mi5LbLi;z{a<;frNaEg69dcp_Wwu +z?1BM+;|SJC?;0$E0zyx8y+CuE_3b|nY%qYg3{L=YYE;6ew(v!!4Zv9g|5)28m46Tv +z|I6C8|JT|!drl7iKh`#8wbMV=_F%fv>N{WdQ8zdokRit=jH1K8)^<2Flzm?C-RM8o +zwvhOLtZn-LZEfSg^dfATU!gqwSldtkZEc%L{>R$h5E3=`v9|Y+>Yp%+Tid}gaJI#K +z>@k4gDF*hh53cqlR`FZB_5U(Th^bv(sa|f64?K)NAAk8unNl+<2r^vu_k%Be!0?il} +zXjq^GwcGc1R2~M){G|tvt!vzjckrqD3o_is+y+3_Rp)XAFZMS@0rVj;5^-vM+xA6eZnu@o`tm@TlvZo3+zUdvQ-*m1kR4^e_o}-n@zp1C(D-`1l;@izJ86$~I*57H6F+v}XO)&X +zCe!MiDY{DOQn|K0T{c?^5LJTen-U@apNuSlAliX7C8p4ROzHUeCYVTr4t@5hxZ#h} +zQl>$iw1j!>&F9%b8yC3>0+otm^vGz6_7T$x$G*QKhGOPmW|d5*n2UnT2YrJo8uq=7 +z%c_ox+FTd|77BY4a`^@B$osAFPgo$X`mAo)A;?Ecn#ko1Is-v-00@H&NF!jz1z=8j +zS*g}-va#hIixsp@6c_hxfT1B^-7mr7`reDz_07n$QUr&{XP5A`Bzk;_)YnjY;BR-( +z(sH%e8sMu+byfVuA@{)bZFBmrU6Z*IoS}vJfaXIMhi+g5bhNI;x*B` +zke>9pXXkf76{ua5xIP7Cz-W4&bwU`Z5 +zbD+L~A~v-mOi9%)`@gMixs(kPZVn?^YfZ3`Ah63*Op4SqcUXnGyF2h(fl^(DOjDFJ +z?43KwpkuJV?Z)vB%}+Ysv78A@)n`6JDp89;k)r29b>hgqRS}o%(gGV6!4 +zuu?E!u&gi;{lN^Kve6A7%xmg|vjZgvmaCGvv;CC7e9RJJO +zzQ|bTY+^nti2kl^gH@CltIru +z5o!}=H$pKxR@`mUn!!9*>IK+TdAYE~C#-sZc~5PYB&D;?73=N@TxLV~?c@D;dM|)( +z2iwB1rnKy;=NT2j=Q}4TXBV0ynFb@i@@Vuc#3x#8CDAJ9#&d5!*ed}?-iRT#_ZQ>xQF?HS@#1xzn@8~U>6RODRx@r2=hS{TwC +zbwlQ{$YGgVr5O$LB+Z9ixSS6-X&Y(R9V;HFh6@niQUPqKcbCNb-_}}#O;{lPl8`o +zw+ez2?(4kPr&UN-d_KQtjprdwE&B7xV*~tYCk9sp3uL&3*s;e_!|Dwo#PD=Z?Pn+V +zKX57H9*g&!B4$m7YU6}`tnn<*Fyj6!M6>7aDB){!i$4!GxPdw5#`(cJBOGDCTIE9n +z04X=1onbfm_FH`K_l3)gMgQ;IM){(F|f5sUKaKH?BS7VN=ZdA!zThAfB2pBAX? +zu+N7zxfH6PyVaO1hTxkid_q31DUiCUz%n5&eg@7lT;xqyCbOAf_GqQNy+TGcH>?>L +zSGPyj+?el)0s3GdGG$5A+4=zIVJxeOci<|Z1LfXh +zB}aE|#ymR_k`g_%=NL-cldE`5oR`(GyTa6?*k(h`$7O3iwRiY()d#RMyRuXLZ;VPz +zl?hDSr^PI)xyl5K#NNDNBg`5-)Q&BY6y$oL3>T5q5QN;;%!A6HF=oFyDS0*DGTe(kl+$Bds)BlRS{ +z1pW(p5dqoo;T4g>_p{fGIBI4B8wcfAn>}B^vZYOB-~M#(UntiZ_PrpHrLCzk>e6V7 +zlRX#XZwy~nlA^FQ#&q&TnSAS{*fV=bAkOsDkO*i56bs9xHYxt>A@t;(@h1NL>R|Gi +zg!)Ak0IV2V8<|!YlHw!VAL6b{rs_L$pBy(bY%q>s%ooB={B;sh5wj}N7>wc9KKG>Y +z5Jj4yw~H!}H}$jes=y3k3x>)zD893?81Ket$s_#5n;gLWeqSHj50n{7DDy2BH3$Ib +zFN0EK88r#`jL#@U>TMQ{+$I}B?B;n$6qb9UC+rp0=_;_2mRVZQUXSFoz}6kiM4Z*j +zh6|VsEz{IhwlZ~$v=hDz`E_ge934GW)aid49q(V`X=lBr%9Tf +zx4Xd_&}x2FVuJR9-SNCJ6i8EyB0IIND80-veRqWwnp~ma<+jpN%Ia1y_=E(9p;8p%6dS2gYp41V^q!>#)C1Pk#o<4K4 +zC@pBS88!@EDv<3m^AOF<9^fHn9lWF*ePLdib;`~~LWjvKqs!p)WJDGQY}7^tgqr0!&n~BNRE9O +z?3wheZvaJybJsknoLz(}hbX<`l1TYi+Urtj(EW04(yh``N6{LgT4VH=B*K8-It(|e +z%Ua^)>^wREHqK){JZ&C6kAA7<)k&L>Hu|01Ps9m}J>mhc!1|c8{A$ +zGnf;kWsLitjuqdA4>O#cLBU^u%gk_-#tGuyQzZ5FS6>y`B3Wh``zheA5w9HBTv#J- +ze82OUxT`+*#)AAntV`&9rX-B6(Ka-5JLygscOkP?M%z~Ti1{KKMP{ao+zXV(r)`(Z0sj&n&dMPFZO$slXF5V4v{I*xubE-D6^JH2{%ut3 +zUAC_9ux?V|Fg8v`b{MEDE}+%QaG{jV*-lDnP(awl+cr|0_*(J +zK16Pm#k^5^+@eDdH4^zZEbztYms2-vHBIy)-lH#LEkIOIZ70>J_8QeC+*@xKAiZ!7 +z3+|fhLsEbdpx@`jI{>$xISa%12-;2TfVOKNBoAA8cl^axep)z7e3@w|v@#LNW6Kfe +zu$kJnu&JV~b)>=5$Q%5iKbxg#0cj+6GZQ#zmSxm}JQA|M6obioC5#Q`&(4}*9Z=qR +z1Ubz|o3(Mqs2~dm=ZH97!TxhJUjizy&WM#;YB_*U4r!0oymllfZ>?CR_abjt-S>Ce +zdXLNS-u>~kJa?l&-mbP@6(2}PHM_>{eZ2fRx@uoEe_YjUY__mjvXb=f^v=a7+{}Yj +zR14Tg6ytcb6T +z6?TUxR4>asz>np95g~GWzyPCVA>Lc=1mqOgL=8v?K36NHIq{H*t}*w892yAmBHN!b +z^+k_t;Lt&fh-zel#*3brsPud^Bddd7M(|%3JUbt36;EitJRDFRrr=O*Y`H>>KW{uw +z<58qa44eaHXEb8Pfx0&*kdJ{eoxCT4(4G|1ak=F`1%_zFxDV#y&J-*liQieM_Tz7F +z8kpITRfrHmEwC!6lE@{S#i!FJ8L#fKO9H$?1|3bUjeNPxlqWPK6NRzSpAlafHS5Th +z74cMWb|la?HB{DYVe{?U)mNIgnA@|mX0JHO@GbVx<|lZJm#FMJ3VtJDE&CI%@;Y&U +z6Qt>PyCZPr_1G4rFdgvKhLOB74~G-ztb%;}@yrvL>ZAqSm;S?}HK3q|M%CP(AJmzn +zjRAUv61lZgN4zB5xjacBm3c}4A+vYGhR)t!uJyEBPQbrx|3cCgxFa$-c$GbXgPKY6 +zW$?tuw3$v)|0k0s!zA5aKLYxth#JH_pF6#E?Hf&5X`41IhehK!%Q=Ok3~$2>ex%7W +z7JIena1e;Y@c@kzN-chi>yyHTh?4}&v3SQ(7S@z<#-%1v>N#ZhFYW6dR?zd`P&tUy +zV9ThB@szmr-qIKvR!r8<_U3?9N^f@KFVS9N5Ju=MPB|L@QA=>746GPb}A +zB)s(y6~K%F{kaIjuDqJRv0408=UkSt$@%OS;*eF%=eU)zV^LS&6)*mBzId?E1t4`2 +z*R8hT`^1`Nq1UA&Y6A$wQP5ilvd!4mVSkxPdfta&<+&kg0y +zeW)S9YL044$CPL)=N5qYrh$doNN +z9H(!b+pVdno3+J2iSv*dOlBhK*v65_<4S^;Q2#EMDeRi7-CJPWpb*jKrDJM-YIZjY*%F{fhq=wAE_X3{JF4@ +zG}C@ULspYm+BYt0bjHk%)tKspxmm6DklsYgn +zT_ylT|Aoh_bFvQ5tJMOE-=zLsg|1iOLKV_dVW+2`{_$$-MsaOxz^+( +z7e-Ws#id)7rw&&Oj6h@1GOkT&TiSg38KKcj8@gcp)z(s@NG@P=BAG-LB~+c_`u=Vy +z@FdVEzx1f(8Xha_RZwy9$hZv? +zZU@(27MT4HDPg_XN9QMt9k9jhB;KDYmRC0G?S4kF>8l1~>nr@R`_1ay^y7Y!03x6P +zaTvjG5W1!v&6#%{_l9Z@l%4SVzqSE6u#j +z<2Ou}u@%7H9k~O3amQ9x$=4uhnMX=#n8Q0$O{FNde5Z&UzObY+U8U++XF$PDd|TEa +z(WJm*b0H;p&0UdNfZCMDT@A2Ou%(9=`*TZ(U!}<~GhhlUS;Svqw+-IgWp@{(A{d8` +z<=}k7ETO|wXf--zn63JMU+8d2YhqwFv>^shnVrNogV8JUz5-ExFNxAFSn3A3-$%s2 +zfcN`5xXtwmq7^0FELG4Li7E^|EVU{2naUuIB3}s2PTMi!(m*CGTWxMf#cU8zEE>>v +zFx%gj7;^I|D%lL$Ri^aTxZP;YA%3wqUEFK2D+pzSIUkUpvK;2LO|JGkUm+RAE#0?LS$_Mx4j9|4%YFZsiI +z0A_G=fU=rQ62Va8SuHA=vo+2$^TYT)eKphhOjIG4XvcSZgQtFSN&v}EuMHx9!j*s1X4zC +zq2U7imYoXmBPS~TD}hp?Pnr)e#&V`h_h8@(c(eg@F`J4w=1LtYouhUL$J4cl4B^E< +zUxjn#c^VE2@j1SzE)W->X~gP?IJqQ9r8N|U(W~Y8fizj`g33EJ%?iAeN14%40fi9o +zCMrR(OTQfjy2ABip!B-36E55oCfvjLG<**^A=au{$B@#{1u6|;JzO^OoZp9!ue(1S +zFN{n{mA&u9{Gmdn49HZ9U+Sw--?6Evv?`RD!5QU)_Rov{K)&pp17PbU!H7f3lgtPHmH<{cE;%Ilmu;u&nXmZ}hu%#or|y{V|J8#>;!>fF&%E6S)ddvtMw<5w3NW4(Jf-TJ&4{a1p#%q +zXI&WyxA4>OwItF|y*bK$#nIyQ4*8ZAjEpS +zDevFfBjhENft^W}pp0WFmfuA$Qyutk0twupH)&ITrC^XM>KS< +zE6+TS{l-)Y6)|zE+=X}NdV?x@E7ax_G!N00E2XpXOld-5p7Pcpo&u!{oLeB}z +zp&tJs0f;ub86*)rm7}mcF^p60$ePZCj{}KAg$}b6LU}}4v=>V;cn^YF9~E5N{J;eh +zMokU218nDPb>T)|KWX0d0_*x3fiQcZv}PsT!0cBAsp;ud+l7a50{3x8bGNC5>jxC% +zH{`Wm27|ZgIgBG1nt99-S+s>IYhWoZLnQ%a)&zyJwgRJJ4Q+F|eOfS>i60cc;LnY_ +z--SPb1jVMx>W1H>%HZfv-1zN;Q3_zdVY_whTx@gj38`fMx@r+t*GKh64Lxq%J(^UJ +z`L6&2P5)mZR(I>3G;qkw|ESSn!i~Dj_(>=lOONW=KJ~XoB5w4=5P1PpLl%?`*LL?Vom+Sy!V?_`mB_IDO)a2^>eL~xWCCOIXK2eR11BumV*z!J|^wAL|q(eJ+t +z38}0MqbDwQGi)LNhy!u^Vh~O@bXLO$KD@Y!Ig$$(*&f;{W(z# +z*BIia%EBOPX~RU2J{>2gJB&cg8N`8rf|G|Ni4ntJqtNGeS&8QWac;w19V+qtwZDhy +zM#`;h@TO#89F8VL_Xd==421EL2j{o +zhHA6zMdb%>Xjlvu`?NRUO&X=9RfrQVwDk6y)FPkCi;Akd@PwV4^+BT5a>p4;r*3Je +ze@@!QQHLPqEPL8e{@ep6mXpf|SAs-G8x|OXjRmY<7AE`-SRh1Gh*11fGLdltX*-%5 +zgc>RsmK{%jgw=k$ighyIbOz2Peeni}J{OU(#<|QV%?GcJl@nuii-rIS%AD8Kwfk(t +zp;WzJ*`>0jdn!3(rs8sm2bDP1aub{_(=zH%aWtNnw71#4EhLU~Y_cjX%>f{g#DxN* +zJGHGwnAGAyvL&5HEKL4+C&`M0S!`kfD}?LBuIGqd?V2^3)s=u1kc~%Ti23+6(tg@t +z+j&9oKE0PUZ{lxhUzRnmN{?uOvXWbm=OBMQ=+qHY=!U6k#*+N%4E{3jCOph(xY~pS +z@xGyuL@>Yth}cuZ<9-bYkNZ03UGpd-pt?GfKRT$DN#vM~a42g6%M7OVd>Eht_Ca$F +zd0pdQsSVERHY82o!o(!HQB}h>RdY^*#Lt5Ox15-Ijl6<<@8-G+n7G9Az1(=rcq3_2 +z?q9en)sd@?MeN4x_x$xf>%Jhv-R>J;mUr0YxvnF5c4gf2<-e2g6;0La7kQ_&5~M)N_;bxuj_Gh +z2yQ=&)5(NK3nF~MXEkAwDW5OnBel}cu!8%o-bZ?%+uJn;_bIGOBHn-MHuNzP7Je@H +zk`bf}C!FC0kIN$0cnhtmY;GUCrJ%Z(Lo>zu7(_44vtWUEJ0FN(pe9K2TJKQIiFy0Y&9X1KfX^!E}T3#Xq?U$c>VqIRnM=nk7QDS +z2k}l)JZ)7b@dPx)M~bidjT|*~!Zq|o61PjQ}VY8KuEo%Mgt})oopfK3V2;gY@16P6KMdt=S +z0Y{_53_t1?_f&?L1)BSKd&c$jVcF$6Ym7im5#8^dtTrn!T-5<_aO%jooh(92B#pAO +zrsbWQb+qgJD67{DIO3uj8u7m;6JV0Ai3LF@{nX$IcWuLO`4m5x<3Hd%Wq}Emt## +zo@ZUa#UndVj8pc-{YPxsR~=Cgd>apRm${1(nSE8eWSFW!b>x4&m|WtB^gHOk&f<2J +zFUpX2kS^3t$q<5|m4T2mW-76S2f03)%I83zOdf7UM(|r(aycv6K1Gy=GKV~5@Ol)& +z7TCU}rg$b9aO^wO?@BDHuS3$qyI +z<;TIl?M~pN?0!V^`#jpS*Y2jR(*s*mUL`ORX3RgRq!>LPp(=>WXFTlRiT14P9h7** +zDIJzP*V@VpIn504Sf#qGvJ(9aaTm=;M;{Jwq +zOs~%+6-RMCCx(hoPXZEpA<3zZ24S$C-!l<4x3i1&GRC{>Yw=`=%J9l4b(TwB)7b%= +zf8n#fA^g5mVVO{vRa=lTSU?~FL4Em*TK|4_X{HPQ-r$zY-DPzd$={@gkx3U6bjXM| +zfnEf#5bZMk^T5iAD$x@Di`W3tPS~-84Vt3&IepV7e!_7$Qo6R{6aYT&7S!%9?(B43 +zDaItn7+?+`k{et`O!f2N2u_5jDJ|PEjXW}iaIVXoJ@M4NlstQuwe4GH_uz41u8J=Z +zSiLsPWfAcijzVfCW)EfvB`u93``X4En5rA7l}{g;cg-eGe=*?Ko-OqBgx7&9nlT}1 +z)`w*~5hKs9B_X(?{EQ_IshD2|pDs5q40{pa +z1IO4dTAW5_0;o4J-luZn`zgglIvrgh87(f;V|#s*TtIlO+!^LFGF?;b!)va!BKVP!T0ATmn(fQW1QPiPyxWh9MB|)Wii5kNGszKBIZ(a%lB{w$Rid_#_$PBN`K! +zIErBu@4`w_S86U_EpS2vC|Z~?;_^;_NPr5LhVy7XiS22FvqON91rQ%he0(M&>aV5yc-=5mu2=eIKOWcJCZ9SuV)Ffhc +zD5EKXeU2(MLlKTx8>DTSV4H(=K?sT!ZQODmePW4yUKRpG_Dfzv!$Is~_%G({o>p2a +z`Fv@#3X%3Uf~KerH?LUKw)V6Fh3PnU`A0~yQk}4i>hYDm3~0TBR2C}tvV4kFVC`Y( +zJy;HSq4;NVo9?2u)dZ3aHbj#3J+mGSey#D +z%ImP{c4LB+7hYJ}07;6*Ol3&0y?>KVb}GH`T~V`k`o-M`UwY4K)Hx(2wJ+TDhSBB! +z0P#w72nDTjOW0XCLFZx>#5umz;$%I)Iak(zF$kW60cw=4_z0}&Pbsw#LqL*;6x!E3 +z-=+qOx+^Gi+dONfx|BUjFOP{?9CSy!LHkpx7wYjx|52xd6PD9$SZ{{TiKh((X{;iG +zm&_uV^6R3#=8uB@{%Wkg!S8bY +zbhUcKZx)bRx>Gy7yCmJFclmmHv%}}~esBFY3gOuMxkKj0c3U^>ZDDxAGY47~bEzC>aEPPYH`?T7z#=1r!zfJ_mN=hucSK +zw}Zr+f{|l-^)k1KyPh0JSbN?3H^}7W8)o7kHvk7^?(Lr4KyNBZ3P`cmgEdFux0JyeoV! +zrQr*Xk?&k-9vuQN;g4agCT1GGrqUT42&Ex*1*eow)7#uh-1JKPKyA|FbL!f7Ak%1= +zW6-btvj|*9s|))b2JC@&%SYd!L#H_s-@SQoy7%qp6F85x1gJFS0H-QrFLzgT +zi<%xML+!cw&iCE(u@y?0(94f21Ag)TI`I5Z+`1nBy3hjEmytxw#jfz(IoPdJ&l6Yc +zNHw2=D(P?4bR&)9LLU)&@Z_3jOwCoq$mKm`BXs5xp+uv%*nAn0z2Ee3`Sc^{2G$@H +zLU>}~*=3~SE>y6Ml2^_I$pB;KZ}LfDR!R?U-|b0ap>%tv1auUtcg?Ocjc2_QPlAV9 +zlMsSwUIhC7_PFjcV)BmW3~-e#*IodoyguiO&cwxJlLe6H9P*zl*E__@J!wJzg_9Q> +z5M6PtHBv25&#iaFMWIpD9EFPLX?Pi}N21dD3zSZ3p;rhnk3@*?iJUdDo9tE4lj9F* +zaQ}!ANfjNN?7GjPfrIWqeNBXQ$BApys2X8Haj{D~X+)6qEDs>tLxDk~HTW^MJ|zsZ +zrqxM@6Z~u-LoN`8nTKiU^Nc~i!tRDF&a<*?Ea^?w{aVR#)Z5@Zl +z0DAqTx!!sO(;ANGEW}MB_Jgh6kp1v15}qOe*%F!8<@9WnJCgu;Vtp#9SoS@t_~z3yj=M1ktv@X!tJM +z@ZbpVI+*}7;vMnc1Wj$RM9*?cQ8Wp*Hh15*+?Zlb980Dj*wU+6QNh*C^XlUi+xnIR +zTpu=zC3V2m*@h3`<^eMGL56_yNAW4G7LF`?!PYV_Yq^LwnUyt=NysJ9ED7*n@O9b8 +z@J($H`-Hj;a}yYHK+Jrwzt0yAs+1eK{e`kR?K4om0GmMVm^f>~xz%Dy%OK#*@21AH +zrSE_pT6oy3tkb+dJN#cI5Zz$@B=zvOuHj?@^ca>Mil1x6JyUGl?AMjS*lvZM{^Sh#>4)bm7tz0;hnjH1&H%Fp&Trdp{sneWY0 +zWPZKyT>1|>s03n@P`pk*KYlcm;Mv*zrpV3#G*UiaFHv28{M2H|JN@>Zz%OVL3AHtD +zbbWD+8-G2c@_s+qU4N_|9AtC)dd8@D5{bmb7d0T=N27=OweSvhbvPS?Z;(>aY`&Xw +z4g~{KtfM`1{Sl>2p_R*9+JyT8bGzLI(u`dC@Q-G1M_k(2^<EyijOeuv4SqEIJU~NV3dZXlC7OjeghC3{D8xqMup|7EPH$jrf-nBC+JK;) +z&TF$G%ie^E_5Fr&(uHL{njW|QZfk}=?|gWAa%X$+@{Vfz4iURwNkD+-WTf~Fugc2 +zyZ}vpx80TtNP!PJKd3Se$JsXooJoYi0W_;MYa?1&^ +zJ7uuwq}7<@4POpT59d9)?vkD4wg+pKyVb1+b8;us+e8!0%?YK+x)}ZS&(;vwvw1+-Z9(T_P@b<|ZQt+aoki7tMe+)|>isM9NkK`32@S +zg{47Ym-900ioUqq{S0sK3g0PySzjEKN@yD=N9%m>e1g~JOv_Bi>HU4*R}*YOrDs&c +zlO(&0ShLbYw?ST>WiDcC(v+F*j!wy^ad}YK|0!-GrT;5#%fOTM|A^aeKjJppe~H`O +z|F5{6{g1e<@sGG|{2y_9@LzE|;z!(mcMY!jlavpcL(cn;xE=c>D!PF?2{QSQxV>hN +zkM!T-w&_3Ow*NokwmBar!aw5n(~r1Kb@U%`J66x7So+>8??>DQNp}%)t&?PagfrKs +z(WP9;m;VvB(|*KlIR&B~DF0STK`wiSvKR +zbi3G+bYr1cx=23IS$7&lJWOO~WHdKJ5lu7FakAZc2u~@EBMBf6`;_VI+W_0Rw!jxb +zK=2V@E*9ug7cb{4T1N#g4I6{vcddl&9Bw19Ba}4XzxAJ4y}1cV@&upRz+Jj8v)_^{qn@s=98(L{1aPJ{A6l(C +z)1xcGOzAqI?HLgL`Gd3ecH +zK;_0N>jl}%!LLTP%AiQR0&by3L5(;#gNN2B+XA#0KwgUj~2 +z*(yN_N&LwKQc)>1CJ8`5z0_?3I^-ofEn}N6jmmwSM<49Nh~EQyIc6D~>kB-tl3>T4`vbB*HoZU_=Q&X;(Qf=&dXgKud?{!$HuGHFU7gXm#kLJ^=ZA11 +z&Vya-iE&2xVC2J<3$UDJAa<$B2l;>-Vy^q{ +zyh^2hNu%K|kxU74iG;xg;a-J}y!FjCI618Sd#)sD2p}vr&p&AH1KXCi7E|k+KxFat +zQcxM(?Wgq&zNhhZgH^0~@p2N&hwF3`E7cmIhLxbE7y*i| +zx1lT@&77V$(0gWDp#-2oombeqAn7)f;lAmJqm}BXJ_A9eu +zQ<8===<7x!9+*Q)dN=azb5h>K$io-6Ei893aS(b2WMc~AsXD8h4o%7c`}6ZEDL2z( +z5CgY)-eDf)XgllK+E;S-gPs`z{Z@aFnq<761sNbrmix;eQHNB4xoab@m&TaR@BYV9 +zFSW!y;-TiXf*JI#rm(}qO7B5r6Dp8xrJNfkjW)gRalwG1ulYD%wB`xChf%J~bxxo7|(6<7(sdy>o3K +zoX9T*y*<7(-R3C$SiM!n)nrsvOzJqkTkyF=yK#3_ayBV`q3=(&!Io3&X7mX-7CT%X +z?eZNTm*hJ_LSD%8)$bm}S537j{riq(-#`o1z(9_dpEsQUm$(i8zr=0r|0Qk{{wr=v +z{D|9y|BBnI_F=|9;`Yk_5Vw>5KgDe?Jx8r<+{)Zze)$!&?Nq-%i|2=6e`Mp?mVLUG +zr>MZ11Q&v)tu$O>_4qy7^=a~-W7PpnIy4elbq^XF=Ur*j{4u*O2o&8u>NJlQdA(;$ +z;27rVhCoD4IdTFfakN-@rZ>*nV$y?S4pm$sg{S@=ZS(u({6EayQ;;aomL}-5ZQHh; +zdD6CR+qP}nwr$&a(zbCDbE>MlU>gt$@j(Oj&dqwQ{*Z*xN*j7lJVPU*)+oGyr +zHifh$FtmXJ^TOb_cd|BCmVr<#85Rhm#l%-sPC~x@;&1gu-QJGQv*6||bbu2G{AR!b +z6V?=qYX{kI+pBkr1iVz>heHf;_91n-Ij3UpnEPCc>-0x`as8l9YnrVV3ep~CdHt*T +zXMG84d6xNsa{NQEFqs~0$ZGFOf^HHU&bt)m%5y#|8e1%pwVdOFy$&PlAiMpSS +zt`1I!ciLQ7aZsN?So!uxMD0QmDrmDA^=d7W-wu&VaAFB_geSjkO#)s{d;a+M)*L0} +z@LLiLPtPJ3se8jd@DiZSRVMKF;4gd4c3&z~}nA +zhAx+@QG0&)_dusr>Z2{ +z_+iJ?lvzjms@S1&{0B1y^MWArgv>sbhD2c~_mgS~R*a#vOV5qm0f@k(%M5HO*++g4 +zdj&qc!|O)jggK$Fy%aRJI7zkuW9B@QZ +zd~sm__)G1+MEJg3grSAqQviYq*?Ng{CPy;1^*)m6(f +zDs>F?Qsh#c{KlMhAJF%#dxjdqd+k{bZ00ipzPViEc5$=RY&Xu4Gz2s#UMhXaqf$3O +z6u7mYkTuxjs&=WnBiP~yF6@%??6>X-bYGmoGS`b8Go=@RfL@tqvU!Jzfia{OSEz(` +zkL?&)hG|J_KKlS8H|?Yy*1tM +zf-l<)IW?Z~))7-_(1K!9-uZ7e)sGoLO#J2kV{|hePM(ki9XWfw3fOt1Z1=#^haVA- +z9|J&gpkwtW4{jP_)E(@sG-A)5ts5VXQfN%>=Q9jz2UAGcQ~QRZmn01Hi$6T#E|(-3-dQOyKFWT_6zzs^<`tQ +zkn{do+-Cgm;wvcGk@@JE-?ztH9`1)AgMDgGgoV|3io{!mNc1EHBXLEm*xpp;<9owQRRqFF +zn~xRb3rz}50Pq0x10KDLLC@8~mpMVZ$%Yz;;I-gz;ST1md?tQZvP{1^v|qCGb1^7B +zJnPtqwZ`t~B#b<=21mVk51k1aHYNjG=0Dp)k?F+C>^}1E_pyt}LG)Z( +zU_y!59(#Lc_1+zNSjn)sn@%_IS{5j>BvwUhDXzVI4{#)&vqKNNuX`kq@Q;c&Z$GS% +z2~NO{oJikycVM5M0vpcoP%|i6kk#pDAHlDShfDU?@|z9w!|=JO4cY~mzx(r|DeByB +zUC1fh-zJtwthepf9O@O>pIrV-I%2{UeAV{lDD +zRC_SMe7SLZ94t5u9`Zsn)yKD%P)b6_UKWZ;V>dzu_YI|nJCRs*R`x-*WW6RLMX8dZ +z(`{_)3x`Uo1>j&41x|Ru#-&iO$&iRSE*SbwGb2A3v&cdq8JvP;?@N{U4smwiKqKjm +zJsUY%OIrRnC+86@OUkFyYX$Ty3)oyUU5s$pAidODq##$)KM3;7r1#e8l`_;dR+a&)YZrA;z +zxc&QI#ck1l7PtHVP27h1AL4fKUvc~V-xs%~{z2TX{3~uh{S~)S!V>h +zI*8!EirW(Zv$!2L1=4bm=QeX7e{ZEdZ35y}F61*CH=uXr-n$d=X&VqP-IsFc{c`UJ +zFB+o%f*3H_+f1iO*#IS;?{*39@TrNZABlI=2nP>v-}{qWsjWfQ@g{s&L;!oHA#Xe9 +z2PB6iKB0U+wTkJ14`GR)o!D}F<;ioc>btZ(rHk%|m~vC|+0*wW(_66h!T&oe6;ZmJ +z5*zUQ<$CMqQECypdPGyE|K}jCBkiT&VnrQ2Hs*BdG6e^;Sji*B@N!j`spr}8)1gg1 +zY>|}DuPm9vuN$S(7zV$W)|e%FT{Dta@iQOVm-z#YGiUfN3tV_&p6{YKx+UxwTG5;2 +z4{Y5m=#a+WKTEVB-kNfb?MycSM7k30?~!&7e +z$DvsOa(yMClpeJu3t**5I+vucNx-x}TAl*;EB6@nY!#rWsTXosiwlI}*4piO +zznpYRpu5q~cA^PpTr3b=dZcB}?o7_d`+#NpLMD%kc3Ei`Ryt}$7w_={Zldm)e8z$b +zjqYLwgGKd3!Ob+j)+hEh;DxPCq|h-D*%`%A?&SB%xM*dQw1$}_vosz{j@@`aOn&`F +z5=04xPJ}7bs4*vS%AnaZj=T7#BLp@Ef~vW7!xn+y!EPJGWubH9bN4R6Hi9bCmJNWQ*1(3LDuVRvlUs-#ElvF)$B>A%moat87W3Xws|E +z)zpGK2JH7cT9Ak!GsR|+3Ln8!CPJSlo;e2+(UY%cB;!(~EDbDAL` +z02%h}!BJ`D&iH|@EljL1elH1(Z&8X)8X){K9u`(Yg>nU!sE1z@Ik>stpPi#!W;?7| +zLT~QyHv9#X&_*)ACk7jNToi&hRi04@lX^C5&XA;Z8-P%N?nE(}M6x*{T3?E?FO(yd +zPa#=?4oK_GSUZYx`coenw4!bwk#|Ypf~~qqj1HtAc~)X@>SyNw9*1ucFd*rJ7V~UE +z77-i@a`(1hA+MpN(xJyi>T&MgS^nSC(%Q%t3T@@IkhM`Wbcr0Y{CcD&dBV1b`0W)G +ze52KV?oU~1TQq_drA1sLB{anoK`+@2qNqc7I5_6zf~$L!dw&y2l^_%(65SMFthYZQAbh_m+6Aciq8^1fF8ohYRQv|8Ht=RS2n$-^ +zI!qL^tk#->E}1;kQ6>(D`(gRKJN)4s!D+kPrkRJ-RZu+dOX3g5t-^#9gfOp^kAxl@ +zVjnU4v9Sk)an{VcgjVNCzonHvGpi7CgUm#&TuqLnaogOD+eP|Vy+logtF3XpSp=Ek +zATTwup;&^HH1vrY-=LL&_j=2rQXgu`@yG8i6=jv$T!61b; +z>-Z`!vjSJIx2*OD=_byUA}(48jGhH$wAxe_Q5PF(idY+)aq#;|A|QEfEE4S%F$u4p +zxA$8*uPzoOHe1^}^*+=9lG4&PYWbU%<(OUvrvt5l_lB=TphnkiReHT(!4e8)+&`{u +zUvnmYJ^#_0ysrq@x%E>RTqjCXaOiSvCGQ98#3g2-Z*X1k7+`ps0Gm4@DZPw-7m~i| +z&mxwc?%!sxT*n~M&qR~Ga?^}iax1-eB;`Ic8J$=A29CIZ*zWxUefy43FzDtY)Aa0% +z`bx +zqeB*bE<#8hQab;>l7v&m>$0F9_RNXe(D|F95@UGnX7(4vlhLgwC<%~!NP6R5H^9cD +z{WyWi-|7n^^rE&2q`YdYJ;)5!Q%_7#;q^DXH1yBh4=sH>!`06(Rqb=?NwTqv{s;NE%Ofk9?8cveC#`bqO7ATLGbS&eGKgWvL27Kh;x%(8M2BY?$ +zANSZ4ckrY5RAszJjD7-43YF_95*57|7M$)Ux~9%!zT7pzkzz;XVyL8G%AaM5O)|Mt +zi!Zhtv$i6HZiBOKO`+2VXbxS2z6rTAI!>d~{Yf%lBi}MVZO=Tzs#I+R-WSBHh&|))`)Lc<#?rc+^5F(fE93&=iV4#I?95ATm +z&GrN@LkbU%@U|T>pG;otTkj$d^YK9%SV+HvtLSc&VBjO~Hwy&|?Cu|d!N?dNFB3ul +ze7|LE@MD}QR= +z@~S@yUsr3QU~9llbcq8qteqX}pmd#gI3cC&@h#&eM&)wtSo`9FGq~}$6;Mdl#`02y +z2@FCJ=z?uUo^Fo6V9{HRxMphq_D_JFb-}-8uap<FOog%oqGK53};Cy>9 +z#=?cE)e6MJ-4@P2+1kGdXem*tUOY**;3$GD`rJ(I`lgO7HI5aXl)WxhQD0Z6`I+X3 +zx3L)btzsnQX4CCEmqs7aLrKW}#!q8}*|0@&DxJ>qQ~yHt3X3#Tc!XwL?iK(-_J)nW +z*OxzVObn1GGy+ogGV)hXLyn$IK}iV+20dGl7JO>-G`(9( +zhA6m7$s^d~mt4CE1if3JJ=04u%;b~DVR+mehWn#OV9wiS%TF3qY{wa1;_W0>{hn<~ +zHd$2g*2S;|wWSEYcdLkkfhRQwtb$9GpDl07k74$j*-{cb+IPW~=#hvUMmqr_e6<-m +zIRr`ev=U8&5|iXeuh7R`Y%rO3oi3b0Aj}e2s8m+TvZf;&|CDkm9GZ$0mhu*MtSVuUeDD<{~W?Y+$(v6Q?vK~=SN4Ra4r +z*H6Dl%mVwgieKXxS#y3%{!#})Hm847Yje*zEdqGet|j0GkSWTU27OQ#!DO8+521N$ +z7ZebwdH4I0nGfCu6IX5PKJ6Vgvp|uyaiYa{*EhRo&bWV0N7?8t7JS!d&XMe3B~Pop +zxNK~ja|iH+4v_+j@?;uMWe?fbSLxU?8F!6K5tR_6{ehU_FQdWDU)gJz^7oVl^f{!0 +zhc+^gMRha);`WQilzV32jwnC!q$OiHBl0ZhCOvkU>^8n@XlxUdYd<~A2a*A4p45F+ +zf3J^mu*@fr|DbYa#rz53(M&BBIW87U>!W+(4G#B@T~hQjkZ(Pim2s-vdcl>Q0M)#4 +z#R<3)hex*+S1Ur`>(M9X_U80|1^6Cdqo9{SLaH+kGLfU{Bt2=F84H}W3UQUTI>9Mu +z<_9gDk%hNlN=9Bl>16IVvJYwAnjWBeJTN37wN03>g|ga-Xs8|&@C3l+<3@NF +z!pXOC1O)+crUBiW5q_#+M}Kt_i+F*f`y|Nd=V`DfOf~%||v28qLGF +z9)i`k{S;KCl{1-+6ygX+EWqI6A6io4dRg+l{T~3_2o)0lF~Du{KLgz47%42esEYpp +za0mXE0q&1~0=W4Tpr$pd{;L2tRmgt_xXFTRfK~ni+?M|aa0map0C)Dk0Ng151K^hX +zXMj8B{{Y~2_}>BCc>gu^bh-IA1;xeI_?t0gC +zrCX)p-e*M!?Sz0!J0%Dv8cfbTmwuSWg?)C1MNFv;*I)b^fWDEWB1ChZv%@b|k;e%e +zj?dzO4JGkXyBgtA5A~NKZ;~1k!B~`5UV<%-M70Xfa{oxLI~q%eO>_M9C|()~<&tYH +z%5&ocNhEX?6S0+LcvQ7x#$c>jOms0WU)g^Sa8o1x7XWVY{}AAw|6c)anSTbj$^I9B +z`|B^jE%849?%{t2;7$NT1|skgE$oo1 +zGZlM}Mzn?Zj>VKB>g{2)VI>hJQ4e@|Y~cJ4gJ +zIqzU(gl9O$qTCoeMz};CQ=j>%zK}l9#N2wtyyQftHLo7~(~54E7Fyr1ze~GwP(m{- +zVwP8|1-ku~BqlQ-99q~z`K(7`yhiJ`I&oTav=+~SfDX9bTROjpac`G{a;Ge{{Q=J$ +zeCxQJUuN_wlIJ~PR%#C_$@J|`l-zR-+zFCR5#-P|lz2zgPpai$jD +zosc|qX^m_W_#Qz#h&7#VRFOceNXs<^jMjFr_LJ8EPpszPN?s^v2$0w`fkh_HCy?Y! +z!&aNsivhclPuOsBOkpJhCfKhC3`}q_FyPz{N!0a`oX~9tGN;O6Gfy)x=fX=L#ISOkx +z0A#FT!5jsXn-|*{o!vQ(oame}inewb-Ph8>oNIkme>Jeqhw*5~PCS6jx|+nv1VClM +zL~stb2Hx0is}v}IeU3Uhw-Xj2qW)-W_r|FOkZl>|vgBT|msi-WJw^=gSP-Tqf9wKuM&a`T5x}u^>oc +z5DkjNc2|+tk`e+t5=!et5MpZJ-^C0FNOfpd$M|tln@Ugo(N$pIV)<9%U5{d{ykcjn +zRolX8)k~{GP#o_U-G~-O(m?p8knGr{zKW~!Ryew-Q%w#P;W$EcPZs$u@e@6{0NJUj#GCA>2 +z4qp(-v*~aOiZUi^hQPdT25F7+3d2dtewJIszn-xKQciv5o +z!gpqyiRB3Q-WL>6#ow-qJ3vza>J0In5WvAzV0J|pG_3FP+{w&l!z(S)$armzDP5pK +zIa0eU&23;R`;un6V~@b+_ow|h>C5rjh- +zL&oZEKL~aQ?!((cJyS2|AEj6MN9H(CD4*jLkODk!Ep4bmS`3T9nnl@O#f#*362#(g +z0E60tN*`$g#S}%w+4s<;a#HF?(@=J4R2p)hdvxCPi@nDFx}fU$ET$DCnd_ZN7s)S{ +zpOuO*DnF7%_(^0}qsimofh>>oV7-Xrin=CC7|ym|K +zl~?35%P&hDo>e+I9v4Vh*!;BOiBBT3*Me5HN*dRz=4 +zB&_*OHP2!xlT22B&UEpa!Iz55P*}YUJLHt~YBAfZ!Kt(80vmxEALuZBLSvZAUekmE +zHfwHY;Q0Zj5X`pNwDIY$>Em)RKHt3HWr}RHZS5bUVCerioN3CZ4jaFK&=W;3$P#;P +zx4?lN>hF%>Z!eu?!Vi**ZLtg0p==j|QwV>#% +zrm|xjeO-CVYnW>aS&Va{-p~y$R3E~Q#SQ8MYXay`RxnH2Wo(V?)74Pb +zWt$Ou^2|&^@+CM<5ijh@+j_9pc_Y2pA;ol&#~fO(c`=;7zJ8k}5l<#;n#sL{^cH** +zCK$@Cy!$H1F0B5C9kW58g7%Y9G7W{)Rbp^;UTQi$KSy!#A +zHT;-F@XVc*d}K07TXSvu@zb+9S&T~z +zclXS`+ts?oxJxgB-7Joim4*?6WtD*l0CxCiiRvz{EF1l#zE+K +zlnN-Avs0u8zu!viShYiN!{EmKl)Icr^IC{col%=&+ajf&ogmB=AuOtzcg&NuK_FtC +zE3jpaiz)J=IzD1w_FumTEyTCFL-c1ix{s;3A +z)}Z%}1ho@$5V?p8H|{2LLw}wx)8j2Z +ze{425?I|XBb;7)`9GxcQkTFHd+9STzLd>pM6N^nw*~bHf}G*{gbIoG$AM0{&;uFn%zr=U0?viZNsgm6$7Y +z>UGfP+Cf2J`hBa{`l1f$w$BGy(Zt`>YbjJ%4hI-eD?O?qNVLE;*p@As9^PyOA)2Ri +zalbHY?44U4?^0&u6sc$`+6X`FW1VMtnGx?-1*RR}Kp9`VYwS&w#VyPcAN~*LykNQ! +zOLYhx0EGO4X1URLz@5zZbfihhB$4NSq#S8tLP@380f*w#A>kNkCc?>1bFS5&Tp13J +zPkkuIk(fW`ELzw?9v*9|Sb}dha0PiZR)9LL!V3)exE1(&IB5?d@)25~mja4MrA?5R1n=}@K28CbFyO~R$J3iFCju3cF`}%9 +zC>KcC*Bg#16!<;G+vXS6!#J+FAk>4D+5nZ1HOxwgI- +zmawU^cBV3(y_Ee@%U5AsB8ZTST46HpBWd?*!OB}l7Mv=t3YgsOXJ4~Jg?OF;`2JKl +z|M^lT(Ml)fY<|Nn3v2{90YrJJ+vi^->p+;Jnhh@@nia)KGujDQ%XvJMkAG!ui~{>e%LI=#n^f;S(#Fpq|7v#Jb>CH9GfUWhD53o8=PD43PkGNHlg?;)mcoI4`f``5A^o8?W9ZQd+0vpeBX|G=VQ7r +z=#d5zKZ3wT-EjXbxQOaV!TZ@OMr;)`f$f9JtF8V|0GYDZil0E5k6)ylOuIhNujTD2 +z(Q4AD3se0U6CaG9mf}J%G^RB21ev_+L|AhNNTANNQxFJf1e6P_Wj3k)tiiM--EpRV +z1Dc?+XoPx26o0H}+M5~Hmtx{0yKho%D`pz|b6*^HGHfu;Ak3G74t$N`k>RsS(rAp~ +z*WPy|@nA*Tp|^`lkhcwU@hZS{VN1qJHmE*xv1lKrD9I!ICEM%(e!tJRjx!~eGKx}% +z4Ff`e)%&OvX%+)we#09|k$UGPOSj4P5ZieHQu*cKsChf}4W=rr#AS}Qo7W3DO|W%$ +zGZ9DKx{-2befvB$?VWUEBhB +z3&wXU2PHkedhdsPLVF_yXK4E6sIu;$^x63V6yi@vWn6DC&oa7O<3S1KTeLB#AmaCA +zmyFu|2G?7xLCxk*EoP`d*dvc81JN}3MDi2IhO)a7lW!k*F+qo}&=7MeUzMlV!e{xc +z1W5h1Os+CN;KP=E^4^UDt!}G*sX}GqW*BTOV#4&MCJM+c7J?EKKjEWAIS5BAC=gxvE0o>=4 +zWysEacbmt*G6OTiKr~{5!p}NBa}_h;2=I1qjR4)*SQ4mINi-3k-Q)5J6N)v7r_1jh +zuvI&eL$`y}SV@tMN=pAl;{WzKVI+D1v(qN4g~eh(v!7V0Hc8ys56em}m?ru2fQ#y(Pgur^6rLTA$|k80Fv&9>J{tV12I~-p3s9YY$L(#Zhbx^`JA}E%A(CsU7edn2QP3g~_>k2zlN% +z(NE6XWz0~yB +z#{7c7>T3o_j>p9>x?e3TEX5;|fc{MdUMNf;PJCFvOgV1UCwGQ$z#%ou!$}N1u$C3{ +z^J3zFhc1K0v!prr?N +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 +zU`j;1$qF#k8uAf;Z^Qvi)Lw6H;*Hz^Ov~1 +zzMqGwhPaFr+4~u6Kne^h&oMs-_*t)bxvizVrU~6XuCLB_p +z1c5Nrp?V?BnFJT=uHw~(ibH{1j*a~r?+aXv&Q&%6{N)FNj9IOG%&di}bsK6cMV%)^ +zT!q8{+Bv)$STKl;isD-g(g{{cObY>ia+|>4d%{YNO>j)N1_3utD!dx7x*9D +z`@=h(j;(taSu0l +zU$+{!7l%CK)Y|2o#a@w2?rq9YGllZ^*TFo6V{$c;W$|k=64{h1UCA5X{&;#-eeZ2G +zTGv@qH?p9@_YgAgMtXUhzcQk;WZZ-Y=pGvuN#F^=yrNbcB&=*J6lm9r>nUD%u~icM +zO)Y1tjEID~)8fkCe||=tyqV4wFlT+;hJC9t{pyd4vpKow6+*NjOF#G2)O;V1dC6Fy +zY~B;;9k)d+kE}aIF2E?X=I@UTe#BSdZF?b9JP)Mk+pC<|p)4~Sc$5<)f|RVYkCK9{ +z?ayWcI3*L;dXk^}>t%y9_cJF=N-1B;5kDATD1EQ79yUI1iAurim8`*L0F1Fr6JDHv +zrsc+a_S^Y4)|6A~vr0n}7oTvG9jDHxs-*^4YW9xFc35k!|_b~`&J@qiG%Ig#M6jgX~-F)83r&g +zRuI8ir+@^4hjIpfAcjHlEyduA=tB~53h{leMktRki^g6RChu^-@QaE|dkB^KfZEnH3SPii_A-Tylp3j+izK8U|$3s_@9b!>FRyEYq!6V}HqA?0UgfO2|%Q|cq^ew4u*}g7CcJ*hC0X-cq+e5}wk(pqi +zfjXEns9)1o%3ded!hX}Um=loje=k%miV~_4eM0Mq9|-{~?!1#-Q8a>}VneJcnMuOY +zgNl|w9UOs8KaVim6A~p|KRX`5ZB;o*T36ohl5`1hMf=nRI9J!UDT`ScbA)gGM>w87sy4q4=t$9`|lLiDBoki#ly +zAR8H*!mn9NfuJC6BiIIupWJkc79Z~}F^*IeSGRInH{&8N0D=`x#q2kRg<7k(;-(u| +z5e-s#JkXAVo>j~)P&QJazs*z?W117Wa|7RnfmxcsEm}}ZSSdcE@n{ZY+whyGpM+Z^ +zhhqgkL=u9k_Q#2uzx;}xh14|XZqRvN_%fll?=KAQ!+)*MDJm9kHS1TaP@wqZIy(}> +zo@Z;&U<{-BL$mhlmel4<`@q0GDcbrBAmpvQ0c|7e;u;Xm{91C1i&;^wjpA7(PH2+p +zx5EA~#lXspzq+Izp97^F%pJ{%fV{oCB!LCVhrB4@TE$T4Fk$}Ebvqm1a}oynTsw6~ +z0n}2SB(ZQag5v`EUh~OTO~VzA4iYwjzXfw%naVfM9|H5cq1Ecl +z|NK_E=blGmX0>ldKRu?_=-wnc7JzA7&7+ZkR@qQexF;Ry-KZ!Kn^XZNS2{~WOVwYavCc< +zf>l~+HS*q-3nf&O`O4KShxzYEa(eN*Vo}$XHeY$Tml)tFUXY3DW?|f1^1`4 +z2rhFDrWU|N_Sf^V@nyv~EmU!4C-5@$cLuFJTN>j5Thn5*?_}tA`^~wpzKB@2p(qw6 +zGO`d6NIn^TV_6M;80p@?)@(wbOe|#oVB${~g*vsIvMn}Kbp%PktbP_BjQ=J<-!o4_ +zjm*matj9`9{{wMKva>`h(o&1i1f3{ +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 +z1Wg|K7X!3@Jde+tncKhNvaw_E}4LrC3y?IWj +zh-3LVdvKqMmATy?V%JWC8I@hN+oUgM?_xCLkH%f2cdmn)H$FxUyqg=7Z4r18%3DRu +zuWH|!Lq`K(OI$v+e=Lm4J>$~{ed@ioJ7RmM?5lPZ`D0!M<8SY`n#4ip+5GP_6Zs#M +z$fY5?<@8l-uEWF&A)UAWe)}`m9_m9*B26iS{GTfC)@~n98sFmvi?grZrP5a&ekdBA +zxoUpyMLV-?Pc!HwykxF@1b`ZBv(umot^|U5f~p1fs=#iOtitw;Fi~loYtrDA+oto) +z!iUg%c$`|R5PQg+KWpyxn{~(iqyI`h9vZAE +zqC~&kmT6X_>eIJi&VIL@aIELVX{;>2E)oeSfI9SWT>a+Vgob;tLVMk`&R0(6V*O*K +zjy~V@nD&#_aqY=$uQ}`OkOv7_pYq7xs>jnQq(dxCi8Wa1qgQVMx5I^@d=0{e!n;7Z +zTS$&+K)xXRY`8n8>)!J!z8GQ3naW0Hu|z41f5Hz+EOXWJ{ln7OR`TVnm9eRMUSbDx&g)0RN +zJJa#K>xXsQ_CpR8lm#tUlp|9HC@5Smd0>9$^!6Q0>w^FGT5ImZ!-1@8F1*8mnZm4% +z5Ii=Q-R-LmRTC!SsNs-f!tg~;Hbpeq2go@bx!6I6Jk)q?6K3jXPHOi?X?l-E@T4c@ +zUBKSQ#>E%nquG_AB{L`<0OZS4oU(yAurx0P9SEP>_9gc_Y4Pm0(trzjdC3w@BQO&& +zeceyl{`4`zgFlTTl??N^I2cS!?k%LykBV44#QS1<3nDc(>YQATesXgATO*iQF~< +z&j+u4S+FiuawoRe)enpO2A#^m`GF9;mJDtd_G}pciQHLg4#sc+ec*Oz#E-QJmHBPQ +zwygSE1X!}ZhrhUub0;8(k*@89xgix>!6b2Ivs}TeqBQ8c?WNG#4xW8_+^t6<>a-ca1_^Oc7(-}_|6$E%) +zR&-Yf(V!D*7-!fmk9@Ka@Vs;w-J^}3=+*`FcIacY>vw@8edQNelrP7xwJ%yJ*HhyW +zet25hUk_`%tsvm5-2QJX{-48R>so|GgZ*Zx +zQ86&7{`jZ!lhr&Rpia!s8Izjd82F11?sLztS6g3yN?}{ET=@1+#T!FP>Bl`AASBs%HIHPYw&9En{|N0v68mj=;oo0JXDQj?{T72)ZGa(14Sl7a0A7 +zUUp2Wj`#kWAVxh}$zHZc&1EU>a+v{E0=A?|Ek9+`Du`_`b_4%JZu5|8QFf)2r7_IGLd)RL*AG30>e}Eq +z)@(zR@KW-dDQ98)eWI_-boy`Sg;U>uBKN>C3}MUNfE9a~)s^G(|1WYc9%4)U6S<$; +zO$vPp$ESp~##5n1zHmp(^mb~*sL!$jz(gYIAZ4^eYW$G+Kb>^<8>-T1gVN?OLc2@p +zdHkIP+5S+*jmm}m?Q)Y&^V(sSHh +zGyX$%7muFn%o=TrWO9Cqg=N{VcQ7~Kmgf8Oy#$JX`jQtldSi}g7hM0Y68G&;Ca62y +zH~kw!tMB)IlRq!_E;RT)W;RW-B~lz|Yf(sts(zTRI*+wD$6}DDlPh^k&6R`25rRXV +zIZ04cemG}MF?Yf~&TrKsa0s%W?LGI(IX=;T-A}q6J1r>vl!InJh4FiQJ^E~ep*ibN +z`iQDw~zu=un2s*Ps?j`{nz0Yr4w}jk?|0B6)r{*+B-X7y2H!OrMOsXak&55-R +zThdjd*7S&ZiYQSEI$RtnH%M_teTFYR?cE$9lhtRN7KQ4}R*kTqM84>L61dLODc`hD +zT$^@7@Vcy)(jfecH~+DlF$591fBJ`dbie7~>ZA^vbm*y5z57jzst%DdqESugrZiq# +zIQ^(t(frTk?ucGI={gvTl(XSZEW3BTow|4MQQ?)S>Pkyw?ujF%rUP{ocHFY%C;NXU +zH-WU@zAYzc+#I;V<}FcS8aR#kSJdRFm5$8C;9I8{xXv9Z%6+7&#RFr;)n{D=3=(;i +zdC3v<{>=yq^f3LEo6tHbJrMHYwD$R~Ak!!7w?D5)aH4u~Xpe|^{H5(**n{Qv +zXNr_6ZegB$Gb|Q!PSS(n$*j+~#P%+Bu`NCilzQflbjrlUw*i^`FUYKOv6=8Xk3+gs|Y$&f#V05s&(F#LOOt +zo)>bKCwOT}Kt4{)@|g^2xz6qge5z<=s9?7%%p$Fg4g|D4J=on!1yLtzQgH->c#YrD +zMCc@7H~jg;{Qa_DMn4uU+ku6#FO6;OS)!T{L+9ZBSag2jCxFVI*2=fMaGHZ=pi#xG +zCN~8lQCHq^w=xbHE$0>Lue;x{|7R9tK3KewoM0n4Q>Ep20p2JJ5icr0Y7ts@kNUUZ +zB!B%@RY|sw*^=`}-FT~?0|sYjl0N=N+A3yc;lzS?GmyZT7%h#qGUXOS6C{=8c#Q#X +z3c03s=I{dxaq0HK??Pdp_o6-9?nDk+jQ$r$C?93Mat4Q#FC2f^>IgjL;8D&>kHQ6v +z|IBP?LKanJ-Ltt&n~EcqBT}Yv$IG|-+9#;N`ythnpRsHJkiu& +z%Uv5)0x#bvN#=sM4k4C)Nn2=qRErz|(zfs_1YI*{6R2@R-}n2B-8YvFm~?5;DJZ<+ +zD)$Ily@yB@$VS``D)A1}X}<<6kQoL@wesUT+GX4IRGauwf}Q_RZo{xc)0clJx2RfY +z^Z%jTje*LJtvx&cQ0}zq!~GDxu@Bwxh@9Gv_`+4VUT;cRa#svmgKaT!eowm!5m21S +z`H7@L*$LsQ|4?qIqpyD`_bhU^3*wL2FeAbLq1?g$q1-?kj_HiL-cv>c(pRdtH_gp- +z`f*Ps-8)C5qJ?~iQ(bXcd$Sl^%MC&_@H5Z7zlrt!UqG>+DyJ=#;M3Q|@_1-^B;jjR +zT=S-cUG3j?NX(UJ;VA&+p(Km>c~Ww?x;?{-fwl04dp0|2fr +zaMKIqc|#<|5VlI7aMkb{n<~jiJr6*Sh3y$BBlhbL8KVN56Dxc7s-7VJL%BWoJ)Lhd +z(-9+CmVONhm*iOwu#XDNq5Ow(f6M3eU-_Oh3^@dD9=LhQ5pWx_&+$GBwu@wk$XHj8 +zqp~afX@Tf!G7x`R?d$JQ92hY7Mm0dy39o4rn3+3BCFd5l<{~)EV2?c6Y3qkI;^6{ +z0tVga$?g(o{7J6? +z!p&(}VAC-l3e7C_oR`9Z*wZK?@X4H_RcG6C_bzLW6OdEM9RnNqn#(B=PwhLz4n;Ia +z1vzuNj>XKL<#C+}_;8iVgqEaN{Gbr9w5pW|jsPSUBfB5YNKh8b&hcKp$!JUCM2bYP +z$dwd}32|G>Z4ch!1mX$dEA{ts)AOj8gaOivouO8;Nw +zKC104Se`R0(dUg)VOp{<&`k!tb+ZlppRlstiEM_-r3PCd!yMVb;5 +z+pboQn;j|8lUdeNDqMHkNkm>L&1_{A_BA^Pjw=qEN|H_#@ar4gO-qL+tFoa2%Iz_7 +zJUYQDd{L6%pIY`a7X`9eO9e4O$RU##u^aR^C#6DU86eovoXu=;MC&#*Iu15_zvh?8 +zzXjdIXICP^a`xZoGgV}hPYN{z?4dE9JiRDr?igvf+&G0IhpB!Q2r$X}Kzc77R&!=@ +ze!7;&C(H<_wDY{?v3L`~w*=8e6pB7;4ZWMz#<(T-RM+}DW)rCczkX@qPwJ2TW+liJ +z!8~`thq_sR_U%IRvI~x#wwj4}yS#Nq6c7C$%FVvQp!5&rrYhw4hjPDazZoTlc#OL?&$LxF{q>GGnK%>C_a~zr64bg12Mu|(+o$6(z@dE1~4r@n)GsCWq>oh40U{J +zO;NiEfT}9cp{m&d=f;Pw6hiBihs_YT^ftX6g&tP-<`XR3t<|Ye+@SHqM9)5ldz+$% +z{b4V>qiBfzL;-VOY(T#IkxEwrr4@pVRpC{^mhF|A%s?Nc~a& +zl7*{>+LC`7SV8mC@BX~Ft%eTrK7fwLfs1C~VB$oq$Y| +z7Z9vU$Q1PIfa=f?4c*cR6Hpyfv{8I`9f{cHA;_3P#L{#|@%u5&isOT}MmCg9f9Bu+ +z5h|e+w5H;S;nC1#u9R3DMeX=qDsuRc$$8vv@!`C}mtEkzVIx(_Abw6Y9|6{pH(()>>{*UFBsZ&~UzyGw> +z!7qe7_COC%sIgj)xVX0U~q6WtCIJGLlo#{nnfVa|bWok(mxq<~?$_1$@x?SAUg??uy?`-t%kR5L+BO +zyHitqUM*+;ijTn^9nXA1URydpW|vWn_Gd)0qK3Cx%;cl2Q5tQ4hK9zKR%G*p>k!6w +zUL^`^39XC}`sx3I-kWD~shrOR>a*4WQ%P*xE21dN7zJsqby;m=o +z@}RdZyFReaY#Je4a^&sWt;b>t4pzPOYv9K}7k?(vYpV)wPn89)3Hw9%wBnB@=UrRk&eap~XW~KJXMoZ|trOX>!qa +zp6@3vB8g(|`}K2#UaaZgU{QxqfV=MZnFlt8)#)0&)!O?9oE?QDc7A(wGj0|xyhwrF +zQ@w&I4|@8Cu`~1zzLPQ7-*EZiF(ObE0VjO{Yc~1*PS=^N?ZTPBqWVWDtN&c?S7=5n +z^nWh5yIAv^GuHoexmjSfweJ=VFQE|ykk^iFn=J6iErxvKKBUP)e-%PKwtDjwIq414 +zn^-B5by?S)^nk +z_2Q2in+tC3$>3P)qz55Orj4j-&9>D{+zyuNNSYr%O0U>ZP=RM>6kts@b2C5Uql?y9 +zu87_!?{ZIKDo4+%#K;yNS9ocvZ6l9|;-O2ZiriQcR~jYib9bQ-E(9plsSA>TtVH~V +zpG8mP(}+M&#>h)UZzfvNvIm`<#ELJ}3h8TSR$RVA_QLx5BLI9d_^SW@{C-vVeqY+H +zho1u7xr{;k{LT^3RQyYb{__=c)(`l2^Zj{RW^BH^1rm5+(#(lPKzyC834gZt6ZAg-+56N +z+r7tz$CFGwCg#4Y(>-is=p2^RpLc@akL#cM(W*YCKJKSnbpqZff$emgEiU=aE8{Mm +zr+3?Rp1kd}gp5}~75xVBEBpaor=D#LMDbT)DS9H!M<;H%umb*Ik66z%0XGF-JbpsK +z&C%ZI-hcvz;~&Pf83wu=V2e0na1`_8ueG^nW_O +zzCVUB_u3&l@-|ps&yeF^?hhF&$|LYH6hn`v){K)ASxBbBoqXQYxn!CkzcT{9#`{;B +zs=k%Bj}*o^2`^`rKN0=r`>XO^b8yxw=6V*6=p(ck(w_+v1isb2-p|bJ={WeDTjxkk +zp2=dh&nr%LP8J5sT|iTM@%OD7Vs^4jtr_jlx)pwRpAP$eLwT(`?FGCbe;2(LSS?zC +z4A^R+r@LhbFbAj?_K|zie3giN4hnsp#`FU<0#K(n4uMmw<4v{4 +zGW|e~JdZE(leWL(3=R(kU#4e^jNi<40R+PBA*&ZRx!aGch%?$O=&dOSgDHOkjL+4l +zO4TnB>7$2eSM1XR-U{ZgKTk|~3$RN8TyC$VhbMoX9NM=E+(09L%b1Y%mx>%4$jeW+ +z3KK7y70lVsB&=5f=6E*}0E&SXc=|&3O2HRkl9DO@d$0nZle;{@+sG14z`Z8_eH#ZW +z;!>Wkq1R6p|36HKO+4`tl?y^kW8Xb#jEpvgZ2M0k`=43ie5Cs0Nf%41xx|X0Bzyf& +zIu5T`^e@QQAwBh8pw=jBl5cdTkc=Y-#N3ijRUrR#M>DKR9|<;)n4Zd;Z2D; +z|G@o6QN6j$WT#z&i<_M!f>z+n@L@&TEM8?%rC5M~CxGMC;hwY4M*@KZ!YAMrYRnq^ +zNGssA4st}mTc-ZN;j^We-|{r#G{oPVAZ5fC14g7TU@K!LqyORk#^4K>!m>?UFTiJh +z&n~&*f9qdF`%ZbXZ;{Ju_nq7`2%q=G!uQ2O&aVJnp^uSg2Dhs;CE&FA-A;gqjO%z= +z@a2PFL$KEo;Jq>WI$&^u`I!{ZXgkzNOokV*fs9ivP!e60u2%lGt-yFg(76vF6pk6a +zopjS>$VLZ7d;C1b34a-d5Y*q&T+0h&g_-2ld({)F6@7onY9Xs-YO&dm+! +z;in(fzejZiFQM|pQ2si^UA*`V^ZPgW_IH9maQAcgTRHp_@P$4{GAR(Ffpu&kIoy0b +z9_RT9f#eL>l1^{}>^_l@=zo~OGNOLJJfEQjfDa5-qY+fn_5%G*--2gF9h{`u!7Z!(p35LP-L80l^_x} +zEfE9LFvofdNKRE?t5!-D5;C*ku8t_9%P67On|?By__A)(T85TEtQoP1eIt?zU~8;= +zPF%k}wCkO`VF=HX$*xT(1%wGmzbO}w`Q-{^h#C|Iybmmo5?4PtCP79HBYKx*_VaZp +z0SG#Xru>+^V#YhBBSiN|XDHTH4-R`%1Yyo2YxxGfypSDad=+7lLkCcSc9mEk(&_N&bH>nm^g9Y;!EO+pC=w(5(zF^4j84b8T9vk+F82)H +z;Lq+etWZ=yJTx3TrOi-rWXg5jbmwp4ZtzS&xHe(vsDYEAeN2_t2KWg!M^4|vae9Kt +zfGSFLUqjjl&wcY2dS_{ybo)}X>Go|QA- +zgrqE?6$H{@zzZdC#JjbDKAMitI+h7i%JoqE072l%nJGeSL^NcQBWE3TCu*{I+}p%Q^;FHtbz4wWoR;)G1l8*_9z<;FZSXeA$j&fT;ZTrEs_AnV+!btH(;?)+2M@DfYDSgu@Eqxdd!6BskMm+p$ePj9+QcH;C{& +z4`S_j#|%EhlryFPe;+R96LD58-y|3WTzp8+0Y0s2>UMUti-vU|5e!Wan2`w-Zd#A0 +zEyBjgVu=9Y(sq419r_?4V^|K38E_p?K;cSL!k~IUQK@)J-cwJ|Im)WqDk@le= +zEWwOycjA-4NJ4m_So6i7 +z&L5O8z9_?-(__$q6Nf|vkC?Q8#N7*SVR6gR0U!p9B)o-u%-x_*JSPV3&E|@D1eaeL +zH#owhrPoV0r)9Q3n%0+BAVI}T2!b9E7NuA9izs_IekBl`io9Ziz?%?Em>XgzKu6#m +zGYpu7if|;#$cK5upD_9&Tpcg|LSsP~;!WR}xBw@ctwe88eB87R3(l>IfH`o%dpA;5 +z{7hD_U2otIzqSmXs@4Hdx?kx8Bb0{fo9tTZ9}TQTa&OO8jJB#i|5}^4d8nA{KySNg +zJufHC2siQqQCW$h4%sub69<%n6Z=&qe~T+S7Y+gj0KwGR*;|H6OiD81(fA+IA>GKN +zLj|4@w9Wc#6xq7Nk42Br|7;TW06HYF5 +zznUamgm(i1A`E|RJ_vk{F{5_UMNZaOA^JxmFLhu`v_1J3ViQ6Y-LB6W+j?euRAOG% +zLiNb#n8`Q%-1+9`)C3MU-0Z2|5e{sML0l1#sd*bbBoHp`0M +z**Q<&gs4`VJh{O`;22UZdfOy2v6oVGr3kz@gh7b#8-K(#4Q3EJHZ<85^){4^8YGnn +zw?#BJ3ycJ-QXQ>_Z`fgy)viUrsk@A1nECXge+uiJ+Q>rxGJTWd8Ixo3FUlZnM9sFb +zt!cxSr<7zi5mwxf&%)8JhSxxh(0shOcSw=q#s`!vE0QzvKI|r^tnX+^9|OH*vBR|L +z;=~X$KkzXVZw*V5;W(hAd;+I@!(Fe9#MQO0Xt?aedOt*r_J4M6aO!Sp38kQ2{=(=8 +zNhF-Y$$kOnvU!AraDnK`VzKcsg(Ce!hehq#zVvu%vLR$zJ32b$nHv=w8wV3)WnPKI4yo5lc;iL7KwOFw^vF^=+~IT>r9 +zhgw~a$Q$)3>r4J_*Eh-eSn0PzWTY-?@C-#@3pTd}BN7gpExvvgn`S}MhTi{D(zY#}KXzB$DkC&MX8m(6k{ +z*f0XI>~t!w5Vbr$TUF4;lq@R<^obDdo~E@ix2C3^Dfxy)Oh6_nxn621-{%xG8LW9( +zB*UU+e*NrwK +zX=Pt`B6X;Sp@(yLPKj0nYv8NCQ&iB>MhZM{<)W49X%F-)Z!~ZOezc2-n +zb#r8>;GyJI{=y&`B$`BPIlxBpP^R?{ +z%o)QKp?4s#=cxXULNAV`{RJESx5Y22<&Hw0J8gnD66c(kOgIoyFi0zhKatDznLKdF +zkWuRyF1b}l##cuUB_$y5xV^dy#LaviY|po(%L1ZxAS?NYSbzp=45uDHQhvJUP}#NtHfH1Ah- +z4?4{a5%kDIUv5t-UdbCH975lS&L6+Q*Rg8yAbkC(x@;MJiQkjK=dUQUjh~Lt-1Z1H +zW%f7koPdCj3{9un<5r1?OuyjA3U7SHWx0s8kFfWR`(+-Lft2n0Q-}2CzIRKc{56AN +zGosjT#t^18VY>hP^}0SoQs(lN4giO7qA4+l+uF6{a8z(r(JV_!y8#W&A?`;!r=NDI +zvJ{*_#9jGgCe~EJiD57ku(8={snIdTwR$WR~@dzbkt$1x-;i>Ifi+NPO3P9d7WZ57NlgZZ;6d&H-6?5EfH#?q^CPa-^ +z-&T%cQ0gOtTuQ5x51uyjnq;&yf)-}iX*&#C!$f&$ccd^h$JEDmE>Z_SeE%Sw%P`nTn$?I#cipV?U^ED!V^Ap6xV~? +z1NQGYP3^!;IxbGtCX!Zk*k80KBk#hkJimwiTX)!YL5|wHn?tY;0g#_tUVSncQjwd^ +zh-LN4+sn43sS`vNa3zomNk?sj-SbU&h}p*oWRL=QuxvCzA&fR4Bb6DpNo3lX@b6zu +zStIg!V|7UZ2d?%_H{3`flk%V?d&!fWrD%;uL1*N=J~*QUQ5<{0UfoE@@k5G4JrHQy +z{!MwpdLOP?rpiCmNS_epo#`#<(J<@n1B6!}$kpsfOP)Uo8ks~&8k*tY@Xux)}(emQF#fQ2O30nqS%k8*m39f!&iF%a$)x~WwYa+s?C9oq;g}*+H +zG8v8jMDfTjIlH{YG!KqOs<*vbV)AlrH-S1_SsndJjH`;w9xM0w;kN@ClTzuwsG<8XH(I}k2j@S1L#u6yIJi(TdquEJJy%F1ukVu`} +zaZheUCaBmPr6H}u$EWfk{Ky~VQYY$kWT44Y25@BSXh&tTs_c$u7@Bm6c7FOlgl!9e +z<%pG5+JN;Sq(1A>B8WW6U-k?dZGZha{e}oX9V4cf +z!$miPB3!GaA*Ym=UAHD-t;~BgZ%zn&4FnEyxyu7rX{(7(Pq$f^Z%SgVgZal_1}xf< +ziwp;KkJwRIS^H#~7jlR;5<4GiBuf#;#79oTs3NboRe~uH5r#`pEBwHL&I8@)w@L)z +z@XlJeT5ZSaI1RNk5q+^JyH;M=pM4_HE +z>s0nL*ln5?(p2komg&Lzc==Q9d2miB5OVuuo?2qLN}({~yD~JnpAyKZ=CW0hz)*?> +z6D8Jd^*YWkm>?srZyn8g{Q^^zlyZi+xLt1{n#;oh<%f5*@}kSc!Dq}TZvpp7me!RO +z9B0qDbWFdTte5l$fj2wJH-4>Z4~v+OUf{}yDA#6t){Xj!Vxy{!O?0h5&FbzLQ*=8F +zCs6~g%7qNA@*6y$Irs49w4WbaN(6|SgCOz5KbVCtr8Oi4HMwQHf!maW)HX%~BWKf@ +zwoZ{4On98Oyk%rs6!Ud@bYW}&P9u5J;6}*&OwVLJfc?na7~RlT=_Pt7)*5|1JyEr= +zCQ_K(jLk3EMA_K*vTg+OVYk6u0`J)~g~TyLTdPlq+WH0a)RD&V`=H=8DAKC|m$!}Z +zIz{aV$gWba*5_xfZ&y-YF3CVJNUPyPLbZm~8cQkW9-fjPnhH9+pVPt@;C{2F5Oh-! +zp;XJcE^Wq`7gKih(WDtd<$!jpB&`w_5)K~P2_cVdC~k832*rUuOqWGi({_%5BtZyM +z%ou}Fr_Ak|-VB+=S;}d+s)r +zu4vI7qF#YllMzdS1B>mKcLlbeCMzm=paWY8DW{}wR4937>tmZOTfAzHH`L*#Q8#8H8V7GBz$vFxL)K5^F;AHj&_`kBfNd%e3nM}E3LV$pN=}3vT8|t +zY+i`0`-jR9X>}JdPO*Fi(?O+!_qjLE4)IpE!q!;}zJ3S|%yU^Vdh6+L@02!n5h0la +zSuM|{?9dC&qA}dGwVm%I>kz1 +zu)pa1TZj>bkF3m^ml1=t9a3)whNMv_QOG1I3fOhf2xFJ56hgs<8V&AYg2$EZrc7&? +zw;2tBBlThpjaWO;MPZs-?zP%Vk}cw(ie<6EZ0rK5 +zx|xj!hnuUeM?z!r*J@DWMV> +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 +zUuXL#40mv}N*4U?cX~c~x@$oS6Z20K8g#=y!L +zT^cJxg8qZ&saN76*d{McFz0Y(j=0;#$cYV9TXjO`V$2-$rJ +zBE_7Io-1P`U`jWh0D1^sHJ*?MB1y8Il@>jJ)5K;O!<6?=-oqWG?LO^?V^WQUGV_nk +zShEpUP|(ZrF0>iUD;nf(O|$+4cYA!%ESLRcdf|`v@uF2NiI8o@0rMe?L_TsNyAPIB +zZHlFx!1zei+aQT?UvL9HXEp)_SF;43wU}tWn!9;dCJ( +zbb|PC{#b%H0|b=Nd>(3XpFa8Fxd`wJj{DGG)Y(;Ne0%q}4(On^nA4W4I0Msr0;qi` +z|u51%rR?kjsL8rPZHh9dKZHDe-5KJvcx1#2niI9#;kq(N}e@{dyqecG(K +zFqXIgY}CaA;DlMgoB}{ZV2@V~ZZ&_nOI=&_(Q_?vAn5E5Sd&voK;^QqRco!;FKnf1 +zAaVlga*m*d&^xs09!tY(wwsgYG%=vdFs^CHcf1WG*f4oSAg?c8ca)9UnAu;^fC>o_ +zs^O_GF$qP}NDW~jM?VN470x%=RAAkz*drjNwmVJgUV~}iWB}|L_R64APy9vzy}RAZ +zJ30&!I$2z5-<$bC>Gb6dcI3gpa)B7GGoUc+I|hibo$g~9s(T^NXX;oShG&#OvCvT( +z-G_w#wP37*KvYakiI2|9QIzrnw1v`#=7nhrmvYxqx;xTmNWR{mMIuDxUWP2SPrg)% +z*Z~;3`yN&jOePnCT|MvRen??FE?;INLKqag=s+Eu(ow=?(@M4(i`U`n>gDd%$i0IUfhEUW&_*zJ3~&|BC_0bny%Zb&Di@(p=7b*i?g|(KuaXErgWCBPZk1uZA>l{jPhO~bEzzeBXtk{zT +za=}G{U?@53gCkDw1FESI#29S~3;LJyxMol@=oHB_*DHUPM)`gpYSENwdGJYFs86gT +zr!38>fPusXK_6!9WbxSw7vFducQ^1e7IjM_s7s2o*n5F8LXmK&@w}u9IBhC7dR#*t +zFl|m-dhP+HWh;k{NC$pT?fq_CR^17LWNE%yg|xL0l3dW!(3=Jm7Jqr!^+XPcy-+7< +z`7hEYi7K@;Xg*QGm(Y!l{6?IyFCg3-xS@UeV;HYPdofl&$v>2hcfyo`yFJt;%z96A +z>gQq7Dq2ZcZ5~vKsWx#Kn6~d*s~n|qR#*pqg5xcEYp*9xi+1DY8(bcBhin^-S`$9a +zce9ONJ)t3(ig~%6t5wtUkQlJgH9j9$>r1?Kiw{&mEf0N?z-U|i)BF|}AflsRGzc_M +zR<}~kONH?SU`n?362_36f)=_<@OYPC%W8Y=uCu%;*-(+7KIAPz&=8Wnz}DM6PTT$N +zpok6O9%{Pg{QmO98-;pK5avqwV;)ncnPZ|(AWgf5E|HqN7&cwvCP$VsN>pT#_wuLW +zM((%BM9U_5PnDcKdI=l?0}oVKk1LUt3Kc7D-o_6MT&+tQzr&J|+v+G`)X5-*et7Yb +zNqB1g|M}Bm#9z7^BMLXM=Dpo-YSVEdHlh0)nMta!* +z6%1B`QX-tp6TFX5`y?j8oV)ptrwOPOy4d86te3+H(jB1q+9u7wY}?5xD)?oNI*~tM +znv#;i9so9-!U<3c?-PU5e2UJ=B +zbOyLeH>1%z6|4m=Ip@J?>pHN5$Yr7$V#{ArF!>R=8>|dTln-gmxO@@wW0mV`4&^%L +z7|0J|M$P6gmdUa7Ed(}EOIoHh{?3VfV*Cy&qt3JfoJoijS+LS65-+OYX5%S324^(L +z707!(ZpdHF%WccF95Ekjsb&rkYLHoFL}KR=5{!@S4luER2xk78z>Cgd*>NBVDy*xQy$~qiXa> +z!hA6I$t|iID;hy~?@E5}hjuI5pmOD7PwQPf!_`yZ{0tH-II+4EvI`57r?u;rIH4o% +z?zV9M$jyz3%l2E0HVj!AI9C;aF`I$`0-%7-oLte<#MhBEe +zjSn;c!Xy;`4gcXiaoLQ02Y5bTSQ}Sv;4?f|KY+|8TsZ~OT +z9mL2dpoTqFa5I>hwyKHkJK#D^yloMJ^2kkOE8oB?aR%U%SAcldf_A9Ocd}>@g#(lzemS7DWw_nTSIH@M4G%DFQ1o&_&`n;ioL$7-t({V1 +zjosF4Vlh>vad?1q2EkxzRVcJr4gI3!vbEgf0Z{mnom*h&d@>|7-?q3Mb)}QUE5klh +z3De`t9!(=q`qz5lm<;p*@c}@NwkkBFx3DMFJjJ8wrlA?AU`{@4n72<4CEtexe7CZ_ +zXK4C+E6%-V`^1XvuG+i02ubH8rm!{CnU0C+KyP)(`u8;^cEcRKnCr1c!YyVCun+GH +zwVtMHQG>0;5zWq-F6#hd-4SaqE7_2s8ly-cUPnvft0XLL@#Gs|J3lzBfq)b%n`W21 +z{E-pErIg;YNxh!7tCY$H9ev611`Qc>({mK{sXf`ZAKLeKU}JSgRJ&l0r`#HsvZ8Mv +zC64zd2loPa+rXa0*Tf?Bgmk>MojitNlGQvO<^d&79Vt%r`mkK`sm8M`S?I!aRuKb6 +zNsCeK!okI)y{?moJH`#3rdr8vI-b}dTJ@0|(um)GYAoQz9!(TOElnfgaoAf6OsJR@ +zhOr#Q@TCcA?85>fhN%0Q14ldQL8Esfwgl# +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 +z;7>IWdr+67B!tvXR=BrD^(O%$jP=|(PXK}5U +zpic7wVsGMn&_g!M5si9AU2U>^ +zM$~_yl_#MUE^oPoCKXd@kd;6lgC6=Y$u`s#>LZKPXjh8fSlbjWL(b(WaG}=(3wY3J +zVpcspKT;`~7Nb_SB4mV(0Fb(&Ksef#TnQ$v9HZZd2=gZK!^-))3IA#@YSrJSv)Gvu +zRC4R&O?ai}UpnB`mYC>&C^sKDWbUyVq{$Z#0A23Qz|A@%FS$pGB*amC^t-W2Saz$- +za`sF>LYvb;i&;VOe5Dw6e2HhOvpn;!wb$ata3KoaJY~c%CNcssyGFwt99Q`1vo;zG +zAs80+Q5E`ov~dUxZmcsNoBNm{|Im@Opa4k!^P#76Mou1USN~-?Z>P>JDWRQ2vx_Yk +zT&$RB(5!c4g$NMsjk-+ybG~4d(6adrWGeC-V5ICG +znS4!u08Z!o9-;mFXP@r?a!zUdzny2Cmf^pbusu*`!|+$h5E}rgWXBqg>gWdJv7TCB1Ob57dwmzFaqh>04j)YB{f(H~2$U*fV$+Am&+V9Qi +z3X1?DWo=eKX~{Qj&v^ +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 +z*{f4VxBgN_s4gTBbv@P)+|GDU=kc_tBZw&!} +zaxa#42|8{w+}BY0qFad|N!y~Q0O1nB3fL@H3~YCeX~hE3seSCXtHKbDy=$4!HGp}_ +znSnA85Vn;&Lt-LuZpawni~$ZGXQc2q#-I`=+{ghFTRD_a2t +z9NhyO3d0sRAs2m3oV!j-xcXN+p-_-!aU^N#TdT>TZAcoB|9i(o#pEA=uBxikW#5l63lUn^B7Mjaz&_|FX^RWTW~3)xzEF4+?7qw^U)XLWRqZ+C4;tUuC1!<%xR@ +zY!nAy)`-^sAI9EvM{=Y|5`3Qp7*m;*)!p-J-(&zIX>>B2SMhKUI`ZLHMO4+yJgVly +zq8s=s<8smtJw-*5Z|>~%rhz$-)-v@gp{1h}kF?*RJ=@-mulfDZaq?hPN=LbVt+cLW&r9D +z<=^X>^uguujVIEAVVWEUtno+G{{G$;+(al_|0)KG2iY$1Zx20n)4E*nEL9@;VoP%6;0iJ)_+`&B?F)&5(obuC|xI&x7$=T +zAra4-M4Vjzomq(YgdabRkC6g>;Fj3`b_tr5va<3heJiWP4#$#mNUBm;fF{|+4LQ)?z+Yz9E~ZfwH2y=onFqM>SSsvbwt{OJPR~D`MoFtrZJygQq)e@+?bhoRmJ) +zllm!)9&|Z#N1e(@oa{DWq(+KIKnbW1=a_;xIHYEb2}5JCzj@$KxpRXHAi*q6=YEbZ +zOO3fIc|1Z?Y2R!=ND=BWsKpfV3jyaGi!x&lbA$CcwDF~xybvfLe`rRav-q8lTU2virukppLd +zmL2j9`Kt41qeu=`9|O!KT4rWR$;}deCErL(5=8QxrdN7b;)yQJz*(nx$3si#lKNQa;gE^1khxR$4!x{FQ%QMi +zZ65H=#7#|+6caePjyyE5`!I^J_2&eK-aciK7qRSJ$;1dc(n&5(GJ-_C*AZs_;J;Ojf((0pX +zId15)K=N2@HQ+U#`|p*kz6ml(rgQl{&Djqtr%Sr7A+Z8dHmG6cB4&Q+#&{fc#XiII +z^aG+;e57a2xTscNoj5WyZS)pe9Z6z|QDWFkZua$-Ko!C@V5+s<-SxXlFx7lEaXeARD>9M>C)=}VSIe74VWpcg&R)~v?o +zaJ!AydUoBO&A*Ql${_`w6ETE3Y*TTd2DPl3j}+#Qt0c*yK)spEbA?S^5?Q0{_>m>F +z@1wYx11hznxl<)$Ub;^SX>OPr2x?nOSzF2F5un}=MdaR>eOfxNi)rl-Wg)j461~NGNFlBmJgV32&P~6BJ4hgO###qxx9My{ +z^&Qs07W&fpE70y|N!=rPPzVMC40vFK*}8LKT>+tJ*4?ajpauK +z!gWb3P1dIHcIEvC2its;PcUG&1fMWmloZWFa?7G@ZdpS;`j4ojNRs`I<7)v7C +z1P9$f5xFdQ>GZ>fxKuJHiHZx6LHo{%@t~+W)ZsCJYbwPU+9AxVs^K95?xFy(-|MAD +zbIyVj58S6)p7Ump_ZaReYavZjf?2XqA$YHEf!l}q&Mra0StgIzNWTqP+PQ+mGSv%G?LelL?7XtAs2^ +z-Y}~x`4G*LgO=yYYM5CdxexU0rErow{{XI;A&?F@$v5AYo~I?*1295q2f-HTO%{;3 +zW{amtW4zFIK!gw-_Puf#5U&k$UJhB6({53m9fSXKFE2fcE2U(K4*0@drzWIMeq-t| +z5LMyW*4-KG#ikD?TUjnVr%v^(Thl_kDQnd@hz-i4ZCFsH+>#u8&f(L +z^q5%upTq)9XU0*w6E5UQ8%9qDiE6N1R +z{xN;Y4f&MwYS?VxK0Uk#0m)SpGLwV=CJ9}@f2QBxkQlX;@0*V-tY~K-sVwNOpq(i( +zdWNR#;qkasw86svaQy2*)ZYJk&R*ox)8x#hNLz+u^?-zd98SdC?xO;vbXlk}SBtt)K +zWtBfA1+iFpl1Gb>g|bIjBt3YBVMtL2>WPN#SGT0KW2+_G`%1hyd(5d}iNT<$tT^hd +zG0+SN~#l#YcjR^tN7Qs9a_1KOt&{$yS0=l=O` +zteE0g(Il3$;#{q1gNb|CfBf~wAH{~Q66P(LuD6a5IwQ9L|9#5-pP6p<3pf?8b!4lV +znF4W+Z-tV~POm3EZneq|iZ$idHDD!DfjXi`u +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 +zJ1cepAL6%cgha*mZ7h!MEMzof#*^F!2t&Or9 +zkO#0*K>e9vqkMci59wNs_=svSlv-y-qfOI(m^bXO*JUE!QoyhnT!GOuff4NGru@&kcv7XJkTt2uutxZOb)J +zU9!)_@FB79W1K`5VuF(6A>TKGUGs6Ek_j0-hAi7!nvn3km$Vml(UBmMaS3#`&K^?F +zXZE|4VoM?`%noP#!U-NU4r~&L>}q=3&4IFfp08!aDjGRITdhkwkd>s$-PY3=Js9T@{PftYqYpMBF!1`ZSif+BPAfO5C~}FI +z9ddX*5-MPLu9>#S?_^>DRxeFWm8kv|*9Lu(b@+DW!4-)e@p*nf<+EwP!?i&G{G>T$ +zYUSR|qliw_%GNG$SFNSoIJ}^rb-oQkD?qv!0>*FFK`0@DF-6M|YvX<8tui79{#5SO +zcY>ap>3M9bU%IC==_`0UC)PL61(&kR;-^{b%PpX5JLbt_`dP3#ONF6c`{s +zr;*}2hePO~p8>;;tF5sY7zpqq+5uX2R0xQI7`ex3NC1?k5hUKhArJ0&YZ~^ZtQ0&l +z6*Y?gmySC2-O)vIPb$LmE*KfUUh7M)pkeNI)%U)h(Fh-@uh)%AxUi*<7-7UJW-9ck +z*-3Sg?^;KgKiG+!m)ITo@Bg-IpdL5(p#nM*rxMJA5uRnujO)p_e}P9nI3KIOj8tgq +zX-N3SjWIiD{pM7$1+5W~29qTrBAtadHGr0YKU~H6)S=9$9J-52bg1hmQGbDa3Bi9> +zB*PAK8gMRymng=!^4CzJd~KyzCiFfhU^{X%i^q&VgQ1M{Y{};Ri?OP_M6NnR%P4R` +z+n}ZlyTot*Nf17MH=r}&wkus@j>v;~?8U0u4!e2FiGj6AjOj4u)l}lTsGO5fYhq-O +z1+=TvD-UIy=C^>6DHiC!KSTT25io4lV +z`y~MBjD?V7hGj`2dN7e4-rsVSXm83fxd~^K2#{pBv^b=^;z@LhxI|3ywu~T@YSNpE +z9CA>l#<6UQ=qcRERpT?!d(G+30rw=)5l5C{O59&w2Nzwv5}@4+qhZKc==%QG{GH<} +zi&prJI=PuVK#4abzTj*Q6}S3RB%Qa`X0FenXb{!w%XJmBR{JtlY`=ln3XY +z-%Ozd!YhOBaPSRlSbqNafE>c5y~7ea@!7(Rig2}_>=e+u-{G(<(Jzw(s34Sl-H8Jmf9Nc<_VF9 +zwW&8%Sp-6}Hc28VaE1v6orB5lsx^vMC(QY}iHpw+o|_w-kXf3vhi-Ie?-MXufwwH= +zNYT|l_Zmb>wkTf4)#qXNzU^w~Zg%%z_QmER;4My3&gst^$iv6ZZKN`s?ej<^#054r +zuH7dIY-M>C&AUjw;Iz!l^zN`-_N4RuK07o&%IPqdzK8@^@KMz!yI!gPD*c}7CE;kZ +ziu&Fx{V@Z!tK^fc}m-EOD;(AX9DOVA4kcmzTTVlgBES?Cf&J6r)T=f0+ +zWPMj7&%msv#XWF)rKC}umCpa7->g$Jd-`K;0-MK@;kWi-RxT_1zax85BO}#ti?Q_$ +z4p(5<+ilE$sE)_!0Xo>1=Mw|+oL(0i^(s^gpL3XASFtvKmY(-o>7yW-NU{%5z$o3&smg)>JYEQlW<$e)%`2O +zOl(5JDS{ky5p=OwWoV=qJ>1M?O2yz-A@W_6c*4X6d_Rgp{Ovd)nuxO^8sBj`cANX4 +z(j6405X-^FZ#b`oEEc>}DRSk;OB!r`fQ*Zt<0OC>7U+wy&(U5nJ1E-V6>`L*)cI7k)BsP(+BVq=Z7DNH +zercyI!#EVjM*rcPprhG;eF!tL*9BkM1zKgj!h`u+fV;g~kXbuIU-@+NSZ5eB7qL+8 +zUCH;UGOD5abC<>xToRrC*07(Xg_!*l5gRd!#nx +zXM_MKa(D|=C58S@D{dYDWU*25)Yq!EN)~D&p9DS+9TI>&fLqN>hk~np*U-7sDYq6d +z^9~U8Kh_dJJATa|o*0R;99b1v|ErV@CNqNfQSNNS+`9veJYYy7Oh%H0mVdEDMGvpP +zGJ1w}0s=aWx@CT7DR12*SxgULBGz{dn##y-H+p)LAgvz4Ih85dpH2Vwy +zc%^vc@4Ap9=^eTv6;&P_akg&w0>H^q-q(ACiC1QpnYGI-Pv<=Fpir&542Ov0u#w?Wkgy5-ERaV_Rld1D2;zE{Fw#2fMbK8^ +zkObY0luV3EsQF_Dt_88qtGFc^1N>=n4Vqq{mjRu$Pfg_J@oiRcYGoIEs{1OWo)*g8 +z@-qG=E=3=OMNYa)m$MFy2U-|Zb|4&*8MP4loRr|m8w#3App6e;-Ght32k|_QSSXYv +zGKXZUHGN%`6X2Caq+_vfL^3@k)9Bj7I}p%mT*{>s1y@{^mk}f$>|d?S5f@kZBhw6R +zYhuGo{b?R2tv@&c&ej`FU-@9yemn?r$xC)>XNe+N!@z`LV<4EoAjm}^L2E1v_LIWKL0f+B9!V)*dZeC;Q0w)kx3=O#V +zEQcmnP7uwF&K$RLdh3F>Z5L%cM0ypjfD^>I`E+$u%k1EdM3_hp!$)vSsO=omvV_IzS5eNL$$@lsZT#tJn0cl}; +zB@Gdd;FobU)-LqV9d^x)i{qhtoB>c>-5~%S)ap1!(nctRg=#yyk5vZ)pjp7@(w#^v +zlcw~vtAc#(b3-blLnj7lu~~2%vhg|{b0?k6p^-mScm$JHKj(M90UPatpqlUV8k +zv>E-zc_n1vHu7hRmw)p7ZuHsXfqLsSZW}5#MznPWE3_O)DdbtgsTv4=>C9w)m6>Gk10~8jnBn +zCi3CJM5jKYlY0trjH}!_;bA=^D5xFWwhlua2LUKa)$3s +zB@s4%{H_;o4ljR%OPN0LZAt8G_}W6L{M&|wEdlZuaF8)hIMfMC2i?T>p28NH5)p9? +zG8&^sM)7}&chgg_g2^1g9@pIsVu(nW5H>bi2S8l7mkU*Fqcb%8HlV~~JfG$=(n~dVh4MBc +z&RQfKPJ)y{yZao_mjYAap$n9qPK|Aw;70)lLr&6XOhz-zNee-a9#~XbMhJ-b)v)(1mXw}cMZ+(gVvK> +z_F#?9E&K+tiuj~BqaED^Z0NLaIHo%LwjA$%=Q=?~_EF`PW~@ckkxO_dWx*95oa}oj +zoR**GhEgdF++gQ%zai_~;YxSfi`)=U4Kqy_hLRNz{gJNLa +zbT5J}#CuOo@knxH-?vXZOx_Z$nL9rbtXaKgrAZFj;>FtB`IrYeFZ*%_sjrMoL7sP# +zT*c1viQ1wC%O;%OZYVVeJ0hroW)3O4zBmc|@D^`0^D +zYdXsD#qmAho9CiDe6Iie93I{W@YOQzg=s496o3mg6dc!5NLY^?RBER)^RN;t{aq)bpl>VMU1zn^sTpnK+)JoW1wE~oI=VP6v{N<@42hht$vk?{1NbgQ`%9@9&}iR#IJ +z6y0U;Gih7KT!G&qj(T=>c!U~POf);P7u&G%rxVHH7~!8XVld@vjp$gIy=Ab%I`OQ) +za@IF`q!2Cz5#KuU(|-a`XuIu>i#3N9r}>Ada_isa|IaJ|!R<$v)l%@31fzAOZgN7< +z>4^CqHwp|W&%MYH(P7JqBez}#RPGXM3wY7OJ%Ni0#Bk^Q-N4~6e>&8u72;Y>`0W7) +z&EWexiT>^Q#Ss8z@ZIeJ8^`C{_j@(MBY6$1J?6)X41DYK`{%n9(;OATs2k@`KioHV +zcQngvzBo9Yqlx;i%2@;!AtkoP??9D)iQF@U8acE-`}^~7^=FSIj7>hsh%6Oik1lKj +z!ND9(V<8UtgMNr26l3^8ZRhK5QWG0CwTpU73` +z{NycjAJL~Ik_^oW=W@TeH*pd0txp3krdgb9flo9SU)sx79m-aNRIVsd-*I8%VEdep +zg;+E)b$q(iEyR!lUT#h}N4ueaqbWVOlKPPOU9}&sHS#zh%)2Fzc&~OS`XSm2F#BMf +zq#=BoB^ZDriM>p +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 +zQc|3lS%wx4D +zYnRdk-BI>zb=ZY5pk+H;Cqg`z+D4+v){6J%B1GoVsg=Ev{hCC5xFzf2&z*>(`#s5b +zfNiPzn=2+*kI9?TI9)m|VXi@;~;VJI*7dFJQ7E>fCYtecHJ +z^}^ZAVmVl77%-Su5RSCc3bYrxw%I|L*X&Lc1oaol^U~Cb>KO?AHi*`$Oe-M}PRenNh%l5~inGNzVO9{U9;d4F%N&BG +zy;=Yr*pRddlD$F|z-GYV6PkEGZ`IfG3&LI9{XtX`z1V$J_`k@bTCYy1~k#mZ{p +z)%<>VO@3yjjXprLB33yYmZzix*+*Li|C*MrBICDent+R7CnSP}?sng7P?yvt(JgWO +zW_yU##J)Xm_BkuVv6PPB3Fa~rVy3`!$+AlghFlbBLMZRMw?*L`Zg#?l|7~Gyu8H~^ +z58dr$@@|ujuxwi2Hq+fa&L4Kc+>T#*6#_3}VO@MS?R$VhkaaY0-UIb7-Q~;Y`~BU{ +zbJ}*@@!Lv}iQeA+k0*$9sJgvD#h2~k&!W;Dj3^2uZWHSW=MKVFpSvMvmtb%?kWtXO +zy$NxG&P;Nj7<faR8?r8BR7ioKc2iB9=dQF +zMgy9OxgdY0}rlZN0Cr|e6s`}rj?_Y{&c +zo@mhhrMzt?itHo_v0x6lwZ8C92qzf(DtKfd8wu5*@|o=t{$9+~DX3JDXTj9G$>O3Z +z6}+x7#I!y*mo51i`0o}OuIvLf%sAfQH!vPqs63T4qMynaDDAcH;5?ML?CVH&-tshG6?SqJ>z?j5UjKlt@hWOcOHfI9G)ncEa8+IvD7_SF+W`zT3|Mk=}m(!z^AyA-cV2axmBi087%2oek$jSV6 +zDk;GbMB?IxM;Q3vK%{oAtH^&>z~fIw)A3gwmJTH0EkdO??GALhC(L1-Ls7oQ3*Wy~DRi)Kx +z8>IDWyDoBZq6An~A?L*`>Uxf>(eV`jiIhcppP77{-ILVtnI{e82A8b3C6Z~t-uCCn +z_yQJ%_@!PR!+E9Mf7YbQY2VNwQ!XGC<_RJb!iZDN@dZJ!O>M6T47uR?&>og3(@YNf +z7qUm6unA@p{=s&d85!!ILZf^i%y~U|!lYJ3u5ogHN#=$*|I+2a<;KEjkWAH1P6?Nk^a{Pzb1JGbGFtyq+u_!4yC^ +zBV2BiAX{%jpa*vvv&BC;s`>xyI5a{H{C9&dP~5=UB~B4Z`I@n8LXguiY=l5f;pF{D +zVv@7nmYp&5>Nf!SuwgA&035}`XK0X1xYZ#q32GSWIv*DTnQfPKm`f>25Tn}A`#B{7 +zQJfYYVn-7^pe7+uu&P)mx{aNQy3=rYmWCqd;Hi$w(*4$XrptzJmvg;w^$)W%M-f=0 +zhrAv3*ALG}bl^&Y*Wt;ORXy=SQ{CEy7?rG!OFjTaTxT_&Sq487MA}IhSkp^g;$o55 +zo{xbi)6aqZu>D>HYV=~O5kQl)#79vQ9s#r{)<9gaYV&zGhSPvw3Q-U85Iyc8FN#T +zPB>ZlFWj!>pJTh#zEr`IKHRN-WYmQ3`-GJGLL&*7n&bQ9 +zH^vd%oHnar(+F?^p&cyw(8*G>MR-tLj5D`X%|7yN>i3uCv{K*C+Ls6CQ8C +zy8YA3HawsBt-cR#d=3EYEf_D)gj +zvm2z9X+i@e?5C!a!ab}8-gCJYW#`HZx*Qt?xm&;TEuu8^r**k*Hj6vj@cRK$+sOp5 +zlYT-L3B~BiMow|6J@=9PbeaeC9Hwy^Fe$CL>sSC5ilZ3hQf`gaHgOwX7chb9HB4KqO~7iC&t0 +zwPIun4-I8a92bGpm$9a~B7f|WRCgo@voEVAqy)h`us8vMBeIg5KC5z}$BHBQszXn^ +zh*0z{RjNqPcJx|KSaDcfN6Q?T3dqH9mxe%yatswc%?!Jp05q}5ADa@dicR^a&Eq`# +ziAgfDV}D(>JnO%#N2>DW5S>Fhf~@Y#YJ}b_Q&8N}L5{o7f=}A&EGwJ)P}vFN?XB%e +zUb{NsG^c=IYl~l}Zya5+uHx4!xvc^FD=})M=~7zPrGY+wZTlwU$Yf-&rENG|zGnFr +zIQqu1v0$f=8bG^&mS5G)8(WMI(CgvBrBOF2f(s%~{1Zd0>m7^d(v +ze)2KqM5nE@bovftN^s$2FUZ3oZ6m>r>vkPhU0t%Wm~Zfv_r3gmcoGO81I5*l_|>Nl_wX#mo=nwN?d2L+;%-hILGtd3PxnzXTB_ +zK!DQhBi}LG&nn(FTLBJ$-~ILLWXhIebU~GhX4ZJ!t(0@D`o`Rp^Di5r`G1%kVeKJ` +z)37>4cPOJddZVklK~;4PMVcI6B7=uvraJbY7ZfN_~!XoN)2 +zlJ$fQa~M2;D8>_p8Z?cXB8dPmi-V(%)iYC{0pbZGx=-h>;; +z+FE+Wbi%We&WjRNHF|9Z`AF)QQR-TJgmtoPf5G=7d<+Jz0GhZ^wJUXwd(~1NHFK5 +zQE%QwT)ug@_x=GLPXC5FYGXm)r02Hb7N7N?rXeariF=Yx(3{slqiq!Cs-vr1%c&Mj +zLpMA*wfu1vV1M3rIFm_qmMu36F9C9An4r8ll7A9umwdqDEp+#n8`$&dChCAo(^o~C(r-)ym2lBNdy +z`+^+Io~UvzT3PatpE#nGU($;~I?u@zCZ^MZDE0@kaoZ=tk|1m7Y9ucZ +zW0I=W%PpNbU5mp=9z`wF6abJnEnD0}Cz1i*nS4Y+x%|X}V`A1g6-V}lHQAu_FO;Sd +z#Ee1cKYjt`xXj%&(OKg?oK2Jt-7uUSM(2o!cuZfsm# +z0F=b^V<9guzQGZzvl;u7uX~uXIsSmV;fal!;OEnqltV5ld=u=rjC-VAWBAlT;f3D_K!E0OvqmdlzB$IgqtsJS2&V4ORGU7mT2*&5gK +zNQs7BR>@13rJr`9z1A~kW{1cKf;DiJAKKazp1U~L;r`#)dP3T=0}&w$+xH>-y{Z;3 +zyNc;gz`j#p^tuqr#OP4H02UnyuW85JG$`8sY- +zifvbtif!Ar?WAJcwylb@^RBge@9rKwM*oHRWzKQW`?yZca3)HUyINyo%8UsstAIVb +zi2`b=rWz<}6np5lbyD|IM#x0bASQO!m$07ZQ}6r8=S7ww`3AeB@PAgRG<7A9U^8+% +zh{kz=??_1>yeF;ojCC=;e9&aQ*N$dXm{|>t9@*pJXyy>(o;-$&{~5c}ZruiBo01{^ +z*_m^zhg12mqw}QzMo~h=w;NNSN%~E};bK5<4Q+!TTPks4)O7sJ{^D(FEuBJ%ql!8e +zQAd`h8qo)IPs;(IqBd?PE6K06&u*+ZeQ-E-`7VuUxL1vxG#jtsJr`dhVrtSemHG$( +zLmEt)NX81^{Bzyg+H2gzHH=&14~srvKY9m5S$6Uf-fKP`;qCy}v4L=XdE>{|=TkTs +zuy7X#G!7NSfN!n%YpP12h!?Mnk4xV?%P7#?HYME`WdVqomuX+AQf +zZN<@l$YS~rStJ)dRQtb^MT`GU785Lg$l~!2StQ=uTvbpzZ0HRq=C}w>mq3w0BHB3ZG2{!JvMm)i=RCJt6 +z^Q+)7=&gKUmTU-SrtmxAtgg#q3>fZOp|00Kw-6DdzD^#hyvb7jK3QY+lzNgdV{Q#J +z5?hwza1%&l%8oZWvmi3!`-RK9FipluxUWaoofh1hUG<%e9LT$(Ws-%Lk6ld$U-LPZv4 +z3{QB8rS-~__>kl7nW7fSLov=Q$QVeB8DvSiqKl2}^MZ+lqG0Xu(Q0#yP-v6h>s@RN +z@jL3+ai(K^FElReI%d&-b}7?>Yps*KNVK{7Z|hN7aFlK`F(}2U{r$Q8K@0}|8s>hv +zqxB>ZgW!oQp$HT)Ui9L167LC=nRDk} +z6WbF(7>}z+K10Mpzo1i!3Nv=;8qPj%dM71}768V(wo8fe-{cGl)?Fv#J8K!U)~BT{ +zUg&yS$fSNtpG7|o9A~z95-@vM(+v?xo4tiZ3cg!)=F^yR#UFOlL8%>9(GlcMcBVhM +z^Z}O7zgJvidp47sTR=*Dpp>SDY=Fkhdw@6Hi;NW^x^#t+2vG` +z%Ihy^Vl=CTpp<^LgH-Y#SQCb4OSiwLhfpTvP131O9hF~V_eTDUkKXganThfA8z|{W +zBPTEqTBnfKzZ`hHHKd8#PI3SBeWX_4)A4d +zJ`K<&04$tAu^O{@a&_98%2j0A%{5ChI}~9TRsSU-W=a0!QI~R>f*9(is#~hG)~|Mo +z=Vf<}Nk%;!!7fM`{VNpWB%Au;#6ZJ7PVq~ewW@);)GW4>CvIIM4lU>ZJKya5ZTuJa85MmD;6yn97 +zX4;=plhq3Tgvq(qogwu*DL67JucxTO2hq19p=N~6N|AFuKnDDX5BB0-+qTq_UioU3Mu3vS3R_>l#W@X0hXdSeOEF6A{EP*8#7^-lQYrWO9D{2m +z7II56cL`Lxt01fSnnF{c# +zYF#1WiZPq){F)2;sM5j9m6A8^yp-wIN2qz&`Syal;h@gBsv;c8#LAYyOaeR9W4aaO +zrb73bpocBUn+_S{;q-#J4FOjrB7d9}XGl&iTTBRMHma!SA1%%snI~w5QY8J?q +z{%p?G%DGa&vxo65dG;afD__i)UMif_)bqAi%?wICd4(MFDtEk8FE$|1a&=C$A=)a< +zkuN&yC^8Mlvwwa1CjHXvzd1sl*zZCp?**^1UFE~tMdRtH6@%1|HdO!IIx!r&%tJ3u +zyiWPL)xbB``W!HxW`uxXg%F!{#U4Z@j-`GOK>|cQ;)|_rOZqrn9a(glrw~t}$YH!# +zi6h1n)qAVq^NWxv8F3kCwH)EPWNV5v*Z9h)rB~WC)(M6>fQ+_QA^-jIq6`p=khXd= +z73^~DZsG|An*fG~0fM*H7YWleJi0&!{Ez&!4w~N!HU=!j4 +zz?e$47_pvmTu56t{c|z2NYk=DzoX$kyW0Z +zZYZ;cDPP?@jJ +z#)rcgQls9uvdbg$BpWKgBuXB9acO=nJk +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 +z;#L)0@)HhbZ<~3?~oB=Spa0 +zAlGm$rSi(9F(5AE{9Ygh{zO@rnJG1f<=)gf{xjT$p@RPXg+`HmCP5dLzQGI-_5+`W +zZe&MQWX1}X9X~1*9m#EYY`{F&*`0D_{3~#}sluhe#LOM2`PfB;ojrC>HgJr=)qkP` +z{t?}p{)-ddg9SJZf_qwchze*DDhW@MRy6=a^503;kkW|s*KZCu^1q^tkz`-F5MsF0 +zUq7z|3u;9-b0qWsB8RxZ=+@^jYx_dB-{X&|c+{6lm%xj2vUoChF8cOanDBjnKk)Az +zhKvW>-S^Fx841%Fvqx3HFR0U +z@0?&mNpyQjBRK$Pbbg}mDRGa}%y$xgnS=P*9!w=?V>ES)5x(CZSi$y!%UY}p-5l*W +z`YUC>MUG*YVBeIWR)DbLs)BnwB&{sK*^pBQ5bqf2i`1{KVdy5k*1Es +zf;oitr^qt?Hlo2j3W?|i7RBdtQHHj+v02%TCRJ#ySy?AAo~c_$OFwqhOStNV^uf)| +zz;Wm1WV61qnMw^nU|OfOYulb%&J@lRKHlKX*YZthY+nFqpTmRhov{zmn|3H$;+F@J +z%$p64+v{nXoutQ7n`;TkXoHAzMxeU!1K+%W +zDh>r(_Bnu3ds#SCS-``@19%y4CT||ihqK60+`9a=kW2xnGW+r=7a4bP3mn}TQ4`{P +zfAxTZM#XnNv~*W>Vm|*^#v}r;q@qYg(!jyLwSP&kdrGHTXB#p>W&>f3SY?7s^4c7b +zbk;iL(2O=oEfC&6{T(msInXyxgyVwddtHs9o>hm1+%f4q3_PJ{^hS1o@~tXA4w$~l +zo9r4X2M65Xxch*!pTwLm;*7t6jT$RMnchp1HsZ#cf@Q*IaL7W +z84#%)QO(RLMFs1nt;CqOQBH{`?8L$5v$X~|Kt@C{H+(X34#{hle}2pAbEenlnXL!v +zw)O8ka6AY|sDLAwsNkTu>|iH_@z(3BTDmRQf+}-T0yAvIvtwAeGyF~rAC5_^*q+F& +zR%g=)la?~i|Lti^Nz?gqTcIxVR72|<%|ifBBiKJkQ<7hE_{z#5C;`9Hk}_-AVO80$ +z%!j~+{D)Stc3dS9Rg)f!+rM;Q`Y`$$NaI3$ki|~sl6&5Y(M}xtBUfj(%J|8?q`cK)po!R1zk27#>12~*=3b`qr)EsYJ` +zBbD|5#`?IRv8<%{8|}M!Cx3Ed`;H9_h~5{oz%|QZh*W9|WfKK%n#O6_aty-ER6A}- +zMv2-{W-_{-EW%C)TDCIqYF>qV#2R5uW8F`yar7P_iB4YZSCV|xo-KcijIM8!te3;3 +z8o*%$Q?ZDIvP1DY0;evLd(9Y2*!-9#Sn%Mf`%6d&EH_#OfrcpcG2@GtBkxL +zd^^C>*5=NU^Ah}%Y~=qrNJ|isON#tf%NXQkM@xKGw7=2*h$V&}j)H0KP#ZY`9jO<~{nZjN(j4 +zWB=3q=>`%pA3T^i7%&3qIEXd|`kCt0I#pfdTg{bccEsxc_SSXzTM&4LFF0NfAlDir +z5lT=#u>+)BBIAZTT!U{SHG=beA5sV#lWKIUyB9XqAbsk=cnmr-tW*FD-EO6%{2Sfk +z9;HZ9@vE$eSR+{+vUXO4j|;Dy3|vui3L3;bpVs0w4SCmGjhh5N%~l4-$dWreMFklD +z#B9>_D2dx7mXtPWppGv@KiVZJAHC4|5{w*y^_e$}8Od4|aXRN+5yvhMPwT}nn6zav +zV-lex9{#&7i}XwZdjXuc8q0^QAHr^-j1882-_1P`ba?>QZMcCAWxIb_6Fi^LQzDfi +zO?3Pyd2z$gBtMk@_x)2HAuxK84(CWvIyfzx4OrW}=&Onr!Q3CE>UiQ4eX&$g95_(U?02pX`RCHjTSMuS{HU@gktk-8yQOf)SK&e4PC=ycO`=PtPU2Qw +zt)Rz;nKxTv36DWe28tt)d?+9Hhv#I6%>6j@o+275suM#r>njGr(QfXsAvkA@_aXu$SK9SKwG8^IU@Xk}U!vwZ +z)aewm5emz`D$3gSKUqe2(uN}s8A(eNND89jIhcbw8K<~Ike}wF3+@-yKS9*bfrzX7 +zqD%W-x!is5>0bv1(@3a^v4azq7}c$iE+NlqHr`($>G&DCl6(Yle2us%8YN8pQd=b4 +zK(X+Gok~ML!N-Ze=5}U +zUSyB)UIV#^&Uhkb@V-GY*g7;@hR`E>!KFM&GX2Gz%^>_|<*Bu6H0PD2K#de*1&z%z +z+ZqjoJ>u+MH+V;XOH(s>&QiEr0xgzU1c=Cf$Yq2uPnCl8_@7BY*Y2O|B>*VkC^JJ(-4t04Da!<1tc+CB +zUf4S&rvgOtU=Kzw=PwyapSL%>=E0GNpWA}tVfHmOd%J7I9Qyoolb#h+ud9;@q|rap +zkrahw7z3qx7<{8XSyg*;hLN((odFMj?Ucd554VV$DZ_UFb0V-8M&b+Y_hcON$|WG +z-NCuH_VQKDW$nfmS1jJ+sZ{WWpW!7LO)l#dM2;LNdw|)iKSI}kRv(@0jYK?ptqGLW +z?nvL2Y;v4d)SEN?ss-K@9`_GaUuekP|Fk=es1iva2Byb3(D|TPwQic`v*AVbar$~% +z)MazzrE*CVe1)1aoHkHXp@yoSTuXAWrF_K(mU%h^HKG2zr_z}9JKjoLL~ +zZkTTSx|wpBIUx%VOiGr?rYPSHQhze4Ll1S0MY@?Hc<_JIr?9pTT$QZ*h6}WdDxYbV +z`G&B@5A`GW^rfdt5&AU`0qYJgj$flYkCg*~1yN##j~6G7`H2v&bV9NMA{{{%(J8Jh +zAPsj2=rjWArQSV*pL;SOM)KuFFL~A}a>(e?P9)=m=Sk+tBpVmmh|E)8OU@;MX4izQ +zmj{P)d`+zTCc^3dfv3;b4f`D*OE +zT3@$7wj)&mKlAyp1I20Tc(m5<49A~MEPqWfgw(PgQce1}G)feQpsO!EWCI(I@*dm! +z^-{PxqSjwd)(8Q5K;)>GG9Pm7WYmH*6Hd^aMN(SgdRn%zA*(FeD&SBU?hx0Q`|8~5 +zCwTV;6F~vsgh%k+JTo5BsJWBuq{Fm*m4^J6MfUU4XmRAjsU~wH?ib7DtfZtTjHlAS +zV@o!(X#0y@+l7^1nd^(g4SyQ)&#~wjrV=}Fo|3vv?>hfvx*IE5IuE9{fct*EDd&5H +z{bOx^D5Z@+6!WtwZku*7tgQuUUY;mki}azfo6mVLRH^chj`*`?^`cM(_1${Yco^w% +z55ratgNOQNIO?i-VVLrDO{Tvn@cl|m77!L3)E2>c9tY{*Eatu>t +zAAfRPLpfoS{)sc{W^*LM9Y*I?SI;QU0hExcf?pc*@#JolR +z37~zB!eE{5*^TQ=tfrU$-o7~?H`FUIJ|9JIalsN-$f~)AL*GClr1bY6h2!Y?Swmqk +z-Wm?22R?VgJyx}FvgCc#+b6$|3VP$loA4$qZ0=An0M#lHZXb)`bJu!K3$8J#hGB>x +z^q#4Wd9esW*CW@`_pA)A{Gxgtsexr2o#11B#rEA +zK`K5cb*RZD#pdSGcG`MYX|6IbjY6$N>LQo(W~Ke``uxMo?tPtQ*f0s6CdW=Kn10+6 +zGq|AO;p}Wj#+BW&ZSpQiWha60>t<|39bQa^wkRTb7~M71U8qCys+N~UrVt$_MQ~9W +z)1nX3j3u03Gc(W5XcbVKDr40datb73Sr|%6OIN(?Nrx=2wO*;TZPZvcio->2a_Ka} +zzsbjN#8niQKC>ER>t}YUi?;Y-iueeEL5lQbP`Qqa8zk<3+w^U1;O9CIViRmj!H#|XD3G(Jw=dT3eJ4fjnD68(h-{s?a>G`TbFoZoDAIpGS2^iD=maaP99?nwoBKQ1@B-f>a~(dC4RF-t +zgBF+`@q-2gS&-6b5kl%Ps*wsI@w}iAHzT}Wmk1cjswv~o2%*@5420fa|6z>}BC!+> +z&CZ^69H2FMwU-iKHZo?~s)NrCWWA&kv4wNwj>5YCcyz7$x|7v*a6@0vsKa;A%=$nB +zxi}USmkEFgu8CKgM?O;-~&E^PseZ} +z&-g>H`&OsEfSsRkFDX)aQ_5Ah%Vy4+p&Sb2wTbANS)sE4;vr6dLzpa_B^9X))P+-c +z^2Z^cW7xPG1&s7gVDY~9fj?mkDiL;>=O4F#LM%VpMW?3L#_Z!PJ|iz6Hk%GT2d=Rg +zMi*?_-JoM*>SW*X$*kb+W2Y}(fB2%aPDd4$|0VA~Nd&=hp^5wZpj~MCdYnl#7IIh< +z4s7FrXOKBm*zUM*I*A)b1BWxNQT&Eb28t$56Vn?|A~9e`$wo|KPQ7Nc`lOWe +zJugyf0#h}Ws+RQvW>)#xi{qt`sE%zOb-{6gRXU1EPogxUH4gnH6ROOM#b$b0>(^52 +zQa%%ZAf+YGgWZu78^-vgz_ZMRxF(tSFwd(EOPU7j=vKVhC-n96OTo^K#t8~r?!>Q3 +zZ4}~-@IpoH$b3y!E`Q-<&aIJ}L)QC3D&rqk&n5#X>l6uDSK2RyRYc21dGK@)+`iDg68&;k9i>o1-i1=!y?;$( +z7iFyk%YVsb!4KrCR2>uNgmFnEX_^F9cyU(hVw_=zF6~jXhDRtVqFHw_tb8n`s=8^LPE(42UkrW-O(%cLXhI +z1ugTgIphM|@B03MCgeBO+0>BF%Yj^(H+Bqi4J?`QLX#C8ljxZ)H=+Z7186(V6Sd(a +zHFjU`ucfTtv*`h0E*+V(m;pP(Nb4^n46BMigsS0$nmHjuF-yxO5FNsPE}X7DAy@V$F*0;Rj}aDgAM +z-D)pS86~kKR=TcRcgVF7c#Pg47s7q4h&^*4!yK~pWbiXI$le=cq=U*??~`NZPx$~J +z_CUtyF0Mva(q7SeF(CFS5q3hd!(DaMa!aWx^IP#fBKNM|eabPL6LH1Qi8~dd)N}$p +zHG*4vm%t4Q3c0 +zvN;&6DS`E#=)i4KE%x%ZLwrDt;WUoDq5xrX#(>kvaP?9j!42>Yf@eO{ +zpc<#PR>Yqe$#@8&-;=%W_XW-*LuYd(SFrk$!A9UYfFM{sluO|;74rbjUyw=4H%QDa +z$W@sMh!~tKNYeyJ*Tb0|pL +zc~W={mh$c=y`<%#5BO7kHi3d8hLlRoyLTsWhb#VpC)I^zE2ERb%bAW;+jQa-eHDM-?BsN&arZt=BZ~iI0C| +ztF+uijhs~qM8wunegkrp6B5BN9d%n%rImZC_1*|lRod|xrLS)BIDYgl`B7$LZ(e9S +z$r4G4TA%hkaF+<+>Yv@Jp*yoOfs9OH#E0fG_3)X?F<%xKRprfY-n(LoZr!8?l`K5z +zrOS0cy{J_vx)e^ANbG1t1*8LtQY4i?9D*A%1uVe-do0)nNDJm&%r4qi%F+xv3?!N9 +zoIHH)Fw<~>6rsuZv{4*>yk64tRp}0Jr(=?0YTWgUR3TOzgrZLn1U=@1+)0@XRk0X_ +z8hRXiW8o4%CW^LFBuEJmC~5DuSJXS@{r&xA%(2YC2Y(-q2@BVh5+$G}JJ>8L%{T3t +z4ve?lL`LqMx&H2CumOIUar>m#vfZNOj9tnj2#n(9bWFu=p@fzbXyAvlM0#O|=mgkm+#i!oxa +zIwWeSIZ;CO5H{$N55@ca5A2b3Q}c?yqck*In+plX^FfJNAepJxdCH~t^^AU5_hFx-`6 +zAy$(0`#rU4x?R+uh6WgLc5-R^pd)CT109`!(C(alyzLHd3 +zMkDm7l;Uf>wl{brTyC}^P1tjz*{Qit(USl-#{%cqE>ou_KgY=-sLtbMh@!1EtgPq` +z8%QV&RH}$fAk6A#mc}Tst^hcaHUXxh1VL-`aw<+DNS8~xvOlayfnNEkG^$2JNUbv4 +z=F%!{=nP3J*AgLYk9$;%MSUhQ1}}HIdRDgfz2XyVI_kQ9V;Y);qlyPy=kVOb(%Q+2 +zw)l=%B*sM(JL@FMqEZl_AR^`Aj;KG@JJRWXVGR{n#laak_4+_20mnd@qGlo8(cxJs +z-c8XO6}jM3es_H!EpMRQjGgcUR#~i!mrd>@szt0K5}<;PM$ip;%&9Tqz2)FbV-r8l +zXr;}~Wq5N~Mz1)U1WE2IOpazf@bR{6#ZH@ni0kj@b3Ez;w>FOuurL)fSf&+$U|J@D +zMb_6-2x65#kliCmS)CqHVbw>SIWzln7A~1KiUCVO7Q!HeYi<25@^(ci0rhgy$L(G^ +z29r$+at8Xt=Z|+D;$!EUsY#U|VC94G779JU`&zK;#Ht9d&;vQ`$U>h4n6v%#7V3s@ +z><`D*Lo_C$0WU{>9Vz~9H@$$;HdfxgG9k7x(C$NKe8hw39TQA=e22liONIKhBt7io +z9fK?(#cSk`nbAC*6 +ziP(JBwK(!Dig-WzQPSQ}!J-y0UUM@w3&+ctt$>r#y&$YO(mckJ^u-qDoV&_XFWo8U +z<>xdU(IWK@1(JaLco2Rpn97Yd^^S4SVHl}5_Owdkj}ZyV8LSYZZC}_NNUdO-iCQ9( +z&_&EO;6roHW>PwghoZSM7yCj69jVg=y1(i;9klEx5RohwD5Lj9skyi9LgYMVgoS%l +zFT|to)TJc?(fvr>bRS}c-P3e-Q#O1YQsy>-uh7n>2QCeUf|3=^8T%W!$Tm-Ye`SzF +ze$d$quFz(nYur+=!K3V#DGlbufDeNN&d)K^B*}v&^MMtR6SIEhQzYw;;yIw{>h1pYbH=8zmnTtr^6s4iTicl>u +zJ9zU(g?0UvZtxI{QdjRFbPbjOy2q5(R<@5oE;n9{ecT&W4E&cG%9uMBufLAGj+w#$ +z#>S6xeBl{(llOOS92lC|vk^>=0u?iCT6t%&V5X5|6HR)cr(-IeWt%feO%fsd@&M#5 +zWr!>?0p=~uY<>`}$2K8IxR>^P$sI->TSZFmPyX@;KyFd&FuycsONQNU=vY%ND$Xx( +zL=92j$bM|@0pYMr;0jMp0{J7%E*I(_IiXVDA!%~{>+LE0{hvHzFkc*PC%AJYo{~mi +zQlK2y2FMv;*lc?WxfoZBe@Ku7WZjd1XpthZep+^tJIL`Gg(#{z!VW_$erk$Znqi#V +z7#Cc+;`XR*$I~z6h>oc@&FATN-(0M|@0;;U2uERb5(pFE@1PoD9ga{?1PWt9|6v>mPQIhf$I#J6=oFWKg8KM92Q +z5;Jk7!bS&M8m!52z3&Ja@GO8v`AM9^q>6@OHG$y|YCU!#%i96_lp!NvfS^LHMtL5P +zKty>*$`OHKHQSaX;9yh@Wh89r{77}^`>aNczC}6UioG5doZ-m+4$!AqE(pa?@oG~^ +zok~Z(WLxRHZe)um4TCu3FY&j3G>O{PBJFHI~V4F9$m{_mWT@>^dmgXyN-OpCkuQXKy*JYdndHBm2!Z6wDZ&rL?c=?izAJ*d! +zbp-Oe0@5vHC;FX`lm%Ir8ptjb&VVf0;||ZXIN(g2ibum}0A~41%dAds-!yv0b0ec`ywn +z8Ib?!N3!2gJ^)hXHwVw`YY`HrmZ^X=S^!hQHKQeTPe47@;02PFMwxA*fbv-s%|_B& +zcWt1JnhX0-A*iTft)IAyU&-7=lR7J*f%FJF8O=N}B8$zdQdkMPFL)xJKN#Iv)Im`+{KWj}tHrSksdeBBrzE%w-OXfuDQIdMF- +znh~XpUDfpkE?Lxc$n}ADo(E>pdvQ=?jR3+?ZFDR`7L{GD(6QLJ0BK6iO=OnAbJu9QSzm +z=$zWFkKn5_xO$f%Qry6@hz>}aLqfXZQi+%2M2G98!|+gC*_MXjnE}??o_;JA4wC!2f(jX*^Zx^BxVnU~I>F{cpZ#uN7FNF<3c;m%tN<~J0 +zFk5LP%c#al0A5M#S^SiHs5`L3nioJu4WY7{GM`xOXRSiO?VpoB7$F?U! +zI_a+8VrUq+Sd)4RFVq~t+EMt7waz+NIQZs5CG2AtOg6=)710SsIgf22^_(ihXzS8^ +z7dKTWsfc>6_M|N=dJKJH;dy07n5GAncsi0JTwS)2=pl;qBr&F(Z;Dn#2*CwM{Yo0# +zZjIQlrihZg`a-}`i2Yh+iaCigo$9;Y?z7?te22(}U?-!=Y*KDaNd){-YndrcW1U?s +zZtXfameMGDb{|*}Vx9CqJl|$dp!y_d3;L +zty2k$qlwW2w@5SVCCdNQ-a;$yoo=(os>ArVtozS@M=}-9HR&p +z`O>>DqC_4td}qin^@+u-f$T?h(!{`p)EUV#DHo{*^8ne3WUA#!TClcn7HR-*zzwS+ +zZ8%JFVqxY2$JDNxU`-N|D@y*5VE;6zgJ7Camw74$KjpJlv+lO4{W{|E{gA`lX`8qM +zyySkH&JFR2_T4bZ8$|myY{v30KT}3{*h8)`O%$=ncL~@n-?nClT)XHni#QF+)tgs5 +z>w_fZz-m`pfLL>;<*Yszlp+j9dEJx?c)3bjqDQ63ZPw97EPX?ZTLPA~opVm~6yfG~ +z&sCMNF{2<$Bg|&SeY?-(;=L3Ifr_|{)`5`QB2?>WR$KaFj3^83QlzF4{k<>+dm)+pOwaHbBAhAn#UgnOO>l# +zX5St+eqn~04MAq69<9mo@5BFs$FeX%8UBGT(60LBqko9rQ(L!a54DS=mc&-EeS +z!COT^5ZojBb#H@+D@brvG&D^?Ty;);5x9~U^0=(8JWUO*W~Y>v3ya^dc=hE@b_Zs4 +z+R~Cb)SRu~@C8$Y%6@yHGlOv{`@`KqdGGfS=8S?eO6G228dw5D_t=jrz>DsQ$a-_I +zM}&Tt;Qlkyh(H +z)+H0BmXlhhjKIO`Gp|qZXkY1jw`iizJEet*CfUTB?OcP<!>v41{D +z9wJ;OtGQr@Wazi)`W9^#t*1X5P%vr&-MA`ITIf+@u_D?)!eyVbIt*VGp63XmDxLpo +zM_>>H-H0w(;gq#$MGj{&useERE$lmxTT+9v=LkH;4pJn?%zI3lO|hW~f=35RI-f#P +zDsF>hj!-3yEkp-=3MuZ4^jQoR9P>?aE00EOCS_CDM!?%od&=^9k9@Lo38s&FDy;5B +zg^+?>4AjZMAt}=1WpYK{O?1f*v8W#p!MsoQPtFhsorOOOeX`!a5x}tA4^SoY-d~UU +zuYRRxuM{vFeLZl*RlY#`iH=w2y0KS@R}zPtH9He+RZefzh`M4N3np5cfpNNR&yKWS +z?#%#A+?w+qM1ktS)C +z!q3UXg-e`}w!$28Cd|5zm9!Ihberk*s(0yxeD<`V-#iG2Q&iMs$+auex*O6p%e~GE +z^(dI2A+go6ws^#lF=Je@E_GAV5u%R1;k@4?h3o4{IH*&-vDcsRx1>%7&sW%6QC%a*Pc=zU0!ZW#ZS$KkW<9muO +zr`unoS61G#8v=`2@i|P7n(!U_osa>w_hvh0_zCG7q+%$0R6S*rROED>YTDfEs7!Nd +zx^n<^MLvP@5d7X@)@iwiH;uFAHu8-~VNL~X=E%qx!KqqDCdg6rk82TJ_%I|m-q&)N +z_i0-^;b8Bxn9+}Bv@rn}6M8D3h2LqzE_P$%#%Bw?vPT#5p5)|B$rf&{KZDZIS>faE +z6H}0Yqq>#8S@Jg#P2zqjJLAkeKG?4@|Nc~1LB8C+$t+>9`UXvb{tP##6xR!Tkwp!v +zfs4m*>YPYW1fiCYY%yuctQ*{>&80Y2 +z4KIItDY&+;w*DDqL_YsjlkqV&*PK{0$2rn09?D3pZ8Bvi +zB%Yh$V+eK%H>{k=8GtuEt3OVgx_Jmgy<*syG;z%1#82C*^3b{sMSnHy$`l>TllbBT +zr`1cPX=upk&%Vms*E===G8`)CAa4PwMdBTzESz)@ddJ`_P{;%38?VcNR4bwdL1m-3 +z6up72m<`@0_lA;Iy#DOzUmKE4UbRl@*^@>5E>sl4%!6_W-`$R4A>+P6l}}t%3-lAZ +zOb+Uwo_T@6mw?sr&S4~9eU=!#fhzV#aN=m(gX?QHfntb&<~o)bnP>8<<&gM8Pnh&s +z^0!`}I`khvUKgaK?e}BG;I*Q`SyU&b5hxc-{dVjdD(HoB=(uwzI-6UANQs!;-3oH$ +zZZW@Mf4%$Ej0pN|I4yRaNa{y@@#l(Q_VEnmrOAvJ35J&iABw4jRqWlIV{+@e>wrXf +zU?W3y=sbo^4$rgOT4`MlLXJ{HkX5Gh8&7f3W>9ju0-vTa +zS>4$!G^4!UiXM%NO?-}p^k{MWaHSy&)}ntl6W)_)1aQ3@Lf6?YxO>#>Yc>8=8Lh)& +z5p3$Rk@vw(^ryAI|E*|7gnvM#NMNxSC;j>1Ih?`JiPp(Pn5@rN|GV_3;LrMEKP*g+ +zZtS3>c^CICJ!7yyWEoIpAYt3FgR-XkFTgrBp(H_!Z*;L-IH9B;naP_~_v%c~H5@Kv +zK(yA@ljgaZFJBP_{Z()@`AbqYUAjBuQ2h8v5EvTne!687HKqa${b8xQ&t) +z6TE{j(aTj^7Qkgyb&?(QMA6%{S4{;Ev)_D;3EmaWd=O?dq_hGbuXR`T67nmGab9P5 +z-9~{Rw$;Ci3V4{i)sy9JbP0E-#L2sU<+c~3Gb#-5R9QnV>BN9+hVfpQ?F|g!nR=W$ +zg8RaTS)#V{r6O0i6{Ch1?bN>3Erts=f!YH)_DblLF)uX)B+{HXKvP02>^yEmaDzJ9 +ztVG+TlPT(Yu1BQ9$z#|kJvX3e%uslWC&b2K4mQE7P=*hDFh(_6*IXwtT^=(*CRaUY0z^_IhB)UA&rDe*BHwj*RW2jc) +z2M@*KWM!k4n%g;D;99f;ii3>oH`3*qU!@G{$?n17%|5(WTi+Ps=St;Bi=`uU{s&OP;QmxEos4PQYCeD4;rMYTjat=if`D&~s2zgn>0hsuLN +ze6WP_E=Fu5FXQOyxeqA#T^0jwhZo2xtJ2xyxA8hv4X-(kg&sae +zN<<#`$LUh2vcY +zZP_9bPLs^$RXC&F4c$mO8Af4xO5g`rgLgKEfnT((JNoQI!`X@VDAcwrv5 +zd?3)?p^Wirkt55AAyx75?JVcXi(uF0prb +zR6QH%RLH+gwp9m=?cMc!PELv9Ul=q?-;*SZsz@xaEB1TFl5X1kyv&ojm^UJhlB4`l +zKCfnlltNC}3ZK!{nSh{y@Asl+mKBvvF`gpsY%|7GtmkH%2*6rI#Q%d`4rhJ?o*3sTh|#u#`tS>pSLG4d2v+Da9?8}(CZ`3^Vx +zysGsnU!o#NWpxUHMJQh!|D+m&<-ik)j!h%om_1)&igz}!D<1yaG0uv((~5-DT&K|< +zuDG&we`XeQbzC=pOHjyxqFF-B1;b}|6vd!j<4BJ1Xi@XZo=v?t;joNPykMH}3j8q^~4>yJ9 +z{Zk#s^vAr&3s1~4Yy!h3Y&gSDX!4k410j6Uq|Tl#JVXU?2d&UwYm%O9MOGUDvxDzn +z&KZcn{DL&e^vYigQ%JSI_c8B708x&@3u482U++{)YD@N!aUtG76g@u?;~Z6>nMIb{ +zf$l8v(TrKmjL6xqq~lXlTIK +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 +z2n$>*<{5c*g8~Nx7DfJ=^?G?J@9o-Lp>x> +zd;mz894fy}#Ui6=!-HP69o+eiU2mb0m>pt$w!f9eL3vJQXhrA9wqMvo$LE|9fWMQ& +zGJRP$=jMLnzI*qmF<-t|wUz`*_Nz#Wi2^)SNUe*TE279K)2y1oLr)k?VsJ-Prw;Qr +zP_^E0Gj4tz;^v1y1i`urIDA*6szsEZXou8B--T}uokf3GR%Vxa+;5+ft*Y-RdT5$ +z6rUZa+DZdppDvJz4vSs#)-bnPYL^yvz0NpzutcmbDG(em9w17PvC~p!0Gia+o<7=S +zbr(&y9LZ>pjys+N#B=E-%ajPFi6LB2-*2>NjS5K=?=_lH*X3uY;k6Tkj9|&Ix{GP* +zvX?S^r((jHnBnC(Ws8j*4_2Q+8Qn +z*huxCLAJ|)8Hz$k(C+tDM$XHE;)KyFS9Cadu1}w6KOuVt!$NJ#zY;V~3s2OB4ZsY)9gkV?!|HRFze3d$3xu+V~{{vrShb+Y{d;(nX}>ti;j0B +z13|n@Dq@$`Jmt_sYg&FdA??Dg>F*gG~ +z79`?<`%V#a*06ujr1;s!;K=O`<&lBHv>NJYvT!(bNL<400h&5{Y0%t6j$FlJSW-4} +zovOkY!PEuDd?#>ti>+9xJ)v|wIYsFCN3c&x>c)Se@MHI80c;^>SCiibAR0c%)cRWP +zK+AjJC7R23FIR*@;ND+&XSRCAP1e4y8vbqZdyplXq=RoQaLx=uyGe}^U(G0ofiEBt +zCEF}S4{Sc`1of2(PkWK7!(x!%s@ga)rJA+&w>RtNt*6u;5tOOs0NqyhT%|r-%U<0j +z@?Q6<@fQn_<2f5!BwXl+d?O}&SG7v(^bhzY9t2>yyARn8H)K~ST)G{0EY~h4sbCKr +zL#&J}R|i2Hz2@~L7$KT*bVX%4r49C^7bO7E;Dwk`e3M&wNuDj$BzhrTo|mqL-@_k#BmU@#5T?FIuc{K +ziAF^DZ9Q}0iI7CffZx~4g#Ku+ZPHxLCYJ_=cw{q^!Ygxp@}lT_-1Eh0D*M$92>7nv +z+0alY50G|j$OujktdN(ONL2a;Lf0X9#r=ixyuQ^>6YOT%3hfq?8a!=Bbe_Q&WnT`{ +zlQ%ZP&a;fd#f2AC=At_|6{?g>eRLr0vwJSr7R%^THEoYzWPDc8~ +zhr4aq-zcL(ey=}j-3&)~hGwaPmqEQV?ekRMGs*b7W2h)HkgZPZ-r*VJdk=|AKE4^F +z@b(L&DEy$pQ`1Hc;S#06wSMh*lD+^Y|K;fDHIps%c0Hottz6EFF_pI;m3E%2utH41 +z-qfQkOVCd*9g228-wpjzqj +z1NYTwB;DgQSUpetw7cB?_#?cCPzxB8f8)L{Fm6<~`_`V26Z#g#S4BeoTj^lT>#4g& +zULind50sqgDt&hZ^9cUgw0iw%j$BaBZZHQ%jv+RDOJ+kfFHzAT+_?Rhag+KZv<=au +zDi!ByJ!JC)K_g3Qwc4)Ob@10@4g~*Bw5W@<2qwQgg(h?ZSdTPaf#JgsrVDGwJ!d@( +zUWy?}B>uEEJzqshBZqzD6^tTPUobnz-MboqgiP(aU*!W@bquoJL7nQX<<6wY}X;&3@7MrED8Qt_gQ@RAKK8$O^PSM3F^n=r5x9 +z?cYRE6*SmoHUM$T48^yOLuhlTPD-CKebEhm9yn}498p43Te{|6nKrGA^l~NKJE?S#yJRQhFQQm?`Y)o${z$!2`7i=Oe31Li=hvUWqLL9fDI)*m{g=S^ +zo8Wm@BVCu5O1JXLO2lQ$H1!#!QDEB`0aA^kIK{ZV!e#WMry_PKi=B~1O8MdZ)x`!OT3 +z#7YC#7Sz)~_}oaJX|063KA8FzhsPf$j_ZucGV74C3D +z_HBi$ZGV@*N$*UwM@Pl5Xas4rUS?_uA3bDbngMxf?lZKw)({sJcMX^%e%|uf9D-R9 +z2p6`9owj!QPBa^+ebgC%BA#Ki=p=Mbn23VP;X>3w-v0Hy0_zApxp-A*fiS?U%Q4~7 +z`4}N)^PG@LqgTk@Y25ha7ab>!ix)izSXnYgL^PZn2xVj;na+t^pmnOj@;LDIgA5UKkcQ$-x%@5wWTq;0lCe;UgTB{nT +z#BVB((t|>R=yclx)Hndh*z&DzDAwpE^?9liZ6NkOSdqS-=zQ@?H^+V&DBRE6FyWoH +z$?N(8nGfi^&1k9uv_XWMa=>jb-tKL8&>}*Bjxq}y?AMyU93fx#zuJ#SxECKG&!2T9 +zDU7!h+HTjpOYH;}kO0WZI1+B`im^(J(OvSq%LKyaFozjS*cD)5b_n&d*Et<*lsiH# +zdd`Y)8T}?rK?ZILXHj#*G?vN1`a>@8pW;B9V_HBvw +zewYscb%gYBjLKB|3`%l|Li%fVt!&U@)kr~dSkzyR>6XA^$ripou +znx8F3l5#9?v3d^6oRI&?6N%FQ$rHzu>Hgx0vH#|Y@&7wdOn@}~zwty8lD~Q4Q+(|w +zPsErGEggZ~DeBm;8KE$e!Q_^6ZqIVa0-C@5bcg<_I3&Q4a~q_HpOydR6HD`VXHN;{0!)Sm`9h{^=7>CI8bW +z^8MQJ=Ai4}YQ@QKpgRr%S-#8XjvE(P*Mmxm}<##-G?II?0$=GMAObR~ndJU!G+ +z8om$UnKcAR4qRk7k+;qs+*x==OGau~_~cKwh&pwi0n`c;)McP$*OaqL3&N<*0v1hy87{z^Dv`Ufe>!ZS2p8#KZgok2QaGE}f0 +zO0)G9=SWU_JbX>^DP*4dgA`-DlR(RZO)t%BRBRMcduD6k=R!LZozOgzbJ56U0f!cye2dIwedp21GQ|tV0-&R--lhqR8=-*0Vx5=PFm&_i(~NbVVplNk}xZ!IYq0Ws>as^6%qSmYz$zM +zme{6Ye)i?>xI{Bt6#uL{Zp-oOE%XRA$p+g^*!+wzvaIj_z{Lv6%+Od*4kImGq7GWS +zY=vv?89i!yXaVp1lEHxlyZ4P12iYDB+s9u +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 +zv*m=@8xhoh&seLt)l=%u +zY*5Yl{%fac=yxP@PJRg+%OEK|G?AWHVwJ}5UHd|Ki#6o4Du02#n`(S#e3>7wTyGx?|Mc|py5B4?|CSn +zw^d({D~h|^GMX496D-_0%ysxVxt)I}kPvG-z_%Nq2`Yp={qS*(KoXQg#Y@1|ZtBf0 +zHB*`D`YmlpQqZ#N9zW+QwPm-vU%HA(X*Rhw^xlz85>yPHi-3^MRwdLg7V&$srCWnd +zRL?KlO@n&FYHJXPy_f3pIxy46=D=0j?W=y-JaOU!aGPg4Y +z=p{{n0VWK{IhiT^Z4545A2Et;&MP+ks(Akx-jxeEhi4ucEvHE)SFozu8k`F*l>|pl +z>Jm0H4&YA0-nAA-MZp5T9r$^4TVB!l`isv+0hH7rJw+a9WU@F?olJpS +z2W`SzG+EUJr2Ex2(lH#K+u*3kE8D99Kid9js1k|y>1S@SK|#k#)qg7Paq=fe$r?2T +z9T(uNZCFi95}%VTKNs_dqRxOBW!)$abc8fB{ax?26;X@Qqb`cD6(!|{PVq}35c0@_ +zSy%(4r0r-S_lV&}N}r>k)J0+z*_RqNp)xm44|cSlsuYcKa0g?@4l!TUlV%Ze5S9bX +z#oa*DdW{~g{cFC<m`?YgVF$2kOQf&WSS0c7w-yyls +zkhU{%56)0W@)9+dZQeID(QC{U2{YDWk@fU2WxcWB1Ga(>y5`F3mG!P7Lpr$n?Kv2-X-4TKGE~fjYc}N)BC8EfNlzimU6QwoXs)n3eD0d3zR||%#3q1T3VR`+c&9k!4 +zpT8|xJIb`7hT7$^05DLo12goDjS%8!-+qR3;J^`MxjiVMzhtj-g+M$mVaLB)Qz!Tz +zk7+9cmHeikJlRM{9$gyt&zxB=zLl1?pqxLq8wF>iHN&AhBb6csVe>B5|L$cWl+NiR +zyKL_?KRK>5TXrp?B2(+!X`D3I@QkWUbAwG(g6EHU%B})Y#-ynafr0G``59fD!da8a +z=4WSMV!hGx#2f#vekVKrc*Mdl3SUV^IiL0&&<5ey>`;KDjhl148Q3&l)j}*^LAtW7 +z!~B|_j27NQm?phvLWnQc!F&quVTm6`E+Q4Of0$z@PX+1)R-Y8T1UYXY%}G$=6|?+& +z^0;ncvhUjYC6MFCHS +z0Y=MU6HqytWa^_bExPn}i>aTT$Y#pfCW2RKA6?R(<8Y&%MCNJ|GY@Yid&$I=ojd%X +zZT7+DP%{Ii2PlL~OcloZl{&hvt^{w?UieWdtV-Rwus|3-dC;&~oP~;j0etROpm1X8 +zCn>6k0`};aR4&@5#Kz75uDu7r4;eRMe0;wFO#4HyB(Qt{kGdAz`&dyn1Q3>uS9URji-@OyteCp1ZUO;cQ +zOPECb0Hiz~%Z{gZ31O_$35+EKRNz`;0LbCj$|mxL`EE32@}>9jGq`vT{-?jVb&Q>e +z+kgRUQl6HICtou8*0*hrN +zH;`61h{U~}_R91sc25Lq(?TkI=8OFAW5#R9*La#>Of;@`oajV(Pv;RGeF%RPIbc;# +z0f+hBlDf;S;TF~}316^YF(k4P1rpvQ$DV$8HRk&M#O6Q%!ffpNtSwHzc!vW(G5kV^AWV)0ho|Bg6S_ATZ;f)VBI;-3@?<#$sD{#GrTy$hFm`?Guq{jkszgZVi!3U(5N7ZK`i(3VQiqiy^)1a1YG5<<0Kw +z8_c5(Ive9GN@5b>{ICDdN1Xo^0{S21ZIruwR{<-kb9j!it$l5o3bn(Y;mWjI@S{Kf +z`1Rj-R00bW*qAvZ0=NL8_GBEPLvl1^uj<>|IEryP+;wOso=1~y&=px+*@(kP^mUMz#dSegUTdr&*bnm;@O>R4-Sy^;_C$h^Dnz#*HKH&*O0^P* +z+8G+wH+OI0){21CkW7ud1*+$1=2vV=eL;`;-6`WA%f9Vz^Y|p>2Y85I_#9UNy7y=U +z9?sI^r@#hZR*f}4G +z5Xy*(#gsWyGNqg~!qO4{2h|kQlpJh+%)+6vTi)ShIdH%X_PB>fBI)PI&xxv`J>Miw +zu>mW4y!i+w2NQpxkk4y9$3$C2-_Bv_D~UK+&BQL6S2VhVAbCQBdT;2Z%}wHjtQ!8Q +zK{SO>*grWSH10u7-JFMqH7L1Yd`!Rh=U>yLu`T8RF`ujFFp227?#O{MAf`cWSR|Ic +zz)5wL_}EmcBxwGyz_J<9pjstxOMDGPv5M^|@FBkSXxD!KGMS>5^>eY-DbOkR35O(& +z-yj>fT8?l(v)95D&V9L!77bWeEtkU)N21_6`cTW>i1Cjt0{}>JW$f^}|ARkM +z4g%U?(|M0(Z@=S;G!f`QOT?&9fmizER~k!(TN{D=^tmCmGdi`-`v>yI&1uI@zxht>|yc0xB^vpHP3Q9o0DZ0(j +zS#X%RmrbD?sC=n5zoJL{Yx~lu*_KWc{|KE+6|xTF^#VN08G0Yqk=Z}`KB1EFa1x<= +z%&`Ab@*oU(j!s-5nS6&L+D<{0??Vq&6B1A0gVdyiYCBY(bm6jA--VM<;6u$u(g!Fl +zs#zKC_hEN+Ay5~@A|LB9%s3(UqP@<;da72Jxp^Q<0+~=pDdQlD?Eg +zLuMma=b>eI$#?Z;l~7?F{M78jOM3>z|MAC<0#vAysppKeN0)Ds=$g>|vbi$117vjA +zFHn6XZ@>|gWTJpR3L}0c=^Fa^dgMBZg5Q*4TWud;5H3Boq6q<{KYW6II&yk~M(wW2 +zVgp*l%CY{1uwfkDPueogLqFPb0w;j0`I&0BC$PmF=*kbsPlLEg!ZKo@U6MlP?(Xa% +zI$Js9)`A+{(}K?5IFhy`GKfTNm~#tDD>WRoPooyDg*IO{&A>g!JUm{_!lq?K9{@2& +z(|Cpt+UDyM1sS#G|MeHCF61>#!7fEyjYYw%F={Wy13QbKweF+pT_gp!d)B0jtux__ +zgc-G9yYf;^A^R$?w)^y=I`7Glt^rm=igE@ +z2NP}Ach&8cF*HIBU6?TMCCO5boM?A91Axd)mt18|-Au^l$hl0CP4KaDwvhs6Sz0Z1 +zql+A~df{~0!N}Do1WI28=s@W)8h2{@w6jqCi0R`(*P$9*kI_cv$^uVw=b_2KB%=ca +z7S^sK$Z+>Z=65i9!t4bbIpHhWc7YeP1IkB|gv2pN7#i7KxqGj_oCI$iHP1 +z+l9oLsJ~;~esn6GtPc428#-w-T8K`lDMnJ_776XDu+>qFWjzL^meZ;}BL9WX6NhuZ +zz{XyCXfFXBY0Dj6B+)=;F7B_0vZSU3W@ux(e=DR*ln!GPP(-!MN^u;Y-AG$XAV;Kb +z5#)~KlqoxQr7f0(I%G2t^~0wNS^W9mpF{k#fq0OAC +z6n^1a`Ttln`p!1Pfyst6%9m}%m& +z|7pF7VQVDvD0FI3M-X@Zh5=nkMuSQW-u+B%;)Lqcx|%15HD-Z&XiEqdJWHZS|xfVI?RgZq;1n?nM;ktXOZ#L@AJ=J5c&L +zcUgPb&U}JC0~lwv(P2aPFr6NVwGN-YcXFWiaC-JSqC^bGt8fvW;VY35Vyxj)nl*{K +zic=gV<=tiV;_xTvUcIM}ND90T=JqbQ`AiCpR?TiRt4L+g)9=&ssej^I(YfrCB0+sh +z0FgOI{dl}_wP#_5ZQy=7P=|`knM?mV&sSu0h-lMD4#xpX8YT;UoPSEE6(@0vv6lbc +z3>?XOuWb;0remWCECKv1SAseyJvKld8tIo^7?vOCLQ-l^E<}`IfEM%^4Fz?@Op({I +z`=j8RRApA>S*FAhua?+myocpi|0 +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 +zWfwV&bxJrDS)$J|KVo$lnpcrI*5 +zBT*B+9Nb3XhGiN{RB7XkjnV)R#jt1t!T>v(XKXp*waaytUo~rsBMSSx?to#T!4Kh# +z!1(HNOx{jJE8*B12}-9&|Cp6H-(veAe4Uy6z=<*;5o(o?dCwbWbtRvonRC$cTv!b= +z3nce}p1o8~lIQP1Hq!_40Vnz9>wM#BN%jDgP})JT1$vVOWUkraDbgG-#2pYJM2CGZ +zoCd^e!R^_-`6lcfa|Jce)kK#(HS)voZaM!5`siWT*I}AisIJR|j3VX5Xy~$RV +z3(v7rJ?qxA5O0dxpYaMdnl}2>l2?2SE7-tp8NyAUN9o3t&jmdu7XL>vfxWVU+24Nt +z{H`TDp06IL}kg?O9mS&Onk`&|N`0Q)2WCP1(ZZajI&Ah5upy +z$AhT7|K*sx$fu{tsY{Wz^!wrg2?IHth^gBK1xV?#P-dx%*i^=pFb40Pcn`QK4cE=rHvlP^`*pOn(Xz_#l7d*QJj$a*=t9{e +z%#t2FL*J*U1NB5h_p4jd+OgG=?R_QQoIK{#u*6`{lvW&cSaMEdbweM}V80%73V}(A +zfMQ~a#KwdGYKx$rnyex~n4=4J`vts33X{nTwl3`|2LB%AwsqQte6V7OXUd}8C6Gfq +zh+t9Kl=Z>M(!3+slx&Z@ySYLpKHC7fD|so9O1{G=1LuT$Nm?KNcP#8s^}@TnK!U1C +zJ{-Slp#BraTXu5`&ms5}M2S%y&qur^X$G`UCH%>{($DSlpJ*|~ucApTXT`}{(*_gw +zu>JVsx8I5lT_nt#Ghc5Lp>#%a0e*eR{vVld_6s-_uXSXrnW+MCj<1E3%to&#K5ntf +z4vID;0Syknd)>8HOyMS7sAG~eMvGh@)9Wt-*HP!woEm!ww$GP8O9yT70tFlU7~%0U_}; +z9cXyHW{~|Dyl%(QD-H&@a?C9xfk48+YqlglP><41Weosyf4357Y;I`ehn&+{@d=e8 +zbJUW+vNt0KZ97yE3IBRH-(ml!tB9DrMT=^^Km^z6vo0k3nlBiCUp!P0Gv39AE!|DR +z-An`pn?fU`w+)w`I0gc?5^3rJ>Xa>JAV`)d?h|z$-okPv=>E>|_w$caEFp^{c?SCP +z`*0dSAt76Pu~Iv$8mb=U0aR(x6=+q=G)Uq@_5g$SOM?4* +zSCYjxlv8Mc%HKB$j4pc(S#2|bKYpwA|NT%T8}z7x#qYQk0DSr2v%>y0{72d(4-zv? +zv&#v77ia-qcS_r#An$MJDJ-jO(bhT)h;RImYuzNqTxva$kU#op6RLabX-dbgyfK_N +zu?U4DpxFjJcN_D#Fw9@ByXhV63%NAb2~fxB&MjkX=NlC+i%t^y&hzp2;ELHHM@gX4 +zfs*RGj*{%gWyc)N_5mY=uL+u7Fz9LT3x3g2OTI;drD8tR6v%QR;>ac1hakX;nHxKZ +z*p3~rg*AgU1pU4^G#~vQ!YS)wHcvk49((p5XhOAB +z{Ws{cpHC1-35dZ>vPp&vBFQ8NKCdzw*; +z->W~{(!<6(zm6eln27u2!t;iw8#XzZ7G^(~P+9GH=wIUHcF9bwm7DGdRNg&j)z=Ku +zOBUsn#Mrc(x?Vm?+|-v3EN7+<1a8W~8(ydvXTB+>GjuS;2tVnwvfynJ0GH%ywgduV +z$1pe$C>YH|JyxZ0Nzf)OTK=IKg=%wknCwKCP?9I+a`T1kFP8aVE^rhJs^l#T(U$zG +zvcy&Ep*ACv1VxP~4e7h$C%)O@&-t!}FNso(hB@qPkx{@;UwIBo*_>gs!Ca)3%;o-b +z$|d6h0!5*9jGv%wEAs%GjoR%XrnTb-)neMbo1drSSnBgin}qT{R3(wvc0Vt!ID;-L +z!emK?`BotY +z>>_yY9^1?SWX$Mh`nHE;cyGd7y}ZofBz*vWJljASwui^9aEwKgAvt^J_!$f}ls&vl +z|5cA?(dp77A*)J-&s_4-zXTBfF?!5+;7s24s4a~w=zt4ucTUmcVAo&35eZm|?FlM2 +z|DJ0!w#-? +za1%Y|wS7-t0Bm?8oa(@@)b<#vmN&Ys5Dw^2mx_s7$*8}&-Uz%D9qaG}w43C=>O4RT +z-Qx@5tvI>xYq;DcteZl@B(~^jO?$yLWPQ?~Y^my2HJ5mFMLqojOywHEyr9p1=)FmU +zZ$4u{m$=Sz8kh%F)F??cF3;j1setDh`gU}6>gPl(Pl-RH9UoNK! +zkf?i0`eg~fYMnsQ%c8R3unRi3N2Y}~4csuk%#%Pk>tBPFkQ9Q~gA58%H8J%BUUL)L +zS1pHP8QyzSJiH)rR&gwdw|Ld5M{4MpQ}bj{OBfHdlO04z(WmCr(tP_Cv^ZM+Pc!9X +z(}kknE(eWMUN$i)5A-?%<%F{#w}MJd*rl=kuV-@>5>)-9z{5fm{=FcSWY$@4hbweS +zCgg{mQ56%sE8PcSwNp`6% +z$FBeWTRI0gd3~#aSwgmecVtdwC)~huxBAPQ5EUW~q^gPG0+k3!J#J~v@fn-Dm)vjj +z#-O4`P!l>Kig+mhB;PN|`3c4IyI +zhmljN%n`1-6Wk)r`IJS^_kLWzusBY%ToAwJIkei@rtr_8@ku@r839t_Yz*%Z&`m7d +zoK4Ih){P~#LTlOMrWY)+q3HnyDK7-7@hpka-B5>#?@d<|)!gw^yiJDdpedVmg2mpi +zIA;A6lPJTt8%B;N&;x-)(4s$aMKgyk?Q*j?5PTB%or^O;R4*h(IBWIH=H72M650jK +zk0)K&n>JH^!O?DwM6ah-HIkd_S1`mwu_Buu8M8n-;k>GkygmZFj<8#=2$|*@Q5^n9W+zO_9$qyNKii=u5;$|Iq|3k3K{_x;< +zK+WB%FJ%;-;fSSb4&rtt81RR>02q?bw#1OHBqb`ww6^HE>rb8a^?ait$W*>rv-J`hXt18 +zOkH!-vLJ(-T`P%XIX4ErCVO2lyhY}QHVjN*KRI-pFD}rO;hIHjRIS6sI^Lu%TUlzf +z4J;2BCF4;Q6P`8MA%`V5^8`4t<}{8x%P4{W{B1MZFAuc38T^-U;x2j%936V9M}`$& +zQR~cdoY!?-2Ti*Y8fQCDl{0aa%V4EdK6FwHE2hN)^+P{6O5EN~hD@~1jObCMZN=+L +z_H4JGk{O6CG04&DRK~o>Deqq(UY26!N8O1L7S*a$TF&(| +z^Ch8^yG^CrDRulOJptqwJ=c0Fa=Xwwnf5{d!WCq1Y|i;oh|_2W0lV*E_HdU^I?b!B!V +z2O`H6y#$!zQPF`$N9JU^pkO}6g77p2>vbF4q8!_@M!t$?uWn7wTY-)nxZp#WQ8MV#`UJ~yQ5RVD^_qb9j$|ajQL)81czV+*U42<^F +z)5eRW;HVjI^(I$fNx2H1o4y~$K&SYj8u@ulZ!=<`AUpjim`t)Om#55V#Q5lSBr{gx +zA|UnigiG(oaGx*z7Y3G~1oRdq3=@I-~qsv(E9J +ze6wky$=3?gP5+Q5hI5xcm6VqPSOn0GT!O?KgrIXgMt?zN_wOyr*Og=48>?!KWo7+A +zBGbxkNxWFz5n_jw9GcKZNT?_B$`+s=2(&}|!BRw9j^`02>0*UZuJjZ94>tfr@Zmn16Z4|6HQaXrMQQ3j=-{?TAx&M7@E5`s)8B#qZD;rGP@%2AEZ{456$;$ykWg(*TSC5>nm +z^%(Fp#EGebXYl-6W3|xKdG+GWNA@-x9|IEJF`6Qmj(~us#;h!3MX<rmP1EXeiCkVPgleCHN+O+WjM!-c4S +zrMmV=bjn9RP!=7^qJ!1H2$MZAmhd*CioJpUfdnzG$+c6bdh`^H{H61S{j6OV*5<_d +z@o&wG4OSPrqVTkwx$t$3l21e{M;KUE!d7GLeUs$Gd?f%e2Ot6LJ~#%{pALgiqi0km +zDidt9QKCR1a+aCMLEL}Gc>xS{?^E#-U4|K;hPoq|NHN!cIFLiafAG*;eAI^|f|!yi +zPa&xsJSO0GpzH`O@N$L0;dA%7O2UkM5Hc+Hu}_D7Rm_LBAamsID-5T$u`C+?5?|Yq +zu{)*o#sFf&PFy_?nY_=IVi09EeFI6Lm$hEeqOzPw^4<>YDst9lk58t}%z8TDz|Nyf +z5Vs+o#f84CkV8Y4g`XhKpOYjMi!BgQi|i#KcDnR``L>aJJktcOx{j-l1`x|PCU94#CZQ$x@ +zaecj1Gy*bw>tUmdlHnlXi3B>V7={%xlMc6A**dj0PBZr;j|%k`d9i=euHa +zNgP!0wAycp--8+&I+(l$-no+KU^}jsf2vM~HNc1vjXUPnvTwdi{8eE3SS5!VPSW6f +zbpQ>)ZgvxJIm__Z{pV`z+0%s#=cfLxbO;`ZzsqV-{5iPPy9HgPTCKPT5>35&IcrI6 +zvYuQqcf+6!*s`XKbP8hdrn*H<#4&%*hjXqWJSRrXXKf!5!_w$OSkc1}+ibxA!kzxE +z7tsyZnxXVMf0w8znzq*IF5I(MXtx41wgvDWjXrOIGuEi70{15fS4JdUd62G$hl_PF +z}cS*M6?;8phi?H&~k5=b#W8uf#$=H2au}T8#DsfcbftfBQmw21=G2F%oa;y<527 +z&ZFek_HI+b=nExURVFdPRK)-Qv5vk%!X967Pix}R3JINVeAqQ&9ZABI?f{LCnlVW$ +zK|-29YzKswHk~sILo~wuDU*r8QziB{9Yvq85#UeGAYrZKCZ-IzCX(!pXO0KGui`aK +zgmNUh@hO|zIigf(y^8dX`-6hGRz3l=5n=~Kp*TwSNs)4s93rn4;Pcb9mdvGYQx+t@ +z*+Wko!3{^Nob>`+DhsG@F6edk>RIHRUFS^ddA+s;l>O-tHkK!s^_e)SxKH06drB9-m0FgbC1-aT_r5DC+QfaX +zGb+Y7(niMrx3UXM_&0gPvN*33>u-T;7d8(DIMR;pYthbEW0-Y%x2az+NN7dr)V|dp +z{%YbRtG|298HT`s#&8L`F1>gn%N~7;t`lph1_9_OF>{t}78d9bP5=g%1tZw34@Iy@5lKzI43)Pm +zr*`L%U^%)$(LkZ=4JM|01YNv@HPf-kT^7{tYzvk;!d1XsHIiehzN2Hu@!VOi1b)S^ +zf{8_2l~oim@7oSkfP~VqPUik=s%s95$)BW;9%c!EH~~D>N7Jgi*k9swF2^)k12kR( +zEBH320dGKFge?w9s-8|&PJ!%}+B2sh`rAOAF`w|_7@`9SA}KN?(zf`ItfcbyGC>#4 +zHp&Pym@C%7%%m)mJiZDJ=+gnY4eVz~hF&7Y1)#?hjD9uPEpzwNyA%^SLNaWSh~_jH +z2BUr>_sBJO;Ky0k2qq_~XA?Lh5lh!!y`2u1C--S32}5F0HcZXZ7TjjtEUVrv7YXPv +zAWP>DvUf4;_l%4N$Jc?tNHYi7_&>%{ALH1D^=O2sc7xcz3ZQa`hkEInHCrV{OCPXgh912N<$0 +zHHOO`nrj(1k(DIMMB+N|`qjle6{(dAQ0Gn33^WnEodNhm3kfqv?sT=JHCz1_JX*n= +zZ9iGPDMd^awd^EqAg~lz0lyldJr*%K8MM$vv0cp>f43iS6r+T{f8E2L=Sz`nPr$TN +zxKPgRl!_Z~KHb7%$r!BuS+0w|%eJF)iOujP87a~M3i0`4EwZ=u+Xfa8?pkL(6MWAU +zxnWb!{BkB0iTQ$?n*p(uzI@_Ro|x)c%z>cb@RUH(nDrr-0s>Tr4T(cQr`y49-1W?s +zi#?7dVN_xIx6;TEEreY31&povc55sv{>H +zys@b|GUFK_Na1!N&2-kDq*=j0md`+1+llG`IxB?5QFixQdw?INFOt^tCKrW07(oFj?zQmZXKc?5U_ClLF%G*3cuRs(~{s#LZe8 +z4@)n#$tAJk>Jyz`#hKRo*q_tvjCSCabiFmqB-k7o3^y?#N*N%Z5F`|GAfO}}{RG9@ +z0~!_u!iEPA$m9l4W}CIsIcG2t#YA*?g_lo=7+5-$Lrgvo*_vF8WN#L52L-eq6X9Q- +zPaG=NFjWv=2Ygxg6wTVWra_rP552Ki9+eC^QxbfOr(3u!v%KtzAsPoDNK%J_@q4KY +zCsdL~AC8+yY;^j-4{o_eGQ%9V#HtQP91#3X^?MCtog;Wo02dFE@l0vtBHUBhH=a$< +ze5Q9E|V2Jc~oi}GOSVY?gX~EgdR{EKYgw!iIRym=6QyNLp@b)WVe&mmc>p}RMf?m!? +zntKlsvZvbk1yd?yIl{$IR^py4&drj-*JU#y1cwf$;XU&NoCaj-n_-V&&~O5hIrW0N +z6ZblcL*e(ue`X(`<#agCIfW>YOPaMSo%L_2dQ>aEt#*K$2GK}F0slZ}!t3_+2f-hv#RaMW6BV@aHdrds=aYQeaXmhxwPIHxRnFHmJr +zi9{mDc0|kIQIIm%Jf4Y(zQGt3x;$=j5>#1SOj7P69{+EjpZk*y9#IbJiLg&%`n0AB +zZZDAS8p>rP3S|80I-xA?Jemj==E|=VvA*I>I!k +z8I6zM{$2lNoEsFH%o$9_#S3#(DWQna+PxJfu;Zx~wM4?9Y;7O6K9yo^mG8OUgxpc? +zf%jVV^8rAN-7R>9^@3yx`}VQKzkmgSM%yFxTx`vO)n#^|+qce7mBZ{@U>U-fIIjB; +zj097bzvr}iP-SW4JD^VNCnprJ4(fK?g9&%^k^^0`Q(^W1Z$<27a$0v#OS8O(KC>~; +zX_Dj11gHy%equkR11cUDL8#}<$lYZhi~@p`LPM<%u}r*>ia){8L)0Xa +zde!IAfYxqbyoWBX(y4K&t +zP_lLwTz?MixFyeY6E-$#6*^o{_9pYu-u{Xhc|^7%hT2%2EuoIr*IWP!(YUp6;f4e} +zb}rzHsfAk>*uf)+!m;mfI7 +zj<)r4bUQ$sB0ma#%i*s8-Q76aaus}kjpSapI|dXJepWtAGOq<)PqO+YIUPj9bI4LkKKXRZe0y$Jrnb+SQvpc`l$g*Lx=>{2_92?n$a$bw{{St~EstyIs1hXf +zFy2Tgj-^)*$q=t->d6&1&{u98)7XKjE-?&TdSDiTSk|q1i9L6C>Ikh>SR!Lk(|6nE +zi=_O{j*a$J#}UgP?_fQmNFRV)%o%I?71GJ(1k`~=8hS=0q! +z^RL&0v;G-tc_W`W=-117A|x+DNzS}KU +zXIWH?W*ij)vya4^gL&iYeK8VkqTX4H%{j}{1}f7h=`_5EQ@_&F^_k#JKlhjTob5-Q +zcEDhki=n-AYMnFd@-jVWq%ft0MUI1wvhN^zSFqLxY{Fk`H&3u>fWNrg!k&4L-0p%b +zq=b`ST`ch<@Nl#02gS#1*XZLxN*T$4=F|HCP-#zt#d5zlDzjj-Jd}El=XK5`TT@43 +z(R*(q1xlMh>ZHW135P5B+C}3$g(vN3%sDOVT}-QEWtFFpgQyv_Iu8<~KTR^P8y|+7 +z(g1oG*EB*W%W=+F% +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 +zVO9=?1TBs)+ZGb54!H +zDqSQ0a+g6j^ht7m&4bonE9Wr87%RL=Xp-vL3349-R+jCZqBf~LYkA|;N96Oh7MMRT +z)<9h#|E91CjJNOb(8dGpd@d#@*E-BCOJPk*WnS1ia{DV_$F{4|Foo=rQKs|k5Ya$n +z(}+4}w;wFIX!wtUb$z{6$Z0(5$2jQxL%}MTgXnA_W>ivCxB-&9su@>*BpD;IhIgaQ +z8;i6~NXWB#tFvBp9fvP-g}_tI5hZv*(<}@u40Ctlj)Wjq+bcJ>d#)EW}l9X9y@~MMZUM&j*q1Iau=AY1=$bh{%8n^y?3Va +zIIyIh054M5cm$dU_;sgNV@YS1iYz5$>og^=@?vkGLJQBd)48V075AZ+T5}J3K~VkH +zI}<0jAk=zY@`N=fM%9ptBrG$W55q$Juxt#H784}9Hz*yYa}KZ9YBSt@&?PnvmWmCF +zqae6p>fyc)c<0xp4Sp(sn1Vm=?kB00dvF +zp**mZKYQce0jhf`APvpr$BCvohGV?W7)#FgzxH~Xc}P7wc)G(tdQY!~3uBY2+)2x{ +z1GNM5JjAA`x#jlE%}ll8m%b}XI+7d>kD@HKRDl&Q_1SeRiH!X9A{}9KeJCdO?Ww(k +zB((rwq#?d6^qNvpnmIzsPKtXVH(T)Flhh|uz}zed;nTBX)|Yl#M2LwHMm#r|Bo`s7 +zx5>JdSbAVilU2(@iM9BsD*2yX%eDgC)ZJc&`+`FrsIVt4;LM%Yt6pSlG&P0Uvqye~ +zW{KGR87S^GMY1Q0 +z^`w)4Hf=Ddcm=STp~vI+xIU&K*#F?j-GAXoEF)UHEGN1s6Lb0h0ojetFAXQbsc|Zh +zhX;?=(7%$!&>U39d!3`B(%wVUXioNjlF?!AT_5z +zn=kYjnA2*LtkT)Us3KK&9jX~+F@_{h(3G_dj0z+ATpgSnZi7-ww%EhrGZ`6u$B)@j +z%cS(9o*=2#Q?Wjs4pbFaBuEt;3ew>@Z*ZSm{f^D*zh8$J1Z}4N%W*)KM7|=8D}Nc0 +zsU7OLJn0<02Z>4kA4amg{U1h>5HPgF3ScBhNro-?OL3qq|7=z?zRAXZ^C@urQmtG5 +zVfUXSNtyGnBl-A`Bgt&5^SU9u7%Ys9gi9)GE_?8gBiXFA)kg9D|2UE$mh9;NIFeT- +zkl&O^x%8`1nt$eIvh&u9s&otF=Jh%_^5(P2-w38ESaJkjQ{da6MU`N}Zd3wY9ySv_ +z$T2EcVB_@(?R}>Q$1`Pn2-2|jdr=5*b4iZEE-ri>V~)1caGqAqWT*_mqL|keHMgeD +zppc1_T~fbJl&+_qFs;QAH<`FQYRw2K?1L5^Q{o@3Nyl|}p8FeAvcD@|1(3gXpsycF +zt#0>b@eje`W)1f}8%K^v?3toPrTi}>`HQi^CkwXh4fNIAb>McqahR-3TNHAq4w#bT +ztaSws@|*3?^7&R&zLgG*mofu-gZ|R0qo1B8w$u;~hHMW;YRRpwj+Cu68K2+tvtNr_ +z;!79RJ~wNM;df?c9YkZQpUVekC4={6mQj8$IPxIjNaN +zMCiLx>7kltdf?t>y%+-Vxyj8V>6b1Q^1b&Y +z4;6any{IX&O1v5~&3IB6KoqU82!aqpz&DzJZY~LGO;|||ewU8WLs@`Y!p^^C+@tSDYF@+FzZX*mlZ<*v#OrBqaf*YNj-7yh +zNakFdcPk|&s!Iud6sd_3D9F7y2@ep*r{hguEJ+*G6h$-RudB>~_t}KfV8baioLoCz +z)+D#yyv8Gt%q$NZPR)ODs34j4BWYNZ#IFjOXVsf4+p!TOk0FK(jOvTUvm@g1pxjLe +zqgUg(()%2EMDLd|6Pxb+G7TUTPn6ugCH6X+30I5J*ciINt#k?!?v+;6&8blE(G3lh +zlflW9EqD3O%OB)b6t~uy%;S=97Zk3%}Rbi)nPdF~-o5YQ?ZL>qc=^1mnZqHy^unJ3!)v@CMhg%n6)m7M9Sf +zl-SP-aTQfTYBPEi;p4LT5SBTB^t-wjaRKHB-=fu+Sk;A0LALn08@+cAh_O3_oQ;6(PL#cMnG>T_6`=QUMbNL0?pJ9Eey{69!p*te4-u5Dn;Lc`&g1` +z?`a8QDc8e*&&`xSV3^)+tI(Q~?Z}rej-rje--#YJVumaIBeg51YoFHkz^eURX*hK>r0H^+CuKZ|Fyc9j(vy=RWkr +zvlb~_AO}Wyolc2WR~A>Oom +zpMp+LVQ#R4_j`Yzp*P5bQoOsYS{f8C;}sc$&$BsJYczL;*#$F(EAOGcPF;h$kJ@!{QNhYiMsVcA +zLVKNsWx7KCtD1DAZ>DitatRCb+|G-aw#1YwE!$275%%#7zlQZ*83+|Ry94*2$7F*< +z2smCfZc?JqQ)<^8=Zv{Z-hlq0woyoTJW#9#ii6%#zx1aD3;DCd&wLEC;egFbiS3!} +zejxt5c6osIV^cF)C?dv$!)eYbT(*;#UAX<2VBZFOX&X&xiSokbKUs3~mHAED79dL+ +zvgb^nnK=e@-V{6}VI3PjlBzeF{PONcU@FUdz=rt-kR|c|%96PR4SIxv)?lhA`5=*S +zc1Qm4J(mud8|@;^px=wr(K~<;aWtt#o8w(}5~4M3W+AKiVivvTHfBE%#RTdhAliG* +z13(?(GCcR+F|sHObCj8+DEs5D1BLE~uB&-PrkV#Kr44SKdF;F$w&L}Ni=z;AK^70y +zCd+0I=G{-a24xShp{Lq-Qs4MRtz8IuA?js99Fy?8?CWiqB6L*i)j}|b5b=knH6Hxh +z5uz^F{26^S5dgX*%V^r-L*Bzko4_Qz_RnXXqt#ewCKS;)E>N4pAYquG0RrH@4_?Hq +zxZYJzJ~9#Wzrv)e!Uzmsn1#27hk+v1S%Kj$pw!&2yK&lwOERVJwW(JGZf9+AAe~Cr>kANEM#Ioxd7NlgKLKB) +z5k&uOHRbf#5L8tY4#}tH$GO_=1#$LgMpGy$&|FToP+&+y_V$xC>b5H!2x6P+7O0vP +zJFS4ba=?M3aGkH_r5TBo@((J}L3FP^5au>I4_2DOQ?+&8QQv~V7vIFxv +z?tAc5ZBRt^=mTqh%j0;@`K>EU6SDdZkA7)?YrOnNm54V?$e^1`1`IA^x)aNX$tCj6 +zUuP1hk1E +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 +z5Wlk`2Q9w6?}eW+un1tMor?CzV5_ +zKsz_;@4AHep+aU&FT{O(W_+};w3evBsb5egvdg3Cg;Gx2W$E%q+uUDTSM8IFk<)f0 +zd3;~IGCdHO?g_N|j&bHLL<5nOoC5?~8r)!dq7n>|pH)+82eu8kX&XyB|Lu}j`sj+L +zT1xgH{XywS2wYZ1Rh6qm4FFMw9{mJBlptn}e<8|gcm%;q(0?IHz%0F|0junDqi_Fh +z03lbN&wmi5oBt{Rq6BU#l9d?mM~dnD7ow~JK$LC&K$N^re<8|Xu4<)QDCsBX*#Chj +z&t0Y~Gq;q-;BitF{567ifb+;P=%(eZin9Wdt9hvjp`5wzQ9YeIQf|%3?8F?C+hsG1 +ztsMSHH3~FeZ9&egPSn>H>p!33!)!z8bKaTOH~?zS`$5Z_FST~bq4*+mE>6Y1;Hgak +zyTozOhs(MW9qO>7Rvy7=t8Af?mb#O+gSeKqCtbyPvy@Nr9+l;3=rbL2v{I(rd-@GK +z(0>(5()Wt{1W>?`j0LD*d)nnY6fLdsHxcv`wltHyjd8`Bb#+vVRh|wB;B{QA9i5ByU+@JK$Zy*yULu2$*;6R~3Gtm3)WTYklWBU&Ch+RnZQ +zQ1?_e^54FQra&5xuiDN{8b8_G{Si2>Zpp#@wQvF@t8puGwWuNyTHu4j^@LNYxG9{w +z@|rF1&A2w6??RPiOt!zn((@3@#5*P^3k&N(j>Vful4EMJK_L3YS{xiJ-M?oGx3JNpCa?J*UZ<)>B2}ezpeI~Ck4?fJKzP>FK8V_4G#P4H?*W=x6{v& +z#DO*O^0~~7a5zS9(6$&@u%d&2J@B=K13kF$aEUU8cr}DhKNpC+@<5(7*s8c5#gO`> +z-0WUy*2_)Gdzv-OPIyIHS*PLc2aZPC8Q;{4B^6Oo>gf$pxQV6_;#5)+=*-_siF-B= +z+9zpsQ7GqXPqoLpv$aysc11E(RGl6_*if*EbkFTgz6qs~dV#bjgG4xXbqf2xMXHfC +zQ;-XQMmUZ#V8dpPSr6dmfDcob$rp5s4oS(NZ14g>s$oZasaeiDCH_*Kc(DCw{;=1T +zmjS0kumBtL7mdv#BS@?k)2HqI5&zZ&zPkFmb16IR-N3RyIE~WZVg##9oPPbUc!n;Bgd@K?E?_CQ<{bO)3nsYB0%;-;^(gyTFe?(ivP|1S`LZR3(1<3zel#Kw3a`=Ve +zHrwCHXh@j4u20j}g=-wz4j;!Fy`jSRSYA=*6K)T6PvZ352rs+!W+^#h6W^W3j +zeqtNzBmvL64+$~U(<cD%F3fVuHPEN0@} +zK}u{a3t^mg1rvnLiQ7|s%ryR0v^J6=JUIalx(xn=d^vqaS}{Uxe)R)}R1}t;=qUimi_$-pFXY7io~K4+i}$HGX@5&7t8hLb}G;OrljE6PUoYb0b4~%PXa3 +zH+p6dQC8lBeZsB~Yr|<(#bQJ}s1dhyrUM_EJ^RfO^tPoZJ9l``Co!Ku@%gQi@?MD( +zSvu5O<{kot0)9s~P4LoQo$v*-O|=8@YDWNg2Ak6cA}Z{_^0CL0QgRNqKy-d_Ff+~@gL~kEzpmj0r +z$B9TvJY2h5->!)%?k4g{Yh%}iI2f0FXzLxYm&NaX1&tTMhIK{DJT_5ID|(z4U@+M)FjcS!D93>>i0?T)G^ +z_0j_D-b6<}PY^jN5u55&2_bYl1uBT?!D8PaH~jr7ff(8WO@H4~2PJir`q$4(=u-3V +zC>BgKlsVVQy|LSS8IR;%pA~mn8@N}Zd08dVSbd`6gk~$FX+iries6g(5F${aF+M6G +zpGWKnd41~V(Ie;9^#4brtT_3rQBJe{|20ape>KX3Gtf3dkU~#@Mp=B_n+UK<%*9|l +zxjZK3ntd(4jk(yl!69j}`}qrt@q_Xvi>QV#M`Ne=8+cr4nk?d39FZeiSuoh%F1Geg +zj`oc2OXf7^noDO2s2>wqDWq^lG~=2Nu!UEIfQEEyUB6!;6w2x~!8*v`^__R2Hu!OK +zIJD}$wWV^dQivzm!Fht}X@wb%DWDLwafM}}mit`^RUTA62;Ha6$3Ujx@4NWEez2!Q +z;YrB=*Ih9B)wL>=dEbunr7)`cK?dLYd_%XUq`DXPEX&~j3N+H=vlvkSiqslwBFwsD +z&iY+vg1tS+oWS<=9($nF~(N$h@vAHA4Vi +zr-DVeM1xYqqzGx)>+q&|8BHktM`=&_r^ozWXSjc)a+Ex3JIQ`Z}# +zw4St%YU>O6e9n~O!b}6Q2n(LaF_5t(P^II4EFy?W-kyvCTfS&zu +zve6s{_ud&94CO5~s(ZE!lL`EA_fX$(zZnTVDJ1UYa$+W9aHr9?s1K=om +z030QbOwK_0gZN$#|AC8i7^e;!*a|0Z0{+FZdMd?{0v;c6F+i&7r +zuX)MOKhtZH3IQBtT`hp4To7e@#Jv7}$ye&dla2DRlf62asB>_HUSH(wOwBpv0cr#d +zdpePI8$-C+#96BRJIVJG{$jzf-JIAQDX$Hs3gl_*^dPXwVlz*{&nd%rP}5(g@4H1X +zVz=K-r3s287%Xr!cR9U@+X2L|oF=RBLjHP)VsytN-h9dc&12RDSfMDw{^%*NZLK&S +z`X(8rPaB&kJ)kgPaV_i4$T&U>q6@vR9^hl#Pvz)n_`wMOW!0UrBW;(|GV-}3|26YP +z^!19&?J37Nm1VQuQ*`8ZG_GQHCwo{`y1836+OC81-J+EC5zd_aFtFp}WxeKW5C_>W +z_jzQJ61f)*smWzu5MQZ;Xlw~7H!A3N?IvF|`GrT|>XBi>Mal=a%&rS2>@p^4KHM$(`%ciW~yw3X-90brbzw)30u*=IL)0W%0@H75Mb?QEQ4F9~MX>r-m14 +zEl7RBjo?C+dB3zg$W%5Ke%AiZI|_DY>B(tv@yc4J&=p`5e;+=s1$ycd%L0Wyf5hfz +z-=~Qu_;mo$#81yj`GePw>90+Bu7E9u5^`3_Au(8pAhOVNPvH12ZwU3q3N|$-v5Nv& +z;oatzjE_;y2j!>|q$$qO*ZhhyX<1GS&6}O5F6FyJYFeUcLSdPvlTrLm4U+P_9HL~f +zu<<(BWjl@DsV?;l^nvI>q`R&y`zA3h;f2qI2f!(BTmPvqW3(%R3&#lY#$+PTLQ1Va +zijQM)@sv`_o}ME#xnxo_d7-_5ByBslT8$wloMyuYEA%m-68BLuP7JF^)iOYT6OrSC +zeRu^27QyZy%Ptau2-;)xpbfn}vh?XUA>R)cNGq9BMZDcW!j`%Mgz5>Xg?nW8yo6i{3O|1B=1u$72C +z?ADB*{EuHc#P`q?4N=X)Bt5DZ4bCPjrZEeL*d6Zyv1KW+W8#KWN+RBp2wcKiv=ps& +zctJU%Lk$FL9R~CjN(pE}wGkBz9CVLtbE(J6&#Jic#Ps0PYmD(kI1QbN7Jcy2L;k(^ +z!ZN(UILdnj{>i{fqaozRQLC+ik5N1L1>UC@b`6!e$kRBy0xHDdQ +zs!m1ctn!tV%Za(S@&NyJYwJ+pZm>&S=xC +z!-#_;gO=PZlW?Rb>n;uJu>!qm^|1bKc4;3E2&E>sCNpf!HE33387lJ{zHD)XHhgv( +zEx))il+C%^hZ(wH{K){+@63Sv98Hl-D(DBM8ZSBi=IX-A7cppx-u<0Ar7yDB36#I+ +zjnB542h24{qsXT8TRsvg7qkivAjyPq6de~Y&@+2iSqBL6$T$%9po~5Y0u%A<0gDzn +zDTgYv^vBcWO|iNaPl@E`rWMG;7%w01`{p4$i$qFOCd}9L;D2k(L|KG9%1VFsRS{Dc@II&uBVPjp?f!7vniCy;+;oOb1F>mZo{qh_OIaT?Vw24O6xh +z=oXzz3Tp7wIq6VYI=S=nPvC|(R=`ScLZRHNwtDp-YNV)^61yK^K&40OVw8(t8p1xn +zycGG7Gkwyya{gYu-^Exg5pERgoo-5`wlc9`4MQ!!fDMVOT?k+`n_-dm63!FEat8w? +zKUof?Q?dhKC)MM(sn2$;Qgvb*BFr3D6hKZfqyQ@4{7B0_EOX96!)EK_eFx`B-LVYG<20(XMm|g6bbA1rDQu#W8ESJ& +zzAP)aa;jR02pQED1cOwt*?>bo2i{QlU5NF)l8ZI+?Vl7b*JbvUCy#pTaX!oO+%6bh +z2NB1nqs{H|;e%U_M9}PqxT8nLYSw0IX+@%U_C3ClgOnBf=<d{o(~~MJvU}j&8H53k4y>O-e(7#DCW@_h)WCP`f$4jstDc?Lt@RT&391^tXzhYM +z=|UV%%3%h#6(G8thJh0P8(n&?4vfFRG+3E`bxgB%U!sc>YM7TF-?)n>!m3}C9ec~# +zgMtKG0v|^nJAVm6H_x|d=F{F4kqITB$tcf +zbM({ezh13#U^Q(x;g2Ax)}1mz1PaPA54G$()5z|9a&Z9gT|d0^S^>{+|qmW2=Xke2T2$&a_@*_UnFZ7yof%8G{9pP{Ok&0FPa@e8JB{j$VgVtP@T8*Lmyq2>;+Tt0$6xX +z2KPIzvwjgaky#gLc)EayTvh9j42;?lRu(~QxgB^j-o4AM;42kDwbR@(QJF&uOk4(K +zcY7^LkQ05~Jx?QM3odm=_b8w2R)AN!Uh~MMn?MX$?#jh@wHtrEEzHqPtSGV>^Pq*z|EIL12c-YbmiVZE +ziOv(wF2(gS?`u4J7-~}RkLZs2j-L#BGI!9t7p01~qyvR7`w96310FZZpY%?*c{kT_ +zJh>fM$vk%F6P_W4Uct-qr*eeSa|9v~5kcF5uj_y{e!DzV4s;nP%t4jJ&kb^c<-Pts +zQ`2*HB{YYq9okMi#ONeM^@SRr=|L?@pB=I2xzq_xsOx+(L>Y$N)%9mkBvsoXsaaOKFFI$(4!)M1a^PJwX1z^J~-BFanDU$YokX|P->oB +zW8P{Hc01mzf9gtdM52G{%Jz}l5kasPz2(~R#K&}Ey@y*!`x-kY%o%$_kZ~pBStjer +zeFtgZN^$*FBuQ~th$Vffv8W*`G0|D?W9kN6LvTW@C2D@H<_~PL>T*@-Px$)j2{!V5 +zv4&SC&!&;A#g0eI?*EA^W$K_`(+)zuK$lED9vgG*6*4QK=?6#m<5^tTS`lZ#+K%qZ +z;8^+}3g@D_Q__oVoghRv*@^P*agR)d3}TP7`0J_Z_zH-S^CpmHtJl?06%HTD*itBr +zs$*N3E^9E1Xsm=Ft(*6FaFsXm*Mb6I?MM-5>g%DD7m$oW8b~u;kz2Bf)_$eZW7_i5 +zQ-L8rTQ{iPM>lVHaQ}tvkaR){?Hfs@7O)nuf+v^)7nFvR4YV^VinypcG!srdi`060nVdhxDH*XBQLS*H!EiIa +z+FP`Z(-*&>+~sbC5@O&f@5Q(EQX^z^ivj|c_Rnqj{fR%$#0g+25heG5z^3uuWm;3l +zbMxh+18pZ{#=Cw(k#yB>fIQ;M7Y= +z!hGm8NPBCT+;>36*$@esLA-0uL=He3sx|p&<%#ATsdM)=ViK#RU3nxyB{V2UGCkmW +zuqcp3{;eoc{->gBViY`Xg@+jXr=lz|F>zqb{->hUG#MYI{994d#IVo)91h|_KYHNr +z>Vsat56rH!iK%R>Wm6MsCI98}%Up&oc8<;7x-w83gI)!-3h4*j~ehq%TFfZvb~Cv07u98 +zIxKt=+^&`93T4=i(bIAY-G`5q*X=61>PujijKh7D?^B&e5W6j@~pX;0M-QB`=I~!?m +zlNGW)Zmb}hh$)&Y6Bi_zvF;%X36!bfhr?qC8(!Y5M0UyP&t~gk5?Su!FQ^xIc$6+? +zoqG^STd-gUwkyxOHqJ$&L(5nP@~plQw!}B!P-Er-1{ulFvE-AWj6JONYYH-{IL?V_ +zNCj1hYFWfInm;-27}lC-G|~lQemztA7%TaJa*kG<`5eoqn1`3Df9sD`0 +z4fTeH7aTKo*OG)z0YZY*FngLsEbtOLWW0be2*P8FgPnWa&HD`MSe|+3o@hXx)iDTZ +z%!XBMv3R2#YH)jfrUfI7l#UJ;>eg!1%LP_e*0=bGz>A~Zcdhe)#I~4>mhp*{&5zXU +z@rvHUd;yH@QS;x`CvgIc|3)lFtR;Yw{mT>omK{ya$9>u?ZH-)W^;zWQ1ydrC4+{1p;JcSgBWL5|HC(J1$C^vah+t`F=d-}(>_ +zjNK!CBj5{8-^ODwOc2Gy*iI_4bv@pVsK>P_+I`H2AM+rI99RKyyjp~ZV0KBTnl3Jo +zPMUC`fWYb$dT1kOW|Ja?ffu=0VofEpRrr{i;;`E|V75T1-L(lCVUGYcTV@K3257~%88`xH|+O5ZZ+)D#r0aAGOB@d%wm+m;uv~mE2SE$yqsjG`~xRx0_`HEk!;vzHi>qAhSiQI +z@uutsM2{L^{DvXNt#K{`oD9g%_T^?ak;PGjBaoaD7Jy7+)tXI%7ld+Up){0at|Qm0 +z$ny&}JLL#`hrynEV>Std(sg1LBKx|_TrBCd{=Hs*Ic!n-i-hw+ugB?d1VXssd7IF_ +zn%m?<1oy*vRwEhjj~J1&nZ{KXQ^1x^xc$;%P#LO(gKsUEm_@iw;|e40igDJg^>IE* +zmYIt_*nH;MmtP5PbXF?5%`WlS7aF8w7cm#VcVwP?^pZHoC9zWLEk4YeD=~s=IIF!w +zJnV1N5u-r3oi?$D#e&|=CCK|~x!vD=e1lsMsPZHI_!_D8zUnSOz=Vdg<# +zLX?`};U?vfEs3C;NEMKs9^PM +znPoF$ajSG;w@wLf#TYnjr1}}c@!Au-b_^2M?kVzAd-OTt{1TVf>>*Tw{PUI;3o`r$ +zdP!R7giTYI*ddBbQt$Qp8>0gj8OzKX8ttXWWSoAB7g*jb5`}xb +z5tO&>P%E;Lo9t7? +zDJmy9t?;$c)fIS&L@XUn55)**dYvLeQB~+S-T;U{ +zm?U@dLo4FXzN2!rspzm=&Iw9*A$Tc19b2*$#@b)(*)Fc?W^JIhG-52rAhUR?3dBx2$b0W;gU6`&ZA$vebvfas&q1I&f5;i +zZOI7Om$BB$+m~y?e#aT?|9<#M`(h;6BP3f1{4K-}(+O|IE4`$TCz^>eIqA}j$_t?( +zR()7Z;_1zpxotqeMfp=p%IYD9aDJu6Ir;S;E$Qa;Eejg#b~IjlrESxEIyWUM^)gxh +z^K#7A+>4?_^FOs@KL16x>JS_y^Jx*N@CW@qYlmw%B~+>m6O9`%K6|5zwNDGpFQ?H~ +zkJDiGT(R>W3;WZL@JfPpAkds2UVDPa#-%&!T~Apdo*8dv!gBR5LC`OMt>n;OD`_Aw +z6k9iob33*6cvB!9(76@Gg_fyR?w^8<8EFttL#uF)9LD3uOf +zmqxQ{GWq}qvCK!tzbhf?e@IDMvr%|rM~;;N39MY;$cCUprV_*#At +z5}hTIUn8%;&S;IaE=}61E9?|V#4-8m`Y{W;p=^R_PGwML-({R$fAujxr1s3pI$?45o#v1Cx;{B3>S}|O0`ra?$a;N0 +zM*1|yX>Q+TZWYy*=uKW}nv>H(VA~i067@nD#iapXY03oDsLyVy=p5hWP(!O5_XvBG +zdQCot%7ado9DEnr99kpz$`&ZAx7jPYhmP_2wQyKtntz$V+Z%)UMePI{>VE;r5t(jT +z?50r-MLK>-P)``Rop{e@k9AE6#TJ@P9$Yh^9-sS{6N1=}lQMkyJ*zU6r37lw+Wfi$ +z@sCUE9c`82RtK{_67l$=`BCq$I!`=0)cb#YWR8dr_5P5(67yc-Kz5cS1x|1p@0Lid +zbykJ9_M~z%=D`|AAX +zhzUj6w;Hc3cd@UzdeK1dXXW4r)FR3Kl13&HU#c;K*~7u!i6#kAL%&D`8~oHLV);dK +z?8+_l#(+Op2h?f>NlzlbOU9^lxQZ5arTqp;s^x$9502cxJp`{wZ&{+>pGQu$>?;zB +z722Jj5EOWNIkmehkx(P#Vc<)`OK@Ur?dB!&2%@M4uNeuM09ltEU90aAydRe0Ir5*H +z--O51@kVfpx7nYfVs+D8_m;V|o695YgyG3vIKXYf{CXt<3WJmo{|v2xVw2^(pMas= +z1G*hatd<^m@N+Lh+r{}lEeN26f6nB+4nciLNgmMIGp!ooxRnj0|I*I<4~$g(3nN7= +z|2K@RGdSam1es*AN&0UX$q#HNIWSM$)e7VcakazRZPWxj%dz$jy(o?Um_qx!sP5I{ +z(P=F-2?T^s%M*2U)I?07jk_StyG_4q1;3xPs8$aeVg*+%!**b0DlzAeTC-ivNAEdr +z1Ke?xK8>6Mn)!uOQ&+`)+oz*nnwC<{nqk1)hM>x6#v}sOncb^4DmH*>+lPoLRy`Ku +zC{QA)+Pp;cTOVt~`f>fzd-AtyVaqNgZ-68l`sB2L-brq3y;w|)`|Y|JW1U4p7vHzn +zFI!hPBd%R}7^@{O**~?Glc3h+aF^%2;6@53Dl*%1;&mr1kHnRS=YkO$ShHs)Qd1nn +zxb(IMnv{aXC(N^Msi +zZ-cON_Dj{_1iQh~5tW*#-a_rvSXnv-O!HbMz`Td+;FAMX2Wre$y+<2P#y?7;#J#GF +zae394h@iGK`<#*-mU4RNT%kM9CYC0WXdm}wLMiJN5}KDfE`^mz$|renwGldhgBJq= +za@QOuzJzVcZFu?W&SD*9uTmxbmW_fRDloPwMMWIW29=_16q4o2mZgf;!3uBLuLcXN +zR8&BmFiT3?HSJa3K`;hdVxSyfhQFHyWa%(u; +zJ>I*X%N5#r;})I6z>5K>MLw1{{44%jQ`+^u^2)mJcPJ1qBzitGaSeBiR~he-uPMGq +z7nnFJN`yj%WEAj0S;Kug8`8Y5l^u+29>6*(7*%xX;L}u;@0xir!!gH*RjkE!E>uv= +zO8}k_^~G8F!1~$=)uTye5jKm84JoeUbJ^S8rlnD`A4!2u +z!qe6o|By~n3w-5`EsB(6wPOxnlrWhPbC@=MfsWl&uBe!w1^1S^{hJ)qY?piW6eAbl +z8X{n4RBR~|)CmBt$dB)H(|2s$HDx3@e7No)`>I9Wid~ivWU>*<_L?{9+u^p|lKCZ@ +z;&94rdq54&fnG=2d=2gQx1lV{X^)MuOuGV>6xB6v&v)-gVdPg5eOdvJYbR%z5vo5L +zQh$8J5IoC7*?W5r}q5O3R< +zZc91o>VIF<#zSpFvs|sIEitQOXvY9scvv`g_d^s;DkCH_>3T` +zbLaN^B$m>OLg1n$y`EsIJAzFMCq$eG9ibM*7NfITi1uiN7d=SV3lNDLU$WfNzA_+o>aXb1vc8Wpb>21-0P-ENp +z^rV+2$c^&aRMxm8;8cG^mXes#+-B;|jgz^t8Ua?!5KgOi#5Nhe?f&(1 +z24W_?_nvi}BA1qWPK)_i#T6L?qoRas(-TBPLm7}hV{3Od6?kQiWHs35UE!q*IisI_ +z00ur#2wZv1=3*5OLKHTNHR(k@>4a5%I-zQ`AgNVynUW%+n4OP^4t}2QXW*wP=S4vj +zP(0&Sbs{?J=anIofkPAJPIx@bDXL{lzsx#cS-||#YgPP-ASr_;qU0uhls$vwDaply +zkfyUf5hRXhB`O}570F2n=fG@nxFXO`Hks-_2(nOjrJUsX%P57oLZr$1u+R-?xo4rXVD7 +zUF2;z-fy%{SczB-n56oT6N0&gXTZqwig@fcbuesIbXRgrBq+w_!QKnlpeJfP;ln;D +zE#?44d7T3W@Ry3Zq9viD;UK_lf%_sj2af$dBUtJ{si5EMi{PM@-jB7^8Zb}V+)OTo +zsNb?iz$Q-kL<7%jS3nOi60zMFgtOz<2nMe4G-&xcks0a*RH(+JUECxR;@#EXLh_n& +z%C!+ge?swT2om=?#S{}Fy!Eg4GEdT$u&2bxL%(1U164-k+8CBGQ2G%Sf$QkX3a)uP +zVKHV(f7_WuJ0Cn@T4vG0kn~r?+{u(JoF_AI7Gtx}C7-G({Xs|hKSnq8BJR<`Kz +zE^GFJ&E8cEgcnz7^S2Tqk;8;){?|b!uYTYa$qKlIjb6!$%VvjU3-tTh;i}G$jkY+j +z8KXvIl4A9r`n@AOgWw`dku524x+Vy@GDj~YD!Jqz{ZWv$&fVsJ7367*X7~t0OD*Nt +zhYE~rudZT?a)JH)-0G2Itz(M5F6-f?P2`yKO8Zq?qcnui|s9&*;z +z!RPzT+P3bGfScb(>jw)TWl~e9jOjHsr-pTC6oCzEA{62REc&6$-c8g?T;Fh-M5Tyj +zq3BHd6Jsg=D##-AU$k<1QmtsUGTw_|cW6HUDoE?ZPX$Ss)DFD=M?vB=X`R7Mzzk(| +zAPddlW6TZGLunh{FH^Jysdfkp5k=@Dl$&BHJbh?8MJW$~#$d1(@y?uqB~eMAQ??S0K=Y+SSV;!s5`UY7d>_~IWhg-nWu!=RV-S%znH9U= +zF2{`gY5_F6G9@q$EXI*EArTUOaAfr4PlL|lolMqu(`h&;H6aw|8%rWM3lIWlpv?Z# +za1tKdzWy=irwWOFc@u`wy_b~2hJfTw3XF7OyRSTnWaSv{>&aeSqz6)WhDE$SK=DT7 +z2>Xt}eIW0Wl&NX&L>`pZJQrX)a3NxgcV(y7X}{8MeQ)W4^*1B@pai;eQbpj&xP6CI +zX>VtTr>_t)nVPzZhiR)3PhYFm@5^bqq^K{DG-#i8dkggc^eX{;3AA01+R?c4>l{)> +zh?L7}r{qlRi)L|@yOd6p5J`x0D|bKz{28&XhWaZ5(ZhauQ#%pa;# +zA=Ui$7aNA?2^nLLc+p@;$<-3hY*9qUT3r1Jmz`loED+{5W44*X%=d%nnWD8x;r38L +z%oI*#Pz4AxQZL|;D^dMqDeRDWydUNaXp?g}jasV(u^Q#j=69K*m%~~*1-qyOKbB0L +z$-%t0U+AB0Vh^F5KK-NTIF2tSiL2Ur-m04pon^ITAT_`GI|q!3hP4c+)6I#3iHLnF +zX%&sas1M?fb-* +z;)njUxtb_xBuzfsOPd7(bP>Ng8<=gxQ9X>rDlQ@~#qMKj{ra@&xm3KZu9F;=&va2T9c-16j#9NCTZ7Uv3h&FsP@4Wa +zWg(AwV4I_j8!&2KW$eVVC_^O6PB)a> +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 +zGEDeIt5@e)1cLc(lK8AOfY8sneXKon +zVe^ZIxA*^WkE&6h?y-{XuY06fp2|}C$33e5b&tcJ?hymQ+#$aM>eD?+o*ZfY>mEb@ +z+dWo(x<^vv@huo&6K-nSKkl*d(>;b&liJeqMi!}#Oe0$Ge0hIWQP2iHs1O^%HD>4i>AyCs|W90{r*MJ +z5vhAh56JdW4yB&7_mFC!UtK}@5*5rhr0LPJ$L{}r^Go2yWEhz;t|37f4DOe>?EoiX +z_-CeGZ5i<7h@{=zRW>)=B}2TaLzC3n`7_M2^TSB!arkWVQ>6Hg=qNFN=L56faeLj6 +z96Deotgdlgf$uIoi_SkIPR@iCUY9>7A`&Ub%h>#ePE!+3O=n-bBU}SMP+pME{mC6? +z@4D;Ok{?4}nSXy?8Xnml(^Wq!K;(xfKkb<9bEeJ=VAl~u1 +z?jP=0v7$d3x+-0D%F}coyNuUT$UKWDBPGrbta|pz9Rn7&UXHpyx#NETD6 +zNAR+ye2R!l&o&yxI-o(^erWT)CS+*7zJeKPr&fTou-2)(cqlsOi)3 +z@6K<)&uU^3-d|QZt@5)}?{q9o#LQ82KB +z49VA)di>@W;gywS`;T3r#YcB&tG8F;z;Ye&oTQ$w5RQZ}t-**TgghFKV06NnPYwc6 +z+CwU{zP<41crKq+NqKw3I<0`g6+aqR=Syxa{X@t2*~(6v-(=yX15vDq?LpxYLInr4 +zjh{)$$9qkp_wx*MfUQN&6QWIQfwO1mw9);OP$l&gRlyW(k(zjKnRZTKCE#b6cey@i2GtFI+OO*P3!@5qCx)t({y +zL4&Je>tD=wvD$W}AVY{|iD0Y7!r81_<7vLu4LS4zT`u%E0I}pM1bMzAtFRDjUTiKa +z-W-9XsXo_6sX&ls&cZ*Z{CH~aa6!_5F#>oMyoLwG9ib!XEq#g797V3ci1o@?R`%@7 +zj1jlNRDkP0?s=mX$pNz}@H_@A@^xkNWVLg<)eK5^R;AU5!Dt^n-Nomj`6+}8v5`zH +zbu3Bnk(=cqUha)ldg~_^x3t@_y)xwbU{|eH-DF4lE(B3kIN@pgl4@UZufUs$XlRoH>XiP7U`u=PAh1e`t9;HZud-!EqlQ)+|hz5`n@ +zopekZ-!A5xB^AW5k@el+a-G5!{kUbAKIfwk0J1$a(18u6UfoSe9gXUylPxI%0KSzj +zl4Cvda7E>bGewY(c<|~?7gl)+X#+7yu6hn4?i}BJdBAEp`F(?t!En?fGe{3SJE1R;^dz%7qFmy9WCDbn|% +z7T_U_EGj*DjK~|urk~{1@Z;wKmCw$<@yHFYoZXUkjL~~2#py)ECfeciBzG^_fzgwa +z-2mh0`?`oZH()JpC%(qGWDTSV|56>tMrDO41uZP`MJ{yDA=@pD62IZMXl^b)*be)^ +z?~Cf{Q3Cn8S1k+}Dbbrm8#21Oz~?`B*}ywg98u86%1H5aA3vj!v|N$N*vvEK}AC@eO$->3AE!KG(tdu_39uoHv6CTRUu +zbL%UFC3FOU70POCQkM4M1u^dezu7}Ux|ruAA-Zr|oas(~lhOjZLsw{7X8X7k5Kw+= +z4)hcSMEExoWtQ1&rzYCHRy(DxG*ygdWP->ijH{HK07*##A!>YJj2W*X+12;>PS)Dq +z&UhX?=E7hE+5K#JUo(fVP&S{J&ehQiv#I(O@;_pcX0@NONKJTF#IwJ#NbVokDap7! +z9*g?T*{Welw#2(EOkCgV(wsime5d6p4i=Dw2wiVocoDbTHAtdKkIHljnu;x^zCV)n +zx#cmv8kq8f@xY7Iytgaj=2jGuqs@O(C$MIZlg`pKzUu5c#;Ui6K55azO+7;}6xUK9 +z{CIOx0SD0luh~^F3I&Ul7H?2Fv^JkK6M*T{je_yFQwzoq2skwj8seIqujqhl+CpNI +zLKTZlA;m!vkk5YR+vP#`dqv-IM?!3vvaVl3<3E+iBzgL=e=Csb42Fj>nyohvLX?NBgb`vw +znAw5GLH;jlS#YKcy#D?-EGOd;->G{)zS1P%S_cF>#w}!yr&852?E1-5879Lhjt(=A +zjMCsmVPwJI#2N0j?vxy~DB4x-4m3z8KYxZ><(x>joE9%NC`$E6LKgMof2n_=vkdoM +z9VAOdj>I9Tp3v#0SN_|E6g65Xi)Uii1L9bjDe*@;LB>&$gW}W@ia?oK@Yp{kj|Sa0 +zqyZdVyMi2oo^W0gsV7-@Iyf~Ue1YXy=g^v%wC$?N+F)c*OL`b+xCH}=U=caN1X}Uz +z1Q@J>$@8FgcBA)%I|Bc9RF!EE$2Nzqqf99qf5G$GhRD;EZ+LT?QN^iB5n7*8(hl}y +z?9mo=j34(D&VQy`^wQ~9?A?w(Gr|N;dfrz|njx*bd#5C}bE?CcdVE-$K)&y?RY6pyVW!}>8z +z5WjSVIUAjK>t2$C80+u91w1g)zv-y0zj6n=Nz&{m}k){+kn=mJrnH8ncPg+5{SVlrd4ND$OD7U +z)4&V*+s-IKK&Dmj`ytaiVWT~Yyg;)d4R(aR7Y$yzxI)%FEPsSLF5?qeN*yrxq8q`< +zh2h=_>%zsc#upaSe~XYaEOv+Mv`$WgZ0w%t8pe`bB+GoM0uaOv4~=1}sm)`o*Oh4k +z0V1x^9Uft@UldZYgX5%)YvUGw7_$vdh6yrzF+e>D!|Kt>Q4t4K@Tg~ehoVX7r&PX~ +zZ@l_O>8MJ_dTT%DtXIo~)t9lHw^+ruv$WA7f5%6G4^gvs?qyafGuKYa@J3Khe$iG2 +z9vZwrE9*cc1`?iaDWewl`EW{#I4NE&ZYHpJeC?P}&f6dP0woXhGh8a-9gbWk+N$+@ +z?mpw;9hQPcEk#;80apFR`@`hr!r--^h(qq7EPE(20ri&4}5aF`kq(-uyH0 +zbBZKRg2H7tHaQBoP7dXfHnjkva2DI*I{<8;++M*mif0i|{X!@5O~eH*0|tr#r9P0C +zrsK;yTt@rXBp1Dr(b7n4b<&m`K_Y!XF@VUp2iI5^L)a$o{rG$N!fQW*%e68M0$I5* +zhWasVF;X3Fx+}b73hg0`bU{K>d1={i)ZZ=J1*V(3H*Bata{d@b-r1}pB$C@GTPQJe +zG`K4h<0wtcbmQkG{Wb$uPC+Qn#?_IH8)_hn=LQ1$R5FKb;RiJEnF}+Gyvm}gG6~hR +z->%Yiy2S=Y)y}?Wh>&@ZF&9k06W#bG`O6sK+|MK2{Y^pYBcn~c1_cudQUYh}6|Je! +z3@+)^Y`1<)ZlE2?kPfk!P(C~CK`wA|XF6y+b_8TGIzi6Wiy5M&Rom6UE=KdXN3H-x +zP*`oBuvF#QXM+sEt9C5cXl%uHL@U?x`C$nagMBPHiLj2@J9Me7O^aU@<0(7%c^}c+X{IF4| +z|2E-w+2CpbX(@xAZ5LjDwGQs00eCzjNC?#wBm(`*YHxGWN6WF`AWYHa;_8WMA1H!{ +z4Oh%1@kD0^X3c)o(s%nk>N~QolKlmW&-i2L-}s|-DYk|>sSyVQir0^rmwxMp)pEhX +zdaslvUC_*GATE>?eQL|`^`nM979Ao7+{X@sD4?QIpg?QFRUfZ$sOui;n}pBuqZx2L +zuk6>Uihwv{HmeTm^{f0JIEDqdEXPc5MqB)FHJCZZ6pYCE4JUFbff_|CgFrcB?3^U9 +z0@V(~xs~xF11^pG1gXv@Ig})TfHJh9I+ry;Q|!F&Dws>Z?jc}p7Gd2+8`&Cn2Uj$} +z_cMLWd~=z6RVHaV{>eU`{de{;6dFmZm!_bGRq;b5Rh*Ma^8EDwv-)Ul>OToDZ_JPA +z`n86@Cbl)4g`1;`s7+@*?EWtP(Uu6(bC`1mG8DYP~AG*Kf|Pi8KdQZX}Qlv_%usKVIz`q0m8_8+n+{$FHK_>(NIef{5L +z(Ua(tES7`xf0D%%`hkS%|B%J*xc`vFoWEr8D_=#cNN5y)a`^vE7Mtz_4gW(HN!rZfI#5~X>2R}X434Xe22!{$9Kl+-!^fKvo +z@)YyWfSWQhvNZy^Jw3<#lDZoIFpa2_ +zFi0d%!ShxaCzsv+>=FO&_ZyJY^9WVNQEH?h*&Kc?kzc*Q!Of^dOfxBcY9Kcqt +zG#BJ}NMfiCv$P?ax5{p~(wf#JyEn*h%oC9V +zh<`2wX-?Z*k#&0T$}J0An~kuMwDz^U@xEy!GnIV8q0Ce +z++emW^s>^-9F#^S1p%Q<$84SxIJ|`)R^wbSJy&KvN})a00%^yk(^{R?&{+v|F_)!2 +zuZz*w@FB*B&3p$Mp6^~?bA%scvr+KfM+@%F)-N&|=WJ_-IL<8xIABQI`PD(1nndU| +ztuYZU8e~t{oFyY=SvKf{EN1Q_eI>fk*(&L^I>lpMX_Jy%M<4v{OTGCSBymj&;G{K7 +zyjirCqX*P*SNMdxIXtH!O@Z)oY~hVa20mCwl@-)`I{kWk2eiUb=f3vgYi`pQ(pv_D +zcS8gtXwG`#%7emzDmNh@NEBVTZfX%pkd1u)n`VpZ5>*nAfHPUsmxMS}2j%S{>cpo7 +zJ4nNz`l(%fl+mqq!rXwxqspDdHYu_hy=T0hA~1;az9VGg3@ozMUEr;Lt4TQJGbXRq +zosSak?wJ}BJoF59UXuSkvzi{6Gd7#_-_GMgn%O1H-_B!W`H=IkH;xY(O&!nHYuq4t +z^N8dwai)--R>MuGd6rwaBT)Am6{92Ih?F(IkB2dWWqx`TxtUO4OiakgyC^XBr8pMd +zP!GBL@;~gbT10$%2OV3u^L;p$d{AiC&v5V^1Z3pmb7VBZl9lt`u_zu*zhhYV2Nj0x +z$0X!aI;s8K;L_N=Q)QMmbuE^g1tBRPWKX>{E`fXq)SG>)A!EtZkI?I-jPZYs^nn +z{|QN$^PR@$?V7fmug!v+1IYRt=x-0dq*b>HmKFiCc?*pEsKAXYw;YF&J^VCF8>;j( +zY7g3u$*oCzNl%PCk|#4EA0CHebQeok +zEN1djqSB8O6qiWJ*joCLC1?tFSn&*5)|zwinhXkwt{)YK5U5zJbHGIYX%2t-j$8lT +zcdTsb+yMA;8O!qC3*pFUvm@Za=VN>eu^}! +zJptPgPN`6GtT#XoOrl5g1FBWOi{8YBD|3|g=^~A|*$QF`$U<&J)nVC4*A^N%`=`IO +zaNcxGH{pFTB8|YGf~(`FEN0|vgsx^$tmFsb=rVcTs4pU0wdGL>gi#wkt)1*IbXpQ0 +z8k9fj8#6vU8O0)>(g|2MDFRV3x4V$Qdr#ruI8kF+u)L6MMU?rT4o+ns8gD^K&$vsJvXCd9s*q2DoCiGVjna*<10b+HwBJQ^R+rf)}kxo5>U`QFoc|% +z>SWymfGVTEYN51m(7dlD>jE>5+H7#yN8q+MN*9xz)5_{M-w*=tqvLC=cnwLnU +zC`)+`)Jyg`IyEvz6-{h`^SG~}&68t*4r2WSxRaN~7nZk{ +z$euS|3S3cGK1PpXG*RG=XjYlY?Ia#xYfQ+ +zHi-S|OrxQ_qBzf#Ys*Eti!+<00sPCl@@QqPTZ{vq7_Z#5cZ$+51WT+2b@&6Bipfv} +z@_^a=shRJym}}tF%qj5-ij?4vu;5$zZ_x1^QbJD7llDF1MJz|IPBdWDWeLO)P$0QS +z%EU|xp%x>QB@z^e^c^lr37U+*-o1K0;~n{qJBRQZF$#5mJaEV?vU?rEB^h;Haf-wrbwV@tTa5;paX(L+WM;XL~S1HJ|0Odo!l?a?${tqkY}2 +zd=6z~Y68Ikk|<}Qigp^xtB$WTK52TL2Hr;$`WExrM6P&jT{rbxHe&p^;3irr#_2NFee_5N{>i;tW|5I +zPH%B9`~@GG*lhJ=*6!Pn^A_(^4}J_7J7?Bt!88u$;KCd35SG6i6Hz4<>E*t)U``evhXWh~@y$bHnQ)J)9Jf-=0wh$ldAVoT9-X|%6w>%~Pjwa6ZSpepX@ +zj)8c->$(kBkbCTAvt1FV9pv2;bipk|nsK303>Aqc^i?2f=SN_ME9kbgNse#rEE|}= +z%J+~;%`hVo6enhYpOn1i6yrD;U5#&q_j>!o; +zW;7Eu0ES~x$SCG8*baJZZ;6bEh{$E260SUZV-9#yu83HqEk#14_n@VI{;Ya++r0P; +z-xfgq#pQ?3q_y9BKGbFIm>d<44DuQcyiw{hEzo^;SI8&qg)?}4i`$AELtZr!&4Z@M +zFTwE@P;lJ;EjSWOKMIchRZvq5HoU2+{JE<)VIZzfO)5_I*klO4Aw6&B2=i2txb-?= +zHoe~;$ac1}@cA8n`M5ORg1eAzD0?7b=x%KvD{@M_?g<;J6gl>xf%^QVGbdcLTG0sP +zG4^F=5yecJy13JuJEVcRE6@iHJ4V6yMW^@0sD)hjXI$WrAtCS`rP^cHCBmieOGW&c +zs2wM~xsuwGCE6nluO`iy5cyMDY=tW$k;?aO^2XDTZA+;vue`jvh^IvH)AzSc?EKW4 +zlyvQ5*T!C3bmT!Oq+KaUB1&$`q-Bd-6tpgcuj*H1X+XXX$vF*s2Hr>QfP3eR8qRUA +z@c!)hMWt9<6gETuZ^3cqh7C5CZ1#`f7y%R<$MlF_zj%I9%>F(fZg+)y)-W*z)ft@6 +zTA$Qx1hiq$jfxPt^`>0W(n*aH*74P|G8c`Z3gyisIa!{j%2y9ld$e<9P0FM`mj_}zBtHts;u<(P!(`)jMncNL8-Fd=LByrFOpym=*e{(iTHZxH>} +zjUs?=EE`KHcmWOeDT+kABmi*|!S!Pg;0kUk>^2xYg#v5b)%eSB;*|5!1-xctc|>KF +z`yn{RP<8W>)DoLL7uT|zSb4&^G9ngdj9Xf+5t5tP1Zh)p9Vj~@KHV&hKwz_C7?;qH +zLllV^M4=(yr6+0;1VVM9E~>tV713O>vx~>1pb~mmhm0K}%dvR-OKioCt+f&Pra^zW +ziCmNIx3$)^9Q&D3a-m{9Lm%I$=)&GS$2XkF_0Z(N;TjHnYZRnOTunjA5z97L*xJBm +zbQR#Pv$&mmMYklX>420l`>k}X==7Y^g7+19F-sODDz;h(qx$O&s4svT9ZC&Kd`~(4 +zR#~bU#7{o8C6uxx&WTLc-LQ6oH8zt7)fTrT|I(X>Zl@nxx&m{1! +zl(X^SviDhSjNX-c$y|h?b~kP*B1tw1{C8#88hC|SB7S?LMgxcxF<8D)FL#sJ<-iGl +ze%p4JF|9^t2k6|XW3sqjuHBNV-q+qO*oM)PIu|1q`_G{3nKeUB5Q@tCZExkyiN-Vx +zDj#Uv~(4p`2!N=oQpp+$Q;=?;^PM6#5*R1s~))!mETgrU%7)Gsp +z)ODiH6}NCd*1X|I7R*Dy;F(ftKu|v2qGA3_mM!lnE}l;HW6U@hELZe3QzIQ^3)(3o +z&Xe1iuATQ{r#JWx4~CstEJ_(q?4??@S(;>P`A3S$IVdlkD%Y6kRmHS5w5+};Ku@~0 +z^LjNel}1iPdZFKiTDpSuN@u#&EexgDoHC+-5369gTykRTkW^Ku>S8@(95lA2FBCWG +zI2!vCv6DI)u4Z7bF{gc$s?wQDiDbcPkY?%2j3O}EcbISNX!1pbwawrA4lyI>fJMy- +zZFhw~!0kgA2$z6~2|ZjQ_v_vdy1E`_2Ux}>`OjP}40Ls?g;?4yyMr0OIuMaPwE2M{ +z`5A3Y#UunIaC%N|mS|G9LwvWOY2PO~tWFdgcYsKqsOR3DNaZD?lf{to2KTJg2tJj> +z14SiBG)F|Fj{A|Lmjk4`$SM?yv4Jc!N_Afxi8MpraPc_0BlCr3>N9sz?Fr+uu}bOK +zl0X3mziZlYl((EB^7nu_D)YBEI`K4kMLqdK-{6xUl$d0)DyFc|+af2x%F1>KjvBt* +zV2$KbTA9E&tY0P`oR@?cv=+cxk5EkPMaQ5ykO%P|m|4?urxa>X6(5Q3?tcrvs@`_l +zpdCQx=>SP=g5cc74$}i)uGxq89TTUC_wCdWeGlUuBLK?bZ{j@6q^J3XE83U#9r#uT +zO#jf`K%AJX&V{T~Q`ATGjiui2`*JVuh;`}dJgS7g&%g;qn?l;2DYqyv8y)5QQP-@t +zRI9Z>j-Gn82TT<%z1~iJMv2fp&%?e-sJ5KwV*U_50Y%6SzHv?APa!QZN{I5BUAk~j +ze^b4lh}ld~DjGq@zU@7<9cVa=66zpv3RhQ#e1dR^=mMwgvCA#7#T@5q^_Yifg|TEW +zUB^a(x?n7tXOR)b=Q6LwLZ&*CJ##qrIgY_{hAL~vPu-iGy33A&eWWDigUU!@vs*e= +z#hi>7J3$_f=YaFf(Fuc7dx7VLs_p*0f{7tq;=nA!mx{TpC@+NCN+%h +zls91u&&dNRYEW5b`}5Fx_3cUHKtnucu^49-;pFoyO*d}fUhLwgzlkjgHxz9cl(7+A +z207WnBT5TXv#}32@Z%p@4$9DsfH%>_swrf;IuO+8fYZzbLFs0Mj;%z?vFa +zrGWn^N3chpVCsoYc~8@1qT|Jb)OUpvBDNj-;yXwOf=|bCyexJl?wyo`zMGpe$-#rs +zF5BkR?i)Ya7d_&L`y}Us_5!QU$2_h06GY;PgVR`j=o!eqG9Z>YWfPIBooVCgYEoLC +zlQVHl-ZJp2s@93q#ywX-XY9XKLEYu8QquExz&iu!3Y{^jCX1fOHNe=wN}b_L;8JY4 +zBbaK?4b!f_nkUgmF9zobkO@$?j;Rq7&X}FKoghY8jSA6iQrgCemeW6iAv-jAeIM`F +zL%)jTf5?IH!z|-@&)^OxIisf{nT_>bc&w~cS(AuP)^|sp5z4XM#Oi7teA%ck@oG<#E%GG>An+(-y~6zA<;f%A +zVIn%Zg)!`zROPLuKK@{lhk__x3v9T_Krvzk4de6@*J5!(QfkrJ_QY64!bH_T)KXZ2ohz5U39`i6d>u*YsE +zIow!5ab)k`D%jr)c}U*!-o|&7TSD;q5w402Wd_)#wDQwnx)^tEJN6AFs%byd!|a59 +z;XX^ds1T1&u4E5W67$Xa^Ege=63W;hfoS}SZ-H?5-Vq*oC3LqDtxgPfvMKAESZnls +zG;kMalS3CT+4SMwMij=w;hst{FQzXv>1r6l%Iw8dEmQ-cmgv|8oe5p;OAs9c8WgU~ +z9($)ZS?O&LU;54vPoa{L5*#e#QreFo40W~ip1-Kd%-rZHQa2w)=DFOb*w%D^$L2MZ +z>A&ycOcnAnn97ueIim-hR*{mP3=%^IT7SzS=h@z>hL2XMc%W~$B|t`ha@{=&moMTP>(>2(grOi=y9`rnWQ +z!QP80=QQ9pMMjn26TNXX6{y7VMZ4K#lOo2k(S;u&Q5ooBhu}{_YEZC|4dl(e_W?H- +z9!3>U_CZB;jK;8i)fja=oCoCJ=B%q0PwX@ +zobfLQ-ts;Jhm?Gg@u1g6BrlHE9qxBukbqL78S`5lk&Qm^6VvhVDlf2wnpkzr8)(OK +zc?gAaXTQ{qL-^2|JRt1B9(v+cY)+F{tR9&_`iz6Q^dsV#SF1psl5;t|m!HX(@iKG! +zSA#bi-BnHmxEG5uHw-u5;wnqN(lA +zB#gaewI;rCGBE(WM$~nY{6t@%*O>FuYn&!$@5EX~cYEeq?uP*I8V4c)USrr#uhFa( +z=rsy9KYERZl9G~2NqLW6V?5AnyfJ+88tIYvHuaS%U@h6fw&xk-}Y5zWh6d7|R%Y2^KauikvbpQCVr +zAa~(<6N^=f97U*deZ_^vAaz<88-OT5)lMz2;{}2ig1JlSKO$8Jqe6gz0>Q;|2Mfz% +zMSiFDK{*OPci(O&Q3Kx{^*Exm$*E1^x{9u3U*$a)|2W<{JY~z#%d)vLuoMoQAFsu+ +z8nCO#;(b{`CFhsFZ&DOe$sUCB?8=kB=vx8RRz5`FstyxoB=@9&%5SAHtrqu;AuKZA +z^|LEug`38f09z@G#@LUrIl8AGSJYSYa~sHD8uyy>X4A=bTj`GAYiG%0rt{W*Cq^+^ +zN`TVlQEMCBQtkF47g9e!d2TdI`%|ZA#@%?$I_nG6IHkFfOVLxna47vj?d`X&hmkBP1X-3D^{3V!jLrB +z`T5Y~P*E(ip|H5($mAuaj8k@*O}rYmt3N+POirY3O+Z3$?2aSaCW-O$Yeotqt_>IJ +zsT>G+PNqc4S@4k?*NZNS$_b`CaGgY3*YiVL6aG{VC7kAW3-o!qp1J84DOfR|1u1!l +zQK@WW9nHc&ZBmt%Ai5xY;=qoGzCi!3UsXo#P=FsHc_RGLz&+nx&T%E+hwZGKa$*N= +zrTRLosudAlm!g(oeD<9^Kx`Bt+yyNy0*H;7UEWs!v9XNgF8X1l3Z02t4KN@qVKpND +z$v?9|r3_v+fie*skI7^Q_2kuZKbGB9uj}g}xUWOPov(-6S$aXV8ddk)_+R@j9`bpS +zje+3gIoQM*fOK&xSbJ$ZP-DO|Y@24IQb!2_y~f%8@o$nGK(A53iI(Hp4_7p)>z7NB +zjG}sJ4RZsu$BQu^_Of);?aAnz3V~ds7LaRPX9RGKCqKEy86emA1>F2M*Vup40^k}y +zHY`FF{^A;O!f2OsfLvqal#n(;d(azG23bh}*C^$kR-_K#8dH&5GI(_X2YN!Q9ygzs_#Gj3khsxc +z*_fgY@tw1Be^Ci3PooIg4zv}47kDN@8c*?yeNO7JqV2mfm!U<=9 +zBhkoWb6Jd-YwZ2swY}=!f2Gy1RAu@Ur8fdkeoaX4{B?b{)4`D*H;XzAYasq}pE90G +z5DZ!2AuDWAn5f&ez_MqlOa>RrCJvFvy2wT$(ujH5l;K`f?Uk5bNg<;x1B<7 +zK%Ny#MP43LdK>q-Xf1ZAYrQ6TySTrtzW6!^%WIi6_Dq(H5`U{eGZt$55fYP{E;6dO +z9?emyx1(zEy}oqu#aJER?4{$E+?5i#M*}8Fx<}MWktN=QG4QpblhF)@NvfHouK0YP +zgI*u!gx*9Sa{UASBcg1Qk(^G +zuCC_iT)|iuT`JQdpCwf5Uq-v`F_b~O*v!;{g`@r*hKp3Zznh1EsBSm)=M1fBr +zhi3`KmTAfL=g=VAj +zuk$CAMuy$bjLA@Zk(EA=5@C%FNYU|@650`IwGe>f3MdV=l8j?W&y40E3f^PginnuC +zkxTMz5S?CGAmi~Zo)&eFP!Ja%aUOerO7r^)xD^`a(#*xa3@D~x7`Feod6y}vtZr=zN{-r{SXZ~Jh+%?%2*PLOc*^c@>Ukm3665tX7pQx11UY#7)W?who8JdDP- +zbyh@)pdrjkVpNyvYBc!+2JI^lk^2G+Ua2`G8rn9#7#u=bVfx%z=-e18+ISyUR$&8739;p*YZ|yO~KmN8IE7 +zobcN8UC2Si!ujESeXb^V&kM+1)8}>dRNDoc0ePDn!Y`-eD;98$DuuwZ>?GkUPwQ}l +zET>yy{UR3!V86~5yeH%Ht87ckYzE8uv_5_$$V4K(#zB;P-7keoD21CT)`ZiHdtp=b +zVZoTo&cL2Sgb+T-2<=VB%eAD)6|YG~Dc-|!2iJjWhMqN6elI){lB#}=)$ZC=U#<~u +z(dG}A{KyOSi!bKn^edEv45;P@t+qJ8=P_Asg^We*-|8X|*x_^wlj2^5Hga!W4;MTL +zV95y3Hm_bI%xOyI@+((4BRK3CMXQ;ZOuu1km?*PvuB`i@7LcMrZId|%0k2xX%AAn) +zHKIl=uc;ue6lOq&^jo$F6-u}xxs#6=ci&zFac8sGeZ{+3tB&+Zt*Qbiqx?96%g1Gv~%=^k6TtVbhY=5XG^uEA*dKquKl4RO3Y$wC^vf@e6*T1b}K} +z22hQ!ep8K5FD|H&gKE)HU9%gfB~#n@nac@k)~z3&XGYWVecCl-`=CF-(kf;^V*cX_ +zuY5%GBQD-DvGn*?rAbX04i{RnXs*ewJt&7fOYD@!Q9U<$R!`h|Wn(|-O4)$^LE_M_ +zgPWF?R31#9Wj&Q<3R5&p_akDq>=sVsMqr^sKpdAQ^1r-zZ7@p->r?(dnu@!TR$tgOdHKz}I^5=#qnJ=naC64*RZhNw! +zetH4P_<2{Oc*yuN7_u|#3s)do2oCPd&~E8eZR?w+Cn&XAGfRwe5N;_TQ< +zu44b78p8loV>a=n?%z~n$iJyZ>A$H)IWU8)QFv9O%b!$Z7?5h5bXAk_n;}0V#X;{_ +z@;x-(-;zjY8GbHFNOPcHoA(u}L5$N~gD#qo2!SrEeY0?h!rEh5iK93pdOi7}hC0{` +z46Ym&EohCHis8eJPA%O>ywA212$_YK(BCHj-xHcL6ttJhrT%LHy)f!VTdH?U_!`fw +zLE&$hD~XYPROxtAA`RIovA;EclG(q}3>Lr&L-p$M(7rAu9KTsy{ru{Zbc0c6M|Q1X +zRSLd|le-JcmQA^_O40e`OTrIK&x-FBaL)YRF(Go8`=ad7joXH2v=iujFVDcSo=d|W +zo@iNcZ+_71n6KlQXSxaBdLz(VzM6b|geOyB3sRrB9Tu@*HQPsOHVO8cLnDiEV9?#w +ziSItqf{x>LB|lQp!(hDDL8cTG{Ds{ +zr+?hmS_@?piu;Xm-crC*pYamFH^E= +zB$*u%6?`)n1vIFxxx^tw_JM~S&pyGY*~edg2EY! +zLkYU56UKE=FClwpXC9<^ml9!o^v%5C0%Pu_HZeI_sKEWjB3(9V*cF_UhdHN{^JUi)&6u%65fQmN>@2bW;(2Q;oYH8mcd2s98MgP?ghz?F)9M$6sY-kysw2<$3&`bM{2Vs(+;4< +z;qwNw6bKap#nm_olVF0=MP`h`%I(`9_}9B%k1?VerVjRbLYz5||!FL58n!drJUJSpiFz@dhb`sz*9i^9s}ovY9x>7ZAj0xH(K +z3&A{kv&1>A=gW?LC$>YEGKd9*UY**5NdD*YHXUb)SP_i?2nXWcGN0G<&Q +zR5##VfAqn*Zp%ji&)9GX;2GB%?HTdg06e3rwkKpysA%h*ql4@#wRQl{ct{*~8}y53 +zWWa@p_E9y|ruvbYMp_6-h6UgmV{L_YgtN6pt`rl?^40-7BMNwi3xH=FC-;^%A#mBY +z83XW)P-Wp-A!pIY2ZqJooliU?B;mB0tduB=DZ`9h1guyDB1q<^V#T?8a@g7ro8{c} +z3h6`{T|3@1q?VlW!yEpq8Kg!7=wKtR14!{%AH0b)4K4WL!8kl`Aii@LeDMoi1dT%k +zsR(k=uMWUk?H|)j#SjcWcYf`5$&q`gBjEy~Hf#$R(!GDNmuNtyFV$;}@Fx7WGpFeu +zKE^cyo``3O19Pr3WAKVSH@lL=QbNJh#Bii~zlI;`hm`cjt{8%k81wT8tm-{8?Qsk~ +z$w`N_Q{T$ldm$H*<6F<~!W-}|^l0Tn-fG6S%*7(Et8rIL!(47J3BIX?j`)e_h3re> +zo>>(Zrx00aQznTEV`s8%AtbKke=rscC3DdE{L!2|O_pyWy6P6(S6?b2N4w-((+jxt +zIw}I!OM8*PPujaq&rbZAc?8hkZFSMXS2oV4YAc+bxooqq&69kiy{Ojm3J%wdC|M)J +z6uL;K#!5LtkHw9}?45WQEM%S_xdvW|+|@et(9hGP($ +zyb6|ABe#qcD1(xPU(Y%9n>Pt9XM+#%Dcziii;T%8;9)1%Oo>cTVr&T~MpN((Rr$rN +zI-!=r-^&uCQk9#Aq?f2DEEHI>vwkdn5v^hsXIe4Y%&K^~Jnoe|?oxtYG9Z28v4WP= +zA;}&h*r+hx`-bTgn%{Bh`*Rhc7J1eXYYmZlksS1ALbGj3E9E9&qMGF1CTO#4!KT)M +z87WTfKk(W?N7N`c!IP1=T(K^zqcPi?A<-=z!XEBV$IxF}YHRb8ZxC7r>`-ge8D=E& +z7N_K1SrnP(d2#3fX6@doMW^3;T>6}SD7c@+Yr>Zjwm@IsyInaYZi2b_3n-uHM<0f`_(qtoAQ+}SfxgB +zNd|cRUnM1_Zx3@7sqT<2r(Ejo1yJ}>U*V4lvNO!~k$k@~o$I5cZnSG~8#rAtmgH59 +zL++678W4YN73*(&P#`8;V@nMJO267rwr_|`yGuJvdEqu1W_=*oa^{UWUJGZE~FO- +z)?y^?IxmkZ18mz$E7u;NM70=$#n~^LSKJm#c~a7N-$O&Fx=O@i2A1+}()Ihn?E*P~Ww3CDMDVcej6Q?{@&{6n~p` +zp4+22-1fRh3=2*cUN5f|=>v+6_m7T}5twFpC_F6^Wz9n>wQB}$!oW6ug2N1N&x(p& +zyRy +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 +zlwZT4L_z$^Ai6KEABgQ2@ +zI{Y38riz3HIOg!=%X!*TWhmBuSfQ52;4J7$HxDX$XzboyME`c(m`#2D1b5h~l^CiF +z{4NR?#md{a;b*tn{0C@j@zaR(2d3~$#*u4MU9@a?Ywo@)=}awKx-tVkuRU_-Lh_q1 +za}Yq*I;yforPXQVi+hM$x~GmWvS(2kI4vQ$`3id52fGQ&lmj5Xzljju95PnjJ}iZ|?TdtGz~b@4c?1F_a7tWj4;I*<|hau +z8*o)t|8g&ZmTZY6vGV#BfidlGhz8 +z1aCF#zPZ@CB#qscDbat3Jnoj8F6on{`21MJ)`^9*RWQLW+eLta0q- +z%=1^YqbQlgihSxsqKuw>N4v<`ppdJ# +zLmy-6U3=;kEhX%mm4zkw1R~EgNdvk8Jwj=YATW3bVTsfsh8MZ-i<-MCw{?!+w)4R5 +zeR!VmO1J*lAboCbJB5GLC3XMiGx`h@K3A`i_&MJ&XGS*(-gIo<pukoUJO}s5oT- +zE~IcJ8+@uCU~hBl8_PDoA+63VYJ(uc-G~mRhWRmM9vX>CCMq=su=`Ft^0<+*K`D3V +zul3N>3JFa4^wze3O)Oxt-=_QDiEec~T%+>34{|k?<9CoEujcd}!5kt@e*~;O!iMi>?ZRyS~2k6KlSna|NBMUxi?I}K0iB|*l{U$#u#03vTRP2c= +zr>S6BMz>H|WE(7xrq#`_u`~*CgEYMwHAzi~?fsEj^j(}stXL;6K-Y}*`07koFC$Oy +zQ$#DGpsYdaoXWWed+aCqbJK@{WD#Y)2Z>RAd}9U!PyL<9OOfNVfr58g7p!REiu9D~ +ztj^-qNPabI!8BgmGrm)+uLt2szJ9tkr8kFnT@XXMZzQpFUyaK=7oS&w3bIMneuvkn +zLi(*5VbHzM?=&oYa*v1Xp3%D!?tqh-oxBx_@r^gTL~aAobA4^qo}5JmiTxAN&&0Ql +zycvXVP7M3yzYSO`kzfQ8Y8z*0+u9P>&m1nK)#lBV&jg`R^e}MAQeHZ}gT1LN(N;&y +zBMz!&FQdYoT*r9+8U3!Brwk(-Fe_}sVSxK#leGn3DxAr@jwUo5_5L=Hem+)bu-ZNN +zgSYAZz`JQtf*JOu2{!~~gW@&gs4p$ddTSiH(t?CCozDV22N_#aDcJVeFFGMz#=?$S +zhso8JGH^drWX5*m&Mjn9DWa0;*Ka=?-2QZ=M!OZ5*X425dn&o!?AF(a5W@;)4YFrx +zAympqq~d_Qz1hM3@TT!oQ%M}et2BhU=~6?TVp}L`nDiCZtOrwsc=I`}V&)DPmRa-o +z=N27aJDsKWX_~eVubPs2LIXWY7BIQM)%;r$>e>>B(4$^Y_FRNOpRxtYraZIMYn +z#8WO2gQ{I4=ckHIeYfs6t`C=A=$$h)dvJ +z<%p=aWGt=p5e;-xbb?%Y6UqUKXJP~1`f?x2qlZ{J#@wVO#?@%qwAu0&lA(X0Pj#a8 +z3Uq2)P4_yl6pxGG`B_WO+)#aSKuF3E&zJ&h1W)Z*l-B4{WHJ;orZq;XpmvE!YSwm> +zXbf5Kw0y=bAFK)(l=?8ohYntLlq0F;cHZMmf#BW^%3G)bNAf*fgfgArGowC}~x0Z9Iwi;+fhm_`07jCmKgo^9tAdqwDCqa`A}_|!Ur>Q1-0g`qySjyhN{E9H_?Ti-|%g{p4WGtNL`Tl+%s0j(p) +zCt}a1)^QiuI;x!|l?)f27HF2TXHv#oWAW{M$ +zrU+;qsr2p#qk*lXRa}Gr4Ef?fPqz!8bv$whvwUUt2Ia^G2~%?Dnw18$j&i`(5tZ|2>*xZRBC-kxXdP{!Z2+w! +zmvmV^uyqVzw$n;|mO`pMW86A6Ast&9DB$FWNr&$vc75bA6v%{fYz}^4P!s0FKmIBJc0u7F +zv30CM$p6(k=KX0M>4B}I*RR&`9N0Pz09(h8vQ)si6;&NT1T=BWIq`YD^cF^pFCqmBamm51@MgZ6;=t#0^AHV+T%|=V^eqVA=?&! +zfh?XfQX>1wGgbq6#=9#X3Lwwu4B#1isekc|d8RQ3e5J+jas)}6NeKZwqxcK5oZh`> +zL9-J+KY2!yIa?b1Sw0}oSPkSEgVt8b2p)Mx`MC^V#-BVRhLQ_7fM-0uo>2yGKKh0Sz%vs6gJ&Gljk|LP@QmoBv6IAXT&j==iDdKup3yg$3dl1axau{p +zSq8^h0C+}3AkP>neE+>pq*J=#@R4Wqd*T@*2?0Fg-fx}}6v#8WerDg6R*8XSlYitH +zb0mleA9=>$J)Qa|p0OLiGj=?Ccdko3Yz#*54kW2PEf5^QGx7m=#!S(SpFE>aB?y3L +zO!z=zA%qw8#51}8c*emC-Izz7QS^~#1ji8D3kUFwj#RWS4nbBCyZ}67-QPST43K9` +z2JnpAoF2YFp3!gkI6UczXUsu10q~49K%TMa07aGdYg=ok)*qfx?HA9uH=?}un`e}# +zg0lO=GZMd@ZTQJE@>l=j8M6R9V+DX`3fAfs!k33^A1i~ZF7(h&_&dC>fbl?Zz87ZH5#-L?F0f1*z>I{>A;u&Rs@{D^D +zR(?#)AFcsBBkUv3sQWk1nDWRoCO-0v;z@~VMO9Bcqa~1My!ne~eDlOJt^s()cEgWR +zk31tT=caoPct#ExsFbJI6p&|x%$EuT@{CPSJY(j+ct%CeGMNh)@qhA+?!S0OFD1We +zQ2s}r(JVRH@h_h7Zdn|_GgkhKXFT=#!!zaqf==lto)MDER^Tt55%nj}sQVYsI1J<& +ztsZ$sbi`jgV;g{Hgni-}KSB&@k<(4SUEh1+8BM-M3qSFUd;p#?iqP8!z%x4k;u*>Q +z;u%GNJfr`AVDG0>>$upjRSp3a1MpkDrbo4&*j6+X6BPh6i36N*Zc;XqUAeF@A +zGyyzg>=%|iNm~HV7%=z5Gmhc$GEV_`M%AMrdH~PJ2ILtD1YLjfj6p>r7qUNj#vdr! +z$Xz0T@r*Zj0G`q1k!NJ3@chX$ay;^kwg8^d4hO(9GLUc6-1XUON!$T>#g +zyrV|MpFATckY_ww=KGsx4CNaYeB>D=0(~EOMqvQY$UY?Beq=yx=}h17k`@OmfJCQ( +zfloV42ic-MD@mgM(uUNye+KXHJ00yZBNprf6Z8-^cJ$$G_tF!4Mg0*p(wDfMi@Q&wU_`)fhTl~Ntyn_VgPg*gksR-z9s +zJ8voLYKCMeNJ4$~C!%VWw}C#R%cIZO^>3eX5qbEJ?CGhUnF{q`9RUY1q-^cm4y +znNc2n#utx1@EHaE(`U5)%V#ug2*dtQpE2X7&xrFcpRr;hEL?bJ +z9q2QziBtc}XGEb5Jc~Y0PXYt_jG4t%v0wIBq7sSg0X}0aOZ|WNjET_d_=7O6|KT(4 +z{PY?306ru8ADFn8PI1W`rkfd3gM&An0gHG +z8TZpl7JmDT`hWS1F#osD=<^>wN&4gcF` +zENcAkJ|o31pV8*YX9PPaee@X_|HEg*uN!_Jo&v{k^MyIZAv^;PRF6v(DO&`|fR$)9 +z`QulbKx_fp7&Cdq`I2w6Gikn4ornZ2ZQ<`QPlSDrEPRc42G+M5mgjt=iVZJ6wyf$m +zr6(pldy^8yhrp}o#qF!fLCaowQ}e#x+aA;n!URT%{#!7g3WpYV3>(75+bwR;-Trtc +z&=0=NbJaW+AcbwksO-spB~`mM(08t=tLYje4EZGrxx#8r4EAO6UEgdB!BnU%!{5nV +zaqB}tHMG?WxO_`n?QySM{nF-piSj@hZ1X<)qBrM_HY#7^7eMI|@c&SD&;NZTdcXH$ +z+qP{xX>6yl**I0v-dUoI`?^;e_^fP*805O&ts=N#4n2o +z?mygx+Rus!zTwJVa7gV<86DX?UZfk0mnG548=!;!I&TvouQ0peZaNtS|JEUmjJ?T_ +z(xVyIy>!^xV*r6LSb6FeansrS;85Ux}lW2)?RJ(oVs_~85-1S)VLd}nL$DEaB~I9@&5uN_&NPZ5tTHWYqa +z7Q%-zJFqY=(bSr@eC`?70iUR>>(Rkknj@+v_4 +z)|Mz67_^PUTJ6^-1&XyuuE@KFF8TIJef}+g_t7rK2?8Mvc!&7w=a)(X7{F~0RV>5( +z^`Osk(KvmHpxI#M?QWvuIT|W@`VW`2o!q*-DBRSjaLjo{?H)7pszDU!kP&8ju+B{@ +zq6Vd($|xdMl$2}QdC##x$OCU?K{qflD?y^Qh}}a}e!ITTE2NxKo_v;p4CiK7R+4=` +z7|gP$hhwL=vApO^(&X?U7k$k|zJh-4WP57sTsS75Y(Wc{1Ov7W2^k{UcST)vM?7J> +zB)XxPfaEvXwVu_Hi0oF6jm{K|cmRmX`r0YVFUmw72CP3mh-juPSWo_MSB&A>*X8MdQsLDzRZR62v4$vzwR +z4MAnfl!sjP1`?Bi$g60c93ifigf(c2bG$skAgEi4>)r{sR`Be>lA2#jWgQzR +zi89KMv--=jT{~1>c)Y{SThh*+E;p=tq0z!76{ +zJSd?*Yp-wxLg<&X5>!?;i@fEKS_=cmyfx-#If=>>cxe1G<*|#Npry{q5UWkY$80N0 +zwwx+KH1UH%I*xRgTb&CaWb}$SLjuPd8<0I +z8v_?IX=b8^N3?*RubI)npBKnw;%FpeKWVt(4bNiS$x2-vw(yC;mq1WXC+^xbK{(Xg +zXDh19Oq^W^t(>X-LK<8{Zrku+{#8_q5`4-&9@#f6KpW<4JcWBT!viN11b`YI=Uz)! +z{ON>fL~dS=nA;g|$ESIRRe3vm+1R~zD5(zKQjIw(xSwsh1YZ=EBh=nx1=En%|sh +zf1?f{bIA{xhCh+rWa9G5=zsWZ_QqykJ^__slmi!=Ac}RFFu1y+_-4?N^HwsV!reGC +zLs&GtU$dT25F3d8C*hAN6`f%Ke+iCKyRpX3gKg#jg<@%r3^yRuojJ`%ZZY-swfk-LFp3xwjz*hrLstXk8Pi+I#lzUsm4OV-VG +zGun3s98;k1Uu|dFg4x&g?VWB1l6{y4hyU3+ivMmMn=bC6|Fdliet^+XZ=uhxGpkJi!hKU>F) +zkJeFnJHsRzNwlT)`FWUTQ*u>A0Jp^Flmn= +zLeDj(@AL9z$A^jx7G^+ag9NPdrj*8r&`*4hJ)`QfB{d=!P09fEy0W#C+mo4n8umj@%5&%=?${fD&row((;)^r{yT`Kw0r2#+^?R +z-YR(iq4pD5;UG1=o&1J>8MtBbcG8E*I5&2iU#SUr2s~ry%xrY=NUNiq7f=*=891y0 +zYHt6Owg+|kfGxnWixWebwTIv=aK%Y=$m_$**Hh_fr?@JH6Zl-x$k|7QAeyH4j7aWZ +zR2<-i)3b5ZYm<@=UunlrB-ueN<%cV=1%EqNQTG1nM&*=lx8&4CZ7pN@aeyZ3vkdkj +z!azQ0r0p9I)iLFo?B+q;`sR6Shws)OSCTwQ_|+Y2Co^^E+*a>(HhxTn2Z#jiemW_d_hB&EBcRJz7++w#{>Wws= +zi4CISI^WA@mM@W-VT+95PJa1zMo`1|KBt)qLS>V8hJ?jfk1-bMw*Khfw-6Nc_F|34 +z-Z$>(R>4%0_ZG~on1&MSf@-e{PJS`(%P~i?tz~9Pq^?Hy={v}Fufo)_B +z3XF->k}p3!cicwzrMruXjJEjJ-S;qJS@Kr4!h#g_Pm_X18{`4k5>%gSR*-{WrS)*{ +z<2f97~$vv9Ih|Hcqnq1S*zY7@ITDd?>}B#aL_uS4c^pp18) +z9CNvJhB(qP;ykVoph`n}YZ+#_hkoWh!!2f-NhIwr(>-eE?n#g(nkq{=Gx(8&_167q +z0K=IO=sH+oDq569p{^KTaT&-UOp}Gf+I2hfW$e2abAEEf&sxrCl@^4Ccu1lC^gWvB +zVTFJQDG25TofmQYJ$pvD=Fv{3te;IlBejve_VjQiIzB3?*t9GSYzcbmiF|4DX@*;y +zdq~~{Jw#Dx0oSg~;S~qq@W6d!x`#gmpwcE4RL$lx-xu}w+F}-2&Rag1Ck)J5gZx8X +zsm}4TTDjfotp24jQ?iESiG1M8#Fi20o&y&^zN!u~kHCcQvRA5WVxOe4`F(k%`VMqI +z3O#k2AQIPttkg+=OQ%fqm0S2u4yS^-v)-wT_u`fw)-0(QvxLA{&Brq6`Y}5=d={n` +zXcRq4XRg31c*xPv{Sb(}kuceNieve(yfC$(r5xV*fu=Kjql2;6Gx9Cr$=)M9Svz=` +zg1&C^tFKf2Vuy|*m2I%ath38`QS0p-+L-buaZS9e87Jpu*vc2XVX5?q?AIDYj;bSD +zL{TW?AQPv3+lN*~5|0)xP>Ln>_=_;?Wy|{3v${y#9u9I;nv+hsXfocsmzl^1IvAy1 +z`1VFFY#;@Al +zuVK%feQGEn9EM-=k{`Z8NxMNVbsFMMCAlyNART9?d}9`*wFDm17HU^te4KoLlf9l5 +z-$z# +zdE_LdS4H0Ou13yhT0|XNqCv}ZvTrZGQ*XpS_mW94!(S#C)Ngv&>6*`Z*NC33COYe@ +z*BBs|I0-lDWy5P=DggZv>5L7p38RUFtmJKvf6TwiC_$<_9x^_AY^<6Uzg{V_A1 +zb8I!?jB7lSZX)GyKRb0=jQuLe_1UV7eb4C#+AkRb(KVo?I!-tYZmCQe1Z6H4g^>RD +zuq&ph|)f1VWoW?)_V?tF2XOL^6AG85$}!n@?acs +zA)^O7F!3rnaa1cpem{<*I<*MQ9zw^sTC39jUDS?%{EF8M-x-O$&0` +z#`6YStKK$EsSZeqVN?*J2{?XZA&tXhb$?wIo^!>co6mOy1K@pwYRvrvmg(eexgwcH +z2j8GvaP7bH_us6tYbcc|LzrU9e1WIvzOzOD!EbZ`?Y$E%d+Gqp{q$9^FgyoTax+*$ +ziX*aZ;%8oQ<8Zqz-Rhz-?@z_`iXp}6CV%G!h!_=U>PugswN6QY1!T9VW2`1UBKK#m6#$1fvBb(&X0&H)u4v>!+dA5UJytEn_ +zZK9{1sn?;&saFh#h#ao8r@ppc9*@%3ofU#SZ}}(pOlPg`4Sv?)S}L|#7l*;IMJ@|i +zJoodv+O}G$olLQSCI@N@VP0{>hTPVz+w(gn=kvhz0Wv8mzmFcg3rOye;(MJ6Di0y- +zfG&65!V~^7!}v&~=g`%MdeshrEW7HJUK!k-IV)M2W-KQgZ6Ra|=^Qc0uFx21UOO}l +zy|}c;Y!pepAEEkF^NkfLpgf7atR|oTz*nRF1^DcT_Eqa(HP!}cOhC9* +z)<#fzH_?b(<}(~!rjQGWf#9C-**7Nb&wDj$zJ-&{m-<{O)g;<0{yI$~o41^!NdeHH +zkSrtxvT8eLa$tE&j3qd{r;EVUcpt>93~>r@)B5PTNm=!-7&}aLfnjw?bB~4<0!;fX +zt*F*=zl51$p-7Sfj@3CAPD8}rck{7b&E;E5Ti+-gW>6HKNb^(Kohd(2ITNQ?IPP>y +z(%4EJC}$AFPl-dg>wbWR$PfvgL)Ye*XOR?;snM{}OY@<4azOqq4F`wBToc-lb1;}E +z8shRbtkZq0(-tJ7UuT?*5(x{CU$XVQJ+PQPsRn6 +zo11MwNmhsa^(6fXr;-~@-!ePiHgP|N24K`yX_=wrY@tFg +z<6ewGCbJP;k_V$#UN)b@awQiq&tQRJpohQ+`x`zZ7n)g~H{5Grlw+A2VPz5rbOnQU +z#tck51oqZUf-eLb@^*b^hbh%Gaq-ZN)mv+}u7&XBRXP>O(t7aReZjOXJ}I;9-?1Ij +zP4_&%9xcWu*MUqUf-;goAI$qQc>;W3i%cZcj~Ixyx+%&HF^I-^25gDv+tnP91>LBO +zt@;uYTl^&jwmAvau#P=3?TAYZcPX(vS7M(HI|+UyA^62d+5=wF=y_+pVHLP;q@NjH +z{pyj3E!o}EU=!eTE<<~)Z;g;&!c_B7&FDSw`uYwg_6{)s3e!TTaVjKr-ym{X^lP+n +z7`y=F_@9?XaibVC%}SJ9`iZ{YlH?ptBqK&(ctk>y0hLNft@mdQL&lH_Kji^}(&Y#q +zd3(`E1`M-cQ=x#YA`qG$9mey6BY*@;R}h{)-lY25h?7`dI?NH5I%z^FU>%{R0~upv +z+K8Z+vBD#IDr}njD@ZL6j>m-^RWFRh8TC(1JXuQIH$!d-j1U$c +zXxGooFVcbVe1*(f^51#e73_SwINA-&>9k2N>1`s_kSd0Y<`1!*BnsL99=s8BcT-97 +z9Rv^j+5XP3gNj^0#5=7hbJD2$3Z`y>DuDc`3p!0xw0lEnRlcG6T7huPjP`h8P%eU1 +z<|fI9qO~iwgIh(3xo6^m`xxxqz9vs%qs%gh=u(MDr&?Uc(FAiz!FP*I496IWh*?iX +zB_xyugg(?;GKt8JX^R)5yv?<`_u#e$8Vf}d?HX8_3D{0n73NoF@`E{WKoO!aG-Z#QMdeqYA?)UGf`pMtQSICNs4FJK~F}$}{Ka +zmu5Ht8%UGU+k>W*?>3#-(!Xq^ +zxsqquzz#{T9bv>z&w(>?ywJ6?It|TKG+=)G0-e#fd~9IJh?P9Sm6TiM%;mo%#076iuhl!P-}T&$m! +zR_EmmL0(N(@A_prCVQveCN^NmU8}AA$euRq*7GTz>oBZ400@FF+f5KH>@)!2c;To1 +z$yJnl+t}~5UR7>}znSiq0Ot|d_!n_j7#?3=A}W^#f9&T2K7X^iWKixx&6_F$x26DA +z5s8{*TLzXEkFP04h(AIbxk2B&kO*5vo4#EE872C(xk@1zn%JmBl`Pk1F?Kk%MLOO_ +z3$ShaVWDV%Hcdc9Fc*P^b?HXga2ewwyo0)T&_B-yq=tkOMof-6tE6Kv&TP3W)~y +z7B5mz5Jgu+F&nzQYEHg%fs^9h=+yKwo*ea2he!Why8NlXylfp^Ro*?D{6%AHH +z6OIDNH7Kp&1`k6YknAWXVnVDA+ks0IUd}D&1$BSShCjIGHwHC*XM6NiWoE{dd +z61zo5m``}L7IINfjMPoxXF4kJ*vyD|+5w+KaqmMEvHcB_GTTwM%C*gi-2p1wevUoX +zQz_KUL5{hEk+)WHPkryiel%aS1E1P*p8QKVTxFjm%CWYd$>a<6bP00!>2rM51U(Ee +zExVmtMNf3)s3Pn4>YU|+&y9V%tWBzbX_euOmZ2vJ$x0~uPr^HU<%*tKKeq#b$#yp* +z#GAUpKYh^vpQA44cmxNNA(J1aoKp&jy_aLi2my`#A$iq)ib&GSi&^|ZNgFM!o4l#O9< +z?^Q8oBCiqrt*q2WmCxIz_~uiZ6NIx0<5Q1S@&E=(`2hB6MSr@Q2qJ|0>MhS^Q$Umm +zLC>NVGusy3j7ldpD?RK`e%-wREJbC!kbN8ocL*y|!yxTGw?R|9J6dUGXn;Lfo0qf2 +zQ_siFH8Tx!eUlX0;K0=Tl9kU(6dMWA2wIJN{ +zqws##t@Ve8ssToS!NgMKTc@EPH&lhJ)IKTY?P8eGgFi+fH_DpK`W_k+vw{g>XKvko +zVRd>_A*P|MXO|9S_PchVKm`n)cd5^|;qScK9)-~ji$1|OSwxs!%h)elWbl^rA$mK$ +z-Or`dJMeKkV+kKYf$Pf~vKuo%(T^?1OViJ4rPwH)38`h<~2sscY%a^|VEW7+f@u9Nn8#0`2*flcKsFA#B{oC%7u96PI( +zoF1Oymbpj*%iW#Ex}1}o05~+eteK8n_tPP-*}9mR*iW~7*;*7E%hCN+0kqlqnt4sy +zWcLAmLP4(yCQRP!U9-5kr`;k%Z?4l<9iPH7hD%*45Ywtv3Tn0T`0CoBC=%sTNZY0_ +z@%uP1nfk_YTfULUf!BMo$ +z9H=lb98`HDALZt2ob)lCi0@A@hn*yTbPnQb_COO|vc_$QjNv8i6%w#tlqM7>@RbZb +zKm7QXtaQFhvOTBMa$EKn%CNxq#m?Hj +zaO7JE_8$A%E}xmNI2*;*-^oE-amD%Z +zGq*kG7h#FF2`HR%%c&nIesqfa;pT=N%7N)~A*@#W0j${?W@qaS9Q-N@A(fwBCmd%7 +zkKGWX@#?SZO=qb1*+-VVi0MBu|3{-_sWZhZ@)0jO4?Nb_(Mf3aGFX8aG6 +zavH`kLca7m=GSv&ss?M&o<~cbDRs~BEiK1aw6tHnb(Q_0lct&H$w;KacbW%Z?}drK +zcgIQ?WP~c;BR4JA&nyPv(>L3$=B%hxv4}gXL0}|g2;g9N^StvD;0kh1Fliltj8WjC +z6LC9fOUxVYsP +zp{Wm};A&MtfXBN@C24wI|k!S=4HIq|3a5}Ql=WZ=7->BB4^wr4@X +zdsh$*-hy0nRcw23FLc2hbA8suT#|X8AbNmbs4{|E!9zg{ +zq%u)tlcu`xYd4OZIEzkRJO*>=bQS6ZSt`MAis17~>Y|Pm)R3&PyC#gWcnu$gS*zP~ +zw{(iYoYPxSZVi->&@6n7!eNK_E?#u|vUZr)I-W$r<9F6}C;3%qq`Ud%CU6V7uo9yW +z4V41cgcIAi_W@)YmG(aRom9e()4=|mdx)UsJ0oTHlBww>b9Jk*kN*+PnZ0y)ZJ!ZR +zJtDj$pAg{=rGZq{mkBdbGwXW-oNqPg26U6;GTbofW@C4`5EA*@k!9zUV1Vtd8NPJ}K`Z!ez^r-|XrL8bne5MPD^tlSAGG?lG6Dv-X&d0?z2q_EjQ$i< +zE-gY;yLHdzE*Uy1b!*0Ma~s0antqcIG$#)Cim*su>UB@z`Us6k%soFzK$&^Lr^!yX +z>g9u~x!1VKD-p|9MW+NQc8rlRLA}Gw$SU!Oh;KK`W=xe9F|GWQ&!}tX*ZnT7S(qA$ +zPwAJR=K)a5@_6@S?r{CN!#_$IGNN^dE%zi;f~Eoxs@c-VhZE!N#kuv?yK9yGC5Fw@ +zuFG&ZalFV}0Gjl6>JXNc`s(TN^8*M>MdVLf)G-CqV^r|jm+f(bVR +zWQKCJ&^&~jXt2|C449`sn*j6eE`!6gQ17U-oOkT4I2vCRgh}|97~}D&GgCvZX>~dR +z?B_Dt>0O{l4u|jh0dx=BIsqRC*vfTt&1WJi`$Z$Xc-ja(Z{T%tzL`r7!>B>4@;h!` +zx)a!Y>5EcP?{c#6y*b77dedHNtY->2lQJI@rPW+ht__B}$5D*0lptT=wM` +z9&-;eO>5+IsUks-4sTd{fbiFssk|CASU12vNf%>VwbJrg$y#6Vw`h+mW*2Cul^YCB +z19wKCdWA^7U@?LhJI3waqO#gwBgkks*|P3qQB@aHcPS5Hp;W(y7MVH93WUVOWaM$c +zI79VyR%G~|OPZM)U4eB}lhWvu!N;hn{Is$nf+7wOOWE>motYsWr6U1EyRr<#pb4u3 +z^5ykrKGg{&ena5JqwM||A{s|iyote!XB?#Tgh1XD5YA}_{D@Bzlc8X^mRAt=9zR?1 +zbYu^4RS%jYpysdUqLTx2-SUH~VrCFQB){LvaiAZer2EFNoU^%^!WZhUc=GTDNVi|( +z0^ePHt-Ls5lEi{Y3hk^Alr6>k+DC>w0Qx$Y6X<2?3$=L6-k9UTUL!b~ou4#vzi~tr +zxgpx~j)GN6l#c48vSWSah~`?WngCnEeDGaOqJ+Ob{vzrQA5eJ;df>397erT|^`cI$ +ztoyj_0wIl#iRrK1o_Ve{s`dIg63S5dEEm*;#f3A;mvHo?VBP@7pUY!6%!n9YZ~9s; +zM{srbbL{d7FmSMFVJw%x?CA6!RPEQ&o+GO6ET1KRIp{(@+M;BH9=Dye)XvH0)mFQ6^fym5nlSV_!k|ZVZUerGh%5KPUJ6|8ERexw7?$>IjLK}voQ3)lY8gHC2WX_$QpyK%ROmm7GeFb!kr``U0k)7w1ez7Q +zk9nx(&ziuToVeGU +zIW>(}>-`k9n>kpV(vkW3awzlQOM{#-1Z-_s3-P5&UdPmoj)?>cpB4C&PL>!ouoInG +zT%UXvuIoL;hBo1i;;|U%WgJ_;T?>jee2_8|yesPr!BC+g4p8gi>JB<@hgXuQg? +z)dxS+uz=sdiZq=q2{94ABiwHP#2QhTERh03a2t0iVJw%^Z1*Ebc5qYUw`NCC&LAzg +z_oj_G@$f`Qo0JUTO{EK=%Jm__EzPSyv9gTSnj$gh%1s9^{v&*_JHwl +zL*@Q~a$8CT-T%H9@x^TfK|(xnzPpPmSU8}O%erPM5#inEy&AhSDHGzUFRlRWvy6CZ +z3CvC|QGLD{uYxa>wLeO2^LV5uchxH#j-0CtqhjT0wpKW5S~i?!9WQ!a(A$}kZ|@X^ +zDDz~WDnmd5PqVZvyHsI(27rY!?DWvG>ay=zrpBhxU2pHKC}}vnxjOd< +zfWJHj&PuoLVN5=cU8NcB8F(eGKLc;j2S|vB?_J`V +zLS!|oX1KR(Tei%0>7jy{Sh&!JXaxx+RmMm0S8EccqR3TPA*IJVrRaQL#!1Pr2wU-q +zbbu3LzXA1OV~+saoH-OY#?eyU(y)Ekj6l;c2b&MUyiGZ9%0-<&$*IE2xrHI>(};>i +zYw^>6T+tXvEa(anxu*7e>*?@8AB-bCy94hhG^z6~EwzMPJr{WTn^PO$XDpj +za!Mk_IMS_ME5+8b*CwV5og3XUwK{@ezJOsx-P-2%++qA`L!J33JtL~X1a!dAEyFEt +zya+`9<+*39_9k>c`w9a +zq#*IO!NJE}HBwzt6IM8jPRXZ!C5B8(7_SZeLe&rZ7quZw`L|0kbvwUXUW}@3gOdjZ +zIrBbf&~2B=$e$7zoMs~{oyK)3gA+_m?Z;W6aWS`$Rg;mRG|x*-7!@KBHHvX$pjhjb +zo4}uaNk#kuaiEH#7>hehm8g`B5YXK9yrEWIqJEw^5u%)7hccH|KISdJ?pI|=Cl5!{ +zCVr*Kr^k6tEgNT#x+w}@NXwwVcAY?PT%S4%87i$w5RGQ%j#?cVmjUNA3fJYkwSjDH +z9mQu_$l_DdNqtk*NC6qBt_S8nt5+tALH9V?J2LMmRiv<02j@DZHs%nQ%7XR_gk!Dg +z4!p)%mozOi%KFqVlhYs)XDN}2)ZstUJaC9iUTO@kTycYXhs?Rf^8^uMZmf=-LCkJQ +z#mY%iJhuz-c?n#Y2CnV7O}%PGooWg6dK4I)F5qy(M@HVk%GEc=-z*-|eb{t`P#mmt +zgaHS^AiCFqzt2dSfm}|oi$1`B=^GiEa9NP|Y{}9_W`g5$=W_G7T9tU^vb#;}cIZ4X +zUN5C+c_Z;k{)ocq$=s15_@!iT)q2SYoLe!o1DLmqGl92E&klxNaG6Uwj0?MOl#%Ie +z2p~z2=B<%aX;8UFQnV<7-C|89iqmo^J4w$}b>oWmSZ4KCl>V7*h!yABb-MPhS~d?6 +zad#~BjVq?mBm{uWTY+vza&JHa#{{?Vll-mDnCK~pW&s^xg9m>b)EDQWa0K;75Hu-k +zdCOf-5-X#JWTB?aWExjoJ@U|FPeVeBMS4ylWS{qPpDL9t_q!K5dR8U-CT(0#2!bnQf)Z+Ex^#?d$_Efe(tpqts +z5#7zd9MTG7;A*SBo5hyyZR7f9j|Hw#GZc%4E5CL5)syHz7mRlwM!qi#f6sL)(phk^ +zAjPoi`LL$0xvMcWju`rbd0m#%p}Y0Ib-=P~w{rO_3tbo!oQwbLFHTphIIPFlkioI0 +z$qwsRdylNaT0olh)p_BLpPP!^_j`z%aTS509JSjZ7b;bB%wJn(W>g<#(~@S%_=zo(Mup@nUUGbcv9zwevGQ2A +zZ{jb%Nw?&~Cy_G91psa=tQ|``RJ%qlIALm;N!|A~-vPS_`svrN1ng=*(HHZHRma?^ +zZ?j=23bRYdR7%Cl9Yi@N!l?_NSXNMjT(u7|AhWMSX_mkm;8`fNl=&5t&4fOuR(TqT +zO=9>@ibjnB +z`225pGe}3m7lMbPX@9wAz(yASRF&=xB1aQK%dr=-3H=m)8)tPup%q9Q4Fd&|LGT(F +z_|V|^QU+Ec88zd~?KDP@AQ1X6xUi19N$#PAv2aH#n325`dG%dX?*V7gTEkE-9rB&9 +zAYA9;2ye7Iiu?+$4aYslSSTLY-DY=P=`Z +zy;CmNA~v{{ESaCBhFjR32A9JdhDAv=omD%T0+vPBsSs|+bo<4ogs(pKELMb2WiuJ- +zq55RdX2%NG@WwKK>Wn|MXsNY1KcluGnWC4)$`v+F=t#-wfm{AJwBpO+(BK;$G6%Jx +z;SyO?4!JxBa`)W5F|BW(HC+QvA!o`$q^mXwPJpUxFTNdFRdZRp0%e%3?aR^h)p3Bu +z>Tq)j_bZ_x*y2K+x51ICaLFIVb=O%Cm~pQ?-a^QXoo&cK-tdS>$2i7{iHPV)^v9@4 +z2qkn!iy-U~j><^TY>@SoN3Hi-UMfzVTqvfI$^|^msXjiTQi}N1Mw}cOrF-+$-%9z9O +z50nx32GsE1DC5*0C}Z7Dw#<(5)Mj7puY5svS?hWTOn$(#W +zHvdK$vrFg*_*L;KT*bPjvT5#P{t8vYOB9d#+u(KBlHK#2=)(@k>zicky@w&{V$XefAw#aQSlr& +z=Qqj-I=Xcbnxgs#%INrkGD7WPXzqNVjEW$j(nq_Df1r%eE?s_qql{tn|2xX)_b-$& +z?oX7_5Y&G7gyhg)%0reV~j{L;peJC}Y_lC}Z3R_41!6 +zBYx3eC?m*kl<{r?%CGzQf1-?cz3-ve=~?;C%*U}wU@;8sL*u1}&ud4btMvi0B?O9$ +zyd{I{5Gu`bDBN|)?6@7gl$xxk`(db>{axO?l?tJyDV_)n502d#mC9lRjWT8o3nokt +zPZdnbe!bVH?gV)+zfr~?NgpVql5Q;i2g*26@(0RD%>6HvG3ZZ}k=QwvlAVb5H_9ma +zFO*Tp{7;mT;)S|9GQO5BPl=0vnC?nP1DC1-6 +zA1I^6UnnEqzfnfOqZp;c2gCF-eOGYFn +z03Kx!;5Xx-LK-ft_O($xG8eI=&<<$&yOw*%iR(0e>F3Z*X4VVl%(PUQmve1Vn>#5N +z6drG_KR>VGU5MqR6-6XBi-{ANEiNSn?83Z1{)mJSg$j!FQvLpx$bpd4t#KMLcxqh{ +z<8w6hSrI7zy?p3kEhcVoDrYO=8~Z%TyiUbnPM;tIp;P$UMvwB7`!SFhP1;)0Y}9@vx61??Q;TF-2I^ +z!!oXD0NqUdO^ra}rVgB6<>t8=4^b(Ard_ITp9{A_Sce{u3Tz&L+QJ*d;W01J$NUYf +z@~7U|+p$UCw!54YsY6Y42+2Cu9Yk9lLN6ePOvKR%fs-=+*IIz)u-0k75#v5C;tk)x +z>C4@(FHG~?HHjcb%f@d;4yMXadkG#ih9z$ZSbHj&@YX+w?*<%yr0~4^8|m>|^lH3^ +z$_)1tuHLewwN#s6Z_Y8tvcEq^E}D_axxrr`1t0#Rv8

to}KJ266#&dhyWaQnQ*=+Q#?xEPz +zp8=0CcWuBY&yO2ru~#-{zSw+^nvh4Axshlus}bOcSt#C5GBAjQjt-ynt^5Nc +z9-!3cqmK-f^!gy$D0ZFns8V%{r1Omn430sl&W!3s%2#oWF43BZi1;d0Od7w#* +zk!M!ZnTNJ{3mBo{@s;DNN0*N;!@Gy0BSKr@C40l8$(c2(3NTt +zF402U2ll8pWBe$pHKJChN8}nFJ=*e20*c_PYZd6gFKjW;c6B|*J75AK(+q5}GazvR +zJUwTtcAO<`xN35=O-b5!Oo3IH0raNa$7!NQp)L-l!1a|&MO6S_yl&FM?C(jE@)N6$piMp{;N!2n?)>H2V6q +z5fknI4TGm3HAqmr^O*_~LK1qC%gB73%i$e4SfTWs0Lz9(Hq>wKrKi0)XJ{(JaoAtb +z^A2)Q?Gv>>sK&&{js4|8iI+{th+-bJ0ok8qb|_5_B+UvL9Y{RJCuSvr11Sqpj__Uy +zv}4EYhJnVdkA~d0;3g-*DK0_O>Z5;8clHA_FV)5{Z(Kl9VNLXJlEyH&Yi(D +z>C+kso%@2gfbcHKulRH_P2BTIeV1grB9&$6axSIK1o^KMF@P_M^JNvkL30z2u2XK? +zk~}(6Tb&)y2&MNZCc-oYA~0McW(T0 +z&I*m8Mphsh;Mo|eF~qsXo1qbMNW77Z;C*c2%NK-W-$HjTlc0)D8ApJ&fM3O35b}jF +zeuZug_RJvxK@H%J$%~|jzd&mJtx)dFaR={~Kr%4(##chn{=ct(E1IXG`kh3gGi4BG +zUk%ywG`_2o^)?>MgNXAKnbE9r3T!k=C!G{VBcba-PC}nd8tLwi+9O4gk3o?PxQ<(5 +ziC3|@K7=;2C?{qfAroNo<1(w}fs7-9rM@-8Y6sc!?JP={n+S6hL=Te9+$?YLyDu79 +z5cA{dx1H(9J;EGnd{}PToh?8obSTqx>H`H*TKFk2wum~o0BI#m@mdyW&`DJpUq8`V +zf!EQ0)hI6~IF@LlLFWbk64kfR6cT}C@(Qi7LFw?2|NYB=)<};!lcAYOTokdk&~y&i +zt`7zvp`djO$iX!Omau`;P2SeBhu_*nW;34l_ycE;dI@N$`YAF`wSMwVoFAK~rG5hP +zte>XlDK$?;KMC!ClagBjpyzF17TJNy3ZSbX6R4+F0C+$fnA;VcwN2zrH}%*Tl@n_0 +zknf}gg&m3lCluSE>C6rRSFuA&J5)waXzGNVT1uy!6i&!_d+oHkKD9%QQ?7C9oVTCC +z3~*@L7n;_DCN(mtzzx;YBr#8>9kF?uwohiH6H`lK=3Cl6&Gl1m=1p$CL}}tmQ=&4d +zm1$LF-X_i4Brwl?QO^T`t|$6I)2@p>bJ7H4_Qtv4vt{yZnS7a-Nxyj+1hnwkB6zk4 +zzPyW|wTA$S3w5(uaD9*#fk>|# +zM;978eV;5v +z-rC5vnb9ip!qYVUdC^v88&1B&xAzzURlDXy$0Ki|t?~sMN$)1XIpd*;7lW`c9;;AW +zu}QC!G#a;#J}>mr!cPTbeL|jjf*VZYU@p=|*=CaWA`6Kst_t!HAr8)>DIRMJe19+% +zv&sT-<5#Po{K_lJXZ7Bzh?@_?Pf#}q#)V$C@En~mlhC9oXHR!lyE3sz6x!zmw^#8% +zpIfn{qLe8wCg{eh+Y$6bLH_p=k-IPZ!dcD<#TCu!^G4eyPm>eitY6Lhc5&r@OGCPiiW +z(X5NCo;DeSSy~#a2I-rXQx|-wj;DgH4z(kXo}m`3q7=(ZOf{|<&8pe7SQr!a}Z!xTUzapnqQlYU`n0`1VQ>OH@9OG+xf*{w$QkY{0kgSn9%J~`m^ta;%$T)Bx(RU*djAOpg^ChgE&lp@ga3g1e(KyZI`rSO{Y +z@Dt~k#rGWx8YOISeovD5hcR417jg+nnp~X4pDve_^v})1UQppJk +z-V@i{RDVDt;k;O+ujvMFAt2mvyd2ZsBfZc=k3M)4CDY$EnP=m#?&cx-VmV}OMYW5D +zbZHQkP75AG1+thGFkDM~*J~>c#aW!f^d&e{;Tz&B8+5}mDcGj2ExOOLDG@_`H{K?@ +zEgnPxRI^?Z_3jFyoo2tGt`kD5@pc)=jtuJ4HoZ?wc%vU!myV;FVEcgyhH+Iwm5clKW1dvov3-m81J;puhw`?bA0&Rby8aD|)uZn}`uNe$9{tUu +z2ao>t(F4v0RA{yS>;JfZ_$TYX{-gE7zgR!~@%rI+*AKt7e)u5;@2?;JnU3V=hw$&} +zb+Od!LccI=R{!+z|MxBl?6^@mW; +zM-SH@zw?jZ{4eW|?yo=o&idn@QOw`&tv~wi`r|)bfAoP)ei#4$_?;EK^IP~TYQjH$ +z6JGeI>mU5V`rUUq?Hx+{bp7rJ>mPh){qFbH?|w#U@7-Vj=$-X@57zH}x_t>EQuI{wZeo0DAV|;rhq#tRLK8KlpV0;5~YNxPI^e9`@D`zPtYMf2Qzf>j(c~ +z{osf2u=@M|_CFu|@4xwrV6XnW?JF6So_a +zc4KB$Hzq&p#vr_d8*|oaXOVToxJ|ne)oeuho4KNRBP!m^HSM;EzVb%YawDpYHlwB+ +zQF5~p^=2dL(~YS4X7zLTJB4nJ(Cr9JNIN)jUz)gO6SwBXom(fR6U^OjU%Htq_uI$_ +zX#@(}uev(85&y>X(FOZ@e_>zm59~clCC??1{0ez0=c_H(=#s?+2a4gQw%Tf6_;lb5 +zU%Z+pgG5}wyPsE!JXWgN{=P^jVyxf^*>#L;a=fQj=nRPGeIn-Gi2@kdXN_`nt%uo^ +z-xG-D`@Xk93ht31Bb2dyVeMP^z}``BG#vGhM*Y#~a({Gm49SzUfKs%J)+-w+mwYXB +zAN^ST9(rWy!3VM|Jn^pO7&os|IR_w5eI$&te8LKA;#RvU&&l#@+W +zZp4VS3HD20>BDCQ2(?f}5#>)An0{TAp9G_zm}|(IePt7fCPNOowbMMb632_KN86(> +z@hAkMUZ@NH`?b1V?lo1~n-D6mx)`!gT_t1-@&=l#`NUiNccOHb+=&E;v66i%E~X-r +z=FWV7d^oxmO73>mH$lc{uJ1brli)*DaP51uG0n3$8N|neX=(iv?o0)=lN> +z%VjuJexZI3t2CyzB*vwe<5$3* +zC6tE#QWFB(#}wmq+62OgvPrZ^MZaZe3L2U=O>oB%@eHH~b86IGr+wN0BJl&k_fb&l +zoxp;^n(>y3LPc9l5Q-kwj>He+i{9{RjUIv`#HKvJYp#;MkO+a2oJPL2UjVZ&OO)4f +zffoZCXlAJWW8?ig?ukZY_YubrX9vHT;A)+Y`w8B9?nHqyLznNYxMnsJGdB*seG}HW +z9XH7{H^QA|q}3&Xn+0!CmPw~_m}^BEcH%O07v#io?Q-T;#@Ph(98_!t%smBh`lRrk_f17vE@|CN5BSPD`jgCr +zazjIC24{uBb$~U1g%3`EXcUu)Zsti;VNkKq@|4#bM|aLmoPL(K(VPM5KQ^BZ>!2)--3J9T0I<2jpo&KH{A+HE>pP?dHTb +zd4jO6Zd@s6N##x}BGUa-EJ7VzXqVn|STSZ4=fFStp;*Ekaq0l&e%4Mri>-0x9J%xp +zo(T(FyqelBaOLt-pk~^_nwo6{6mY_eg{pw&>C&`ip{Jl}`GP0QX`wN;+X!{Ivw)cp +zwKbGUtbHgfNc12e&~8}T5p7v+xACH|u&LC7SZJI1G?`ehCH7&)Wr5w5rk4w+B2X9u +zkx$T_6*`00aTOt|#z~c$s0B_)qP@flI%FRG$N(8<2r8oU_!e@0rgISMwfIbzkhpnJ +zVCyh*m8v|RtL^6=h$9ks-~^W>?ew7rL^t$B$_{xODd?hn7{JmD@rEYkh@!T4Fd_X& +zO&)k&EG!X;fTyE&0rJ%k@(~g(f;1`lTIM{7>Pe&Sd%{3@)~BPUFAzJ}_A2(TtKC|j +zbcC}$<8y{Z&lXz<+&`cTg0=Ltd!6odXs=bGnEQ&;H^&- +zNT+iRagAsaO6E^afgbB7Q32(UPS3HbNu#406*jnp-We<9(LjaaXpEL-uPQ-yY1)KtDK8CKN&;qyYD3zn-8U`H +zYB`SxEXo>_vfy9EG`U)yhhCVuMeIN-bLR$z%T^IWSt=E#8| +zNK&2DF{otX>t(@m1)~X8xUPB5W-QgD*F)(t! +zicW(R?+&AR0_ul?Uq}}1KyL`c(`CP)R>z}jTC_QyQ5GDv +zV-(YPqVWu*6cB~Ga}DOUTDI_LPdaoOwtLP^ntR$!q*!VUh0Z)gpPdl{03J*WTrDut +z=;_G3=0xCGos3MgaUA0me-NXL@?=#AF9xP&ygR0KLYeXCo!<%Ha56E23W{M?nowAo +z#|$JYL`$pCFRYqI#BS~ROwL7VPT)I8zRi{(l4A%o`T0^yqD7&f7YjKR8jq|`UN^b~ +z5w}%}`Ai_Y>7$Dz*U4Uo4q^&22D$&gkjlSX?I +zpC3sdX)uUs&??RNSOO#`%wu(3ScF~PZD(R+p9XzDv&+WqnK9r^ssvp-ZtUIYT(?46 +z1x4$EO;lx1RDo7GK-}hKHq{QSX;L&*gAW1vb8CsZwL`Vd64#EXw +z5I72pyDsc;Twsep_>obr-`MF30sz6+j)fuCPb`9N?t-F17d;W9JP~X!h`;32E!y)V4=Kw85x81!~Ojyy)~7-6&dw6hX2usK_Oe +zQL`7o{XAEK~hUxs-^ +zIKR;Qjo(Z+TpXOpfl1APu(fUbrQZe%1?@p;CundhyiLL@zNkE{ +zZ!hy;a9%b(sNICpa-iPUae>^-Om$V`BM2)f)hEhr&7iCzKMA3pph`+pMOZcHVa<5N +zT_GskG89Yp?ryhHOd_bSCWlN^V2RYTRhl%0h$QS=SsWJrEXAqWZ*_HqfUY +z4y{`~I}IgwFRJ#aI2Ygd~Cps>j)b#wF+%Xi*t7Nv!T{973(kt>EHUrEB+TGeQnT}-r8vZ9k9oDKYn +zI#Kbb>bPlzj%&?c@alBN)P8lE<|<~MONMIQIl3&;$icmv=SdSo7cEuj(a{kXDw94s +zpTSLNDv>5WEJOHWA|5#3uAFx+iXBaA&59oP?Xo8(h;S=MTxX*+ItxsINk4VjjwS0|oQ$Zdp8v*1r{|#fk(5K3UI%RpPoDLX +z*vOBrsfvjO>wov+O%X0`oPScAl>7E&eOGltO>gvNE>d)A7n#rJiw05p0<|$W2x0mW +zrBVb&6%FtffB|vT#L4%Aek@VaUyx99x3j!`_NmKxwFEpsIH4r)5c#j(I?j|Ia%OnH +z03nZw=F;amB}iQKOYy`}(C9h%&Wi&R;zQ^zor_=`GHGO&)r5rTOGk%1<&F2&Xn_mX +zBKNIxw*dh`4g$43>Ckw}3eq3Q?~G|VepAix?XrJzs@jdy;Jn*gL#xU4 +zifNfb(O%40yd2;_4tQf^=b*C(ADIePjqmQvcbZk?&KhR&Ei;o{vb*WOD8_^A5Q+7U +z9)QGOz#vvJQ&vQS2fj;~mdn;IVujLhlZt9-FlSd8H6dim29q^HugOiVI6g6L^i`w$ +zw=p4uN+scb$+AL~BxqMfJPJU1;&E#T5f)bjnNjl)4&0R$kJ_R+dcIJzyN|O~t%3pk +zhDFU{5KsMWt3|J^xCl&BbpdoFsTe|ln7cdY4h~s_r?Xt)0P7#%Sz(TzH-k9oyxN8i +z)eV@|sn6CK@R3!ZWtGzc$oDL2hm6LfFQ*Oq6(Dbj_6*Wf6!Ge=+GS)oQ+P};RNUDU +zC7SsavXP5@REf6$4;jGx)li2w8h&(gHsXI_w+Z=YTKMot`auS@DtS++H!W +zq82k!_67@YmgFbGV>++rE(lDBa1O7xdEdskke@wtoRc81axfiWM7JqXQx*8}=x*t1 +z9*>T%n1)aVtS*A6V<@^d>3TIZpT9#df%Yglp2Q2%wsMhf`F2cfqC8dvNmJFdh>M-1 +zm3i1KIe|aq-wQ>U9eGi>4B}Er`bDU@alR~JMq4u&H|AyA1n8uYpe9_Z{ +zE|s7=yfHlL5!li;#qWx6si!H8*mlMNxuivluq^pqBC=bgB+;Bjjbt8eaoz67m+18> +zSs;}Z$pFv4JWB}o^1|a!;eo)qsm^Ry;Ycz!A7-GJMLXJqopc-&Yjl8zzI)KA6uguL +zG@2C93{X%&@Ao>*2$XTe3KvkNwr!ZWg(`__->FwB{~+CUC*;g33`$G@Y=$JXost6g +zc0&{(kWyHpI1exjh)|oO8Rz8jrPcpnLD%!p=g-Qgza2(g&$U9M3c&ET9xz)zx^w9@ +zc{z)jbGfZSTbU|Ql!ddBV9*s%aYr0O`VD+;hxzAyBQ{|R;=%A{Ac4Nm17D8eFRuEr +zIwu})<1C#DN~pld=YbNLh{a#xK&CbU9MP!=)pDnBt~~P6b07o@M!fXU0eLED?@=j~ +zS&282TPc|w4w%8Vn+M{Pl-#yH^kiFal#Q +zsH{MKW(Df06#(JHhDNahXKfR4E5U|FaYBt9@}0DxutQPcgkn21o!Oym;e?iUsEnM@ +z)CoDYlukJ*oRIVO+G%xtYKI!9T;tR^Z$E_@;Lx-$G_46uYGhI)sh=i^c{1&Y&C|4f +zG9#UsS`stg()MYtpK>#Aa`Poh6IYrNl}W8kt19z0Y2GH8Ti2` +zUW3vvANvAwXvy2DTNCqW2};wB_QUjeLhW?q@c0}>seBb~CZZ1?f-~Npn#7sdo&?&l +zI&IyWrfj%2)22Sqf*p-X0_|32Gwno9k}ymo-XZL!b`Y6&WWe)<0u4d7rK5{D(Dy|i +zB}KuU?8EC>oIFAJ;(Wmc9Y8nONize`oDLeoK~)OYqGcB~0X^+VMHj +zEIh+T?w*QeB+#ydHzu|uv#Ido`p81ruCH%x7;YrNDw~1+QJ-y3N9Rcr#61)ki%GpB +zQxb|D^BnqQ-Avs~KaKppwZFeTgWCSecI23fS}I?$TT;;_Us25Dj=~A<%hY0bYN>UH +z?aB9=qTbbXytaeR8JFABOW8l=6h}t_`8{L+Fi7K%#Q6rNr8bZT?u2L6avDYT?s86y +z**`kJGk<~53jO(vbuofjNY0|07Pm%#7j*)|qJ)T1caKZ^%oybkJR~D^0L6GW0%R(5 +z2xlBAgY55wL9%zlo%}3~ccVZI??#<26Ugsw +zSh``5W8HA)opC2T?bJW*rg!=QDv=xRj65htZn$>Cpes3H&@$Zc(hcXG@hLm+1Kq<7 +zcluLyzI@qfPt~cv>hxE3-Um918}7W1Xic?RAZQ*<*{Z=A>s?EH)JwO%tV0=fxz!> +z{PBF)z3T^jR@pnzM*EhrNADqWiUYf2NI`~+QxT@Q|A7X`j +z+(#A-9vxq?tRhg|f!;(>evQLTUCf%a#ucWHzcwu=?9)D6`tIqUFDK0jUK|DuAwZg~ +zcF1^Z%a_*Mq2Gas3(JY%%4~rK)l}Ivgb{k4<;R3Pd_FIne}+9hWqoPlDs9O8174C6nku-Kc2>OwsSvcAIYx@C;Rx_&s+Bq#w +z$pRU71Gx{*mg~wo@!?w^u$0X!lPahKwc9mA@z)otG|G}3T8BrMy7NGtl9Ik}CZ-^& +z%4uC0&%<~!3j$)5C>4AKy1v~3%or`A4ElA$EPeW>nL=yT~rytVXAntWM6H5S)R{j +zQ3kLElx4*VuT5qGlmTV0Q`0U{)nwY*N%m>m21*iPD5Z6fxspY`OcQPpPkq0EH)3WA +z(Wi$`Ae$gSH%B~l*dw{jXCCyg5tdm`O=L1(8xDY6os3%@z8$9$%UhsgA|oR+G)ga-PT7nS{|i&@MbzYBAP`SfoB^xa@qE +zsKnb;eWGqHov;|g7Rwbqy9;ZcCwaIW9zBDmu!6+t1*{EJ09i!qc&5zO;O +z5@Uu2!V~gAPkjg^a|oQ+8n>0R{%|p>;om +zE4DrUlcEvZ79C*6;B{&hp@&31ZlOf5zOGG~N$t-nRZM#IDPk?KnMx7ZYb+0F15LjI +z7xT +znbb7aRMwoZU!N+&I?%4jx28G4<;^wDWADnV9l4GnfZBQwu|orb!pF8_7tqvUO#7H+ +z9y{5BEFZ&Kqg5HN0zzCjtZus8ZO1H@0NnZMQSdN-m12P$;xbHkaF&-DQ!2WHW=p +z;Y@4r_Q_p|$Wbu&2lOzexrvu92F8=|&CN=UkY_B%_%7Q3H&X`akemMTkS~%?2T(LN +zk8O2dc*xglkh-ZmUM)ZBO`8 +zoV5&|$c|i-jIClJ*HwwW4DcFF7Ao4p7B9wN$|L(wU7xd1*tNMC-xD>G0-6pAE +z=;ftaYTXf~wpphkhEdzmE4(eeB((W9a>vQ##^(UhGD;B+Z|jS;rt)WOO49VU6xvMM +zW;BFWM;Gaq>7_A>G`jRRV$dW=uK9+28;iR_M{rfM)5xncn+bay$t2JV9d`oUKSi5A +zyqSA+c(@o{Iz&S3kciFiutE015IwTa1{YBoI1h`id2CjKf7_nlj4j6=IJ2`aj46yT +zc0QI7kulK_#_&cM!;IF%NEovc-x#S_W=E4P21v%##6K}lre?o2UfO1;)V?@qjg!nv +zg4Uv@waGEBvuv9zTcWlGp*pjzk{ko9i4$@Rn?&M-9%r}}Iw8lb%FmsUW7OpueEE)f +zlz(Q20;d+&G%Rr15;(PlPi;gN)plrdVuxas@tBc9e^voZ~nW=>m1oMu%^Gnmp0gEZe(nifd& +zHfh={OxArTBND>#>-!O@zvMP +zy$w~oa>u)J)XPIY;yHlt;$gre#vbM%(w6#42xE_lFf^EmRD3i%Jiy=K(eSWGSWkGS +zi2bvgWFwNCSpJF-)WgaKQmc?&C^qBpTww;2fbinjAps)hLL)2#=cb{1K^J+0Ys0X) +z&3X6Yplw1{(6!p};|dIfxHmYR!2ceZP +zndv|n>8D8Qr%9!slH5GirnoRqd0Qo6-&-Nk=#VgPkYazob(s_({BDj{o7j)0^ydm` +zlfC+Q#_t&-dYDugrf@hp1ZCepIu3?-{gq6>t0J$}wO|oO3xZ1|7d1wOHjP`^qq4F` +zWo1TXWkzLXMrCD2#XQxfxG+!o${CfFGb$@HDl0Q8>dPIEzR1dedCj{ZUu-#D8C@lm +z$S+pv3zpa)m%(XVr&IYwUL(t~2)!@ZvZLXpUIx=>iA@A@qgL_jFN_Yi#ZQt&6ru;r +zq9lY#$A1|t{!AM1F!n_>d~%jiHw!vJLxN1OGZ00*(~sc_v&)$jmNOOrYVd+8gyM8_)$%pgFPK*K*PKg +zS`5isQh<5Ps@zUkxEUR=DRiC7Co%{Nr7$@Ve5q4hHSlr|A-?tAJxsL>z1_-56ya?? +zY$Jyn};^s8oW8-PI?r!G4O#FNjG9?2N!LiF36&lI&tana`$s*JLd(L +z7%84vR7;QVrYp&SF=mrGMl=<4(<2$iOu^_IbmOFwwZ8Yu?0I}zmD}PC+a{3MD!E1P +z5#i|4;o|7d#oci-br$Dgq(TNQHowS$;)N8(O-lv +zB90{4NW8_YhyV>!gbDisv}nvkZ(JK_s;9Cs(3_B<1#GkB6sN2QY|t=HvN9caP8m#T +zcT`(9p&{RNMOTJR1pRXJ?H9=yCX!!4UG$YQWGvcwsG2*Mj(Suiw_G|a;6>c#W@&M2 +z7ILK&?6rw~1cWmfMdBC4MCi4$S)ctBan#;FIaGK!EW(u>BR +z#lD)4&2isY`;mk?T95LInCTg<2`k}w=Ag?-t17L!nN|?xNGh$m9q~y}YY<2p5T5~~ +z`w7I>suzsIoGQ(6xp-^f<0&N)em?y(5{e3SI0|&Cu#px)}(BO%s)pK|; +zjNsd(cyzqIBGn*Ryqf7MIS3gc%0fEB2qnzuG|7X;Pefg$e2q+{9~})JBfM>&Yp6xg +zMJF7XEXileWfV+cN0`G!G9D}KkVGX~`HU$)#;(n({&fidNK9A?3Rk#6Ywd7a-{u6By92b(sXR4N=@3>CBzce-oN9Pp+jR7$88xu6=%y^ +z9c|_R1-)WIMeV*aB7KT<=@)5!^4=>p%Ot#shc614Q!+}&0SE;5 +z`{Unb_2_L=@G{Evi_=gVf*_}7@LxZiAlOwR3bSN^Wh=sT*RkbvgcM!xrK`B?MR9z5 +z9Oybs+O-~DBu>tzQGU8`(_mGBCUN4=a=(*s*khQ2KHAPlXANzfw#mr4WP?|D`hFBu +zcYD`|qvPWvP(m(x@Tb3RnXAG_LmY%NnJv#?wdZ%+c-nC}TbwQ2=u4PA4(=^Z&hjND +z?co-bD3-8r3H%2lbml`;F|wsMt*DOG%0D@i%Y_O6g-6^z^g*~-p0%$yywuwQonbfr +z0E)^2&xdx{`un1g(`L~qn{9Z$*D%tqehY4`kX31@_wWf<)=0pcC60zT%+?AkFf +zZ+~fQr;)ItQo|-)idnc>4r(E1K_Ni=P#b?ynzj`lDLx}h9d~?n*sDM#t=P?Bo*VK4 +zNu)O7^+iU~yGyWcJu9ZG4z)vmskd=80$<<>B&TO6^D&IwpWj@^aiJk=_Dg`$eRJk3Ls15vGC87#uWskjhG>c3o$x+ch=(7 +zYu8+^7Nmtlys2Qe^y^$_yEeMQJ9jf8(k#kRq6aH$hyse*t?_QXG=5X33@`Um#L5g4 +zr48!Cy2LsaGn+zO=;+FE52V&fL)XW`$YH8_L*NLRChiby+e3gc^g8 +zOnI1GwG5_Ejqb_BA&@-r(?Ppv>RvjTIwg0r@X=ntp0 +zr4f}AYV45jqy>c?iUKDT+o9>q4rL1`w6sHI1t%1PmboVV9btLsxc)HvlD +zr_Oo%Da-(erhTDlO=wahlNw3=G)c^pX-90HrtOm%>BQ8MnE95rPjmg0n|YI)FHxGf +z(v+x7YGqngnYT&vHaSx#*>4G86<#X*D1H0ca(K2JzP!t!|CmDwR#u6ZgXVVQ-0ReM7{cBkt`7dA(=$#LnM1C#RmQ#^YKvu+T_>d$z2eEvskC>Q}R@ +wd|Xy~d*IrzrwrHay-T&jc#U?<>Ny+G#{~r?UK}|q5OAvaKmBhmKyJSU0F!OWhX4Qo literal 0 HcmV?d00001 @@ -64353,12819 +52125,15835 @@ new file mode 100644 +elemHideEmulation.apply(elemHidingEmulatedPatterns); diff --git a/components/resources/adblocking/exceptionrules.txt.gz b/components/resources/adblocking/exceptionrules.txt.gz new file mode 100644 -index 0000000000000000000000000000000000000000..41f36e4807daf27b7eb156ee33141b245b709426 +index 0000000000000000000000000000000000000000..bd320aa3cbc5ed7736ad0c00ac9cac34cd6da341 GIT binary patch -literal 699295 -zcmY(JV~{1lvY^|xZDShKw)?bgYudJL+qP|E+O}=mcysUD-H82FQHhGI%82?3Nf-$Q -zRitQZ3Gx4y+`R3;x?Ls7ZlUu`OX7bvCT;-}+ -zE#+!7W}m8u-GnlE3q&Grh(*Enb_Bcc -z181C6<~828)P^NF8}^l-x3QU=&xYMG+1900ImNH1txn$`o$smdl^yRd#3$=}xmsV# -z9^qu)14&p7-?zi(_vf{z$PG;P*47oOpWcC_&k4%f2}OdO#RiOKg=!4X@1SDOnyA@= -z>D<`o1f_}kGsz!*vA*J9Wbj$%HG$%rRCD=5i7^#HV1dDj9w$1YCGTWcCYW9{9n(m -z_dC7R&tv?(-`8q--cMT>wLf-l-milfJO4u2@TKwnVVL=L9?|3b$hvbqzR>$FY5%79 -z8O+uFysP}0I3zTDdTLdv+~>dY{kh1x@^O5X{^{NE%E6yB{b}i}^!*uOc*N|DT$@^< -z>HT_+tmW$YdTKnFu=Ra=zpY%U?foda!R9X6yd7EvH;ef+V{0E}yj^guRvqjVS%z@d -z>g(Pw*U!wzw5C(6lIcIsvb}yZC$#0u?j!1Yj{Nxprc6Uiajxd;vm*KTROjbJI;ks8 -z((xq?jc1`Cq1m&_r1PXW%37TE>-+Y)31gkb`g1hChTTUX(|C}^h2a9K@w90#SqEhD -z++_mCS{>mvBuBuXmg~;ZbJHVnMa|3v0Q6!>*@t7LwOA;$dj8 -zg5gjwlWhV)@k)EFJL$Q$%sDZsLFNk8GJ43A)ioB9fHDGKvc_vm`aFajp`&~fcXH-? -zIjg*A6-dJGr=@5=L}uf-ftq5gjY}uIHu-9fwH$k{2baOLn3{rAB5j_tR`f#57EO3? -z&pQ_haWkx=wb8hl&+bU;nqxI_+dsaYy1wD?&pdkHTg}mWTmIhQ_@(HLWp;~P!;-t@tYi!n^~n~-Bl1%3Ge*#W)@I@sF%1oBR4=v(!V -zDj*pJ5Z2;5nYV^<*|Z^lXNGYUxb|bn6>NJ``WS>^Dl$5I`C%&Dvr>YC&??6`$d}i~ -z{yy9lcM>g=$?fXqvWx_^d>xn&dwqc;1ZM#Yo~YG5k!e4qpepv2LBE{2T1^5xsDr~} -z(N|~g#ePs=wPj%midgm;AzBYN>I=n19v*&Q&gyrb#Z9KfHp08^%;#UW7Yv)V+()Xe -zlpNWu -zZKF}Z)}e&u#Xit~6@&0;8UyQZi8yP4BJd38O+}mVhX!ExrC=NKO}18xph&eV5p9g` -zHRxoNok=4Da6CZj!0^gdJnK!15vmHTP~#!qtH`LvnL+v@Rs$UnGueK$;LL> -zLFI^$>|o1&{1V_+sXhQ`+Dr^Il)!}&e}{g#eBpSc`b0*>l=TBpCFgmLX$K^3WLRj7 -zy)~&qMl4mqqcPrIurHc-{Ud62Y7x*lH=NdqVVf -z)RsXkR0;JffXE`Xe}41`3Jy_8aud1tdLnlk$S8g-(_d9k3e6OHndt^jc1um_ -zJ|)U(J>_$mv8HCYgut04yhxEKqJwf->>^P8!xeb^Vlc7eU{roKb>#u9U?ysI!&|ek^LSav*~)N^z%uQE_%PE_fGf|Ju%nZ{1>QeU5w~6p -z3W}Bj%tr{s{)8FBdFEXaoSKs5$a2_VB2{Vk(ha+LpsLJ!7=pdDtZD)?UFhYI4Wa;P -zppK>6d?HjR4zLlhq#)w83Ise8$?US_!F(G5<*Y;4MuGd!j3ww;7=iMrOU$nUH6T#I -z!D#B|O@Z!%&umh?_!S}0cC9jckv;fFJ`i|%#mO$afbV`90A%%`li==Ed=tW+;5;w` -zQ3>pEIEz|CwNg$B$$_kXCvr2BourYU#Q+T>pblRuRsGL_GCn*#P!>cGP=ZQ9bzbd> -zu4Z}0(QJYtG}l8HsGSU%$Xp+xppf~cXi2af@SkH@rd|%q|^3Ha9Qg8~b -zf@M^bp|Ig`I?ZDB09Pi%U93i}Hc3+)O&ne>3wEp)u^IFSyc9En5@da5xYb`ww?JtJ -z5E7?(sLOVM&^+Z?=2H>7Dx1H4;;Nq=Zvp30@)TkDQXu)lzbGAG^x`1$Q8i3*c*3qm -zx~kk&CdQ>K%~0BnI5h2<{kz`L8k5E?(7 -z$k31ZRaa9OR*lsV*28JT)scV$7rdk -z6f2C>Bg9^SotNSV9@vOV8yumYxNFa~99bbb@GksWTm?e8VO-(+yarq8ZrBoR1)YOH -zjpqqU*RFC9fJ32`h_>621=gjfw1!tC9S)3aSj-}Z$fRp%e?R(5+Nm#b5DTE6pp_yd -zfvjjR)%W}g$S5QaR``he%d2oVJ)z4Oa!qi0Q%r8e&IlF2TnNo=V$Q-hqa;1BA9vAS -zU4f7wTbJ>85b)6sVuCP$rqX%fQ%?-^93UeW^*34G!5#S$-_V)$bS+v#G;T!(`N&uf -z47g8*rhx!(PnS@EYYXKZv`aS5;?TG!VONHlG|=D~_!` -z01x!xC>^YIEPu#uh0u+}zdjg+_{;cJ0iWJ^$3V~k$}f6awNPS=O0s*Jjgh^eETH+w -z3{wzjN(Ag%5FG%Nt{mU5+y$!)Zvy*6y#@#c-v~^A%7kE=WfINF;d$AbOX9?y0Ww;9 -z71F%{Z{n_OPevX-b+5T$A;t;ufFNq>kCFk`url+jxlcheg~T?=dsmLeG*mfBk3h$M -z#j#bu=#SaXmk`l5u9Kzr0b*+a{T3g_^om7G0#&gwN86i?MbbTJr -ztu6D$OeZbt1d%l50`Xz}X~}E$*3=^rL3tB^5t}CSM5t-GnI`*;Fy0{)0_fMFz2KCu -zdh`O2@%%j*>$L@=bWt|Itwi^^Y{olrBy;o{L5@l6OZp#yU<EA}PYc!}Vpl9Kfdb -z@@#8tp``o8osk61$%dEIeTx>L)rE!|)l4PthvIRX9XrHNI)ms8(b2*OI?M2bo|UGB -zKvcvTgX^g@&M0Nz!myyKsBGz*iB1b4ft0nmoAbmHGR!v;axNe?EC8GUa``i&!`s+d -zMMD)R;3i{uC~>CIh+XfFK$ad-;bU3%YPb@twP^TDxT=m+9s!zittkjy2xQq7MmJsx -zY#sn}2t7uYKcu_c_Paq}TONdNwdqTj`OQuDbK8ZaI;I0s;Gv5n*XVACUrBK$!aNZ; -z(iT<~ry=+#pg`p>n>Bs)N3>T|0MZ{Nd#u-bD$YCXS#uzUH2Nw%tV#@G-m?}?2})1_ -zTz>mqKj%PADd;x;;DB+)G(8gk%j_!H{Im}rzKmf=)qvzdmND2BWbCjiprF7GFpzPc -zmOv9VRHY5sC}BQ4B31mf4dy>F?d#J;svaa;2I8p42vwm`P&19y6_C>{HxQC|{ktoK -z1*>s;-gaCtd2o0E!T3$eCkU$VG1e?M)!w!Uf#}{NL?F!uH1Y-#Ns4f}gRR$Zi^R|* -zI2;(#(O3cDBBkCGfp%)hYJo&o5Nsz^Y;u}pMkXnew#vH`^Q*kc&MBt+q?JyO<^hIU -zlSu0oP#)`D;jH*Thy%IPU=q=j!QNQY1vSmCzw;`^HVX`mP; -ze^>ps(jNpt<_Zyk=}#(eBI2!NhMS+%B-lM3%IPW#z_ZbJy&mhitF&Wpb7G<`lj*bW -zCA8PCdhi*@N}RGJ$^k7h-Gm-Cn0R5n)zWdrZFGINhH1{H#isLQ%@YJ(p6CQs-l?mJ -zdfo)2l6Z!=GcY4%CKe*{j0&cP56`CZnu6-bK4w?3&YnmRZv_5{8Tjb(lPswYyny%| -zjmzMq;c@XK84q;Dt;i51e<{Xjkr9%GQe&kJLcFlQ?Hu|2hz`POr!gAMhQJFQRR2pX@SR+5ovEPeymXK41O+t`{e?sK)%MGlf-(Onna(8w+mC0hMrTsU{qpw!g^L(+o5U1kdgbSYmyUYx=;?bMx$rBpRB -z|1S@Ad?Q#DS}w#Z{(^1u^F5lB-%3!?a!C!bw}i#gnUm{yfhP_mviWGUL04+RgdkI^ -zQr;CeBGE*i`IUr&M~dZWED~c1VEbK&-mh9Xt$e`Nn9QCrByR=m>n{TlHB?SIo)SiJ -z(~7{l=&gh)GwBDRSg;jDEaS465QOj`X(yQ#nx>^4kzQ?@(4js)1(DyRvi!Or?%S>a -zMQ2ZA4Y=sWs|iwCc1Sq+{9K)U;Iu? -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 -z+vt_Ide7h%)3tJ9NJPBYgM -z|AItisy@qt(3l2wZN`m(d`MxPq9B@kQ9m*5T<0&{R^XzGO9rk?B;94MAXH6aZHBJ=~zprs+^X6r7((^^t$NNW-e?DUN?(|dq -zY)ua)uW(Tp_{C_KYN8=_#~LC!u#R%z-1l?48}qpEMJqqUIgGFALUAZFaEz2NvoZKE -zT=e{>OUH@%Ra8eGnKSEQN%wRuSRhI(J719BwJ!&b2x{XBo!&Zo-h4aX?%?=scKYhN -zA~@7fRnG<=sdYy>qBkH$(E-FLgEi6zbBZ|Va1R3oV7uv$;+tYmix?F%X)rW+WTl0B -z>fao03lIt>FtI$1>nnMrEWD)R&s*5Ixk5u>rm^a?3QBHrT{^?jrmGl81_Q=P>+n>P -ztmx69QJ;HOsmN~R) -zocMQ-oH%sVHU~srRWR!>BhnLtn1#C0#ImuYYfk);qRjZse3znDB+vozPytDLRc94o1394NJlSHb9&kJKRe_J -z58Aia>kvP(Y*cAPjr@k_OphBu{KPRI>sZJ&qS4X64QVn3W=p(n^LI7|U(NFx5Fyu^ -zbQ7^m6vfJ~q@OqVR+^_y(DV8i|kKxkS9!bL1)=)TyVMMtdZ?}ox -zguS65?70F|?q=P;Ki;0V0lu?7D43m8KXGiPfFN1foJ)|Y|3DG=w^YQF0>$6ZCigzb -zbPd}{zOpH7!5xbl)b=R9^c239?=e|B7CTf+Cyv~jpOnOZ^`>PYMVU -zS@$zA|1t2zE9zpwMVr6m`olGW(mLbmdPnOaYFqY&`GoT-NRDi~=+?e@CcRk#`PXW8 -zI{m}{QoLKfJrC()jFHkLw%k)TJA!&eM#7a%=CPpupY=%W=jE7{)us+cE3#3i#M*(y -zjOl&@qPflba4?!}q#O6T9%}4UIDG5+V#U3&ZZ!RgYM(`A&@Zig--i_8yIHOy8EWp9 -zI!vSZ1rxOL8Onz9(DRwsBr^t*YX|BF2NPG@zuqgkG__5nvxh3H`!eb4qE2e~YI6m> -zN(WAJ%epdV9VVT7%yg~%JkX$cHGlFi+?&mZ2jNdZ#YyCI&f&Mh -z{Nf$4Dm-tD5M)2>Gey$o7(^lEMd1~gYThFVOh=Drp(dV*w|i3CN>eu@!ftCe0=#0 -zDJ`gf`rJ0{Y1tyc>loP70kme}{rs`5O)i;>M94dDE_1@SIy)9@Q$8k51Cq}m`on67 -z3Y<6;u% -z+Gh|O7^eSRDOI2H@yk#vcj+0r1ic?Fs&nvnahx&bWUDuV9fz_m&j1r5go>V?E+nRX -zslfPn9ES}qxT}BkPJ_tyVlQ^Rp(gd*0T;fz!0Du_&^M?a%|~MrrVoenWQ(0MkZ>{{ -za5KBVO*4$8t3U1>z=DCC`-rp4EohkR)%@}tH(C~@EVdk>W~tm|~%&Y52 -zcSOnc!QtRbMUXplsXr)@7YIyvGj>F0_AE$j^3N`vZ5jI~3>PpCrA0%I<{BrEaeIJZ$0WvSJ9ro -zaDQ9LzBg~*NA~YmR>a2{-N)OP;qQd&6+lOB!sFPHx_4WemF&Dxn`tjb2?yz!PjbPpngP-`!XD<@&zZSW1PW+T--$DN!5H;ai+|uzHIYYtK_m>AU -z+GT>Qd&ZV_Jgst(mS=l_j3Sq_g^t;iP$j13SGXDLPEkYgB&L&I&J&ksI821MW3Zz1 -zm&!mvNp#`A`lP%4_xIzYtEY*~3)2~!ohq>sJ>%Qp8V08?rG=-D=Ho0}SGUtinE}hp -z#8TX-5{c=@T9ffb2gK74?yD8G7x*(o5#S^h4!xXX53G6LO_&h5?Yz2R?P);Eu5t*KWBG6~C-)ps`^ -znT2;(XWm3=h*+a?F0i9VnsL3ymV$hjIB|)UqA4#sK_E5SY-E2hRED`7g_4WZQ~XZw -zE~p%eYv|sEhWszGdfyG&qzuMruSiH(~9VTjY+l4F*uY -zyBtggJ%5Rx?YPqA*RJuEbnX3ly3*aOw;7=#CfHzNU@hfgyvn>@BR)_elVXRJYZ(5X9qsR2kco%dxk_60~2gBO6 -zki=$X``f|hfh0>vma1Af+X-2x_BJw;Uewq;fvACCP?&<#B`mmT;wuY%q5E~w`l&dty%0Q7h7Ts$hFpl_CsU9m -zPenc}n_fYP9Ff%Z{#B=k9p$%|*kf;lr!>;7qF);k{*u{x;QW -z#^Q}O7+Nd2LEEx?#n{{ifXFmHp^}pPq6GQr%d2|W>MdDQxlNBuug$iz)?=@VE4`~UOizbbajQ$~KxhX>Y@DG@$ -zEYa0$kGbjNRb9_50%#rzzvpBEQ7F6+(t6LuQH)Ln{pq9milQs9vjI>T`?F7;6mAZb -zsM_8f3uZi2>E-g&Q6j#qEn@I$C_p~TuA(Zafdu4q8Iz=+Lc%IA&nUSuv%$EUxEFPv -zQIXg#=hok2nop@Z=EhS~D`wtDD&nnY(zHn6{CuACCUTE?LDcI2Q}djO%~Fy)i;^K$ -zo;I0rkNPj&Ri|J3L)6IjxABcE^=(xmU3L2wQAwDU?~Lnu*z3 -zBM=!cMikYRc0-7vM$J0*-5h>~!M$R#7Dni~zJeiMkS`CWU66{6mZ+ePD=IW -z^eO?bgvB1oo)rdolB>wD`J?m&6BE;{upKqKN(Vys`Ei2zavimG6B>W#G`lNo;0Ae& -z(?EA_Ihc0Zo;6OTs=9O1Q{r<*pkEqwo){#uYr&Vw`HMIc_~VTFaa&7-u%}p6FNobI -z6Z@^DFDOc4d24n6Fr?;Y6xIZ{PZK*#Q~LCBMJhe^h1>`k4TukfRkbgknu)|Ce>j6b -zH2~|ty4F}3a -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 -zu%9B6{ZJ6#Qy=y}U4Jz=80xWiv -zaMNRzwC4pf~?GoRwI?#K4fLCEfJYyOqYFJ(6f7eK14t@>SeUdFa0i%`hPqtJ4pi -z71E93k?Ch&#sNhWb0S$A=a+CWM(Ab;*;NCCBN%B0kP)9HT27+?9uX#G0UC-pJC=r0 -zhNI~8+oct38eiZA5k#n+mCfOQW#uovLtk!!8L+zHkNwvqZmV<^_-dQH7FFz=f$%=L -zn+E`JYQTI*Bd!W40p9YsH3Li!k{B4qTQ$gPR6Xfo;Ad>n521(N70b-)BnFO2MU#;T -z^-&3lK_U1cxI6y5_w_n-Zqt%V3e@*vHi(s$Kfj7}*(eR`4;CB-h!TXJ3&d%xR_!;%t!ULD;Yj-5 -zh9SChcU_PzTf`9H&9zIC5h}X#KB6Haf -zCMS;R`{5WPS8>Im!^((>(_fIAvDTAh@;D{)SO8TXh>?`f@ghq=u4>DyXrlx-0am){ -z*o;>wu|iQ=2nZsFG%ie6jCxFFf0tED4oMQ4Tj6`#mxE&s7w6!-V>y8fdVDF+Jj4y; -zRGGbPU239rOK7NxU2W-xt1i3?10_P$qY_TZ-gHmFh}m1^m}jgHj)UVkrVSm$mnGYsG?SG=FqG_MMB$s>Q -zIt$Xn)3_g_hAVw=@aqYd2cs2AQMu00(Yv*=$Q%9lNN3L#+fZg4M#H2iJ>Bh_kDhE8 -z>Olm-9ECR&l_q|+D@M2r=Lm|+uqreFtT>qv3UiRIgHKuC81e})mVuGq9g)AmjFYl} -z#;HeV_VCKwd~$NHo8b*5sL<>OQKq_Wb8r#QKvq0HLNrT!R5-mDjFu9zUID(u3O5G} -zn>V7t-c}W93ld{4FFK>#=4hHVOIX1emmthJgDIMIenh-_FbnOosJrM;)FJN)#f5r; -z@-Ub;Xz!e{s)8D4>w#I7GTTi)W)|G3)e&jJy+|&xD^|mPGJ%|&9^DFpsgWHbNqSg! -z;V+>a%m%XcBui-Se2w>xPX61p`0&a#TLd}!*+KDWoC)tDh15od@|n&aSh_U)B1B|( -z(y^);SgE7XVXBsu<+l4YP^2syM*mb1!6nxr(b|f2M$XM0%EbewE*w -z2%4PBFhCx-^r2DPnc%&(;FKT=sSso@=i-O^EYE9(ig5+~Im+^f?lwAV&|J(y|5-DS -z0kFY91_lLc_&jknx6@4;qE))C@dL7bj9J6S3Fgh8pVhSSvxjDSz9Sk96!B9fFO -z-jElMf{sJkL--gWg8&vsP8PovWj2I5?_&XS)+?_X0T@3{>cWyaeLrH%wET4xD`2>2 -zG(!P3bo?|&?Q}J%a}cGw&X(6Jfhu)EN~Ru%9WPro6N?H7fp?oM{^Y8B2KUWxs9=?s>dc}(7WZ5e| -zZKd0_Q8rsWo&R~I -z`*o#VZltMT=Qu0N74%D=yBId(u~?=+m+|%HbPYjXbT?m_VCf8xu5Yl}>|04t*%i0gb|w?l?fNV3ts -z{U_yLc_3gw8PVFs5C6=CdaI5t>rW97a42xTZ;Iu)QZE+_w(JEG*PPGZZ)RS7s~gl4 -zhSQ}{T*J1aGu%_};@NFV98B<>;mg+BQwNBn6V|t8fc-;}_`J79-3wp_*BsVERXP4X -zt}A>>(suXn$>}cwa3QNp7R!}>b3iSCVVj$`{Q_`4cTC{SgXg`{rkMa?2Icr7BqtbE -zM2=4SN3YJAH6gIi$!W7aHCp6T-ivjm*S0(&i0E4vBIbUbNAWBjUJR+$VuRnh9rX%rzg&a?VohjJ8sFGT -zN))Ol#FLq@v0XsFYaunyXN+{}=Yz?_FRsaUh7x?s7$r1qhI~2pfF(m>wu(P32fx>- -zGGfI$5Y7hc!a2^i(cuO;jc97m#EdJH0wQN&17vrbK3%fRP_5azpbApmc -zw<#SBDec-vTk2vJ2U5~#)fiyHhJEFr16egUd;vBgkZPDsy@qzz6A37<6Tmo2-i_}w -z1*riqSatJh(O7sOYOPyxA}sQk$?(V=Hil58rKGvMQ{%D=8JQsgzT%n522g9k{YDwD -z7?i9^cY(GKR(FwgW6=!_oHhtK%5!W-NwiZUvaFC!0$(F8JZUNCsR{3!$+Ly-NpJ1CO_X)CNKqI?TOG!loFEzVyWTQgkCnWTnU` -zz~w)6vF@^`wi;HU^=Cwaqc$WOEVnxa83RZzrX3p09fHKgPF`csU3ioWkf`Lap$>#$ -z{+=I2#Op$S&6F?>(Gu~JC5(5{(@by^e>^n`BOH>d_}@#O+=ChietG>$so(u934jws -zX$XG1I$ecq!=tN~HgBr@7=w5Mz|hiI1n|D3|0)eID1BY$gN%*4^-BtrY?dxbcn{m{ -zcVbjh9CaJnLNT77l<>-;oXZTDf<$t0Ei#R96q8bnV8V6V`dZ*z*Oc6wTG%EMi+#TXxJ0T -zcBy$fBih84wfyp@!4<@YgNH=5<6;H*h)0KU_yr0>Vj74FzE7ZzFQymw$YmO*f2d`FthV`;5k~J&hi7)v~{-K@G`2WAO$a?5)+*Uc?eS -zNBP1^3*#D^=~v#J#v%kajoz4H)uBNT#Oe5z!^NPoAf(ifZi^{I;YlskDtuC;Ip_EQ -zFch<1p~)nwa&i$8{4ib3VSV?-iE^Hvsq&d{wcbit^-{BX26LGmO!3E>^i8gt=q^bZ~U-EP(erfA}@E1mp -zA?hX7)LJoJ;^(RpJsds2!Yp$jymS2q&*8(r$*A&tag)VW=*XY6eWm8 -z4-w1|(=@>6$B>)7FcY0vi*jrPryG?2#3wp#r1mC8onI!-o2{|Bu4Y9f+i0BLNmpvl -z%LtO)2Kmot2uLn6sP)>ok*;*Dg0lM^S^)|3qY>{O+y*AaZY(Nzfzmb5iW;ZH$vEc& -z?Q;dgE)?ij#_)uZD7=M8&CS@REl`~*XX0hSeMj1nS0Bj|f(d`rqY?|gZ^kT_H^`R? -z;^Y^NgPhhDcNdTq58dh4untwNO2|J(kdI>2y}e?j-PcUajyh9BD2BqdCp_S8bbjj) -za9KpnKbxE+0!bI?<-!l|=@_Vmb@Y1p*t}2aN-3Q{;|FwNkb^djE5`@0$MupCVjDiK -zWu-_bV7vh#$WJ0CLExQgx-wE^*H-VQHI7IueZCc^4rjUH3Sw;d$*K0rLgw%yEhHDF -z83e*5@f0)03N=*$oW -zZlpV3Q?cQ=lHWCW@GeB4s?ZB6;jnj3JFJ9fX$XwBqPbrZq32pkx$_+pyF(15m$mmhI4}t_IoK+#W06kT>7ofw7x5dbiJOyq;DtkScRW?l{83LF% -zor?cd4|sYg6(E+HQvY;x4zq*4BdpdsjFjvLk2Hq}q{ZEj=(_id2FY*p&u;hn{R8Vt -z{3K7OeV#*&&*F*+WP;`WRsp}%&1&OW)6&awyn6oqFk>lkefijtBy^K$R -zw-RN+-PaFy*EaC9$pm2I=m!y&%}Z{_!g_UF=5`9LRG`Z&*qU?ld#waw -zjbi0%(cZrNE*sPKkLk+oJ~3rTNXTuGxmsX&DYk2@*vg;3Jb)>x4jY&sDhU6I2Gha_?9M -z;(j8@%o_Xgp#N3o^>bx%0Cz^Y+)=C(TVQ5Iz;_EA;3aI -zvyn8l7WYi4R(NC`8kv$}DeN*o9EtnF}HO? -zN=~vxYjBi3;{@j*JsM=X-6_Tj6EQn00T^&!ZfKtDluCAb39IuDEenmRd5+QVR^Zl7X4Q*3m`P^oNRbK -zly(%SUTwiSDz`8eW~;;!oGnk#pqV(aUTi54-0gP`MLX#b#J2Q@?yY6j9m;<0567a^8L7M^tH5DH -zUT?)i$$XqGYnMa5K*KQ*{RC0Wh3GYI+YAE&+)rxJS-tW+ZVHUec50e5{DHT4AeS{_ -zo+1X9(tNx5)Ss)l;Ra<(71Am6-*85vX79L*77 -zt{}O#HE5;dW&L0;YPl#}1d#7;ik-E|(r`m*460I}-UiG3gm-Hvg)Tf`jO*0N)||Wd -z7ms3r;qlkY?d}FH;4xNYO^2OGY*e~t(Isb$oy~}k)kV$a7DIT|LzW^wK`WTR9E5y6 -z35V3msY-JZ!`r=fr4fv%!7wyp?srjQ0tfga8Q*^PC6UgDO};X|%^5m4^+D32{BYnn -zO-i=opX}$sqzyuSB4=1&Um{<@!QDpwBjDZj&*^yR*SH0%YXoP|CGXOD(M`$yw(;yA -zPq$pd2}Xk2(-@^<^?}L#c!D2;bk^=`TbP?D0E59*uj0b~hLfZOtpqB@_7M?tvkf`j -zjC-@BkH$s}Z_?zp?nj{W3|2!b{7fn4@`4u?JbY~OGJ&S{0Y>o}RIu-(PQ`Ni(j4^pO=Oqj(pNE+E?a$cV`zA|k$8krBY;QI=<{{Sj(b++9 -z%fQK@EouL6?m#-i#Xi+PRHm#?F)#zbGil`Ael0oUlWy7~MH|^d$O$y~mcK`YN=8Wz?a$Dyd&E -zw`rrJmOx76o+c}icQ{ZVb#-1k2#Lr`4CTBr#Q4SH<*SL~2dE!de{l(Iq#B!g@d@o= -ze&&`3qfj2ZW6}hcSA%Pv4lqbm!ptRa_HOEo{jz+rlO>fBm%1#mgSnI-!AxHzexSqO -zv#l8z;Y%*IpuQV$+XeiV(lcF%k8>~`^6ke)UCdhjEQ9e6RwA!dnP<3&9$(HOV;VE! -zr?#b=-N?*CKvP-UI1X}lv6b|EaX$y)j3~^&oJi0!+Je2>DeKiN -z8mQ5tL)*1P6Y0t*m8Jy|cPVC3*aNrFz{6AxxxI82iGMeSC{TH~eRO%QE^AbfAP@p6 -zptN?-g9&8|5+O$Bjjo$~(U-3TKJCj6_D=vEN@+$kqYp*P|S$ -zQ6Vqn_PJT2B!e)&xr4OMj~CM6W~$J{#;gaSKb%;K56p~Dhi>6wGH|U7SHJ8}rIb^j -zaTh{^_#|97YBjqB=QM_10303y-Q^21zYiSmfUgw(Nm)*@!NBIrkqD8*J_*ScQBJ~4 -zhl|0x9??)t1!N==wr=~QC^PbE+ts5iZDQ94Txe~jBYS4bXmJQH?yk4dn9WvH`9-W|F)R{}+d%J?J&XZED7Zi_h9 -zl89dj2gYThmGIT8_4A8&m0NhLM`b64>tcf$kBk3it~9Svsq -z1?Fi)>KMBOVM+eD{%@3x1`PF{vuLjmFI*7ls)qER$K{xDfAKPf+K+ns|s)1pYj5vM>gkF{NP1LXA0=8AM#9DaItWUYnvRf%`3B5v`n -zPz(^SVW^hD1cN#5UZ)eH -zJRr_i(C5*d2qG}a&e*^NG)@bBTTzHj*hvtCZ?qYQ$pRrlcrJ{)i<){U*88P@w~Olv -z#pa@ZXLW8xx44$p+E5t_7pYU{T0-fhj)Q!sMFAPz%Of6BvXW -zV?bVd4&-ZCVQ&Z@7nw!VI1g$_@g^Qk@7`~~tUZNVDAeGD-mlT(X8G%XqkLaD+OoFB -z6pW!m4T0fsLH$AyN{-I>q3e|V!i31_U& -zWp@B@x_!x&^5k;>`%YDi{=I2za=QvOiI}cdb@BA(CEwWF_=)dXBDs{!c=(@b0Jeg81VUR -zixaysQuzp6RXCuReodJ_Oz`IWRr_U=w9|o?GU9@k=8bD#xojy|Am*mzHA>t` -zN!Xa~!4c01iibI@Ur!6>oYt+Px%jBbF3*M%H`_no)1VsHwVJF6(|CY6o`s7yjaQH2 -zGhn*PGa@)F)?bNAMn%L!XEI+>Oi`ogNUN$3!tQ)ui@zVKlB6^IF8{ID3r3w*2X0>{ -zQfFY|3e5jiV+ -z&-)dcFL+1yHAOhbA-z^+CXrt}Ujk;u1t&2I9iUg1Che+Rl#dJEU|2ey_vPRoLbfqi -z5hi2l_DQqCeb@eudT%M!zN0%QTCmenZZ$j~1D-7w(<(MCnc;qwq06gfR`)0Xcfb~@IK~x_9DgvEq2;RS?pAvw+F)9f}4r1Vq -z?A%B5Jv^hiI;aoL^CXicQknM5PD9K-Pnf27g0W#uf%QHN^K&Ax31fJrv;4@P$hd`2 -zlfIM%kgAaL%DGMaBE`*S4MRtDe9PoW(XS&&ht{O75-ScPog>gFDI#t0ZQK*ZAteX2 -zGtlI{gK3eT-95+;Q7dT5LTwFFfY8Dj8~ZFvE|zyMj4j7L2o!9%m$)ao6tc?@#FG?I -zGqEQ}7ObCE2xgOMKWrvG%c@>!I6sj2bCHr333UBzTi_MyhvaoLEc_+e95}nhbCpHT -ztdI#kX~-9!5_M#x`3Y}cb5_NH{wiU5wX(xd!HM|OOf@IH*8$0aIrY9Jz2@O3$oeQ( -zkqbLMdL|%KI!75WLb{HZCC#2{TC&(AVj~S@3VX?}GtZwJ-XY*b8b=Cl6hnA)by$@J -z$;nhFjk_IH?+LmUmi}^7CS^c6KXD0~h@@rrBy^$!5GZJ*a5>N9ZX~5 -zV3dH+G8AEDlr&l1m;$fUi7B`cRgLtUt@&Qp39slg>gyH&99hMOei*0$zr!|~4@7O- -z#}thVYr}s}L8QZ^gJ3*}+t0#FZE^D71gx$9o~(;YhgjXK)c{})0+I#qCP8arR&u~3 -zxiav3ORCmPE|lFaG0kQZ;o1zctilJG4(4HmVHxK(1gChmM -z`*HFq4lKRqkuO~r+K)D8PFv>`8{Y~|LfBipHXSa|NE+B-;luAc*#RX(B)M1tIYzBx -zv~45u`%lHfJvji8ho&gxQ$#hF5v7=!q;bOxj -zySXg_f@O5hec~r3h?uSA~Ri#`PyX2A<6L=LjDk{AL|d%3=+CwCpHy6_k9#~#y~fe&Xc!I>Twcq& -zSBU}8@?1=;+y5d*npFposgJI^Z$J8)ZjqN+jTxK)c)iXY5iAG|65ZXvL8sHZNKxm)@{-5|R3)!SkDoHF+nYeeJI#GQ9vzQ^5QCai -zVH>|44^XZ&t~ICIT0u}+_7KlqMwOyO*Q8E|>kkFlM9$I5T;S=q%9qdM>72!!{PQq- -z)808eK?;0U@H0ZRB@@m{pLHit7c$7i4ejr8{gDr7W5$?bci@cQSzdEuEb~Q)ihI{Mi9C?*=4?& -z{&u1yql3_}3Uh*tR#EGi2O}NJ#&En=1oV}xqz!|#-;hi!oUVgA#hnd2Uj9ugDG{5` -zRKtcC=Kx%b$VM$m6>4h+shTkmUPu?AkCQlj0mT?F?Hb1a#0jnZ7?H?yt7TUGZtnS6 -z4C^|)VFkP{4Xx7zSaq(6{Ay7 -zLF6z;^K;>a8{0sx8vR7j9?~oDimPcB$RT5yM44Gku@qt+k7R^7Yko*RAYf=^JPNTB -z^+`gFc6^e>=TuCo*kUZO;oH!Ivq>&(y>^<+XXN9Hbp@4MEVlQH$1{H}iNWiI(me)$ -zK7E?}*_bIVh=Da^qN2gturjRcph!JDgY{@XaqAyf^n1=Prb(&$=r9Z|J=5?=aT{T+ -zlJrM5XD@Y-GaIO)f;oUou^MzEeXm~tySw2sQ8JYD;Lo#)70JU(>|EeRo5j`__{lME -zs%i?s-10m=j26-6qYXO|OxFlbjiM#$fa1 -zf>fCWYg`Y@8wC7u0+p%~la4$mRWRc%wMs^^3g!2>oEi~_CM*?tuK^3ArfSQW4xMf$ -zQy%vQHG8C^VyVqNhOAESfz52w#s;q!c?vHRLsCvjmKVAzPX=#qsxL9%HqIT+HTUUh -zbl`tmuxj$DlJvl15&G`I -zheAKAiAN=QQgh}Np9bzSvD?WG<0$Isj(>1iC(z0?Ssee&wNDov1Xq|ayOA$E-w*^P -z#XY@qQItAoH`N8OHA-&F$U%1#ij8Syue3ldMNlj36K_0r=x*5Uc$^;45giNsbv{xpr*)SpXKLLFiJPFD -z5aL~xx1jq_9kbZ#b#Sm&U}C7&K3*53TT^kTdf1G_D!l$R8;~Gk3qrEJ?NCEhb)+@< -zHezjuNwXLKbaR-4V&<*mh1^dz^A=OO6QnU?QJIru>BZfAgzzOo$w(6pf7xJ6n|+D> -z%sK$^HON3||yIS9I5b^ypRq(_OqK8RF~E -z_31FN>(wrJ*uXF(qLNa7Gn9f@%ek9X2bC5Zb8qsV9_)Q@^%w~H3eMN|iNTMa=y62> -zoxO{{B+7E%uyaDp`t3&WxN!+Pu<1V{4jRH2KQKmXNNw2R8tgUyggQOrsY$yxftvX* -z@18lLy>R_&?A`bFntIL=tNxr438aqKO7}lL%ZSW&s>QY>g)15a@-M&^ -z(y4>AU1*}TBG9jZRI2AP@5J$boa8`Yl+Gs;@iYApMAp?^+P6o_S5*gnhob}OFAJ3& -zJKpASyoOk)*vdWseuUgRFZzzuFSp(N5qL<}j2#x$3yak2!S~mK=HDmo&perr>Lus!FONsWpYg{$3lZgg-y;9oj9G9w^Cgxqhk%?z&7O%0!1Gh>ND? -zPkL$j{9_-EGMjRs>xR>eRyRomcE`&Le36GCS)j5>QZGm6RB1V#3=h%H`TJ!7ZE!ef -z#4vFB?yKS#gih_F7*8I#njbAhj+5aGRex3m{kdztIdWnMA`yoY4A2Ht*ZH9JJFjbh -zJRdb|e13(@Woj-z>^jzjPRZJfV@4pB$21ozWS0k0+1-G`6Dee*sqi-46#fIg`lbAa -zJJ)4_qoLpaZ8bMj`|%b7v|;D(6>kV7h}yRXb)^OJS6=(Ht?3z_e^U$sHru^1kN%PX -z)PiiidjfNr1MmxspOQX0MKZa3baE|Kad^!5c@z8chhlHxa*o8(a6cz@Z+|U%22!mC -zPDufk6Nvd9mB2)ST_V^K0D#cpW+hR^g%OXGk8=N -z+^yA9dtc>#{*_fNui9&68g<_kb+wt2AFBKVZQgDHY-6OoyKuxg{?Gnmugnf@79NZ` -zsWj3~dz*WO!_lb@t-^E7ZswlMim}S;L2271pWubTfns*9ZOb^YNo7pvEm)l5;Sc#J -zH!1*6)od#4q)yo@yXW)}k^#=HbOc$Wih3!zmcjy%`x#Rh53axYf-tP9moO~>0dtYW -zfyW#KhiZ4zEUwzjk@vg_;_ou8aDAyAEEm*~W%M?O!RskWsr{0$Gd*d0iWVN+8y&3_ -zeZ5@?EaMfs`&oS_d+c}c+<%=Tt_Q?ZN8BJbsd&CN$Dycrja9mLS72e+4O -z-r9Ddq|bUDC%&=VBrxSf3W&mo}pYwn9kyh>JL$1oiS(1~dv -zVcq9PyMCpinM%uUTizUTGak(T9{*UiI?31b!mT0zYTH%yE^oI{w0tZbx|vlAGf*_^jIx}2)Mmm)+WFB -zlByuKWNy{3xtld}xA>Yllt`o;rRYY#*^Yps;DbVIHdy{0rSxkb*^jtb+5GN_c*E%~ -z3-DLEK@;NAf+e(jy;->q9`g&JQgos)^z^qE>Yz<{!oui(Jk4yTSO7fWrH4YhS@q?Y -z7T|DnQR=IyC~S|VZI7SiI{&LizmXWibN&S{v42lob39S%X4<{DRF6XRK)_9U<2f20 -z0Al?LcvHXMVJ^66@bbPsJln6rd>eLmyO0qMDkzzUu|q*#c4p5deC?L)=?(lB>jKl8KlUO!G_AMg1lzPmgaFJs`~j8t*5t0V*W0D_c<-!tx(-iaDU4( -zZ1?aT$LIHMm%gOExBfxhV+E{hJa9Z} -zH{E}|LPo;8Y~P*)zeOL7sq*drAUp!?C@TPG8Q#8L8>B9>=y0VEqDeizHEIO6`GqTN -zt8~6rlVZ>6Ko^pR@Tfqg!s)V!hgW4b+}gskY%thCkK+k>RA;=68P^@+ti^Hz -zH_EKea)~_CoetFSdinLJ+UMf18pQMSOAiTEv7qK_L>6yR$6zT*<99S -zQd?G3FYwG4iL{b|8Pq&P>=2mngmY;d4JD{}F}FXF=xiOa515&yh;6ccC4m^tgOeS5 -z9i;0eg)$?6`#VGmQsQU_f5@}c1SaNgm&WPezz?p=|Gx81qy(plQxZYer -zxqXI1)Ra&HCMj(uVo%XaSYe!YpE7@K{OLf73tJ~S!GnA6bN&0R=Oa>}ySUruK+%>$ -z&<)GaS}yzcatrsi=bN!}yVvW>?7hw!PYuelxOArSl<;z!u`q@#5^#JMdCRR!v7KY1 -z$hkwq7P_eXPTc>o^X?xs)!utiOpp+UN{t;}{i -zsmv161c^J@C?6l(X^dF3s3ZKEMHqaM8c(`oU}gcC4zBEoY0bTP(qY?_bXw$9S`$@G -zLny9{4o#yxm`C#1q~^#{`$C?6bo!HfxtF?d5$Lf)Lobs!Be3!+U-vEmtUH?BDJ~Gf3WWa^Bxw -z6d4fbzTuzbVhSZr&bh(*{2nYYU|>|V_*~5hrM|4MNO<+>&?MIw!j@^;JU0{t8h)4M -zv38yNGBVk0CP>N$yZMVEdbQ^~vZ!FfLc;=g`-kK6u%CXvLp*qdz&H|3Zd;ZSp?xmk -zYM`zZPi4yppy8GeEE;o@mhe)&yw4IR-iEe4B5@_)(rkz?#5kQ8sV$x_Yhn%P_Ne*unE>^@Epy7waq8T%Ba -z*lW#k(Wc9fIGUGYpKOjE!ZC4ya@aYrIwJ0?Hz0*}GYa}}vi~RiEO-+0Q0ZT->tGDa -zgd6Pa3o$k)i%}{1ODr|v0j=UQoGd%BP7e;};X?u)aTSRG#!&$TOWM6uoPbvL=4bPh -zZ^zC*0C@$UF;vx)^@A}g;U54yGi}BoG~R*o=kOaS5w(pwnstM0U(qyZiXTJ7Rpb-! -zaRvR;4sY)aGN2OCa+O0!Q$w-4@T2T9+@fQ+wN)uz6={{T3pfPt@SqhfMqv@L8vlOX -z<wIb^4iQbZA@KvSXl -zC(o=TNT@j7n{E*w`glIdn)^*E7UfONSJVWy+xZkPKm?bG-;|O?X#Pr!9v)Jo(2ez{ -zZce#)^?(p7+>9K3&+$Te*|k(K7tKH4nT#&>iAz#RH!Rn3bKOD8(>$-P;UL{Qs#|RT -z{QEMva*Y+%Y}bAg?oLyM-|DgyOit{IhLAh{x75TQ4dQcX8zU@yKKW>Z(?8p3OdWJ_ -zThzA!irOk5N`FCYR=C!giSOWBpQ8|7Cq^VTY->~e(pjuWUvZL;RQB))2U~6MCm0S| -zgh0JLxEbFvDNrm_fbiYh)QPfkJhd5ssVxQiyc7#s5b+!KD=+v9C0}o3*sz+E-c7CU -zl#|F%Z7~L2q{n9x3Zz|UamG?-t?CT-KSZZ^1e7^+Q8Jc -ze6CL{?+_UsyTL+|<-CJr6U!A!J}zll%BzVq%u#QMV2KK}@7Vo)fG$_$|BX0VEh)ZG -z$L|wCj?1BClC<<|r{bh!hh^OD7EvF$sgaOcz^1d)lIWGug)@{fKtK?8x{@wus%M)x -zaK(wnh4`edeX2;zgv7A84MN;_zgPwLeLC0o?rFTM!2q>fOI9@Ct_*>3KO4j2TtXnmW+#se|ZWn&1{8qg##_#WgFW&=rsUM-<#vUnyB@}Qm -z4-c1jZvPE3i%*ORZ%QZ@clLAp#8jm|I7W@9id^Y$FeDfN?KXMB6u0Q}hxW-0yq9Ps -zhcOmuc@!KH$CXs4Kr^0~SxX`f=3YC4dqz7oYq!4xY0JXqynn%TlSHWiBOx*ez15C< -zZ;Tx3LP@!h@=0y=AFxJ2U}+DaIr5qi)!32QFd!OA>r2oo*~l!Q=kqFBg_F^(T3sd= -zX6jwNJ7jtWAD*O7O(t$&z@A@=u&2Cd^GK}a&cuziNhK4U{Cn#~nc7*}&78&*fFrir -zWfq_4-O9AAPFAq(z_p?k&P`>GO)?!?b5JT@35gJBuJRbW;$fH6QH;_LXJBDT3-WE=n>V5ldZAnevhO8g^3SxS{i22GJbr -zfaE{VXyKZ`pGW_{z$I6uzl_@B)qC>+#EL)BVC`e_=;{JCw0P~9iT-6}aiXY}m+8)n -z^dObUQKh-$)GZG(Wl|IbiHFoRA&HFprE)tmPe<`7j_wc-1YxiFvkF13RZjVHL&%R6 -z_Wdix6lrpHh$LoTlP_FmTXj^Bs8t_@(CHwuf8?^)ipaNl*tOPbkw@>^?m{d%+L(hD -ztXj5?!*@chSCQ`k8@uV*)`^c9`dlv#9$FG0NpcPRZ*utvU`vvu6o;6RVdaI#k*P9U -z0%tASICUr#T?OYbeskaUs)*DGNUIkT{N -zTvsv0z6&fcvN02fQ7(pYqDQ;C&I_f|z(K+aIanHA=mvtXvtAEn5~)r6Y0Ef@T?A02 -zb9_0@8~&NFgFgWx&$&UWo_Ecin{Z0;w>Yin#ABhn(+O^i0CMKxQ;}jhRc1$HitLZ7 -zuLKXIth@V+x}&I0wd*;;={GO5Nl=>E*>p8T5kLh|^9t75K3D~DZy>z3$dgs0;Xd%x -zuyLOR`j9v-g2g*XAEUZA86ka`hTL*SZclAm?|N648D#?y5L-MXFA5BT0lpEA6Er4^ -zCtEO|*&YA|&;tagCh=aaPaf{2;5x#UE%88VXgXoykQI2%TdUq1*=Kj9B^fM23Di-+ -z4N%7pg}&kq`6)7qNN4R|ySwGNw{l$u2KWot2;eut2mtiXwJuZv_>?cR-pT1i$(r+u9^9&M~??W*>MX7TZ9-6mqorh)D;@IQhX3{6rYl -zuqVhkH&HOzn0+Z{g=!OYtb7Ei$(;OTFc5R*Gwv#`BwD~Iox93^H+lxLG25cA|IRhx -z<{rL>5NC`$cNl_K)vCg9;-=%Ue>jhZCNLdhg|Gzg@iyf`uk3_G!G6-!Zg_y%_xuk@ -zdHyYkv8E6r8fmaeJIil~K-ny!%UATYi4ox@n%d`UW&e5`L=US$!8vN94Ami+XkbO{ -zT~8-w5|X-`oIn2oyV%%-0&?&VQRa0u-&koq+5GAQ6W$%x9zwuy?Ea14hUSnXN(0kqmo;Iro&h8Z9zkZJeyTV -zv%U5dht!+GkH0fY|CVi4CG&hHAaLm$fP1e;7Kob7sgOP>>+o?}Yh@ZCdRz5brn$Z` -zn!@=`09 -z+p?&({%)RU+BWn%yBTMKSQ8hMFFdxB8--;I^=TnZ8XeewSuOiVB@2tJr{z{HItfp= -zv6m7!$7o~z-9+O5Z!764g4K%D6>+>&;;`kA)xihTWiy=${*vdI5+J9*3UMJh(3!fq -zSb|C^_J2yr1^3GuXGpxC-gXHfX-bC}13$F@Ui~l8GZt52*|))%XQlsUk~u9C{G!n`7ppo!_7{n6-VbTj -z$!i6|G=-z`Bx{(s73=XdLZZ9s$C}&`WAb^SajY!dr@a|uaxp~*j`3xB@FsK|tR(aFu+nrLwRou;^*zve<^pyP7~!KD -zX_os{w>A(-hEwBB%44q48Fo<>fEJtC+$BN~JRxhZcaZSlRc^ujoc&0rM|+|3pLPIC -zDYml)8f0O(n3MlUNVetK{*cX@_sN|8@id-OxB_OOMDP -z;WeP+PmHB!StaBUccygaFrQ^fQFZVvHp1sd*s${U)RRa7Vr?w_goGbXTZeJh|Jz2w -z0F+y}Th4@*P7n?_RQwzYL!|*;B9o#g-TAVY|?y8l$9fecoYQ$X?h!VB8!prhyq^?qel@^!oz#1SHd;Fr&TZ>o6iFTdaND! -ziOm(C8j*72lb{jE*)1Em2R(<=RP|tWHx9p2RmLj+Z070%{E2mCBKEe>Wqx_w@Kc5z -z_zJQ)X|2TMJ!3ayrD1 -zgweUJ^m$b*Kx+HXY^AQhlvA?5D72M+lA0YT^{a62J$L~Witb(-DsweqhWFu9W>RzG -zT*Oj@RO!9Fw!FS^ElU0qLOKrda}jK$|2oHY3twbRV^DUL)Gig_OeQ^<4Y_g@KGI#r -z(*#VuL8E%(Si@eSTdaUQ-u+@Q93j_75P8r+W@o_gJ1W(CHoqk&>v|_oBjmB1#am)w -ztDO}123$p}qvkJ@-y^L5pC-Wp`-3Hj -zWf0uzjnXzpZvaQ>lY@K=6^)&B)HPKI|Lsq)8R`5?E35!6dLWy=F)ojWSSvsAh -zftLJ2JsL<(N4~n$cz;fj@Ie>s1}DHcB$yJpG?6Oxr;}=v+GiN4aCPhdSqTS-Dmx*= -z#WHzYNQ)CoLA_6cAZ{w}>Z+XRp&(CwX7^{+HrX&5j?JS$(@RhhJVq -z1;fui`0LM~!V${ZSoOZ+&0zRC^$T7Jk(MVOBy>$#G8 -zCcV=8#pW;**cRro;>+TA7lkzQAN(>&NaS_d57VM|JlUuO=X#mrPa#U`=hjOt##%+O#XD~D=EN3agLure0(IJ8;lg3c4}ADl&2@?^ -zO*U|h!E>7q{rC^+c3F7Fc$2$OXUYUf4D@p1tAFkh$2(BAo;OVMgNf*1u_jUC!MrRZ -z3L7KOL?lsyLq7%UW#~=(=XCA5!v$iyJ{c2G@Hzs)7!;SYe`^uPzp3RDc}4NOkUNTh -z*BbRJKC|SssJx8u=_b3k!aExR0i5QQf7j^#z8SIf3dakyt-au<;OlbhY#u -z8 -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 -z$P`*AMO2FFO -z+S5M+FJ842G-BA55u-LWX+WqN&1z#lfYUct?!fW}nZOa*d_ -zH?WPo9(Y@bg1PdE1=$PF3C>5&SL`TV{OXF+QY^aiz*(2PWzVOnw?U~Go$k;CD}E78 -zE+be8wOg|jWsYT?B9TKY+ts)-Raz-W?LdmLKXs8aDK8|WKZOSRrkzK5OTeC=+B8kO -z6(lGk2u-(8Tjx<0gHTty2cSMn&GX2tf1d&YHOE)04$&xr11(HQ9eHEqd-nsgkU0jP -zOqXYXZf#azr+xFe&SEwFlJWGuM3O)p7hlVxSYr~giRm+mJ_!RucfX!fm}mdV@osCb -zQ19*}XMUe}%=6(?;L)FQ@n-$33+zaX19kQ3qbzoUdXwuUr4wsY`z}Io|0eMd*BD85 -zuh2c91MJ~!NYd^E)}}AXA*hY`p(H>8sFB3(*gsD~K5R4c!WI&IEa7d}+ -z0Ls@{-8bh*H=?PBt^$h6*aH8B6e4dZf=_RJ+izV(mB}kn);J=Lgcz(6fTH%ZKwORb -z&ftq*O3ywe!JsaP=7$VPES8jJ+{K-kJ{Zmd;X(s(`ov6$OEpa3FAj_V7TDcPte-{= -zKgufq%=;1NEdPoV(ys;;jszi2z)zI%N=SI?w$H5I#Y|IWDshdz4*$45 -zh99S9C@zOU8;ZYs65^5eoNlZ&@zwdqUjHVh7I{qVH>_T4_)6wd7@`J?bjp_e#+P}5 -z&*S|pq>K5j7O^a78z6m1_65XBg+j&J_UwWb%U=o~1M`h&(~rv=tZaVQF`Xg7#v-;n*gwX;ov?^vWf -zjBv8=2f2tNYtEC(6u)J=I9z8q5ZGN4ngF#G>_j+8y3G44HxxEg8X7Fbyf;|MWJye6 -zLn{+Yp1aFK15#f;Fj4B&n2;Zxcl9(U&&n!t&0NpMt&F3SE|=H>=1*EGJJUh|W3QbS -zRVjBCNbt|9OUW7q(r9HFkC8vz9~OL -z03^T%LeLCAG$u@s2F@tYY76DYIN>_k!Z`MkJ`GMQt_HP)}e3(;(;n0XI?uu!;?M8qP(|@ecXS5;(8~dE|9WiQswb -zCgnYuL~DsY$1Mb*Q|FGY=10(*(<06D>Ss7wY$%aHkkwG*zxWhn6zn00;Upt62p-@#(7I5H_?LAd9_rA%{I8kE9ZXuel#K7F;7 -z(3X`bl<{@Gzi_La!{wkd-yHunC#?`oSdj5{6NdY*QZ7QR4Av5?LyM -zd>gTDWpgJ)Fa-bxvP3rr>y0x*Bg0d1J!Z;z--J!VRl<5BQ2S -zK)e<<+8#WZ5wuj$)FD)XK}Qg0N(a~h&x>Jg=}o$t5EY|AZE6LpghmeT8iny4h*%F%fxjU|#i56DTf -z*1NjSJAs@x*QES0Cj--RbgmN1#s{Z;PQw@pY3*Y2yZ+EB!)CdHzJu0qRr+CnXUS{!L)#9kWb~Q= -zE=y}D{g%6wzXT*cK(b-Mgf(DKYsY8(L*_8Dv+rZobI3zDic%_}(%6?EA(}PY%-7+{ -zcAc)9 -zVp`QbTMV8bd)Po?OvTvDksaCV+Ki=Wd%J{!y|t>i+}#Q;AJW{#3ep&(vkp%i({r^6 -zrZA80OfR5a&D3XKb-REc}J -z9B`vn*}yG@HAl+yiEZ!g=Vb4{Lu2-Vj3?_S5`)Q^hJL6W7;u%f?8B)S%4MADq8FsV -zZ?YqlkuD~5bYe0A(8>HTQdCVq1Wr-R1Kf?mq_rk2Y>pujGWu!ayEaX -zPxGF;Uu~v`I%@W=ZulS0ZsM>_0v~A2tz}N|)B;l-lCFHh6h#6f6E?t(CYWvyOxs{og -zAQQL%2MB6aRkhYq1FHQ6MtlmAk32f#_78lSJo*oO`T9TL%cZu?QbP{M9MH)+wM}LX -ze1?v?KtucxlX|3vE>h4kZA_yQTbQ=|)4`*4Lp7$bBt2{d;GKx~EEnL@04+1g?QNVw -z+A28|)jCvxC1@-#E5Wo00%^K|;$rYIEZlA?otHszKbEd3fitLf#8*K%lF?bgDN}f* -zH6?KY_7K%g-gjfU-fd_gZuA7K)b!Monov!Po;UvJVsU( -zln}?xfhL3QXxj`%^vgnKZ3#?aF%aFjsGmvn$i@jalrC%x>w>E}6g^`Ax|XN0k;S`! -zjU{m{V8ZzzxkyZJSN^9Q+KMcG#us|t2z<(~MCc`{Wa42#pYJPgH7YyKP!%DFu+5-l -zfw>lkz%hzT1t4Fg9AQtfY6`#0fACAFu*D@~;GkV_%;zjDK`YOeyvDxT;FGbW+g~gz -zCdru$0!4Icoa&q@#y~|W8T*=u{u+gUnatF`OeW97^dVC!52k9E;3A-h|BsQ -zMv9+Gd@>NWU)xhR{YiN4KTM_q9A{UEi`R7%pHc=!CissT#<6U^5}&L&<_znwBw64Y -zMacw%`yjp_1;b^`WNQX-z2gD{%t=GuYz;ZaYYD*F*lpfrXB3T=*t$kp$PMc)A4a2? -z0n*yV?w3*}dNg#J5spg^KQG~t5P$}Ni}-k$&(#Oz8Y!vtymBEXA<14_qHqY4Vc95V -z3d=$!=1>35SCQvw4wULmjX8OXeIP;!Ha~D%^cc1Xr+rgF=cw5jAp^Fx1L<{x1S&zP -zB~5T}+)b6oxU~D&=N1Yr@BU#jF)G+!VgAiz4!UkqRm)lZ9TP={70LYu%S?9{)YKw%)`3_lSAsEBGI=|6g19*KujWmAAPb@@ZS^sU-JEX -zs>u1jr|>^AvP}BFKc4+xpDi!^-)>fXecuv)_&)@S@5cZAO$j#N!~VqoP0{=I-!1!E -zc#DuLjkS}ji!W;|qt}IYFJ@!*klvFvp@QqkpGY{zX%d|`*ndKx$;3<|fI6sI~ -zoL7x|yb1NY){oE03s~oZ1$y^z(8iA~ZqN0xTz)17?9~-JaPWQbf1%pE*O} -z;;#9U@=VkB+@Se>^ZUF+JJRQ#YPKm>>G6lYFb*a5t$NAce$Gq3 -zqO`rQ4t(z$`i(qwUQdgQ3Ga4hx{sWD1~H=*pa$A@6Jme&guZ?MmDrJUhAO}2N-jA? -z*+05|KL{Ye{-Uo*3F$`~N@4?&V$#!8_Vqu(sWa@8{rli|H>+kEN*fN8}lXMNLPev+xm~a3) -zyBi3N?GYu4mXPNKGhl1yko5RS#wUn=1#wyQe%#^z*zfUu>DSdPqaQ_bI}eJ~M_lne -zpF#c%fd$f44(`<_vxe`5&Z97;BHMoa|p={opIoh^nl+-AT$3Q^GgE9)hkXv=2p7RFTsaJf^W88lp9N*+wJ*Wt&;)iT5q>S%nSvP -zxh)mL5Y|rTZQeB^wThjt#wJI}zVX{CMEQKY9fk8)H3U#zQyj%2uJTM24r+NHSaSrO -zs*Zpd;#m9k^Rq;x^=&(;)tbYa9zXfi?I -zk-yye^Rb@TrHeuT;*WXwBhW4OF^rdYe9;|jUlTOS3k8u@E0;;jmvAU~-j=j7M0~oo -zh*(~QM%X{}{tg$iMM(=8E -zX718HG5a|gvQVOb(oa7L{Kz1#^}pqSkr7h08lQd$qvVJv)sj^CcdLTc?rWrEde0pA -zYsmGiA$hdx3BjaHO)~le56!aM-}1&B(^&>H$WN4MHlAEooJTlnuO8=f`r6V@dcDrN -z?V<7RD_peU#e$rts+NblzA1L@*PQw`s_Hnxh#R{rcNWUl&`k+LrW0pcQ$L$=B*Lfb;FFqCRse2{?L9B;OgNQzcU9n?xTOLq( -z8)%?_W_UKLEGD+9;9<^y>gJ+`M34~^SSe>4#ojm&-Z(xKI~9tfA!QCOe!fJq&0JQ` -z%z$Lr0epyKBUC(pRv91dslyP(kxgHT0c6)gAxD}2YT`S~LAis2frpT5>w670Mho>l+o7p7h -zDqGd=IpSY6MT5^@*N0AryLrp3`C=SmK-G?7Lr+DF7&xhW#%<^OF?vIcCHlKjtni9- -zP|5>dTLLdr4xA_Y%YnhB1*g@o!T&ivs-5u*bMY2xFndx1 -zT_^9l>-p&>%T)^Yb@cOfn*9!6Lz;cr)wg-e!)(nD_q3t){!gi6Z*9pg<^=upc(0Fj -z6O!fTTYBYn{e~27>Q`1xNt-uc|KtstXZGgl$*-62O(!$i<*&My*OBM%z1NX!#t(Ol -z0c^g6+&YkUMwEOhEDx5J-4?}1-&;3sxsm3)F5 -znn?(Ocafix5wJ59|MegXn!Ja7ji-MFu5{?|Cra>g(7_h)u>$bP-mYSE%1X(SLS)9H4cmS@2rXw9v<*n!F$U7#;<{~4Ec|1lvkev>koUnmOd~46UNAX -zV_Fui{e9HI-9j`^lqFRi<*x%=^IS%{c98RE$M@02-y6fLb9krzT2plK>P4<~^<^V& -zDQ}BV;1>0i+ocztoz)kfBKSv`Gg%FK+g*Np%(n||Rw9oyb?3LmKX2lf!X947HI`Xf -zFx4}jzYtf7DgHFL=C@Jgf}5NwMoFX4m{&J-7etD)Tc?2O9%4C;s3K8_88@3!z3sT(LRHed;L3VN6j6>h=Q_ZjiU(I?q|ztzZ9x&95wd&*&1+!qhFB#t_4 -zo>)8S5)ZG%`0YkgW(8Ffd;E)%pNHMUitF(mKL~J|`4C!;b=*Kg&!1yqTh5l1bM2M& -zsI;q6ERAVhilYgk$UQX;DeJ)zH2~>-H(k6?K3bIP%OjN)N&WQ-TGV3h}& -z^5~zL$m39l&gO<}8kw8?S3dq&CV7tKmx4ThxZRU@F6JFR@bcBc;(D!oHsroEgWXlF -zMSV!b&M$637-~i1Awf&h8KKv+nC(lpsP}dAhdbQ=96Y39+_4OQIvGoUrk=f;s(@CX -zDhdV4q@3OXq`0Pgi%;6HP -z_tusqeV$2#=}nL>#x+7E-O1(q9Jpoaz;JM8({ff;tb6U)` -ziU51wCV8EcTTYRCoD@KaIt;~hWN#(eXD{3exFhT|$tVhW5^T{;M(34FZWCP-&EF)b -zfCs!?mD0xcQV5iImMEpeqJOC*qS*0+gyO})zg=yRS>AfepQtxhz-Ys*y7u7*)&*I6 -zc@|Uph#Np8ShBe^`mSTPU-*)_w>*6>f+n_JN}ztxKZtDx_TossdO*03tl5s4+-%V# -z?t<$I9;jVvWc35sW)dsjK9AqBl?{<=R|QuiP|keMul*xptd^lT^rx!VdG -zMkpe_;R46(xU};>R?nw)5M`*Nw_+RH##2cEI>$@bDMv?%1U5%+hk> -zUG%*KXLs=?kDB+rOm{ox$hkeT%`p43we4_d<~hDi>~^PksqHX3Gk!?stpl%5PW8y= -z_@rA09z6R!^X7&v*G81>mRbAj-TdVJ1p9KX?H2pi27NR8e&&0A+Z7YP=~x5l*rmgQ -zM^wu%X&YWwR~9N2p1!xg{f@FnsbdrcdnqVh1mJGdl0H8pYrK=+)uC^R>^O@r%>N -zL<`&7vU}o927TR#cC+(%Yfro8oVuG5K3dA^KsNF==WRAJHTlw6f|u`w<*|3khU*{i -zk_+xb$+HClzT-05qPht=^7=Fopq!QSCj4KeUNzqKcmp_lf^cLnWfQ3{sf`Us!E%*wbT*k6VV^%{wFgiH>rqPl_}oS&Xf`*Ji!2 -zj~$s!S%GZCe+Fhet_i(7u&@4W!o6?*Z2S^jmY!zi5=q7f!b9>?+i9}|m8o~lw%Rn@ -zU;%N8R@RY>f>qP -zIs)HkjMQh?ah6s8B%?8mpXX2yTEw`%F2|cfqvPA1JlFm<*OzH>Mqi(m6puH(+P5f{ -zUUj*Q4;@npC&XD5c=RW9PAe3LFf@Wn5+H`_@|y}Cl0fjj1Qctpm!he$aFO*i4Z4~| -zyAM_#h{foqM+N~+7H_IZB7S`uz(IsJuG8&xuib^X^Ax{!oV@s*tB1@GmZ#gF)oy$b -z&;Om7>Zgy3y~m&B)TMpH+fQ_Oke{WV$$tLC#=o~`qCWtSOLy#*AKzdyj}Bh1uJF9H -zu^@iu616m1jUoZf)ypD$Q}rhE_Np;4%xf0zH_D|uM@jTfypzM&V!c`{O+sAwnSKX6smOIFABR~p6FRQ#WvA#wxyPF$Eq -zbS9p<9YqZ*B0L;@kozCuxLtSg*u8|H&lfCN10Dp=8oMQ^L6C~nZFbWL33#Y|d#VBe -z;mDrm#it*(L84DF<7|eTYu${hjefDcck~O);0GC@`CI;j_|q}F73QJ3l!abn_KFL^ -zktY335;0}E-Eg_9{Z`G67*h+*kB72= -zy*J0{_lJJE=<>7Yw$H)1M1F7Z*VAe4OJq=uZkMurQInRZf%TECrG1(+cI+Adje_vp8#bHYK+(7^ -zCDz0(N3Mt6EZ6h-r>OZ}FYbD;+W4KVb~lU}&XglDMH^v1Oq#zA0P<>fuE>pZg-+qA -zDay9Dx%uzueL?E+Al-o9K0GVQ%pcPj1#X?6DvcQ!WNh%A-}#SD`XRWl=z0kd`{B1) -zO_&v7-(9df`xRFpv9`N$J*XtzmL4x|iY5DZWBGgf+|qnKD)nceZszW -zFUA{kc`3n=NE!?I5fQ2(SZJbf0-t?@Pk*Ms`n~AsCEqQ765Z}(9M*i2!qhcAmOl7j -z`4Q-f%j2VW^FWMC{n-_Ai1>Qa=!h-)@Z6dA_~6y0`ht&8s*cdc$$eX9mvv_5jS36a -z`h28pZ4OSfapwtcgPqA!WQaZ5dD-U*KI9VIg|20@Z6Zk4i}}0ed&wV>P;n~1RZLP` -z3GAn@)ODrRw$;WJV7kY-1DD;DkXJQX?nrhpMN7t}5eEr#cOf$g$nX~f?pd8ItJed( -zK;cL{cC_?rBR}x-IG;f5X`Sr=dIp+%0{y#4gUsFqB?F?prj?x8-wM@(svu*+7<@H^ -zA*6>$;OgDgqtKI45XM(EjMNvLK5rl;pQrNn_qX>Ctrc^$X%(UN(R%9(%!p<58>s@U -z@GMQzWEYj@@1#&Nisr?uxGpOo^_e%_E`g(k3nYHlVQZv`5Yf}5m-{?VmQ03K>vR>v -zE3vh|(Rp8vtL!FCqg!qkD|`3|-vyd2m{e@IPd^t0r%LC7sBqe)?ulV5anb7uje>(< -zbIGb)@6nowf&Ds8-&?Foo$+;*t9c<=?L%P-0mL&)xJ#l50*8d4_watn`eyueI&2QmMpMKrcsZY-_gIowYle4unnEh-9*aT2-{K$} -zOJIrB=W)8H-mrR(?W9U?l4;>5`g%pancg;E{6HC_O4D?$%%?Ag9je7^bWl)y7dZOd -zJ7<{K*E?&!sXxQ7OKzIMrqYGi}LDo -zl~1DI-W|wvec_yb+Qk1DkA>$yuDr(o+If~qkVJcl?!L)zjf-y9*`G()=0dVMyqB!f -z7^lOzwd(zfyU;2hUc}K3+8I+Jh(^nVRpL4nu+W9FB~=m|g4JgXG9+zuX4e#SWi}+~B(W*f&kspukx@ -z_R}v{{w;5wFb}mHMk8QO#hOa!?shSJ0xJAEZ+VXRCuUAgsD#=l&o^jxc0YRH -zsQ}-!7oPL*F|Xq+o|E9uqa+r&U|>bNvtCgV-b;b@5d&RYr7f;hYl{UbsrV<$1bVKR -zEbIm~0AJX`7jzoPfbk@<(|U8|g5CH#=ntp<95O5+QsEW57a~lZ!_=*!T0q5zAi9h< -zj{h)-MCqI`zhvyIk3Tey#aeM=G|7Dy0FmjGi(auo5;E_*!iDIPcCtgD90XTRNR5vv -zykY@NaN^FPOJ|N&uCY(&5zh|}4c -zz0(`KPEkhnvCLF6PN<)=Qj#7bl4zf^nrPsB59m(vn-W4YRTw$~YI-VzYFv|aRd>S5 -z;|ewtKQ0?V|E=}mn1jGTkUu-w^|&B(W;{?Ke|kciUpU -zR?=78&*ROLT{HIS!b8EG2hJUeixUzT@y~`{9{lI?RF|V&1Ll5Q~br!eY -z7{z^MJ0#6Y2`2@zw0OMegG}v4=`Lyb{@RzXDhBN%LLJ0s#D9p5Sksh3Z7*r0W3d?T -zqJMS9R&`S^yqtJy5b?`ywrKwf#SL?%yj*=l$$dSuJpDIntM?>{`LfLz=eaVsC(Y*@ -zgB4I8F>dO%!M7cY2~Yk}E9sN<`R<*JCDgec_SC1H)U#=y0c -z;@h4Kzp`5QyB7?QgQ+lA96&G+9lNQ`{Cr@mZizLImuuYQs+Myl8ICr7OYU7LzTof_ -zbIKEt_QporMVn-AC(oW31^7d=BRGNBM;5LARqLFPa)Xk`nd|>*`&)pgMt>wQfJVNQuEd$wC5IZ@d??7YFcpAWera4w<{|!+ -zHY#ZZGQQ^84q85t-dr23z1>57;Cub5&O&-kD#%-W3&!5$@VC!@q$v9R?mB+5A397O -z_v$6E#sI$ud;D`|fSYD!l_vci(%A+{+-ZV+lp>;}B~lRH<`(|GUF -z9k$wWRaD)A8+ug6-<^mQKRELIxjQdZjotJg(?s6mv->fh@}Y){<`9`m5GOkG3)p&( -z8-EG-k``7rR7iYceFx1Jc3JcP>#B -zDjG5DjRgd7Cc_V$%`AeBpR;OVT(>pDBMe|y=_Y|5{J_!xfJ-HN*%SGkxzsMkFL;?e -z47w3ey4d3XeuU;lrM!3`=xTwSb)`|?^XsS&hyq@l950VtH*{%NczpT+iV}?%C+=-w -zAPTBgNh`YH!KJ<}j(`-&dM1>@SPZq!%x_i>kWZUyojk`Y0vpe#XLKRyvfy3bU$sGy -zK<3a$OBJu5m5|oQ-t)8KsRpHN^Kzw(-KD4W#gB&NbjloPoPi5a)(&T|ct|b@FSdiC -zXCtyXP5C@lmc7V3T9;8iK98;p7;DC)aFi)=0p3os5$RCFLt~Ld%8%ZvX`Ic!u3(cB -zHwzWYNwbU+;7(Kp;4TJ<^!S^0lg#(e4r2_uT~xlnf?ES46raE!VQG=tQJ)c3m!F5j -zwsDnA=uugxDE3td#PS3e@%Zu}Nf&rKs4SBqT8c+NoQ{jXnK@>{|grwAR3 -zpRe5x37#$nz+ZLebok-~6zLZ6tLyThj$|?4AP@+vf8yU_ -zsY_&%yj>!&DjuouIbQ3~O4S`=z@XS(*~1a7H+>8VmjlU>*jjfCS0yO~p)LXMia7AV -zue@z8t8kq;GjiG%b6)zY`0cu&F)sDuQA2a?aLleJv&ckOi`*Ii6)+B33FokjCuJ^> -z#=oCDi^i;vgh4GywyK&<``Ze>J_r~lA5-~$iR|8oV_*fof_%Hwix(J`l2-+J>MTg>r|r>vVrE5IT}{y(=2f{zvU#L6}RTZQ~C~cDyGTPsu{Re(i*zOH6}#AO3j~ -zr^sTYWC;qwl;eC$QSZ6L7I~Rm3kuluSaIx)-xdQiD7}h9f2~s%GD^oBa{GBgSwB#D -zu{MP@%*S#{16g-!<5jo^_-t$7WgoC4GYKZ`z=TNIdMmY(y^CANId8SlVUK_$ -zT2*NLEva#WQnK5RovA5i-OoK}jj?TwZla5ly -zr;;*>OAT|ryHANf_Y2HQh&UJ|txGad@m`h&#(upaSxDcQ+pInCVAh4!`zbc~f2UO>8;iT3t;%1l3h*rl!z{BB -zftlZ6#-di`3?MUOeQ_t8Edhw*jS1}S-uS06De~u9asRrgVt{>s+Syc;)`@kCZVFK~ -z(sQQ;yHId8w}6S$VkKVu{;P}%ap>st%EyYiDzgZKMfVbEJ3dQ>3?D9s$knllu>h_e -zOZ);pp=}eR=`bjZXdw-~jPBKQYROAqh0!4ACOEMBJ?xGD8QMTve| -z1A!T#6cOB$Rqrley!;?b-MmBQdTR%>`S}T)L3c$2P>O2QwUxrpo2gonY}(O@>PYjk -z#KN`EG&y&Fe@`p=;OQwK;0z|}=5+SRz~#S|s^?2tc|a#_rGMq-VT4>e^DWVpt1Uag -zn`{lg7VbhvrF<#%HTdcF+I!= -zQd45gm2na<2PO)f&ncp=+`e~tJ1v%7#r^|cC{iYHCXn377m2@Wcv#4SMa$DMbwC#6 -zm$i{sXd~hh)HPGQ<$?9TWmPFSI`(fgC06`QQ_rtEPr{S+h{PJT!sdjTK5Y$KO<{EzOOjzB5NiI(V5-zF1MUF%p!3eaUn6(F8 -z*XY&=5;L+OA}0=CiLDY#+Co|+HgU;6<}Y?bOj2@4SpAV&$c}T2S)OCjx?MU&a~68A -z;cWJZ-*G0UwfiG_>9GNE0J{vo&jS&nD~lMfe+jGdifrBRkU+TOCaUxWQ$}BPuc_*Z -zG`a+QvCtz`m9pRfJ~$#Ke0Gow=&|i@Dsq)wbBNr%Kl@5i+=*L47n^+1mFP2(`>Vrh -zd*^`P!tly!4M+ZwR{<#tN!oSS30{-8>JDa9%?1Rr(9KItHpxB66%AhOY6QN+XPKGZ -zHsz+&#ZMhSx&2#U1+tpED>~GqVAR%!h&}vAu26RrZcw;i+n)+FMM^8I-F7B$w?X%% -zvBo(HLl1l)?n-(vIS6F!jf7guhn>3~ljfYh@X1ELp%mCxeqK0e#RT)W%yrk~PceJz -z9E*&#fj_VnM-1U3xcs}ALNnuf8otAkSlK2LA6QuEiJV@P_0Cz(tWdToZq<)6SY{R8 -zw7L{bh&na>*A8vHH3Uf -z7|Z^d=f)TA(*IjX%Fxn?+W6sxt?j%EK)SY`KoVSGT*JR>4Cm%}#zG937{{L>J1ry# -zHp~F3>^TQ=fq{Y=w=uxR+*)$*Qp6eqBoybm?av4mO6qA-kbAooQ^yG{&+<1;7vh3c -z^i`irIVTh7o9!MzbupaQY9Jq4SN{0J*8Ouu+I%PZNX2BkMi;<3cAi{pCz?~%ec`u? -z$?2N6W2`_U#98zE`IiUN2GmWnI1woj?GvjS+Pu>A{<%OR9!C(ikbLv1K?|7w{AO=1 -zYk>R{#8t4s;FNP+6NGw4fzxy~2j^|?c`)%EKjcO9)L*w%81(WfN<9EH>q6oBaK2DH -zD;A(%-V*vH2dCoG{Ua6T|Icob`}{mU?H|9|D;uhRT+ms028)K -z-y-h&9D_k;(Z_a5zw;X};>h5*yZ3K-Q2C6GO@paeLdQywz#>LW6NdPNb7{%x9Oc~+ -z!SR)k;6R$@Eo_RTK|%eS-fPX3GkjtpL0_5 -z8}u!crOt^@C;&Vi@pSObOCVkMUyiHZc!-I~FR4-7AEj0?NBeV*L?9!nBC~l=zcGFP -z$dPP0k^DE!6?HXUQI-Krjl^=yY??5#UWCs$$dy=d$ZtH}TR&l$IL=dbti&)v(?FIX -z5ZeCdy;>K%k;H#ISKwKHz}etS_SZF`FXpB+VQH%US~&~MlLbO=-HmiiBQNmPH|VEx^fW|=Z_;}_QAtp95KqcG%YzsQF*Z~1VGsz -zCQh9a75*)|8XX8YXUqOUIXQgzr48psNC2hG+qeqs0$49{8d$R{FqxwB`wc0RUudOjlefmaQe_ -zPxZj8Yjg#vgPGj5F}Ln#6?SRrZCD2M%zl?7)OBOoKsvyD9*lQ -z^|S^5z2ba-9Ho9{BOz3XlEgf>7L+lOVC+G=+R|ElLk$UNoS7lxcYb%8K8v$ITKAD{ -z(+u}4@wyymq7L~0v`nzuh5HbYJMTyL@8oIhu5l32*G_o!y;_f=85*1zV(o=`zc_=@E2ZKE3s>y+nRSL6010~&3YS;HxB#!C&ytb&t~ -z#LE*Gu!wuy?-o)sF*Fyj_D@iWeJvafwoGX1jtm1RtdXvU#Y -z1>1LW3VRM@eWm2_|DnOswqJe?yt4>lCL9YKHNI@MrZNle}cZXzO)A4}68Z+Le3+IUiM54yTShI9Ly;-&I7A2f*(!Kbz&-RhS -z+zrbQL?P$&bODS%sL-=|`PG3azxxxaH}CfKE!M&;>0 -zTv)hDGOM4z~|W)zjBb@v>RkciUYw2J1j)s*;2?VGx`x+%-S`X+64)VoV>=M -zI&sM7A(2U;Lj%wt&3<(90B}{W-M?mH;{#aVjejCfAK(nsS~sV%mQ#q2y$P%L-~TWR -z)_u{T`PKI-3yv8;Vhnx1K3fNG$El%}K4-3O^~3_(3J38B)R*%vld9ZTtNcHeSSI1O -zc?oY}JAF;60?KxQP@(jU3bRPn7IG$(Cv%#LMQ(UU$w -z=pii)Q3b&!==S(B4H@}0lpSnp##C{$Z*&5(P!4Ow`tT5Okf~%Qfz`uN4sA@~M)f;_ -zyeOiv3tE1L@OyO0^O?Fw!0CCB@?2|u3H|!t)F4H#rRDND_<-p0?UUt_5VRSp)mv0= -z!_*0WPzR||RstX~XR(X3mC~M1w73L74|DR3=T-EWyV4l5|NVCYV(Cq@A<{9q{D1bb -z;4NT1wHk|^5B1=DG5|Jc@s3FM*H`cloJ9XlWYuz0uURon62eS%CUrxG!ul|@$4d!i -z;C7KE^vGZlLLS4i#W+@}Z(Y9Cmm8vzN>pBDw|EB>$SS8;&Lq8SOKqutC1xUq -zVRIvhzAQQ{O+WJzMC`r*{xgwPrdX_g&xEo1Ib*RD?;zCBl9%p89=UzVCzAg+G}!Z9 -zno6tSII3P8XEaowzvCgKf!aY}FbvOHlNbdq602Q&Lpo1Liw(s0ohe%54h9pP25n^! -z0UmPqZ*MniI3VJ&9>?%AaYzul$M=aWO$o-mJ~U1wB1a*7eI0(E -z3%XtDM5H8;A8o{JH=gX=DWpu;2OyD>!%;Ltkojb4n)DaTYV&bfMwUNtqg`dMay%dN -zyBlmHQ6tDZP}+7|Tl1(T`)^j3_fP5mQiMeKUt<%{4gAuqRvLe;tj1))lNF4*IN7}R -z3Ckvh;jtB%oRSw;D)XqU%773}ZH6SHZ)p-L%y3fTVeK#e*O=#%hn951L)K>EW1pAPZvS -zS*<56oW^I3pwxQ60RKUKVn0_jnHv>_ELxRep3TAcvBjBh{DZp5K6(KG&fSuvWS|MIft-NH;Ex#B@8f=|l_LOj~8GvZvN -z!_uA$ru}{i0jkR6N?nR8a#@+S6MJMhu&*FT#BfS(C1k)~*Q1(D-4^F8g;|BSdmKvI -z_z~$B=Nn+=6n~PaD;}4kPV8Cf%t-Xu(P`=!CD-eWBPf!El6kl-*#MSJhR6DRq)qSm_q&JvGo -zOL%I+WiJ02Wx4+MTt`+q_XY$%T@4fIl{WbXIq#j^f!|kZ$WNTy@#b;Lc<+ -z=v!sdd!=mf&BYB%9YOe}e67rI-y4_ZF}zo|F#)oKDfs~fUOgq3e5E07qy`%)Ux4Nt -zAD|FqG+CaLdi6oQymTBx=U&zD5BL0=J%TDy77=}3ieo0OfW}_!zsp&8^BAg#S9cDP -zwQpzjVxOk(oo;n|`<4~B3GR-2oCj*}g~%Y2B2yD1WC>%!0UF~lO(eb}4w(aGRE^q{caDN!uvYDzgh+h?W&x>|EC`lE| -zjXF6&;_05JUqPox&e;iV!-0>HoQW%12sK5;KD~Qr!0Ctz3z&Y#40+#Pzqu%D -zi>WK`eKfmG!(K|5J+NMd0F2~^BI0+7wfo(kH1TFRTq!W -z+i@7l(Wx=oTP&C*0oHE$La$`BM;X05avMY;4Y4M%ULzi$yHcES*Hg#8NLi -zD7b3epg2ZAdF3tz?%JOODy7U(Rt-o@AMR3JLHZsttUx%Mrc2X>M$oI*1B>{7LbMK^ -z6m|P)N28CKjm|TKpRI$=UG5QsIWiHvSg^pcWg};YA%L9h1+Zm -zN>HUt7A#u9@Jc09&!YU?42o2!yQ83?; -zveLe5O%Clx!#Z&b3K?x(N%pc>anm!ZLnD`UN3B4&asr7@zY+OrB4r*7jz*ZyZs>(8_K -zE~0D0dIakIW&9c~<*Za!IjRY+oIHf}tt7kf8Pwmetp0Af*3WN|iFQG#-c7Px{>(9) -z0=Wf>NpQxUxwVY!R8r13^Pv={It^wJ`w>_e6Ld7isxjou6fd%|>n;ucsn_ME$8b;H -z#KZBC3P0%4o%(&mv2WHcvHOMLCEZl~5wByJ5S5w8mLm=FA`{sjCj7YBC6BbF8i{CU -z*RRu5DCW|D1{K_}ASIl(Uf_K^dNVO?$v#6aJQ-q!yVTOZF~%`Q4(T -ztRTV#13Sw~CO(FpQ<=&trmtt?RxEN>V);>FHzNgphAUS&+I`us#6cAz5V#V!L&d{lAGv`Mv0zHOsMaLN$lMJ!L;ZN -zDKWDoXv>T4WHB%>NGrIi>j$WX>tv2Ul#2tfm?T8e -zC7B`2*u6H*Wsy=eC*)#PHcPWiuo~;q3%-l`*83n|BG<+Yf64|F{0B4Y173T< -zgAnCL%H&zxF0FS9*JAA9i6?v4dg226EGXfWgjKbI_sm)(-AwRCloAqN3F~KT3w-44 -z0H2ydm&KPtqFP?{YZee~BsBn-6_aNfYgd -zbP~XDABYA@!W`XM!AlGg8MwP6~~si=Gn -z=O``xQx75M4@+cjhI*cLyr&D3Y8Es0H?SN`HTv$9D3%l`se2@9*qyW-G<}W3CbfvP -z#Sze6J?F4g98mb=G>yw@WTPn>h_fT`z1ldNqC@-Ods;y&Eul_p6^Q^>pBo76p)6%h3($Xpa4_4^$W2>Wq~2XGWvkJh0EpbP%hL`6Fv=qGa$Si -z><2o!S*{u*JA@a2oTd_~@~q8P2088o5vSVH%fW4KrYh@^lVW9b%Vz|1Ws!4JM(O|s -zbSKun=Xa-VTz|(CYv&j>qb|rGT*uW9G<@hI${`Fp9Ws2VLQy**A^(G5Bn|lBT<9jy -zCAP6w@%pl*c`1_ubT$A>NN_4ttSl;Dt-$v|XEYO)`e0xfyUr{1S!cN_u?(dsx>cmB -z7BI*=jPzIKlt)yn(=C?S!ZV$CUO;FMrFHgG?N&jfpis|o#L8n)R(Zi(Sp^GH7}^wl -zHvVC(*-!sC5o -zedM=FqJ-MH^Z6zp6oM -zn4)h&)P?s#G(NulPUE%}gL4y>2(lMn6(|v%T#cTXGNvltNwhw~@oGToH-_rN23z@V@fiqyl -z)E?zSOU>mC74+=m#sw1*565KV!X{lXN|S#9N^CyO&w2I-C-Zzm9VDh_ugR75n|NZY -zWJ?N?a)W1a`~J(O3xOZE5}%RGPu~_`Z9qFl9K^Flc;hu$FYt@b?BHrbJ$ADl?&m$xeiW_J#k!(&{^IB=%7e5wgV~PF3^7 -zSx0cwj~9aTZAU_&hl`Q)lV!e>l3sY`zu!Z{v!L3Hnbm!qsc*_6?l!O$SaP8Bm&Ce| -z#aIVfyC1=(P+IZ9cvLjNBxYTd4En -zf9pe{*S9IQB1&I!9tM!jBMJEVv&9Tw9;kXLUzFaalKMzlI!SbY!2SwZU8&e-9kbU( -z95?22DhZI^NRzf(IiwbS4zcjj{XcSA;59c9@CTkstK184#Oz&Q*eoK!T8HSu$eL3) -zzp3bkgnKK#kx&qD(iqMCDkQ6xx2IOt1z~Zzufg35S4z-=GF89we}>CZ>_Dn-ADC5! -ziX&n&w7%L_{J()(@mbf2;0`1pfj%{ma}(O&E+kSEi+-Q-17QfIV!{2cg#A_zP-*h; -zY2-yvtg~@`BZx>)5xO0e@Sq)lcK(xFLkop2=`ZI|mg#x7Gc0Z+;X*OU8C$f7807aB -zY3lgn0>KLbD8p{?L@wawIRqLF>4ArIhN<{yys|HQq|h}7BqDM3VhCfpgm~?~?n2i1IO&{92YM7s{)_6zAAMDoA_>y` -z2srf!xRSIOW|=2_(~*E1&;;@mCQMypg?GGAzIV5T2YJzP(x_L4MbGKATAvCyp|Unw~i(qG0>5m?!(K+Ve`no1FS@ -zed?omKP@ci(YzLJs*8^wyz^-ne|WU{S5E7X!ApOu4qnBl1*;TMysw4>10s_Wz7|*? -zk{?g!_Gyb*P)k3krzdvUS9ux^WIZ>eS3FfgY)x<#+cRS$Wr`7+IlgoC+SgkV3k+8JOsFyY;`R89-Q -zt;GkzY=2I`7%(+bRwOXk1%}RL2U~2_FXqSvCkkr=bcWbA46`sum?-_71h3VO&Nm-X -z#ZacJgEArr7N9OTVXI}8+clO?zL62cXYnfMe4JO(A^udl-tUYcqgjsX -zbq$GmdTenQnB^flgNVcM?xZT@p3@lDqk?M{)J93=nDp;S@%UePKZ|M)6ba(j$0PDd -zcTq@5I|#DCD|ym^E -zgpF}G&x~53(J`(BvYtMdxpl_aQruyUN5wo9tjBE_8poO9fG)sk8p4Nkqz(4L1ZpUT -z6}Q4bSr|W1&CPoHBdF1YpX=FC?edCCul|-;OiG#TKc=L7!Rlh`i_P|08WQVxXp^MB -zK>sxJlVKLQ=tf4gGOoJi5sBz}jnpnGb}p!>58;%PlXr=RQoiOjjrh==gb_%GVA7k0 -zX?@6ApOz$?zxV&%MmWB-`~iB~K9Tc17fiQ(X)j@1QMAjbgQRsmu|W(cy@Y)RWIQS8 -z!m`5(U^1wW<`&lg&Dj~zQCd*rfG+eyAye8ir~uA;Fu>^^v|P^6YNY$PI% -zd^kmv=y8D;MYCvuR&BC;VES8g6m*6_1)70gRyDB+q$s6v03tuli6SclbE_;6w=)>b -z7Y9;ICLP7Oe$6bIY~Lm5SdEPr!#kMvt;l>7U$%H&!()GbDnQKV2{0a}SsY$A9 -zz@$@&qusCX7G$4~vOFagk?Z#ci?V-Lj9sP6icL==A+rSfGEthpG*KTBmZ+DI+hKTi -zUag2JvU}~D=Ac*%6vWJG@5@k$Rs0cubo?v~vf#%32amKB&(LY&Y+{aNR+n3d8I3jB -zUk2{r*SQLVfnG2Q37W%)pH}H64jTp0L`E_@BD0lRn|1e_X1tsCwmX9L;u=7{sq~ZU -zJ~b!+rP_OnwGyHE^#>MV^gj6?eZ6zp@&gOmg*?<|Q -z67jORG2%HbScx550@kTTaZ#OKJ`+LHu=dR_ag@l=zc~wLI{BQOXTFI}N}-)-2A$q$ -z^h}y!Du)+q(2tO&nOvcNTC!S0v-8z)Fq2B|&4$daAV=!$j3g_2IxOIFL+e1-?=M*F -zzt>PjSI)gHTsD_?b>2CG36x2~VpvYYs8=dDzCn7YyANv@5PN_>_}q!P49h7~VY@R^Pr%Lb2Rq0U6Lqf_TGeFKZiMut`WS(MtY=5au221PIc^+EY`*?QKudci -zI~^Hkzjh9iGq4mcs*c-b=pt(y)}th1uoA=o@>L!R54IH0v?mh8BOU^^=;)_yZR-4y03a)_d=vlao<6Fn2FZ+zYmT -zu^9XpQtyJ>Q}~n2AN+9GHT=HF%;!paV-FRYT=v)VRd8*p)RQc=Z0b>Z%09<{@ua+I -z7&O4BeHV-LPUcFLDS^)~L)H({f=O<|W!R9AnU;(M_PsF};u -zdntVo9jEZ)U|6(op)1=^Rp{y@en4e@F{=_4V&rV~Mi<6fzeCx`JJ$MSQF8DVkN{Q1 -z*jh&ZzD77QFJ%r?y4aNTI7;ReRnxwBvFjd`li_00V1699)I+ixR -zz>yrgJqD=LTgH-;=7RR`F6FxVXihi5HTuK775r-|saxgyJKuo+J}`d{)#f9c7IM}c -zqxsy#*=p5cCyP6=tVQ-xh&QRb+Ic -zQP&C=P|>){1|}{16j{$l{6#Q9mCvAE#Mf&&~1bM&;VDcefh5u?g*K{oDBb9th@~YyXD^ -z>pcgJ!z(Y|t*Kd8m)T@RPuwVfD;Yv{F}(95+38h)5g -za}9HWhPW{DmA`djZG)YCYp!`V!=vcb*bO3Elc+6I$pA7~*Pj#FMX`=KsxqR5dfgnw -zLIaYKfUIiVB34lmszn#nF#_FKtWejC -z^k`Yg7qenekQ3k3elJuTz1%0kPMJgNj09#^@re*BHfJZtHP;)Ya1{H;^9=wp@wz^tV=doWW{^@lcU>k(G|(y1Ut~Rog>_oS`;&=KcY5 -z=NC$^da3V_EFpd=U>=ov2>H?IKLe)+obLTN?)?|{q!F$%FE6uy-U}>)*49YN94j@b -zlEKjRn<{1<7p}dldBOISs|#?QRf;`vHQt8>sTSieY~uq)=A*^W#~B;Y)z -zvY;TyGpMI~a4=&a8hn>%<-ngUEED_(MY*glthhpi!#n~DF(??gNPUx%ii#pUYQu6O -zoab3`E36^sH#=QRWDDPDtL9{s7G3k(?4lEo%riqpGp1Z`ashx3r>;E>a%~j6QIPrG -z8?3CrKX7SMZZlbLa6eg2*CRQG@9gR&<}7ogmV$YT)^a(gDRFLAQc%nYoDvVcY!R_x -z0g>y$ihYm#x>#{yi%U6Waiok1|D-RVCwkr|PfJCw*!)5^GkS9}NVK`O&&70n^{-rt -zU0I%^C*6L>hhSM|xp3z~nI^nqyl=A)1FFaCIlVO7;aMn1ua=2S#)6`2h}J{?YK8T4 -z2ouJ@6`SC9$`3>KKbaGlp24q;&l?&@kJU;b?L)Fc%e*VD1Ukk!KbS>LnpWl3(uK+( -z#;_yKGZuA&KJo%jnE(7>m76+DjT&fzZic86l^*I8!|@_IMGXk8Vo*-mae9Cy(!DG} -zVs$4&Ozw$?fMqf9^g~+MahkP3VRd+lx@S*W0@WVxs#v}^dPewe4JDUFJ=%v&2RN!O -zpa&00-bR`=Oj+PPJQ>}iX_3DStPwC7nBGp7dRD~c4_1ExX;VIrIP&E>h$lU7>!x4rl?#*Mc9k3_w8a$YLIxFVXPXQacyhUzKhW6JXU -zGp`HXU{@{yso!|evaW_$qb_(TH72SHSWe{Y@pg(#QE<)DZT -zMJ>6*{D2$WgAVSa8(gdJ_Uq=Oj|{c*_wk>%_5s6oQz`tVw{(2?ToYM>op`ap;uMQ{ -zg5o3Y{2>x9GH%Gx6Psa95T-ji6dAI!Eomm;-0g-Rr~`qWpwZ# -zTVYrzR-Y7XJ(qa(OWE@6OTgmf`QvE}VBpFL$1_mvObsy7ke`eS_aj))-Dd -z$qh!@pHs;J)zPj^H)&KfdOPBdIzT^EN6#ALRXJrB*;a%29h#@MCkpQaY$2k*fT`-A -z(HgXx)j8dIo@z^MRs+ZYHzV@T3WL$dg;HGto~uu`s<`66glQxSTpP~62-B_DB#t?c -z@6?fLbZpShqtVtx+9>ayM>A(>k72Ds1c?yrTT{0TW7J2o5#5_*;Q5X?DuKj!{XR=Ao(S{ -z{vN~G0N7AXASjkN$`uXO=|tUgvt%Rx5zr(j8OMIZ0Ge+z)zH#BAZBO+KRzpYXEw$v -zc_k`*Nux@g5MZhe;2Y;slvM{1m%h&TjdNiytO -zdgCCbiPQCswhw61s^zLEARxnV5iAFv#K!HTmID8sP)Os#O&muG4r=cozI1Z_*FwZ- -zn583p?a`K({Z2!6(VEJTx6%1!4?p_l3YJ)CkHl-}h0jV=h`WJu8RxAYbNt%mqY;GZ -z9HuOPs9544StKaAW#yc+hM=nMRTe8QKX7J_zpxhA)|2~Lb&kXbu0hPGt@j<7c4}qh -z-bfaOWK=y5auL!8noY69uMXCm7r#A*Dqg!dvgR%W*O%1IS>zjXJsCPf4pzTRpse*Y -zsDzo@Q8A=-8WXk0`-XLip<&QApzzFJsC3cLgP`58MwROzZ}Mihd)5$^@g!l-dVYo@ -zbDzwYmLns^IDvCSg8$e<&tgxxFmfj#p5Kb~+Ro<9Eou1zPwMRmmETgRx|mxZd+&3& -znfe(p@%~9$Rr(S=`}~GF+K08g(Ju}iJ7eb~d -zd`l@%lpUQnFtV5DcV7aix$voJ{hs!z#U(uutY*H5=Dg0=%cZEJ12B=YJbujFcC1*R -zk~7Z?vt}-yt}DSd5uYezQ -z3xK4=*87-IsHe+`aNxx1DE$@p6S0vgOi_wtdS -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 -zX65b?}Wx -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 -zK)gAShqi -zSsAPuoVju{DGU&UXdd<2a;C0&$B~Uqa!L8XF#*UFFQlvNGvXoxWw6VZ70Cb>Q_?%f -zKp`p8)K8eb@aMDzd^ac{>YWhFzbLX4D -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 -z7%l*3D;IQ$c=aX`+#npLW -zTBPoEK5|S`PUTj>r`9TI@fGal>=qIdNkyV)Lw1t4^)wmPRne8aOwItSrGsH>mM9tmqIQ9M(!M5L~Clo_eFTf=o1p_XU;-r||Z$NFYKM -zBD^#*2sfVhYN3(`ITM|~+)Yh-{(59Tl6es5>Dj3#!@f*o38BP#9hqe7(pT+e=W$%6 -zJ)OoR&t5WcmCjkK6DPLj&L?ob450y9BGBi!; -zm0P}&qXMD^mQH`@ceR>Y>F=@cDqVOzy@VKh;!@L0Nv$l=XV1y -zMaCqIvF^^l9g?=2hCQ9iNl9n{Uc|{Xp7;WxYF%^z(R~nANkb7KR|9ky37EwCohd5+ -zCV^GT7*5efv#Aetm-yaf-asdvjW{8XeuuqsvK+*VJTcbM7`f;8D!E-F<*f2oSQ<|dC@+keuO!t$=_IEsdQlH~OSTM;{y+>1X%+=SD!SZo -z*~RFy=V1RL{GyVXEBNPy0Vn1X=qC__MLi?ai^bSssxK<>-cX~a* -z;uDSZ2>LT4m!0LXWKN42608Aa&v}Ur;x01J2Nj3$w=)-glNs4t%^9CUDS(y18`&+v -zDu7UU35hbERA;P>XFC0vUk;(YFf?eXE(Rhi%T~g&lpllKbUPm+FC>z7$A%=X!8`2a -zMMLKk>gakP4GW7g*P4PbiqPkhdOyah0f?L+ZUbgylt7{lG+S>xlf21ss*Zlp8wCvC1;G*{r2k5zLx@BtX6FY(xhh9Uc+xbqV1LDB9$Pio -zrzB!<*yj%;tvO;+Bk74%F%@A%nMRCjKOyIe#Rnhnf&IamvDlvh{Fc}nFPE6T5sLFnXbxM6>1HzJ9UfII~9d<&19Od*J -z6#~3NWpF4C-Nn>r7HVQJ`EY?Xi~n?nBqLY&z3U8g2#A{jrP1V7npc7JXL>tuWe$@E -zM6-Vm>eQdPH!2=R4W~^OylsV90c3BFs9Qf%77(rIA!|hSH#u -zyhccZFEaX860eJ{zZCG6)5Zb69aDxCDtZW$mQTgOY0$Q3vzKHV&TM(kwpEv82yn7_ -zTZj~<6jDVBL|uCM8Mp={4jn2fc7RK|yT0r^q6LH70ezsbS>dawDgfj_2av91XORkk -z4@G>SD({?DrCuQ=*t+amHVUPuzBkC6IE&yjh>RgL>39&7~k)?F9~c)^@99>M|=XtCG -zzDJ<3;o0nVI%o~dEf#f^ygW!uc#jJSXVsUrRgc1kimHQbI!@ct#_oK91S^u>Rwi9rN-H@f+{`g$=8))m9-9EZGc0t^f2evcvPxKe&XY|(Fv -zAj80wh$v$uDrtSJ*}`Ds0d0WNqpvfltn-FWx&~U&jvj+MSZR>RG|*!{Nes)8b-RoW -z+zZ;^(@#m>MWzaAIsoXLlde;f!Ro*sRb|G#Tl&GBlR=MBj647%%_nl3JU~NI<^%DX -z9qMXzs-l8IQ&T1!3?Y~SLY8F=5_o-LEMFtR5^6R?albT>f!-L;z=**%TpBPtBCL%2 -zPbxyA$@75|BClA26ZMj`u?sLjtnUoe+)#OprN-7vj_jR+oLwS_uJ=UZ&m`=@dKQ@U -zRML^5-hO`1)HEH#>#{XUiZo_B7|=+NJaUOYESTN_z+Zl=ZScG -zcLm0!dT2S5n^rLX>$&uK-yN8r>$O;#i%jjro(i2Pmx}}_E!gKqvj=o(48)MchVg(5 -zax6LPpCzslBdA6U8*(15-s(ZKYT&Ll?d2SD5@3(pWs;@HNW;X9g@(xYa1+g%O)R+x -z`keZ*+s7qEBoAZ3Ft6~!m{@?xP+wfUa&;9h%Bl%}vqv0w53z(&7XilDPK+!7I;i5y -zh5<7aFDFI*#)X5xrYn!J6A#`Ci>nK?3dd%AW=BLjg7fMPwIz1awiAw=YiExtw^9Si -zt;9!I4XE0;5vzq*Qi|{~jwpBu|Eqn-2Dvp^ik_xz4X?CSX4xRmXWf -z6ZX#n&1ibt>(UEGumb}{HNepdMNN5C>>TXF -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 -zh1kOrBV7RoHH(3L6#~;aFPM#~&^<#th~a -zK7!p6P(gG1_WR#GR`yZRMm`-m0Me_kKUnD1vQ -zIk$chf*3O|Ds%+Id4%VUSu`NC6=w!G4|zoGiX5G5cp+ -z$=R(dsU){7vY=y2VHi$#L5(PmN|R^@Pa!^8TvYy)QtQQ+HsIWgXf1#@Lhu@M6Wswm -zc#W~IB5k0JF001ujsY{5O -zo!7cZkh3jK&dG)vK!{1?$%vUKp6)}D_XA&P8K>NiXOGc>MVbi+*@?EQ(Ksq1cO-ib -z!My<#vIzJ^Y~%{_DQhvo&E~%m@jRD!Vjzl10zQKSi<4>^--VVz@4dZBX^ -zrsOj%W7sM5QLZsep{|S4`XaH|7-Ar{PC}Det)nrmyRu4aWQrfuYs@JYooR<@hxj9R -zoZ8(ezaDMX`gibL1bwq+lY_%C1d;HX8_J!UR=zmVanjb -zt;h)l{6$Z@RyrGDV3B}3aqP_C-IA#Fgm7&3$7_N*(GpXpkOn{kRY^>RK{X+k5ExzE -z(+-di7~N`~PXf@(qP7jOA&nnW%3$Tp2q!tiWAYH@(tmd(mISZ_O%fqONz%<|E_Dz( -zNex%o0fUrWqP9IQoq6&BUvxbc7AcIq`;<^zW*B=u@e%5#b5lN|rzcyhCC(rXwK1n~ -zq2N4v?L^$-?oS9fom_V0U>ok=Gy*`$I;2@}qJ$c7qA_YXnBI8^G$ylcJB=I$wS5}> -zkB}NzAsEh_3{u*)D>-0eIj1U#CH2BNHI -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 -z?clY2Q37h--jc*6vjg2rHDm3>%VK4F4hD -z4bm{Lh$Gr#gV<5vC~gdsk9uGRWp{Cz2qrUef}g6TS_%#p7DJ<^|Bi)?9U&iHFz@Zd -zMSH`ZA?U2RrXEH2Y|Ro_&E-_9dV&iMm(?e~o- -zX|_<=or9Qusv@)=LerWu_2z`mZ5&2S%~(|aAIC)8H^Ls_P$Y4m)}ym*LY-1<<+_fA -zL#2Gj3se2tnKUoKLUmmlI4yT04U-!zOIBWRV+&06ujwL-EoCx3zXq_BzW^5|9jKq| -z2(5D2=o8Uz9%F -zXrjxt&{8LZ2w6nq1W2;PO~w>N&T&DvS+@l19=O`yWdP~nK@x#jxT!b1D -zp+efx)Jl3o{woD@v9Gkx=qy)@(DUnUD-r-6S$Wy|o(2R)3s74M6k4B~|I|%yZ0=() -z5l$p#L)i_mu77V=M>U+ud(yuX=S&mlN%u6jQZudlDNvGre<eQc?x`X;Sv`?qf!3#&0;#s`r!4X!Qy&&x}~1 -zjcfuT4G94uzIGkMfQgpy83_ -zRER)30gN!(s?*0Z(B}G#6~~){4a!{j#k{FGo=VZ8W@}cS(c8bNHcxr6)$?{B^H*VE -zZ#^8UTscX#^A7RHa(Wx(rCCbW_n5B{2chC^bj!hS;g3q -z6x_@W_bomhtt-dCGz%J^kbxNdehFhPG6&>*N!>pK`1rJIpvaPZ(MxS)Qxlt{3}tiQ -zU4sxtn(n!_zm06-cEX~-#@GJdv>gRTj&o_gfRjsn=HAc7R-bO5>bGE#iL%jP_=p>- -zF^E;Np-;&`8L&rPVR}nD%mk*OUZzt8R{MiRtXbG-jBr>!>w}W{>#)ql#i4k6$!7F% -zMqEmvQ1#?r_mX6DzOAXsHI``^3Ds_tIPs4~Z)fTl-CcK5Q>XdPiAv3nWtSyAf#H>p -z?G-8C6RW0A2auRUi{$qBunSYpL@?J_r0h9}P&$v7`9W(RDC~jHecBkZe&SWb)s5v& -z$W5E_6Hd{F?iNH8GaeC+Z!6`Dbcj}mX?6O8zq2j9HHZ-DZdtiZY=L7zs7tmey6qzY -zAyLBDPhhDc=?8ROJ^B-COVU>&-VYhTiPCB(+8_8{pKFtznG9tCl9c!;`} -zuMP-{;#47~Gxhr1YqL7^ihj+GM -zu9NbjOZ;at>TT=kS^S3;Xdk8d>Oxva=|dWi;2vLqGM0Ls-!SVi8_QMwkO`mJ3)1?k>>8x@+=IVBdwu7#ESO9 -z1D|6-@{~+Yf^5EO^h=B^REV83grt;`u4hFLPfGX=Ei!`s-dk4kL%$B0vDM`8$7W%M -z108yv%0H}1!1xS_@LnzDmOpl_xF?iejOm+*j4i=MtLfgK(vQ;AoZ6SusH6TUeo;0Q -zk*Ft}b6y<=F-Z8t#v^{lt!ZZA{B=nX+MiyPvvu6-&#{6bE=nNXgfy!kFHf2DEWI_$ -zXUgvOWxQ>cx10~#FSC5lz!m4ekpQsDmz*Nd!WfW`@ -z7h8~8a{B9&tSB>Vc6jG+eBKMJbsvCZv{!U0fxjf*lzhr3YA$1mxg{{82g?j#u -zXI79;ct`JL#OC-8Dq4kWj_L?gY}?j8VBCgXGMGE?jGwj98R#`nhG-NBq!5uo{g&W2 -zvS~Z@2#|-aLE9X8gRCW9-O(8$MWj;2xirL?`*VUde8!NFxLJb$HZj$L(L{GFp2)Xs -zy_CEj7Vff50E>#9ob -z*Foi+g3Q7$wH#Af&KC61-CL{P?`ExV=|o={Ls_ChdTD&(v_`N!vyrRcdLeaV*f@Dy -z=*%ld&Y8nn==b!IgrxW1`oVS>SfeGhT6&Gy*%@KiIAR-`P-@%)oUL^0H`W1pUG6#m -zVku<>iF(%O73%g!H4dp>Il+5e1v`|lh_~jt!n0LVpOH>eo`w)Ys6TWzg(C`_g+TF- -zt+H>jPe7-HUBHOFM&f4A@N4VI8VnGSOiE<@v1wuMj?dc#Cy~N1SuOU&*#&IlK(wTg -z5A}^3xETH7E~H-uc+{UMF8vIzts_(EgQIHmO#iW2pOspx$dgvB`G=CVM -zJC#psB($TwB4vpkAb+xorhmaY^$6+e@KQj$UonC>%C(gr@g3iu`^6BPskq_f)j^F0 -zTZ4tFcRt>OwrSM2&Y4r}-n-nd*2C}zy1>@?*V;6FHSdY|Sex{S@@X-e)C -zl>dQIii@}wqEk%Z;pk1~t}FTY(AVw@NoV@f4((sN%Y{MFW`78c#WMyv$)HLZgh?!3 -z26+fmeR6TsO{ih*fV9Fy%!|FEvk!ygto<u&K-u&#+CB1R>!ZozRvb_pD}XVhs`l;{g0qC@(k``;f%2aA5z7kDIs;^q+K -zEbh58we=UioiUFvkMi -zME#Jy;;M-@PX*C7SB@k0DAm9O8a(av&ca_FHC8NxM^y&-ZV_xF=L|k9n)acWKo?^Z!;T -zj|^Ua8I;i?LXJziMal8Z&&|Q`bNX`MFM59H*ALF=o7>XfYaB_n>x0B>dPR7%gq=+Y -zVA(;9CQ`8!Ec{!j{j*Sprf`c9CX!SA+<*-pHpXI%>3<_AiF9ZeJEINo_Nc(z-o1tKcQCoYvs3z-@*LNW30fO*%fIc!0Pp+pd8 -zXO6!8yM#=zz06nfg~W1`{y~>bw_1uaZ?zI&8iJLAUcl0>NU;~mZq3{Q -ziu3|Mh$lz~ckZr(GR4`dN#`u~No!5o -zMv6Q*2~Fxb8YWw#)L0Q7Uwqa_uThhk+AEl9zo8l -zude4pYxH$C^(yXA^gB0+JakE|Zez^fx4_a0mZ&t>Lm>+2Uq(=jNT_~eltq4x>?7vk -z?QoK0wKsV~K3~u>?95f1%y#1iTm=l^e$am2DJ!;l{>qnP&=^;e2|~lK7{ltWE<6IG -z6B0$TG?U-IY(Xbz!F>W?A)D~nm@WShanzNd+g_Lvh2GB`0QOk_g;A`GRy>6CiC2E9 -zCz^;y;tf-aVmc=aBSlOi${ufDk`6*J~iAqj@`>FuW -z>5*z0DNKPMrExSG(O{*>1Ik&13E{PK0OIhor;Yk}7A*%Xx79LJ%AwtPCx^xMrzC$1(YqK_AGExlMOm<&|6o)J?*$kT`xbwm{+~8WF92FS+1_k1TSa67_A9a4fL`df$0R46+=&eMPf#*2)O~s@CIIs^=uFM0cr9onx#Gzh -zE%VSnF-pQ<3=}oJ?y}5X{CxI%V^@rlV8SF;>@c%()Sp}culfIbi_-spWKnKE1ba+F -z%%?mua|5L;yhv4`lPBh{AR~@D?LN^jG_bBqPy9HE>*_6v|3IkP#&Gd;mY!+|lita#X2s#sijz1a -zzgDiud^)D>arq5O0`;No2;X4dBR`I>mj~93vQ#9M%P~uGGev-#pk>lp@KY4&UmB%S -zoAr^w@If${#mLUxXNr*`NGf#?G(+tk4%*Xcgp -zDf=y#Gnel~T<9Ukk}~%~_pn@;NJyuD!R_bESxPjSZ6`uKh%ZHOSA$oeW0-lQ@a9&> -zfcxpt?>MQCSEWP1Jw0He%_lPsWEm -zL4gb_|acNK=CuKtT5bY^U2v1qjk41>!G -z4$^#ZUaWnNDy$QTX{ -z;(#)RE&nHnqQ9|zgNrPJ#Pg){A&DwAx*OA;yZ+;dP!~!R`e?{j8@=!73eKnmYi?#kjQf|)&@8UMI)^QbhKl&f;Qf;vu -z5j~ElQE*nRpF>Kz!*M7Y9DbTNgYfu_ps0fMfs&(Ndsb_hz>h8^sul`SHmJ_KmwjP$C7m -z3ZAd9)3oq=XRxrBZ3N2+c1V9nh -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 -zh4fqqB4J9JvUM01`%O8(9^VK@`?G|5qs -zx-)EkxEseW(>A-|(J;>4pmak~^0JqSQ#mg*=InRx)CkL4iK8lsld)i-dR?b9dqaa? -zhlhB)kP0FzN8T4w(f9|cfV>Li<16xKv&0E544V4PTxbo2PVl)>qEklo)EWr^meTCb -z$I?GZ{_>29Tji(8NrC6a%$K=TzzJ;ml1SpmZ-93tg3}kSh1er++$+`%Is67b@5YV2 -zwO^fk9dc5-)o#lYTxFftLolP?cFhWY>EF3gt9rRZM+E -z@2~SHs_i-V{M9P3a1UGD<0!j*V3DtK>$bmkD%Cm@>mG|FE?zRQnMI!u=@oC~VEvjD1(X#vQm`X{MKNst8# -z{U#NF$bXUwh1Ni#&Hsf|tbThT6(7Td^;hSTzWn1lueZ>22&NdHAD_EY~sDj2+8 -zNX6R(SHh%)`QXIXf02sT&_789gzGO-v7`S#kcv6zThcnmpWi`m6ocR5q`xcSe^loy -zQVY-i(1hGhp^2J7-Y|L=$JBzzrkJ^SgS{&wB*WuNZ$gG^4WG -zoLJh()_reMDabqiSGfcbJwZW22;aH#u;Ux4#}7it9HZ4t#7C8rslR7RPr)RuQ(AVX -zFxVGp$-yOlw**g2$Gjy5NTO7F=6X`#@eg*U+osfH@52(#Iyi$R9-~2LV*M{sLGSom -zRCFRhefUdM6p9X@fTH@;Ni^0N+>a8BL&2r3ZY?X;lt3NDt1m#1lbyCW=wou) -z$P4tKS4#m6B16$1!|;Yy0~hPCDaqK{qcf82C+Eg=TxbnwtNq86QngTFMhJ8?*-F2~ -z3#BG&sW8=-$#1>f70E=R(|Y4!h4`(c%5~Z<-8P0asUd_sJ=wgE8B+=#)eZh8vG9qf -z4aK-cAxB~=?B-1Due+l|z@NdXxN?>Pm*lDvfMr4kZ0m^Fep9Yt<$rbSt1ifFUUqkfJ>6?P{t -z$p;-LFWNeI;|l4c5;azU7ZcbC+<2R_7NkfL`7Dq^7`Fo8- -z$tB;j0%MpT$tLRbzgr|>>LVUKcI1}tc7Q}2X}1PC4U*v%`b>m7>|)c7@A*e~j%F16 -z6Dxs;QJ!%$XvRHwt?FKdqW)A(LT8>a;;Wz@H9>P<12XKYlls~yq)bu1W0KXE1PRu_ -zvLcQX?5cH+XA(aq2cq_D0)I-cr0{?#=s7iZwezk-h5Ilcl#@ -z*5elo)YE-M{c -zxM7J!Fc~28th=sEJ1sylMcY>WY%au&88{>NM6%D7t(|W=e@Tr*7lT-g0Ym&Kc(Yt? -z6h*dY6rMv2RldGuuDJkKj4ZcRB4icBfxF9xi)gpcfxfWf-$+@pPs<&vJg7Q$0o(@G -z+F^(BpL5|PD_lR6(x&8&%Z0`~y{_ -z1pO0LyjS~AR1tjf8&z07|3(#bt$(44ew`u~Nov`Dpo%_$=wrrzM-^OL{{yOMp!^%E -z$g6%q6(Y6&L=~2x>;FO(`IT-zEBvxfOXf%4^$5o4l`e+0(GNpZMe;NG5b4c~-%R-C -zCdpx8O?6jbBIi#!jj|&5Z8Op8ahw$=r;>zHQMJ;i*zzWiPo^NN7Y0EGiOBJ(4K;)) -zT6Va&@r|}1zM5N5n{<)Ekwl~FIp+3Ax&bXqVvI;Ust>Gl!FmdjA9rg$+(N^^Mg@Al -ztJ(@bvDWpUsrHezDx-48h`zqml28+U>+__#?u@+HA4V!&$W2r6#kTNO!Ouo3 -z)+R*=-wS0UbU5Va{qduqaddMD@2u{^^%u%47p?Wow@j9G#UgpYj`EbA@y3U1;{wnH -z1R+03;?*{ej>dN`1yrN~5Ex!F!;5B^5GG0H!6jICK#M+WUM=w8NA&dSiUsMHltfB! -zxc$Mo$HKicGB%iNZBgkf>lg+_TOi`yv&j6ZUy4sb0hWhLXdq$;DS*KOr9$Zr?l5TJ -zo$Q}6kt8P8xMb_jz)5tc4w59!4vNB1_2_b95E<#7>61ZF0p@F;%b@;O!w -zmzGG|=NxD<#pnCWl;nf`RbkgE6$|$(?VgtKq~jIXx>eU!nlgZ~E(EU*O_Q@a>$H@y -z^;1Gt+1wZv_ND>~8QYueKTU;(6u|MtRET4XznBX4_y05%$(%lu|1=eTwE#9{W8%<2 -zK#D$a;duaGrxc|@Nzu`%BGLLKAJXpp_k4){ce>8pqx|B(b4V=clb?-SX5OBtoJb>v`^o8Z< -zHC9H?VemIXwqij)ki;U9ZSXvPWJ`e`_NBVqn23}gQqdg6k=ws_Lw4*$vru~k(e_^AV}@l -zwlyKCxhsJY;3G5X7r#LfSh4%{zQ|IKg0$2_M-2$}5BuZ^xP{Z6zO+gV)A~j$FrM8YRR)TS~J1kxk -zC7VGA=`|5Rn}M(m%W@7Gf29)o_>>?`&cJDPXXC|DJGSr(d=@E%4P2nw!D!Zq6@jEi -z9w})rLw2+&kKrS631#Qt+r!0A~Ok~@CDTN@j -z_$fU_J9I?a_fB -z7A)6x=dnjQ0mu$g)G~CdCqXw9A}xhqT#2g!19kLRa7tDA -zKgS&PkB5Pf2qK#+@Qm}6pt5Okad8F2YWX#}Z5+MLgO;%`K{Fhbj0vWVwQoE>Y#S$R -zl3`qwZ>$_D!SzZ=gE{y7j3%aINS6Nx34PUS%v(;OmaaR|9_l(A&Rj@y64$SqaUDIA -z)P}s5L!i(rDp;1TgDRgK?_v?A3qq?Muka#Pz|>RD9V#Cn?TzAp6hgv3k?$hGp5V-0 -z%Ikfm8pfPml@;y##-hjnIbt}pq`YE;d_9u$)t&wjx6{E%?kD>o(bXva&3V$x-r*Ya -z@-j?8+X<@ID)U^(bO>0N{U2ks-Y%J>Y`~=24|5ZhhWKh8%?qQ77~7+}U|zCHvs~JK -zEjr4S<%}wZIj_Wang9_N(4$1w%Yz=veo!=?G@^2XyY16vE@xBAq{9Gbr&!V*8a$?q%kp|Vq#gDb -z+UL~q{?n*1lD?}j&fx0gr{8UmcIC3AScfwJr`O7BTfG4w=}J7`jVKq_V=B4iu{*R5 -zp%ey@N&%h??%Q!dTyc_ZMBW#+T-81tPG9vaMa6#VwDS5DRC*ei(iz)ecf(~Un9mbE -zEt5p<1L}74OMYxtO41=*=O1Uy*_r-sLmlL -zEN-SR_9X0HD|ZM9QN$>3SRhl(IBnmu`0!)TG*r(a;JX=+a$_M -zdln^B5e7GBD-1;J#dpGK#{AsNfTw5NC;rbS$e#7^Kbs&~3NTxB0CF>hLRK#`SDAUu -z7Tk#n{Ps%*EpS(TBSpGJc_w^t#A~Z2(f5!7xW+Qw5XqniqM-DO=+AV6p-uFl$%L02 -zh#w@O!+W0} -zAJQEn8}@D`B -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 -zee{I%@S?X1T=_whri>2Va -zAt(zUZ(^+ISExLLgt9{|U~GLQ+C4>X2VpF?NK<;a5=E~`vDV`T#~!AS;-l7Uf3CUzRr_mm -zP`km=*PM!8dmhY<;XKAhJ8dD9@zIicthWJ|O4-&N<`K;MgxtJKf9K5)0r}w%gmRv- -z+KR7Vg)NAUH&&{Kwa!FnJ+E5B?n}ZZAKJ8dE^5RX+nIC9M(kPeD>TVHD}i|JiN3d- -zK&i6D(9eHab^X(d^^gOHYtVP-BSNOcmtB3rLhE4iFE(zH9?GuIMA|pz&8bc9UGLto -zZlxfW`e)pJ62;D{Nel@2z_L}N3{ERH*0c3G=}*iyctgR;Tx3`9>vcXe4%X&xZHIIM -zc3R^2bFaO*iY4K;yH%7U*~Btzi1#$;zjqBYG~6p|7!30v$s5T%-!g=xr_j*trakj$ -zUEYB=D>UW77nnGA0OKah4_uZlL&~3WxI`ifedV_I+&^scpXs-Cdq^_Q8kS`_%cZ!B -z`-`nlFk*4}KeO>qa`IkZGit~#avbh{($&Yv^kbK+E7yVp^dUTe#DTm10*38g7cSPtawVB@0ojpSalbZ9vFQwPP}GmCMpk}dta(18Vqb-3R{IOpyOJN^RuCIy| -zH;7|U+@CpkOJ2<*%jF&O8wpan0sj9Arh@Iwi^s*H|62kda!T2S2I)cr8P=CEL2E#* -z2f`7ZL0v24AI8_F71DKSGdx)l!@D)4Yz3To-5zUuF*QRQgR`#pILWE~ybi&qp1-g) -zX$7AFo^CwyX_5S{WrZRwKZMpZ0ts`bULsmq1I(Uk2sy600c8S>vm6 -zqtvnU6+?whBJ}i9TQsuSSx|-VP|wtO<}?Qyk)SR1FRP9(-$il0U@P2DOymeWJk9!TMfSW&}TL~alWC#-b7ls5~vfo2{c-Wtum9W~6#bTv=8!N`QLip$l`LmcH8TKbt9(6cCjZ|ARU9n+8>pf? -z_Wuu1McZu5i&FakB~Zncq~?|CyJz*onPCZe=sODf^id_IAAG3=QsXhOff3I@^f?~E -zfh<_nTYlK91;1B}g7S;TkqR%bgUL7b^`l0!%H?E{{l(OYMxq_wWZqGBvyM^tz29Wq -zJ@Djd)dK&Qr9Boqw5_Lx9%*-;IS`%pcu?u=TkGH{D6gxd6(trkljjy@YxEJ`2{jcI4KIPUgB1b>}L78+*^cd*IV!70sX#;hEI|U++gvN===`TiNf?o|H0r*V|9TyM52uO -zq$pRtcu6agv^c&KrRM%trc -zK!in;s+|zh~1&z(?FCuCqKi -zYh^;l?EiR0PZAMMT^e0il6md|KI|0KW5-~eK;J4mq}QZ*d~x2Ez?Ma)OY$z34reCP -z=EsfuIL2i`dFY@PW6{lcj4Kt*b6IHBLfI4|JcV_o7H;kJHl55I;7YACP4kNbLk`HH -ze~K(=_*B}`@)5J*T{BfrjoMpf(Ma7s3bdUU@2Snmzi}~f{(QvnFY``F43s?oWT7sm -zT3tsJL}%LI^3~_tO{TBu%H6lf3nSLA0w!M!)iYwVE)SY;`W2sez3fACz9TNUw2U*^ -z>a32IcFG{AdmdCr97}CI5v6V-yp!#H`Rvz6rly1ezjHQ5&7MWfk!4*q3mv}Rryq$@ -zOX4{IWc~`_>o3;c{7_Md`0lF59n4di;Xr^kN$Z4Tm2nHwUsE!rE~xin?(?9m{_NFI -zmEy!0pWeoX^_DrfSJch$&-_bYBZ*+ElWeT0e1R3+@vLlr#_HprSLz*{X;0J``+U@D -z9-quH4T~>%B1red1>02koyO(TdyG|5@|~<^d|Ntw4)dhf -z{4CW3ZVl8MzZY*6gtB))`V&D--&SEFOFP=i*XY*7OT0&GlD`duJ_E=4b?u -zR2gaK12uwKk4lJfWF?+o-n!S2B8~~qMO>c?6+0|t3jGIg#pU<^BjAb;{s;dFT=Dhd -z-+?QJ{{gNr*IKdPb$zC__?9*)G-AV49~*s}D0@9XHKAu}8t;QkfI~%%#{A+^&0XilQll=vA|XGFu(1Wh6diDyrke^^4CC -zJtH+FWZK~p?z-zREa8sZ6^xx+r4rokA}{R-#n>R1TGW~E5Q_%WHz{B-*_XNp`p73o(TM -zm#`Kd|HN9bwEsU~Er30S<^*zh4*JL0fn)zqxW?vj{DKV`;nnCQ@C -zABYDC{GKJ>sNn4Z+JvDL$~lqObCk(#7IWCBQ$6d4x~UtRqO)1`jf(u9mVfMk3gPVu -zLnihr`A1I_g41&H!uGq3jf`_^GnNkXBQL{=yewiDB%__d?FYkKx=lFumy -z<4^}oQb^m+N04I24OnT?O|#C84Z-Q`yVVM*KPYsmKm5#|sF?HRlGp3)xA^TIm9ym^ -zxilukf7d!!gN_Nzx2p%K{{9J}6&-ws!cOkshpAKu?`FDVjpMMFO#Yit$izKUuQe(a -z;?8Yq-%9j*ZFoj(jq)_|L>z&a+56+((kZyNbGv6rof+I=Xb}2iH=Bv7Y#sTsAg*4+ -zN@5bEc#F8d1~sy=rgrN{aHwy`FZ1MyV@fHrT7D!TcQ5kcDEBz9^~L4Wt3cDmAYqTb -zsZ{vzba_OWe7p_(q?}Vbw?`FOslR -zE#C;IKS6>?%!uDEH{~&NPknKBQwf8a3O=IA -zq-i&~^+8#5w=-ma3be-6@UOIRB)RuCMe9xBi;7)(K8oUnV -z?i8nVprc5&@`38|AF*JCO*}7M7>m57S-Gejr7f+$*qH!X8)Bmfgr=q8k{ee#CPJM~DvoAZD_xYR2!uJWt$JIxx -zRPv!@muAI$egle>H!oE`yb$kc|LnqTa=BVHA85JYo{dsG=p_M^5Wla@^zdJ~i0&?ky55KNCC1?p*2cX(<&Nl^g8l^gwY|QOL -z&L^TYr9GLNVwd8NffNhqaCoXWS$Gcc73OT3V6okDw`! -zjWdp0!i&7E>l+M22?SMwB_|h_x_iPEdp+OLh?0r&*FnF7KtC6;V!}h!yLSHiAWzRW -z0%53|z1~rJb#LTN=Y3||NpEEP{lopG9eyO+i`v5|OJ`t@%p09tGf&z0{kx;08oDwP -zR@oH53W4MC9jMbfTSdun{fwf;`a4~U)_W>La~dvux;}!#MYrfNN%cP#y+}CYr -z)izFNTOsQ&Nvpk4w%olLPag21!$()*o#)Wh_HGLL+6G(7{pwUSSpo)MK~KMuzva|> -z9CYp5Jz#d+({pDyg^}M -z7bO0CzCksz>x#;~o6YiljWq|un3n8{9xp=rW6~!Rc<5_~w8LT>n*=Pm5c=|(WqF@m -zbL5xBwfrj-41OejyF;T9z(B}XIPQv6`K`dIr2@yqtHwCw0;RLakS9rX_=UCg_1`vw -zOLI~9%eUKsn~gEBXt9i9W8gH=$JYbb8DgR3$a5=0N%_PLf2F;C{FGMH1~a=62V^x1 -zV^KWF=NQxcEvOOtN -z*nepbgM&*%CoTwe<{!qrCG0S?d6y5R0QiZCSDmvW4`<2Bqp9%Uh)UvqyZIcZS6loV8*%WG -z@*wTg2=DJ^WA+F1*GWK|#fBh7Nnq=|Vkn?{q8NO$Jm+&`@OL&!fB=1jAIVZO;>-&pa#^{jcbG}3Mi0605_z*bZB8s@;7Ub|JVN~o!Hv5Ad -z>K=%pyWob4ez|lbxq&OAD{S#F$h|?(ARhgus>vxQ1)dyg7%Ombp?id3xNZ#J$Ky1n -zr>`?cM~k>@VuSM^8@aU%NPLM|_r{;(G}nH@djE)G6M87hBd|h~p{^W~>a=I1e1Fwk -z;o2|DWj_pi%woG~9+ppF*D5H`v@t5ej_^YIO#vlFf-=^xD#Df1$hp|}Vb6@) -z0^ibTxki2x+ti=#;NjYKsV`xu&ur+RU<;))++MS?dG@oJDHlkOV;lYo55e3xAUd%nBIt4;_inq7{)V!5hW=3)~WjT9EQsh -z^py~tc?J+Yn(lTiRg -z$(j3HHcqD+U*p|T@F}SUy_4{btQ6{^Uxx?<^04vBYv#6kAAvy8*y9-&dT~(O82Dhjh;`~nMCof -zs-h&Ws>KQZr@ptQzyX)TlqdeD$~-qfYZ -z{FxV5{%%(?GDz5>JDZR`;8n!Oy`^#i|0?n~pFJy;czH$ipdW7kB0Qdz(@~C;6-i{_ -zVS#uIe#>CHzc#4+U~e}SY)M(gwYvW?MRc|B+a(2?=mW;|E?bx&t9Ywdu`<46kV9In -zvq4UozSX5^Q0JPr@l7pocvuMZ(@N{Ob3Ab$N@Ky_dKBB9D6LCCyj6O8S%GXo#rxb` -zw7?$cbEq{MRCHr)00^-M5_G6t&pPFgR>nVZOron%d>1sYVJ5psLpq`A(0!izz_%z#dyYyAl1V^_i#C^94_&)k^5nCuTp~MTxZ1aU -z**($1qU>v|{O)cA_fu{ruTF-8gJo-SuspV#68QB~zl7}LRq`bE@q-+8{}6C(Rq~NO -z*v<3C47LNHWgRd?-5-b|2kOX^$P|Kb3&QoMb;+wKMRcOv_MateYLot$(~F1PoVL|@ -z+^!)CVc-v9h^u>=-|@@to-YillaPU(0$0Z;D{X|?>G<{QeOpqp+}>E3uU>711R}>! -z4iBA??WnHxg@?eZ>vs2nOk_fmdgnb@8Y1Hctsz-NR0%w+b+%J1h(E9frnTnBW+n{K -z{0#?XcFKfeN$ghRy|MlFMB=2 -z6aFK|mPTIM%p@;;u&j+zO%;)`^QI@BQ%x?3wr*tkoRSrID~KoaYm*>j0a=a}6I4F* -zWZAy~9dmqwWBcU1*xQ1Gk0yuKGq4ophGCt22C2XZJAV60xDZ -zp}m3a8WNvI%;#Y_@&qzD2+7`Z;I~Ni@G@I)%SUXWcFR^RP;2dTXX276SPM6(Pf_sz -zqgc!O220ldRPPB8!Gfb7xS -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 -z_w~yl>R -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 -z%k2;^a(9$R8^T8`7HkOHmaYE}m1%oe! -ztiAl&A0#Q_zni&~57PQuY6aW4rNca{;%*QRv3V%=BbW;h+<<+Sfkjd*g@r_;WfXW&>KW -zsu-?3tCvmhHuHbK-Hi8T+Kg|e+l<$z-Hgx4cB?onnYhl^+a7t$dUp|s-g3cfP5u!co{hL+TNr}mayJdT7IM)MN&OIM#vuSQEW)1IaIYC|(72$8p;a?4! -zEg$?P`@sX3gRA0qO_XdntsFWe@%fqH5qHC(!`bnzwpXb&(6-7ckXHs&r?uCkuA*fL -z%*?!g=)!*C2&TD|rc8Ri!ed#JKbhjWpyFDq1bbP)v)KE)KMj(sh4bpF=X -z&rOAJmg$WDyk(gmj_Jr_VK9HEP#?_|635Gu^tl<4NFlbo9;%dXzu~-50N`CtgC7aN -zeBrG8Ff+IvFHE+itforWVv%n7)gG}diBI#;q<=cwR`D49nwnScJi6NEI}IVZPL|&l!4E(!bEAifAc$|T7x$8cWV23&F3#~ad`1wGXD~6 -z^J3tU>lBI@7OyPU+@o0HG6uk$^*g5bo-%Xx^Vc%d3&SdFvu*;wOr!w;`3+(`w%7Z{ -z`Z&h&nHl$cnum#?8{+aDf%*Q6{a^1jNEum^3(QQ`zta0<;<|DD>5qEvmxK$T{4K!K -zZ$zJYg7P*VM=jop-3iC$ZY}3_GNS9XF1Kr#t)BQ|J!o^Ub^U!ae3z7y;_bur6MDkH -zeKk%;i+KA(GEG7&6-@Q%`|p6r%$d!rb|Q+;6@GSk^vid=+j^JI)s*}TAtSsLzEO-` -zQXxwrE7Sf5=SyJ+?~%BZ_!J;vS8V_tn;qSkccA8a@)qM|SN6FiTys(ps`B|K!-4d; -z5)X&-|1tt2l02?~DR9UPcwAoN)MB%xHqEQW!5;RsR0Oj2g08YP_AU>Psb6>hl@^M% -zI$`?+aQUsb^u*w@e1W#$VvU3E5;g*J8?=cjN{7k97@&+JOj(f#V%QtlrG!jO>Tg05 -zNgveO&TENt18zyCJ5M}PFgNtx-w?E{v`pf+>mroY?~`g$duG6X@xCcos0zF3+CWYF -zLN5yvsS8X6fbU1ke8|IZ7E$`7^jX0OF`gvI1H7p@#NlSN;N$@329)iL8Ov}r^#;q# -zkUKvkWFudu$C>|wT#SRw2FO?hOj6N%ypE?)&L2x%%P(mKIE~T`)Db_^&P%-!mkU0F -z#IS9m=r4OwatouGEd^zbL%r*Mx9NE}4fds1uB+FMdjxOZS%t-_5bhrWZac_WZyhv2 -zvE|}dHOAXoknsADl}|Vg&J}y|6umnR)}69ldH3S{Bwr)eNcaT!t;Hw?2~woawCF@hzV$&@Q`AX4^$#(>mqBF3!5MJC^BJTo -zrPPpQ?cm+Rj#)^>i&GagB%Jlr`p*!386f9$0u#*ROUyS54}-vpgH!evJmWdI%~?y{ -z>g+*`mw_Y9tpD-0fQ4ueY!Aw2H$bTIr&TR}^Loe~bBaR--`#A_FIse9jxNPxs*5-& -zq$0U?{sdY#A88dFG+o#wwi^ -zxwI)->|YGAZlMO*#<1ShIg~GG)-Ub%Uw-*}ttA -zPwf7$OWFjKeDBrof&B@)O9nDTxaB2@w!=2m*bW2F$Gefu@{^@SI>p-ymxLc<+O($N -zfJC%gd7#Yr3!nHNKmKs<`q9A=CXTN@c+T;iJ -zd8Y*c*i_a#uvD7M3@;veIs4JD{z<&UKH6%Ny^YXo8&Y0X*>x^Pj6!euYc3o;wbrHD)K1M|+nSjv6mfY>3;}y)gIqm_M@r17y11>t -zIKw09WwGxC0Wpz})0wZ;`f1d`JjwM#_@UEhtN9A-5}tzNFZ>MG;U?*c%dNiK`5f%l -ztawSAvT}IQw^aoAA?`d~oo}mAeW!Gxk%~SYJsLgfmHP}%88sVZPqh+Kx#k4{>6{aN -zLUc7@hvN##(VWs+q{+a6<853vb1No7KxG+5?)lG>L}d*Eo_KBzW3Ko|dA6iJu;HIn -zr?y|C!-9)piNmhfF+f(qsTjt5{SRBhOoh6q2@L$n@JPFev!5E5@kFiFKee?^wR>>P -zw9$XI$8eb6!k68w<6AiwIKKaQTY_uad6J6)Uw==ekFiIA+ME#Nh!^E4eK|%x_gNB+ -zjl>0ZigfQR%S1tYD|cr1wr#9-(L3$fLQ6R{@MAmYZ`1y)kuXv5R%B7)dMmVfmIv_K -zNq#5U*t=6R*zHRp*iUHg4C^AE-Fx=VaKErZ^)w6S!WlUH40(0uf@1LLSy4*4HuBVUIn&>d#)O=vpcAm5_F7>L6o1AUq&^ovenIK{irdmNj=vf@s -zlGDT`Xx`GMk^rv%PPVJ{Wj&_pHv9%vcKSbDe@DC#q&;qJWB!}(_kTUp!7J!T>lIgo -z*>bEi0~hMf-tUKgQ8<@tlK<3X$+IcN{?dQtb34L|7lSzQzj1ZdVQu|hfBSC0hC5@} -z7&hG9h75;};ac3?9frHh&>};I4l54B2L(D{XesW+-3o8_`}2LCJh`8ob8=4X<~B)_ -zjB6eO9}#O>oDV^rJ9CoA3fvE_eA+d+=s?kHif`Nk%Xg`jjh>>O>S}w91kSKlSv}zoH&NymyB_cF -zTdZ(jQdM%JZm|HxY``YF!sIX9X9{0EbjaUu-KKSc9vZJ)NI<6!G~A6eM9iZ)A;xSS -zc*iTs9gf%CmD8gE@*o?u$e>1re)zCWg;Li{T*3-+q5q1kCmCIF@HP34nVb3CF66KJ -z1)N9wIZo0MO{t(L#Q5hduHL}{RE+LAdmRiLMa_(~z_nMrUBQ*}RWI|B;Ic5hm0Xx{ZC2Fz@p5{+(YM_-*S)E~#(TMS -zVQ<3Vdi&fNJ0(SuNbAR9# -zuW3p8RfECf)a7Zw*8<|C{Op1vLA71)tutD@e=Rezqk^1{{w4S_Ek{mi3oeMqt52;x -zfzF4{$A~rUAeflg^62l~S(r7#=l&I?^L7%RXV5(=O5gSsfsGR=bbIg0!1>tTAMt$9 -zhEs6G@BY1ma|SpkiehFpw3pYZ=W^B@*(~VOiQ6 -zHD1lbFo`Rx!eEkTm6h54Q#9w+k$3xgs6ArG~*f*9YNb;C3V+{s%tv8tzE30{1d(hm|eE -z1@w-vq)O?%N)4z3oJqW9EyEDBX1}SPSkQVr -za(2XY2nWo1OZq;&YU=<|9tWNI9j8&wxUQsmLotVgmaaD+kC>`DKmnciBON-@LDxzq -zJF`XrQt!I(^~VT-Xz7nfC>q{N9Ult -zcex!j)ZOcA`;V5@lfvGT5BwT~cFSFOG{@Ud5>q?NQHYM)$|Q{T`?U_J9u2?8asLLg -zTHZYFDA1=JWMubp3XT`7+5!MJiUF=0?Gvm}g7?|rAu;&viOxeU`bYTFg$`Pt!nGCmWMlBp`U^TW~};g0B52=+6EnUBdl8VSW2Sodo?` -zE%6p_7`C+T0ur!Nmvgh)*a2D&p239&lK^4CGu|}a>+`eo;Cs+xWwX~qCAVbI_;VIl -zw`)nHmT1#$CAV|8U9-y={GSc)79g#I?a$?Z7}v2!`gZC=PY39z$L{Z49exeJ*vVsg -zk6rLJaB%LfF4f?!PJaj3Z8sEImrAvyg9P8R)b65mwbpUf*mQ2d0ZBjx(Rd((Z6dJw -z%W$0tT6vv5`?Sts>a>nx4$z$E&mUAVcL(RgYsS;PgYA8<+c}Q6ySL!wM!wgt7CPjA -zFFS&k;Oy!LN7O}dc&AzLwHj&-0es&94MW1MdmoSL;VbMLhsU6d4&hy-{>qxuvUlsf -zD4sX!IE;?cqWvRJ19(@Ykl}SV)A6><4BQ;C5pe8xb9%JawPNGagLmK~$SSftzMbSv -zV|@u9Ywzx8xrAevcKbh{^>#kGbKvhIRJ_D9CA -z$C0dSPBTAHgSRGN|G-g8NV7L*UGL`ko8M;Q)r0N#|D36+ez1Cd -zL6Vs`4PkzV)Hu}O?|Q2u6}Vz%=-Sl=LD~#2PQ~t!60a>c>XR3&xb(wiSapwUH})Vb -zZj+)CEDH%^5v-UV!ghPJN$PoyQ$Efq;W#E7_0~yU(E72Rf7rm=O=yMD7XcG`=A72a -zFHgzS@@b-F77wG%F||b-KdKb<@Na0&W{`G>Gjw>es7Iy^Ug?m+B=wwn25Q?H(PbS| -z1-~VRb2+A5!(Mc(6hM$y9e4(ioQ+_C5g5>S>1f2&z3u&wRa&R`&v7q6&LPyc06YRa -zc51nzj!Jh(ZNUJ;&HO0g^`DMff*V%W-%#4rD=t$X2l;c{A9hVUCyits;^M+OdL35| -z!R7Og!HF;tvw82HPt+~m{jFVX!-q*UEm_-5Na5+L&-q}%YsPEqowL}^(+K-nt=bix -z+TlV&Kv0`;=+@n(7t*goBElOn*kjNW)IxoT^i#M-0GH}?hJw0SuKpqKm7o$L#Oo!K -zfT&Ass@Y?aYGJ5pmvH5!pf+Mz2RQrva$W}kB&Hcpy=#4(#7XR;Ev1_44>kncxOVyM -zUmnaNFc6oza|q|kxf0zvL50Rlo}5c-K?I)NY`)E`aVO)RM-h#X{Lf%2{FSD)@z7(_hZ)WkFDBtz_1uW&1wqGW^-`$?l$cdb`l>9Cu?_=YaKp8aIEVJTNqswQn!45XFNovQ4KEyp`JBe9R)ZIk;NxluW6;CTpo%Dd -zd@G7S`x~AggLEVQ&Ui1VH9ZDg{+)M2JxKEAGn?+jj0cIq95s@_K@zZFjpT~%6H7#M -zS;frG$k3ftKB62dIKjD~3vB0ps!l^*+@c4JiNvWDShE^J$=hZ@&c9ZiHtug(78_|D -zkhep(hk~;`KzZXg5EN_4xvl=uZ6jdxK4FJqrA}MXK-k$qD6reLXNINGoOfye+|NAl -zlEu^-3x0Q=a9=05TDM#%c{y|&44(%!N=c3l-CMno7$3U*rllU05K;w&;oMC+{h9OH -z2!P={90*L5!&*W8=z&ILZ1a^qkGG2pH7BJWTe*9qzU8bx^J-U3+Z#yRQ0{%46{`oG -zfu1t>KfI2Nj^&za_mxm%YF4*I|C+Z*{-)y3e`-B6>Dio8)Wq%JqfG -zEa>5g==a{) -zS>9icUhijY)aoR57(ef~vcwx7&9hHcZ*)_&iYUp=VC7>?E!L9)H2$|}74an}qfvm> -z+DiKfUcDsK5juN_831NInW{Z-Rz0)VxtgmzC^Gn()jvv&%lgwJZ-Uvl)aAryB1;Fq -zV9a{QN1u6Zi@AU}szYorEwnwW+~9XT+RQC*>Im|CC)^+crN(k?k%w-5bSf;?LUj3bX;Y2W)^*sIVYpnuQIN -zzeVzH>j!@pbo{I-Z~UJW=J|r2@m6AicGm3@8-VpsfLCS~gciWD5a5(qKI0@I3aP5z -zvYp9;PMoo%ui0Ma|BG6wYHjU{CUEh03i=ONUHmosV{PS|kRjGAc5!QK{K5;Q&vo~} -zS0}{_(wDwF-~&`K1P0~Iz0(5JaQp-Kkp=qB{{#wycgwX4B}B)oqH_T?ivM_D*UPnj -zpeWO$TA=)GThA)gE=~~(gl$GORPDSeb=JDvSKkqFKHZ7S9;DxlXq*?|_5Viv$6zGygyevOv4@{$EDc|0kv@f=b}N9|*MVsc<*V5{Lr) -zDgl5RQR8s;ueD5+lYIGSuIb#i -zbOx$&`quP604o@!iM4uti+;n_bN+ui{Piub2AK=AivxXQvz#|=Kf(Ty<0Wh2?@?OF -zLO|N{|2QQJ(@I_c3@HcdpI)O3O%Q>!af48tu-R$Mfq&^@xU*&0_-BathQy&0P{r8u -zFV&ON`;dR!T|fQ7TU5M6TR@f6KhEv1>B^~p8WTE0doOL#5dX5gb%zpB<0;UF{8O#W -z45)JYC#w}(KGX3pGtVBIFmF(0N2vkQCJIK0oTrp)jr`-doMK+xm6QDWhf!}^>Rp_M -zSPl3Ql?SFCKoz)$ZxCzr=z1EtjR%xC&6C??(bi%)wAi71KF2qHd8{&3(H`jBE;OU4 -zGu5(;_o$Akh2$%67QtfQ^oG2!l>+&Cz}PnHCCzEQ3Np}IpI@vU`~EfFiSW&rd8JVk -z&`l%5deip;lBQm2-2N)}W82BQ9~Kba>AnfERh@Exc~nSi0A!oXHVJlGtlBN1a2dr%q?`0+;snRi}S~p2xqac>7EJ89p9Xe=d#D*{;N} -z&JL%UTjz9I9#xJgD5#Fr=d8}`HoQ;rggUX!&XV2BEhaUfy-lz0u*5D+Y_?bt7Ldt^94nhelD-~9a{Wb{vnp4MjI)gPrn(ledUv3-}9 -zWV1l^U}hx$1%{-=zDw)*1|`kv>TkIyKH%zp!)Fki@AEl>P2|!=?x#=UL@O5}ClSn-muZ8h -zE}~#IdX)&Y^h|rLLn=U}Xy4HHZZA9;HT1O7N`9}eRgm%mR6?gBDTExznfiIlaR`ZJ -z^A>SxMg}%)i`Hzw0Ci!DVRhKsMhm^!WHt++u>x9Zheom=$; -z=^GbZ^dGNfZ2BfLqpevwX6b!tD=(Jt^#}nAdmo&_)d%~Y&BRJilI!1; -zrDCO+^DI%uX%x%d*n4V-^y1-CxH3QOw*0VOs4vbreUk@s(BJFHe0Q{BZn`Uc`GIfht{zh6LFn -zkml9YiFS2MNuQXonjr?)w9!^i-|%e)&Xz~q!z3Y-G&;qIr|zn~l{S^DvP>Q-4$%>< -zBBj93Q%IxvsLpTS<9XR;AB!O0bj|avO0L5+cWdk)H0Tnt6aGd_#t;tf&dE_?RW(FP -zKHGj|Qj|AtYP;Ki{BFRETJTA=#p==^0X20p;ppEHxdx{!?LR4oUPxLM|A)~$Z9(5A -zQQ_B`tfJLgRT6*bwRfDpWxP?~{b@4R=Vr8))>O(+3k}(rmSHb6_O7A=9CjTt|>?^{P{Jy)Sq24B0sk?&rxG>c=RGj@}_5g@k)(YpG -zv>6?Z2iG0YWJuigz~o}jDnFA@{jkFkGo00bNb)u+y${AQb+7xr0I5~)sQQ*@3YZpe -zEs7ZZ{z>S%g>jYbvJ0bA8qrmuhNKyai@C7QIsov;e5`R=I{EUq%q>YdfAq0hx!B;P -z1l=zd!1Ig;Jg#C{7&M{x{ZzXr -zcux=AB(m7DPk`|^i%)1=xWO6y!Myq%lFx0AK;N0~)Is@X=6z~-@5QRQAWqwo98 -zHSTEa1W>%+FDdmKa}POv!KzWGNmC^q*K{iBrL`FScbR>9PD6y&t!&mqMLe3&Y0pjv -z%Upq*BE{UDxZ_(PoIS4g)%6@^($l-EiGe1m8#D2|7ftbhh$xf~!*v7;A -zuh!QvG+m+J-EByP*g&}x*YD=dG5{9JoflujKgeo`fP>F_Sw4j`hzeh-i_OhYZR@*x -zUx)pSg}qaSI@qzn)o=`NT(!ev-sN+8 -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 -z%n6>|$r-QwMo{<$KKG5dT$p7}W!~Qaxt -zQ_Q{IG^ncNPq#b+XESAia~t6A^r}Nu+6C?3K%TWICS`%D6PHNtwUIF{qJlA%5fl(Z -zfp~vpTH`U>m(&vvt8K(e?o`5wg`5qC4-YReoQZdO-e!xJkfdM&n+TZ=Fkg(~EePam -zK8?@hZe+X8;&0x#&~dwZX3aSFXi%42vLthhU(1v%77nLv!d-KJl_K+oQW{P?5t+;% -zUP>F!hU)t8OwBOS`u$O7sM;)@2$Ww7cGj;^;W%6R;IY2kISc`Ag-B%uV^^1@U_`vB -zFe69IoGO -zvo4x=)ZH<+e>I@ExqL@WeSiTBdXF?@^(V*fV{s~zF`~yN!%$O`)3mKV#t5@vS)dG1 -zKOSG}m#SC*?An8jOWWhHvWZz1N-%dl@JX%d;xOBYK2>)}Q)k}4f9qN(I7ZTUY#bDO -z4o#5w>DKhWq83s7cmN4dMBFCswgqli*+M}yj_TK2Q|-k(@(XC -zkka>Uub=bff8Nj*?T2ettPi+!&7Vl~^AtsJ)X-}&O1akuIC3`3z`xK6D{>YnsSoDU -z4)7?iObpCvS9#o~*!Fn6^tV1Pta~R};UYm*QrQITta|9?LI+Si*Zt+O*X_Rjj9BTG -zD3ZQ?0c4NkH4S+BE#*Gy}T?D -z4i_7nQtgpAg$&u}yo2ac=Z@ly+qp()w0?L6%$F7XXqa_e7CiBGY=OW~>UNCyBB|s< -z=9k&Fhi=%?0!)yKO6)w@J!D?#J*UHAF7w0Vh>BDLz-lq&-gi4@6J-514e5IXMS-t; -z?6m(K&uD!CNqYIvSHaKJ@jt)=gz&I0gz_dICRxNccTPwDR>$ITo0@)pmDYLt^KZws -zu%mvNgNfSB&i5ecB`RSWf)nA90>V9RJqej;|EUfI2l-9Um_m-UKbFO99~pPTU9*WN -zqF0ia*a=#nE9Mf`TQ)R*tQh)koBd{d1WMSe_l}#c*ex=ijUbWs#~Z?^kGTImfAxVT -zS*-99JB3W$JF=SYB9Cs95)Jwejy+4(0)OO##XJxwRi*fZ^5mj}V -zo3RdO5^PIxQ~ymhk<-@gFwO0#lUlnn)9yFpPF3UAKCzXNuLl_=?^&03Sq66g%08Gx -z|KV}iY8>m_P_s@c -zx8GT-jNYnZJ>1ZK3!pqU&@K!?hz5+f`KRDrc;rDrY>~UYCAXM0X{5PpV%fAb2##&+tWVh=r)WPNPjTQVX0pnJD^*p(k -zd_Akx2R2ozd<~gq{;D2g*-oT~w$}2%=&*QFKzKWQ8*+()52-N>jEu?LZ#{3@#PoTX -z_WDVy!Pz-UfcS3&zG+x(Kmk=1WHKhO+6hD5U#qTSq=EJK-dAD`?YYTU2vqNuut%al -zeK_x$&EIIdXy?rqp`f9aZ(P73_PGeOsLa7;!rm{EXYH-EUjKhckgbaH-5yVygiIQg -zXxV*no}94#BNG(AA1$`!Ua6ioJ%oKJpki8gsf*hCk=zEk1%fS;b@+UJqJ -z&fl&heOIv03pbY~SaitYYIQRON9IPK+`pQ?bG1)PtU|8d_^<2 -zzPR<-7z463#bh&*WqlA>+6K=krJgtL30&<;=sE@gLWKG_08ufqO1wYA!)4Sl0DF -z*A{AL366jRn9r+bS-&ZgD;w`fd!}t@{Wzkify}un;YkYQ2aWHbnz?{EGWva&G`<@1 -z(O(3c56@bTvMmo`+?}fuJEycGK_utP=-Sj!rffU$50$nyL*xs-&tfUcItc{3L&Pqh -z`LCfH554hwX&|)6JKPpvrHs+odcVbPJQVP_#g_H)F3p{Cxb%0G)7vMp9%iYj96Qyb -zgz9)UGnp5$D#kbZbc(9UCA&|J=BlaQhy7}A7bFaY#PhM4X<`1m`dws3UL&owqq6D_ -zv{sN_ -zdaJ0F-M$CrU*F3G1i5nRtM95B{PMW5+}V_OHk!A%i74NS1p4)w-f;bVd^lk;uBQoF -z(?*^o)RYx7u>A6A=hv*vuQtn$W#qkA)8^`Rg85ja?U|9q^vROb>agWJ}3x>Vpz -zNqYw(d1-w(+s;MGvI}NnCMsn~ul^S4NM*t3u5XQ->*?{G0Ec~PfKS4i<6Q&lg2j;0L1e#C=}9Bz+HKg8w8 -zFw80pXzD1C?-Ca5^B7`OLw$Z4UEblchsr)T6^J~4j9;btxV#9t`VZkDQ(Re{$!UVn -zQmrDgWRHt>jT~8+ZRXEcxx%+ABmkcyR(#+MJ6ON5ao8-+KQ@K|n&^L_EY&}c`!I!> -z*)7*ZR%68zD|dw6Szf2jg(QZXs}GP-=RnNC0cPrzU2& -zM6un;Rzq53s?+sX6=yD1TicFC3X3uoZylYNDx3X17qaR;vU|agI{@kPAd2;~{p&kC -zBa5FU#nE18?+<)-m#|D95Uk(n)Vj);#?y=3-$Fz6d8dpRF-KLf^gi=j-3=5^aZO|0U|`wOsU(3d7U4v#8}^O -zCBeTw+JLu;AV{6s$qnt{Mxr@zk~D=e;-pu8QQDU`<+T>Y$mBA3uRHV;{2iSRcokd^;AIo_L) -zOctWC^x^$$m>@v&brxnc%iz_psNzeE;-RZC)>Hsj$dNB)W*jXHOz8Z35G>9iK2T$8 -zblY?J)ix4NT*#l?;gRM9jE!$*EC`jW!tSJ?p-_G4AR1pq=F@dcXmVMN8a&F|bxf8riVgl(lM7>Bb6Czy -z0&cpyeeShk8smPQ4=g`Ra6rUeFFot#m934v@HrS!SL|=AaJcB`&tf}CAJEe9BH-&) -z&f(r33E?OQx%DQRJTjb4gWay|5BQfam?~At_!qSTTH#^t;oe)L=7`p3*1S{uX2dVw -z)eEfTW!dmfhP@oKMS#8f4t}Y&Bo>6r5nAbfC7fY2HQQ3=$4Pmv=WvXR{@-%$#|Qr! -zo6Xq<_f$p?6)yL$tv~H$%dWmF5aUY;P*rK!=@W)h{RDD7yhLB!IzK$EVKd8HL$_E= -z$*ssvlgpMdJ%86JTtl&vs?r(b`sUE&C^SWWs>A_ -zbW1h5{43rkrbeu1Oi?_qy2#g;xAjfmz~0J^2DI$(n5>d7pnX;H-|ZYQj=Xz+q_&xCE;L1 -z?VNbZg0vTzZRNe%c0{=wg}=KQnc|f}BdNIfLbNNsk=%eO5sQr>mg|4tTzh*-b55fb -zR<{fIZ0$aT3=2$>X7-KqdxtA)<(|Hlk-AK`VI>Y -zPbTN3HTvatdzh8co-DeN56=Rj{N2vxUBh232C(W&dgWY>l?Olg%%uQYsO=WD0Nuw0 -zxrYd@eL~9X4G#4P3NuDmXRAg1Y8Cp19|HY)>8?CCv#6g(CJihmRZF<~UlRjI90jPD -z70nDxd5a@#|LAQf9;N3hefZGznG>|Z^f!&MnNh9YCBSbd$ -z{>!0Ez}FA9R~}Yi`kmPwQ`-vn@rLGJXYGi^74Y|Rheu@ijb=Jf1)#BI~f_bp;%SS|56O>)Jf=d9LDV;jzmo97b%tf -zelciEQ~LB+={m7(3gGSK!nci}&IU$)%y!e0<9{uwl_M8pol$t7rL{r}tgM$hF>GmBd0ss18s -z`ga|l7d5+YbSH()NI$Rp##kV~Ow`yPM8l?j_8lNIkDdtd`wyJ^(sqoJOy+oC0PR%h -zoL5XO|8){?Qg5Y!iOD_9n;UEGhx#8ugVa419>9ib==ct+z?qiJ&HSP`k1gkX4Ozmp -zHQOHz-t$m)Un?#NYZB`0py4a{@Scu!=36P` -zj%n^MHd8ZPC)0)M$#4@w<1%~D&X)%wTTCh_^f$^FTk4G*?Zk2oe*5vxlN-#HN!i;q -z>vO599su0wrhlh4S#abmgj+>|Vmz%K`p6e-Gvm35;vm9}qm_piR`19Sq!`N*W5mrJ -zn!f2XT5U%aC77BheACC0WBi)E+*7!O$A1%(BQZC~gn6w{B~dN{xY)=h?EJom`*)#j -zLgb4I)8Y;}iF>Vlfd=XD+cky5+IlUVr<72G@j{}8BmC+if#UZZ?Qv48Cp#o!%Y1?!?d@^I)5xJADm4f9MS -z<-J*tRS6t{38f`*xcyWb){>apz^+Ocg_XL^{XVp_GMpOK26cV!E3)^>@_HRMy;bKT -zUt~C!mCzj^Rp_N4th5=im3nVyyi(0|`Y=RVXSsI(r8?1$gK7L6DML0jyv!eJX|DQ}?j^A60@$2A9T -z_eKu4aaeCVoMUY;dc_ -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 -zqS|(?pS9&QT+!uii&LeM_xstiyFpuY-a0lvA -zZ@F)Gba6kTE^*w_y&B#0`gY?!`W3JP6pp>st)4D*<^MkboIqp0`wA9lb9GdE)pQ$( -zD;~P05JX8Y8XXs%jS@Rt_yU5xk_XC$$p~7j&(LMLpM>20}LaM_jWD -zx4vqoGs$)^zq%K@N?*l=-d$zM?bh%+*&2OO@vKUAEs4DMAGS8`QWCd^RqZ8LV>*(a -z)6EXnHUUI7o2GC(aC;j^8Ao?|+c5SV$~MQ51w>ee_7O-=;dTU^LkOILSr1D~05gG# -z@zoFScXWxvn;Kuo=*&k4yGC!{4#^)9sH-d0S7h%0Z-Qm56=w@?W?AYxWkj`A{f6{& -zjm}@+gwYQ-HCp*-d80L~a_Z;IheNiJNFp;=c4l*`Qq`*ozq~`kyUNIG>!7{H-&c3$ -z(zopT%=NoOWS6{_8Eot4OUH#nV0`T~9tb6u0sp0Y7sAE78U -z&HN5mtumKH?J8qB(ge5sOX?u1M75jKl~jw3v5_u3c>P~Gb%MZwGeyGG<+TCp{ -z4$t6>qkS%HW@*I>%UWZWuk{JKogb|+_{4EcDD7np`RjJwXB^A?11lR`7>uP_V_Tz3 -zdE2OOVZInny|TQ~Ff7b9ylC?RJuok_FWnbXr0{lZjfBrYT*8=Qr8(pOf`M&9;#Db} -zNWC>2ZNf{~052i!iGTydH`H0z^I^CZak07JR8}r9Z)2dmmn9o?wgzT`lz^i+*9(0huXHqu*4tektvRM{v`7ywDQR{1W#S2u|M)~GzZvk6>w^ -zfqi`}27>l#V2)~J>iFlz$QClXDd?C3xw_OwK -ztfT*IZs#btC%Q7kY&OTrTpYX?YhB{j#OUBej&-{2n|g-SGvR#`1~=wnV^+1qj~1BD -zgtJW8$CyWq8Nr;|Pe}TlZZ8q%Aq5_j*)c7h63h`*JVW{>^lePUrj%+(j>a@+LRc24 -z$Am;o>A)1(9Y#;kc8r^21RP@77?q~@GDV6R%B;jXkDgE_pC!5nx?|v6P -zK3w^CfAX6@$3H6B{MzchtbY1GWuqQ+_1#~gOxWP5N`LzP_DlNdCX2sM<;_h-U;oXY -zx2IbEz}iqZf<|y{&e%h -z&F#&f{N}sS*T19v({Fzud1T{{D%t)<4~R -zy8Zm)&7aoxzfXVt^OuhwexTR+zx4WFC<6+>N5c|sVBD-@m;3MVN=5K7ROcfBX5v -zyT>!%qL)>>8{?F^?>$Sb1ch@kiUpEoG%{KPcWvpG5g@E%PFxmF}^gqSbct)%%mZH9jll}?a -z$*IU+q-(bCUmb`@4&`vheoJ#c#vc)1cqk;M#xw-Ey -z%er_)+2H)<_<8xU__b8kb)n+x62%O!ch@Er*H52Bh_BbjjQ)Sb3yR)Fr6vYhUEP_> -zkGef-8_7&K#Zt$+F;G0=s%Pi&%RehVtj<4N_wXjl(}@lO$%4vofb*~KEpI{+BAf>^R3gb6mE>sQIG!yw -zSHMsb<05ln;p_U3UBj{1f30fi$#ZiRo1dTijZ}AWA?;F04!=&*@_Ibi>jTg~30%5H -zo0IL1SQ6M~`m0e7k|dT7_n$t8zUj-%Y5Ma2ede`=t@Sfac3Bhojq4!^j<1bONEp9v -zn@(P}>KgfK+e^rPX -zu=3i^hS$93|Bd;7k9BKz@r3nX@})$FPuS0y{m^ed?$@lWp_|Hps5d3^W#G5z@cGDWiJyYPjb -zY@?1ye5BH!Ux4J#qTwSkbXkJ^lYY#f{(t`T3VSWO-LI{nuT7r)r$79+Uq$*S^Y6S5 -z|Ds`kN>m})pQ56X$!!F44{5<0?_71Uh=_=^w2uo$lO9vVT9CdDjc;o-^Oen2mnTg2 -zU;pMm|EEt;ER5WGAytRJQ|Y^(e*2$v8S6i!zx{{Jh3sHaQS_Mzfy%K+_LqDlDTFcf -zo$&Vdm+abp3Ga~1Q$`mo5QNN^3-647TGFc~FRi?CyYd~zHhTwycgvVC@#itsddkb-Sx7HIR2;K5(U8d?1G+e*{=Wz%5HXsUmB+RoE6n@uybeAu%EXF#q-+{=Cxde;5mvf5yMjz~BA!TN}>(+kg18jcJ1{Wd+2| -zd0BX*X@@^u_$?qKmj4%j^T&$^-fk>E3|w0FrSIN8_vOF(@Bi%uuRi0m{$xPTE*-dW -zgoBYEFCO{nqNAmO&%PEc{8{JID>|DSx2h9sa?zIJHyQkleO-YglAet1g_pkj-@kkJ -zoNX>nwzYsn2ou5M{hj@1Du^fk7f|F1Ue@nuR9zsXKu-B6T}u2baq3^&UCa0Hv`)`b -zU4o9PSoLE^gFxo9l7gj^9{je$GnuI$vS-R~Pc$OaIA!YPWfv4=p$n+}|rcgjf2uxVpqC -z@>(Aw(WRD+t+V5liSWhO-`{Usuquahu-IhEp#gD_Fy?aT&W=6R;(Af7wT5;^7VD+& -z>v>%N{Pm}CvKqH7K_?TZG#84!MaFJ_G!(YSQbwVw-Me3=lhr!5rA*tS&mvqHknhhu -z+{=x(_wwfZ9~?9;4WNUUyGFz-Lpma?sQJo6{?@f@HTC^uvj%1^ai_vj^Xhs-&|tCW -z$NxIfT?QL)p}V!Tfp5!;MHHQScyO^wKby&Mo1>I9QSH5i7UKf=+)TerhVqXtZV9z_ -z-F5q4pcza~fUc?(sL~tRGExYk0SJ8U&>(KIQlk@vPVxu=3&C+=_Bkx2U9z{W&#rUr -z8`dujLxtF`YV$6(cWT?tPwy(%H6r{ZSDv^wNj@2nt6gs6*=$Pl@~B3W+T3O$aR)g& -z??UDK-QbL;NvVWIr3m`d{JIF0_bbyAVxgZhKLnC3f29@0Uc|aG|+%HhE8E -zt>s83bAHXJn58Ru@`-IU(d6ioD}Aebl$`DvD|wKWk6c_>$AQbGvEf-|O4^t}yTP9q -zXc0XCF`k5f`vc0SMXziSq1r37EwmSVJtJGTMs+T2yyEgsro*nf{qn$4>v%$^m^&>D -zS{Yz}NBY+JC6y9uStIE4%;!>F -z?b_oR==RcCIiReQ_ob_h1o`OQb*lgN%t}y&3MH`5t-}WSwurJlGXn6KqleX*=Xate -zn&NiC118%c9b4rhhb%JRYpw2U+i~^XFZOMe=bj7#rk|G2>SJ9J@w04s{xlPr=;{@& -zpmkviYwsz#cs@ZRMf%}pIKhnVLvd&u9N^*%YA=#poJZ$Z=+7ecV_&p;lFE8=Aa8ZiG4Uy3Yv_dv!D?z{TvAiwG#h -zp83Q5-XdLcb~D6Kbm4;Eum6I8p7`aju*R}XGNt^xvMbM%i#siq>ppjmTobS573JEr -z3xG%DZxP;i`nDzJ)~u3`ia4{anY4I0DVh~-Bz8uvaI09vr?ZFsG1ez@yHicE -zMdmUI>~UZ=n&_ -z=Lp0HX`_om$(HjJlDMw#Y|SiUPO>#xVH0>x*r`+n3j<5bJ|*&p<#S`Lsa)p4^rfz% -z6;D3IaX;K$VfLs-1=f3F0%pM8=9j6YXcJMTr$x9W@+#9*q6O(9Od3^LeT7t#difwr -zB89DX%IIu@AAZ=`K3CVLWk4a>oaBi!Z|i+2iegPlDCj1Xs1`R@Hm%^U;J-|f2>mi{ -zzMNZgt{PpUYU>#xS2QZcfy|x|%`XV7NM20OLBKNkNQhyPDluOw9bVK+o{J}l%B_o& -z-pQ&WOm03cuZ0EE47DB{BKK+r`-2zc39-gglN_MGxDo>G$g|4D0kPU;_No?N=G>&& -z*@y?m&Z8I!t>ZB_U)q~5=Xf|NBT2r5bq942N2wN$2hrGNbX!!jMt_n=XwaCL`%*~`;{JW1NZLG7I3VnJ>qgt&8p#DXA# -zl$MXlfR@hWVI;SiQWhdUGl$u)^PEha&Wl|rU&aDCO^tv57k&I6dUArcB@hr-eeISM -zKw@W!{Cs=+1J^2B22gHDof{?dmgEE09nXuWrt<8yN! -zTEG^Oe2?Ru`RW`Y;2fr -zkLZrEUs{$ON>MN0Soz`e?T0g%UK1kimf4^pT3?;G&fdaR(0hq!$Cc_VpZ|Kh%vB1p -zKhJa8W6U?Opt2AlkxkN_QJ@Hn&EkwlQIJp^oq+~|f5;SPz*G>gmV3QFBa&F-&EiK< -zMVb(@TNUZs>c^X#A4Znp$(0d%uFfdq$*Iki`0&Gr&kGa>1?`jN1D3=K#CbwwND*Vx -z+Sw~2v_6NJjaruZOe>lroBWc+eU^xyTzpf+jfi7)=F%ZT6SDhKS7&5D)|eIqQL)SS -z%bcxMCs8h=IiFmq?z2K1bhB{uu`nv}s{EYab%j17QrUyK6GK&bGWWfWO0sUWJ97;= -z0!`O9=T3roa9mJ|w&*wtc%3zA${E07+Jo2HRM3hKwct>(d@!kLaoedG8 -zpT9=G{RbEI(aQUlBSseIxJt{v(dMuI_=oh5`hIgnlgegsPzX=q!GB2q7padmN0M2( -z*JyJy@j}s0(?grhY~Nl8Ie+&b&BISO_c#A>5?Zu4LBrBHV*f0=`n?UKzrXqYC2!xB -zDYw+){9ln?zl(ed!p6(UjyB)LC+mCv&3Auo{c-r!!bEztv^5)tSk~9?{*V9sSAY56 -z{xbT%{_tP^`+xs$fA}ANIdPIB@9H4R`YM&|LGTpi5p@yLolC*zh$dnG1JgABi{3zH -z`ZyA6V>P^t$gb(1cP0PlfBu`l{J;PEfBUQd{1<;Y&3Ap>l?-x@#NqlR>g%1re+J&X -zSN#Z*OKQcD%WDR{L71JP?e-dQ;hTk0KL2&fY>wjdJH}Q==VND)aqh###R9%0( -z`f&aE=H}zo&Gqf=&6giP&3NG8v(~VJIg`}Y0Z#h_$9GH>mQd#00>>~ro7On4eTKYE -zsa1O7_bQfuz7)z<Ov$khu^gMR-X#FlD~{| -zCBNb4Sn+aa`0c)Q^?&eg{*eA3Dt_V|bN|BG*Y8bABf -zKed$ZSA=FBl=+h(_T$Y4gaWxGY!sVLOwz#g4bBQzZ6O!N{tD~aWC2%kn+3+Wc~Dnn -zMB*TL+fykMUN%I9jBeP7H(R%RDAUMR-J70-mwNa>a2QdWcV%4Bzh;AnY%8#1aFfZn -zFzByOzx{_lk3?KYxiJ61Qq5DbcfYw@7xN$f*01r;{%rHG{`4v>qQEnM{go(d6q&D` -zXtod9Wx|?5r843=8jkz^_8-2(w27zzh|$riIDhh+@7$Z;rLwgd)>|dgE+HUG6Wm-n -z!E?(^ZOuC^Bl%Y*Ff37>!L^z_n)57DOo|QAVZZ8GY -zaLM1(DLE$S_S2VzXO&MRSbUVZ&fkj@UOkXNx&XcA_EWUt?LCltB0*4?4=Z< -z)J-g^{nCw*$k1FNsb;!DVRDEf_|`0%&~y#*DbF0`u930|;bzkmf=VBwLb~{x>2Y@V -zYLV`M&nLM)EBl(pZwPw*<5pKr(c-KXa!1oN)X0(-mXH()=Er&W>nvNldmK_jV3XciQG_?YgF0 -zczjR|JzRhkJVe0o6{jyPJS31bS6o{B>6-#-9fTE&r_c9_sE|BIS9Bsp#WA6r3vo?K -z)GRWE7tnO3m8r`UaS>Ne;-uLmcuM_J=w> -z2_0Q;KR+r+%Aw{Di9z(bcMLPHBf|UX=4Qb65SP(9?0a0eiH(aI-pk|Q79J;OzI4Qo -zgL7OwxhcejBkRv+L4cdcYD2MXB#4b2EF(cHh*s;8gAoh4ynBtFaphF(M% -z3k72_V8r-`tbWMc$LxH>z(*{5%%sO`dBTXNtar$41ACn?)By_}G0i!foG``-D;zMt -z#{sJwGPfZ+n=r5u%X;(->d~{K$1(GH9I=|mAq{?f -zp?{WL<@*duKuLcc4zz7Pr?E~$JI?;%=gLG$ukg1VNEY=`IU=F@`8er=VK8od^_gm`fEY5Oumr=>>j -z2RBXPJ+vFM-adKOsmA`l(*Ls5^dU~-ACez_l;4x$p8fdc_7yeuA3l8gf{qH|%Ryy7 -zYf`>8#3Y(uE@`fjiz+RoBHmN&h$&Q^DC#uBBv*0sh%%-2N20-Z*Hq+;{j>l>~+2&^>UZCo###F3shGDhX{w@pxZF(GMR)O?>n&kAFz7@I!hdii{tf -zeiZpTqc$Nk`On--|8m*KE4s(i(5Hb^_40HfA6IK=uv(x -zJ|>@k6jFTtdgXr9w>QG?DX;v$lIHQQBd(WTN%`2-U2EEdzG@6A6Er%h)E-kC#Zw=4 -zH}TD<;`?^blYW#R;x8Y*_%&U{dbqmb(p31KIXpIcFU+nHrD%o0)8g=W5UD=6zgj=G -z4(lyb_b=j(<$eF}gb~h<+J!gM@S9A+Y+;>v>)`)FuNx;X*qcw>SFecHx}!@)ek)FK -zsrR3=t9ZvhN6~E&CuJf&C24EY_=cdf@h=E@eF0m?Rs!@@>4Td5)MTgzv;9ybnorpS?&Me<0F28+WjWwwnPeYN8EIK`qDv} -ziUFVaDT#FZdvR)8t@EopVpVD8R@Ypm -zdvLCB{UMb73ATLbz5%9f1k) -z97Cik?*{wsOn+xAe!1%vjWeNuRxCTYti!-Mx!&l-8@+g=7jN`p-HB+QBE*X{3hM-= -z^O}0d$01*D)Z>kMyit!g>fxye7X^Q#7;hBgjbgk}jLRs-PFBC(e)x1Q6z`2*ywQs{ -zdhtdth+ZUyyPO;(%&NcquBM&6QHeJy@kS-ysKiXFa1N6<^6*9;-pIqhEAsGen&tfN -zjS9R`fj27f?}rMEX~69p4S1sgZ#3ZF84cK06u7rQm8qTA72fQRZv^9wVElU~7@>cy -zBNCCfVWk -zIw|YhHyZIqBi?Alze^f1#Pj!4JbypN^Y;PI-;eS9{TV!eKg9F*=kfgg8lJ!3!1K|n -z3C{aEj=kEi|xUUkPzhB1l_h<3^{Y7~GehJV0 -z_Xl`BI6!IqrX8LSp4I*jhv)Anc>aEZ=kL$p`TH|?{(cG1-w*Ko{TR>RkMaEd2+!XS -z@%;S=&)*O5{QWsRAMCp`{he`ToPg&j(^L@-rzSpGUEvM$-!T6T^Z#97{*|lCE7CWl -ze?$5=r2lt-^iyshRa(R}nf&vr%_E(0UA+Hr`)7ahoA1yl)MjU%%gIEE>g#vc4^8_k -zveUcT7Oh^((tOjD-!$caW18}!!Tp`HxBu=9?%&}4-!9xgB{62wFXjy+-Z0|d7)DG> -z^86wFYhB54J)TeTmz$3tv+qBBO1}Icvh)?}@qGFG;lq#IQVezJT```YyNV}J;wL&? -zIV*YoAoqk4XxL1G-DBKU25o)s>c^e5-Q4M)Rk!a-lw6{J%c7Qz(uC)}{n`8ruQc)F -zW0)DgjO(pCuhep^%WHg_6x!j}ubZD&1>4v7WIOrfyHRS;YkUFCe8%6%2SuV^{smLg -z8)*I1jX4pD{5 -zbRsR)J>3VZZjFppdNo+sdYbz;TZl;Slk$p~@BM3144Rd`g0`6cBiFi?Rnx|=`jz^s -zP6^Q7I@WvJiq@f}-?Q^?|+%}#Gzm~CxouT2!6dmn%g^t}u&`qTxnYAHTP)(C^IkyVt=nLqOW7 -zBo`f&AzMrHI*-34t%^_cFTQ(Cc0_u2vh<0OzWveaog|#<5I3-`t1~A4vDgetboh>(iGnpFXh4^*1s>3+Ye- -zHI*pd+MH;)jeX>)#`%tprH&g{>-tU{L|bcBxq8_hF~S3@Zsjm -zEzz_OA3xr%7f1c3OZj;7G){?9+Y-dxX_Y1DF(&LuWilh*ZU3Hj2A&Em|@n;3ilwTbopucm23ho^kq^~Jg&q5D@^l&>-G?1oa4v^TGH<&0xXZA)KcrLQ)#JzI(R -zoAlS96nz(33=`QeqyDIW`YkM8&)ozKAXV?D-~JlYoBQAX!}Pdnb>-%L#Y<=#t3U*c -z>?>Wtx0;u(RoV7ATC -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 -zwF=eR1eE|tX;1BY6iZz{sBd`IU -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 -z0SR(nalttcf!5sHs -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 -zgTMn(KshIz_Rrn1e1>oZ}DFP -za6H14niAh?oCd=#gHNQ6@Lv^Ydrq8yB&C1VY%jg6+EG2$U;TJm&O_=#MI#jf+EJ -zPe?r&<)PwkS_B(N(ij34BssbCDjL@))fxM&T6?fA7o0yoa!?phT|y+5Q#r4~pQ|K& -zLOOGV3y3AL)m7#t-q?#z$e~2gO9!_qaOsOA1#;9)tvNan -z`0r!65b(5D!9WR5f=1v%lybn3jjR6bgEdI}N3EI6r}J>3KxD!Up^(cpc$t8IAw`QW -zW_-e^)3f)vlN?IqlO099FI52g#>RD6H)Aik`x6FJGi>@4kHl+JuF4%$dROJcB{cEr -zd6CKc(t-?PtCx-fA>glS&<|!xJD)Ax{H@&WNIs -zPC&59Um)hs*&-+$Y6ekHHQIe}brl~hWU=4&auDnSaEzdVaNO69fQ7}@fpPRo5tt;o -zr-QJ-0k&W?4dj~(EefuMaInSHa+2(hx(eRG -z^!28q5@Er)0*xM+3=0xZNYG)6p`aT{e98sl(wRiI*$K) -z4-yH{@IyGGhl|Q)Hw(hF!@S;z?qXN_aCw_!7s^eJfh$h<8{ -zf#_e~5@(Mp?5<>@<2N00qdjIi`xB8{pZ48G9}h1;fCpLWMV* -zZeHOcP$Rhy1h$skPz{67gp|GV)XRh3ui|Z(5aqa-jnAaXPbEx+&Q}rk*d7GX$C*zM -zzKDhf9BJYsagQ)D__jh^JIi%iBh7_-HwJ}VktD(WRycjiSGGXClp5u2GWau<Dr(!PE0MeVw1CH8GDruEZQ8~*=Sgd0n)DE{><#cCj6Y1I5f`Ntn`uK -znhN8E0ZvX7scXEL?k5+Gb)FE_yk@j -zwxK#Vf68rSPD3{f8|WZTAk?jI3c(I}F%TAETPUphM-k?`mY=Ir*P)2o8SRFFh1Qc@c@coeY$9yLVL)kJjqpoLTt?TSzGqZ{BO6-oSk -z+>5r)A%(JCA#RnM6B683!MHKv=}s&rjltPJhv#DVVp@1EaT(r8#%0hE6ykG?t&u&6 -zMi)2;(~fLDX9&@=AXGlC_eCvHhT->o77KIv+elsL894!Q0^Z{|Sj<-9vH=8`G!*i5 -zmOrn3aJ2lekwBFdDYUp$kqG4-o3>X>c@k(k;psxi+l;)D<_rdOd@c~noM0V*$FWw$$2ckXGa-qL!4evYIaqB?Lt01m&JAwKUFf! -zLSlu?DOp?*EFpd{@PV*TJ@K_q%8qLlHr}G`Vb6BGLp@?v4Scj0C(1{3c(Id|1qUBn -z`;$}BL^SlN*se=9=*?jbbEIH3@KqF~ajuPnQ!lNPi)6*dXKmgOVA|rNI#t?NtwZfd -z-%|~F2QF6(gqvePY*_&Mf*?`I2m6tdp(>JZiVl4$1`#$4c!)lZ5w7g=>1-}Dstw6d -z%y0)TA0lEv>1@lx!1JK35n=>-Q=>kRfa@_7^^1ClgT)%8N~XmAq;Dt$XRT~PG7K@Q -zrc>-}ik&PEO9sId3E#x&YQ7dtn{ALN;{y;#se{3IZ0Z7plG5lC;3_U&bn;0(z;Y|e -z6dI|tu5vo6-k^wI6^(5ejh3iof{<`Q8c!9{D#SjBedQ?@R-aM6^^;>Nwy_+69#KPQ -zAhoJHqIrowvkRP^%gAl3*wWNo5kNoYo!Os|n?qbNL>jpgOc046fV#dSooTZ|)dCmq -zAcvlnJ|+MM%Z0xO25Va&D!2_%;7?E~AL{wULcSS$>I|5#GS -zgsJh>RF9-Ju$t=_CdU%iBKQirh9Gp-O(aOe=2M9Ip-G7KKzt2CFXuoy_AVq^n_9;& -zs-dFwhR9r$6|pBL=k{%bceQcN4t(ffNYHbffHVGB_3gtRQ6<9{8PUNPl%9aseFG@G -zPyDmz0oI%j#;Jpdf|f|ydZqgwx7^t%vhi(^4{)lI_Wfc7^EC)E>EG_e2i2nczHa@38BiwVnTO5j=7(GzxPkZSRw)H31T0~^x;fx -z0Q(?%y)-^YeIA0&;=kH)h1T?n@6h%+Y-FfhfNrF{OyFXkg)`)2$l(y2BI0W>bJ=r< -zX}*-GJbd`xJ}Gq!Lz80$RhN0g9Csq&MnO$FGECscgDt9-91i8q_K>S!igl;F@9j;{ -z9SIM-uho7Z0f;iqg}1O~P?m6SSG9aZEC~9r9fHrrojGE4Sv#=T*XW~dd71hq%4lv0 -zaBU0W3SH9iE6zw4wtF=69h65@l`k6LJgBDI3)h@Okq(sgOog=va4U|z3`}c}^3iPG -zgP++|m$OQaKPH5_a4{dLssNzGaUq0yof*12-GeLhz-5Dq$TGwzc*6rraU7;2q|(s+ -z(LaymES#D-id`_e2KmzTW~|0mnMdY_C7KPGj~W!uw8ed8>e5w_k}mp!0K9l~|8+G1 -zx!lr2FO35Bf`5R6QxhNb&yC$Br(i -z2`Y*yIK2=yiO`|yu8UE+uC2Wfomk6#d2+QVoR(uN&^a1J+DVWOj23$iK6l)#HlI>= -zoJ5mgEpNG*wS5tmN&YC2)(CBd2(_!+>=bIb -zd(eY`LO5=nxR65um#J^ki>!sbZ=!=G5amUs^n&YAux1__ipV`l>(0BbQqOZ*t6Lsa=SJ_3Bk#c^-t`?Di>< -z_>)VP7P1V^K4R5irs%llZXRkwVS)a^ntE(u;Si4-7%%BIghHJs7ldBBozfAB+&=#` -z-RFhtI>!w@TS0VHTXQ0uP6549xQ``wCxce#zn!vA(GifAf29zIGm-Q4zynuw7Izk7it(} -zD0x>D>2+L8#$H3>8XgK?NRI%Vh?GzN^m0-&(i^N{`pyOOva3|)O~h>%bPhu=7RPz+ -zgpYe^NegEwA;hhPH`0eK1$E7u0Fz3DDpK5ffRocKEgHmFkZ`>7;FqIu1Lw~pr?xYQ -z0=1G10Zi^J0Xdf*?P>zJ#2GNq8ljThhKZB>Aexs5*MN=+-%;PqdmwZTWidD)4UrWl -z5eT=5)eiCj*EO)H-=XwS-luEXR3)^@Lkc5@;yCr{KpNr>PCY_#7xdLTj+xk@8eOO& -zkSWA0B4XKI%>&VMAD&vGpDHMktCD8-W^_g>zpEnY<9n~}PY;jn0q@`*+1TXciX8O1 -zdY&1|&4#>+nj}fO9dKJ#pz=Wt0_d=8)J4GN<3j~lzmpN|$mblWCTmU*$p@k&=e(pU -z1i*70Ck`7geA6t~TVZlGTpbY=9=MT^vu2Hb?kw2#ZGpo>@cWN0kztTyg`I$)K}ZlV -z@bewhrn-IO%nVk^-2?kvyrxZZNV^CLQ;wj(IL#r;PEfvBXlG)^tMoKUXHWHE98VmXnI%jN>kVJ&(lBQC;JHd>ElL -zqQzM!n{zHtBDni}Xpe@C`0}pI=~Q3D&3^Y2@f>p#g&S~TmbHuavYF|emrk2eC>4b) -zEgZ5eT)KLTV(vCr>k2gCk=@M|Xd1#_Jln#Zc^|pM1v*F)C+|}^j2{7q)3!&DJZOhT -zR|hT|LpqQ?c|QO;v4`Yg!f(UfS8!QglscBDo$d>1RVfz_-7D9Kz?Mef@<^e2CKxX1 -zYnhevYm(XZEsC>E1-B=>m(tlLMh?Y=CEEd -z9wDtSBg`B0C3QU*8Qh`vIzg8^Idd8V$2<;l>8sR6UD@yF$Tbz!K3I)1lw9*th|Ln< -z>P$W$7(PH4?sIR*hqQ%AEbtNAq6a+;h(B|s0q?)3iz?wc5w3uiGIX-&EYi6eJ4g*g -zfMy$vMbL3ix;x4=7(AWVU@usmrj_j3LqO!6SwBdwY_0Pl;1-AWhidq=4kuwg-jSI6 -z;OVDA7>4uXafxUd>x!**@I8UO>&9aUBBD{N7?m>x$}sUi9rF_p4&I2&8rQ6hB%lKt -zAG!vo3LPkw?aYVL7^nx2G>a<8{fAI6>E4on2guC1F2vLUY@);XhzSCV~80#6v4u<=bC>Kft2e}An -z4IL;Jwxt_1UlW8<(08MJ-%pkzjjK>%MR0DA=!3VyKHMregAY@9i}8W2!$jdoCGkCu -zyQX+xOtgU>!+3=Rxp(NeZJk?~m3uff!DDD!6Ui}ZFf{-PYFhM-Mf18xbTp_!mTrMM -zgryBh;l$pT00?D`xYF_031b1Z>N5Gbxze>FWe_TNc6B -z@N=%-x)FIF+JVGP;&8Ee5Z=&-?YV?q-%Yu2Hd#7ZB2|ORr;x)yqg<4~hAITll405N!IT;$bEJT|XrJA5PQL&;od&X}z=N4SIG*caHzNy+VO&&qZbTcUczxV6ES!SVFHq`Vc!r#P@K}nNb7Ygv+413I?JvwqSH{ -ztNz&P&%S|qNN(j^O?RwN4SWL^{)msoC-s9geuriRpuWB_{C=+D3D;pK>BVWW_O;Hi -zKRF$8d^aG7h^StOQVAAE4x=|@wYka|OEGGfSfiLYRS<*|x>LBC#t4K`W<1 -zz#!{a+2|wu@Pob_C@6!TvL0^Hiv%F>jsr@`?idSh+W1p2T)Zar)Qr># -z0@08crn16Ca5)GL8(;$&GPfEby+0ov3`Ese*5H6XXOILqTcf1=Qc(n7IM+vW{%n_% -zZAg3cMJYIs6F!De_Xesx9ZpF6MaDCn+Af0`&X0j92|*`!XnuR=%H46o38N^&C>p7E -zzQ*_f1q#T_qXypu;&8>e -zI{X%HbmSYPcZStLr{voParaTU(He4 -zE^EOTF)i)!sq|L0>l=bt(8C=fwRO(IlZ15$}RS -z3-JTX9iwu;4i*4V+}jQ5RyF&xd`;pj+vUk{24>RPS~o6IuDjaph?hBu$9JU(iY1an -zwXZ@fYV;$CePU`M=|lD4FYP03cX{Y;k?5nV-!z-gy2EtQ*lIV>R>I?b)Bl^akkM-- -zvNJsOcY{a77H-caevUn5~slWq&Zhx)_h(YR$Z|c`Sp@p&^G()*<9|esDz}Ya; -zoud}VqadhGf8$aJbe6*BWoT|t=$NAp$p%Oz0xLTD?$0)jC{!eMvHj&~=v#^N0dcOq -z3}vT95v3YQ4vsN!bW9(ML6|X|36#TDtMpIpEJS=W-l}c-5ysp>?_sqRWvdy+ha95Dbj6431Qgj88<5wpg=) -z=pcN-NO(p01UV*ipnH(K+zS20R?|ifKdR;Dy5%_Y5Mh^x!n3W5P2b;(Dx8L+;m2L& -z{+Nuyk7rUa5$HY5$O&xCHlbgF0cka}jz;%pUx3al?s5`58R69f(A@9NQDpy*L)zc(D6K -zJl4+hH3`?jjq603^aZ!zkgyT+qfMpB5au!6tzWjQ)+FyW@G5`fad>V-tsP -zTaqR0lhI2AFE=)VFm49-pWQcMb95mE+GIMAYDH1?t$L6qUbd6^+2x51<2aDPVt}XL -zhgXy1$B+IWKL*VB)ayt}clR7-*sm(heZ$_uq4m*gLbxP2!hN`~4OvEC@R0U#!f(A! -z)YZ0;yAN$b-@SoIWJ`zpjKQRuK%MHB#h>Qt{vN524taDRLDYHaqB5d`s;zV7-oSir -zQJntmrSRM)cv-a`p-aLboy@sKI<6?q8n=KKqxJ@Z4n4}^)K*Vw(*~`?NKm}J5)TBr -zPGodG95^r7_kB>!P8Ev(P282k=^kuw6GSxsYf$X*MIklj$L)v2nb<&kT4rtNeJ!M+>(#l)jK{ -zY&=2iq;03@>W#YZoow(1PR=*g+X?4e^lnS*9NGyNzf%U^dUfYXUEKfn0Ba0e>0sq1 -zZO2L#_99OWDuy|lEvqWLhK!W-fMA`Vq?mqApL*ttox?faYuz@9B#g$Qt&tLr40qn3 -zL>A}zzM6LK++s*Y?X#MW}xwdgLTo(Zy}`|SBalIXPM3%LRYU`bM(1FT%I&AO>1$R| -z)#|DDJ+j>LD?%J9fdUy)5lz%i907-Dmwh(9ig^rDA%lrjcqIt -zrQ8NV*yu0!8^RB4+qwJ>HP^X9{ULD`KYDRAT-cFwYu$d(t7Q1MXvcpi`6IFiY>zh5 -zhIONmt!B9`o}d+U@M~HMR}W2kefe$uA$H16`QVVJg`351IN>1t6UV)AbQ_F-E!U>t -zKlRbaR=`N4DoD<;*I(My<+v2^568|O?B21)uT-J@cAr@%ni9c0$khn^H}7^iiZeOw -zoJlevR^Mpo#F0;KgG9U^dNFi&Xf5lrZHW;jQn((d$g_`8J0|wT*nY@{)yy8clko4i -zO?QAi%YQtmGA24+ct&qdmGJJB;R*6;RS^s*fV+yDXnASKdHQ8ZjPI)>VZP<2FX3D! -zxl!Yt+X|r>0t5T1mliX-6rK9~{n5&jDDKlW -z;{;9A$HD1_z$byqt%xfXu0v^u8YkXdSrjI;x+NySsUHKW_IvX+bLo3Td@RId@ -z*Hu>X-PbNu^4RX(5=HB^U_Uy3a9UJ*`05w-DeRk=+-?7@yT&Tr`}=$MHncSR&yPdZ -z0tK;Jef!aU{oZA@vjL{`P8!SFzJ!l{>4kXW9$t7Q1^L!$5(tPR4nOcr>`9RH`)Ch- -zZAIq);d@eNzMB+ZF}~`q!VY|B4^A&n=@UnosUUopA>GThrn~(#%!;mkhBbTDZR0He -zXLl6dv_q^1Ms0AB+Yj6VOdHFXM5DN%E8EZUQz2Yqp~OQpQY>}?tsdyHl|I;0kav=F -z%He4G5hYt|K{$awYGm*0;fD$$tQw`(>}U>=i(HHx{_ajbrG)>ax1^<6eh$yuWr5B) -zqq%F%1=CRYWVBBVAN_?O5s}^z>9_FQau9CfR17bda|d8V_}gp&T6?ChiuUnNbfgLw -z2ci_2zz-O>L#_z^aKjFe5OrOsj(xHi2 -z)}b9C2fhwIc6Mal^#AN*xcI&B7gN2AHlSTPX_9x#u0 -zWZn@bP(R*Ll1A@nZ0u`z)kud?_YRS`_xP@HnwLEItd~lFO#6mR2rn&)Ua+ZjY6;IV -zxVT-z83VxbR(29Y`V{9+H#dEfg9AdB??IQ}xja@5bmHEeE_)FL6j$;X3wqV`3PSe)4SwgyT_h*gtpd4sH -zj_h5 -zNwD%M2I7I#mJ>c%!J6(9kBLpA>b3F}R+{F7yvk~@1k$g+cCt!N9REAG8&nwd>1>FL -z>#ty^Nm8jf@r;diHOV`^-YI8Fad8J7T)L4Hw6FH^5j}26pOpTp5iaKFJO?ZeJ_CIZ -z;fuZ1$X{O&+^xvx^q**;Z*s0#se6}qUy$&C7AvG^Ry!ZKjedwG@m5IFx>*O+M+($o -z)V?Fyz~Apy^>1k%?-p)A7YuOW+(rbn(j -zK`8uvtclo;9z!F6jXAf%N(I1K$0mW!-w -zW9NhOYm+X@iie=DhvY78{^eLbJlG|oq!LN9(*A{#0tmN5rYJW~u_a?rJsFvD=(yyQ -z^B~|OHP>V0!DA;nqu3(Mi0VEOYMe^WZ7LnQAV>*CNQ3Jahu8{{9qw -zimaQ#HbmznWu}N0AqxTmbA?i-3Tm;{J94sj4o9Wk@2akYOJIW5T8bUsdXHSKs*Wa+!=6 -zE#Mm7yds!WW$&s-#Vum_v=Df-91kSE6?%OJq0A#HVrA>3hn$QANCqdcZ`j5wl1)4U -zGrC>@Umw}P6M-?bAwtXu7All}+}U^rh$qA&xdsF_n1yzbgy*TM3-0Qkxa2twWtXkG -z+u4Z8j;oCWUzxfh97uAeqoe!H2MqS=HInb8Ot&PRIxam7F0o -z=xbps19$-d2*~&k7oJ-mu(K6=P7_1EJZw44bT|gul3%WcH6+aYLhbFB4-(}mdAy7r -z%EnsmZ9s9A3$e34Us3q3Vsw-WHqco09S6dEDAhr)-rU@hW{S2gmH`e<(Iy{qbO{k& -zSD^z==Bl{L5K-(%d$VuRVuAl-qnP)I3d#__MhcO5=n%J5h3Z=lsO;+`hc<0035VEY -zRoMEDXdcsW!|7fU_RZk$NJ68_EAU1m?Ey6HA>|xh)X>B>pfxz(B0=nc7?M0iqMhr) -z!4POGLrLYrVJ&lOI2@U9rav$~Z+d@nOwg6NQ6;f|`-f?{GFA~7!UG`)*mrB#Gs4`p -za2g6p?uEX;S5p|KPlvLDy~YgMV+k~@HbiA%OOi6<327t8$>NX;*8fEk@IWL|d)!*d -z(c>CL)CSUWm(Fi3T&)}VQoO_QKY_@X_x_V~qsf`V+WeZ*~F-HBz7+fQGZ-;(s+X3Yty -z!&bt97K@E>?NC}1No}QsKt#Y`<;z&aCohVYVC|gKmmnnA+Q;zyT(*1M<(&*^hK1Wm -zDT#flJNy7`o@PdzDocM}KILU0`bt82?QuT~ad2o_;Sc%%6~yKc?}crrZp#`M;y8?2 -zhZ(UJCrG1C%hl|F@a97f>ZkFVKkBK(n58JGO*6r5z#QyS5qakrcP$trXB)41S6VY}_< -z!I76uXh}p{Ko|-!vo_=&xZiC1dItjs8=7i{1Cks%S1Al5!}t-%DH6+vL9c$^0#Vd@ -zKdxKiU$nKVMTWi{u446gfUZvos-5<)Vlra-VWmDkb~q+gCzN|0R10!~HX_T>Ut%zp -z!}1hwH -zE`pITL -z1R}t{j=sJ;#EimPoT~}(zjzpYX^*y*HO_@|$iwn7TPXz8FpUeP6$%?&Dd86J2{5maWI$+-Bf-3Sa(_eKn7E? -zzu`gp?%`|}_V2THW_q?_e;>5COHUQDA&(5;gJ8o_q6XD)n_Y!EEBb`Izi^i94QdC) -zxcoYYZ`zB&R%|2*%ZnC}mX7Ge1yn*X9)i{E{fu{wq7}o4x|`dbBmuf31>z`NPADJj -zjD(Zmia-h%YfHk43#qhd?CZHA+CEms*8wAb(`e&cQN`@UFZF$JYM}m9;ezF4;q6X# -zs*cum63(;Ko#=TeQ{xW1QE0jCe3@uY;AKd3e17QYYohR3hfP<}|K}d^X*JBdKu1cH -zY7k}cpMJO*#0fa7A)CG$*k}Y=m?7E7_>~DR6X@hK5&&#UQqjeaT+wR>w6pEOEhV~X -zi_@p-qZb10!uvR8G)!zv4FTpLFh3q@bnDnzBL_^BMTTg;)EBd6&v65Mbpa!ldxh5lN -z_y%O%V|yjQ+AZqXoUv_mY}>YN+qP}nPDh<|Y|PlU?R4k#+V48&?0xNjP@n30s%q3d -zs4n*RQ^mR!+Q-eZBokaq+<3`GyPeO!MLQ4i=S+<)*^%P -z6tI9pR1_|8*MQ|mT>`}i;V6l56Z*m*DH00CHsW-cg_aS+QRPJ5N;8a7 -zG=4;L5+iQ_@BT2vv^fXmjTk_Ta3liBxS3#xy);nQJ<5e+&Nkvy1~1|%h-iKk1tXG% -zo~LNt44;l(OJ_wKB|QzDz#0{i1P&X@>sht8QxrBj^5A?*c<{z}|4y5BOxq=4Q(G_l -zFLQLv=z_t``}_Kbui8L-;9v#YJ+|bZ5fa%0=>dPDMAB{?YUdQTv?Zp|o9p-{=7-;8KT4yt4F>0WpD?8CG -z^;)r`-`P?uqY4#UzsrhYT9TY%-xoym3daP4TIYoMD52giD{`cW4?Zf_aq17-rHCt~ -z(rw>q(XM7Iqq7mo`CPI*0t9g=i>5w)th~hL1|QHJ3=%GsLt1<_AkIfXV8ehHVI7JA -zH1cu%I-M++NB3eS3S)A+G!|*=d{>>a0Q-Oq{+Z3uk(wCm8yx0%6h5CYJZRGo2ULr} -z6>*Fb8u~U@H8Chwn@yYDVG#~)m1_Q(a`0MrF4}}`Hf1TW6BPpLU>upj!f02<*|>C9bpY7$TwCbch0#Hz&2Cp8j^h3$W0lvAl?&MLkuQs -zZL%ITApTEQ?MqQP)YV89)cD5Ay%DNjC)e?45++S_4LfvlrgV0y -z3t8LvR>vHZOxJ3let22qT~O_c^WMu2@)k6CNcfLe#MvBwg{xFAz^293Gn-zvIBMcb -ze4!ej26SozrVmQytnZq#InOOOkH -z@wz}3%9F?0+-WAz$_<;eK&|#v4|!ugM9Nb)DG^rFfd#{VM5IKjJ8_zQq~67%mz^&lCAm -zDJxPtD|J1HbSOYqaz7(!JhJz;F^feh_GEgJi{(TDvdL&+<?s`WOx52Q#XJ#;2jh*3%D|-#Ln*3K$Hx -ze!QAKGagt@4JR*WkM#;QPutD^>Q-p<{1Vl}l#qY#j5NduSfb#MSSO*YMlD`PDn>yC -znsE=mtZ9&J6BTDOX}58dEIgQ1ol*j7*D&i8gMhi@%y4D#*V#=p?QhNMj_(ikEJEwi}c~us0Ev;|x3XeFM@hCgL -zU}4+T4W*&>VMAS(`nX79YBUQL(}yldAY&+pDhj_HzH -zDccrlpGw%l@DZlLL?)z2KQnN%c^;Hda#>;K!o6O -z>j#z?A93_}-*GHTA{;@?0i!Jx^J?)I6aF%({A30Co>VxkKumS6UvHYKE#IWAf&3It -zYBf62QXo%;DB$KJluPW(bL6ym_%9^_bJ#yxfeE$sYH3jbAO;kv^z -zTmLSmVd@ulQNaL4*-ZaZmM2>$_Jtx9_MnP|Kfn@ic~X=Lrn*j>&`#OfENu>C{nQ)G -z$y~aa1RZ97M6n;mjGY>%R4WK;>2=Utez -znOE$v>_3&-;U&(7z>I`MBTEKz8|6j*0r|r44F0yDs(7qc_KwOd=}{ci|H1J+Hh5Qa -zG(DIr?K)bT2?DPt6^q}<)^JS%bFeWBi?~61waejWtyfmFtqj!7M -zOVYOQ(ycB;MTwOj3OAh{BGJTA@cbLx*fW{5Kd!Zg^jd;eP{}%0 -z7K-LoCF$z#2yjy0vk{=%?Z)*B7cKiBUPTWU=v$1m2kOE8hRQukbMmg+6B!cn -z@%#5kLs%qJIy8;TU(2;YeV^W5gjje3R3BD(ycKl4gRlor*W3hgeI0JCL!U;RtH&9D -z_fQBpae2p-htd(O76onAu4fq#mz3>bScm=T>kZ-u4<(0*$zb8s{7VHwvi3Syw^rzN -z?LexgYEe+^q5W1p62&&H89w+q50Q<=h|wman7cO#S)vI#$$Yf0JZnfy%dJ;lg8Yus -zC)9h=y-B`G5sFZ@DgGi%UkG}$JsMp1pZrtj=Mpr}DG^-cCTR6@;-L_R#-f64OW~Y& -z=u|ADm>0F=sBR)qNNK}tPH3^?*9>`+StQgg5&`PIF;ZV{=!CxhegQls#Qrm^Gf`Bi -z6UgMhe(+)4Hf8%n>TXq_X(m-{iUA_-WLZLM -zg-)*Je<}7eWvb}X=foTj3|Hw`@%*el_N}dJ8kcl}Gul$E7+B_9D0DvbCLfw9R6-spoLuT|pFzTeK|*|bvfWc=ZfR_R>#5ZluFyU55U#LIqxQL-*vOF#|^ -zTJQ|U7`Bsta{U!99dC(f)5o0=!>NZcdCJ>IN!jS;Pa1j|9V4STVPO3M+C}IGI`vvy -zn1?&X)Bl+Du!ne-^l(t4Ee^dus%o9NndCa3ui8mwme|vS)6m@0HT__gxHb~f1y|LQ -zH(4T~0$zUoTEc>quhuAtww@vR-pP}HsHX!l8&Ik+5?{%=3}ZW3ql!FJXlc0~3UNIz -z^MsQlUJ8we?3mpXv=cpAGBm5u>mZxEBblPcyNEzXA0R}PeBNLbUgP(nM--P@EmXF7 -zoKKKb3w>y-n8OGo2wr<<(!PqyYwESv7H+w`M^!A;mod3b;d0n`L&-{@KzGwlXwvG%Z$!&=_Fq%oe%K2dYsd@8+VzST!Llg@^ -zeW>JI7+M$0$_i))A;| -zMH(xUd-VT^XiX}E74-LY)qNO}X(Le}zW%R6uNYAg+VC^>oVLtfVw~P7{x{C8{Saf% -ze;9hU&|kd&=w^A(*}%*+;U7(p^q%MKK$BPo7efTrT58!z67JZMBxVHe2snlx$j5i=(tMbcV1Gguepi2iRNA -zd(!2elEPg`qi`jE=li8>oLNpk#(Ykz6$k9_W$IeJw7@D`2lSaHns3HZgAsIxCa&}JcT+UKS9k9(yvTH(fE -zCV_iGdN}VdVld1kA=k1D|HICsHc-+|Q8P&US+5pAQ6jv;z?H%1$AB-odC(~yZVzae -zTrGy?Bs3YgS?sFgQ1KTRXEl&gC8+gYEfahHGXKFgwYw!(H0dkd#f|#sMT16fq(5dN -ze!-4F^MFw-i(92X^N-Nhj&f(f-Bsst&JOlYQ+w-(ga5X#N^|#$30WJvXMWhP2I{v-j>y><(VAs@O4EQBF -z@tEqukZpWp-}%sy*o$>SY=Z2@;K_ZB2PWf%f-vXrG-n}+2_->WdJSys-F|Ni!Si8p8S7oc`gC)`}c9NNYnnn<~DP|`v2dS -z?}lpxrXp8#kf&3cma9GRIep6At -zLPt#XDVLYhh5ggh!!fJj3eD)$d*wBEUU#GbK!i -zJTYiXicPB;>r^HbICLzuA+OBVyMS#YI^I2;9bK*{)0le^kow&$nm#-lFa?SE6zQta -zMv%+~{p)Dg_o!ag46yye&O6=o1dAvU;4_`Hgu>i;LHV}AQctCHkt~d0-2rF>PkPUg21K=Q0B%6{&V+g^>U?_XpbAPUXmPWM}G%g1-3JojI -zfz%l&$vj<5Y}ZsOe!D6$2dUi~C0RrjH2c9D{yf%7G_J7J5t)2Rr>gh`WI&bDr|MeQ -z38sJ9!aCATgKBH*bGc8Xj^B-bN_#Rx$i$X#MrFb8b%QGVQolyNMpLH=S)MQ9e6h`m -zopoCr9-wGdP$|18DXVj+Fr+#X&XWAj`xSNYnr~L1qMQ-^pZXRsbq8{tS?&<~V`S?; -zpOoU~XpxY_z*(n#NaKJJwvJ{FLUZnk;Z=#P)ClEbw*s{PU6Ci8xvB>_?pa7mT39P{ -z0Ut?ROj5$-88#O#qokl`JEf536LnxYAE4;iZPQ0eEDP=O(mxDYPu*(5Jn$ck+-zhF -z*uWxV`7a)if1CUo@hhzX9Y&h-b_pF%;VKSVb4y@n5XMA!P5(%oBt=l~Ryg6a<*nO_ -zun0E!F^6_T8a1@&C{d4PU1IFefk;JK@FCd3P?Nmd4k;R%$3B}^t`d-1y^1Gwu*F`?4%8( -zaL4lSNRI(mz1bGHa(F*tVpK0AYkLeARszEMhXsgXWdV|L-N6df4OKG8M2a+7025jg -zN$<)42ahrsNhnX%8nPS9Bot}uz;%z>X|@-w0Q*Cor$v%{oGfKYzedw|)08S{o8|!m -z`{>>pA{br{?VHytnV;(aJWx?rRN0Y^t_zB$#Mn&=<7^})O(KdApZbRYx{oaHQ94~N -zV{+C_eD@o}{utMxV&@dt{~&uXOif`}gw6q*myVx>@sxCKMzhRZ&9f7-?hkb){pTn -z0bvhU199mvS?Ceos>9f%8?Z-)4TZ94iP(g&YN5Z_9b_(Q*ME{rt3kz5&YP?K2%bWH -zmf#=Tp_rJMtVwCJz2w`=N6n?BSPg(a`e<15s86SjTKjO1k=${={u3a!{x1ZLP`rsF -zzRwZHWhFCa`6zPEx3TFXYs;L6Lwm8d@rZZ%Nlf( -z*PzOX8CcKbv;I`rD}=-USBN(uYcDQPPe9hHam?moW4k=NZjTn}U`&oL7Xv+sW<_*2 -zuK&Mzcun#CDZ1oXpdIp0u~JbZ(dm&Mdpa--JX)J_gak*>XGxIiF#y;q!Rg(m$uBh4CSrHA!L88{wg~98Aj0Y$xZyF3; -zS2jSk%2yQk3cN_}iIJFVZefTCuW-{!YEw}iBM(W^8OB?X3prgsh3a^WkRQq&qzAKl -z3JUY>NHcRu%M8d>M_e-Rpe!&FN>6FKrLmSL*Cs13(5*?8c;vm(H>cNo`f14H0>zp1 -zn+qm$%FFaFEgQm8OXZ|F5$sLy`j$g&S`JDk&-olqz)(gw2=JfE6UGZyPSv)B$>)2; -zE@7afyx0c6kg8FH4xh-7!luf8*hyQm?sFDO_D2*(9h=M<}vKh)p~#u)>_@s=#$0;@bs(y#s%i3QiZ34`!)+ksBPteJSqTDH>Ar9x*`-^%uQwv#Wa!VEyPh8x#Z^;e`I|;JQZ5 -z|Kq?Xd?@o~I`00z47?8P2UIuv#7)i-Q>j^__a+oA^`HrfJl~F`UiZ!;dXcuo9vtX) -zgtl()a=@j63oi?pwIr7Pw~pg6m}~M%Gr3W;TZQ1}L}F=<9|@ud$*2K^sWaCw0K1A| -za`a!h-OTV|a-`1M%}5@X=orm)gmye2TgQAQw -zF_P02#dkA7J6wtjtpd6iY7;iV#DoiTF^#pH?$8vuU@{t88Xj)MIsu(eXjj+&zC^wX -zuxIW7Ua8)WZ8^Bl=}md1EaM(O$ZWavvRdhAGUcj$i;uNh*{79@G<0WYQK34;pVB2K -zskUJ*l!*xktPv!iNVvl)?A=}<&_{hx{NQ!Mprx>)#=9+I)X$Vmpxtf6jDC^#(HL5{ -zHLvC(_JK>0h1nEOlnT?L_Mr~#u0R8Q19T^aE65>dm -z;`Rrqx-Lqa*Q}FE`b>DEG^vwJV=KHzJFZ$VcR?}Yggf-Ya`op5;$z4!WOyFF1+BkZ -zjyhY&;Y%L>#$tAr(uMG4ceyOr@L&GuVnFH_4uRN{;u{B{5cr!@lg*u%e5r=4Q}eQe -zgX#x@e-R%c$SsyJw1>y}X=H~}LRv~C4{3qT2B_@PfhPPOZ19Jt}6R3XOGK$Yc -zNcp?aCp$+%weX>yuUKQ#+^yMer7!hj1<>MX{$`#$Y-X9TI?y4x7r!mW{d4xQQU4j2 -z-zbx#@&51@lTvLBNp?-KZT1_N1FusN`L@`>dns)Cjhcc9xQE#KJCrR_TV={xJ~ZZ? -zkZCv)`q;`+CN4lkb>+?r|DeWl*Qo{P+nvnjHt@yTb5~wZLjJiYV5;>B;i!qM!h-;A -z|JmCJ(PXW@lAQqS2YlEN9TChO<}*nQfBR_}Rw*?uEVdoW7BX*%m -zH83ggG*2(h_6+sEDd@u{$I6Th9It$11+>Shv&v&wI{1wQx(w?#ng=rzrV5C%2vG6t -zaxg;R&0VvJKxnqLAHI_$OtYl1(G&n*1sz>{<*w!!5aWaf-CO88-0D4APHNt1f?GFe -zbFo_eacH^-R!F{jzzft75XmGkx&73ukrI;{Radgp74$KO?FjP}PDL|6gHnLKeD5`EYY{H|sWwQ& -zRMyQga!uz)@Eh}Y3}y3GI)%-6E)kP6@@3-h-+?~}&k%N!DIsHPE?{;VgQ!CVZy&y1 -z@t>ZE`m4?MgY4K9F`2GR*#=Ma9>Z4Ah&abo2YtjBiMhUR+*b{l|3TJO{wZt{v3g2l -zEKUU7?>9?pqMa`{c-R?FdySn0P-==zfE1yV_Eg3el){tC^79$IP -zE;Z+wfO`_FINCcoXPj>3{psW`F8EMN8^yCkR8?+4Y75MgT810E5rBKk_V^R<_v3BM -zp;h)W`}@L3P#!;C@&=WOz+@!6`lUzyyRad|7bUDTG;}3GYYaXFk893$Z3PaaBE}Bg -zX6)Fmcu4xipcX=4P~-TMk}f1rx%YP-h<`yMAEl!)_5Cm)S6P$KyrwW@MWl481o?N! -zd_BQ}g>;tKrc^Jw5YP2S-!RC8_GAjbkCl35r)?AM;Ve2$iG!MnSm?hrnVD9O?v~(^ -z)s)P8=T=e>n}IThWZ3Q#D|^w`7N1>FOB@ -zpi#G(nTgxMVE_jm1IeJ7;vVst`dUo`MCjF%E_f7IXL5E|RD+yBpjgE$K?k7qVqsQV -zpS5OsE#a|lCE58MA1e&!_=3q$Bc4K`R)fDjqxBR1!LT(F&SZ4+t*N|6rt|YjULsYV -ztgI3-vVaQ;>?aeJDRex~HO#ghmm%S72nn{gTltVUXX2x0k-$o>%p5mGCf=9;(sQ$S -zRkbN!j0)>tzYs-#r)&IutVKe^BLRYM!ZYG&W}X!hA`r1ED~2VSBcV6SK#P$U5p&dD -zr;$p)#JI|`{V|uy!y(BSfZ%W?dtk((}_h`0Bu2Cnd%JyL0* -zoh_)ohv+;L5kVE%o?hldcooYC+1%A?RbTTz@I0{{g2;SC-oaM%o^ScDSJim^pgS?0 -z%i?-idFB^ZYF}5sdqk*9v5UpEj%$%xeY^xatl9-2?|R)uotmgO=!xt$xK7A6KiKEC -zn~9ttsD^-s_R|X*Fm<)Jv8%5P5kpf6D%|o9c!d9`!_SyHOdf}vtMFqI{1zAnv~ao1 -z3hnkGRnB|FEHWmc!RzSA&NnB!0%<}wUQl|V0jkrd#=bt%qNVOKRCQfU5C)oi3#+De -z{!6N4FH0D_t@VxA^bM`$C2~mH{==bC(ks>zdIknQApSq{J1_-QJ+6`+YkeBO;bopu?KMM` -zo`}_Uq=j+FSzh)W#_FeeBG9KcT#;e=pX|QKDx>!dbFnY(yHIu5Hs)hux0s$rCr(vu -zmO&FrXAy}{5v)fpQ-cr7FM4jdYoArBovv={Piy5fT2#4x>oKCVHHR&5muHI3` -z>k|EfHK`d0al7L%>7C;pxlaT9y{*;#m=yqeqzw>65x!^~?pJ^w))*;%KYK+`YyB2NtEs;bESl;Q9O-H3Gy)S}+M1H6qlk?`WBP0ni2K%2Q2~d~o=P3BnDdx` -zYU_jmy+7s#9R!02|G;gZ0o*n04^8|q!`Wjx*-@2%(WZeDLLAL_ImzK!06cJhkI!x( -z!0UArK^II!2+tZt^g7;1V%jn*ciSL=L*4f}3P1x&)LaFBnY4oia9}UgK%XS##MLAZ -z{@6e@Ekq~M`6*ssv6 -zS>OOV*%w_E&l|#%g8s<_L|WAWLjner -z)rm`WDM*F+Uwvpv;pCo(a4XpW^{>~GXQkX^Sfei7(#8JZ_l-L=L%Vy1?e;qgJ}QWk4me^8FODr(h)?vZRj!d8-rBcU`eq-YHKx1M(H%(V4@IE$P{xQrNPxly+sX-RFw0zR`N|xNf!l{@(wI%-10XIyL;zBm&#X -z%&oig9v?dfr!yWclw7qMn=NjgtS-N^bb2v^w&M9It_Myynsz+O9px3E&6~jo7hfJz -zTTmhAU(tg~Ut}We&0yHctLVb1&y(gbCOW`Q#Q{yQ#+e)o>046?`n7r}CPL)|8f?2N -z!hg>jjh5k&q74fp;9;w}AQ?X0H|e#MKo28X?y%L8851@uHy%|f$O -zJZ1SXTotqMiYfjPnq-jRJz7Y-P_~98`(&d%N_xL*W92|oCq?;izN)89qmu5B9Lt^| -zxn9Jp4E7CQcd@WD4dAgnqG!`61ONvN^|ETM)9?Vs!4zOT)(74kSMnbma%4$Tb=A!4N1Jb*RYVxD>95rhH|a -ziX}DJ{qxufl!#AvGJ@_YlnWS4s_5X;H~#_$3=|pT;5-q;9i4ViFN=3BEzrwno{3@P -z4(>RxIEUzFKQGmjifp<30EWU|B_}4H3Kj`5@|d8^zJ*ygaVgsK@|ZI%a$HQ6IDCs3 -zV88x}lMOF|kjqP&Q^i#BE8JB16bUupuj}9s^#zBNKkdDnK@#x0#1jTF$U7ATWqPHM -zqJ#5jI_*?Lwc*?d>dF9uOnmM2eVwC6{xv0NgA~OZ^q(!qhaOBeWU}#u!H|E*vI^Si -z<9jI;$C=07bAkv~AV!TXsL1zz|85+;KUP-H74m>hyauZUnNj9CA4V}$T2qspCCW6% -zVH=wS=DJJ5Hnd(6)Fn*D-uTpcB`O3EBEpA4v`F1{IY1wh=~zbGR*iEU98jqLTug)` -zfrMagpTC5Gdg2`YYd*>0a2&_0oM%_?7yQb|Wg^U*5z22VADdTsWN=9b>7I3l!Z)=? -z{&{&bo%b~hO)&mGu&F{x -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 -zwmmTSMNszY+wPb6SpA&eO@17dvI}ibjml4 -z$1~LOyW$?6OPz7I5=-b`-rgkp<%dEE>!o=9-N%w|P9Der;Y{07TNtKOya)5*{`K`_KufO~s|H&ug*O@H!Y5ySJ@Vu(_>Jq+#9qXs3M0iN(h&ygr -zvCB{j&+{J#es?BE`>fLLj&Xt#Ul9^1nYfP*Hq)0~*PoZguO{EWA1cg6KJ7~YKOYUA -zQ9b%uyDT3o>gamJ<=-BTUv<(;^Lt>J!iu>v>yPZ@m}cr7(9W2>Qm{j{tZtP?X=@jV -zi%FpP^ILey*0qq)nmOoVunGR?mrFnN{I_^l;_6mV0*gjGYTtJ#iUTX>GJBU`O-AouYM1B|49GL)Ci`@AQ&*qAd!a1D -zavjRulJ;m+p%3y{Kpkc_J5E!68%9&w2T(gXTUpP~^cgg#KS!7ROuu!SB)=LLt<_3& -zG;F>AUc_2=2=k*B0*Tqs0s=G^ii*T{bq3RIiXBw^n^e5T1eg5Hq?YlQ%nO3|7r*y+pkHerhSn1>^8uic -zchmwK21wgEQNf?Ub?fhx94TL(dZ=Czda>ffHLN<&4fhct=#}LrGpyuPQZA -zwG>7O3Ins>0f(SMbk`fm*U4G`XpH*f3`g?=dveIu?g#26<Opo{4qTp -zWPxf?KOu6iJ%8C+8+IAcD6Xw9Z12%3Slfe#`y8YFq_@k|azkgfy2jW@& -z@ao4}?D*i0em$n(eU@?sdA0qJ3nr7$-GBl!MjH -z2&e!GR{%_dX_oFFJMp^ZFsxbpR-6E5K#HjLzt-QK&GCux8Ay1t#FK7v0x9CNpbT*A -zmVy}d`|Z&5oh_8YHv0SBDL*&MiZM`br{kt6@Q?3# -z+YzIA#jOs1=goW4_5HF>8u{L5!%RN6 -zyIo?~JPY<$*DuSWw#RS3uwVJU#mW6Vzw5SW(tZERZ7c$+@HZqJK}m!-G&$W -z`JJL*X;sG*mY&S6ETrRCLolhK#&hVg@=b&iZ0+6c;N*@Bly8y -z_CSP~=AqyDTR<*9@DGU^@S-K`7k$0rhPmkm%RC6w#SffcVe)SELo^%i5VGP&0TJ8c -zUqdg++imJ21}yZ-B=y0E*Z4^+*FD|8eAyW$AauN3;D0v{y2@Kec7$R0IXBzc(fV=z -z^8|D8efcL^y-sc**<5LJ-KTr)Tw~xML_PStmPM!g^^>;?h7~&Rhy@VIn -z_2b7m?O>bG20!HC?>5j%#1qvzZHy7jiY8TvpKo$oeG_cd(WHbhJS}-&krUz*PC}4* -z-OD#u7oD4S^8y$hL4`IpI4`C>tv${W(TzPnEz-ksK$IL~>Sh@0@p%rKFDczu3O?pM -z7{b^fG#koxElNr6yc8Hlbd^}r9TW|8@a(6w!C_NHR{|@aH3%sX;00E)QBd>hb=APo%?<4n}H!Z~PNpP8s5C<}E&ZABE0LK_Y7cv^e^4aRGx)5j5 -zl$!|tngf4aOnargKw69+aJYq)T(F+fx~A?q_zau3Bm1U_u)}yw{8V2+0yq=0t{Ef -z$!NSDIMWM11ax!2#mGNVx#;$-wjP{cTQs;8Ujl)TNZmGnbKSpQdWqmxl4v&SPv8~+ -z?hYfPR8Udw7|fWm -ztUb*$XVP&=!G@JI_DT@Fd0dQRG3MlTpE;I^%Co%b(d)pXo_w*Q2|6;j9iczrEA~vu -zlL4{=`RcV_+CDJ*qOpB-oa*$1cA>()^Lv-BzQy$uj?0%bx4UvsDl3EphpBA?RqC4-~(Z)jxAk<_8s^*||A)PA35* -zw-ekqYU7i{CVqfj-3ZGM~n>?ABYI9ffIPfS) -zIb#J4;b#51(Bg3$SIxrM+?uc52tercg~Apa2~ZBIvs+c)%=nat2E5_p}*@lKO%T4`TAJf -zk*!m_E3$aHhH%lIZx~!&OqQ}o4Ycl0>4E%t;OvmM{`m1zGE?Zcr~@okQKt}zE)m0P -zR2^tCPs6tk&|)*~%YB2^0{=(h%y*!IIsn-uAquY@xTPu6aM`BPw@VzlY;BY?#E#XV -zM2}FBStvn$M#3%+f0GDJ9^Qa=EKwI=*&Z#2bwQ?y+d$S}y+zrvg)x+PN@k}LR_+(nRCIo-tzu0%YfBi#$E7AMbEeB?ZHNrs_ -ziyI?}s9cjoZDT}0B%49w%R1DDhoU1~JBRxkV1u(Vxesyey!vBBIyx>~|Rl2lWbH=m$~|9VWg96$iWcN?h*I;lU*+o_;gk`UEpdmlIkBjn -z1oh9+A#b6nBfns6L -zl~Opji}3+W)t}WZtpz?x6{9v?a$y#e!-1?=Uw3EN-hKosJ;)v~k@SX7>r!XRFOHNV -z264QSW}(ma0+>l2g+G%%TqZC+mJYUm#Z}es3A4q;`GpW+NY5EOg6Bycodh% -z$E=wMzohL~n}W6kr+E{X2Kuw!FJFIT%A9{(4SX0>b|)1}J}z0CNNxcz6me!-9zw9+ -zsi3{>frmm<*YX9;6*<=!Rvw1;Kf#=0!n_2%`sWTnQK$Pmfr-CSNvlH#fexdtet$ul -zj|Q}-=Uee%;`H;CIzG01P1_&feJ*H&EYJqB96}StYYFRC@~*!5m&*j<;-7cT -z;!yExT+C$vqo_iC&X2)g?0CN2iTrMcyiB*1Lw@%0at}t3VD=G#%09O)T`92&sG)c3 -z2XQD{d0~nku>%j=Xf1yoddl~U{0UNXJqa{O_((2UY0K7Xe~Ie)wqT4f9$zAR)i -zjM!32Fj5jB2EQ47i=0kk_|1c%WN06C63N=b@&zeAlKqBPbQy7$h5h}^&eqed=Qn*6E1-(fE0$cm0-mnm3oYw*cE8| -zx?i0TO#ID~R@bDe*~A~yM{a6>h-xsfTpYaaq#w1*bsfPvOZy>z&wMqu*h>%XZR=%1 -zrNCoINI$=J`L;0l_~Eio^8XZ*Z>MtZ0@9S=YzSlSpML*Q-~_B{$kNw>8cl$f8K#a_ -zzp_BSK#R{L0MOZ_VXr?)?RCMiQ=M?NL_fCS_%;3IL7-mviDQOx;*UVk3S~J -zc3iZ`ffD7=0nOJst2H~v3(l(nMkad`N4RweQrp+>$iQ!yDg_5P~(*5puk=JzfA4MqWV -zw>CwgA`&Ci6>?8y|7c_*)mgkOng$J%2TkW2@-hP`Z1yBUKSo!g8I4C-&OoK`Sv?0H -zlC~Vp1_p!`8e8l(NRW6vg{nMY0wLfk-e40CXk!unry+*R9vyc_Y_RAL|Eh1V%7&4;hA)R9YqXADcH`bRMcqleoS3C8VaMqKi^W2C};w4d$P(0 -z0BuU^8x5ybb%pvRU7hYlog9;>5g$1==vWFzgRSjd9O#=AJ>sVX|MxR)D)L*IoD -z34`CrW|z6g1GR^SM&w#*SM`Iuzu8v@Xh9L)MBy`=8qOhnJLtF{$;F4VQUO#lZBQM= -zAdgl&#sIyrHf%YClbEdsh5&4nM@{M`&q6JJD5w1tAaP9PZzY}$@*CnzV^bHvZFp1ZqafZ+kaiE;w-4+$z8E!hDRcQ9v=QjR#?frc6s4xR#T5RF_kNFiMz>S2(QKm0tscx>ZV+Ys8^ROtA$BBXK -zefV+)N#qW)cJG*H-m$7E^x{h)(vjB=g`yQ@uv4cC&Br=TX8><(1P^gsgY61gLl^!t -zrSWU7LU<0Id9K-&l{0qS(vjg3-PY_GnGFfErT5VU%{U-$WN|9c3{GW%iOAwF&=P?A -zqE^_NZ#_&IO`*G;sE7__)NM7?tln{f)ri*8p}w?iaC5%$tpO!1 -zEwWpHW~ZHI?Sz;D*9X3c#fcS+#oMZT_8JW#L7DO6=M?uG$^QKHk1~I1VE5}E3L9JG -zGAM4>&h`k{K-@7x^Ac;9oGlDPpKS1KPHnnOm@mZS4!k+y#0<<0gNBVk0;X~1#D3Ij -zoW64%E?07fUM38ElUSS4$Fq>4r57Ka7XQ%j -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 -ziCY -z*LhHs?lrJc9DG|NTF<`Ofm~zH9H`Vg2rV6*cqGV0M94~!?mZsyO?g4wNKk+$4@Q^^ -z7CEjXBxEhr$U!2Pw5jU7A6gIikwV>%eCLU3ev;Cu*t>~3Tdl867qIo&dnMM!JPAI` -z7IHjJ|E993+tRzNp63`O#gxS_m=sm?-s-j79grIu&}i*2>MY)%;8-Q7FfG^J=cfYD -z`6&M$G%#v^r)~fbPJ}w08ElO|qW1UK7UU>)3SgkEaN&V4-?A=0>$LijyC*CE) -zm_V*)0hlEFVhi?MqGDpc+@X7~0h9~aNRYDV*!haYkAq4ekIu*~gw&FRWgTCM#5+tc -zOCCH@sZ#|JpOS+aqIWg8dvjfxg?LZ+@$8`mf~y`9Ms?w!PfRP{W{HKS?URrlq;= -z^1t8*0O5uBiPQPTk0uUinH#Iq5S~*pmve^z_3oGgBxwMB+QZNu7lCtmmTE=g0?|XM -zD1F^9tBJaBo4ZY*JZk%+%2clu_ia%K2TB?@dV~umkmYRW91>l456~13-9v9>?N8S( -zrcon7Pu>>HDH%U7V;%Kbd5XL>2j%l6lGCnb=TdeG%OJL((sq!Az0pDnr}B8fnCK^!@71`72GnBBDm8b=o&;mTetb5Z~q -zSyFbhRMmER^!2&}N!>XXDOP&#)S(>bnzVhaNrprm{vK~E(qpvTPMk%1zEwfUEH -zASXrOwiNtzq1&F<3@!`!c7*S_x97*)7G&-QXRr(XinMyGKrCR -z9#F{7-y!(fd0k9ve<%yN-H_-lQu^EWdl+AsPmwpN+e+b1+%-c^rX6yK_BK>sVGV4d -zr>-2FrG$y*J6rakk2DMb18&twAT=8<^XxO5wjU-l3@F~A@ZvdS4*-qjM+Cxk(Wx(G -zZ3=H!o`0pqYcc-E{UyOC3>RJ*wyZHoYpYU+W?x>2XL4UzG7h7+K4l59y#mc+AX@4a -zlefV^IjTd0O{uSk4KK1=5AuE~{RCt=v^IbyyRLR>564NA(SiIL#JaGaj}XWp@9 -z#6ZS-u8nh?$q<(;rd1LZ6U@4({O&-VaNy9l~=}H9SPXT@)bJ -zd!1@D=PWq!zs2l|m#B@UfJ&s5{#5jjs3xb{U<IpI`fF(WjCvsRfNjY^`+>e9zmS#ZI%*H&`X -zTsj!UsaJ~4sL)ZoiSb-m_Zn1p;6Ha8g%jrUTqCQrG2uaJ0El83sb+z!cgjWzf61oX -zU|4AIi%)n2##h}wc{>rU1d>Cc-u@6v^5Mg~@~-f4pf5kO%p95iDbPLaF4D -zW!+@$WmBx$L2$KNzyqQI5t(bYxQdiXc)(;6vg4KTt#>ZgLCJe^z3GH;!MjRs1kRyGVbs^cKN#Nnc{>QM7 -z$I7IuiED+#7rlpS^rP!*x9&4`zG`h+<;&wMs;j0IoVAy9ll^MgY~VgUyodhfQ4=!b -z!%NiF9&4Jzh)zz`oEl%t&~G5QHjS;OOTh^wA`!^vj+*Nv#X|Jmo^ -zeK&C#HP!F>El;~Mki(9c+I1*2+UJ2ah+(&$)^uFFED#Q_d?3JE)Q2ec)Si=GjG|~H -zV6aim*RyxD$63p-)R{xa4B&2EI7Ao;JKZ~F{XG^E&MjiqUYS+PzL)}|3G&YX(i-{k -zAi;)VQyEjj7`%7lJ>cGf)d1mA2_Oy7=HXq{T2}c>QV@%kN4d1v-1DS+s+4g$M;%{? -zbG&wJwPd?ri8m*YIW;UX7&O)}Api};<~oByAJAaG>?w!9IEySMmPqV5X>D;t<;E%k -zggLszy&u49q{ge%tUvz#{=Imh -zGnh%56fCN$BbdPgq744L%k$rJ(9?ear;?=wvei6!!my9g2%B@w6JAez+#FA}>lICd -z;PAWGU36yHjHi;o7@zU|7=gIAJgK3#yZ9Ay9?q<}x

O)Z)Z>%;_51nj;~%@tF0E(&tE2xkaWo#eN5FK56&I%3?>7B^x(e<=P?8P~ -zS{q^=F9>enJg;F}D^!>&@>QrEm$QWqC;5G?68H#PmG7Ip3I0X({&I@+c|P(Wy@jE~ -z6H9DH3G$T5fC}OZjZ%v~{0h#uc1W8gVG?a4^-=)ov}^kk10-iDOZMoYRh{Cl!Mlt* -zQ>2KxQHc=^0#5{zVQFr0|4^eXE9K*ILjuxxMO7RTe$&rXiSl#vu*sqUNnyrNJ;5z# -zNvp2>fRK2ab~Lb>j2kaPg5cBH86;~hvWvx94Ycg+!Ks+bAzefv6`M%yV)yFgAXXlX4)$41UUryOhBL+l=CPBEW{ -z?dc^Ajn*lyu;#)Lm|uZQUyrf&QBRH7FN;~8aU1qUU!C{#rT4*nc3(h*XKOE3YGYL+ -zwv0iyKP|cft%{ijNqkzYmO=X^!Tqb%_{5$FT1K%3Dt`krUAI-B-ZumI<9nt5_d}6v -zVUpy~;&+@13J917P}skQ|45tULOiQDBbJId8*yBYbq8K|%8x@q-e1sDSXQu1G!6se -z9YbvfWHO%CTx2tIxY|dXP~BS&v3$&|70bE|$2BdbBcR!qJwofP7CyBwe`noI&nR)# -zBglyt?Mb7K(;n-Iu}xQ!vJ{=9l6$5Mu9zKilmvp3D5-KJ^bDn+eYatbW>wy;^{Jrg -z8H1j7zuOg8$&zo8U@0>$l2qN2?#LzDUnp?>5xjf5DJyDbCWfa#|8`^P&SUxokY`E! -zKozOK5(7IOkYg2x=A++3IIhl>xXD-DW6%BrO{li2|9~$0{uJ-J;(`ejQFAXFv6d_< -zPQdKT`Y`@$Nm>moWG+u4n?Bnm8_?ns1jLu;1PBWd6zXf#HcP;}h7YI5kY#|wn0rqd -zA$6rF05up}+M8?YNLd`szWE$T -znNrRD@QT$6_}O4cs~(s`sy3>M3cqMajD2#DO5~r`-Pi?xeEt7H*%F=Sta_W!wBF(&iSf-v$mFZU -zO?~*l^2wNnz>UGsExb@K9`g=jIztCjjPS3Z>fkfbJ9Qx_lUSn8w>VZ99LcAw%XAHo -zCBCZ-Ytiy=%_s;qkmu2b30*=-o|wy}juM%c`F9;01!eFW7NRZrRe9ix)ZfwI(e6hv1bl1X{M5#u788)`aB-r#ePzrO|oME%UT%?uE<@|HX<-`TZ(aB@{ -z1Z`WH2iWW_sZ2)8FRI9w?S|W@<5=qRN}Gi8K2)We>zxa6q05ReS&|{yOJZ;}r{C{T -zS5b4>h|wChLpg`f@Q6T16NW@^lH*&N`)9bH^)^W>E*w5l1u=c_XeyF0e)}@TZf4*= -zKYpm2>6?B)irXlDs+XJD8x!yV@Z;Ga7IY0v1*cR+k|8;J>-ZTAHIzNPuKxfFUXwdr -zx+P>)Q8+6~UiwJ@@$aL@j8r7LZ&6zsG+`{^lGI<%oTA6&>QO64VX}$#Oi;0bD@H3X -zGqC9;;!MkqaZQIvkB00IRxdj9K-pJ=tg{ -zbf&xq3sZ36kiTuF>MX5ride#~lXgj6+G`&x#%tF&-LP0R^RoFD7#YzEyv!QzwG6Zuv8Ur$&cPr-bVh#g^t+h!fwR#)WQeU9Nq{;^X -ziMqF>UzYHz(g_qjERX?Pzrikix_%((j#5G1b4~(buYU|yLQ)7`4>Bll8pqrdc%?ct -zuSzz>JiPa&xOquQ4}=Q5-BWZ}>$@)S*o|$gvF*mTZ5xfzIE`)FYS7rWZMLzKp0r)7 -zi~qgP-s6mOKdHM}J1I6XYHI4^L@Sdg& -z^Z3;EgY@8xMZLtZS*uQb98&BX;FH4_hxY4As_a?ZYcF~=z%c*n&y<6jOXjOMSN@*B -z+JRhVOO2-+6u|vJFAo{FfX>?Mrn(8y)EhWrO(y|Ju9nK)1k`PU^ay77N~17nMM9!S -zcB2j-$5qz__cXK?k-JZ#ukk_wt!75RB#>RKjbO#uW>JeXiAeztH&RX;?VF5TGv&hu -zp?oUH(yPvnTcgcL!6!F%@Ew|vTJr~kQPt=tKD73=Xo3dcPyuSE?8%QDhA^A&mVRN6 -zd-j$A0AJ%uD1048di$8@%xO={ivJ6i0h8$K1(&`272Cf1**L<;x{=cl8-(x -zm{JvcWzI9~HhvLpU&<8|i#}GX9$|YqTO#@)w -z_*uw{7+vcG&&3NnPR;u0d||ZCDL(|uN%c>C+OcFi;ZiKs37n68shFmV<`VvXxEcQZ9WBUru+!1AfW8aUu2 -zwjHUW-A}t28;8z|ipo(Fi&JudL=VSY5fPW}^?7@s+0>_D6>=nZ>awls -z8qgrTyCS%>iOPW%i%zC-eDAApcjn%V8^bWtgNH2l(BD8O$t_`R?uP+|3aWx=iG#pI -zvPOf?<-k9U`pCcX;5F4pfh#0(y3lr8Ot+*kPRKbpASa+*s`RlVO#w}_QNF?@=*_i6 -z8M^gj>HsRnAnZC6WslroijORDW-Oh4$`wNl`CA1fpB4Ai3L2yQp2}zNy~KFcljo3z -z!5W$KmU<6qu(vtdOFA`~%1M2DHNGX0+e)R$6KdBEIvt%ZWxv -zP}p1}q66R?29N25EuM`RUV50jFAK$m-0 -zgms8^0S68;D_rw#A{xBmMl&BU8ZDQ7CO>Vs>6N*=vVPv6wph=&j@jaV+!LK=9vlx{8uexa4<0Y@ -zuAmzS9fLr}W(P?YhTz{X@*|Lx<3q^>_~P>LuB_xbIUWQeM3ShGWZKZpKlqJ;ytx2B -zwSSfp+7A6IY&M -zv*ekeyP2oi{PrUitXZ-*o6bPJuGkt{nY!;jO(56TP2e6FrAg)6ej^DPI`7sTs?u?; -zHltLhdoJx%*Q@rxo~+JUiFKweom*&l2qwGWpB(Pt0$u5RzmqY<23SAI8V`2ZmaW0{ -zZ4QHn1CpPV{ATcc+}7*dr$#9kiGLXE>2v=z)qB072}%igsmv_BHB5ka^@q?@&l;Ka -zvTbhHTcaWk9N09#(ra=O&}tjPT^hAD;VAr+(`pVP6zTL9#4>b&Ios>{UaE+Ml?To3 -zXjo1BX_Wf3tqzXoh5DR4a!yvgHq;57RV`-{QwT3ic63(~?Xm*tU;(>i)Xe$0`o_jp -zBF+YBYGXGI&l84x`RLbN{LF0erS|yzg-S8&0?9OGxAt4MJ_!qkHRGcwlV3t}GcRp8 -zrFCO~(_?6e%TSMEI0)0APZ6mo={l=pn^vk49`gAB%^nsj)0nxG`g_Jcf|T-=Y*Tt8 -zJp$_iUUFtH!%9-LMwB%_HO2i{}rA=(EYQ<01C70(ZwGq1iDFi4gLqU(O#8U(-PO-SkM -zSZQ3fhshBtv`K=jYe<0ZjR^N)hM^u%HmoFxlqr}UdB3*dGnH!wKTm+$>&tR&xtRI{ -zX7_?k1=xR}4v?p4{6>iC>JeA -z&Qp)rSo$cI&Fof-iJkZI>H}y9t@4}Qjf^qR5Z4hdwsE^E8U9)P8o5-yAwV;f2~jHj -zZ^T!4y`LV2Y5RGM<%fD%Z9wSsijafljS%@B)vMdHb8dPCj2vZenb_L2DKUNV+it2R -z-woPEoe2TqD8qCEWwVH^Q=jCis}xFeH|-b(wOkgvY@Dbs18B((`x|oD_!^sn(KJ=g;(T2YRFG8LHvuZ6ws?G&XyEW?M}uyq4;G -z#-q%#6XbEiY&ehya+TH|`4Lp49x?x`MkkAOY^$xIY6g>=5zyW#^v*UHEcx5w3q -zipy(Oln`FKgD{keIf!jwkN`e7o*(1~ILKqaqyhORYhXX@>V;Ka*ZXY#BF1Y -zC70WPIC2b3^n&}^dDB<)&lHnkq{*hqxF9AdGL!VmcZ|1S*hwL`f=##%JW(q32;+#p -zM!>CVMk3@394qa(ui*MZU8?f{P9ZFTgXFWB-iqNkDc}>1qE1{*=f{lXo7d80f)&(stb~OEZtq>H0Y*q1g;L0J&2+%=HN4y*bcrm;8N$!&Mt -zaVXq-FoL>#26UiWXa|Udk(8H$QDiVzIPVtLM7`|Gb{ASr5(vgIB2e$lh2a1Rsy&r( -zth4_TlXER=tN4O!fr>sU@cMmzlpR`-Nn|s9Fv9=r##6^> -zBL4n;C?qVDl}!=7r|>a+0Sxyv#h?`G%$Ozc6i1ED7|uxE -z5@lTuzx)C09$-#ilequF)@cQ6Y$@P^!UAW)mI7Xy6&7{nW8fM)zlp$i46d|(>608rXx8hZFc -zydrU8Eif;s8qrY_r#Gw}6JmAUbMNw@ts6WM37H_N5=-#t3bLY!Rg99&e#Hk#*C*k9 -zxGygBC$~uCZ-y#yeB(X16_XMO)H+}eI7Ob`@Rb2AVS>R_+fWt0TNs&-pE@}5fTGcH -z9UmXAi(8NzCN{azE4-i$oed7l+e>cbrmRFt);&Q+I7F6=m!4v$-yhZ6qQorp?c;Eo -za~8hqee#}#k7uSAHombPZ6NMI>BQR<4i5NQ;VE?V;>q2|lu$RvQX0{)E$-+8cxrF( -z=_H!~E3iTr=e2eSm_nuv6cCVmmR>RbYeN5t2b2)@kHhb-4#A_cK}Ul9Uhnn -zzdo7IaVQ62P{2uE-?jIfwgX6 -zYe`#x+{Ut`Y{V7hK%q`;WKo#wt;|%JF8;7dQu#HX69CRUMLGLJ?r6%^q}Wm=imFqH -zHU|ovB9e7XOEk8dom(XRd>~s09ce=e!NMslj`RRLuYv+B6+J;MaoCPt#GQW*cvr^z -zZ6=CsY4z^jw@YoeiuiCdy^?RRPkWOe#8E37MA_jB%dW{JrUaC36cw|?&h4Dd52Ed7 -zJ0Q`v%*!K!@)MVKn)zI3IWv1R<}MfT6zu&tCnTGnFolsV%U}Xi(cz8YeRApp1U^E? -z5$9$Sw_!Mosv|>SS#trzTi~Z^HKrJh{VXTaXckpve=H=xAheJe)%8?fQpK}E6lInUTn94pgTn<=K!YR -zPynvz&4tD|(&Cb$($_Quaej%wR}M$_tv|5hj=7d -zeP5&4V-zIHIb#TvDnl3T^H~j9FWdKl8=oOi0M0+Xi92Lf<~@z#2UKz?P$8p`%~`27 -ze(l(9B#eiOus|#&(+;ZSfeV!VBApY4Ic=7Vg1Z^*8u5DwTCAZOAZ -zZ0#Ibdkkn>t-%JhceoXgDoo&p_e|U*9kq1pLtL4!Sp~bKKIDFsJLn@J=M~&$H1?ay -zc7{C>9wAM*u6gV$d(Ej8_h4E6S8+R7A$#hVxUGo(DsCSVzKYx97q8;BE&dO2Tj0$; -z(eL86^54Ym_dmq#API!Lzlqy=Pd0g6GcLcx?W!*VLq27T|FyVHGlmiVZ{oJ3jzP&E -z;x_a>LdHME?cQcIzFWI%yBprgqwnJOpym&8JLFZ|wg=e!L)^BD>@Y(tv>+Aa=wdR# -z`KP!&iD(Y>zY({iEdM5MA0?F^QwxG4eHXXw^uLSS+HjOiuj003==07K&`)t2C-U#& -zcEL|^n~>u-ar^7v#chKC{O*5>+w$)J5Vr}q1BHGQw`+^JI;!gjl_e{KVmV*M?QGp# -zIAX@>zlhs2K9Om{|0Zse?kgJqA#TS8zlz)RrLW@l?jPcI!>hPWQu-go?IZ1Dclz8{ -zaXT>=Sj}3D^LKF@rtPP=4JrCV+}`=8xXrEeUEKcsL)?xkfy=9S6}Rg}eiye7?*A%o -zTYLNxw^bE)^0QiA#ce~^@8b5vx1Zv+%AdsTi^N%{U*fjOZ{oH?$g8+bnEr3#cGJ-> -zaodjNPvSPX-M@<4l;6c|$Qe0k$3KbN*xoUED@g!EgMVxNY!D+(r?g2-HqCeigTqe~Q~8r~eeUr(VTv-F?vs -z3RAEuiyz{4`F|9*M_$G45}p4bZV&www+&y@4}TH2wpi?+#qHVkU*dKm -z#CLH!`BmJWk^gsbJLs?Cc2Cm}aeL*5xUK((xUG-M;gSi@`$OCw`ir=IE&E;Ej`<~S -zCpG;hZi|NhUEJol)E)i1xP5f+xf=A}#O)6N?tc@vhxY%6;&x2K|6g&NZSVo``iHnp -zN&IJVJMC56&j0jX+@^c_FT`yjr9X??J->0 -zySRP)hq!I=`Rp&^HVVTJaeL@r#O=x7#O*o;BE>3}zlz%uBY%k79tE%Bwi?TS6t^w( -zUd8PJkAD}pqt0H%?H!X>ak~Ljef_(*Ek^TKaeJfc|FO93{BPp6qWS-=xShU|O27Sw -zxIHZQ-;3L)*JbMeg}7aW{bzBz;fJ`5jP@#SgT(w4xAQ3f2jVuh?GJI==)1U`zsorI -zDsGGXL);GhC2p5p{}8vg`iuN5U&Za+8eDOee~8=dq=CcTU}RXFMd9TZ -zzRdWYIVPT-9_UU24V3lFBbfFcLeMy!Sc7Jr*SHg?GnfJc4T|f_JDND^X;|Vl*rdQR -zTNS@8NLvqY6#b>jb|MSEGNUtuk3x%rm$?+?{k-1J=jeMKzg= -z!R<67pXA$xLTppZqd-)*A$ZQkUPZqJ2mi)w6_95_x5hlZXboo2?j1l;8JPUIZ&c&G -zx*T+E$>Hvq$n&D{ZHIich&t=0#4hw94HR$Dr-e -zn_k|nmubgBN1^No}KTty1m6iJFbGmA@}ip^57@XU4j>P%a7XZa6gV -zUgU|=4({n1mzY<1t6^ -zMGw{-&$V|uI^SLs*m6x2$S#E3DfSiZ{l>NC;-iT0>=oK&n2pZ0Z2#_h)nQ+HthrfopyV5ub?}<}o -zd%L;Eo+RQyv6Lll-MipPw6VM41NX36Nm%J6Ndw|b#ziipDStWFeS-rnuL(1D=)K#> -zGXC29>itBP8Lnf(Fr=9pcR))F!tSQGS6x4 -zP&X$Ol)2YC(Y$~i9?bjE=1ZjAF}t`ds`6QZsoD#gz!u9X5Na2wwK?6=nZ@Aa4yV7z$u;Fx$(nh0Rudy*+o)L -znav_cnqw&Wms9AuJ2pWpjfF6vhis`qJ>c&@FPKY -z^o?t`nRXlXT=P8v=3_6Dub(6{Wx1+;xV+Hh`6LgJ&#yXEh*cFv^L0&>qiP -zpRj5mx2~MEy;VKlWM;R6FK*u?d#HHRNXHGh06pe>dozif(CPtv(QoAK&U6927_^%{ -zELgO*H~-OP7uj1tDLUhgRvRJ+R#K#!Mq9$@gFQm;#tE|ty7U;Mu88jhh)^AJH78zn -z!@;=I>QR0xjkH34{>6>X`A(~Lo!{`ZaDsPG$-?9W5vkAZlWV%;v`{n?L5D^5i71Gw -z3Ex`50)KD2*qp|Q>)^U%1%~(F2!X5jxw|(wNAr!IsWhMx9srhGKXX;SPfrFT+7qPZ -zrx)qL=!@OKLLUMN$^NW(!+QoSv1%uI<-;fcTgiCcxGU7_5_?c33A+zjeDsevQBah| -zE}wlf(pzsM`v&;OY?*kg$og$hy|R4dU$7f)GgFVrz}_g{OVw=FU7=el*o3w7>2fsk -z&326%U4Jz^l3urvaPCXQ$#{c<(Y_hz`s@$S4zwvtyCQ1Pi8np1hh9W>jYPP=beULQ -zZji0d#SLs#O`w{NT!Mp*~ -zS_p+ol*%$(laHS#t6a)(?rWz-j~w>84Wk~-&Y|VFfrHlLEvE{@BrJMYEWU!w-kQL- -z@ytw3wM!|<&3$OLcnAzTPodM+N);l2x90U5XA-He!HfhXMGn=~@MtJ}H&77fq%ViC -z9LSZHu-z%3j=hk!;(5X5-z=V27xOaFGkxR8CAc6d$R1=NAPiEOXn}(=Qxq%g~ATojI&ifWF;jG~&pmsjM8Gxx74i -zhc4CTHORnOd%4QvP*Lkt*6Vn=nlv@p#FD_`s;$#L=0$(?WKrC8Xjvu+9Ie&$c6zR% -zGIxKvfqsnts*$!be%WFjM!I?%3FppQ!}PqbV`L8arR?QZpCTl -zQ~tL!{#I8wIBgRCm*QlQDu=DjFw#CPAhGty)6IDn#}_!2<}aGLp^@n8=8*zAcT2bl -ziH#R1GI7Q59+7SgBOqVBUMRtfOz`@Qfwgx(J@r3hwAK+-fM46VMrW>5P$eikN$MRA -zJ`c%rdNG5Kn}Mshtn*__E1($cp)fs9TFn>(eROhM0gm(sbpc -z8mI*~+ws6hIvU=6XD)Yb-ZAeCTiQ0-Z$hQ> -zgKvmaxvVN49V^o#V5mM6foIOw96YsqT{w5L3GQ>(0+hJb5=%4>SXdN3rqHubdoS?k -zyDy$t6lCxF#hQrT&atHSOQp&p2#_x?_3N}JtDaqHj_5vPVVi*jS?)Q5~IkB_W -z+5mM#Clg@M`@L7C_0SxI&DHyb@7}AzLZli*t-=^^^Nh<~k>o#$PY$Gk3u7uVgLhS(%A8}_YCla;!~FtVG*ANZ0UZlneq -zt}ES3BI@<*9;x5}PpQd;6@~DygN5(7PxOg6MA3Mxs9Kd(qIG+w2)l$3PH1R#eF*5( -z=JpP9S96dom)9JBcw`J|`E_DnaO2~QmqhcnVSln1Fu9je+DXNhz?xpf;cbG(lQoDI -za%g7j!=enc*j5^Fs+FM*76+4MA)Qxyn+53nZtTrI2RS17u~Be$Ns0y3SM(w<9DLm* -zx1IROr4kW22wMYtqsa}BbQ@WM2LgRzsyrH>mC&{%2^|;#x8iw2 -z>u&}*=}0+z({^Ms)M$?P{n7cfs`2-!Og*VonmWaZ-P7h`Ft6TI?huCuoFP@i&XKqi -zi?yl`cYkpo*?EnGA=e~g40ODWLDT+s+ -z7$pKuG6WvskL@^kK%CL{9+O>c79tT+4$Z>=+!2UuqqBoCFWCWRKzigiU5EAZCc4BA -z=zac*C<}5-*;{>tOzs>~6E`iGa9Pq0uLBI5NCNV45M$YY4rXVcUSPr9mZwIqP{9yT -zuOPhaA)QXs9*xh;aaYE4l@H#%_K9YdFQceM&acg^Kg{uPeAB8VN7{--32w0-Ym~8Y -z?v>o`OMWG{qk3P-?GHc6?N7gv+oHKY$Zc`P@8mWh%`3T`2gm{PXL8$Uj(z-ha+`kV -z4{{qg_;+#}K2jI>GEt!u!JIdl`zN`r==K+Ko1*o1a{J|#++L{3itYYIZs!WWss9tX -zZBO$javMeH2f6)9fc)3ww&Y*Q?WuR)$!&(88{yVviA4C{L -z_>=^##eIN=WxXKsEa%~q;r4%mE6W)_>J5iVNWXiPHvz6Ah+>f$?Z$4 -znSy_i+aJAuBez@sOm4@n{y}b2KKvWG9oVSo^Ml+*;`&K$$63CT+e)!^FP-WDs;}gB -z)hoGeTW6+{@H@Hv@H@Hv-tiZ?jkEO|xjjGoN^Zk|H3PwaC%5r;eX<2$*%^NZZReE&*r=b`^bZpTiTfdJv=;QlMQy=p9u#4AHc{ugq)ApAFSd-Pw) -z?f!3=SwVj$w+Ze3N^a-)WdK8@X-$ -zo!rj8{y}cb)4`_ymE4y8PHvl7zLMK-m!s6bliLx0BDb-nSgI~P{!DJiekZqMGyhI* -zC;cS1KmQ`P6{^?txh%h#Lt6GZC~Ks5zcgQW=Fst>px)J8id -zc2ik@8aDEaIUjE^wkx`0rrBfgaZt?W+3(+=b>>?CBILy?=u@yfM9=r=+60~}OZOPe -zXOyXd))=P>x-;2w?a$UwK0^Nv&R+Wg+{abNTZXxks#5bQ`&=&?td54fai7;$2hz~E -z1ljmFycMpe0Zw{;$)yigrX_xz>9%IRSBE%1^*Kg+Z%Sku9&-+&-9u;RT%Aos4FL#~9OMq%hTE&Z4s(0^)j5p}j{kD06 -zZMf^j%h=@jQ2FZi1E#jSBzl^My+4|6H@#m)N$aR55Qzi_9bwXZ%xYHo#_7c|)p{`; -zSYwVTVqaKu^ovyptbMs59d3vDgU8xe%qLWmoG<<35^(_U6G65xEIs0&AA=whJ5czb -zx|hVO^rOVN`=pO5B~r7=ifjKxYzm1ixtA`gjJnfa8M(N$?+wOytnmv);!>Za#E -zN41*>V`-e^2XQoBGh`cV&=dD$>$G@ipnLGyEt1`P4~;e|u)6@Bi&t?3(BI0medljmiDQK -zUQokM%>;xl(r3IM4=I3~Mtz4b#Qwl%&m#RcC4C!oe-?l!_H&5f8V70d>9LF92J1+= -zUzI`kN{kUkr08Z)n}+2*@7Ltk<0oC_6;r8KDyS4Pi(uD`lMpO7&T)T*(wxbSx1a(W -z_rv5yrVWKCGL!ETx7sc+Q1#m_723^ph%I-+2?L1$LGTo|$l1wS0}NyKn&=yOs(^08 -zZLKt9C1yOemEnla?5|xx0i8CEb;B#$zDt6FME2CPnEkaby*lTHRs7TZ}#Ea -zZ~|5%cP@m~h5Vl||7iH*zw3j**A<&rkVnq;H$#!Y)cT~K-v -zkVU0|u~_x9BF809x0Rvhwt5QPivwpbR}P^!A^OWQ1B=jJJNi1>Jp{slB=uNKvI&|7 -zv&l-IS%*P=eIxM+Ga-_YckA3r_(8+?3{$MInZ!!WR?E^kI>6!Kp7Pz}i38TR4k?mz -zdgJHr+~w94V@Ppk+*t~7BLXSh-hE`267-vm4L-p)G2k+QtOMdSn0ZkX@Yi&~qj+A~ -z;}+q9V~i%cUumd-%!3zjqX?%p^nKM?9{0>O3{_)<#z{4aJN?F(ZF%qG1`q8xyhn?H -zD7;2>q+}$jF!F4C02eI9Ka;yKo!v5qc(=;g`u2FBUVqq_0W7B~eetuZ;Z7?S5U{|p -zA2wv0U#Rv!zId;SJhs -zdI6&kYnxvXTSceyhq7!5;1tw*W)%W1@Nvn7lc6CDPV2(~+YoDuoA8mqfyJpuQ$J&D -zc)l7o6jLy=mJT7qbF`v29iDPhmZOch1>pq~tI~=>K@3L?B=ar7!zc>#)(%FUdvS@O -z3#0Wzf*r5sn1-=&WbD=3*v#c!&FDz|qK=hp`zUmmLiH`j!CQgNHTL_>_k9gq=){<2 -z240FYg1}`9%u5}a+A%W~z{K-D;gjHu*2}77D$2ce!3zVXY`os$@c8bFQ-mA2If8Sy -zpE}HiEDmK~U+yP%o%=bTm;}^CYQEZO=~`z2N#A4O+@7r&=)OyEAeQ)F(6ik_>Ltd=0<&dUTv^C?wMa+M^zFgd -zu}E2EK)km+w?9C_jnd$+BtMKU>6}WLKI?F=FNdc#Cv|T<*r&?ds*V< -z;^Fv2^A`RxDp9cav604}Rne<0f$L6YoT;O6MJ>^^clM(eCW)7= -z6*mHl!JR{%iJe|9X2KfqGYg5BMKN1p&y>E7F=vP?t9I4babI1-AD%D~X&H&!+C#&1 -zKrP&KUOrKKg5pQ7uuGQD8g_^7pknu+L3&CSxoJN!)azdEh9Taop$V@|m$<(3EJ?C5 -z*GNP&;E;PQrJ->2x+d>8*D+vN(DRgjM^&K^N(pve-{OD{^t{kC1{eaMs8&G5HqLj$ -zh0P$!?xZX|;>V<-1{4=hjm=*R=4oS4Y`XpJ+&d;>lNNH%72_N9#?7}(Bx>x=U1>kh -zycgQf4NuU~He2!oF#?$5MmoDzB?7vhd#8up$|AhYp>uV>F#<6>d*I2e-fc5|4dds& -zCTyW0Nd(xu?cacqpJMrg&Fya8=I}mA&b(#$pim+xYz-UJoT#>zy)3PeJ%q%5CC46$ -zYxJ!e*&{ZHu`xZhv6e*6G{5S3l?rwtK-=M+OMKXbUNR<9OUu~$CJz1lYs{H -z2;Q@fYfQO_s9tI?SMs@W>zewK3 -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 -zWp5tKoXnyJwRsD$LHXTBSy&v -zAIA@L!9dVvh-s+LeR0&r6k{}LAFdeELjvdhYr2q9dVuIne4XC-rOhKw@~23O>&Sa| -z9_K?(Hm8nGkUKYm<6y?UOIJ1ub=Q*7`I9575nI^0n!azilabnK|=n_kb{8$}nbPdX! -zMm^S^(HUr$64_Wxh&)G$TPz+!(BxY$utY7VueMov2}8bWp_|Kg*C1S%;aO`?*O$RA -zOW_Q!&cSgmIuRN?5l0y7&b5_#;`b>!Ye5P(oDL1dPE+KdU%e>WUx>y`Vb-0u4)=`c -zLo?p}7*hTdalS&ni-Kc=x=tz${#Na+cv*xTf=3edj%(VB6thBOzKaz1IQ@VNMVL+$ -zamm)_S&JslEM}&x$tAr|wN`%qOz~D-^@^5AVNigtaxdJbx-&1*s{o;?5M~^V3z*(Q -zr(Y|nU1d&?JNPsJ@7OrkoV)A`jPib)`c3EL1uT+k&GxLorj3rh%iNWdAZzL<;N>@_n$ -zpJ$wH@7n;&a3W1UXjI+=>NXNAY`;gnPChWyvpCd))@xA@I`mEa&L;w4&-n0ilKckCE>8T>rMXvM+1G1RCpPNCxt!1z}i(n -zz*VTfvj=;9xJnNyI_0xp7nIFSqrY{LG!xnfniC{1{m`rjgXFZy;*#27JaZ!wucldi -zvYZ1C3&3Q31%U>GHoQ2-PTYKkn?*6x6tpn3lv$xAnJes<(MpZZ&v2yE#|2Yk$KD|x -z!;3-}nZgLjvs{SJPLy*<)&LeC-k+>5Tkdn^WOI_GtCO&f+~nuMz>;uuf$U}hJG4JJ -zCQGdb5UyU3vIw};h$L07-k5T4?k1HH -z-*EDQbeJkzkUYo;p+e~E8$DnUQH#yZJ{uE+bR_4WP_3PYbq(8gbNOc2SHK;7OiKDHHeB5@s#jt -zI0_0O`X2eQ*>Aug_oC1xSU@s;q~Yl@`mDN__ds8hcVbLYd^)m!>;x{_>_8=7c6Fg* -z1xe_3W7S6tMDoGjR2*B7#KrF}ai>ZDzGqX6PYI@6u63r^k~M_500oUYdl*X%s3~|X -zC!^_>+|ItTIB%t%1BFWT-wDj8BN@AnUk<*lw-Zi4Y8Iey&>jt{2tI{yc4-z -z;)X5SY#o)7txsn+#fgR_3OA~vsj6DUL>-#GEF9HQ -z^T?K{5?mopqf%13s-?y3#l4%No5I1%vhzs2?bL(d%9_Y%7d)-KY)+bckwvv{A(+(2 -z`_g!NOV>vCp3p|VF}^E3$~-Vll5+?C)T*eh3v)q0MvEOu!U=KIrQw7h&kP*^Y^5X` -z-Hb(ZZ?T`=idWJYUA9$lv)5q&7XWiO5+dL@r&fJv33;u8>)Vj)ynapOqlBLfI!!Bs -zrJ8QkoU#+_Xj?1%_)c4mA$Fgpr#Yg&J7`KjU)@YGu??fIyoU(j+Ij -zbDQTdu0Q}nIX7ZK*DJmHR=fmt&Vc7IMC_TaH=NF*VyQ-$&QMCF`Z_)d%-6 -zb@>{0#8=1^N!aWU5-^BNp7Y$4=RNvhu~f6!_arDj;1GDcI{pDWe0{XcBoQ*T%8Y;RYT0>=7};2&cJJ!*u%)m^mnC>u*MZThzF%|XO{+2aW`{iv;453Oj=V=Og1#ZZDZMB!I>gNL1 -zmuyhvzr>rwRL#Hl1>Kv$`u!_j>6B|x@X@)cnqMsV4!EIR(KaFR1V%HP -zxx&E2uemTg3j&x&^myv~rcyS<2!*eBZR8FlV!XJjRYFsWOq~UIZ;=Hcd?=WRQT56$ -zmEz$N;5V6(XtlnUO>HeUenC0mfZcYhJ4-VjW{p36K*(N9$*n18VJf>h5-9`yc -z=r4ZW<2Vpi=`FmZmZMd8sw6E28O4zK86v;oJM!RBCxnqzqax|uj6_Z;00G0!GQ4qPIHr;|;ViI}rd|OG -z|8SF!b}1e>CTB5*jTt7a_IQLP&$!WJ&wuA -z0be8t-tf?zv%jeq;OMyZ1F%)V&tF#Zl=WZ?&yVx%EoRW0+MK~NrR`QUg$rZy{pq}e -zU_f&2bd~tC!K|UfY4!d< -z02YLdvwa9Jfq?h=5*(mCn)+0AqPnBPra{Cc>S;po&u(6U|{S?B) -z=uD4M@#V(}3$?&eB8&$1+<6x9@WU}srJs>E!CZQ7@$efkJ7EgAG2$I2k{FG0q`v`q -z%b}IlyZV-HEN?2zkj8a2@`F2G0Fj?+Kc3&-o_75v32@C7YfH%9eFHngW>VsCvzkP2U0X3%q -zUdqe3l8xdGw7lx_Gx#>O7uY#ZUn*N3B!HToF&-M;z5dfxlK$3iF+VEof&iS$>)Bii -zcbt;V4jk=au^7$NeR5(YCIk7j3|`c{196c7mGnU1EhJ1ikKp{Wz&FQy>FTH^#^;>v -zXJhtDjqJnRz>M2I9^f3Is&=YH_uBpE2~{h2FB=z!nRTdh2SKafT}QBWmApZ@glL|N -z_9PltX5nR%9t#^N?2jein+vU-*hm~=$JYkdVLf68qcv8=EN -zd92zUhkYl|hjwIinJztwo}M7PJJ_MY@Q)K$^PXS%;N;a)p(CrMg1b;l<2vp-DX6aKk -zwD2ro>1teleT*wX-7mQ6_l*M)f)ocV1QMw@sJ89NF@rW9yfE!+t1Ja8^~PdRdf8)G`y;#z*5ZR3nuM7RilyohH~t -z3dmE9>K?Kuks0P7R_SlpLdOkNKb0+*?U<{ik1cr7`k-&|!Vz2cRHd-`cmf8WSRcgJ -z@z6JwyOHWtyH*4CoQt?_8qXM`+jFRv-1`VsKjjJ>Nb)`amjjCk`J-zjJ7B` -z#Y<|YF|``Hj3^+PiRKrM#Z5COdOvOibEd0MHZ7L;7n{O(tiIc*X_HEIiTW26wn!*C -zOSKcHnEB+nJcwUkUK9tGq&Z<^1HG?B6>-O$pbKP^-T*@ven`TcI|-Pp;H1ZR!|$|m -z!S0gjImht6!L#J8mVW@ZpT8+}oP|S^$%{;MS`BE{mvR6$(4X}`*O20~*2cE+gju~> -zrC13>NFgBTWg`>N2*{V#D6G){USaWNz6d1)!hOHwH4Y3<$_JR&w=%b_E+Zx<^tp>U -zubimuDSETtPP4+;hcQ`xJM=axLQ^WNIAqXA*m^s3B*2zred?!HrQS9TAguDxhoc-R -z1)}_&kIVS@jh-sbN7I!U?)T06TZ~3dKBp*S)Eyi&U~RNsrBOaL+b!`ywh)jCdzFjw -zDy>t1$CzI}nQox>dtb7~LTuR(q)WG|&th9hl&dBQ`BQon7ckh9```j>g_SgP1HN== -ztl84MVMv?1>IQZsIrVgNtUSrjU&^59csFYS!LmTMI69dV -zB&oY0T?$vZp620}vmJ_ZtEGBq^S)Y=54|RQ6J{Dfcm*RDIF4BjEdR|Q+SaTNv>s9s -zR)z8MGEsv5+?oL8FJs5x2{6YvRi>1?DasUNbOLemm>c9qYhyh9hL%Do4BGBeBGhJV -zo1EzHWmDAFNMmpENn>TM)pbF1)O|+Zf{p0IdKWUiyM;MKCya^3ESKSmkoo$FfpBH+ -z5PQEx+nQhI?07G(kyN$XJ&O$X-uD)iNzgrCjHCQa^ZWe$oM%&P`wB>DQ}A4-Yhz+7 -zodMhvV;Z17eL#zvsfhY5c>la=&y-@6ORbZ?OGM{`>b4F;Zvq8m~%>8l63-rSe78L9mL -z!Q}_h)zBy|c{e08f`<;ktKgYN<>yAn>LKL08zi6QlYpyQS{1y}(;MHm6B)x` -zza}G9J6MgJdvdMv*HVkp29$?;xYRLHe|NzeuO-I>@U0(1zI68ADB*uaT!@eR^zEeK -zlAzl03U5WCxfdRZFhP@FPXS2|xK}H!-uBQj;+qPK18Z!VA~_wFp|_!+s?WuuQG)_Z -z245V;DkYGUL?z^Jh7IS^70#r561!^Io*u+*66E|B$vOh71*(S -z2m5(_GV5E&EeYyA#R(bM`N60T`Hj$xcO+Lp4aZS#JLz<~gK7ok?s_w0_mFgr2Z74y -z=&4*OW`3HncOQ|sKn^BX|?EpWwWMyFl;m! -z@X_hBZR=G{b=V@tqdV2mcd&O^H_3?3y6F<`wYLk9UO1cOV$J0`(eFE;kJr>20C$Zo -z3&Z#b+I4iHwo4x*4_ifd?9FCgYA8!=xk)gzG7-r`>mlc`Y2_86QdzZCxWVJdEBv4@ -zn}taLX*hQa6F6z6MZ~-u60)zH-Nd7o`6^R~T-l%zsK8Q!topO_<_JqdfSH{`Y~p&` -z+N=>ycqPWMknWyNH4u(RG621dBjw@!09Mnj$`j7mN6fm7{?G3RFJJ$WE=GX-{dry5 -zUO;YoHuW7xkoYO^Gyxjk*;;!z+~ku~M@fA-g3Ae=Ih4z2g0L7EN@!R|D7!Dl7wYj8 -zEXm~69*Im>X*QzQKH)F>O+O4Sc+xhUHso7y;YAlSdvLyR&wW}ntJ3VnE4?YCl}rH; -zkYt^RyMYsuXth;F6HJ2VUsX{O_^7k5Q~?UyiUc@GulkPrYNjr5sVF6wU;XiO_3uLH -zCaRh=Rg6-wxEPIhPIqgCt6DqXPS58eg_q;*D=s9tyR+z`W>HTikg -zr2q&9$i6l06_^^1s~R;ypX$2nQ4i43u=I!x&M3|?R*jGT$glcyW=Ty^d<~~DrnR0- -z69#Fu&`Tj6^S0Gb6dol#+K_A(jiXHaWP)n`L4CEWlX{^-1Ab -zk>wu?NQ4_05v#dFm*2#AOEF(4{K)XOHnNhZh@ -zj162tjqI^qXah8BLzuPAsw(j33qU{r21Oi{hrP%i2pj)-`#Cnb-+BfXej1qN!uu30F-e -zR-YKCJRwYGFE%1P5%u{@w`sx2F6$ic-D}t0J2XOgx+h$`NbrVsi_5HIwhQEcz4PS6 -zOM;yWNlO8A9b;_(;-NY>57NJp+@$Paii-$CvI$9W`&DoB539}8M>#KCa=e`O>pN}1#NWb538N?ht;P3%WBJivD(1Y4RF5ke^_mS -zqRi@daIu6W=D(~qlGI;Tdx$U}?I~DamtTy}ev^ki|g|^mT -zRy#2>v-n?D8??7|7s>Yq(6PPp=nt#i`Ips(jQPWAt+E623thQ;u -zl(#n>-V|sc#5L9zt4;Wa)n>w%R_FmLSUz_(`C_%d+K0Em|FYW5`tDaDo$~d@LQgb% -z86yN*J+1^ce^_nlzpS>r@IS0}aR_y8xhmlot1YOU6E*g*4pdlNdiM{j-I@I#RvYXO -ztL^Oam(_k~nnp3MpT;v&%6!lNKdd(Ee^~9=X@lIqtakF$A6C0m&~G%5`7f*OGRgrM -z`(Lc~DEA*$`}q8e)t2!3%W6CF{KINjni}X%hl|B><>c~gVl|7P9zdu5)`D)DuK3Gp -zyD;KF0=I7{RDfwD|I2FkqR(k;iLInFiv4A^)3yv*zF2Mg#eZ0B#Xqd}ob5lXw*0@W -zw*9}X_Tilr^&eJSd!Kxd1vJNyOy?g~JNn`et6f?6#cJcQa!6IoVhig0VYTJ{u-d71 -zzCg=Hh7M3EB$4)C8N3CGc1q4Snb0egSbDec6kB7v)LD`jYG`S)c3_|59A5x -z|HEo?0{msQVF)^83ffKnu-dABSZ$rXT)982_L0RGs~u+N{jQZ^_%EwHhx#8@J77?V -zT>HiSFRM*P3Fx&l^V>A1cP8808N>ZQtTv%o7*JSe8Zx6l$7l30(D}*c5fdq?7=T_W -z#jN4+X*X{D7psk7TF*y$0>lXa#cId1{bjYK|FYUvyskO9B)KEvc>l86qON8QH~+HQ -zXac}S8CnjGU#xa3pH<~wR@-&{i`B*{wzY$Bs!E0?4U5$JVzu3r|BKZY7%jm6m(`xI -z{D;-f#02y@*3{2Y#(~A5hQpkls|knmivswE)fW6>wT%P*u-XX0|FYVWC10$z4Pz|g -zPF|vg{H%u}!WXNZsPHeVJrU`;p758|e$xD6wG9COKdd&}A67e4zZB)WqOmvsKdg4; -zpb)QP?d?CTHXz*pWwqT|!53+*;x+q=WqHka|6#QSj{i5SU1RvaSZ$9+mQ?&dtacE^ -zzpS>4+kaSX*{b@0yJwMNBUwAU-2brJvl9QX+TQ=L+D8o^RzJU3?Oc7|*#BX*J4T~+ -zBP*eC8Bg&4WwrHXZAj$GS -ztTxT+7pvXs`Ne9N3+DIzT)Y5h`@?Gce6iXPjY2g4#cB&K|7EqOqfA;?yMR#hk&O-P -z-d|4&VFOCWcx<_x_;v(+DPIDCElJrO4M!Ni#j^1130_sW!6N73P+I@UKJQ!rdHFzNa5U!@+O_Swv0mJ`&Y2=nn;@!FewaDJ)c=Ub{zc}QW(G&v+7)zMo -zxLrU7!Cg5G-yhu|_llzLQS3J1J1zMxZv%{bpjl&&8ncHPaM(q~sU0-x09{1eSUvVu -z?%4oVIqREN_$ZEXMi3}hATmHl)+~b6c!=T;@Ad(~Ir{#siMzZF&bjV6CFylJGf&{a -z6K2g224m$kI02jbTo)7U>lwsUpycv6E5!v|TyD5sA!jUGMrHlOaaCB=1Sm*Kxv)v<6PWrOrZC_UOe0O)@@04PUgWU&#K>C>}-lIQXV}#k3iTlhrilyMS -zUS^(figql*03a$pjhAEF@7?P(-v+{W`+Y6W}&R1nYoYt@UtSgv@(p5 -zsUgI&nG`S#!UBR_Xy3tAgSh_o>Ws0t&Zx4P(W((wEgu+0I0d`k7#?GKAREab*%u{xax#Ls$k4qb)5ttrpt$#04zYsk|Ti4=)m+y}cu8FDSP -z>P%o2KFMeKPxUs(+PemB36Vy}071`%b!aOYrx$=|`WKQVT+H%vEflPxF+!6}8wxuE -zB)tn0zUq>CeD;)bzpj2A3dq~JNfMajydsDJE|m2L4-n?gUDUGiJtUx`PjMvA%Lkq4 -zNf8S-A~?*TPd6T}Rn?uN=pbPe_?k0km8g91yb+jmB_gM`=ZT^%Jt7IYe^)~NK13|w -zkw1a-i>*_`J>CQqSc5O%dlh&&@NuiG`NRyq^&(1)?5uZHPr20nY?)hbx?RG0)ILiD -zwQFP>+W=tzW1R|Ynzie(olx*|TDk*T7-Sl$#y+U!SK|#Y!s9%)sQ{)c6B?cF%wuQC -zs;fS!iN&@Vee}3my<3y$m>+^s6~9J2T6uj*{;Cv|SA&vpOkxGtWD$azr8N&t=RDaG -zs6*N23(aF=_V7n)yyKFe;B3+YgO@(?cZT%=UkXkDr&3ZBhmjl-%y*KTiCW>Re1T=V -zJ-`5M;Kp-{xlA*#Bl%y6!RT%;k)eJ?N<01Mcd=EYy(5n%U{dk|XN*d3Do4@6gIL8> -z&AT7@<4}1T*eN_n#L*Tjo@^Nw5eEvRvAm?cEpF{;F{GmtbQmf20RAM-6d2tp?X|+B -z=J$-PVJKoDF^}7cmL$w1F!NYGT&=bO2ka_WtdXRm4Cw$EcqDsiw|1hfN42&*r@1fE -zS3vTI%F4R3&Dj>)`2yu-+zg$&IV(V>j+n?c$ka09>?_kbOJ1G$snduxsc~Xr1A(y+ -zfTd*-=Vyzs?>N`n)<+{-V#6T%2H!q)P%4wis9In#7fBohOlxJ(Jp`;{w>+{(7K<(H -zk2+2zwO{IzBb_R&NQ*6lVv&cI<&fOSS2!|2xzNX4sRt!LDZ=QyL!^B&HOH3Yj!HdL -zekD_P68=p4IYn-d*=<9s;vl+|Jy|_3Z+&D2P>SW2XbPOxaA^MxFPD -z>&JsTL!g5zlFmE^&v@V!M9hFCjbU52l|kFkcl?7-IWETaUKUr30=}{Yn(HjwO`DhR -zR(HLI3?QEc#gW10_Oc5lMzGS369!0993kt}%jhe4K4#(jW^V6EjQqERyB-K#hq);U -zv4@+&fjwnx-o0T^fYH;KW0LC$gKZ^l*T%Xsw>^0Q?$T2{fJYyxui3TYcE%hF5@VgY -zk3DUC#<|ztH#sHn(+*rXrelOqfpPIJMRG-2r`RgtwiP(r#eytI3T>i}!QswC%ntTA6#b-168Ds~bI&eulfWU=wATy6n -zAr^Dynf>_jN&h~cYJrme3sc(jD2VekPM*%pdB_Vd -zvaKK!_^Rpj3D_57&GH(`GQS7It-w)IeYmN9x+iJpZ!Pq4?#`c>WYL}IcBqmbI -za`hTQ`j{JGOW2NK6!kTlCEKjpb -zVODc1;^zAWP3tU22 -z?N%bdm@26ULyH{`$&+oQfm?riF9K>%<~tf{q${KCN%#^rzw*FQ*N`SR#7RgoA6$+*)jLt!n?3n&kB}k6{YKp{cQyZ-=Y}XWu@$XfgxL -zI38&D+xuP1(r*G=0=X8_$O3zW7Pd%C9HqhRr>i&jM;!q>+t#%hZ$hG^LpTmia#}4o -zl#Z)c62w;-j*ETF%fwHDnDN-Tbw{oDAuep__T6;oyvj-TA1Rj~y>X>IqnUEF5PqgN -zW`-6k@onZ_ec!iXJO)9%Oy(73Ccw7W(WeoyR>S8r+kE3OaRD>48PA$JuDo0jPmyj{ -zj}NBTOif%T$#L{3PE*Rnl1qNjs1eOM!UGtQL>gPmnXL6+PMkMD?1WO~KGO5lZ& -zEg{F&j!cC2^T=%MIDpkm?ZQk=shV}up$exjq=xEj<&gb3?%pBJN}H(&G+-^vK5HPw -zsWXS9&m8oNR1^>>y0naziUAD?NAJg*4&hc0rHAz5CAEAm*62uZnq9J^^1!mN+ouY%slnc{L~l4?@&B1ujdiV -z%WFl3l8T?2hg5~U_u`#?Tn#VX{NB8LhRr5UkcpkAXn|iiX9Ls&19pG)A0!-(AC|Q40bcqa*Z6zBR1y7e{3Rfb!B*WXcxj$2 -z#DjjC!59p5)LbZeLIt=G^(LKiHU&kQV2wyIDv-2;Wi+dgW*c~mT=l7!VH}fMD_m3t -zTmm49#!c%C@PXzoTp_XmZM#i;ce1zc=79?%j6h+j^5yXSpbUuhI6(r-X5gD{+uQ?r -zQbzVu$~otmXQ8n8n5}zgeALP5fHOEgE*YT65p- -z=jI^OLskbZXr|a*S?>jzX#8F{bQQ|dHgPR6eAoD42^bXk8eoAK-X?_cSKYE+|B!>~ -z`R_dKZnNextdt_Qouh~pf^nRn7!1uf9gRq{3O`3{aGGpEE=z| -z&2Y&~jp#rU*4xV7sC&HTfdI9%+W*??9N65Ys;XNoYatn#c?sb;F;kSyyoM3#{)_9h -zL{mY{;{)15rr$|QqX2Ed@-oOQ1%NXh2O$!R0O<)`ZohvG2nqTv6zV}>RN&F{7S`=u -z7jHgv>>C4Cm3LBHP}hi!G`ATnh=8NiDA7Qx_&UB!7E-nuu{S7LR2n$9;Zw{uw -z&;Y;n9kg7At)Yop0u3_!G2DxA0_R1Z@JaP|T{t+3I5BC3F@#HnWXcfSJb0n4J+_Swj4$ -z4`V}8R++1mE%>0{ZBY@$A7BTt5s^R^0Cs7tetAehAi8CVT|Sc6wcpItfH5{fY7O4M -z`$PT!K~`o+jEe7D>^OC%cDkRf`aBBZ3q9COf7cuyIgPBpA8Eoboygd|aq~aVd78w& -zaq2Pd=;xA0abx|2@{5BRv=A0lX(LkK5rKrY+1-fhoHR@myrw|Q!YyGlAQjx9WhX%7 -zIOE;f6T~Wj|51zGx!5Erj~|IvD%?7+Umvdi{5zVIodZpOMjO{Q?+{5;vJ)0nJ+@4c -z9c^-u$Uxs6N~A -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 -zV-DVx3$rxU#L4suyF&>L -zvi8(m&(yc!Tniz}^F-+F^>F2=E}Jz1J{5}DEDp<3&t_;GCuNbI44#PX-l2oT)i!9Y)BGk`Om|vs-PJ2YbytSJ@|0kaa2`IGBQ73K`yCRWrAH1#UZNS!?Ti -zwd>_E0ZgU8xQ`?5yOy`qOWCx<*mrosMjKsSnR5KIsfJz_Wx75sbYLoBFRW{LO7GLI -z8}-V|G6fiR;Bo`#4i#$j^M@W*3)76#y_xZ3tM+S11M -zchDW&VwwGbw)6SxBS3*A@Q|nJM_wK@gk@6B>g1T+m0#6AURTEap)%=utN -zGRIE|RBKz9nlbPW&pt=3sryQaGV`E925B#=;3^m>x?zjg$Ob%z@MXoN&4p?T-Wl#CJ0I|7oGPb-+sDJi~%;Ay~Q -zF}gSA&c?fMhWwO25QeGEQNrB=M`TLCv|_>CbFCViIg+evQ8f}=+cXn=unZq&q+Q>O -zaDzHbnf$W)h=20%nM8@W#kcEKfvy5&o{DN<9Zxx2ZR#-@$9wQVEd( -z+jPKdyRx&vesOZ8(QUP=nqeP7(RK`3wo7FiYp+lC*2%rl}{c~2m9;?wfQQJG~h5n&;TNUM- -zkdFfSY&YzTAXXB{5U{#T&eWMsKs%B6yw}G$mVK@(BmrJ8moR6oPpX~0Heew`WfccC -zSlPVsd1bZ0TFU#Wm45vejlHvAdA#UvM(?70F!fR};BnS~qpW-RpV~`^mGzDIx9&t0 -zb-lVC5Vl&h$Vi}L?AK(P -zu~znZr{lH3;Lo>Yx3)>(iXAcY+e8=KibF$v)xgWg#5+9+w>(_qA$>+qNmG%GI)f3mqKYN}K@-^`p~J@#$^~&0 -z<5(0Zd=+OsIAR;`24p5_r!N}Fx*^-JJO`4Cf&HF-O -zH2Co~2JwO>u(n6bd_enkh5za){3}6x_XK*ZiEwDa0O!6sYIaP+EJrfZo{EJgm`uFR -z`A${Nk;%PO7##XGe2E+U!Zf?gJszk%G!!D&T)3(qd4t^}rB-YVs(_+vHKG`44%wpMt!yH)I8p -zuE4tO_=AiMbJ~~He3X|%X(>A^bpD -z!MhDAc5hh1)v$cj?~xtf+MhoXIoC+0)GcaBg5zSni{z5i*^F%sUWQks!6bc<_?2ss0kp??Ox=?&9<8(Uk -zMn!O!jcc%3A!F#OegW%ukm>Oz7qHqT{H+^((d5wL+~M+?nUtX*`fFf@I#z_U58=`x|e5S=^N&EY2| -zU~U-HZ4BZtjWgTz8_mY)FV~^FkTA5H(Dao)Aa@;s+c*E>EiEEs_%1GUw%jhVeafE1 -z+>Ab+h5RhN?9p-YgNED8IinRMdw$+T;AJ< -z+tL>R63Lyz)LKq9tO#yFFWiaiV;ao!;+Lrjo3|51Qm-!byr)(1iuzR1+f>)C9L8`W -zQ<_3i=sfi(%W7YnXt2Zb?21@if)rT{;%j%OCj|PjbqNC!0jOw9o^YOl?72H+kV@&y -zoR|fvE;0m2E1NrlVh!rvMnF+F|Ihy-(SigFU!2GPyD$GYg~+S_4PIkF-T$}KE*!yi -zO@f_3|I0mG{(>JIIWRK7(7B(T^^dHSGYXkd2SgLL$hYyV7X& -z*-Y>VN7f%RgyZLrUjT-G(S?LKw>1Eq=V#irm&-JTJtgN^QKc6eyF({QN7L~?{w -zccMoTV9b@>&EUZP-LPgEQVK$!#5$!TyXPBDe16Gm8sfw{qzODq9yP8d@-xC -zt(J5?l~699C36(yLlNJ0I;mxVRLJyvMKV@@YBfIp!;Cg+JvjL-C))+Hm} -zPsM$Q^<9T~TcJ77yVYB-0Zekx(_u%wfiARtWdQT0dNbE>4?j~_u#SLR_Rp*fpA7ZD -zYR7#_889~gJ3%1kiS4oCaH?O6xRk%0A*9 -zloCuBJcQ8VFce_Zz=PHcMG?w3bqjA$s@cO?)ytNH9te_ZN)L+NJG)P@Maa)<)dso0 -z+1C#knZ)uhN0JNp{F@3u>ikg9x41-E*cs38vpA(vl*$^LC|ATe)Z^N&Py -zmTSwd*dC@SeQoRVN!l=aZ_P4WAA3+HHiDYTSts|Zct%&J6JG`Qp*EV7{bU1Ii+o?v -zhUdLJ3XJ6V_|tM!B+L*zh|mmh=sn}V;lg$_tl9O!)2IO0YoPL(_L=n;bf~zjr-rQu -zjY;$H$oFG(B)SQP*g|szV7mcZXpL|#XqO&t!i8fmc>JY%&`O#~c)6Q|zP1X=SXTSy -z{9%AAo+P4w{XLG>h|{+aa4^y|L{|%D(`avOP_wB55DPg4tKzvwjnQ<+N7yOP7IB=h -zq=Po*Bt>**^ip1`!1%dnU=0( -z_x9E-Dgmrlek3+XY-@l4EhUmaDTu=AUN^44(66%c`?TKJce6qIsW|%(O1ZS@7A5ks -zfD)poy=My`7bhm`gDLD!1~;@B{;F4J;A0h+Gd -zLjq`@7tPo5rTJ(ZI&`O_p^^{;S#8G?Ld6%mpt~uLu`NZ3&A@vX2lr^GKc{W0sgsox -zG7K$5UREo~`m|C7n! -zNQ}f1%M3UA-JzRtgp|Nr+-AL#qc3;CHeek@^!<0JOCxgAI~T -z$|C6zkd>{H1&ZSY43(iy`j$)cnskYFB%)dKJTH)E+vnw!=q|-D49!ZN3E%A728ykw -z=bk5Kqu`F6`OoCf*JY9=03 -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 -zY*Z!6CIQhO>-W3^ -zMwIluVR)|cJB`^lOQ%b?t}d|xQqZAUok`5|rnSAoz!~*5j1Qk63fe|^HrYO)R$n)9 -zL}*&*J)?;sZr0OAFEL>A#F!?ESapz55WUG>0&g7C-@I`a3<2>lLIL+z3Il6ycV%m| -z1-#1U;$_=Ori!9Q)yp8h1=b%}QeP!9T|2h(D=#k(UO)7bEae$5Q*Bn`3K5!P-rIIP -z&3_9V1oUy53F71MA#}qgOe4-nz=0*on=#MR6-1MwwyNfGpJ7ui?h)%OPaNqa!;0P5 -zD}uhf!M0N{+DH`GUd5&9E<2_=ZHu>;Dpm-!#JGimQeEb!#5pE4G&FcOcaS>1bpK#6 -z1TIjB%-iFKj=8an;v$RdbgHi_&$uM%t21KI5yh~Sp6}}GC5odh4r!ZgwQ;?Kjn#lngVzPix?h| -zB)KR3HW_=F6suMcT$2{?fX0A`j5TXqMNDivpsWdL;}!R4b4%ca_)( -zreR<6MUUhPZmUah86ZKhU8f>s%j9oCJyQ(2V_RKo7&aZvMc6U&fv+z8iN<2lq6XFC -zmf;l!wA(^IZ*}!9&G=?ku!P+*gqvQ^jY&mubsHISSMp%nHL+<4AP;7=hex0ss^i&1 -z+{)7*!~-FF!DyOZU@Cyik$R5})}~7!>9_J-d<-d&)>F0Kw5rMKUge{8AX%e{Al$_K -zM^}&g%H*YK)&hYqY7fQeOV`J4-Dk{v71gxNm-|=LP>n0dX}frp`D)l~;6B~GhtTCw -z5;EgmmB2uQLd-q~e-5LhnvI(V74tb@h!1zlQO*<}{e-5h;eJ14tDb$r$z=T3iKw;z -z*&E+|HgOm=)NlJOwYAfc!;F~fb;y+1=YcthVYiyrbab8;2#04r;NUH~hbZ>co|9gT -zqG-fnu%684qj$8&naeM9GlyUqz}-4<@Gv4~x>w5jTayVj*YH()rBKc5VhW5V$Ugx{ -zOT@>6I2(pdrB4ZC@LGv?hkFNB1I$V}fHXjahj&$KTIDYZLCjYk<v&_x@!YZHlI?!Q-<;g%RJX)n&=|uA2Q(0y>r@GSK!Ls6V{(D97MV=Uk=S$8+~SDL -zjb#J~b95nlUx1f}Vy<$7GQ)i1oo--{sI>}tXU1@*mZxRHUVt20LF_vjdv^M2V1X2| -zRRl}VbtDwknIV%sJBid{H$W))3Zo2_T*%m0O0l9(R^1L162*iy+X+>Zc)0m0fcj4u -zZ)o*}2ieih5S|#-@whjaL=c1WsklENOLduw>pOfMZ_B=lBC*VsrBRnRJz(M<*3Z9x -z{Ky{Y3<{De2J@=Q1{7ccUIt(9^8EMY^z>iAsU!`7WHnDhFwA2V!se9o#I7fM+}xa+ -z)+>qz!Qpq$o7RdEYS}>TlY}vv1H$ITJ>)VrcIUg&EW -zijsh!{=-D7Y!GJmk-^Wj>i6^4*FScfZCuazS9|+V{3XR9a`jatSsF#}6;a8Bm)kEAY2orA`p_c+kr(MgJXdpRLSu#ft&FW-# -z4T5FdnIc7W8x|biMWu&}aZiqk{ugHqS!>{_8a!|f*?$%i}ASg^2 -zss~5}Eojw|AK(&C(~g4IGd4G4+GybtuUj@T&_r(Af|DsK9K2vj;sg08tyC5OK=(IG -zfi@*%m7U6m1WB5FLZ-+zY6)Ojn~{mOqGOM_8<}OJE#dw*E(RgI*;|yT773P+sd8jD -zec3k1zh-w8#EjR?-G=TW?(V}U8BI2gkghf?dg2%e*g{{7Ei?+Z!*#PheR((wnqcJ7 -zN^*l$ufL6MX88YiBpVnD)j%?$hz_jt<-$ -zV`j~y0>Fui(n1+Sa)ht)F*BA0GK;8%D?XJ-My9H+E8CHxFArHRkcqI}P4l@n?^%SC -z#}D!#7vZ=K#=Nz`m6u;_xe>&^&A#-LcrBpHZYUbYqXQ)coc2;qh%8fcr1t$1**BJn -zvhcAK=OfR!$!%>&p2yN355>7v!w$SfZaS;5^b-G~(>Eo!PIpi)RMxCrYjTu|wNkGp -zf>m9dvprd^0_meCkba~g9q-E4k(Jc*JwTv&kRK&%Y0`giMZ{Ji#2ak_+*u;`CSw;%sE&a;!V>x>I@_3i5tKPhnU= -zCs8>Jh<6NG8L-B9SkuX5W^=W-HX*yW9AfzxSu2)x8IDU_@{NFITjmI@w_5mE!~C6j -zH(jH|RgYjHUbH5SJWhSAC&o5j$i9+Ql5&!n+__?O$W{_4M#yL|+fC_D69qAL3e;~mrtaLQ -zUjTWQzz>{|`j!~j>45I4Y-ry4J%r=pq==iG>elqEKhT6~srnD-vd>T1T~}N%fg)<| -zWg?amMKu#J`!YWC|7x;R0}GkblZd9za>)j?xHtjL(_;d-1#k-WJ8GN7;a$U*^I*s@ -zV8fVu4;i6pr6>S37+c({OKizd$anscnY9@fINyF8cqS7DF@qWQzPcSrx5f17ia88u -z#P_=S9LSAQ%>D3eiWTs)!H`xxFo%?9RJjzMXort|l8uVzAJ^Sz1V4ZL_?-1A+NLO` -zao%Ae0M_w~l}L2OM83yVQ-~n$rqynggbUT6p5ma$iD#}~zp!LhROGF3y50Be&pP+8 -z@lKNDR9~}EXTab-F1Wg3m5FI?_MHKh<(`NB38GnvOs$lg)`v`q)?-$^O^8=-%^`vD -z)z!x2RI*KddBgHajRwb!&d@bHkuM(83}QIL4JK>hUqRKuXP|fLichAcL_u%aSYdD^ -zp0X;_CESRG(+s#Fh7^Div36U2zLlR=CL$49Q#) -zgR3$9euIpPn#)Rz*03E)E_}L21Ui}mB%G7v-_qPa!tKnrNm$Xb`9!6{^ueR3NM`u$ -zt&82vz<)nKb(`s{en5y@DSoP#o7pQ<>HzTLQNb5#ja# -z(KGjCt(_2*@)|5mLB}S4n@q)-T45KlxLqf|l5T0weJtp&U7G2pS*;6_4YF$%GF0LO -z@o(#4r^rs76F_?S0$_uqKJ=jl)Ps98Rm&Y+7U=Cl@kzXc#OwyN4;ac+=gH8q4o^V2 -zN&YI%2HI;ZaUQI#)gDJ^Z=`cdn8XS-t!c}+hOAEdlOkCOj{#WOodD&TsCz8cN*h>wY67Eb4%T&K9DhFxMl -z&Vr6QvOdqm=}cWOaw#gerY!6mp -zgXEG*8~`NhyCwH!alZ=fK+(kly|48HcH!HF0!eoiGxDCZ69{wtYp@iOLhyQ!L4mxu -zNi~6IEJO7yWKzt-Yi){?m)!F}sF17QvrauiL&u!jPA1;!3PqVdfe2yC*7DHQeD&hA -zI9mRiN-E3>zI@adL98~<;;*+YZ* -z%p34Bq)yYmt_Kep*cR~Dk2DW3^ZH61vxIB`??_B(C#=9@v-}JB?;VN>PXnQ9Vz@vi -zLPC#A>T`TFW`Qy_TFu-V7;@!pjf%oMqgMF^|arwfa*gn8jYz$;)|5@QIQ}`J4 -zJ!vmAb=%Cv0Xt(%BIN8zJWp1SIi*5nQRAu$E3u&I!~{2}7*k%$8>8pR^QNPSEbe$H -z&gO*apcwlieX(GA^|Xcmy0Xaa1X>_4@S4{rTTo=Pr7dbE1%h|rTEp~FAjmHgG_@rm -z!cpjsY}@+9S)T*?#%YuG;`P6t`pI+zeP0O`KvHq=!Uc1qOH&RYK(o -zaiqd$nCAzAHTH`Kw*zwRmUYR!?-PbdzCYU|;jb&PfL~M#K*%|_#dmy)!)JpS%EG+n -zx<9nX*W(N$$Q?sgCY*P;eMtSfMMai#J%|Srm%L7S&hTvJ{rSwO(bY3PIj|r{QF5?b -zr#MIQCP{;s>5q(jMhUXGV`g=;#62*_8SK*qe7(?|Bwh7?GuEkh%b_bx#yQ2GIi#uu -z4cZ-|t{(12R&aT-z>plNT81n(s_Z7XH#5#wp -zvGu_n)V#!dj^l#tM6>=BOXWOx-t$2E58jrN0+HK_y9A^rkjYu+)ZY&Kx2qym##!J_ -zdQky1sDvc -z8*DTnB3nKrq78C!A^I`Xg_14+315CsmqTKMnLvZg9sk-E`lDxVO-(Si+dQ*MCat3Z -zABoomh{Ie^oyB~RZGAua;S~6xJ$0zd@X!gJFHXQ%L4 -z-A}3HIRg{{Y$J;x@dd%@9905@AqqHQ6si5nvxrf(g0iyxAdsnKwIn_)uLQ9&O72W( -zq9wEw`D8ON4}{MKd3J^nv*CE`4V2OlrpS_hfcN17;Hu>d#X6xa)jOq9b~l5pDF%IC -zVlm3GpyjjO)k$vB)*Fx!`*J&htUH#ij!&>`Td1<6S*Q;bEzasuxc!nq<@mHMW!Sr2 -zY?{gtO#f=IR#+_WJ9JPe=cL`ss>!siJem{YpfF{En*#1&JyP*xoB+@0t3sW0pU^d) -zf9+Hrt+*f)H27rsC)~d5fHGAZXMC0k_|2XPFf1edl5m8tCU$_n6$ZuCslZHr@=sF?s!0?K -z_Qox*fC8}U;Mh;UIy69y9#MsfrXW~Lqj-Tt -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 -zg3X}AiuhWFAX47IU2 -zTR`1(&zJ!UQMfgC;er6Xsa?1iT?>~}SO=FNmKW^l134-fnJ1Bv<|f{{RoD9(JbeAf -zcqkk~969lcSBIK_1Yc&=yjPXaqstDu6!|K6Er;&_z1?QC;mUaaN{PKLH#8QS=cgvU)Auf#U8gmyOca==d!L%lP6y3x -zxw9Lc*}d{;qX`*H(D0^=X~8`Yjzj$4c%78$dW%1Qad6nVUuV%T9c>D3kh~%5Q1Vig -z#C0T?(Z^7k2x4$@J(=KQq`W26{iNk3ZqUT^)xf+gl{S~9pcF&AAkmA9WAD4H$6KSO -zgG2oiLmj(g|tj> -z;caZlm$T=i$L^F0P9I{w|H~Q~vK}kk2@D#Xgn$G;pRwH3ep@Wfph4~p -ztIzP7+T>901sbNzpddL-$g;U=fV3iBGkyA!@(Sc$M5>XngqJ3{Q>F#%;QPetKKN!i -zV`WRRsObPDpiu{JYdxTzWnM9gaa0C8_ek717&pFN2P4rX>Y6p*oV`3%pdx*eOv8;h -zwO^Zt@OXZ=A4f8CZ^S~vdT}$ -zM${9u8VB*wA10Mok9WgOsRKO>vbbf(EM9m6-Z)4uAA5qyJ=o-lW -zO!fh<-^+sjRxRzp}2HV*q= -zv8tNIwXDEm!^^<|CDMo~N*TgE$}$BtX>Ebsf{NePKof+T3%ydxYAt|z081I|I-~d0 -zw^QgxyV1jyvvQbjznpeGUg^pgj_5b|P2eI5+vtR2NS)EbN9=Y}dwRzJ&9#4?{ -z^WJ$Qo({N-cUT8X1h3{_Auy7mSZye%F;@gDoG87)O}x9Y*I6tx2p+|vv*T1MtRyJB -zVwe&RSB0GyjBqlpWm_M2FC)Nnyce2)Lf!SskfnW -z3oQ)mTf^1*d4DgSXOs*j2ED -z4~OuK@txUWv2YTSxbE@33{S2^1$yLog$liQP~q0%7LH0?rzKSkRj#OcT^h6oFhR=( -zEm;WKeM9A7N?p1GxCuvvq_DB~{+GB#cu*8Rt@mq_B&+wXsb!*6@-L&{0$>Uj>E{n) -zE0&8xlanXy_N~JcvcV9i)&=E3kFyjAU3C`VikUvq+I%6K0D3@$zktf1_eKkxZgZA> -zKP5EKMW&6_R=#?DgPm+AmQBFC@S*Vp;=wQS+zJ1=k -z-{0Hkm$%Qy$!-?knNyb<+7B}@0L;d0}*bXYqJ8RnZQZLUhs&%BRll-M7F)`fV50tq+*`I{ND2o -z_sWq9r{pdV=I>gy1w6mzs4Fdk^ZHq-cV5Efgm$2DQ+BvAJcB3taC_FU>k7+*#yxa`PzQ=xO?a -z``5Qbx}Z}dL~u}M6L}3-BT`^|(eNuJ|Gl9uy}@A1I}^V);_vxc@jq}{J~FzUA!OT_gLhu8rTf6jw_ -zeG%oYNR4U?24Pv1L^_pK|GUM%UDP}^x3X8$h83ZKi@NY6j>VVoLn3}#W->vY^B8qM -zV>}@@yLc}a#p=)YmG$I0-|_7W$wdUCA*d2`joe>EF&oHTZ4zZ#`Umj`;zYZBBsgl< -zlE0?Gli(d|MM0PA>uu9_QV|x-N`FB=dNO#A%gm4(8jCkAGq^X;))I!dScx0B6)XK)TsDK#4KP85&aEXhUeAZBL6}Zv4FdWsA&Kd%Nl81?Fr->I -zIn%73Z9UnmM2}8N!9GsZ7!vOdLVFpU)cA{zXB4%qgBit-ER_V%$rXaQSEImV!wHut -zU=&LeJJ+4MgqnOxq1s-5`ZBuW9Rb!+8O6w91S;d~xK9?e(5V>40wU{4p4bk6;6+AO -zcDGaw3=+yB^V#_u0M%dxo!IgXoQ-ICbF_@yvrPh&7@$3mGWjGrx#_%M?c` -z&baw?PED#IpV%C$K;2=xNR-Y%JmIq{eHgxXu!$M%Z9?3jPq1?G5YW?~4MgkB86F!| -zUP~21NR;)EwDJZ{WB@dmOEhB-P)c1}&g=g>16=AVIQiAVRlz_0Pa!}Fgh`?&;++w0 -zh&SkqywC#M{J{WF1ZFfm37*%{2r_&$D(-K)67G=Oe1d~3#E$817nY{c=+<0yh -z=(Ad0j#_M&*R!C5)BnCt--Fgn`etA{w|~3G`TTYf-j3YAUH_6@Y&E67hhWJma?p6M -z3R4}|*eQxp?;F6Fdoz58Ny6f+#(Rz{Kr(2Daq++N6S+{@JcJvgx>Dy1Aj -z;xw~(M11Hi#DA1^8-4v?)xX4z*z<(CyCj0z&G72CuP~+2FuVTfCj0AF->o>)+V|V| -z^*{QN!!d8NasKkpemX?#5e(pXLoL&nGiln_WAU&5{a>>qcQtj7hmlgs{TO)dR@(J# -zliliU)h_w{uUlo`S}aUE(gi*iGefuKw;t<%azJ+|tDibrw>F*^CDyv^!u7iT(h6bO-96HUjZhgYll|}^l -zsJ!UA&gn_~vSV-IYNKXO*rVL++6F@*PLJ@yU_8IRL`9`J@@5u1%+Iu|$UWM<4Gt^9 -z){=%te~5C$6j29=#yTqx#+J`PjCb;|9^0b1=37`?q_O8$Uasrp#FO2y^!EN+XGoaG -z8f?l!7hg{Gh>x33`(`r&psDibB9`aEwQi5NY<;bq -zD20Qteh!5WsI4_a%u$$P>HP@4+U{Z^tnc~>QQQZ4k3oc(PQtGwABkF$HYdN!ICo(k5+#&NV5s-Qn`XG-5EMjJ}n`ufvLzhZ@2Y@F9 -zF6((rZ%1=dbQH|bNL(9B(zkKZnz%%9!^RtyNY~t{zj=L0F>)Q_l4B*u>r=>@X9KD@ -z>|^PAa2qJL!>!K+LvVoAxFGdf(cTU{V;dCIMn=p1@XOvMFMmS_K{mae*B=%i!$;_E -zLFTv}lfUZE!D+^U_o*Mi-dZ$hS;sL8I=7^R^F_cOFlCJ -zW_*$;Lh$?Seg6eYw{|d8p#Yx`z=ym77+5<%1kdIQz5?y7|59S4ba`?VP+^Jb7&K)p -zC$ruY8z-fYPA|MTs!XEfu_#v+ASi0eB?Lu;*?WK_s65@}3LbVc+21Q;0Xf~#^uQkM -zx3&9$rb+%fY_G4Y%Qrd-RLf1G;kfkZVAI_epFlD?)jHL}&3T&dq~wl2N(*+zr!Afh -zr5C^9iopDXSU4iykQm&^SHYL@;dl!qj`|6nbLsKRR$Jf8fSPe>C1U%HCdBFdhbi{ -z$&_x4^+XD_`Qt+y3IF}J?05LHeDUnZQtbHP8~u7r!Amar2=Z$CAtg{S?m#b? -zeZ3gdSC*6oSzp{#cZ^M&;LO43CNNY0n=7!U!IVsQ@Sb=Ia~Reni7T4`+d(p~_CM?I -z)>`_+_zdJeS(=l1asof%BV!M67?L*SQqT7`8+`Jy-Ru&>=25VJyL?&{wcUUFh5btREt}lW^IX?OgYMhc -zm;D-1n*RA$9$J7TYl}bsva^3#r#llcqZe*;Yx^gi^qwT2ApmnhMVMm|DP0!tUpRbb0s?vLQ99oc%2=*BMc^9QBE;;I`{SbCDYGN+EWhF}6jmCtCjU33BR5Av~k -zAFLi+_C{jL{M+&-Xk6zYYXUE3bo9skM1vUC2>LbsHeqvx;pXsqKfKL^FXdN_+AKeY -z@9oV1g`JmU&ygf*AVYb%PkjC56@Vk5zKZGB`MeRBTUm(VemRwbf%?}D0=f3K{}{IK -zYuF_e9`0f(+JHCk#SZ-=cwt|=!$XYo(C>T~=*utsAzlN%w1mCW?<<6ulWwrcgP2{s -zU@HrQcgr85?r?*=6%Pe)Y>mH$UV^vl)Hmq0&?}SB2L~_lN-Wnc-ri1jx(RR{yAJ#B -z=1y0B>xhof7eA-EJBwSN=btC8i@!^+X!TmTfoLtJ)n%V!*Dt_Q>@kS -zJW|=)L}*q_EYGrw8*;Wi|N8tq8y{>ES`Uak{M~w634Wr6r*$-fWYGi+@%k#a)mOo~ -z9!+2febf^7WicU+aB_pp>z@C(=(L5}%?l89#1~oz;k=k4wU#?acsKU^G)WK30jY9y -zteash$H&=ozQlN2DFd0}V8~^I+ib`yw@4+uQdFQX(Y0gAe2~@BLAf8}h7FtAy5d-Q -z+d+6r*mB^M6SC>vj4azUn6P_iU0Id`y_QpU2@+rb-kYg9hzZV~4Oj=g#SK`w^AU7W -zJe8TvXiV14;_o;ID!Zph_z+W>w=hThUF#ve5xWM=0HV$4p1cn^@qGi&6J -zFFEe&@>%>-Wbr2Z&&GI`!B3LHJ7iZR(40C4b3-?Atvn04Zg$j+kz@cjV|3-T3*9wb5a%h^yRvqHfPYIAn|%4&yv;rJ9Re7;nDvtGZghcMk1>6ktYch -zhpxfc@GaX#yBYC@7-_>_Q7T<$Tx_stO*gVsDi8ix{l~#lEYikU7#jil?qoJCc -z|G4a*PrXFYEQvSU=qu0+0D_0^QHrT3jSLu-(LDzhCU4k-gO7GyUy*lTolr|rVrC${ -z4_O+=$bP5MmJ5JOASO+vUkv^^ysLN)>unc@B3Mp_ -z>6>U>3+pN8!qe}=%BxCC7Jz_9PtCiu -zsHVL{W~f1n?L=$q|PWI3%Bs*dzo|nc$VtH!X;b2TnH*!wg<|- -zl{7(bSnDz-6@^{ -z?uqP?6e$Xv0~*;VLh(Vb>D#W1j!(X-aU2WtTY?OITkS{}dR&Zb@I=$PE$$kB&Z -zjw>7|8#j3}Gll0aw&P$&LCDz@P!_J%_korjw{ihJd~rkvpiBL5u@(0S_N_4L?j){+ -zc5CI6yU6$n@BMr#CIcSYuxlvOx=^+NcL1;ex&BeYv+Kj^+`^5mW9XqrE{B^AanWji -z$&ZyA=G)NU^vw4Ll$HE`Q`(X(V{=oG@pK8H)0%G>Txm>(vPTZI>`xVfbUe^^$WK2% -ze@bKuDHq)Uvr*KBM50T?@EU6eip`rhU0>kX_(^6xnSVGd8>ab2SwppKvo(;kvfW(IM -zx@JTTSevl$CvmpFGqhfzG?~b(M%S=III9UZU%{m>B=C^M-jbP11JJ3?M1l8pHTOi8 -zSTi~YI;CPYBapSP#Ol@@b?JVp4ATsRXO=h+L$jBeO3Q|p(K7U|%4vOobY=*s1&Ob?j1N7EQ!~1X=I1Gi)y} -z0Z;?wHN#Qw$ZQurW_SJEgH^9YffP7O9B5As0Sc5QJgn_??+DDQH$CI&Uc -z>Z6(N`b#?sSaCWTk1!!_f+QI=D=N{scZg)>VlYS3@aDI>qjuBXg1G5uYTMCDC&57 -zLfp6wn!ikU82wmP2zQ`z~R9 -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 -zqJqGBoP3|6rkzKJtTnk -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 -zm|M}H;iGCSS@N{Eg%JS3Hy+o -zIBZDO&?F3v`Tn*8UuDgCe~##Vrv}w -zRoYr;0YLfkbhbrY8rh@zvqU#E2qKVOkc}KT1I2U&H0fFZjirl2xSAK!oD@Aql$5qv -zDrq|p`g+*`nQk46)D(L8tCj>2Jo_|b5P_6J-a;iCLm_tp|Cdy{V)I500-W&0gdkrP!uC;i;JCki{Y)Au-nd_q2daYAGh_UtS -z4Bx!#+3S8{*~L2ooY3wJ>>IM6!gTg!AlX8P1}G_SJP%vuH?8dz2F|FjVSM-mQP4KRv&r@Wwfee=BSOC&n~U#Hxdgg6K{55_sd7{^pIdUDsZKUwL_X@cN;bWGT;hnQF5dSBTIY^WL`WY5rT_ -zAfS)aOpqdn51|`2VH$Bp0uC%u-i&#kt{|EewN*8j`wW|EagSJMdE!VX8CLAZUJ>-= -z4Yr+v(MF=c_9`w-ciA!3XSr>!DXJkIn(CDWQGCBJ0xB_hU@{LvG|BUxVCYQOBtJN -zx69YR^550y^W*#y=M#nt-wa#Q6{NLQc|)@=Pxv#bt}GFU@mQZygqU7|<}na0bqdH^ -zhoCIgp~9rp@56>?(XBgqzm#VJ`Wu=XK#^TXJJyHeBy#UUDT>5MaA7!3PyU&Aj2SVI -z%`N4|*|%hfOD59_@rns%T~za1Kas}}Kr1SbWC-^@tQPmfQfr0q994A>;c#aOi1k*+ -z62&=lPTX-HyQK7{HQueirKknI*$K1swt3m*Uy>UjZ)NQvYD{qK<9KMlXC7_C?Hd`( -ziMJwdu>}Ikvg%cQt2Nk@z+_6AchwFx(T5WoDA(eQ!Ctm3F%BxJ&RXx!z0We8Wq%$I -zN`tPiJB#lg#SdHi=8U{mO9gx^I@7}US4$Rq-&3&6TA8kJ&=qE_ajTx|+EAHHrnK2b -zmACaQ7dDqh3rhi+NK5^x&>vAv&Z)r?V(B3n-Qk2KSP{1Liec<9n`MtjOX{HF#_XYy -z)m+^6!JKW~oR~o>n9t7?8W>EE^uR2y)LUO=Je`)u%xsuhpe^doPJ{uTB4p>${V7ib)D*xYSj6yvB*{JL -zx5?Pcq*%3r;0m>X2Q&smWUN`^Dq>>W0cA}{8?U%;y_2pE%F>haO(%>CyQ{=TFb(^f -zFM1?ba9dr1%K!<2?K%}9TPA-Cs+(fa9oy>4!?5XSF2atH4}5j$Pc#;b7B#3Aw+yc^ -zpxqYwd8?~;X~s9Rf+g&hA>8zOZcHkQtJ}zsyOIanu8B=c0C_N@Jv;*CP#w=6;#Qvi -zARY+W3r5rQ0#gB8j?{Z>ur^%+Nxzlv;$ujGw4SQ1IZdq1mPy;Ke~F{ -zS0*n_vla+^QF|yxU%Eba>po-VtEi@BzTCf}qH0`0PTR$+%vZx^1NZ6fJ%lcgl8_ni -zsssia6k_%{_;VN~)ok1}sF=?ILwvYXj&i2>=qEH~4fp#YTlMS{PA22OPDHK!&))d% -zvx&o~p?=$MsjZ!k9A?B+uS2HGJ`c=647=5|rla$;KsY?}0S9ln>hr_0Pfa-gNG3@)4fvG-*j>Mj$<`zd}ZY(1} -zn4`2Qi>IQvg&rAkSHds*-ogM#KX;30n~rOctfi% -zJjjl2hVaCwj>o;ZB!U=}PsRNKS*puaT;JjAcw6>W6p3Z7ERDLn=>Ze>uzvpi<45*D -zXHbw-F_>3XHlP3t@G|&%m*>AHr>Fk{P9Y~y;yzuMzZ6G!8bY6J|2m~mmK{c6+yZ&$%N2=39r -zL2E-(HXWQBY@U~}tpzen1&Jxtj?3CYg_A_SmI=Ivtw{Gxf&@QNxj&r?eV&ihF>h`t -z@x7Mx5`;ot>J5+BG%X{E9N0J^_f3bZL9 -ztL#)hBuLWa6Ea1%QA+^J+Kf!J6&-ub-N-B(Z3*|kaWM$t&EBF!wMejpOqCC3i3 -z{x!R+AZEO7?lyE6ad#g+$!M}^gmkrG(G$l&z!v&qY@t!c9j=@8>C3}e&;%ooF5hrb -z&13%^SdjIm;$x1{mB%rULwRiOYHAygqSTB^pWst(Tsyn@#k4mDa-WWWcXZ(97&B`o -z6#!0DlorYuk|TVTkD0M7kXb}6T=A(yGBQS#L@;sLQcqq=T8g}3;63gu1+TUDU1mY>D0YR|TP%jru -zTFEV!$0ME#o=yH>e*S%kC1i5s?18?%H>c5d%BGzmCl-{nmaJkU>!4LKwe2o;4}7NR -z&%^Zel!kiiR8d${Vh9wkz@@LpSbD3cdhFd|mS^0CebH~HIoI+y -z$rdIF4$XhZs-RMU?Enh}Z;3}E&%>pc?z(tU%Q_?qb@%9%gS$_qu-fl{Nnka~|Q=opkF?HuY{Q}6d -z1b*Oz)VIXIP6u>XWkd7U?;#u)Cq>-kRJW#Q{edP_OVxismwkT9?z-ZF2^3LtFB7qp -zD5{x&*_ZL5|5uZp8d%7bo=iW4TiMpfjOi+qspc5L_2)!lWbHx|G4f(Bl!8_$LFk1(Kbafjq?r* -z0kDo=tVE(KCh|R|nnDC|H?4M~BwVNl^%Mt1PCRq{`h_L4q9SjN)9t=zf7ZE&jdzkH -zr}~vnSZ9=?yYYqvFudX&G -zr;=^z%Nv$YYBV@*bcU|siG1;xW)Q;}ZZKI3{|c%OJ_Ef|S9~%pB?@}W#tMTY@sw4W -zF5$j3ud>3LwESBm3W5#fd9-0dl~95w#&WTx7N$l1ZHtY9dUq8Q(H8uw4sfUWQ0tKi -zAiNqIXM_U@w&5qxx^bvcgT4U`XbY7+j6% -z_ZwtX)Ld3#w1(|aa^cfGBGAzkAmN-O|CZ+d5pHL`O~Q(f%_k}qrVk!PMKZ&0Z(ZzW -z2LAi`soP9n^#elOO7T;@+{|8?QU`z^j|#q^i(M)>rO1K|iP>w%&!DLxui>@*7wGP) -zRO!+wA)|`KS(ftBBLT#}kM1*4dg!(_TGF5iV+xn-{krB9JuX*|TsabxRb$Tt85?ZH -zDCH%pHNB+NOo^1MXGF9~AjQW7&U?$?3K-wwMI+f1i&HS9qvutIqml(+S$Fj@i=MeB -zYwd)fl-FQk3OY9V+hi)v)C#+Z#qB!zm2^vc?qflJ?b1v)&1zkcY>-{Ekf9PMh<{rT -zJ4JTtoB-0p7XTX^^`Q?fpdQ?#sao#nvOsSaicjJlBxX0DeZWwrI!}gt@b!Vdn27w!X#FxX-!+kHDqVd{UI(?*9VC}j -z;s78~-z~W>i~Ch*2Z}Bh=zXmpunXTV6iB+Gn34CKoj{oDUxTHP6oS`-3<~7MO{xhz -zV;QPvA(LVrUTagFyyTt-LWNxYo^|RG8an3Gb~5o+S18K#2}B56ww8yc=BpQ{#nJM= -z&6JO29kP16Of+_RS;wSY(DMi=D`$q>5-J5@msm@PCXe#Sh#vb%frpOg`6D63oeQJJ -zd^@&6r)26i+okC=-mhxMiOGfm_Hh5PU;Ag$%BqiY?@T|y{9sJ4LL!&CSa%2gVBUb2 -zA$6Mebv<~JNJ7EPLo8@1~fA3ICcp3;*6T<~E5fXY_ -zQlI0aDQ_VWtFA1Hq4&t@4_SjYa%O`CiaVz=8zr1-i_}lz6M$WCP4-(!+Y-D_sl{Xj -zK-UvbSome$$TX9jXmE0nqTHF>;$)19%oylEUYeU+1sL@#0A8x9%lh=h8r5>DTXJRp -ze=xm)36FW`&mW(*fB{Cs67MeF541 -zsoQ2Q4%iuE5+P?#;(4-q%qbNriyBv5ScwHqCnmT-#hCJ1-WWYko;MvuWO2tsaW*GR -z2gTSI>5B!^tEVmO-Gh=KT^FG1vTfV8t?sgI+qP}n)n(hZZQC|a{SznV9wy?uhuo1F -zxz~E$&y{3R8}eBofB%(EzO?|NOj>JsW=e!k;1#UmSRg^4_`EV&NW>T+SEG$(`ssI^ -zS$3I1FHHYxW5y8dj5RCw$zf*JM!gl8u4#I2OZx5P6ZO6O%h}cA&qCMb=b4gcNy11h -zu#z2+wIjRAy!Oo2*G_iBh?lYz9Q=ev;RAVs()J;r&?HcWWU48XqO0h3&O>1y>6oTJ -zM|wd%IG&OS|BC0Yw(Gqe!#*B`Y`C%$XaucW!020Zrhv6Y4UB2d;$AS7@o~vn~XA(pnFl#~njVnQvxH#iFZo?#BE2@!Ik4etTe=_T2x-{Xm&6%btzb6TmY0YM@5uBgw*y{r( -zB0)nA|1LQk*6P{K{Ksqm$7}z`YyZb<|Ho_p$7}z`YyZb<|Ho_p$7}z`YyUsbYwxup -zyqoV<#8f3`@A)u(>n@2J%S7d*^J+EFBDRVkh_)gUHFQMc#25PN#xllm`Zlo|7hbj^ -z;p&C8D`8AqnuUcB5~#6Fl8gl;k?RJU`*AO={SlQof|+!WX8;xjp*IEimJ@8BMC5iR -z)SuGmdmr6qT4q#<)dS -zod64%Yy;kQSC&iD<~A%XgOZ&7&C1Rs0!@hK4Ww!5*@2ppT`TDY%)#JH^wKz)`v+fS -z_GBMOk$W+0|6E6lg5Ij!XVMJ>LVi&^XU&5X8h)NepJ2drxAIBA1psx0vU=>Ja4I9C -zFu7Kjxwf6u<6OxlFTpNRDcZ<3^1>~Ol6^2Gkg;9~7Sd*Cwhj_=-?aRGngq-U%_yF< -zGU1D$!oRjyhZBFiHL=I;E~mp!lv!A;ePf|x3e`2MD+ESaDNSrQtSV*D$4Z4vQrdSL -zmt?-F6>MGx9AknL{FMt0y0a{YW>yLivyI67Yv$xu2(QxS!6Yo=SyfjS2njyuqj;Aw -zpk@H4XJ^Y$A2_#LHpjz;IYvMXwFG}tNK4Xa -z31i`Q*7&GdNUMbqJUQ&a7CiF$#xkxg%IbCmW1mV+{w*rS@I4K(i=g7?M5Jv>_Gtru -zm+<=)iPrfY$Mwh^!g#`wi~<)UUaB0>!XqKuQJdo*sZZ-)P2#8iKxH;#C+(|I6s$}! -zJ3S}62q`>aFr&(*Zo6KNN{NoIlKYOU^TwSa$ia1AJIPE~^6|zl)@Vg-(4j|KzirqM -z|LBLj4dYrbLz6{0S486YbsEm4<+ZMCp}&AR=;2`ZFHZXtu>3I!syI0Yp`PrI9BS|4S0m_3;u2 -z0uEPN#W4)Qa^F$_6gcp2KSySGw8f#O5|anc5E#)XS*Dn$onlu)4ZPj*YQ -z92YghmKtZbScU~izD;xk2DRp=zgw7)+&9`2*?sK?o?y!>J6=s3AR+sIUtQyzWPdBlp3XPS -z;wns@oX0yzh&x=$sQKIq;wsyI=VXykXy)-_!PM7??_(lk%3qc>6NalQ^5aq&p}V|) -zKH^fl;U!v&n+R~mhMql-l&F@4Ufd7TVYtS)ZdJ-N@Bjvix&fwYnjn&HHu#PYurv^j -zYu9DR28M8zbcMj)UXos=FeX?1;|QIDPFo>*hp9}Tyd8^yR1(D7fW`*=obi6jaw}hG -zQniJt7^S@IsABM|RbgFHnajU@B&nPHX{#tltix9Zz;mI1+~VAMkYrqRnbMKTu&pCb -zj3?l-pb#PUK_caWg%ktsNxDcXqUX@!oL6;>rYFSqBq!|t0_pqa9{ -zh!#|Pwu+k2)a#1_;z+%bp+vQJAPE6y?jD6{o@IOjb{0o@z7bvQR@^U(G`A`2tULG* -zq7y9>TmXH|Y~k=HNqWquwM2YaYVtS%w4tNoBunKNIswx*nOz}tniDH-82rJaoZ}Lv -zY<~+94{L-5+g+ynJi_h-TMi>{BaN$(%_9IoD@P}$O)+8( -z3RZX|g3n++7I!Qe?895;!A+$_c-Jc%G6(Cz!fK6gM%9YfKLTZl-Y4XUZL>7RNr6o(&ia}`$>CA8L9*)hz=*`MNFZplEn37@$ -zf&TB~{{HF*-NoH -z=lPszM~#4gIXN-%u|c{Y^x5ARbuukuNSIMlDcFDMtFPcIULab)j8qnXO8Q-oosPOO -zpyDdhP%|KUt;f3qeFdt4wcoiFRQNRH0*T8sgl$J`(h2AImAdyiin`?Y%5f;Zz|a2_Q)aO}pIRTFsW -zopS+h4_%0?yzB^R7c||lv6;vMp8WTPQl>nr+7{}#{{<|BuHO9Ai-lBULy3R{uN?JnvBYD15=Afeg& -zCw`q|4#@q=SJw{Ttv;=`ra)uCB>-u**tekpUuv4J8fAc!3^>D!sD+k?xh8%?BhDYi^}fQ!;S<88wX|Juig%sqy){un -z%plLr4Hw}2vMgV1`9(q$jfckdAKt;-P@;s{8PebMBn;NNJ&Dfc^4yZ! -zBG_Qg62q==bLYy+d*ph=Cy=UPL9fS9@uQ`KEjz_?0r)@~n>EHr^ld+OxOw=a4*b~3 -ztg`{2k1q|s6HrXw4P{aq>V#9EQ2Si<@Hk>|nBlJcC!w9?z~AjIyk+=m;>M?@`g^7- -zg$3h7r$4KfF?37WYr_JQhReGAOA+n!54y9KSjC#-SWS8Qj`SiOAfu~?etL@l@vS{> -zMEKiiacZl7l$ycY!Rq-Fy?ZZS?(@WyWCG$Xo+_ef7R6i+wgfE+05UWs&f|^@pxrse3b?xe{gPlM)i$R1!h+S;Gl%TYRrd~_lehcd?NdB=< -zO;WuEbRJ%>f>_7&Deu!2%Da4xDw~eM!JMsH7?Z?;=WTT%>*X^(pV7dd`Wq+i;iZ@k=C?g6LY$%IK)IKP330phl8=FgK -zv<9LZ4BkWjX5fZ@IBH<0-7P?+Akfm^3d)yi@2dW{0g{r|vfln47yTxr_+ -z>HtcP&)uL|Qz;bAtxGopq+r|Y?C8)SE6UkPMcc3@@pJ$j2g@+K>9Mzlq0fClAq%XL -z#M3~}V|5lFglnajYGr>}=PbjQ#L-7vpi`yV8hQTstLHF4M8c-qCY|vJNV%bJE-BGeU -zrqixDppuO&;~iN@Sf_Y%!=~gKogF<>Y}6l*VSj^cfAu+b^x=>p-wy?62i@2pf%_|7 -zG20tm=#LA}huimd-;U9{i>D`NA8%UC*AMgDJzbfO&Ml3%5!$$HR$t4j?e2S@vW1P8 -z9k{igE}I_=!e)-1&QQ4Rt1Hh@*{)6>?1G7nxaX&fi?b`7hY#ncnwr#>o0Xf`JL@bu -z+uYEWgBsgh*PEA@=eMJ)hdVdV!=)EhWm%fjuZzc|qt}`n)l^$FU*%w0CO_CggSJdf}2seFP?a7dTs(* -zWQ?*jQ-+=wuYoRyqJGM@iNLoG6>Gqm8qRZx$lXpKmGkUWJI;Juv&|&jYM7bbaK6nP -z*30((dp%BdOm#+OOl+!81`Kmsx&G*Com!P~C)?y9LABS#NbfVN&W4YL(FZId$It5J -z$h6fslpz}eW5|Vuv#MEc5efj|(Z|GDikYstdR^SOn(MhgZ*7 -znTSmuC=QPdpWW{#+IYItMF>Qkq%{#8;N>tB3|*E_i7{W>Qb}8e)%)qen&?+gAC*t| -zjYpya039=4*NpABnd6SDx~o;#!Ejoced!PvQt%;OO5)XX1fJ+JmH3Sq@QtN -zJ1OZ>awj}uTQeB4qf>O-k)n0)4c^AQZPTt^A3_d@eP$5lAlk$)=<<_b4yu_V=_%iW -zpZ*+kHu#V+>rIC>=C>pq5xU!Z0{aRuJG)L9?j&DbGT<7vBvN1@l@(ciAgLn=Zx{+{ -zR|Tq+OW@1fC;#x-H2>24188)B0fbcV87JkF3!Q1?5}*LiR?lsjHT5rbZJ+$7`kT)q -zqLz6S*~PpV)hPNz9i@uLg~qH*XnkAF2@?O#UP7PWvZo`&5u+sDc40F=Kc;SqdmzF~ -z|7XN0R-&opjiQpUvS>3!k`+gp@!tRL!T^#wwd({d6_@X52^qcekZ*xdoTwh?$0zyM -zfXh;0ewqcQ3{7U5rNUHG_L*v~Fj1j47MV3<&@*sW2aKHcyWjv*)cQhC?2cHH6wt{b -znBaPe;&#=ppA-sXXnt_oxr8pCELWklc_p_ys@m<3pRtEj_U;~N5v+TC%uC1?qE55CCgh~bK_(W1?DmKd -z7}V<|eZdaXkbDHQjZd~>qQxjV+X$7M>na`6KV}5k*GdWekQ-bp12NA`1ol(p$}Ap` -z$467(IS5wYYIgP_)W)R=N|qZ#mY|WbO2&>QDBNoDKeVnP>Kg -z0Ie=E&`dL&=xG%klhc%>?Mf~dhXPJdR9x>3?F1+>RQ%zy$C0~65wuWIOgn_WqFCFB -zw-ymHdVXZ~oJ^4S%9PYXw2h-Dn$z9Ko|}c2Jl4c+%(UsNoojo(9_^qO;uqVM9wT&3 -z>9ZR`HHQcsmhFmur4d$_2!q8BFoxr8m>vCuT8@gloCByhn00-v&znyXx}>H#w8qVt -zs1P~3%)*^;Bd;&Ctd*CSzp(^{n4PM`3Zt`ZlWAB8vpPXnXM0q0>l#UElCU@YcQ -zI*q_QU3w(op$-0FM#DF&BQQGdGaDHn{s~}}SCRZtiX{RY%P>?XqI0YlGuO`fAEF>175#g)qX$yY<*H`udTBcHGX;A`bDvz;0&yn;#!L;pyu5i#XF4eS -z1M?M?L#&H!;6OxeQ_8yXtA`Q=-3>IE0) -zoe?`tSJ%%nCem>oSY|!Kn^BG2S>?Sf=dDM~HGBaP^u#D{=xA=_gWNyS@~yM -z*ioBZ)dn%0rY<$P#2!Iqu5doEh2<22BTBKF2Y*0Kb4MD)MF;OJkeJu=`NDPTWt~UX -zj+idmR_}*nd(8T6d(6 -ziK+NwUT;cD`fWxtJzpC0Q)9rG1SRH*7SIDu67PA=UYpx)%_D(h4lsXR7}ZLC#QCf6 -ze7}x-KiR9IbWJxGN4_Fw2Oi4LBY#_C&6W6gxO;^89M=d2!HmNEJWT;OZZ}bh&+4E% -zxYr=w-IJsW5%xDkmBlUUE4isdii)7U=%^Yb_%28UbAN;_P+okN1144?lG^F)-!^z3 -zBH6snOW`>b)#eOL{v~8jE=2VMQ(-rd!@8KICpR%sSw8`dG1{Z}`UI6oX**(8{j%v` -z7ke*0XYctZJM|q%1}{pziEaet(TmhL5jQEGK}yE__vkb`Y_3bYuWN*AvT(K!m+#9i -zjr51tiVe42D|!D&+RU)bi_zq^9@Fb7npd98YE7A8{dPD4+%gd%is25IVE4C6FAMDB -z*5BYjo%9a1ylS9TY#$Yh(W2V*(sCG=HcBco+wZ+@!eL;UT}QnnL5g&O`9=)^Bh%I{ -zO)}in-(*5mHX>1XmSp@@ail1}f|EzZ%o7h1R -zij%fIc?umGxkY@}jN`N!Ijnhiw8OgdBA=ysH@$skIDCUgprHGhD2!(}!aH`QgU@#} -zSK`)blKX^2Rd-`+Jd@b9%0oOhezj0JdJsejY)G|I;TW3&KmtWUR-4sIx%LXuh~yt} -zrcV8AUuD~(30`@tCqD_#M=i=;&iv#?S&ItkXNYe<*=zbI4J>-^50Do8NtCZsMd(st -z1!nAHhhnY(ff$+)ax#R0UUxf>!OwoG+d`nmZ0JaQ=(AUrwP$S@Z(UXKh -zshxuZs-$MX1tyI-F;@99I4pivxByKbLzPJ3PBX3y3K5av04a#5|BOcfNhRyr77&^( -z_53ofCLrU=!dnaeVSVM3XP(dlw{dZCejgnJwB(Rz#zDu+wd&L|L>?C<(!P -zaz7*x15=zFvHgMM^;@qt-X)U{lNXE(dGH5L*eFo73;xMyiJhg3+P<; -z`3s3M*%5A_c@3-n)Pre!@L^3h`HwSu*}am^^2g(39BUnj#*In;e02ofph`4lRT#%Cxlge -zf1Iq>C2q3fYv#S9DTR-b54cS><=7}Et2g#_bQKt9_@A2?ukTZt6K!mb@X2jqMq)c) -zdCp`o`ugs*!2eF&QpJqIg_PWT=PrKPPp}@ekK-hdeSMOhNE6PH -zEiH-JHb7b<)dSxhZ41deTm{6BLo;R9)BDROZztgw`#1B{8eJ+j1R9a%&TA!_XN`t= -z#3FpJohhQ&Ur)aqeci#!k%oX-_a@>gt7EQ`Cr=r3L<_!aLIq;(Eoz5Ln_b8zPz(!n -zn;@fS3|TQ#D3+`|u}aTuh#9EJ6AhR9Az9WlJ$(E#!{C`g%fLkNzAf7-0lB4n=D5)W -z>MVf5o!#TsPs+8`e~>YR@S6s`)uqCSvo;AH+E4iDxUBPC9)Lt}?}C>FIp~Z3Rvk?v -zZb$R-OV1BD2$bXCUYKA^+}S^8(KBwVj0+TVU^uMpvSHtk(<+G9prD>gI$fzT;TttM -z$z6}M>JJn*S97RryCCEsHREs`1zEMT6Hl!%Q>VLl -z$=2h?ts}UgG4r7@ZWH7qam-pyD8Fx~G9rx{JV(xe^C0ykk$168!;P(y;Syw;QCH#` -z>!MkwFZ_t(kCbA^m5N#fr>l>@T=6rV&Qc2I^KPpynZkUe_}iH?+F-=`Baz-K_NZn4j+BM3EkmMRI?N?H!5**l#!AGs)oh0s~mg*l9*Ecnte_cehY` -zMfGq?m3&blDGl@Qjd02^WBrbK;}OsVWWltU{d+O4?tDIfM`M{I*V35M7NLvm!{oD*mO^be=~EZcqwRI}94#BA -z+m@+|8PNj`fBVaNM=7;#rCCtXq;u$nEJ-AYX^h9G= -zI{|n)$SJ$cv|bpt>rY(hvr!45w$^Y;bX$pE0DIooeT`xwVm)6tne!?4TffJ6+wJ2= -z?S1)t0w}@moZ&wTT4->GXvN;IXryE9|yAaW7=uUae|;wVEBNTa;Cd -z<{&Ih;Oq!KAJ+&|KTjf05_dwoKMCji -zA=nQ5seAa_;8Ejh2-$u`J;1o>q=qe*V*E5s&3$KEn1$P~%@H;&v@hird>p6RRU&8s -zBc}o;XV4^(w%uq8ZAZg~w9k5t828A$T^uQjbpL>JyBjuRaM1{$6F)Jw2sy7=%lBsL -z!h^&b3-{g`F?#6_9-jA3`ua*O26ePQzE$zghj&B7qR{N0V9}pg2HdrXbzg7D-K+plqzg_qf-a8N_s`o0gS@803lZAAK4Cf*oi||58S3 -zS{uw&xwyz&IUFAIlMkRq#)hSHCZ+b;BCj}BMvVD|vRz`0H_|21_TmE22vqwf-Cn-ea<$kQ -zUSN2f#!u`O3u`rI=-wM1g}kvnvhzN40UDF`>?AcCO{{LB81ZNeoi-k0gQ;RA=3mAG -z(|#xh6X3!>;@&UJ%;X}a3yq7i_gbMe5yqb)F?J5G`x8B|cr^-OW}55TU>l*o;)}BF -z_(56tn7OqkyUe{-xS8GGf_)m8 -zI{~Cz=``4)cV@K0iomL9CShh`3g49sHZdE+O$!)DT6hGGo*y?O6wp{6<1oaue12P} -zAy6xJDm43g*V!0NV9kfzCV>WAd1|U-?p<@K1rgV@}Qe>6=Ldct#GlY$Iir7@BO6O>2IbJ19M5$#s4Dft}dXccLO2VSo4aeISAtl|q_~sbY@x5@FgRU`o~Q3>uQhsIJB6 -zcpkv1oLPR?TYHK(o^&~C+FzzjZ3@EZin^|y^^bOYF4X`F@LoD8+~Dk`aq)b8zHuW= -zSA~NHK0!7nkVPLcI6bTOhp3Dzd`UsAR5&(UCUWF@gyIhd?mb$$(D!B+V4!qtAF(xy -z|Dl|K@`nKC*)17isTQHI@#%+M1|)SyTnYonS<1rfL1t1BpJy>!y1YKTYZuvjq=b}W!bu31|% -zYrJ?h0%yEKt14U&w(i}mxZ`_1MhJ~1y;tTmUKw(X`F= -zhWhhb{GJusN8Ze%do8k^ -zna{Fd*z{Txo2V*|=9l+KL+8C=cdD!@_DUp+Q7+qD -zkvMwcx@~3Ue=x -zQCh-JfRk{OT)@r@qYkB`J?}7cY0g-S?#vk7oEr*-9tI-w0At6%x|Q8;Y?9mky82yy -z<}~WC>r4T3J=345?|OFB5hVFNrO0PHA*Tdo5+o+p@++%)^t?u`RVk2tKre*(Kwq0jR{FOxgT}dsKa0sVC7m}w -zRLOa^5QgQszpSDiPztNjxuswXnZPm(?B5Dqbpq$SH`9Fpv&{M0)E%R@^V&-#CN0{z -z6E>Wl;+{>&MQDEeNd$SVWlXq9-rd(%2BE&f1rl(DBw=V4-7AolN*sE%8ZeCX%RiUL -z%RYZ;b$f__`DgW@Ok!ZYCDDvGv8i|-uM7r$yd`P0PyCnc3R&Etx?+?a85yXBTs_C% -z=t(+fznKmi(s=(d7o4dD3TLPDH@~uvf;x3H(LpUGVh}dQSx|kbk|LK$ahXJq%`v#m -z+I16&GW+$L$PyJ9IgymlQ6w9~qCn*?Iq%Y$PtjTH38dxM^;HLQgr_PtjN_8o0aw>! -zTh#+=Xa@PRu;g!Gk8B}gTjl!s(+Qdw%}pVlQDfRZQ(3_TE$L2qcq1U@2!e+x4C)=O -zUs=hC#*j^otR8C@FkpSYVg!%Q7n#&Fe5lWHioLrVrU5_5>P{F`?V|Ne2`s`(EALGF<;$cC>ThbXW!QX#a=;G#q -z+Pf`;$_`qng|2S&O?t;x3nz&{6Qr5*UhG1&t<)RB#KBbzqzG}`t$FA{2=KTk8QI@c -zEPjS|ZpaGitYOy!iREjL2PZ0dmjqH2+6}<)-5i9x(uBG -zBSJ8Qr&ij5tswa1Rqk$qp?0v->{+PsmA{R~*iOyjhnHKD*q);`k@VTuZHqEZoZTrq -zKF^gfefwud)Q_Y+!N0itzM4QOhTKp}-jmu`%1&~wmPZX%0|&scBx*U`AX)|a9puS_ -zCxb^r1(m;Vp}n;-O#a#*!(3{QkmR+8JpoQJc9D{m8rR#>RftlNLOxawhyu|-XaK(? -zs-#!qom{P?QN>NHJXf6Q1F~g5!ZH9{NK>MdhJ$_kkPXD5Lvfjnkw58BNa7+4)nC$^ -zkzNc?QVupPleG+bIGSsy*lGWP4Ts<)mJ>U~F)5c(j69D|_17s2?i^W%DWe#Po -zpFT_JTG7Bn>;!;w?Ica!L`(gSZuy5 -zg+u3|OD^9v+^021TN4k4DWXx^M+t=wxN>!9RUk>Hey$jC-9ljaG%&r{y1Y=b)IdYT -z%E*-Cw{jwf<+(Obv|H#TjCSAJZ{f5&pTF2>W#`y^Uj;}?OIxq$XHt@Faut*Yv;uw} -zw#11RHM>#n`HTfi*q8JBZMu2Ineg>?K~D;})O)?6yU5WzYOJ(boqYva>u)mxF(p~4 -z?X=GT<6Ym^z&UZoW!R07$bEYphRn>s9)-mQ2ANhIJn)gNa`2dK-nso3-y@sxG5P2J -z_}n+&{hoXxrMFwZK6ls7pm&6N_a9U^4D -zP#K_il{h_xjiwt~5^RJBJ7(Lxf;D?sGH7P69@ktYJX^h|tJ(7#X(eL0@P4An^T!do -zqHRMuk~8}~sBSgqlMCmJWvqwN6d4FCG%Q9-f;J_Kr)K%r7C1mVo)l<*|mzM -z>|4x8(M%2D026bTZs;;UD)lot -zOIZa9?R$O2U4CPz)eHg{&=;-q4w07}*a`=J4(ph|Kuv7M@f&o7h`nVt1vLj+cW^@$ -zel4m1SK_{Qr1P_X-dO{xlbsxr=q%HxU55fq2b?KT7%vZKtZpb~VE=PCA$%4(gTp)a -zlEZ=roRbR2A`c%}&{3y0GWPr+kB)KW34+r-G;^Z9~<8 -zutvSwSu#JVVNb54iiB6Dj`?1R1IPLh|JNzndO4^dN`wk^ndHEfub&~^=P@v^rdTWAZhOc(f>Ov` -zCzFlhi`K_SV1^{bm$%-fHR-$-6=`DNs8OuBTj)UDUm5PuQJk`d^MhF2UQi -zN5f363iV33b{%h}!u#6tL1M7M<954q9piIeqtzfwVz11#@?I33GI>7KwXihH+lM%8 -zHP~A`L-0u|i@7OoWCnBK;@ysuOFp0qDwb^)h{VrE08A -z+o)v;XKTAv?(sjKyEr6B6Bx>@O8#Sv6Gg^#-R-+S?(h))t<(O}BoI!?Ifii2!Tf<& -zV&C|U1Vs*<9!-E-Mrs**Nh9}w&WebWx)zBCISITgVP?BB4+LaTt0pCMK!0EB_`vU* -znYgXwaHgBSedbAVVy@WR9YV_t1T|%|Tv6A$1oKn|QM -zBRaW8qU%!o7}~?35pb6O`P?hHLGq*4eyPqAp4W-9jFm)$dv*;cVwG1K0d4%X>wdkX1cPKawiDB#2s-{AL-36)Bn)OB{lS*Lt)SlRz -z!Jd3@@Ogc!#sv#T -z5R*aNqI7)9CNXI^eIJ+#Her&#s;ISET19@i;*MRlzXRsJFk7L@PksM7iYg~7nIu?}#y(0UR9^L@+jZDpwH!gb-IWTh?kG*%E*NsxAPDgdTyBb5P -z(a8wI8)7A}Y6_@eNS&E$L*pDP-T^#I;f3=(Pzo5O22bdxsCD&)Fk>1b{WI+~*lwV% -zpz+|KkX?9R(ny$D$1p`Wm-syQi8Z5JxygLV+WyWR)7+F?9Leh@GygNTBS$0d`_WlV -zd0j5`bHa9^)rwzsru~Z?>%A)2GAc1N&8~3HB@%Q=` -zaRLU)V}LDI+e|n;>j=Xr_n#zo@ -z?&6`;pZQnkeo=ge&tiY{-UNq{YASR&d#%uQeV37|Y6bF34d&7+9$16{iX7 -zyg52{jnnhGYiHD@e5niD8@H!-qsl8aI`YJ*N&|++F7x+J%+{m4Wsvb}0-+bsz)uks -z9XJ)#NA{XtK#_Kdk8i#>I2H)G?&TPsGWLhL*c8Oq2gF}8dg8C0!ov%5_vG5rT$9t} -z;PE^%0>-I{C?YaV0{BMZy&P0a1T%a(@u%7%p}YwRUz7h{FshOeQAoHoZi`61r=(ys -ziyUlgkQb#2%+b%xmHi5%&yX;-1cf|T1Par#nb-ghn7y)nA4!mUaBs(WpOuz8gr&o345xEAS%ll -z!(NL&SgM-&%N|3rOoeB$YoN;mow3QLG5XwBok~Kv;8Oh?))=FWfUaQrV`&kVROyi3 -zA7dIFRfO9ujmt=K?-sD+(<(q2n(OFAbr5(koz_3=cS;X2c149w540)*)0{{*b`Tl4 -zHHa03o6I;)hN#icMty*TTe?ECExILGvG6ib=z^|<@A9mBhIb^FfF12* -zyg&Xes!Js*-uChj^LO!LuNOD*(G$YQl`J3pydKw@(0ARokrW9=s -ztrnBd!4Y*uHum+h`W@-eIy-Ol=<=og_+AxFgK7!P)0ii1F$jj0s$p2wYPwRR*0S49 -z!*-4;aQ~|%yG;pqyH{kfe0{XbhC*1Yz*=Fvs!Q-LpIvz0STfl4sm4Tl)$_(X(;7#( -z&YS>#tdu}s-;}<{@&0`6@`JaKD7*JU>uWANLIHjtBwOKTM*{k${3{`^&{d{QA=o)3 -z`f7e)9Kda|A%RM1?1A$4*uOpmDFtEbx!mU98#(660L6YL6q9+Q*fO9i7U>T_-n<^_V3VEM%ZMlLi$rfl|%f3VXp0@)CCYbr$`=|#7Lha7HW$Fvd#G- -zTRA~}Vs(iaPQ(JBEH>SV1?&@>oD^UQNp&0eO0NUwsbs8GC!U;tUR^w;Qbh%qBxt*? -z6RyUCpND)OT&gsEV#W0C;Au_$;`T5tS;}#OSQo;guWQNt9>54B!Efrx#vWxfqqG?} -zSU)l|F49LjYeZhM^?ji>Pi_|ji$pqcKwqGq)8)fug70#`Z8u-Sc%ZD@IAl)V;O}r> -zT|a=8&3H`i)79F0-)`L-iTe*GE=})2K*=B|DPJA&1fV3-l{4SClxe}bAZ4Av -zWS^dPAi+sfkZT-sVnC{r_N~X6#ObvOFe}s{Zf`Ugul$KxdPkS0;mQlM47uS6<2Wr{ -z;7S)|fGKwx>Ta@sH4hVUel>XSsbxixLl}T^+#%q!wpFa*odzj50nc>BL^fx190VsZ -zf6k=?3!p191xMUjhE}w?LoA`Xb@0`d%d84dXWcQ -zLafU|(KsXy;+f^!p>_xZqpob(PM<7GQ8bV)QZ|@zg#n6rFMa_<_fUw+t0PaP0k! -zAaLQc>-C@8EhmH`=D@1EKP6vZivb`*GQTu8Djg5PvF7}HL(Et#&4_ds=^Y*BFbone -zbT7#ox@PSO5-Re;6I_`mY@SwwSU{5U$OJMHKOBia2^VoAf`TMc%0Ew1q#MS6H14+| -z_A*NXUJ`I7qgzI`&&Mfg!EUmzcMrD03f#2v@0vBwzF(wJ?!zmRkpM}}T=b-X9|ALet;0Ex8^Q)Ue1sm(QC3e`r~ZJ# -z1BB5I%4SX1d|0(3(mER2VhuRb9ot^dW^Lmt`jNoy%6MX|9}o%9%}9~5&>`?95zV*2 -zGN+e9x3q15SQNVa2Jg=#cz4i(?eg;N3;(nl%&SeiOcTxpzW_+v&j6FC%-glQFh*lR -zdfYb~;ElQYVLmX74j%zsw@yyoQ+9Y-abq^)5onc$T~3pN4$l2`J<0TJpx -ziic45W2&pfD9Jtwl>5J0+-6xblUw`?YQKGK-Zpb3$fkx&2vqF -z<0xn%%ekhti({0q_ -zQKqGqDeMsg(d6Avpupy5#Z>mwrp~5G^!_1Kaikm`_7mWDVAK4ql#4ZTfeD7y2~;k_ -zgu4F{gHr$&ZDmb0NsAEiS+i){>x7Z~&jUCdc41KFQ5gy?Az5PR`1*%B)sBmf8S9HK -zO(=`5SWeHHff={B(aI_w?-QFr;(0#U43Yd3gg6CBWAYQY1wSRpwClX~Z%Oi~$W|%T -z&pVqlMUWi(MI}$~hqD9>3K~jHue%aC+-H>(t~D~jJDKej75|{QU23gNE?Z`Y%12e{ -zn!bj*cDe1y(sYRY5kOwg_V*HoQ%akugF(^6m<1p`N(A?y5`W?`E{=gg!K|9<83yL0 -z1Zrv8Erb4g?liVj?`8IiCygxeI -zIOl1CY`AGv6fJMy_b`}Y5~2nhH;2#_NiWC}b7ecnfgR%KhLP(xLY=J7+7g<;x(+C_ -zuhnVIJ)t5$TPlV**wXtBEOA~U(tMG;@F_7d0dJe@A+B;C)zZdVaR&&SVYv3emwns= -z4hMA4u?0iwFouVu^K%w-)Zn@Xhu(KXl_9MP_gRx(Ix@;evn>I!ei)eZZz%K(BW -zM=`yVf4AnTEoJFT0o}G0cUo1r-g5QA(8Ul+WUJ7EI*|Qp5t1dveTZ;nUE1A`wJH?r -z%}F3xhBW2ceEI(Y;6NY0K_77(0S4TviGXP~T$aUWGi^W2W*AVsL*d19$N>Nv%Z~_z -z>pQ2ol(i|mU3vbM{;tKCANQ98pD`7wpJ_X0Dm+guGU18Rmx9WF& -zbQC6&Ep2vD)os1X1?SRfV=15#X{A5a`6H^yDK*$atUV=TIGnKr32Doq7{)7hv-o&S -zq>id>%n=$n&DDJ$E!bA)#0pZydVV3;h_Z`p#wsVAiY#V?W^mRj)1Xm2bWN^yT$KeE -zTzhRLSIwn^L7WDq((DvEiZ?Ny3u&)GX$PKjw^2A@KDRZoO4~&|C=CEn3?rp%KsIVH -z2MT=2rrYGW%3ICaVvE8)uNz=kXz+_qcm&2*{XTm;5v>H0K%w6L5KHpuL%Q;=@Ohvw -zzp&&K`<``>JtgbO6)&<%xiq0(b<= -z7@klhd1U!ES$o+ONjnHGPz!iKXFx>enk}v(X0jbH)`aYMC43v4b9Gdbo?LG_VO;R8 -zk{iJ^?5RBTD6ZhPt{E-^BnaGfZbJ4f{#Fz>#iBd5)rE&)(=l5Fk5Mjsa~n=H7Mm6= -zm=?DJuP|cT7V>$?#k;iPTUfywcFPcMdOdd*6(!W|WXWB~gHzYUre%OUh|!*&fpV#i -z*8puRFMkjZgz5#eX-0v$0WP03cy5roYX(VwY2U@?m=kIJs@`W-wOBohV~av@~6+kocnaP)&YxeeKe|VCSo*rd7T?zM`ONOyH)y#t+%AhRp`<)5Ck{ -zTpl$cGd@%a3^W+T?C+q@VV2Z#ZquM*z6T8P;XygtnG&O)(3BJ&k3(Gb;u}sj -zdNGQkk$}NQGGEWZ(H>_lzfxxoy)uBib>R?UMC^3$lnwW;P;G7zs}9PbTK2^h7)_9W -z29Vask4FhM44cZB62{=Y6Yl}{4y*=I+YjqnjZ-F{;z?=x&)G2JKS`f54UMDit4J;p_Od_*FECWv{HAhP?R!6ZepQ -z{Q3QR@jw?akTfw^R8@Ci01JpR`13B$f6qbB@ClqsmJrBR^W+1=K1L&K$u&=SJ@Ii% -zcM4o5G!25o?_PK96(iNMh1zFHW3_p_}hcjXi|h;J$%j$-v`;y)>+-PO61K -z6`q^RSc|{hyLU>j@^Dho#>94z106s8w8fs~6dSk$rFv^4jEg+y=IqBU5%tuEqBP#v -zYnY0Xf1v%%M5<~KcK1=h&$R3J^VjEJcAI@nXa1`r{xoqk9=S)rbchufrrPf|{eN~9 -z+=HMV9UZhbc6E0}a0BOg3tOsCVXDYWp>|x(7CM~d@wH0eBWzW^Z}KDf7uEaAsnD0@ -z$OH2hh7wOKu^CmzVP{+63NI?)koquQuN~?#|0`8=H0ZOYx|x} -zIC=cw4ss2S`)I^l8$x+`*H#)q_-&4*pS)`UU3Np!FdrSMDB!G@@`b1}bw{4wuTgzt -zo2W=1YY9HeiksZlhT?gw{qaznTP5s3TjZv*3F{#FFD89+f$IzhfeOEduS7(|{mZ -z>L`~BBCQ;j%j1#A1<$5@FhBo1#1gVNa?U`1d>u}s?G&e7ASYI|wAP|yBj=!3F176; -zb`Nx>n9sxZ^pb`~>l9H)xiAEVSK!jqG1WfmsS*2iHOn(?^ScVx~b7pBAfS(0)m9|7bNnu_uC-QC9<%zkz|S-zre-n*sds -zz0&{tp-8qcOLA!OJ5B|K0?Y#_>|euwq)l=mo>iO?OGTWGI4;M!1Ft*h$DttaFX$;O -zE7&9&hXL`9p(+E?7*A`ivY9zt?W0Yo?yZMdK4#X6WnIVP7T3}d&}_>dq4ib^A6uBe -zv+ky6l(^~%B*d%sq*2Fdk91;eBsvHSDL+R(xZ{trP{I24jnRbBjF*3i+GAWM^%L1uor>1J7i`AZIYcJ~a0u%eI(2UA2S} -zgZSPzUjnI7s%02oU6lYo8x3hS0CPxnMpaAU7ww3#Pp(mk{A1dUMexV>?>`oOislr> -zG%hTtoA$(FYwGtW@@e6d_H7L^q#ZoZ9=kdhb -zKU{1~zDnHGrw=Tj%xDPQ7z}-c7wW}R-a$-f=wONw{sgKHJ_Ef|7kn})CF*&LV}-$y -ze9F2^xA0iIcU566TK=gS1;GaLJo+%BODM?`bGg`43ez(GzK5fr++D*$v?aeP1ANtb -zsLjX(@Lf%v6T*Q5+wc=#Z1G3DYvD_xRHL{I8(U-&Y$j$7H33UMY@oW$ay4IzFQ>r4#ket1B{0xQ~${t=n -ze1h$+$(=6U60)i&oE0T6{Um_+_sL^MDi7VaPFor@VJzX2ykF0pqQ~XxQ7cDbvgz!Z -zpkf18j8gSi-K8UP)crYo98{YqxH`YgOxpVuN_iN|s83 -zApYBC*r~D8mi&*Nz5v+Zs1JQ;0sY_sL)CIew-s``5PXv8AQQU*?E```m3cCBtiuz~ -zZjygh=K$?TtnocKTge_r=TG7D$(&uU7~A -zkF%kpfvoQ{2|DxCi(HDTt!YS$l>z`~L-#0T2E*zoj}qZ#e%%&oCLyN{~WD^q!7FTWKiHP -z?s8Ay735@!k7L$@}%j|wxg#E91Hm4d)^1wc|)UtSw^;icO>Sr6Hef -z7LyeKT~9n=;kRWY(@YMc!O1~}awl?&vk@w?VxS9o>+W(DAk?!2cx{?%F{dZisFkm} -z=TP?lKG7R^@K}ca@%@LLUtrO2!ml?U2j15YS?lw-PwOYv#M}T6u@R7+<7btVOySR9 -z@5!#vv~7zB2i%M?OOSIU@%*xODj5|TOB$1&t4xBX`x4BcVoP}~U-&#vnm1iU6mh3R -zVKyg92ff%g;foc!YoICo*MmiBC$Iv6f7gOO@j#KYmUgCD69_(lYxB}ag&e=i$kd*E -z2uGz3*}VGAIiCZ@#%Ysp6Tr3X#n7Lb$riI~G*e>_ZtXnk{5H1s7F>Cm6%o%4g>7y> -z250^7dg-_nil||9@=Z`(jz&244e_)%HXT)B5r%0RtUi=yO1DSP>CG|j^BcQ?`-jD{XKZ7BI;U04ZArRAYZvzs -znKGKQCgo8cTQK5CKHXV;+HMU&aJyIlxZX3*oSfF~IVK-&;ug~!J!JkW@V}#{5*pWs -zBN0BcJpUjVW50M%JD}8VMVB)8K2eCI`!g4ba9w!?{Gxi`LC(D`q2o*9JzK<3R~9t4 -z!=WR-o@N+5?i7kH;j$y@L*>^EDvF%xARJ60@-~+_!>e2N*Q+2#*TDFsz=9Y>&BgAW -z;2gD^EDU0nKQi%|B*&t|EZSz7dSHnQxThj73r0ZJq-J -z0AY3+g=Hy5ebk*8Pf^7ZRVv5%nedXw$=#;1>=aHx>k7en><}X;kOp$1D^sb)bZ$J* -z6YFA5>wP|oP|a>tO<)F_=SlpCkk%k#!t9C$L^ez$TlK7OY54%<3_zO!q0*2}#vR(QFN3QIswV9M|nU2GO8PDW1&vMZ9XRiVPsuIAG=+E7GVLNV9+ -zqzAPi@lnFKAUe^dpJJ(;2G2(x$o|3GQcfUJThU8EXaa?twB+%2*uP!%s0zvgkI}0p -zxJB91lFkV2Ejq4{w#UheZ0R<--WZuvBJws5nZy|(DK$6#{9~ -zhbWehnP-DkTu6S*bfKdQJi@2n)9sMdU?I++h{iv+mEq`FT2m7YcUu-#Nu+gjpd<0N -z0AZLbnzPss;@0<*9!_x|I#S0ry-$D9o_e;}OXiJIajKFWfhDIXxNfCT?++W^msl}; -z>~Er3WF9+wE2ywWC2IoWkbF+UgsIW%L_(}gK>)JuZN9lQl@h!TpO{lt0~ypY;kaiXnnowus!^>FSqRbnM7lUDJ&Lqa<;qbWP{s2x><#L#+_L0m5Z -z1aakZBu1k5p6Q?U@2>mX<%N@OALeS}H)MMN7D>^s-;T#k`oBO$v -zycBpMU~S|OWV#>(os$ZHFhv0+i~_aaX%?}n)=yTlA0#r3oR&<7<&7XVMoFCsMYIfd -zBAsl3<$>(kD9_FSVzwO5y@O5~(iAz;PtZQxfLpb4p;#wOrTU;$F76hHHHDz>Ypf>u -zEGYSG4-JyL?0N$VVxMj&P;|$!)%6KhYzs|MGYjp3p2gWb3in@Z3am4vJDHwkhBa(vf>7(+qUR&{P_v`-X1u{99-8 -z=p_W1p};4{Kg0IL1IkwIobXvT;NN?f&f*q^2d#nx5%d|FL3dS>-$H3Fq~juRN; -zK%1ls39E(rqmBaSg1Q8Y3P5m-WG*+PQjZj9A5A}p#F@fVMNI7ML{JK(H*WGbu|E(B -zFuxP}?Z7m`+i0q*DM}FII`-HK6M8p}0G0C*d$zGQU053r=hwgWEE24)93;l69JTOu -z?IfS*tQ=t&Sty7rS+DrUGkn5WC2%l1kN|8tIP}x64)afwXH;RPDF`;vC{ZARI7=j8 -z5a-|FUBE!yhg`Fy_z18J73EtDYW=6v@9%GLPm!m&WcW4z#IZ%iiQSi1X(F -z3AjX40fbW7G!U*hen?Nh$~y#h1}*juQhX7f$% -z#Xx$5hw`gIW9vz&AYVlAM}<${&Pet^$eYMCz^4QFIR(22|pD>k75Dr3=Z92r4 -zds(qjPU$kDVU;xt6XNX7VfgT2t>1gF-{vd$7@%r0?pQRseu>XAiE^W$BWp=_82b-> -z-f&`dt}}qMR&-!1$Jmxxuia5xUWV(o*M1D;Y0rpgo1;^CU^6X^1ziLYSt~}|1No(1gX}dYm)R;t*oHal -zNs=|60H+`ZZ>}2DL>%h(d^pt_!gE5ye8l$AVMZE#2rGIRP@A0>Ah+}9dJ)~=tS5qA -z$L=x%Mcq_7)P-~Q3Qa1oVkv;`X!0=&?6LY3s|3%=goNvypBv!ex~dp$Z`#rORoRdq -z^0Bv&p^*~MbI!hV%r~l)D1B!$uPhY+1iMPk9mMR$qGbE%q~1<5-Hi6kh&!ig#; -zy8wmC0>+yjEzUtbi|n&&Jh?ot*QP+4#Lq8HGPI=-*US6rPQ(vEIGT&xDRbn(I(t;ji?x7OB)COZ)F#j -z@NaU7WpQ2y)!zcwHY5)QILVIgYthA5V+bl>W6ql)0=OkBO5@znlj(~;O)1f1&M*cB -zGzLe|b%D+x@~ARD1WCe3-%*6^jpQdsD#znJvkZBjXtKapGkORGiS4WE@DVD=U=~A` -zWoy1c*NHV$>-@J=mO08c3k!4zCxCuCbt2fK52Y;qeCw$gcva<=Or8F2zi0kP|IPAakAvgHgYca^!k;;HM~S -zL|t;{$st}wB9?ZzdOIC158|TaUdZIh2Ble=g3_#wvg+;9w~+nrzR~%E<6R8<{RBjV -z+G|H(C0`Gp>Gr}+C|4Bns -z*2EZ@*~2y45&=sDPlOvG61%&`5h?ojbWCw7>8ouf8*Rr#bbtZsa$~scp&=WFeqi0P -zk|YOGo_q_U0eY%)jEaoP1(x$BX$G1I-p&C0p@DLl19sX<(wbDg1&>xRXWI`7r#WI8 -zC8CDhyy8iL74V}Gntc(YbAlGyPHb0wbbr_j9K0yu??3mjonxg)wr42z>g@p*$n8o;JTq!fwV5;>5ue*{X&Bw>xw=Aw&GkO*xpvgv^pGl7uzl4~iZLd+LqTp-emJ3sV6pDalWRoPQfAtuGa*{PvN%2fj=R_KzoHXfE< -zYLn{QP7;a)flqmoT)e;Ih{!fyOVV3x2+#y|2 -zAZ)nt07$NZV0Im9jyHpVsLT9@S9tl1h=HY36~yfGkgdtV$o6IdWl%utG4uRY=Z-_g -z8m6ji#r<`zF@$Dqx90g6aa8L*u-Q~wERRZt>?sMp#nUZ(EKzQD#q5j&5G1KX!T7z@ -zg&itMqtC?6Pg;a~4*RB~ -z4w}ylt_EdJMYZN+>!~^}3Z$C41K=zEnJsWOmoe@(v(mJFlMVgPZBO?D<2vFMGt$Ud -znGg~o05z$RJ#GCsECCPRc8>gQa!ddgmR#UP!CE<^a@&w$O(Y?72HW&u0MrKgt>=ks -zZK_Il&Z}+&nIEa7r%SSxn64G7PMB#w8R4CA<7^h_kSO1+d@IAFWWD%1WG>{`Qqzv4 -zN7buhwp{5A+0FcqdB1Hxg6&^CZUd$Hjnz*(WKcTQo$1v{3Xv#Btl8=w=dDPkLgU)Q -z>WS0%)#t$w%H2tHQDX`%v%e!e60fm}<^HmTfw+gx*kA;+`zdJ(Yy7OEUcfhYseMJ@W({0%YoY!X81K;k+X; -z_k!93=laxy!u!R4o<2a!>2RDehbT}p)H -zhdNFYB9%}=4Wz38c3nsokR2N(T^NEQKfMLnI$^K0*2a=J5lxl$`P72(L0Zax%ECEQ -z(R+dF1eHi6vZuYX3?2n3bIsF{3FvD~Poc}>CMQFc#l>X7KEm*S`~I^(S>qCAqaFzR -zB&N@6s+jfy&^{#}TmK!E&hUS@lC-t`#%HL~hijL~3?NW?#sr3W4pzwNG1d_{HR80) -zWI{)n=Io-~ip` -z)|-$!$~o{}tA0NKh+TUNUSaK#EaAC*Te^RM1%Wi%Bllcv&4JZrcA$@MjZamiItIys`qQZ}dw{nh_A)!II~b)| -z-b0_+2_9v4BV=gi36Cw%oLRyQUEcw$x=hoKu0#pu>vz=wLw=;B&Fr^DzeEXz?+I7e`@5L;#b{1TA4y3pxy>uNC8?_1@E|_|=`DkwcbeMERwjzew$eb;q?yj#`01DB# -zwQ%8v1iWiqw--|jw^LUKmmroGBID`ap5)&tf -znt%gecGa>sjqjt|4z?6|DQGRne*)xoyUCWTp!usM_qyFNmzeRh@@0~FE$DiZ%rC3x -zAR3MX%a88xUAJaB;Vq$#b><8quu#P~iP@Z@K^(NJH+%A2KyR-1R!sb1^V6Z5aZ6aQ -zV=PI-7hz0G?)l;Pi2oU_lQLaz@#ilt4hQ$!BKu{aO}!0rHxv^}-ingEj{GwE7#h<+ -z49=}58(fT(PlS4$w7%sHTA2PYFfUuB-EFO?#1L;N^y1<;`Yz}3-l=KfloB9r8@iDW -zTgvI0mH?YMWMV0*5pZ5jZBc=-kl^_0+wTS~2aeQZ%yv&efodcp8|G$}fE(FJ_eC~b -zV+9PTCCnX_nK<`{(0l@1134;sN2kDd5p`tZN{73lvKWvbpn6bj0z@Q;W2q^IL8Ou%W_tnY_n&jSb`V6nBLk{g; -zVPMJ(3X0Q&EL*4sNGtL+lc%q#u0ZNVlo|<3cpH*CRa!s}zR&FLgKm~PR$Pi@O$QhO -zjX8Kr?TCJsMa5{wQ5f*_k+^dZZhXEkMrKRYGi$LqXL*`HLHewih8uClS9-ePuEdYP!$p-1>K@UK(YFVgWF!ZQhxY*>&YtIq<$Na!vfyEPDD|9< -zYdpEN=9YY-_rbIYlr4dbNtsX+4p;KEUgJE4Cv9lVIUDO;OsivMm7b7;s3&MOjuN9k -zO)0OP9)_FJ0D2tdaEr&R-e?29P>_C8y8G!U%$Ytckl&{YG%u+5n^%>ztjd}TT*iH2 -zCqh0+axnUa-Wz?}0CwS4XIQ`S9AT`lmy=gWm6|Lgw>#2a3v?;&%rORH9*gn%xmDDa -ze*X=#reVJ4s!h$NP0VaE{W6Jw9?(KG&C>y*l!J=(fz6yRNl9x=z;`KKO_Vo{St~p?O}Dy~6-aD& -zIru=yG-A$D#_))8Ou~ -zacZaBepJl8RZ$$>H?VL-=n*s{ShV1n^&_E5;C&jo+n>bh#^;a>Vrm<a>$^UP_0gOCN>gNaMk#yb+7I;RP5yW~LH4i5)d%r(!DYQe -z8mSPREWScwBukNODJU^l1#6rryTM(eyJ^r}EISAh#j3mG6e?^aDZG~kBm!r>XM8*u -zWb}cLcB3C{t9sN2vjvJ0t}SS-A`U)ZW5o@w1t>L><1N%&qDiT@p=t}VH5kSsxL75v -zYQ6|5%GF@^@B&yP&cpCS-KiU|DEk#8iMCB7X%?721}!6u!JMjLpBfbFxyK%f(j|jI -zY0w}K`B)YldyN0$|=_iNY6Mrq`~jDZV)DOjYR-;JzTE)GLZUbNe{ -zE1r-oh6J^)Cl7X4R8a@O)!>H6g*UoUn3^7=0yIehuK|80dh;{5hIOz>`BUWfYB -z+s|K?==NnvhxYyF`O9}KU$1L;|9SoL`u6K%{IX8BFMkhTK0kf=`}OPnefj(C%ipKt -z%Oh|8`E1&m4ZVNeo^l-j_4m!~A2xqggd}}J>b -z{I}L^0nM)k>Pm~?w0_p=UDj|rp&c096c1O2SMWj~ZqEjGU0`{%nyjp>n5u#d6>%7h -zv=1oZMw2(Jl`-8%W$__weCox%O*TF_{b}5J9g#VHSLr4uHe^AuJ4ji={OShlH-px! -z`t7&vo+PVXgUm`x)a2so5oZ -zu`E{KwkP(J+tTCP3v!4ELPJm`=oxvuX<~LzyV@knwDJ$~59En<`zUa);R~q_5XwMi*7q&sS)l2iFLND~%+j04iW5B%c*Z)Cs$9PUS0$=r -zp@3BqHy`_xFv(w&{2)CX=MutUlrj=+7n`Q-KJy4UFXCBPO15KkyT#qJUAXUA(&N -z)Gf5+Qwq)Y{?@nEmFNhtj>afP4kJ*R7RPCXY8ba#TsPKDQUhY$*7 -z0~D=%fD;t}t>qHUH~^H=wpR1{zfAy_hYC)1bx>9CAOE8apa#GsvlH>gh&IG87>c}+ -z0^9b$9-{&rCa@N^xSYB8n`%KN4rMmG(%%?(ZvS?@ihHvl$hB*7u8FzP=v>8Nfoe(Z -zv#Mh!U$hiIMF-zrZ&?GQiBF?+`t9?yLl(zX32>0WrM -zT5Y%YZ@~bk|NAljGiu9Z=tfp^hcEZIoUg9JmrowPT>n~JY%}M7kHKnFq@eLp6;?Vv -z;#EP6df&jsJi76pFiTckw0O^T1x5zbFfRRf{zWd7tmVcv=K(KXp -zL-Ls+W378;3i0`zih{tpBrQDBU*Y34l-!|K= -zF4pXl_y4*#_Nvvgv?E{Ob2T$`U;oz6`tK6Y9qQ(%uGYPe=LI=jT>m0T&QEhQTeZ}D535Tw4t&Ymb)A%W;tgw`?!R9R2=h$A -zwk#w*IVw~;r~FGkIGrnd|IFx_;c9;I?W>;gdG~GKZN~pIH~w72^4xgV?Ge|#pOq7& -za1hncrO*Ynvu1!f%2KR@e}bR3hnNT(yFD-gMtFAeZTCxjtbWelO@17dw+n4^a&VzX -zp&^?yuC^G%MS$=)@$+n -z`_DDsoIH>bVw$$4wlL18pbsX;r|k>N_H?jTjs+<$2Ius@@>`qdAAk5i{*zC}uQP2L -z;{HkG;dxc<&1HQ@JJwH6j_{Ds8+Qb;qL`r`o+m*L{O(MX_C@919qj~lz9J-2f^i=r -zZ00Y!Za6QCUrh}FKUA2IeA<@)h&~xmqk0UB_FFy^D(ZT~<=-Bd-*o0nGku_$Lc)ZZ -zbxL;fPBRG)XlyKAGuWYIR<}y1w6!Y)$0Shv`7OL;>srWYZ5{M8*baXT>vb3h{#(2& -z5q2-dJ4pnh%1DEvq4?W+j}WRHCccB++wP$X96ztf)pNkxy{izJ|{* -z+=J|K`%J!TI2Wgr$aeKp|;}Bb=~T{ncWdQs -zzT(MwT_}OG(?*m34pp(Ep)X9J?)mXL(WZ$a=|F(XLV1x$uigN=O|gTDf0LBAnB|hc -znfx;Tk{Lqq{^Ixk4s>qq!_b5RdOiRi@{V6%>i`KnXDj#ZI}mRZFpipnx#@9S{jBPIvnN4Lf=4AB~ZKoZ)DG -zU{8+Q+WkP$r2IK-?>{%Ue=ty>N^X)3$92E}n|fRP1%lDJ)u|S4DXV-ZBX|5>Te35~ -z?C@;py!Z__#N{7^!V&O>y5L5-3jP?M4!1zvXqXW>*Pg#@t&P2mXc^bmA-4BuJ**wT -z$bAmmg>?eH2jd&r|K9fN4SY?Oozo=C!8+xL4uYZV2E};4&M@@)*wpo@crkz@qba3g -z^u7k2Ozp;4zetfbzx~lx!r#BG`vdVTe|Qa3Ep~i#N1u*4c*mt&L0;`J<^l@#-At)1 -zkA|%I-%aB9{x%cl!ko_PJTGWQmGe*XOA%9?Lt3jcWlkJ3RF -zTpv-p?CEAiUqww8Tzzp<)iKU&f-(oIo3T&i0K4l&$6YdFUQ~HcJ*aK$CDgBiKK3 -z{<>Hwg>CfbyHkE{mK9^P+)l@brocbG=WR!{<_)(x{+U1jucF2*sqNE)n;)K32TRM- -zt@g_g?`$^rZMMY0BkTKhpEdHmFNU6cZg;!Huz42judZK~MQxA2{lb3b`xYnn^Zc%l -zRg>=f=cm0JS(^Uyk219YN7fd9{$bz#X@l-8z)aq^QP=iY{?fnBAYQzO2d|PK|I|zZ -z7&-CqMYG~Afu!HZ_V8;Pd;f9wMU^Zd~FZQ%Uk)1C(2X^zNb6^W&(CU -zf0cvMiw|A1(XR4Z{^R}(UfL1YgE}|7$j|Q-3X4e{Q&u=BS7Uw+~r5;fpOYuK;)dPNX( -z(~XvS5VDIOILX4~-Rg&EJKP~|#g76uw#C23L6WzRdFU`|p;soU4?eucPhz?5@&4t@ -z&M*O?jo?@` -z`9l2sA-6R&!G<19UI=5)2 -zAL9mxO=VpPtbFPqyd-To@Rc*F={}1rZW=_`gOjeT>w!_rxwr($um9e=xj6_4E}jiY -z2Ytc~P`UFFT%$xP3un<-tXm}BaSBupPm%8-<}Pn#f%dn1_YahCC7WU!&Lg1hx}O-s_7tNq&jd_tmKdao;hn$4aW54x?Z+tFrpy&dgjiO)BJZHY?P13_`B>- -z^!u2JsK`fIBv2T-CS&72;x78lcsImI8~lnw>AK@$heKkN3smq6;Hqn4Y$xgK6Gy+p7qNi^H(Phc4U0uRHZ)KXCv84xOCcn%^=KCg!WAJe*i -zA|HM_A(o=N%m8{Hax{*K<4%(u7vPq_OPX81Sp0K&lSB^bzDqz6tgF;bRj+`sYbQ%N -zKV&&?`U~+j;A&Yz;5eMII%v&6ex5oAb&t+FHtuwaEFdhDg;l>3#%t~ZC|$1n39TCl -zTyK`&#Sf4q>TZ;vZ{G1DUHWrKn<}Ssn@!aNQuj2^oKD9j1shw^*egQ*=5aN)#V#kW -z`@#WDRG#Hck3mNl_2i2cjZl>N*b({@$YRfwj2WOku%8*t$B)1dXH)`Xv#3p`#d0fBYy#B)iPX))Y -zWzbj(3@V2B&sFgZ2v5XEk`@9t*k{p5Ip^)LjMRQ_Y@Uwj_HG+Kt_q^uNkESCO6v-Q -zP{-j%v-~4sAySzuz?1M4SOAnW<=gH%%MYxrt?^^;4Abz>YoGdXTlHPn{ota5#1>Tm -z0;4mNsSBWF#s!~KyLNZZipe{h^;otD2F}rBl9?!|3iobXc2uA!a1NMbqXxw{Mos_N -zl`-%sPqjSYSErYzV;-J;K2|waE|)BaWB6!Mb>!zuM2ZP+#0{GHb;NeS5pnwY2V!fO -z%D`PF3o|) -z4-Z@Qh#=nzlX@o!C3IM;+}u?`Pxu&?Q!g3l(2hexh17+T1$Y2}1IY7_7M@)nPUjZx -zoE*alJ!(00I)p{5`6WG8X_)WhaMy2sbYQIH>$}>HY#qD1VvOfo2v_a-hS7z_WGM&K -zK2HTbsmxE5;43++JPqXJbvo|GB(q`-Z!W&@P8E8 -zd*TbeT=mu)J2yTqaE)^>7+*s&Uw@)3G6D`lzANZ2LgKO{nvhd1IK -zYo`maZjY8@yP(y?Z6Ir~-lFW-!Wc?CC83=Ob8rVLSyVR|LROvIN`$hUnRCIo-tzu0 -z%YLa7*oNjIep?rX|po^Ag=# -z`}yKV0Y{rDO8h(tpBQ`m{Ph?8twirzzaE$-)(8h#EN+Z+qH;|VwM`uYBH0WYU)G^M -zJQSVa+BxRe041#TF?|26+wORlA6=e29PLJ?PTbeKar@SnnuR27p -z=h^Qw4h}jNzR(Y(AUalj4=TE@Ovht*mOyrt5tncv8nrApvH{`cLxQ@NWuKpG$Wl{R -zoRflV)_0;;gRltTupzsy8BxR4W+?p0o9(|Dd+$)1N@UTa>o_1>^aQ)l;K~=0c*tSz -zNzA1Q=-d{Xz|cMv=cP?x`Nu -z?S?vxej0Ya3Oq4GN3eVTC`o4uOUxyfYsl=Jlmx}Xo-3umjNJo!Cfc$#>e%KR+qRt! -zJL=fB?T&5RR(EXM=-9UH#XMf*5f1<{yQ8n(zCS@Nq)q=A^Qv=p3(L>C- -z{h*iDBoy?yrt@O5y5k+n%OjRgulE=}XQ5$oPZyW|8{Cc?*@SRSOl-^X!WQohC1RrD -zVseQCc_UHK4ZW(RhP4?`uS1zA(Yj}mplWprt -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 -zBYFyQ5XaZWTi$aKM;BMg2%Us -zi*s9?Phe^NTVWtlG4wv#N1jK>z+ffl@4dNJ6ImJL5o>~nQl+{jUBaQhWYJs-y&+Q0rVw|#?dRwhJVt2i(pO~qv;i@{CI+SofRMTn$AYGxkF29N-6?0fsq5@iHZVW5(^1byXr -z2+)6&m&a&=F~k4FK`oZge-(#U!y|qO9)O%XE>#6xMOFSsS+i(VV4FDs>JErlcIu`u -zm9EW8&wQ1G7QMp4pnU|;`W*0&-q*1DQXulei8dy^!7Ow5!udyN38Q$-2hTXR4!r;oYN~l -zHh2-yU52B9GFQY0H^LKIb7z8eaW~k5bpXa>@5>g4zY4`#YR{?l*+R;@+~wDUDaUKL -zAJlzsosIFBflR`flR7x7L}hEmBFIiYmuwW=^Jd`a3IN-UKo4N>Dq0&N4yGCEAk6WV -zieK1cVANoO#NRxbhh?lqr3J?ygjPeB#;z@ws*BB2OQnik -zHTW;pn`!Aw^=|$kC83gha&h#0my$$F1k_*Zm!v5dG9O_zK0nXJJmn`S-AU6+$mgI4 -z?m1{~;3K))bXj1JVc|UU$`~Za)o03~vUZv2E0Jh~0BfyuAc!b8E5Let48u`7M>JPp -zDW;)AKq{TQ_B#GX(e{w>%!mGds5TU|KRQ1r;Z!_-@RX*mCEAQd+SAHQr2dFQLHX$GEfEVwgUXk -zNb(2lOfGM(4;KY__J(ypm2`r0Myl4KL6F*KIc5AwT6^3zr_TCIq|>g1LDfzk1pUK6 -zUG9i=L68-Jm9bW@R077Oygi6OAutVmsm=`AHAKl>h0GzN%NENu9n{) -zF(qprWaLO{**r5H+-Szm=BY#!Zge83fU7ldqEpx#4NU(mi^oMdZfc7#{H1(H)QZ7r -z2?AA_Ct4M(H=+^KUtO8)C212u!OwNc*fZbzj^S0Aan;TL)YPR0ca1wj*S@~CQ-S7x -zH3r1Bs7;?otx+V}&vHaXFc1)O2|%1f&rv@9+IwL)>i}GcmwL}y&#_Gmfdq?IBFncq -z!1cr2+qaJjw6Lar-$8wPNZp=WxjoY$zk>?f5jyaZyH>}gaScv9=x-o03}pGm6YL^u -zMqp2B<%OkE8yS|A)DBW$zoVVY#L -z!0d7#3c8JXV}Ouez_hi=NmWsj+sKcVD6}l-KRc^gW%tuUV@*^Izh($jCZ_e0pt|B5fY;oL+aVeYGGB -zNKgyaZinT9!F`hfh~NwT -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 -zA%n=z0+weNV){_7wyY0_H_3;<^zdmrhZl-1 -zY!2H`#GIbvq;y(IHN%cIhzqQ{K6xY*qvI;@M;``F8F6=kLm8e;NQB-Dg -zM(KLv!{x1IiDI%1PBEYJ^pad-SEyYuXsZ3XUZQyZOi+SzWn|zBE|UWxgZ09MY|;E! -zYIxRT0{DL_D2nyfbJv|H)iZ|}}o7+clU&_t0#;UDXaJhT4OWFX?XrbwMz0^a!piKN*T)$o7$)WEs -zPJ!mKG%I|apD7>4;cPH62XF@+kG;6cl9br>jkZD1yw_S08r;2kR@MYfL@5T=NtdP_ -z&@Ba-pqC9NkD$Iw4NY6<3-}`_*{e-OZ9uRfGL7OFElcU36=P?D1e@47)IQ6txy*s| -zHQG%~fa48Al<1Kt&~S_fxy})k!lU){W(b55MOX -zQP^Xs(DC)LVQM>irA;y~ltk=CNa#N|&~s(qQ-sv)a&U -zH4_0}YG9rX%=Mn5&GnFl?t@#tNZ7!b9H?s*wn^99tl#H>e{Nh^bE6>;`DOO^kK~aP -zcBN>4bsW2|M~wmG-*jO3$F5Ow>sDnNwZOY{=~@=gqy73LbCMVm#w~>w6KH>`^Fz+q -z;i~;~3c2)Wn}xQ8cCKVmhw=+5@0A=sK!e}O)$UkMI0W%<>}WFBLBz>KSWnFG-YMVy -zp4Vw2hi~3jn(9+P2*WMIIQs34RyX)M6P!k`!YO25bYRwAH9qw%-bY?N< -zK%6f7>=w`;6W2D7%TnL0`G7XzYt`@U*M!ud?fpdPNpMrWjFsC$=c-ar*Q!e3%?fNN -ziQP$Qpy4ouI3)fy^^}>o;}Id?V{gw{vx%|H0BQ|m9b2E5Du1JrxaUloJTo+%`lN67 -zgKv4upwJ6#ZnyBB&UU)@F2v7$nflzu@*8xpn@Aoe=1`g|SIncV3~Wgvkp1d(l+)4= -z*~NOWrEww_DTQF)01Jx3Nt+1NgWZn6_EqezTXX0%!q-S%0g&%Kpk+8W;TUHoOp&B -zoRpw<%>bsPXhVN0LX1LHS?~8kagI){aA%kN(&$-W?m!tM1ZhtT+{5@>-A=%)mDPw1 -zzt4I~*Q6wF0?6<-U(avdwEx2mZ!$$ZS^f_SMlvmm<_AGo&m4_Zn{0T5=(__g@}e;Yq8)tmF2fig`D{bR(u@jV -z1%n0#|H*IIQuf}dktUR|#v_}v&E`Cuw@w51Jxxf+K0VeLb{@$5Tc=6u9h))wa7*Y9 -z5`Ab}5r-09Shb$Vv~};RafhLB>6*%8AoN@X2-`BenW@@Rzyv2XNH#x;D?)M9)Z@S~ -zYnX=#9s41z9BQd(PSGDb64`qxIgZRgo0pER{=-57<)0uBby{%eMT#ex3Mm;_f;d4` -zbhHi}D@QL72Cm?i-T^Yr)$6={#lRmsHn3CUo_j7BMnq(pZ&qz60w9Q($_%BRqC8@o -z_=T}?xRm%CkiOKO_@v3VS*88{A^UlAj@(}j#eBLZO4tS@Dw%vb*bg#eav4sokwuTF -zTeR%@Jf=g|N>`?;=p{Bn_i;Vk4 -zNdcqjOLezL4)s-A?vAaF@}FAj2s%5g$Dk~zXVQ_LBODLgJ8Mw0Ak8fO_d&A -zoje5#kI1zP2~WD|qH>lYK&U(I!O5YDg6hjV$9Q`1b9RLo-_as3%nTJUGaDBnfKL$Z -z!d7QkydIns<1KXbUT{kAjYS=@-G>3uLimsrkhTzOWSqxbi?fL!1`0gA=1>F0b%Fe7 -zx_IDU;tYS`cU-SEl7$Dtbm{cY*s@+c5#rSdbv`xzK@JKmKuk -z8~0@8O5P*bBfhEtk)UWm6M!}yIPv>i30K!u?K`;%dzxLEs32k}VfxZB5ZkDb@{6G1 -zWJ+Nn8~IjSVhQ3 -zrM^71`Z>5fq+V5lw&|Vv%TI*9!bO_slqJpvMH>O?gAHo3=nI@94&p$lbmTjAyYZK} -zSduILsI_xB1Ls{w2?(YJ_|^WmmvC?|Qq(ynG;vAy|A(@BU<_={wuK$LV%xTD+qUhb -zV%xTpimi%Kv2EM7zwF)J2lwl9@hj$9?;P_PR=O^$lscVWXI~FGc>S-(6F$Ev>bVNF -zc^ogmJ?@GqrGOFr8#bAEapxIcd&JsjVw+V6P6Jnf79f^Ty;Kpvb8G5$!Ipru -zGe&MuEoo}$Ax-T#se=19BjnB6k{j-=_=`E;l~gmHKLk< -z&oT^$-5h-~Q0s-{^$Jpp!mEUh3{Fhye~5W<@wy?VoG$FAVovJ}d~Ig^eO<=zN?w9D -z)>~F1w*+McfYfL^9Tyz80eTANlrxLdE5S}d930pg%STN8C$M1KqTSb7quit0waPk4 -z^mDBAH$Yl|$m`37dc?sl{rEkY -z;0)l=ns)!yQ2(hEt}kw{*5Q-8kE7Uw4>N}yz3xYp&jYI^y5Fi_uF%FNG``8zdb+m{ibr%c -zU$^mnskv`ks$oQvcHMm-SC0oSrE;Ag?nQOrldMbDlxp6=F -zhxvT?O^pp6pInsm{YbMz!^W3k+f-nsBt9-dgZbchP+MIg@h4zp86N}8oMX?Yr;t`2 -z4*@OGdxQr#0|z>f=(s7xD6$mW-|4@qT(o+wto++%3E6XVn>jY$wt$e1}i<;PM0GKk07RdncUcPwQ`zkHjSPM3Lo -zb+B;l%U+BY4|*-Qc2Ius<7F+B+v)x2h%HX1&s6`BW3pEgMpm_pxl8sg{zcTzbL$8% -z?O`p9I%u>dnrKs_-*?5O$FxB0mwGW}>rb<%RRo{+_!0nI1e -z=!WDYE@~?#-CF*LQ*>(zU2b@Ub|%uK?zNexE_XczcS|=;NSGcYfKp&;cuxkVA#i+w -zRHHcAH_jJdu5nGwztH8!OKgW*0``Dhu06g1MT(s><^*G6*MFknGr^3xn?I%FV;M>o -zXkC+~y!Fq#H$og50{c~=_^F1_<>MYIwD*v_p9KqngBYh%AH1P;P{Z7h#h4MF -zcZKCZa_VA=D3@yZ6~j-}$@P=_Cx$+WrEiyr`NZLdT7&G-e?$I)aQ{R#1521&ix_5!AkGjO!}k^OX+Zwh~ys1fMLOC@f| -zWu-9NWr6KPm!)m7IMtkfPP|f>sAwO9#1k^^891+tN(T37xQiiUlc_IyS4d6*=zI%E -zunt$)wbug~ORkS>g;rC|<^oOgk|fyB+5KSSLc$4DS;!C(-v^;wJm8RPZEm2*AdS+$ -z&_G@14UmAQp>bo|iiJ*`EOKyn+6_<&Mt0nvVz+JCKb%=;vY%svls5pOgXrLpVyncn -z?KFldmOxaEBj8VlM!_zTF~J9X_Fgy(=q3!fLNLX8v+2P3XN}d8%75i_y$tYf--+5d -zkAM7~^pQpjyNZ2pe~E{s!qv;v!5ZixaIPLqX5Qr_sXliyQwi|W{FCS3xD3141% -zQ@&E7w~wrlTPN7`dQDy4mQ5R*-Jpq?pI1X(7)@%7&O~D^eW{+>lWJ-^V`Ol8)xI>e -z&FOdDL;4~Vj#JN3P*T`1FfwpK}V2 -z8mC$YrD(Aw_eKJxjr!ZYSs?L@WVAxEqAwD)grkNhz6){)LdHUMl#pscD)p6YtjAQvy^%DW6nKcSkpW}-(&{$a{Wyom<< -zeacmKm^C) -zGF1|| -zrW?1{|3H_p@jhRoRD$l?-A{HkA_skd1iXt)>B -zo3jAKQB`9rG&r{)3h-jxv67kcPVBQ{X1CL)IuTG~*16IY9m1QHyAxgK=Kh6{opeba -zs(wxHYg|M4Wd6j;nFUczLKoYGU=zVn@QD{~qKX@ZlN-2viLJr&Tg7VpskV)LuP3!b -zXK5suY_s;U?(=N{o_-41dQ5OWkx8(rVYqugaIUrfX$mG2qxukStLqda_vhB*hG{>a -z)83Q_^;ERk2Cl=#n+C@WB>2v|Hk6J$msLnoA^ZU6Gug9+XIOZx`xIW+*$Zk0Qbdk#ds#EZ6F2W=iC!}Un@cW2o$O2TiCc)KkJ@^lQx(&_ -zsv+dZ*jlD>_q#l^K_}`|_m}qF#0W43L9T_CCG?(`o9*J{_br5t$VzIxoQp}p)E -zRd9^Z@cJLlamg3H_>>>Ra)P3_^IjYc2$l@M@{G7h1zR9+Y!JMJL+Jy(iY^fmU0-O)`e4&ZQPZy(Iz -zO4)R#MeO1Y7SvJyK->BXvvTT~M%o5hC(yvXc-<_QZ+(8@=t{SAyw)%@;X% -zLs}N`N9d{8ST7v}CFLe4dEtA!3)NrE{)$}dp^Eq*cyUp{iZv)k7t?gjA_8*8^%-z_ -z=W{o=b`W@Bb8GG&1`jM=Av?Inv1?|xI(@C|*}`2+$0#3mVUM-@2Uv0V-_7EM@p{9& -z)K}WLf)A{Dt{qmn&q(DF_txik$@t4X0OM=7P3MEDk>p@zH5^6u2^oOcP!Oc_dB0#b -zULcyleXGw@YYto-wA-|(uC7qzCZPo(jk8%3-+z`y;QSCVAatIJT~c6`K^_4H;zvD= -z2y%M}nYW3+QGU;~?iheieV+hHy-Ah+5%7f8{q!@>#0oFu5=s9KuqE#2HjpRS@H&Tb -zZ!Z7Ov#TU*3cVaJDDv8V=O|6e6uO3VBrURE(UW{`O3E0*BYFyCDA=W%qeLJg0V`Jk -zBJvzE2 -zf0^N9o@6NhX@;A(ew*PS`*{652qz%{+oCytnc*=F{JsBShEKFd9iuEQVt$+91eG}a -z1KzSL-)49%xYIw)aN&QM;h&x8%T%6?sGSP(!GIz<+j6Es -z0~z}ReHSJOO1}XV^f~>}UtG_!9nKsv6jIv}NZaV*2n(NTukF7Tco}$!IOG;DjkB_P -zBcG|&fw8-Ov5S6u9)`{~a`VA$^i7$Ll!G0^+M0p9iB0OELI0|a{`C4eIyF&mIG(h2 -z@;r_F{GA89fSBvpQ61vDJNi;VP9;3iK_>)L#&i7NH7!`kL -zb$5#Ie2vfMPc~@U2o~$<>gTB5>k>wPJq>T_)CK*-Z|#_qpaiT?ZU0p -z^lw^$Ne~}(`VqV_I?RDu(dp`w3dqz77`o8hr@kSn=faK(rOboeovu!-{L;I}6)9qO -zOmX?mOC&nqH%PzuX`ir@rH>ATxHa{N9S4qNfB(m&5x~|*pJ!Iv)Yw`nN^ahM#e2Z+ -z9_X4htX{asdT_%2mZ-kTEg+Yda9{CxKeQ@??$a|A&T$zw%|n4oTAytQ=)|8Dcm-Sb -zp;;(=P=|#NH*O+|a2W>-dsdQX@AVD!pRPR@Z0&4DO!!h)5 -z-TOXVnVNi)zBz8RU36c<6-#43gt2IBY~Q?UvTb3QgG#}3m+DXbx_xe42Ra0=Wa3ok{G>

WfiL((VPUg2Ig`}hIs{%PG#>P* -zO_mnF!PmD~(CfoZHrH2!n^GU`A`*9hdR`qK;-j{>vFc;p&#>z6Pm0+`BbHHP3mVng -z#=8x*%5kuW6ojU&wI_qFZe4DGuKrGtbNws@#9`u+yEeRG8GZsV;jR$n^xxz02!@>7Ua^Fv`UtL#X`|;NAeIx^Y%9xx9319QBQP~u`=#Myqu}kcGJMJix3NGN&W+*VJG5xAu?HK4R{>WZM -zqO$*>JS>qGHbX{?(+9(R_HUFE0UiG3nqFBs5T%8 -zOR=5aK)RsMt5Ge$BWH4ZwyjIuly`y57z_*m@MZ!EQR$6g<4fAX=gE|0!tix#8`Tv{I!7 -zDAjz=qYT)$V9$g&YQq3aQz -zr|zpXwzK2gp0<{2|Qy?kq?m0-5fA&AV@ojdYYn -z%0&x6?H|Yd+o$gN=$14bd)7PEk5FB$EVEoUUVlk8#nETjaq}K+*NT6(KBR|(z0heo -z!~dPzCGHS6+unNp1X+V$ogAdXhb(Go9aKI?`vpmpEv|8sx;ygQznR}47uf396KT6Y -za%OdrIbzK$2k*bI$l*wdk%D5aDXLQox}4avWRBF4)qM(1OfTgg%ftIqM_be}m!X@< -z>|9Lma*!z9v<+;zbU8`D;BMA{JBBLI$&o?Nhy=Q@v1v0F69Er82?%VBoclajdSa+H -z*i*v2aO%GLi9HRoB81q!Wy7hf87yYSd{@K -z@XvJW@pJU3E55HgwC?J(NkvEt4t*!H^35HAC2WVXZEYjGftIwWdALQO;T2_tU`^ca -z-HAgTi(~cmol%AmRa+`A**e=>V^pZgjq$ynLi~esN^(fHlQY4{AscOWIJzwQmm@?z -zZtDf202eCh(`@3TX^JXGCpA#I9V2zwVB;P^E?H<4OtewNZ9o86{3$+7H&<`=Y^@e2 -zW0;1!(u3&}c(|&=)DHDu23@gzI^8cb{^bcZSKl -zs!%0wd|zC1uKg-LpZBD3WJKCifJl{j0pS9v{%cGv@Qm@h=PK~FW$8DME&Sg-Ukbu^ -zIHh^G>Z}rBf2_c5EheS4o6GJm5JRiA)A;vi&jH^Y8b -zX4Cex@n}w-1;`=&_OI;qh^#k)HX^@C3UVzT?!_skR@l&=R(G+b${%qwodn(U7<=oc -zMshTXP>pz7!kZOMsbt^^O2vk6xuU6K61?Kn3?YnvL+9fQt?^Xv;#7jq!CiyVWiZU4Q(xZQs-IadzLgZ^TOHbkOSq_wl#Z<;6%-5%tB*y{-4_I)(4d -zG3%aUXNORK7UYWyIOe|LDIIT9#E#w3AY4`u)&ApeK3~5+3>K6M2YITQ;_XvSU?r{N -zAPbeEu@$cS;}4-OEuo8KiUGKq+1EU4qa~ -zGNM${JSVL%z$*$3H$t(>%&fO8#5zp`@mIeM|PDI3&1}Of9gpt?ODlCn^N;WIXL!dn3La~o_e8Sxxl6x -z8Qv8H0aXrwZHoFr1M_Typ_212`z%N+F9bRNY#VFI^2Mqt2E1k=KU(@7@;ecD^pp6-=B2sB+2G?)j?56Ym&^=3z$STO0a_8NWwmm*~L7a -z`{48ON~Co7Zp3(PAb*gpPW{qo>Q2}S+9TheZsQKy>r+zy*bI&fB_neHoq^?8O+kzs -z^2FDhWjNdc()oH6!>=&(#uXagt>9iE1Q!i!RO90-pdAA?UUH;$W3YRFm(0oA>?Om6 -zo##WF7Dzn}R*$WTG++gJme@(VC~;ez|B^Zeamo!qsma@ix}>BX;ygHxlLE+9^4nIK6C41x@f)#$>7!R -zo!uWYOZjWBTbr3F2*_m=Sb(387i(W1Bqu)>4Xa4EeQ$==rP@m?Sr&uu_Fry2Ok@DD -zRCIqWw>70o+jZi0Z_pSQI)_hfQK(JY(FJQ`^o7zvWBed$PN9ra7C8>sis}-PC1ZF$ -z?3HJ1jOA=KzA$(RK*k&K>8o%eaYzaN_!ys@JyE@X3SQUo98Zh#atuV%?<)hwQ*qCH -zgPBZr(+8ukA!!%T5*R;N(&$pcgRvEfCyqjMA^KQD#35E1(dYJCxPR%`Vu7HR6yAu< -zU6KVl)&z+^QEv2QfWCnyA**b^9r7gjVmV -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 -zGKzN{r5!O3$1nLFK -z-rcKyY3HS~;5TJY5Gfi3Q2M$q8rKQzOPmmWfXr)WTKn%Z0~45}CFCE?ybrGmagC0j -zo9Cbn+pVQOB<)oHjd`d1jd@d6STv`asI{)(FoGHS8=nC~SS%vmV0>LW -z(OzYaB@cgaS5&@4BE49N_)V$JL^#&Fk|a+D$CL6tTFg7if{{uJKd1w5yg5H=0f&NWLlIcbwnHk&1I5@aA&?_k*&9bxdUSGt$wD -zD(<2}UX<4^W}}aJ!0ZE0TQmU2`xf01!~FsDAzc#W=O0?F+2G#a@^EtSbuCIZ*3=Ja -zwwgn8Cl8-Bux^aEWB?KE!3j*qqaYEMIneiksd(fh7FTnq(dH_m#c8$gwEYb606*dWVOEtF$)z3?kNp^-BH;9*A1;ZK%asV~&hAP9i5P%0 -zpOhZqu*vSd*TKhynhIHWo-6czzADhY=FJ9Zj$~!K6iBn}_084uj9`UzTpb+#jMMkJ -zsi)VYc&ZEA8FipDC&y1RUT{aRN&|+=O!N0n%+{y4rkCZf0;!?X%uHqx3fvZ8|K=R$ -zkY!}z8;{_2nc6C|f`NgOrxQLf!`vwZov%aQ=z2_Ci@Q!s=#kc@i@%`l}6>&P~v@MIm< -zFVD3HNh4uiknI?IfzOOAr}YXfm)U&_a>RvJHSD1#g0L)S1WO`zZ=q^RoGpfUkrLN( -z+fa`iI%AzxbNI2hIE9#E&b1mjxj_Oa0=j|`)XEYfsM0b0PmEb~R1r>>3=RR|ty{o? -zPYXXqXs(kNWqx4aXxg7?zhk>e> -zg+H}?1pY7@8SGp#612p{f7 -z)GW?=3u3c*&$T??0_NNq(c_pVd8*BNa}Dzr{f%=cvGS+@a5=*xUjH|oTVWRoV2lZN -zz}=Mw$s*of(^55yr72P##CQK7eq>avr6I547L@YUF++bR`%c2e&K*ujweuL -z7C5AwPuL5z`0a_zmH~{^Fb4|xE2IR!Z95wz8LcqdJ^KCmVE}Fz9Amz#c=n3kb2N8H -zJ@as^Qwu+tF_Nin_r*A=MiLfA%L9$3u@aVcRIWmggx~!jS)5*8D=j*Bxz1p6kn6u$ -zZubIc0h-b#P8nPPFMh<@)+m}7APIzp=0bXF2PDUtn(#YzOGq_eOjKkjY{I}I3&%!i -zcIF}5E!&k)Z}bVS{$lG#Ws*^P49T!zc6MZRw{aPXs|ITxExt4=)?DH%zQRCId#&lX -z7TJC>S7Q!73Bt}vvg8wK<__Fsz#MvF)G&^x3M=^ij+EmciiV0q35HO*bUNYV8`ip_ -z4sF1tQ}{@y$dpdMe_EZt`V5{JpL2`04wziGu{B*-gEs(mFit0nnPSg903>co(4+qMN7@;#PScIAaMxQx}9)%Io{ -z-q{2|1UE&9l_waB+v2N;x06UxQ@y+7JQaEVuto;oS`1rkuyf^JWTpqFOokSe5+lQf -z`~!yrQZT%_iL;Rz63`N#$1Z~#Rf}wFuPqkVt63T!C`@aiwD3mXjC)NK+=lluN#ycE -z{7Y%YHPNhDQxB^Kf1}|^vNF03-Ybn}-#P1322}pHi@iVh6vMC$MWh})VYyf5f>kRQ -zJ~nf~%&L*0Mu&hvvZS@Xwq1Ly0I1)&!Y7Zp{`}|U2Lxv(ET@xcEz9R|V|T8mebzFC -zpMUe8VDLX)QkuSt3@`Bq%;Aann$hK606`T8}0Nm4W7arLM7 -zZi2f*?nL(dW&o&ymJ)yJ32TIRc|zhy;Brb^%VtC5MtWh=GGUs&FE#(kaNF=(nBn{f -z!+rkW7;a=X>w!SK`KToxplR?m5nL#VcY}aH5VsTekEL5bFZ>X#HGxaxN&|UYG)JM5 -z7S`W7pJ+y(+g0#<4xHb~i4)Pr@#riIn5kCunpPo6kDty}gbJf=0y77*z{$%> -z^qs5@Fk2EIkE}&F5EZ_djQ8PVr2=acw<-eOm4<&kaqxonW1NiBH?WlUb4@}8T7o)P -zf*S#W&egvc52NfS*3~H+mket;$#+S+hFFdO>CZD}uZ!yYEmy2+w*|2{b4@aUs6Snk -zLVKIo6j}iXkx^G3(@)Mgt5UbX=3Lf}AQ7=+>;K8Zr+QLC=Q(!F!Eup&7z~{(<{#D~ -z8lcGoafW_N3uI?6GCgMu88r00>%nt8^zukBwOF0w%_*pvPS7gL^MM`9yQSLcUpw~( -zIBEjPa#Bmen37+jwnGlZl6yXd2AiFgL0Qh4I-Mlf1F}%Ym$JX#O@Z6}k>q2qRH~N` -zMlz(0qI4c5lq?AjP6JrFl{48aDNe*|$*$#W6iN)V0P3*cgF$Xcr4O=%XpXJp6=daH -zH!eY8WGt~Vp@_GpF*#=gj{k4)ZAX4dY$1}L0ne$zt%fiCf8pCOr3&Hm7FKNG#D_tV -zDbokh=>8o-W(rg5o@5TUd1XcGO{{QkX1m43F~nEPt+c`aPTubMmbbST|B|=MMSOcYHs*tBYJFT%#Q`TdF(K>QLir`ww&yyVq0m3XJciB -z(L#b6Jt}&}N?8;#dWy&B@66h$x%7oK`mjQdgf>e!-b@diC6-u-Rr#R~=`tI_+&3Fx -z<!ydVo4 -ztbHQ~SLi|d`;LLQb<1EPT6vNpXJG9Sk9KX=G@2s}1zAS%yFeH5#1;5R>UC+4n5ZD7A&;9+?4ACk4Xk; -zl#}-A*-2;_sB#Rv+CBa1Z)}>uLkX_^1jRpLPbN3d3^m_`G=?uigza!dI&8W_Pl6ec -z+!NcX&@Y4JnD&iV2|~^7gdR{9dr&>j$6nMZ|BiA)ttN16hF6g6F&#-{GsYgSpc%IQE8k$ -zAA`P;zNC^GG@xE6>A`PS%X5bjmddWbX8j@)bNR3CHl0blUt7o`*tGG|Ld?YudpKj8 -zJP;uRA~$->T;dls*J2d<@MVtGUX~|b?b0H$5IcpEsr0M#I@=52|5izME56+prb`C`gKcH -zaC07lSW;|KB;2->I6FS7Mv529+^0}DoR3rh{A}$;4U(QDqu6RL*DpM~a -z0CWr%Gk%}`^md-dNu;rHRS>c290fg^wJ@T{L$vtCmwZK3K7zrtELh1yV)WhH4gzU0 -zmWMt_<=XJ<29p&-sWA?T!7;JmjYqSrdejf4IN;%v-xpRNX+20umK8y58f0p}NZF93 -zfaEMgYp9(Jil*&pL!vhED^MT{%w+T&nKOcoAqU!`rdJ&t)9JSYy8&+sOP%DJ2sil; -z00kH#BWr$EOM39rpCiR<`z@nd6RU=ie|T%K^wrI;Bjwyc2Gu@zJ-HC7KpeUAH$UN} -zZcmt6ZmX}|^XR&3_mSUnT;h00&R&hU+4<-zsD7}rU`*v5wANypqMApZu7uO~CdG~mc=XqoKVvF!ovlff;L!)`nLko<}$n4 -z#6FJk7d*+!_&9rC -z%y#J?RTvkmba8hT$XZJ0<#Z0ht<;1}fL+e@c@C@NvJf!wGC{&HL;N|v(jPMT*0!nt -z&)PQc;$?gISZSFLpS8Prwm-IO|9Wwqyq2EmBL3iphvuEbLp?ux$E`nroeEyTvXZB) -z2SY?byk9RVt=?4c46YeXx1t#=2cuuR%MQGO@VWC<(vPQVcq3bc3RuZF&Bp;`beT9` -zu(-wHSTRUen9R{M#KG-Oq$|KD*h(jV+iFl=ZT-mhD*h)VYTm_*2*Rv5YP2H4?}WSNYW -zgmW14vnvp*V1af&5T!3zGFuhW6WGxl+@WQ3)hR{|2|6jPib&nFim0%35-R=qoLT_d -z&QJLkM-&6IHO|63iC-kQG6ct*I0Evl8L6D~#r{bH@FACBQ+^j(&M`NWfSaLw?&jDw -z{S)*;3DTE8_>>SCPjBb!x#?MjIozbCGCQQ>1rX^e&gcE*!}Eq84L*vQL0wtpC;l^3 -z7~}ID?Ue77z|=KlmZU1guV?@$mnd**5a9LW+pwJ~})fqCt3=4=rHc9JWY{NYKsum=G=}hj)Ea -z=$UFfd%9aX(sRx9mNxsWKze6(V8(3~>v0Z4K`UOpV*T)SMOhEjN5#QuWOa4E^kmS&Xw<~J&DShRdmuMxlLrP(q%V`_l#yT@rEVZdB@!moZpWmWi85Zlg8l< -z^$8WN7|H7eB#&q3H<(SKD7;bH9|q=6 -z1~gL3jJNSwCaR@6I&?4yQRE<~f{ozAM2+lu>vUH;Qh*>~FeuL>fM70BQT-kk=a%!6 -zxkIW;>FZBwVm(SeZgalI?JB54V}MN)qC=InV}h+gN5WQ -zM5AQS^WaO98r}>S+5YQCdt1ObK^%kanh=0~H^^1NoFUi{zQeg1b(QiO!gSg5cf%J1ga_<^MmiowTVM%vp=rdSd;DQ~WbhVoQ6QvrnK^o}VX&O&2bk3Y>zyfVJ9EGN;>3DgV -z<2aep#xraKSc~HDu9l~>D1U~N1yPX}#=i%p<=$DkDb~ZX-$!TSR(h?a=Jm9rq$Y4` -zso@QX_y0lI#!veewqaiXjj)Xa@P8w0*Z)J<4jc4C`hOL+hyI(e{rfLro5FZ>J7R@E -zOd=0DJb_Y7a7zA_;~wkKJYm-CS4luI8jQ#4hb@~niBy+Jz%P*B;)*U(ZA7W&zQ1H2 -z%&spliua4t_0j(qVSDeN!nVr4gl&$49a24)E3ijAbHOH+4=m@ErxLfNAZSu~;fYS` -ze$D#Q?{I_OV(5*Y)TME2brh&iI(_RnL3jHv~crDz-$8b4yF|QhpK|g-i -z(?lx&VWK6*pqd&<&y=W;=8qn1MK6T``DYO>!}CN*Wx}sCS0c#wn~%3xk=z0f5r*h7 -zSZKi77`;m40!XYE1SdIyfRs$tcBKd!=Rhz?-vUzIAfLX`6pe+rkRBX9$D~O#(l^&UK#hYzHh10bY!4^EV`MiNKx|+_css!!H%UL?=P)?a41@Um%LAwQujU`Jq`wyt8@uWT_QbjM -zv~x7viX9kFmZAc+{@k&= -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 -z26EYyhy>BF7wy+`TY$5cpF$wCj4j -zc_=sH@|pjm5w)l3C)faQADx8Q^ZX>@Ov`j`5GQQuh+KfV1&4FGVIS@)+5V)1WDCwP -zsSwdn>9I!XoPwwzxWt -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 -zmuCau6>o7Rsja;46$#+GdX+Wp<%plq -zHxYt#v@rvh4!E}28ECQ;fP2mPSf{l`S=Hu{wdq2|F$G%yWWN{CP%)q(W9Yg+s^u+r -zX1T%4pFmJbMH%b$t5qRe6KtJyjRsg$d;M_xHxxX>6TKm($a-1g3JYAFB;C*j)P6+f -z1EvpF&I$wAD8Zu-f)g{%7WM?%o_NGqo|Ymt-q5#*lgAXPxsD;wnVpRxvdu29vKQ9@ -zgK8JUoq+41`KvF9-Jy71T`xcqme&f4Mi)P&7|>DlD2Q=(Kdmp{ysuoj!RHV~%EVCB -zZ(0)P@UWZQX$=v^|Ki4R(M -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 -zzET$U53P|(=ArfCEWBS9EIPV435d(hC= -zCttP=YtN7+OuR6Ho1$ji6w(T|*y8A(Y~CRn4!T5;zX9&N@4n&Qt@qym_xpuF<>joY -z_{SqjXSV#%vKj%W_ZQ9!yb(}#E#>`(ety)D1EG-N*lvch-bH0Z;k`<}Csu%WtBHB@)1Ju(edQzy2cZG;E8 -zA&&y%b?;c9AO7|oSP62VKj=1z=KW@lH;{#Y<8ZhR+1-P_HvRyFp#^JzM_P$2O4QU+ -zM{Nf$2@$4Bq7uh9iMJDv>kNLjJ)9ce;dQ&Iu_tQf9yqH`H*jI%f4!vo3*ffnqx}ZB -zm$s_je*XnkZt1l)v}6ycd7Rs9Wce|!Vnt}M>6p>?v~05|8Q -z>OTPYCG|JJt@#(g4gVLwt;!_S^3dY5xXX)$J!uLHjU_!q~+6DXXj^FiiB&@Jf&M2U%gtqXQL+;4jagF -zLaNwyn9m@#!b$8f78U$(%!~knD_lPAdil_SrnKH>y4vsv4EkLpo$fFDcM`ad$ -zP++S!Z7^+VHcQ~3!cPO7cjWiR%^~3xy-WWebU?LWK`GMj3`@=D$2oVfWZ+o(_1>gQ2)$?Ae%x3{FLbbKhR>NP`m -ze|na@9B=tWAq>`1*816V3%Ju@bDP*|JiHYDi;y@F*wwc`u{@SaM+^6gERexF~hMi;g^dx3=(IHJpn@ZQR$A1o|P9 -z9t2!%h3O{XjkIVrP#5w<6`DoTYip0E -z80{s58N@&e&V>RuvhUViVqr3H$lHCNR<3HO(YfeG`y4x$IjQ+0&X+*up$Z`ol#TEw)|B4S=bRZ{1V% -zU`76@Scsh!R1vK+c(ieV2m$od;Ac(xO|Nm -zq8Z0ylRM@Ld%Wj_^fJApaNk3)Hjt2N%TL;RMHegTL-1DH>F5rzI6=I2Q*N>+S4#Q2 -zp>9SkKo2;PmTqFX{!)jw03)mGh`E1E2MmS0HU+>lrQhM0Xu;&Ity;4yWqGLW#HOk< -zUX7ch=AF3KVeR_nk31?DCT3sIUJhOjlVt{Z!Zq+H6$(Q5;TdegIto|mGn=_ecwwwbclLn+@M|DIS;6B996bW~{Fj%uDL53nxnEH1w8Kv^ -znnS8c*8ON{3ZJiauzj -zZyadIZ`otpKydd(xDXY`qV&arqFl$3ofv;2xNr@K#zb0UGoRi7Ix9 -z*nPzeVrarL{2(0q{eB~+3F-UQeC0aW@V?6--L!HuhvUt8w8N9^0P5Z}kOob@;>vVb -z&y89C=))Gi|7J}(ImD9P;%-rG?$+g41bXQY#$87HV01;p{PO-Xmdvs}h~mTT&wh%3 -zSruEV{piF(SyONZ#oFCk=73ScC=e02IAvA>(5~ty5ojKNh0l6}dB|Q&Z9ygLcZVyY -z{8n?{(UQ*d?Qf6CEM5Id$rA8;CO-khE-CU8`ODwFt>f;7+Z>2B8M_5F1OCh3R{OWV -z?c+Qi`|WST#D4qR3;*)B!$vyyR7ZNg{q2rYLMe;4>z$)evc#pnIHy8BFh59=lDhF^UPb3A(=db`TEa -zXZ^lWAL<@6lmX1Xn&KK#+G<8UY@aRoT%z6B+iF?s6yK1yN1Gtg=?PQ1cxrP!F84OM -z&i6wyd?CR%ielZTJJADcLyC}*!-ZGSN?kFKgSEHa^;U1M5N*ZX8`_it_-9ZZw?01z -zpW4(-M1o;sY?n{8>v6hwp#rc@GuSr~-5LyioAx-Tn9}dWUIey`H3FItJzpM%55@VAU|cZ(G32PuuG3d2&Lo8X3CTYjG+$VH981AY*>_X -z&es%|up#B|yj81P;uQkF5-JHud>><)VDa7vKbl8{c9;%W8gWR*x)7`%F{demt|<|e -z?H8u!tvlY4s~1BW@*KEuvvIx!P53!o|6AkAc+nr@LFkhj>d;Z1Msc@=Qq@5ma3+hT -z3@q^3L0fK}2}3Z>i>JYG%=|N34E=DQVTYCr<%8FRkaAxE4HCtydTiyH;HqFdN<%2B -z5wMcnrJ9S@g}t%(U7bn|e4F~KnJ?nFRHY25KR6ac!VppqIbeO_DzISEW)n)izUWW> -z26}af(ySW~eG$43MCqZQf4pyj!`vTDYaaHV=IJ~YFUUb|&a=9g%=6us1u2l&1mTA4 -zPY_%{y$gC=$tIM;a6n_m;eGsu17vrIYlhf!vfHZ?WC!x`P8jkh0j(OrZfHdpBTN*4~d?R40E!iO4LPIyl23Ub}*a}ZN$GdTHt -z`IL{+W8r`Xz;EeuS?})^uPWx50!1?%>C%y<;0{SLe*Sw`(jh0Up`qN3WMbbRvy3el -z)ZCy;9l$lIJz3=uvzKGsrTcdA=)aU|f^~ah!_|^wsR00E{R>=P3!qak^Stx+w-*Y%7w+~7jDPK!8O1bVcr*$@H#2QEL -ztYFKWrG*Djn*V7w77GplI`)%bDVO##T)5Z&H^80y4RFIbxIMb-egoVGb>9GY!#@DG -zN#p+l+%HG}55R5fqs6JZj*0-`l!nu<1P8J4l(O<8-xY^OD1OvCN>_K_ -z4L7A`S}V|W7-qc?3{wTGuD+DSS$hUP3Cq1x8yl>5I+qxTR3}~3*(=FI74`k!jk@tPzB+(V;9qfc=t7Vz70N8|S${r{M=N5ZI -z(G!cvDyQ8X(&?~M_-VUb&%SHIKJhmQUX(^l@Fug$L**tS8^Hf`ja_l -zY(QF%fK4?!YiJ4XgW9KGTfae^Y@ipnc}Sq;4#J!h6SI_{RjGi6ydi36H|I@)_MaKu^k81><_Ut}T;#|hmg+3yN7|5<8 -z(I9_8WMtFM!fww!4t%K9bXb<gc*B+XjOz`~k_yBA+Wr1m~8{nB;r3q&$vCm_3Hf!#VVx19Kib -z&vpbna!GE@!cE#*3f-CG4pBCvT>Q|>FT4;ps -zz5y-KiV*6VqYuod!N}dA?13xvFQeBg?30GrR8M+FkcL+n=I#`NdWs&+DnSU&pDx(A6WGGW@=V@Eqwb -zg&r#EXtA+pQkSWCpv+2cDTkJ-x{N%|51;pK^5Ki5ygp?m>_6QooW?MCJ86uVqgH;7 -z(FCOp^>~pgle@aY>bE&TXT&yIe9D -zg537O>iEHyzzr%LT3<1Zs_gme_jIOQfLVhAr|O!%$a>SaqKYKY>nudy%Sk!Kv5*Ab -z0I1F%-+3(Sm6Ibn^ZDp-Lgu+j;N$jz3AEMvrrAMi0sf+|tOB6|D_bzUAg< -zrMqFXl&Vs@YfoI9)K)YqPm;PxM)!U3LaJr@jn*=W(20F{lA{YOYF!6ak7Q -zAh>(qI9%^PDGWL1o%m8>@6MiRgC3O+$R&_&^L_mg^GB{NCy>&mvS0>mH%_CM^fC6| -z@I%X$0LXI`-`DYt8$J&(EXmlh2=}qtzp?zB2;}d&MjnAl9%P|`(7OW6jpY*+chYJc -z^+!5f0iIgs3}oRNp_;A$6gBZg9%*vkQCMHD8SS-A!v}pB4rwEqV7$U1!4C0hI{a!i -z#;m>zT(m1>ai?sPm2qXEr&4tF96#hD?wSQ;B&t;J{KceSuAV5gnZDif%(eo&u(^g3 -z3?(WpuQrcV4u}bM7#$*5kCj>mb;=E7S96RKq-a%=bG}7$ndseDhe<7rzBd -z!S^$gce#M)s~`6(NV~Iv*Hebh_ZR9R8nITtx=^4Y=~vy*OW0H%MA4oc4DGOAuSxW; -zq3bT%VchZ_XJ^Bti)0t+$KNt}IQXH@{*VIXrqA2K?XC-SdB@T+C#gW@g_#ST;sds| -z>@kR%1vcqVP-G2S0n>x%rEpvPW_CxjxDn#GEWxkYLw5iglhvDd@e&g7;rL@&k8yZN -zG_HmTvFW2SJerIVRQ`iQxU2;FKKzc&2)~zDCvy0QpwOVdLx8KMvYV}XzmYoc_(Rx8 -zi}|r_dZZ;G!x>r=NuP7ws)*vq>2XErh2g06J1`sS&`8ChT%6=yiifk -z5A53$*FS;aHU$h9loqe@5pUi{<9>uu@tybRMhU=nzmzAJBoEBa&@$s)vgZYMGsJC;+{d(58^vrN%`J=2 -zbwurVyq+|ls;xbtSE|B0yMSLh?*8g{Ry-Q&`Ng} -zP~>&4KWzrJc_}P%PhM!F>2w%j(`DeZW?fCaf^?^d*pXh&4I=FWcdcWB%P!Hw7~Q5l -zjru|!0yT+4nHg4RS56X>>P45dqg{YkEw-Ej9+*U6or;H=JOx1I(!@fapX$_L9^{4@ -z$MC9GY@K;_f?1Y^hKRNLV|peR>DORRb0fra=~P@YCv7cec9T;n2@TdpR*jb>zl2oe -z1zO&!d5H!WL2>VcKbC4;I>UYP7k@b?P>bznzb3D6>9w}@qE(mnkavWffwd^!j3j4@fR~fjhtR-? -zmz-K6?>Yq+@{*^km9Stbk_Er6_b)8JaXxUvf7;d!c2<0JZ63?_jdgO28O2!T;VO^=6b#2rye`PJ746PYdL -z{jv5!wpOd9e9!%o^68Z?625uJe}4GdhoIF)x)6HsJ#9JE4f7^K7eYg2bk*qf0^bVK -z@__kd>iTdfi$=+90F1Rm*{A&%!JYL4P6U%YiF=FB$Dc|rY88>JY#TXXO4ZZYwO-w@Eiax?+p<|1GyF|Sis&X$O@0&H^S?S^?$G;# -zaw< -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 -zpgQ}*PSrchz@AY~*2-r;k4x`F*I;>-qa -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 -zP6`BBb&X*xcFX7a4mc=$7M7Wm@M`x9I=B}U$ -z;W)I3EfzIe#eJeb+Kd{yt)XTFQYwHCFvF@s{+%ya?>f#rLVtb@9_i)jGjL~YX5hiC5I<(wIz1EszkJI39)O@re4srO;eDaGJZx+h+(jgFlWVO -zR6ij#=NG(bth9k6dwq65+F3{k5Gpd|r%nIN^lwLQ?0N0iC|PO7niNE}w1* -z;T5kfAew(<@GL76O(~Q7K#zr&wkI7gGs}VsTQAL6I|y1iixSX2lVzoK=?mpi<~p87 -zCbPsrmQLbQ4!*sLV^EpBEZS`0UI!3?-9{5_fCADayDjl31{dNVOVJ9U6!;41gjpFm -z=dG`2A=TYFJnn6giPTK8yGr<8f4J`gU_m4m)$IrRhUAvfgdEjHDmQ9B;+*M^wp2Kj -zXG{jO)6-41|9B@}9);f;l;YB+3~)#u=(HC?M{ZJne-v}x9-aQ%xK(CN!R7qYL#!g} -zF8>{niZ|CYXQZ#6ypKxJqk6qBHEb!3fUCSVs?}K{=JKI{Qk;Wd+5(2t1&}4m+$~); -zN|R$>3V9@*>5rT>u%_ -zOeRrQG{M0M6YB)z?>+p(O8per`uIs4pcM3DfJL)u+WTQRB8y1jfmJ^HVjg3K6 -zYmQC74-7w$sKVsDM{J;Q48v_hQHCpwrTY;Q=OobU^FA=fy-_B>`k8oU)X-8EDOV4m -zk;W%cUOa|3&)!Mgb~Jg(hT!D`acb4)sP0sQAkpMDjcU^a7kxd+KP3eq0MdpX9>?A#_NM0Rx@n6BCfn|vniRerdkF|JlQd82lVb`u7-h(> -ztyCjGfQ%2mVvDR?%XNjwkD+~&Cj?`))TRSONGIx8%FMy#7|3*XD)7+nuP`XGvkN@z -zs6HHChwEh~#umkHhJ;i%`m$H$S&rO$ml)EOad2uf-wIp6mgnucWO-q;%I4~%-SAP# -zzVQ+2Nc>{8f1G}+h#%@#9w!tV?vLOkOS##H40=EZHReO2JXo%AtY+>VJId^!!FZe0 -z;cIU32W2X*bRf>he`5zKxCj+!kVWr%Mx@Xd -zsi`-QY}H*;mwwQY+t;wkB7RkW4omLs-Im4gjx(aVOs1wz!z|)V-3Z=}WST*~;Ukgn -z@Ijx#c$K1UmHroe;@hkikvbV3o%1chbMA`7e9@{R=4z0U95;=;*pEwG>?&TG$qrpe -z$vpN7t9|I+Hmji^1;Hr9B^&!2W(EzOT(im1!gSTI=b1Lkm^uE_cRj~lX+U8^L6kj7+9~jp3A%rUusg^%~CbFj?m1&!*ZEif~h$40MaGzWVa<1 -zA~|T(vhnJANYo}a{HzvDN4@1msSXFPw4iyfMRi{&>ts~6}(YsNmy6k!Lz=}~=A^IaX5(_6sMLnhfgG&6iAQ5e$CWjEa;G!if;L*_^ -zGq&B68NSfL(>|qdsf!EY -z7f4~I>N~bNzT6kK9;CO+-i^L-gz|HINrZiM%KF6= -z5Ud^K3it$UQpC&%$J_o|{9KzMT3Llw5c1F{!M|aYKU;`ch(Ew*rI)Ztr0|FJ{%VU? -zgT+9;U_k`IojL~#%sJloN$iDr%`s57n2%=osK|#tp-+!){zjLjsk_3!AKHkI=PG#+ -zz15$W*5ZLr>x@e_L@1*577)l)Z_*)WGDEyJLZ~xpMsptGSFck~ZN7I(abuYks!9;KRD>deJpYUl$ -zZHIyzLQ7s(^c#5ZEjt5eS|F#9@Q}tL0ik5 -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 -z35AQt5yUrQrE3c(5f2DQ_8vEi~RiJJ9 -zu>0x*H&D1t6`iue-lSy1M|reWjuU-_^}CQqI76-%uQk -zp$T?<@Z;?ds24F3GA**01dpYT^BSdgm)H6CTQ$5v*Rx5_9P(AV -zP_{*Y;l1kD7IVLw%HHTytIz`Kb9H)xg=GsQFO -z(&_*!*pNC1T2+aPbha_!Hp~lL9RSNgcXXdpF6Vs|(Cz@@+2(NKNuZIDT;m{yR3(-R -zr9cCo=M^4>LL+)|Sj+Dzlzpy>0fSv)5_|uBZ=4+NaHt3JTPRqQYy6g~Ng6MUNZ!AvBMx@e=krbdn7trX -zSi**RTF-zSfgEzD(f9Bo*chNpzH@< -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 -zFkvI+MM3Y=jr -z{=V)Eik!pQ*rwMG3G8iKCVkrG(~n6dN11{1EGix|c;y`l_cAg^+q~K1X}RjkSJL8} -zeaHg|@G@I(;mi7x3Iz|8#ox7eLo!K&>{*Zw*p)V-JfJhpK+2fX8BXAR;medG490Pq -z_CT5MNiEu3FjeBaw5Eb5Buq2O$M -z++}dd$t9MTDR?^WmNx5F;eldHE#thF2cDWRWUnhWF5&w3)GNB$d^8bjS3RHoK8Nq9 -zWY6~>)zc~oSL@3uU0CYrU-vbPO#oO+Kk+r=?Jr}ZOX^TyC4!gi -zyULXCxz7)kXkj{Doyp{ONt4%@cOo})F)et?wHrdd9;FW|QfFy>oYAAddmKJ2U}gyLgB!J0g}V -zbZ;I*P>%Ca$?gc55qRtk{Rf+8p=R_O_-aEjKv2y?J;MU=Ez|BN^vZd^Nz34QJBQ^A -z+H7v0o{UXX{bp_*{J%H3Pbh71R)2x*q-^M!qMeVtP9yaWJs;+nJ$khHn>7?pI_KCn -z-ADMlB0TQgYp7<2L)OSVm-x%_N*gNDaa}x -zHqMIFQlt|T_ -zZhT@P6J~q*XcUJZ2fVe9EY8rcEE(a@>K=BJLUx&Orw6GOFknrl(MXKfX(OliJF%!O -zWG7EQ+F6RR4;(1gs0LBx)kVmTZ^nN4i?QgG!->iU`}e%>RAuS0SN>2-E8t+c=h?;v -zF2Fa!6xc%`#~7IW$_pfgJnnCQ858O`YPf6WMWUgikxN)xj;4C<=jD<&|EB8Q*c2X1 -zt%1pLxGHrw*eh;rgz4fao-W)5%R$3O3FVy(T)NEdg=>ygkn2f>cs_?Nb`vbg;DQ?p -zqxDl6=;J5^;_!)vnMlKS_2}xB)~Ya&aTkoenu=r8F3RFUE-;8PV@#)ma)#$wv3^eL -zb*DLjk6ggGRS*>a75R9D@!2c=9bQlM%;?1h!aY -z$K<3b2f7Nl;ZnRiQw8$8K!>h`4Y&t?^JCbzZVr%QAQUlNJaFCWNmAOS2x85GKk$#r2$6BtOr+emUI -zg#2RKwD{s&`Lbd~6u?aQ+u=DdM+Wbp0t^;+XEH>`Jv`*0Jvmay5SO`SXW=O@-yQh9{N+?xgnm!v -zLmh{Uyda&rE&Td@OuVXmWB~|x3>3G^hicwyRE9cC6mstaEf#bZ_}e^uT$UgHz2wNK -zq5rn><_Fnx!*sUlLANC?UoHe4E%Slmx3bD-4$AzX0w}vQ=g#RRfaG?9`$lbime|A( -zFpujuoYxN)cq%xCEyKf7U{Eo{kBj0N5T1ySBmo3&u+Kt}a?aaf8L8*q*yJ2>?AXeG14=M?KEPiCRQ+|@h|JPK0Iu7Xx@lin9v -zJZ|Gkd3fQ3Q9sx8;bE)p5j0z2Qtu?8gpOsEo4YEA2=BvkY9Ip#+HpLn5VcTR01p6g -z0D1n=!n5nc>DA1Nrm7(;;vD@#CjtrqFCr2Ux74P973nB8J!KInZRD$8SC0 -z#Ae#p+Xj6F{*OYKZ$Jh00Ix|x6rMY9OLL~)vQ4FLmpF9Y+D^_8J65BTJ3={TrPTBp -z3A+sZr$lJ-@J762?Q{Xw?cQ=g7X+HP4P*`0Ta+DJ7(puh3W>w!m4vy -ziA9z(b1oRyTi*Y+Ovsg~QYr3Ve@Gi?vBvBWo^n9ozPH5A2)*lQ8Hz;iWBmFW-uJM4 -zb>H$1h8&~ZaC8Alv1?h})< -z0dZ#DRoG~>Qx`B#@y9Df1SR0spY!1#MxVgz;5R^X@xHy55gjm_ZH^N#?U3o)-UZ61{KzdSGr?BOGM0xG@rk$~8&U -zHgyPyWHV@dS%>=YP;`Q8=RjWrJh0Zs@cq|ryWv@Wc6r8dv>TZ^abLqHet~RWJ{cfY -zMt>fk^0I)w>JYu2XTQ%lI4D;5Lf?^s=m7C8sF1pH8js;oLe^16T*859)Uw>j285Rn -z3F=yweSWMVi%MN^P6}FC--%ug!XkjJhCI4vL=8ckLGLF+w*O}Ay+dhwkVTKK<0x>^ -z6YRc%Yg|a;A&0#u1(znEb6cqY?kQP#B1f#7oa~&Muv!r)=2T*H>yEbeI8~Nu0m8E= -z9EhRW>q3rY!)$0B2AAKofj{`w@k5^J;`Wy-h -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 -z&{yWKKI3(sj{?);{o_BR4f@R>d7EA-V}0Y -zRTXcSA=^Ec7$x_#{3A5KPh~n_szF+pk@Ot@d7~>23u9=`6LMh!TYiigPXRGIi74TE -z5hgTfA9{tnCF^y{gk+v|_8m^i1#<3o90BP_ch_!6S7Q-Ayj+13grMsfM)6d -z8B0s;)=T|ui>UKH0J$1{qOofSL`^Sw3Iph&vG4?1q^9!WTMVX}&ksN(J4377W(O+3 -z$zY>3@B6yfCZlXdNA~LTsiktgFbPSVO;pl&6-i+zshfeVf}C5S+%fwkV2vVCh(;t4 -zAHOuOe1-|tHjXF;ZpLZZy!o>)csM9b*!A3ElFZa3WDw<4`|OF2Y&F8`nEaW9B1M?9 -zT%WF&M}1Y!l$ODrSd7H@d;MDCTVwpuZP>MNMOwbKAWb~>VF%qJD-{dN-J~O41~`Gt -z{#pkLW$*`;KW_a&_Je5~xx+^+GbpwVGbe#95VLyQ-T-G0MWr%?G&RO9roZ%+&9H)u -zHl4$Ps3V9wFQ>yE7y`SgK!wDvkD~^h#0+fSPuV|ktkCyyA21iyj@pdluYTR=N4@BS -zN(*Wwb9UB=`rM2UPs{coe<1R{r<>nFg7L-6!+fRO$0CL+$GxDVfI^a0>0z{D4m@mf -z2KG&Mf~CO2I03y9yv}ItR@M#;iU-9^@H0K1ltNy3-qCsxX#pv0h^5a+^16{!q*hHZX4^dsIhlFAMW64ZwT5V_ozw+95C -z+duS-C7I^)ba`1s(sDjs%v{T(8qsE8K)csrs0ue~p-&HqK_hcX`;0lw3Zn!j^UZUw -z@?3gNd!h+U#h?evm1~z_ToaU07mf5wpf$@6bRj25@7g`CD8XRv&0{nuJ8936Y%cBJ -zcGbL9vGIM?LK)^DEL_Ed421?yc%CoBEOj@|-84rNxE%mR?SLz?B&mg9&^fYy&QLsZ -z{|!EA^8OQ&>s+i5>t7W`QazJbvK_~ZTc43`97(KIJk-F&zIYZixoxzN?UT(dNm8cm -zTq#OslR^|1R%I&I)DRF^}X=lD=!2Zxt2g`ok_ -zUl4iQRW3#ZOo=&D&9p5Gob;_^8ujVBbfR-JGEr+#>-b$J2%{|v)oIHwQqVFk*(R|l*3zDX0J{e -zYLd5FObMXYuC5SUu`{XYtgP|2XZ<{{288j~ZWK;8H1ifsqhuTHwxtkpftg1muj~pz -zap01HlPd?@(43YtTkY5NX)SOkvp81n3@OWrYeU8eXIys-?VR#LjuHm!Q!d{$VhUJS^aBnt<@OxgNVh3o -zT+c(?n1)KW(Kt;CNdb024=eg2Scc42jUH;=Wc!J?!N2C>+_C^B2E5CqE1aZtnCRSd -zRJ(xmPSU6elCUt8M}?-FgxtFI&ML{QW$fx62Ldtx$j9h88Uy}~lk$9Oi7W4ccCcNJ -z`qN~TuE>+`>8vD6Rx7Ixu0d~1UWRAAAD$EO118kWn+cNx`lVL)XP?2$PNHB1jo3h^Jt`AC;YchHbN*M?Ajo+wQ5>Ykq<|$=6ue%#5}~`<+>GLN2T-6v -zAJnN-=5FuS*!BI4)5+L*jB<<1;B{|`+Sv|f1$bqkE04^$rt1M{`PwR}oE1P7Bzb^y -z6WimEyH+^>h=TL#a%WB>BqGa5gD1NjO~Bm*2gQEuQ(1jM4QK0?Uyon|IL+6~BoPX0 -z6^~RU$&lPYs*rX|lvq~y>pb^K_ZrwJ4!*4st!LltxU6Yl4pd4OgqDs@JQ5TiIw(Vt -zy}diS7x4sfBSG<+JQ!gqNa47SP=U2jBL|6G(x$5SVQf9%M+$X2@|{Nt@<~dkdhMpm -zY_+~NUO>KQ@0C~^<01GkTgd4+{hKPEZtLL6c%EaB<5CvCAVyT(daKuRcR(>{M5DFG -zquo%<2AHXQ`!%wTK$(P@7_wct9jQvd^Pg$oaa -z`IfZ)tYh*c%c&A4L%d0bF@r150x(JT#TM+jM8(8>y+OKO11Q&^ksxK&De{EGk8?-h -zg3drJgw&FRWhq{X#Cr@QOCCH?Y*RH2ACiL^KsOnBy}2f4A>I?d|NL!$X=fiwzx8TA -z5$rYucwEmyUMr6j2U4EAr74OZw&KAzipA?50r-RMA`gWm{xGFM0=@LS{$qJSJ`h8$ -z?I3qD)-Wj74{}7OxHi{a{ukr^;I9xraXP>5tLa9x%#EaJ43D`Ov$;V-dUs3#k~CmA -z?O|w-i#WJE8kNwvK=e?GLSHwGUZO7C=57-hjN0L-GIJ~Sd0Q010eZ%b9^rz4VmaG6 -zheQ|N12ly<50Fer!|B?^G-@R1$=iytBcuCe%)=lXmjiqxIa2}is5uAV^Lz@7GxC{X -zW@}Ihc$^&u)d~n$55@=z#%1|Ukt@h2V`HhhPLa3fpnRF^4Aqhaz^G+fxsAX8u~)UZ -zbO~$dcARSn@b2M75BkE|M%M-iP*_;eVXUL+tXOavJl$cFCq{5Nz=SzbR_>=TdeG%O -zJL;V7jdz_X9F-0bS^`kNJe_TokVbseaJJ~i4oL*63*yLuGf?DK -zz$mUI&^WsI2p8vKnUfmE$da;~r7*U$ou}&#V076lYpuiRHFo`)7NeiNz4fsEuqT`K?3=Q&Z3^V_fF#EK~qV&Yi%Cz -z&csbk9m(FYb6o>luXP?qF}8l4;e&U*c;8PfyF^C-4ceW7V?z#9n9u186k8b3043!E -z26`&V=saaYjtmqTtz>F2l_q>0{XeBg*34Fg%~~KF!%TE2m4kt|74kQZR?voJGv@rgezIz!~jl -zm>#}C6q=3nY&JijR$rYsGBj=Up4r40H=A5zlo;SVv8I^_Rs&=-L~r6t5RGH|TQtsw -zAs`+`8{qLuWsuD6uAGc^fRi{EZ`;nYRTLYlQ3mlXu>L@d`YDm^dg0K%vhVW4+lO9~ -zl|18hZp~_ZLTct%_P$T2`R{>)fC^4GLs=X#ggR`(G~$8+9Jru-yE8X+u}o{iWNdHF>axv4wuC# -zafw;#3}f8g9n_64Gd?&Bfd>={@;7L9_Ffm$+8@e7ZZ{-)>!{vs`#nrgjGM@t)NRFZ -zBaE6MC({l&M0*>mcUS{k=&>*7V5vx=`OcO-=sk`jz<^sd5f{yd%d+?grtOE>3cQI_pd8h)!KT#L!-f~xtp|C(luZIE8(JGclU-Lkwuj>+ -z%IHFgh{Q`{1ET&Zw6%)+5s)V=xMIJ){d8j;+G2Dlc -zEboV<)(+vhsu~_5;4TUf=~l-Y%{dEBJaC^bSRo*6HQ1BDX37$F%?@$Uhtn4*qvC?a -zUbmt!4#KF54cMQ)&nlhuaDEu5SBi!L~XlR*)*z^9un+lwD*qRypBRWHBQ&gR@qd -z?TlieYjXACsw}wR+G{JhYAziN;xs5@W~b0myovE#NP7+DI?$QBjlv1@@vMne+AiWj -zX#j{~7@1=OvQdLMP{&I)-6qFX-fGqsTNL(r-2lTvgI|2YJutrN_u1QtXeE&A3HA27 -zSduTF#g%u3uLFJgg(auh_pF2LDOuMaW5W4?SzT$c>B)EoEsurOFtb2gRL@R?0iGgM -zu{p6*tBRtsJIn)g%LxwP{~WK(WMpN!V1=~TZVAc>$$P0D4}jAOYV9d9Ihrd -zEd%7ifA;VUluLCy2S`|X`Ga^MR4I -zV)dZf(7KT9(L~T{V*g`y$75x(&vdCm;)~uxHTlu?wM+Ygov+fFR{8SyiUO%Ifr9oD -zKV`ofHXFE45APvodDMi=`0OMw&>#x4zk?-*SyIdKOoNK~9x%j*2jysIN{oI&Q&PC! -z4{_CtZ#dbE|F{vg_rLgfyYD70qo(@(u;t-(26EUDbDPFOW_=l1gBW+~Y0byQ%L3u> -z$_E0xRegwJPwhGB#VCqK0tTDBd_D$8dz`iWN}V}m$pG%wg+qi9vD3X%Hr%>Gg}Ftn -zIw(TFWYbNeW`I -z@+6nmHMcyt9xEk~&QZr3502N4t(I)}EAi&+F{g$l27|^LMg*XN*jy(>7y=sXmp$eX -z7-x~i#1e_UM6E4OsN7gZfG|f_srLhT?I_tQHz+&I9q)VtM?|Y#$U7^B3l%%967~Y* -z&<^5ok+tVMuO=2K5nD&F_F6|qQJobs@!4657Ty4<(LP4eOHs{-mjW4xir7art5H$!-0RHx(KT{8^~+NTo!fD+ZkC_dle>-e?!RWylZ -zudJPhy!inW_mF=4{r!9KKo<~=G%;9IRd*oz3WzfJ^DfVS&q2@d1)NG&3dmOTr2WD^ -zMk8#=HBWdw@o`Ic3RWjH4T8h(o;U3kBh|8n+Gj~)w8#ZHECbh}o9|AIJ%sDvzJX!M -zz~h9yG_0sjs)axmo}0_aiQn$sJEa$SIH_o3Vmruzj$eM-V$X7l4cvh_y|qcjMV@nW -z_T!d_dg@(K8ZRU@OhrjE(Eec}RU8Pr`zYXN+V%VS>+9ckn|(}Y{;QMxG;uT@xktcs -zh!q#6+OIbKf4U0pK`@Mt4q6+#y1O8_f%CkEEmf#6RivL#J1%Dn9Zu5qS|#uvwkqE@ -zX%PI2ve^96DzZn*a -zKKZ%1+hoy*q%dQs9-s=eq*YgbL`Xc(I~rck*xigzqen=bwqj#oRNUNxQzj}Lykbk@ -z8|qQosjL8i9&T0w?P`c8J7EuLkhJ)ON|8BgNnqKVk&TuxvB%nt?6S#@@bDWKgB0HE -zEm~BoBul7NIkKCvY#-#m77rD~jJMt0mhLLy?!z}3O*V~?o;DnM;ur|n!d#3UG^(;A -zbhBxEc{nSEVC2!24j0`#&fkISSZ^vmmKa@M9Q!!b$L67?j`1i;%?R@eKJ~%1b7o&m -zduJf``S|BR2Vsu!uNHy;U_M1_p^hO3!k_YIRxB%27SRh=d@7NQELD9bjw3}s9&%hD -z24UV!>$$e?*@TnF4~ig{+PICzueBkRmv?QY5rp67^!Z7z7SLrk6b1NI4A%lBJHSxZummVYxgWiCpk($_MlF??WshizDX@^ym9<8f~XI?E*QmqNTMK -z9UD0Zy;7!acd>h5Eya8uwx^dgG+L)tLdu095V-=Eo{p*ZQBRH7FRNLeX&d)dU!C{# -zW$-zBc3;42XKOE3YGYNSYZ-%Xe_C_}S`{-5lK8Y(Era$;g8Nsi@rgYVw2ZnMsQe8? -zbNyCX^E0%Q~k84~@M?kYJ -zdxX|oEqrWY{?59ao>AheCvXj~+LJ~dr#;e%v5i-9tQ4K3l1iowu9zKilmz;aD5-KJ -z^bDmzUVu58q%>OTp`hsngPwN3+Z9*Il5dew=Mlk4j&Eu1AK`Y^+a#^HaQH+8 -z!SunSsYw3!?QM$P%)ozs{7^SDG{cA#w^97mAUCr&rpE!`$D=_k=#rKSPN|9{Lvr@k -z@iQ1|D0_JQ@C8!4CU?4YOUSCCa8{JO^pgPM-zSe5DKK=~I&Eptgt3H6j($CJiXNA% -zN39%%$)>Ysf{G1XF4^yJ#>J6f%85xm;mEjy=f#)u{vczE{weD -za5QoNtm>{YW;L+(WTTysjq)BWOu>ai{aD#yl`DwjVA38HZg7?A0_TQP?ha~LRW -zr6!(C>1|L;eSxr&3K;+->fVxmS;DVMCs6dTK-DXKgI)M=IY81K#e%%&oCLyN{~E1? -zq!7FTWKf_e?s8Ay8SBtIE7=sw_}ZJ|<|V^C5GrKk_o~x?)X*`f=E)>lP0)=QGKdhi -zEY*jW=9`zG#nJM=&6H1d8;X9rY&1@J*~Fw=(DMjrD;I{`3Mv(0mpDtvCXf0k=p2Vx -zfrpOg`J*62&xKWEy&bO5DVYYXc4;|{_p1tVVzOa?J>7ropTjdNVzo!TUrZ&y;$UpA -zN-~$WO1p!8uy4T2kS9%twjDiX;8?(4-}64e&KnvH%rdeCydyD}op1t=&FU{?xpycg -zA`PUfnc)JJ2uVGzdCu|C)whu8QxltFm_4%oLouL@n%QWH;?AwiK?$eYBK4ER1mF-% -z*?ucETZZ>3wV12`=z8J_3%@QKnPzej4NeXck;mxxJ>yMe#XuMG+TG+Tz?)|Y@Y*z& -zVop!2Q7d0{%c1Q53-UJb+_C=rpYM>4L#}h?PC(r?bU)Q2NaXpbkmUfs~3W^wrX%!>8HLBu}?eH`;HWpQa5Qb?QtT2>^Nw<5?vCT2=^9!wkJBG#5W^7}AI>%JZ -zUrC-rGZ*&}DKfgUCe=}%S5VGL -zJzK<3R~9X|!=baio?jUK?G%dk;Ibp!L&?`IDXN?4AP!7I@ix~t!?RoV=d&O_*NFJ! -zzJl09&BgAWz#K)JEc{_6KQiN)B)OueEc#`cb6|-JxTPz^c%eJVx!V5}Y*X)+Lr2nQ7q|%5noW-RA0^?*L58=&C2MTw4(~w+x3oCO65iO -z16F)MGe1vFGb4BuWgGGGk}ccmN0E@Cff(EvbP5BS8`JPKH5<2b -zMxQ8tHV*&-c`&<7!m<=IKI%@4pr~SPDwT8m%ydcMK?Awa -zl{r*nIyN5RiFGlj^*R_ujApm0<}ahn^CW&oNM{f#VRl6$A)6wSt$G%=v~GYp1~ARQ -zPU%zG#}QN;@+K5(+;Y$Gbh~UStGHZ7#Ur2@FlF3|E;cI@CzYo}*A>~`5nB!LP}TJl^w?BA|> -zQw3Ln2j^82+@kDhNoQ#G5*Am;*W+Z>wR9a_PmGi)5eb`zOyZ1?jhY+(@m;*tdTyNR -zr2c~8bc2n-LsZGfOt3)?E@VAsy3oo65aG-3>3T>`un=HSgyCP?$~g3_si_HuyDclK -zWY9V~@Q`>vfcVQ5U0Li0aqIiZ3#Wh&ouy-c-p9UZPd!cSCFMqqI8{lGz>;$lT(?rB -z_lHgGORN|^_ZLwtQjQ(I6;wE*k~INiNIoZF!no*VA`@2T9sn8lHeX$ON|{}UFAOLv -zbJ*(>ZKI`^;&*HLoQy_9L3FreKdm@k2_{+~ZIQ@Y_F8w_!$Wg1T623D{JgR+B}>#9 -zP7|Gqu%3$a9)SVjSw4^~PDpL7IMLR(PFPhmc{p&IDzOrkNvHVTA(I`M%9Jg66pgAu -zVrV_eAf}f9f`D>45+h-IkMyzr?z-PDADndiFi8`?A=?9ppeu(@{65c=h#SXnyQXo2 -zx+pLYu-~Y!V0YXlfHL;rLuVS;yK_|qL|%;MP$0j7 -zV?Fo`k8T=q&?Y%zk@3Yl`P4FiAxvTyF_x@P%VVY&Ga -z=Y;Ut)z2m5r2rBEWFvQWVL8)iEYmnS!*Bej?`*J&hYCDdtu1~NkTWE@6S!fS5E6%P_xc!nu<@jMP -zW!x{j*fbRxnE%mWC0HzEw9*ko&Sz+jw}voLE%^d0 -z|I$b;lxm)Xc=L(949CNOba&F)K^CNu@Ybv>V@0sW^wzym&Sne~$rJ2C(b8`*AS?-y -zmu%hNi;dhMCe>jtypnM7r(!!kP*!clZ>^TWuzm1L(h>eNbMo`8At<3v14i4ekb(XfiZ-anN(Lxlpw}+>ai6jG;JLEDd!{h>|brVur?RYuYYM)Bv@TJ -zNQ_fCW8v%CNj}k8Il{oPPzYC+Uh$1*_=I^%0AO}N0N8DC%%@)+2A?L+sKQKB5NwoD -zqCg^WmPn)^&cEZj0Dig+xmZbY5r7yf%Ci{8`fmqrNca!lnXF7o(m+hbl)I4B4IUHl -zH;@q>((4L?v*+e>l!O)e;A2>B(~vj)su&M#Ii8WbuP~fiVi`0*u(>5ecTVYz@xz9j -zxOyHkd0#EZAj)L=0*XNIYQ0d5$QV|`*n&+(_FDA#WKL$*^9Bc29$kShjonckXj8kE -zy~%G7=g-Lzkcg%N0j08NU|MnDke+_kbqH(+m?Kyb9G^TAsIVv}jM=N9f+U>VK~&(d -zw@^UM=9{F8fxHNJC02um)`L<&zK9@>3SYjRk?eO+%XmdUS$^d?2s*Ge$`TkEK&@g8 -zd3D^NboLEF{wgqhtddKF-qt=C`D_6a -zg57Lq;Bc1l|-u!G1?CR#>b>YkvxSN6f9R_BC407K)79x -zz2wsNZd1YFD^F%rB@&g~wVpo^>gX$!%9C>W#Gw_EIqh_}W5ha=geUC|+8#Ayl2(Fr -zG=tXm1Z;@Tm4(rj>*td^44x{pz3J%rj0XX}oK8JXuXPjkJ~*^5njtDfHFedfT$Bk~0;jxf@96k&TK`N@&Wxp>bkLmniWEb!Hg9tuHX`>Hy8 -zh6*y5#dKxalW)*3_FL*XsUq1`!C -zzSC1o^iOC9gN5lcN@JKawoJz$x5wb9w+5_qgr|V3Y9gmpbwkIFW0U}h6Tfq{*NwW1?I}*D-(9C0)cUO8uPz+7 -z@fb^@W-@^wS%y=E9_BTwJ#)&TKL+TG>4XQz5FA%ZsfwwWNZaB+vXGhz=()F1Mu=dl -zSVuFHvPg3IDlni|2c$Nzo*^50i4+%r91k$~RbaC`yPw{rn8^up!UTz6&Vyhu>Q{1& -zT+R;s6lIO5JMIKI1jmjqWj?n^UVB0yvZwO%(yw)&a?1sj2T7=DfT`6U*&Zi*jh4=ip -z%xeh_wM=qhA9gPPqF9Y?mDD^Fvv*3|M5-4%MT9a1lbw@vPRx08n0kuFY2c}jy|tYY -zelh<~8lti$#>mVbuGy9dJR%4p+z64;-NlW_&A+E(ic`s3ZNu1TJ0_w73`v(8!(|T* -z*|2Oo(8Jb*g;nz8TQCgJQ=Riuq*5+GoL5OR&_wWd2H+13B+DGB(^it!r0OMjw1PR? -zeo!#Y5z{CUHRR+KND8cgAC1uLix`~~w9s~9yXvF+%UQb9{CW04c&h*fB;3C#g}b{v+^X(3I?)#2FgkYssre_&N1cak2Y)Wj$YD!t-z{F^wOz# -zpqg-#+>PW+i|cnxxi-X6gDJ9A4S{WU=x{=Y_?eq>B8dr^C0S$#Ys4QEJrMTP8|Oip -zcJdakUeWfwrwVxBCT42jXfF=USF(7uMaqFdWUW70k`}76r=ki>3V^dyLywfJ2F|F^ -zC2MWmExptx*9AhU-uW!{w4TS|n4>e;fk)Ey)i8r#b7L^v#DFM802HVt6msC7BpJgj -z@y)nHv!X!QaN_}qTm!o7I@6qM2J=vti48CC@);2WOQ-UO+2u5VfYxIs -z_^Zwxhl({!Ro9C9>s(w2&Dw6wgE8W$)_q{JskT@il?>Ta5`2rNTliR_-0X^>83!Op -zQip=^YpDx6RFXy?hMP%bbohV|PPs-hW5igkv8aOq2ZVle^;*MNV+URnz{7)NJaZng -z2)7*eO-CIxpBY>R%AAUd%*obM^;;B3HFXEFSNtk$wejJv72X8w^{x&%#01HbJ@SM7B0ng*)d}SE9?0RPxd#*-A{;3OOeXv!7J(PPK713v@b^?^dFf;a<{R{0^A} -zIkptDBim8+te7oVdP8IT^&5DDIaHL8ve|4(-tLvIf(ykq -z9-%Z4$pT*obmmO3+_zzc{Im}N<>i!RWC_xvu#q)sAk3_+VY(PK5`IqcQwe^GB3u_* -znXE*ZFplRk)A$d$c&cSq^aQt_krk8*YH#J$0%kpIo1RJ3K@f! -zt`cZHn)oBdOUG-rtz+<4e~?w>B^$5MBDZ$?gdu?O91|)1ghP#>Y>ZoUj~(K%5h*BV -zA9L}K%d73LLZ4K_D8U4d0JrN-dNCEGaInftDFYxm?&Z9sXj^iv^*5)HLUpafbqyQA -zEArzWkIL5%0DR|57T2IgvAV$H$6u$szMy`j>pV}|R+D~<#?Co0Hc{}uyRCHOF$9xW -zs@BmX?-i4Lb{yU1Nz4zpawM@$$PjAaEY@s#13AG){a)uw={$NH|dXIDRI#RN{%N+HV-+_4}mEHha_ -zmDhs^bC)->8J -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 -z*Cw9Y -z?2RPcZQWQQVR{UIN`dK-4-uI9fQdy?jiTQ^u|D{64eMfl`A)De(;cqy*n@Q0w)h4V -zNj8p{lZ*+U;&*r&aASt2-(SdKSrFg7)e%A{v>iGQ!OPHM3$3m0%6J+&ZfL^Mx1I|l%1zz*)N4o5-a~0XYm{uj~#K;PF -zu*uwEQlG#|JE>)H-vJP>4bhOQa+Ac~@up3Jg;yL(5Gy4Br5V>FVnCHtpHy#VI4kjt6}J -z)=Bvz5Zj3N_NX_D+|;ick&$Sx1&J6yY)=sE`N62{J9)*Z -zmYG!6=^_e3=i9$oWl?69>F3(#qVj6=ywXc*;@Avn7r@awHY&s~&7vTg#w?53RAh6XN -zPbiZ^9$wjJgFR;b+V7_!d55={D&%gH*_iUh0%By~{Mps8ewfVoxe(*SCYu%h%)!!*Yrb4+zyn!l%gTl9~a#sLVXH -zhc3X-RI -z?(SRw?MZDCY&~xCQSmk9w~<@X<=ANbi<@r5ZtoRs)Vk~bH1WK+D=j{*hi$U7+&966F%R3ELOt9|`dX-YSs93wnIfMQ -zcpX_(9&fTWsa;In&$lWu&n+)aHmpRSsgypnhHkXn=Z~S|OVeXvvg{DY$BHNZYZ^=i -z*g@n;TYSB8>pIeblk2$XAB40X55JzIJS)7Xt|@uopw@!gI7gdjGUV^y$7L2(x{hz` -z^t@MxHWoa^1~^~RhxQRAUv!+|V+y5bw8BX4>F8|YKW{)*iEynjXR -z;M2rEy(7;poi`RS;1LJvu@`?uZmP~k_xFe7uYJDLpYNP^g}hhWf!JAUDtg)@E;U9U -ze<~p0A!Y1B;HW$?+;`1E4tlPq-p#UAb~X)UXZFVh2@6r4PJ1of*PTAxG~O-hKHqZt -z%ntgyKp^gC5ikckvm0k`JM$8&#I!#z5nn_?I++K-BPlA-Y3fl&WsA&BwgGXXRwF>U -z8pg*oQxluq{RUD%!u9z2l$xr7BA2EGhyuL+cyv2{%-n77=|EO`P|ipYA}k7?{Qw)> -zPVxw3Hs-srVc-K -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 -zGMYKD&tBb7IqqaVn4b!`UA1&Qn&l>9h^_ef+ -ztPAkR0?;@qq=M^J4~h;c}4%%mCJFF4Rie_>yR;FMiISDh-Z-Ea*ac$5-T5Ime!hGvvOS*SUqlDwJ!bi#XUG3Ch=D-G0&D9L@XJwu6 -z^Y&uU%%CKDD*1~0x8ZqXmwRk{ANIUFCV@HiS33*9Z8IO5tm*c5HN_B?xd0YU@buJbM|W#wb`I!c`bdy`)@j -zZWNr|HI8jHK-`K42G6g;RcqIzWzr~YIAR&%_#x#G -zhxpowSJ`_D1XRESmV!kVA`9QOKtDdn`VTgta~#Qp?=EgfSh9fnEd4ti?OQ=4c#aDi -zj8q&)V+~P6DNq$$8AYcY&kJQq7EA$^U -zLe~}qbILq(q8y)X5f&=ta~T)B*e3%Ub;QNcGpxo>k8dO;<+GUtzZX{hTyZ_rr^buq -zOMlKtZ%pTIN-hQ=u^Nw0a*1QiqZCPM9r1>Y1)#ycEULm#>*ammlrp|@Eluc-V?j}; -z3q=Fe{(ip!_3L&fD>^=)6x^TiDa!7H#f!hg9wL+qLj|y_3pB_d5gFMwF|mbl5B%&m -z)^3&I`c)5Pw+=02KrBKRV@%r4xh|DPyh*WE!no_k_l=gM1N9W2%3%ey{FORSq<}v( -zt~TFdq*Lc(%KhL2D6a>sMu$m8kw<9&f(fUrq#Pg~xqde`^Vq7Houzf>wBa9P_K)@d -zc_m9xf=NBjQTy5eBtLWYIHbQ}qqK1{%bhj2SgfWCy;Jaex%Z^vmCo>PQyd;XsxEy4 -zUYN#khy`8aPZF{u^q?{Ds#_l9l-OES`?62n(SE`4qK1b|N`$wugRx?3)g$(M`-s=ifdn@NP}*|TdL{|c;l=6bdI3B@OMw`2Uu0AK -zt4SDqR2c~!UZ2H_x7r03C<0sI>1B}xiT^sDpWA;j#NObGeix|)NZdeO3sMzEv2=K) -zRmZQ1?ro8ycVL^^&Pk&zUgn*_ySNCfr34IkoF(A@V%%YM-x&8PLH9St4e{d}<9_%D -z;|9y-*Z%IT&vw6kNSxN;&qQi~HIV+8&(6k>?I{bU_M$171sO>-_+$1!1ziC155|on -zhxvFLaG{G6ohcbqPV%}DyuW;(4DRQ?OBRi>7dFmGmm7w5-EuMQ;|4eKD4WW0ez$#s8eIR0fPb)kI>UcM`8 -zd5hwTQ+{NquUc^Rn0V(R?w;#lJY>Y+Az?aDQ%f4s#^hstV-pKi(%wh`wHSv^P!sD; -z`Q}1`RVw{z95p&a?>6JuMaaVB+h-z2Nc_{0q-?e%@el?DDtpmkhroRD)JmUUJ-2qS -zDgY!bS*d&snA8@iY7dt6#+Ma!*9S9g<}zykDipS<+t-a&z~o?NGX9hb(&kZVB?ZE= -zBW>~(pNKmF4xu2lcZ6k~BPASDW-X?6vRKG~`T5uq1_@MV$2vy!#TV!z{CQF8S4SCknJN{i~4uaZEmR-_Ch?@uY!Yy{J3bSZyC}sI#{QweNM=?zyU=hK`Ah&)g>~q+6rIk%Q8-;f96Ea{Z{ -zqCRvAvlA7&LmO>bqeEbMvgSj|>MfxHG2M&2$kJYCKNM}rjijBoS;j+9pKI83&zqKm -z0ge()Eeo2~yGl)unEC-~4`i#C2(2|=8A9>RGB+dtn9Yl9`!x$nlXmD|Yth_Vr|%#w -zC3113SwNsa=j;o|G~54;aj#5X+SC4vaZ89sW_)AZ7jvERsV>ppEx0n7crc7%3o`D? -zDBQpmD*}J(vj1S*Lw_;u9QyxY+@rz7JF~qO%u92*0}WQT -z4qdmEfFv|Dby~hA#hE6Tfhj=C;A5eKtv@11*2_E|F<}XM({5f^SUkdic6)#1A7o>$ -ze7uIN4WYKegs(T&^8m5VT%hN=g*QgXq6g>7vAVLFvgwdcpc&eOZ(-XR0v!bl^bg?! -z&a*q1bnIcogxVe)oJv|3*(iP{UNX7Aq5f%p -zIw&?g$j9s{{q$fMZpO9v{g7-E9VHI&Lmc+RGRj@RZoQ8v-$I_aZFKlB*`i&bf?6HK -zeLlp*t0sQ4U8sDT&LB)43n`nqcAKsnT`PSuv7|ko&b9rhv2ol@Th$}iYC!+6%erRU -zY0(VYAM;HSNG0B@R*xiB7D?AXqg}&_=aB0vpSL@FVr)WOw>s~xT%YFpGG=`a4FG90 -zvwuNThP6W6T7Ypw;>1XD;%+aw6g0h=E}U3j2i;AseDB9YsbN!Tl@4Fzsc;cnP|?iG -zVm@}c*RQ-@xN!$cLpuURWron|&CCLXli{Tx7;%uCIR>|0H?X?nt5|`v!g_l{)PlAV -zq?`(?U5GT66Avs{kBUmyBM`KU|YsAu5lFvh_ma><8& -z@lgTZC*}aIhIMlSWd%YJZc3)v{58HKLF-%Tqc*220Wp!Q9zw&RKlf;chvwGua%2rb=P(*A{9H -zF|T&12EWcBw2i+ehAt(<;pLq-ij~jy61(pJ4YO02evc>ut1}}ot^s9nl0>OQndz9y -zsM1DvCWp*DZd1s{U-Lk6xpULu=;ZBz8ao*c65m*H`BByO4T0}Ii8;h$&~Wf%{?jTj&XT_Pqh -zuG&puw=-5#c&H|ofX`)z!TX(9(QAu8fDn=k@CyvLL6^Ku=Bkq>MnKL4-t>)@3+`1w -zUS5e+zUB0SckmeDPy=woXS=}_Oap>KLmSybW3 -z!d2=oygl5gLvVH#UKc}G9)50BwSv1u^kH>=BcVv|ZZpZa-s3L6$C8&Up+NRj)+2(J -zpO6Fclsl9H^FjQjI`5&!U~??Q74CcR`aEy{Of-QY7&HSDy3yItz1!z3U9|c@P*CDK -zVTpg1iaquUU8lsoq|}cQFqG)}Jo;qhIMR9=up;14qSp>6Y=&%8rI(Cr4dmND!S|_X -zS|6{1w0l9yQI+Y>n6%i%p@VK4MrL}V=M$4JvvE&zj~Ph>Yrf#W$-G9#8oI0uI1`v* -zr{cGsPil0w7N<8>FVbgHaIzD^!GXX-`H}3*m_;tw{-kFV5a!e-iVOnc)c0$ER3a5O -zO#`|qk2fv=J#F67ukrwuBvv8M0vJC-9sp%BN1oYr)V*@xnayd8TPzt>{n%-;;POFy -z2^Ilt-`jFxtIP7(LZXn0qo|W5g7Wk1H(uB~qBX2*cA@ZZGGi(B&GVr4Dk?zNFv -zaLC7uIN*+H81+2FN{?Q%o^;!qu1$sg=$xcvVJxxp&fK|Dp0&_z=`-lZa*4w*%r164 -zHIaib=X9BJGDPLy^0ry-X`SZvV)JjPB@}aYJQ@%?8ow2v>QDqIa!b%^#4_!(^0wUQ -z?~%*30Hpoe-okjd^zF^9OjOuz+@Yan^yi*CMopa -zq?QRXCZMZcN;f42OwJ0(#Iu{zDT;O>rLp-3YT0~zOy*X~SYiyu`loEE6Ox};I`@-xNZBX -z2@grhpG{3=P_Z(ylm+JG_+J_&QOTo`dlbRwPPK3+E#nE+6zohK?mGCr*LmrR30)|H -z4a`)>BwOljupk=JJUw*%ey4Bdn&G3O7jYgJ0)AjJv&o9E;&2<&q4t7kj=wLm=oX!h -zeER~R!r=Pm4GA1V_2CftW2+6ZfOu*p;Uz3z)!mROvFiYLXGxD6&Ck?P{uHiNg~0F^ -z)ZU~zUAW)P>&YnOI95f9mKNiqh2_NU7ne-9zT1Mc@x6IjF!6^`1T1PQz%Ew_n?}DC -z=H$lt1RvfO%77~{nVlh}ry+CLfbQs-f{(-r&`4{}hf{76QR)*yDXW$Z1cTu6&_*q9 -z^{c}YV0cv@Syv#R9I=%f!}L{G&vB{nniymaP(UQNQ&&j$yJLsOmh1{M<~k+x(AH4T -zg!zZeQ~8+4wVd{gI7n>P!HNq4dfIWsayXaT%Q-60_J4fK+az3`yuJ?rkN?Ws)rJ8E -z-|{xeVd3PE|B$6$j`Xkp$lHXI-}3faB2nD8yxn79>$kN&ko#YG8$xO|w3a%A-vR)K -z`#m>at(r*Voh -z3n1`C9^Gc^LjI16FOtT>k_&OD%Tg;oA5V=oRjS?KT2~#Um*4WXve37@?UmxCj)+Eo -zJ0OpC_GUltQe|y7W-N&^h7k$yV-dG6DQS&H=fx<3{DIfE4b!uvw$$TadAqCb56D?T -z(c8cBw)(fc9kF2o%-S;>n@@86R+mg#@vpqS_#b&&?_1vfE%T4Oz3HE*mD|GbLa!gj -zsSr9u@~^y&2+Af)@hxxLZFPLrPyZ`#?@^|fhK=EmQ9OfF)nlg2W5yTV{pysD_mBrqNmKG$ -zdQ_uY`NG80RkI140wnH6LDRNqu;E3vw*Mvcv;tG@qlsTb79zOqv(vCqtQ;kg> -zGBxN`2qHkzPNC>|OP!~g8Mm34f2|vKJ|q?6oHOVK%E$~3dPGYr^^9&N*9oQxyC<)lFV0JFnGI6(=d7JtDT)dm2v_v+A*c@JBU-84H1|Iwu?XO&0 -z>QUzGV(2Nt_@ukj+apbw#ZXoQ;ImE`ueeqPXfMrBILz$vHaYY~YI+&{zHRO&%9X<9 -zhH7R%OV;yV`@=b6;$?`+1r4GPY|F`8V4ab$`F7?QXi0i>uRC;DO}RB^;#{eZW*rtA -z6)R7zg_&@UP#8510^qz}sJL`$`oa -z<8q9XmGB-Pn&fD}Gx5n$i~IWGP9r-}VIplVxS2kSQhFRYhz<`C-Y!)rxWg;LC32Y$ -zt$$n-2B)3?6u$zfUL#7wXH9C_yYC-DmuF&KExBEj46d>9M2#$6*p2PdP}i#!!+4Eq -zQ51ogSuSgZHm;ro -zZ+iP8`Ov)YFTJh8iyda+Pn7oIJ25z@SK0pND|_`Sw7(ZaMLr#~MV$IgZ;!lRy1vzH -z37w`}=Z~FIK&<2h)Buf94f9vXV};0mju!T|AY}tUWZRKX)mx^{@KhusF@AYS&hDwV -zG8M>^Rl#BqW!SCKH#jUob4aGt>M6YxAu08=<>A?mP%R%H47p<&9Yf*m4KXX%MGg5W -zhQib!x~tEk^)d!FOExIXldj8+z<#nAA18s*GwjGv>g*EJe25=s<*i|KxWtP_A%q3x -zazov35+5v8x~NK!(iovVtso}=O7j*?&!Yda!Tx=wB&BT*ztDMUzmP3z*q4x_{X1&P(1oP6I#9OgQ#RNBbmMg8CAwf8dw*C63}tg{83Edx&PZRu728~t1m?%j -zP)o*gz%(FfiIjG&8=nQ)knxwl80I}%MEmxJO+FtWSOb*2x?zxWYgGS;|A>bfg{=Uc -zvkpVLgYrogzUuce2bejn@ePx;uu5ICJBwd&?I;s8qhFRDb}#!eDa`gku`CZ&HE_qwN4U3%9)@$g6uSwnUpRiOV6g -zfhLWKyh&z&53tgP!;deJ0iDP{Aoq>Ar(m6WHhm4N6gb?m^G8>v!Z+W@fq(~ee;>_}ROGJPwGrTVyrBi1L^nni!Oi5< -z)a3R46kAlU%{k}!$KIa#Yj3Nmp8b!#jr}Le1xLxR=wEvq>5%~R+umNBA^wlOU2T8l -z85?h6zOn4Z{-8%d)hsXlk&*r%dz;}M;Pu$S%KwkO -zjWYnf@?U#9{I9*u|9k4Mz1{U~Z^wPx+sZyoC&6I`3AQj;Ie4ooq;CPic~4I+l07E~M5LRwGZ*ndfCI?v+Y>p|ua^ -zFnAs3t8dVB{3p3^Pg+ipLCg_QW|O`oBI&a7QE% -zTWBzdbj+HEN&Lovx^Q+q&MsdVnn6?7dpS-8y9q0|pyZh?WD-ehERgozYrQA9^o1p+ -zu!4^%ujezo>h0SK&M}dw@Imua7BvRAZ8VR`VKNl-`k(*6=ABp-m?pdcHol$>#O0dj -zKTVJZx2*ob%pU+a4r7tguEE65CvZpB^Ebm@-_EmRg#o;wKLUtRgAy{fb}2M&0PYBP -zxM{j1))Lvx#WY6P20DkIDal4!t-?8e{Oy~Jr^|OAUvYpzr}Rs8AF46cXlvb>XVM26 -z8zj&+4N`MIlwiRCxd_n|WrrX9P$~I%`A1+>-nWiqpKYK-bB%aTEr)$b+#kNlj^Yp4 -z(YrxWVo3~bRgE;~n2e*9*)(`8{(~w|*Kk8nz?e2dX%9Q$8H2PnoofY4Z^+XY9SEMB -z`OrrG#;TLHsF5!*Xv13keo20M{m}zGJB2-tt#mznSCp7VNVW*aKJ<|j<+=u}X~rl$ -zrcW_Z_%4&iZN>u|%oniPkeE3QHrefwLV6uO0Rs%>THf^ryAIrU=#~g*cWr2t+V~fv -zO>(vmNn1I?%o(3ZvQ3Y=!SZycJq!GU6nQ~~e -z0zXHYP>@V%bqMTqofiD9H$^T;AZr7wFKK&~a|Qgc#KCNkJz`kgPOoi7*1PFet;qmC -zYqK)ev2Q#9t%fueF(qk=lY)ZHM+A2;z^A+$u~5sCL1PDAk|tN+ahZi{s4o{4e?>E6 -zlG&7o?VjJ;3W)^U<&E_RjWJE=q-;vz^l(J74~4aF;qT6n5{};5nEl*t8*r3 -zD&0%v+P1V&tVuwWajLIMBz$>k8QcLh19M7@!Tpd@HH5!TfAp^yutmfSU!3Ng4Pqz7 -z&1-Kw_WJ*FlC8l1QE_YobXfBtvhAq -zsJd0HZ(7N#nH~p2N5y>KL%#C6QE8Xkk`<=%bCfG--X4tid}FWbpz_2!8K0)+7;G}e -z`KhON{%WMi&O={L^}za_5z0AasK+!xHH$b~4WsW-3asKD;yw)X4FGZl8Ar#R!EGhW -zW!3OlMJabi(Dq0D<2&RVI>BP8Eh62(xl;r=dL#L~#MOS5&ZAQ&XV_{2ajiGDM -zqfHZdtD1Z|7j9z$Dz!o*)N=Z;p{|@L-yBEcG72}PhMb-RaGS&L;R-fZ$eG2XT+#6^ -zz>QFbHc^BD`uz#!sd(MmyXFW<{IS#(5ko*S_o`AUS8P$+rq*btBmQVcn8H%~#n821 -z%Lr+f*2w=C-)4CI#<#VeFu3#n>>$G4YkyYcqQOt)?8Fut6KEUtYXAzij*v_)ke*1e_f&S4H}h>F~C7V9 -z5E&MG6jyY!q|!P>sW+-sEp*To^_cm;Bl|W8dvlA|7_2A{CDMacXS%|-xahO+=OzM+ -z11~tcsud=we8!^;7#=FnR+d_uJM*B95oG2?vr%GK<7m;WUa9R(jvC3rO2L3du|z`f -z1J|}rh0TC7ue9?N{RiL14&xE4q>26)-(If##<$H&*8at}9f4(pEC0c_nMD2v-!|MH -zU2`ZsRZfM6Mp87vh4EA=}qJPL&k8GN-Ceg -z#=U2Nry|?u>phic21A=j1qM~+H*8B6P#(-@$N1g0(#*UMaB=(qQ2ZiyYIjY{EJV7} -zB(koY=f*|`(h^k~SnsaOboyg>oW-i(WkLai=7B$9lHd8vq)YJ-ZeO9xc27;gv0b0; -z8JaTLqF@fx^rZ3ofX&lY=A10giU_H#-Mm -zo`)*(D6}lhqP(A&C13P$W$=NUUO)dZUA}sKynYT_*GHYFex1?t$zVr`ogvcW7!C%N -zK9>oOm%(LPsgq^S(o&HoJ$WlNccVB6?5+IBl?eLjoo? -zrI30&$yLd`sOl|<n*6L3)lwZBJ`9E^xCt*~CwwoyH2VZQt>?=f;10q=!|--@(q_<`(Eu{lDEbqVp*ZO0(KJGqr7 -z(kNaRDEXVH9b>#n;M4L^USPs?bK}=3Ez%XQXTt2yd5BZ<{#>$XKVO=O!4-jgSuQ~~ -ztdZo9dVL5{T%9Z1*~$HPoRj~@*6|K-w;;yo=Hx9-)hC3Kx856;bsY^1r -z%Iw{zos}#QmZ_m`2-b)j7=UGXXrM!xO7uPqX*}l`?g~wXv~qvd+7+1qZSDM>&z9Ka -zmj~giAe>M~ri#N=F2f{A9Il_h>Snu4=mLx3(;FI$`a|%pnIT6ce5>4P>eKb(!k$e$ -zGj|oe;FFC{AROF|&1)(Xi_Q+q2E%pe6f-q?bHMTO);_PTSknfN%yL}8Cp-4~c~nz= -zi;b_BWxA#AzM@Q;Y*CCL6VmZEa?*aUB^ntnr^hkjv_}z-NwSBf*&H4JOLvNwj?m-E+*dn(!-`7!(>t)v;b;BzH#)4voR}u^z}OOlq?2FET#GOF8xQYoqQyxnz(h$ -z8V$AMNdpPH#<1CnD-c6=C8sj!7ll}2gBaFV;~A7A6p04m9l2eGn3ZbC^Ua1K5_t;&{Ml~SXm%2dQZs?b8se#(CQAB>|&8xDK$SoZ1ZMRIvU*j>U{H(zE;fvD -zTzR!XQ!Db(xdKeI&NL!x=cDyon$cUn-ktAD3v*%);waN}9N?EVFGTHd#%bL-L{}gW -z-`>PveA#wyDPVntdxO(vVR70n*0eKqyvIG_ZCH4TuvPwD;-G|*CXNS*>8u<{v^OIG -zI?hD_x66&mAkV|+-MX;$xL&mib`3;clr}l0*ucFRWEer_*n9CVaNmjpNbKpbe8goHbrn3~?GaRN%Aa -zP8&~P($$8+mYB-xXeq|I=<(@PZKk_X4c}ag&Kh1~BB;C4D{g3{Rh#gdGVk>{+_AXIY%hOQ-aK_E8pPW}@?8d% -zHWvfc6R#@$iyB>2uopc?`t9B{=|mC(>zbmYqW#x%=%Jo%wrH@UAFm6R%yLg86Cx`NJCEt4)9A22Oe{vehrh*0nip=N+)ZiGi|Ph!#gVodkkfY^%dF3FP30@%`e -z41=3@PHqF3*(r#^S?VYVhC#i4`E;B0<7LAbNqPgq`}{!1-7&?ja)NgswS`V2F_Z_l -z&t4o$PbkZ2R{HKsqAxRY5R8mw;UFbtoqyc8MKaZE6dMZ+Z6_^&&OyKt6Oe8(Gn3iV -zg}6Ps$T!U?y#yvV%|6dpHPtPB7YW)D_SQ#!9OtWKY&|1*3uWlSSP&sKngekJYM7`G<219#M -zt66!7oSUF3jg`aSJ4s3Knkf8G3uMzp+Z;UD>>wwCwR1%lVjIIDW;t&SNPbd9Yal~! -zzgLhw9ebTqKF%}rUf&M)Wuu^z8)kWJb1 -zYo8pW$Mt0cA9<=?m28s0H(dk+tE?bvVZ}Y43;THI-Ok7^M6u-P+k{1Z=pPoKjXpG& -zY8~Z&q?}uu{g=M|?q1(6DEvd;#)})5!hF=XliA=}MHhILgsb3ykZsI_ -zo2iyRq@$2I%H!=--MRzxZGn4z8xX$zpl{<8-Rs*p+LG$zrqTd?yI+zMb_Vt6$AiAz -z3(&WT*3SxL!hY)8D)=wQNfGglXB2T16G~M*(ckvpG0Sj$wCTCrFCS%H*FlN0{MxH2Dw2Zzf&8WXBtI9{#<9V=T(%azPV+15Qkv* -zcT5`sN{G+lu^S{GfOj}V-D3-O%Go%}1go4UseQ`tKs8=$?aN!;USAmap|vn#Z+=^; -zXuh(H@!=dkt##G{9@seQz?%EQW+ca&iFylHkg|66uACWGkEaeJs+@HbVVJhCJBcg3 -z9L{3$O*F=^HHzmC8936?^^lySHS2M-H=VW|s4`Z3mLv8qqZRU>VjO21-8co-EI_~! -z^=+uzQ0!3Hz}=U|tC_J~P=&UFz}}b$yPBi!xD5KJCH1kX3noFFGk^&9cflsd -z&ghkub&)ewrVWT&4bn0i(nds2%OWlAAr5V*Y7tGH4(ARDrfXtBY)*iAt(zC6RVCVw -zI6u=0Jj5a*3Bav=Pl~3~1Zd -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 -zs++(Va?0!V*elo&QL%B5g|M8sh@^NdcRt}; -zKy6vGr-ew|Xm@lnnp#Td4IG!&Mc^w!)or1$Djw}m$=h1e1i&Mlut -z+mYr`6CrEZK}NR0`OF;$p7a2JTji&}UEmD!=x>7+cHnB?``eV8T$py2XfzN0c7fdz -z;iJFZ_q^Ob8{ls*X+8McfepDC1)?yH5B_!m#8Ada(bR0Ml4HJD$+OG6#fyP^fBQBr -zqhiW~eT-?6&Q85T^TFSy2J+4Y_}iZV{`L*g!QiJixddq`JFdRG-TeoCKXv47#6bq -zixo4nid11DzI)`*O`YR|&QwySwykNwpom2IZ(7f*CVXB}2xlU+h!N4gcFu#$RVIwb -z*NmQu8*g<4MQ+ZwFV>(c1CE8pTjpg*ArE=)tpsz`l?j(Hd`xqrEiT}*uDzSTMGcdc -z@ELTF@;08@oH>?$j=5~C@;V&;#$slA&SM7qAQ0L>8}-rOF6n79-5(hSMp(2By*9Ca -z2Za8y66p^{85-y -z!~G`9&CW5TLLm($-MJ>R@c1lgWyMaYqq{7}{Uv5-pkAwS-N=jb#EVqnCKGPYSv3w* -zaNvuONeOoCaHh%R?MdN+P%`|YnH}^^YSC=Ib*#3Xfa&Fh%~r&|1z~F`%{3~iMnVqc -z(lY;b*SR*!kZ!KNyHtM7S}y}rdLEZZ5``sp_D>6k-8tfrL9K|_VF?UaIh`}IxRFeB -zgG_$HRLj`XrRr+hez)l)k$|zX4{g^ye*U|>=Lw#wLp%vi2=G~ARR^%lvO;FwQ<8Ek -zDO5w8I$re-Ol6>c&vJk{kHC`7wRW7^a9Sgmi3sUWJa<4hFHzmwt~%XPxOn=v&6DVT -z$in#pXJfdSO!JLp$(oAI-4h{3h4|Oe2Qev_?|cmWGQ^Mx)+PDivx0yqRJKsUVO|ic -zV0cn-H-gQ))}XDN>WXAV67xB|nD9K{RqS&!Y+<7wHS*X2ixDC!2dwmCa==J$By38x -zq0Q=wo&~qXlgDpA#gV3Zqh*JIeWbgl!%swYiY5cjLezNL1WM4Fy#K2e0cW1$tHYNg -zgr`wa5b}^V3udhyY>vGiv%dgtw&E9CnGXQ>m-Q!rTboOaJNqwydl1yX%a`w^X2j>^ -z-roTC@IAm?&BYfRSVG>UJj^haL3I>&Ety%@a&e65kP~^uToqENNyM4t4b)(tcZWra -zxBW3i?^R%9>?J5zuH3WB+)qyJNLI9iAZ89SM>kqc`d79Jka%CFNG!f4SsFpSl0zI>9sO#w74f)3CC*aWXh$tV^W(j;7+b*w#pNhqtQ=v%^O48jB{#1 -zknyihwfVpz|H!e8P<=Nj0yM_Bj7t?&U3q2fWC`@QXd1rj=dDEXi?`E@O3#$-~b2J1lO8sZsXVlMNMVlwqAC?#i7-Bm6+7GN&(BKo7CD -zM!)iMTC;UmS<6Bb>SJgSp>~fI)@%E}{1f07jFktQ#rYH9_D%r+++|tYjm2d#(O>0> -zUVgn=y|Q;TwrhYKj_4%mMw|J@#5If#$a*f({3s-y@~nXxB~P@A*B$$#fC>;ZcM8hs -zWfl27z@4TxyUrt&;sXG<^RK|%Ny7jDw^xvEeDyuR{SpZd0TuZdzzv&p`v`Dr{|n%j -z{}bR|g#9PLt$0kFjoMT33*aV#jcYjzSa31#{|Rv4q>h4_8F8ki>PXQiSjYl%xDb8A -z-oyG@8WfR-bTXi5Jfx69A?d=^o4G8Qv>208!Yw?1?Bo_OtiT;~3rE}Mp*WOf -zL((>I_Azd1qnHIP)9meWfkgHU?B$2fL{88+s1UMoR!2Ldgp3M=aU6HW{CV<`gu}NR__EvZ3Si@u6mAYlyGqBm=y>NdZ(We%jc|BW#wJ0LUOf&t)(VCMq9C;O -zH$Dam^jL(|awoh-<0v*Vhkcj3E@HZe=(^_-Y{HdQA)xQ3*&e(53F>H-LgR3J -zUk?Gp_vAnbX(8G|bMjduY3*6Y(3A%2qzCD#`+ -z65T_$zOIJ2#GUxC6~iUx1iW^u)~7#>>Ehay%*VZR61YmtEWRH-7v@=4)906Y1<@A* -zb>LwLq=SxK;YvgV)gVD=cO_6{>U>M4tO~YMN_s5eL!+rriR$N* -zyUTn8&AJ-h<|%rBzO+v^4n>Z*2~)>5&#Cqy7NWkg{AHL;f27493{@}M>@AaarXpEZHiaMAuGTs5NViL -ziwK@^scCh>mw=x$e&|-ptK*N7HhYterfozQEMQ(Hr1-uupQLY6{p<&bJfV2|50{y| -z7qoc?XhZ?kVnhb$`dp6GgmA4%1sbUosJnID-zaTF9KFWUcyY$c1fR)5#8|)CsLx45 -zJ$2bvIg657GlV0?@|3|FZB^Rl+M{4?^$YtEc#u4)QDz<)S=)8c1SgTg5AL{T?*mg| -zCpka0fzHJwh`WBQHN(DevaP5AukQH~{&N{(>6Lp%Yjln^Ds2K|j*S -zEET^`ll01bSCQ!#%wKB`HidO3m(MCq?RrP`+z+3Wc6MLMk5oGdpSL)u+Y3gIJpA(x -zO$%Cub4KF@Uy{2>%9$W=lBpGXb1Dp09Km?2p^;kSt!I>p?AdNSWS|X%u7Fz|9Sha% -zcx*wy)upfy(O1{*z5N><4Y!*Gj)vR$W|g(`o692`*Bb@p^Q&pD_Gah(LtCSD+!`K| -zsp}6$XQz>8qRES@cc&3IbHn?%lpRQ$v0pVj?VOxm?#R$`H&c(Un+RWBo@{RKvu~X3 -z?x?w`E~=_Eb9dF)d~UemY;d`~JU#n%bGvx!>Tq>s-@tjevszz3%6xoloV5L1Q+leOBM9|_osv&sQhnoeTb5!IS&p7w_q#AFo&ynAgPn*$Z)LkKnq;S4 -zw&Y`{t0l)Nfg4`(;hIl@-}{_!sLrIIpg{i~^N4(f4#NOfvMr=!@spgRHEv9&-=~B8 -z=T{6f_M6AKNb5}e8|Ny;&*{tX^Zgch`jB(<#+8~ev2{Cfn~Trhmn+(XUF77~?-W-= -zXScQ*XBV*p;*&kY4JS`1qJEveEGlw) -z=G$}(;YHmXe_oDsmy(Kh=cna}qyR))nZizO*7LRGaNr=d6c?}7cd%v8D#~p%v|5atZnp+WbnOJe?+Y-J+cz&47o??PAumHX2n~f8y4O|j?ygHO?D%xu_glyY1*V~{i)&V_`UbP2=0JKf*b1(f?MvM -z;D$MvD;!<0Sn__0N*9{R;bwMU-r;~J}i$YTC3k@Jp7*XQ9M8pjam;Fme@Cq}&DIKXi -zn*&td)-Z6!$%b)gNI_BdGyJt4$DR)tK%^8viv7e1WsqdqCB+*j-;K=-JeStQAZfwx -z4!C`;h)0M50{!iH_3>R>Ygc`~O`n1=qgE}@nKD(Rt|xVH%dQ)&gXvaLPKV&HpW>>J -zHVqKqe8?6KAok_YtU&a`bR^0~$axmxJeqWa`qE%dCGxWX8gAFuFWESSZU&ek303r{Bk_Tkw4MDHb`NN|?# -zK5ke;jkGGmDu)wXHZCl3Hs+gW8yNnfY-Jdh42Ke)>yp(XcZIHj7`QLI-*4AYMMvt` -zq}XZ2^=I6bmEvmSiZ)AKXx6ZGlU&;TDERk9Fy!E47zzd5FXbn5zj*3K$akH-) -zB83{v*P~*mrAjU}g71t<%~sFcc2lt(9Z*Ow`tMHH%|E@Rqg#b{5#=7rQd0}-RJ%QM -z8wj1BoZ!R}{s~f8;Pt7E54!9uvaFjbX8$X5$P{JDpLgoh?vkIU!@IuWm*38z*d_Lm4jR -z&TtyTzF306+0Z+rune;`^LpdIq&RlC^z4yI|4s4H2`#0{5@*<; -zAlg&s-hP|pYr7SAQQY-r8(&9r!lzbxgM++;v85U -znS3=CJY{@;tK4y@Y(KS+6kD7cgA!qm*fyL!0$x?2yTuA4PSxnR2bEaHN%u{F -z>U3xBTkN^~P14u*j@YOrur@Zxrs??U{ui-{1%=MTtE)}d@cAV-;A;Vn449aHp?luG^RCo6Vi|$l_BN_KjL~k#P*trjfTO#1O}=;Ygq(Ab@$SLU9-4#L*#j8b`1gi(Lm0r&*6|Yu7}}S3 -znUf9xL)#xR_1@5id@{6Ky#cjRcgYqSkE?<8 -z4S=ETa`t3s6W$xz68DBSm?H0pfmP3=p$&-=b8l#u0u1eM2=1RGMTv?EnXI1-?WIA8 -z8i1i)1TeH;KN;F4idS^jNkB0OEuIaYXkSQqs)u+1hIZg@L)+=z&_4VGFtpZ3YXFot=k^zQxowzT+&<=hwv@5CrhBn17Lwg*wVD!<@ -zE_^Vw!ILi&?hWlMyD_uhhBouPp^bP8xbRUEG7!_XoO?t23k+(&FGD-H-~HCyU|$_z -zXgBZR9M5fP0}O3<2fD&1LtF2sq5aAl@k0AgL%Y0#Cjc(TBarP1d7l2!(4PFChV~rg -zpN6(Rz|c;<{b^{MzV`WPXyaFc)BVtHd@!_k{xG!9vpkk+9u4g>M;&l^#G_8JlMdE2 -zXxDo~n+u$-2IK?QyL4;F?toZIfT1m212D8NBc2RxX9<9zodPhl6-Y?U@wpgsfc%Wf -zZ66G6!(WDWFVM^XG_=|NFtqi58`^3AHnb<0{$Xf~{C_dD5jB4r+J^UrHpzb(+CVD+ -zLpwR(FGE{+;d8?OFtlr9g~tJgc5a4V>L=X~Dn1pz3~d3E2SXd^$#u_Pr5g>p~rcge;V2WKMiff -zCqo+uqD?Iq{J#xt%D)WlvA+y$nny$18DMCCfq5{ryUo3f0fsiuABJ|x|I5&31Q^<7 -z6%h}Hw)t;EoAuGqM%7Bgc{H^BF7FL(Mu4H+26Ddo)6iaK(!zc)v;kXp4~F(c|Gl9d -z4*g^7x1rr>;`z(aew%b}Xuo*|Ftiu%4Q;C;u-8(F<2iuHM*TMLCqtVATZ|Qo@t2_u -z{A6g?0u1f6O@HD_1Aw8OZD3;Z+t5Z{ixYn|w3{9b?ZtaTyA>h~U}ziM8`_yIa2ZBz -zk?VN7iC(G?hIT?7z|i*p!_fXAKmSU;)JabsU}#&#{9$O{4W__jK)58q*VaB6+Fp8( -zhW1x-(rlq`h%%x-4ehQ+L%XFDU}%4OFtl5q|I^TB0vOtdT+jeRTmHe&u7&6PWoYja -zg4$zbQfBDfxB?7qXDf?84Q=&%L)*Ore=xMk?+xwGPlh&ysbZ=;9+#A|t_lC9&z|dBFG_6X9ePIBGHU{kLXTJ>XSD3^^e;C>re;L}B@9qt4b)El*q3!(-L)-n{(0=x4 -zXun^ee33#J{a|SO_a+-Z8rq;tN!E{swpm>U+yC3pE&~|a8EGgc`Gv_uj^MZ=07DzH -z{mIZ?*iZ+#H?-9r3~h>gL%UeY{NILl&Xb|-6aJ^6J^kCzew+NChIWs1zW%+Ty|eIS -zXe$5=?eo~+9)O{(4=}W6D*=XfoLIf|@ROnK{L9de|7~c){WP@Y?+xwQVI7wTLwo$m -z(2i2LH?(Q)4Q-JgcTeUd#6D~4Xv}{a+Hn{g>ko!D1i;X)`}Et;=KO7FOa3yn(S91* -z763y#@AXeZyZX`4c78Opx1J1b)CWVG=-$xQd@!_|e;L{?|1`7#liqPYp5p*RTl2?1 -z4DDbV)_)n=6!(TU9Kg`_yEn8$|2DMqo(%1-|ErEQ5Y;Xy^Txp-o8-fd9Xj3@d8`?aGsP~3;){~*li;<+>PkwJ`i=|redL(hEr~Jdv -zE@1nop)H#TB -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 -z)z;Jn;h~Z_qiN%OadO^4s|Oz0p@s)Ce}GI -zs@7Tw%uHkCgUKsfZDP196y%=p3IC|^%Fi)#_DZZweOwTgdzL%xO^c`b>*grl?JKhK -ztPIIz)1LSTAq%=)Us2)XX!Nogur-?-DSX~Wyr(Dk&v7nZQR$#VL0US-Y1!oT+-|Di -z75!$~;H*())xPk$xiL%rDkm3dCV^9&t-(jt10=zTsyWu9$tAI^u=Zm`5QH8JN -z%}DdY*LKJn|1GrDi4nzDSxp%E567U-FxM}WrsU1E_LO_y%*XkPRFAUq!_WgWb0bh* -z63F|u$OTLp%xYgjSF|?g?9G=0kw7#6vN)2mvT?WPWn|gCcE!i?kTgHhMZfh>P4u4s -zd@@AQo29e2g5$J8=ic7k!G;BT8J!|6NH>)c0Kl;g3afaxYQ6 -z7Q^-~_3Cg_P!2!^CkEDcqk<0(^^5538G1x=>asm(z^c@z3|~0_eFGM5+32fcg<0d5 -zoeORI)G5{@@D*iKV+6V6c4C+em6Z=dczjF!xupKH!6ubRgnF!g_Ty~hW7+q;bQmJu -zJtOSM80G_F4&S1rIhD9ED4A1*aaE0{q9u*PBc&o -z84cxa651mG8HVM#iFA~4bql#yiT1r!O -znRdLEbiqhHll8n>urkHDqP?sug-w!14$<)S>jR+?NBuNtfw9vKeN}Cgju0>(gF|(1 -zwpGv7*L-)Ad?BbrmcoS@^H=Go?zrR=`$Bd&WaMz^ouc;P=9>u)OqIU?X9BMN{2WwTqPO}2jYg()OulXA+Ex+C|1Z7 -zF@|7hR0ni-;d0t)bqQh$l8t`&j1w%Ly31fN@}Os7r9#)NreH8z-pzbM)WY(}%P~R? -zop9xAt%N$v?+1V2v&Ai2egG~05F4Z5f9CyNtr?zlKkLn|S>r6F=R#m@Xum>F;d;ah -zPhV8cD*=smIgWGQc>4vy7UxeYYw6(~xH2Cj-+td@#Z8G91dcw2_Zo!&CAig`bdd!(946 -z{6Gg_G|jXKT?ckDpW~3zD`1o>H9+@>IK4#+u8bdQWrf-7;QAmMIiVk+Hs(A;H0gg0 -zB%?6O+oL%5)$z~(n-%3^+q$zhy6S=HqkdHQFfeV5a*-E+Eq%Pl%-GrtbI8wFz*b(v -zqwp7~1DTp_L-zJDQ}>MBfjJvoP%AEp-6^A@%n;)i$}<9Hun3m1Az|P@P%)?1?!s=y -zE5HOPZh5QVbELLxwgXDn;Y -zWquOP?6qZXBY2z_y*_~=5@et$Ro?d(gZQdhxX&P!{79|YmUPj<@fP!0rOK)g^ -zgy)1t+N#qha2Dx=(NZ<3OB!$w-nuS&2io9;&Y-#8mehkq^W3u;qIky$@)3|lWJPfc -zJV>Q$Rk?4SkY)~joTlX4E3HcrMwt!?O_ -zVaR}}E89B)`H~7*T&!d^*KsR@pcMF0MoBo^bhYW8$6{b6>}>W^vY@`IFLcaWSL4A!hH!bn{h_ce9A?uJFcjSWL_^;&6;bvJ1bWS?vnM^;zQ#%yr$j_Yt5p4SwY$5j*T@?2&+s$}=DG=}4`eG%stDRsM^2>O# -z4-7GTN=it}G!r}!*?F>LE;x^|Ib6yMad)l@C$ue>gvW_7;`~}dmY`gX|Jh!em=d*C&r+z2h>T;X71(Bq_ -z=oXZWihIw2&o%PSbQ$Vi^rJmWnYfx&u$N+?E5^Dj{1s{CyBHVkI-zG5o2B5Axg3U7 -ziF7n!z7)kZO?T7R>UlK>N~z(lCi -zETaQAca^ffnmul2i^GehvvyW+vS=Fu|1@Q0NR^3Vp7%oKfTVa3nt4HxmY2+sBefEY -zW-394F$~YS=Eh|t1)*4R1Q?5RwAY$|c0u)14~$}`t0#F|P<1Ha1}94mp*8U{v7IB1 -zPE~+#RM&239Dt>7yqc0MPnLr8<+zlLTcmVEdu70bG1msBkEb@WD!S=+t2{SAZH;=G -z$pR$I80J?6yja+YOSw*#ViWs;`W35XC>_jwtCg32R_AlRO?*tx -zZQ8+x$c>?vu50i24O6gE86kcMLVVl5h(QYWFv2}?uRThw)c_zS!W^h3RS~YztJ;HgQe92L`6@IVU -zn2Ql4J7f1`D8gXZRP0HT0z5_$c|&L#%ji3ey}-O%WMu{tde?oJ^3)vr>zn-;thmSn -zHyF?SE9k!j_ZduQLqu*RY@$PqObOz?ax$kcyD?F%^jl@}OVJq*7ZHJW!cn(R{JbH} -zT4fGRh`3Y}Xqu^2{9#e3X=s?B2QeXS(4W=S-neObJ -zaPhMeHx>Umf1^lp9~snp0upX~npnqtby(8(yS!*Q1lqbSP8n6_DvZ4#e?S0(y2-uD+L_|yqv5(8n8(jcJlo(%Wg19nMdv#CQYg-OT2Lhdf|5zhHNyA&+O -z@YnZ5<*rxo6e*{=?AcdeO*1U6S9^?Sl-my*SZc=j5x5PC=ZR3&G9c#&16Ex%rYGO1 -z6XF7jeO?WPhzbWqycBJiB9r1BdZ3BpV#j8YH3_BYjYANX3uLVf4C -zgaEB7{?1hLUc$#&!>raxsy&yS_S2=R*_cC5vb9v6k294$dJ}5hK|m}>Df>K79{j#- -z%Z4!CcF)wMN1_)TW|p>shQd|Apd1`MTwi!421u6K`&M_aoXWDx3(YL~x7HYNC>2gq -z>p$m5I3&DEE9LEXVXfj1Uf}Y{o999a*(;3-9+!owJ%JD>)76j5ih;$tm%LTF7_?aM -z7R^qoG~v#&h(Tmu2bX_@{s2$({)F(d39Ab=hYSDuW6Xl?1Yi6Kq;z4qfSpHR#fSN= -zmy@IkZPhH;XZeuQE8Tau*W($BplO}Y6?^p*R2IF~X$Xfl##?wEdBJ(Vu-j5g5E817 -z#va1nV}@69&hl(t_VkaAQmM3MnR~k^th&FpI3Ut; -zy@rRAa>b`O$nz9%QltYbK3UP~lX!4GUZXnP-YiweL0uL=aD2F$ex{kAWVM0d_qh(9 -za_lU%q=tZ9Y)0ugWXfeTU!Pji+4~L=wJ4c?VO0#`#dP`le8utG1GeSH^xF!Alj)vG -zmt1_{X(CmvB#ZW?i^pjdTSOl|i8z_S4T!OGl=?b;|02SDza=|P&0X7=ym@Nx -z>q_*`?*~0MbmNSUo+n+%emHpsh{MxXVO@3`W?u~M(y&O5-ks1SE$ -z1)Y?5=Fi1uq_oI9gBOQE4cG$?;Fr>H+JW@znXb**ybK#1HDl56>)B7RhLa9T(X`DM -z_V>lGl6c_fmE?{G2b%aYDw!z*J!=6Wk_-h-~-b+AVBIF -zFbpBXT@RpEt)O)A$9#w|-#9jPi?BzYzs}^CO9_eO6ir0$=R?@3dQ(_r$P=Q-obK); -z=V5z@JBu;BhB@HD^_6!*Ajz<{K -zyWHJ=p$J$O!jTqp-uWxu6x*|#PPlCtoQ6)bIyS$vvvN9ipOa-=t{3XFAk7B>+4_83 -z^3MTS!w#&1u|)(+if;B@ADcn~UjmBzHadG#8GP@#+TDk&vwD~r@3;XOQ}hI#GhOMs -ze2{r8gdzW-cXgIB-ilSK*t5d&`BJv^6vHZ+?iXNFkq;2nAazaZoI1_Ol)3z&$*#zcKhr;T;CTHAWUge&`S8G88HAx@Y;8{Px!DgLVu}%GBnJ -zIq2;M@qkC`50Eup)tyuY+;Z>RxQYgs;0rLen#o~1rQWH@g;}>oX^`!c?!Ym4zx(cKH_4#3|JKv)`r&C8{=?Jm``ey& -zQNe%YX-m-m;%P&v{_1H@A^w@CZOnMu^bb!PCF3`qb{&Qa>~~N5o$xnL8~3k0ZMCK+ -zPkZ6X(>|m4)zg+RPnG(`(`F{*jQlfCTjV#M_R!3CPn+r=p7vS#UwGPMgMKlEbN}jT -zv;MKCo%O@hHu&Lb5B%b3*8n_iH_+~X@wAcE{{N!m@>-@&kws+mP|E;IZ@()k@ -zKRoSt+CT8Lwf@-Ce)+4XJ@fF#o_6G4d)lCXsya>HcR= -zyX%{$jr(tT+BSdeX;@pgzxK54QonoJFTZ)(Do>vF&F?*JmcR70_ey``X`?-P -z+MGW;ZR+27+J*OMynpCvBXRx>Py12{;AzwUmp$!E;P0OHHY>o>?qdBHPg~^gdD?LT -zPoB2K+`oF-XYYS_+Jpato;JZBd)myudfJjwf8l9M1^yrPw5|Th(|-Hi)3z}By{CO* -z1Msv}^8d@8cF6cIo;CuJaqaIsZL&Y`v>|`*X-od8r@d|UC!TiZ-}AI*M8134iy;4= -zr(MVMA9>o1|M0Xs|H;!n`;R?s;Wz(TPh0Na_O$c=+|%Yghd$eS^0e80c-jiT^|WhE -z|Bk1*Z%5h3;gi3C%=2z=l|?!hXFiosj2^r -zrw#XSdD>3GPo8$qKYQ9xzwxvg|CXm+`|dA2?Pj6B^t8L?e&cC_{I#e3_2VCT+KHE$ -zdy)U-Y5Ot$+n%<_@Sl6yEdPt1w&71t`*)r;_y3Zo4gVi_+Sb_3w1fX!JngAJ@wAiwTRiRafA+L5CjQCOHu}4sHl@aY=xKNTtEX-M_dV^} -z|GcLi^TX2)|KVwaee<+)pa0&|X8qOE2K(>uw0nNzY0LhBr;YYEJZHo5)o%UbxwCVmQJ?-Sb_OyHQ|J2it`Tx16J@G&2X>a^DdD@dV -zKRxZAp7u{q`=_V<|Ej0W^ya6h{nOL_>1qG;w10ZqKRxZAp7u{q`=_V<)6@RxY5(-J -ze|p+KJ?)>K_D@gyO+ePFhthn(PfxqsH$_ga*f(!yKks4~vErwv{Rnq`I12RB)5b6Q -z>1n@5YqT6Ny_JjJNlE?bY5(-Je|p+KJ#DMi?ZFYWpPn{~oP?R_Pfwe~kmRVOeG6mY -z<4&yiPfz=&r~T8@?n%)4>1o5}{`9nIetOzJJ?)>K_D@fHMni_JRNO}3|AeRQc00PC -zv5hEZs}QTV4gj>-0f06oZWCK|A5w?Z)JN_O3Zq3s`lz5MK)cyJ;t9}}`2lEG9wS2F -zQs=K0G8?@0PUf%D!@a&4KDO46dz2&G7_impuX6!tivr06=>Y0BFaY6@3G=y$Q#Ih0CWUut0GI`?wEj -z{qz8Uc3wEA%m9${6QKRb$jHge1OT+@tkdhJ)D0sw7`CqVn`8=$?F -zFTwl+&_)aY4rsrQ)&Kz7#2ZND1W+vV697QlA)5aQ&~|wOwEMpU+6VwZ`}yX1bPP4- -zjc*44(BAkCXon7J*ONUr>p9pw_zq|*noHh8uLA&WHEiYeItt&RCqP?T%3wZ`Wbg^l -zHYR|#rkwc>Xukje+9;Hg3h)@e0NOLl+FSrYJI@wx003wce+RVBzX94Qiiks%q617# -zPk?sWZm|POFaXd7i4Do1UAK63OcQY6t|+Ge4bYBw0<_%$fc9qd{5L?`4ghHPAfs=% -zz|U~UVgLYb-EV-l+CuN?P>; -z(EbDtig`*3`3=x!1OVC$zR_7kuYUmA@c=+OGD@k0TElGyPWlUH3;@s`mBw1ohGHqSo*?V-0D-vRA5A;=$qHU|LEmInaZ!q11qtqXl?9wQ~Oa)Tf$egN8^ -zKkj0G1GEFa0otWM0PSe4G60}$`UGg3KLOfRPk{DzO&sN6F515W+RCF45(QhSKLG94 -zp(&9d0H6))1@{DK&(*T|{{zr21OVE}-vDht0HAI11JJ%=0<8fwm9_ygUYM8(}zXRGvEF0>+jeS&Y -z`P2DU9RNW4#V>$%G62wC1#)}>w1bq8Rh2pYpG^S(?c48wwgLdq&iob7jvuYl`37ij -zKLOf#*D==sK>NX5rVRjS&;9~v7k&q{RRMr@L~+PBK%16Ma_l>xo$c76=vzTgw99#Q -z-uDgAPJIHj>z@Gar6)kU`Em;YXtP}mxyW?wvm!@-1GM3v0PP`WGzHuKxyT%Rd3ylmI|`5ddg|b^QRef$)KNegN8emJ?5awsdQ) -zx0>y1I{AM9+AdFkwx2zzI{?rQf~7}tPT>gt9iTk`nK}If(8l)zeUL7H0<`M@fVTK| -zKwF&b7eG7aJD^Q+`8dANLdO|FI_T40?UoKo^-f(~X&UjKjOKo$F`5vV0|g-p*z-$r -z@jK4cXjZX^5y#h}V9&j}SIaGmp9$%KtuQ9tMk}(-#KC{;ue7KT@^M7J7^)Mpn2dg$ -z+n;;;<=T4JMzt1_?kJ{upn8dVC_O~#;^QzMc@KCP596SJ_WP9!-xAHV<|Gt<`x9b* -zdM7WRygcXqysz~lGp{qeG{X4?7wSN>^BZ{lfiEW1TtKiCQEyJ@Ae2TwK?233WvSTI -zfP!xr*-j>3d#qY2$+P8EWF# -z@nvF-Vn%tQn1{+(Tta7>T3FAO+p5Nvrs3VB^+KJkh(>)Kp$yNJKIAGf%`Eh=b}oqy -z1c$fug9fC9(FvpqpUoG6E8juvrfxA>X3Bi{8glP4#2VM-H6UF?#yloJ7NS1-{Pv6Z -z(Mq2{wlpE{LXsfv=LKEqm|vSq*!+9S$8#XUdf=?qhrij|!~rz@ZJAkK95E_S_BH~KmB9~t -zyPE^J4yEm -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 -zm}%b14xQ2AvsV};w)$1 -zGVuzWTbGQv>}=;0y-vXp-HP9mSb}Iocy~ll{;BZ5cUhm -z4k>+t`W{&7zL>A~%}4uthe0+^h9E&&RXlu?T#{;@2Q~fls!;U`1^xiRpVS+X}hD -zU5ULRLk*k@jKbYoqA^VURszPL>WnmTj`fO^zz4$Crb*&DmL=Y -zN!)9<2sS~gEm4T7a2V818e|9X16g=Io5YsmoH{bJ^2GHKdWUrpVcA?XMq4#CV05j( -zii58)jm@?N^RpB{&^@ZLoin2;$xD}I3zN6IS53iZ-uAf&1wZE*^sosy=_!=$&uKBa -z!>E-bdjLi+4wYYd-!*?~d0JwIGOVM{4gcmGl>CV3%gz1$^_Dk1A*Q)OWnu9V{|P#h -z@yRFc^v87H^i5Qb_)?^(vX2ti{vKhX3o(}IC$3u`5{_nyWzDd`0@vG)mS{wajbZD? -zWBSaZVVTq*%7xh1)3Dv3<~uz=yJNijq20{Y6w;Joy{UQF6QfbyHoZQM)7jq4%?=Mf -zB!uMhyfY8w9j0Qlh3vbSBS*t{Gd8*ysY$$7geYR(8a>T`PS(bM9~i8xKzMMJTWO{t`=cC%E{w#o%E!nl=kgPIkBk>Nq)z+&{x -zZC1Y)iE642_3!jS<=P3V;39i6)1tYZIhX&DWT%IqYF*Tivr9-r!!7kw -zP+hMa_8xLoV0Wu=LIQ4g#XEs0>f)XY#}{#**?NZW;VcV_+^I>OD5$P%*R!FG8y-dm -zPAwP9L#h(9r^%>64!&jloC2$5%0Y=iZ8}%Z3Mr{#!BQN&A)UBkHJ(r+c)JUpO8|{v -z1g^0UH{-S*$hZfjd?>E4*v}oMW&$~F`}#AI_;+_(j8*HzXy+Gqd&l?o_L?XmsyEsJ -z;_k|cBfMTI)!92$ZE{K@G$K6JSEp#IK5&7zGTwj>ad}z_8@o)2glMM=2};XbO0Hk| -z{>j}=oTVMF4Zkn07<0R0x^d@idA?CoQ-?uQS5-V&7bei~g02~)EaV-8gu6y*g1|jl -z=a-V%o1Szi4N+})<*yJvO`atknXe#D`mZG)j{}JpyJ!cqdXG8KXMhgAsDTZrQ|8%djF=zvYCiS|{s=JO;^@NIRJ7YuxR6+Inekjg5(S+~2_m=PsP -z_%>%M*EV{O-sH-fvv2tmJ>G`AmTA-j5t&&T7A++U-80dG}pw%pd;p^f;867=1jR6riASaN59Mu>Vb -zRN%h5+eJ_AwmExD2f=##quK>kvJ%>K<3S}7(Ed%YBzbaWGy&r^8nGF`-R8~%xZ7r# -z7XWu#WS70v>YWO_x_PSfwdExR9jH~S5+P^wyul0>L*qD2xs7x+Bi)E6Lss?DIY%o$ -z3C+8rI{Wk6D7s0vvEl}3^Sv@|QpWd92}$npjYV<d|R@EyDuuggE25W5|)B97J_! -zT2T5t#q{_-FefuvyIZi9tiAZmZPK-HbO3BZT_)|k&3kL<1Xb7Sly0r=giN8B@t@pn -zMK;p~D+Ua6G6&AbRC`W4V0*_i%ohU7svm*b+(L_;C(lBur+({hJGvgb{>I(r76!Q6 -zYzDP`hw^*h-R%p2yS;sr@bN3wk!hRER0wRKoHCR&0Z($sw#WK=>8cd0oAF43J(BQ4xk4YwjglrA;nHAm1raJu{ADF2qAc5#0mmF0h9S{*+d&?brrO+ -zkeEbI6#j?%ZAKD*|0B%;I{0LU1lz&U3RBt15B8UZ@i`2Oj#tw1Ro*nBG|y3sK9lX} -zOU7xn5oZg5aK0e7T@!;q)pIXl5AUH;Ex;Y{kA8_4A&TIovdY?53Ne>%Rf}q`u;%Me -z)o44g&Zgv)pvoaat3N-Oo=bmNCx`x_&XRq-uGmSWN}$z*Oo~hZ>Cu|`Aa253%2iBG -z7s$$XCXlbz%k#u5%c3b~ABI(Xms7$q>dms(74TzHF$Wgc+$OXc`(S&qgV)tFOLxRE -z)#`raJMO_`Ch{r)Imz6Cro$MKmnNnJY -zBcSI7_mgKCb}r8#CBU`DIap#v@J~5oN4f^@YSd8d(#<0@@fXNGez4j#Biz52_8H^3 -zBu>mWu)v-&$OGzFoZyAQ^5G;12Yxr!g6`nL80g)lYOysKwFXf)g8@Zda(q%!9HtY89|GKBi~br+rwU=TBu1tx -z?6{4}Mu%w_G)s`&vw{m=93IcXB3(Lr7OX9a$QMd~Skc4G{QVnP4P3g%W$9bxhOFI& -zVbKq9i89hd;B66J_4fJ$Wtob|&cQW)R%eBgK7Dpc=q|f1=`UaeFSOKH=ax5N(qhaf -zED{r@UD}J`D9CXj7N);^^2E_mhc4mW`(m&M^bFF_O(mwOR%HqA!q)>-CxFMCtM+i0 -z3bY^O>s|Uau=Co4nO;IP-3DH8(}5qViyrt&_c~04*W8 -zC#n%*AQh`4u^)Xg9o$EJpIyjD<8jN~b~MxVac##$!pNF`CcbBq+=yB_seR4{t3r$z -zV2)ji9Y-PFAU3W(%6N2+lj!Z{+iP!ZW$4Lesx%@YVK21&>>BwEqefN!umZl~$-4N} -ziaP6(4Ls4S7PZEPHRh7k)X^hOasuP6XVYOkM)lNDO*y_O*cfgkCApZ -zs3z$XN}C_0kWBtecq6rS%!a|*U7~q4U!uo3&u~N9>QgN|+Iy5%h8v$;dZzEp$29tm -zG$-4QHreQ%nO-n#P%aIaa~3yN)6ydvnvyPEU^8DloQsKijvpCSw(cWTi7bsRBp1n34Ugw2g3=G -z%L0Yrw5+b6&kp1=?dR-Su9A6(`tj%OAWYOyF#;3QrhriU#L=M=H|Y@?(vp(_I? -z3 -zhH1cIVGrBZ5}8Q-bmR~rItXJKBdC-vc|OW5h$Y~O8IQ-LA{m+q2fVtZH1Xq+){AFP*eDS``li*2i*u4EsWOPKOpJ%fEI -zKJ~$ftj-ZnnVEO&3y{Uvp0PR>oCPJ -z3WLdB7#2ge2bUUrC9EcQ`zEpjXrGoqT$MOC -zN;TDNU(>XRnu|M?NhV$`c*s%l;V9~T#E9+?9}l(2EFohpzH#M*6p#Q~6E2{X-e!8I -z_V)Gat9cmNW{;$I!Rt|nz?c*9s1%+VruaSKhI-nlwE~Q2{E!Q;&{Qh9@lp7(j8C$B -z;j9*#{6L7Gi#imtaSA#3GVgsBxY+WZ>=Du10u^;s9}2F*cefQ|59ctO#;6*&**bKC -z!RR=P3usH({%kVc2%p2A?cp|Od2qDI{@PKy=Al$=dBKv55H7)r#h-?1u*JnCVlB!4HK@5L=Hb`&SgT!|^9WFB>d)7*RhDy<bZH68a6 -zZVCgDQnSv%)pXIT{hB^4k2VZOqYWzLBQsc^rf+9GA4O2)Fda>5w#Iw-i@D -zNNvEIhPC3RkJ-HoiA?@E_uW@3MvjT;3WRCdSW{*Fd@3lmc1i_8eRe5Q9;8p}om%`n -ztAScsxiL^tu;_JaaB5!~a#%?pAQz<*h{%)(MfHcY#ot3jLf_z+1t5I(@E4eIxZad7 -z2zFm$q`fvDNbywB3%tS_A6R{fDN9#%g_SwB5|hAPa3OlGk1C_Zi}vW`bQ|NNO*pUDM?^YT!#GKPn+Se%jG -zu#%Xi@1%eU^=BF`3Hwoq-ZrYrrV>kCI{PRdHV4&sJjZ?tO0sEh->*g~2&X$bs#b9V -z&0%J0#-r4}94!u*HhjsKru~=8?!fngaUKjuYAns3!Q)KE_Blu-mi(_V&k#M^~ -znf0nw9rZr+HO8w~tSV^f1Ps^Dd&2FQj|Z8h}&#*ghVMfvi+W{Gd;@6e;Vh3t&=)0vJR>b1ul&{A@+@gl?lnM)e`c^+Y4CiUy+; -zsZ>FoDJ2lB$dFgO1hS<8C#n1l1ce@sNkO6nT_N}o!zLNv9ET50I>PKHd%=nGL@gui -z3heO_wwtMKg0V10YA}TC$?k<9Zl!$j6rIIPM4Ma%I}k37<<_Db(n{cKnsS=S>owkaBJ~2-bk~W3WO^a{W>USZVg45hw&85 -z#ScMy`x-d}m5vwalJ6v%+{6!x%c@3Nt^|P%}LticSjkbWNEqd`L4Y@#U>ZztX{mK9KB4Er>@lz -zdEbACO!-*8gSvr{WyW6^EM%8~#>uWt6k`fZ@kz0 -z+G{;uOvpigocR6#MegI+a2}N{SrcLxA`!o>`U1p2zj=INo14-!fZaAzDuX1IkJr%U -zGkwct9=^jld`CSd0iKby*pN!^NmWM+Dm8Y*bR?vyTnl}qMMB-TFxA)iD7NTN_E4f_ -zpq@Hkbz@smQk}YJK%P -zFR=0$N3i7cYa&x<3)2=MlpT9=y)rF`qm`Y+`XiVdkrMkf;gFJws#W+z^iRJoOx`8R -zHB=kE8VClM`<|4l*%?q_R>=g -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 -zh@g0&l8{xi-h1v0>`qFIqtn -zqr~V>)5UA2hvB9)fF4IV+~P5-HVE@q$a}1?T)n90$oZubBuwQ$6}a% -zZWVQ<-+#rdX_)W1YSe>s&7%;V5+FU31A@^5MB)DGg?vO?Kw`m|ity0L?8Ii;&|UaesDgE_hnk;2xMx%az>OArSLU*AJ81 -zZQ6XuXN%DOOouPmVG-uXO~T}t+s^?o4C~{OBf6{O%&HxFPjK&X^%DX_G{}lUof*Kx -z#DALe3oqMmVrG-6l}QBjfbyX!oDPtn98{VQ+~s^pN?KzAzDvnzqP%I$%HXkSy48iN -zKv~1f!3RpF5p$L@hDVfR3Letd61x>0zpaA+2n7}f<&V`~0LlN?I@)zcAE58&Fid*A -z;&_RTQ#)Y}%eVet-}OPPkKXK8nj*V1O3)+MexNsRV#m`7vVT1;K8U9a -zF6$lANIl?W@f8vyS&C#!K|#4HSmQ*w4DJ%$O@r=Y*+GaXR^1(^EMX%_;k`5<5jg8T -zqYr$v8@;uys!t!x7AQfuwji;JIQV>x6*ssRAka*Xw@`D5CZ*nnYAeXrU>J+w -zVwJS2`68PrSA*Td3t){n55o_2r*6EW$XAdg+BT7-S>X8?w2UwYbE<}YYEZ1_9(yDT -zl?(=@L4!QxV~rfB4yx&f%s1tr6!tw0F8s+TG8sjQhTv34bnsTb54#FZ@Zlr8V*Frr -zSS*~RBrbBiuj7j+QGp&MUZKJ49VEB4xrI-S(MLJ`SPss2eY#dy1DK$7gK#X=>pmc9 -zFy|@V5k!QOLQ*)``}j-3B0MOnoVNR|%lg#&rE6uQH1c1@w*|lyEYi>KMolaihao2~ -z+U?r~PskQSf?8LP2N%v-A$8SVfGcMCM0@jAB+Py-{vBIKNmDGMW%z**1mfG -z1t;4m?>8_H6zdGkivDtCZdmw)WUw-cYSRsx$zx@sqyxW)8 -zp+5EY^Oq&Mep%9?egAp>@*T_9>l)sFUcbD){rVWctkd<&-@}*BPhb9i`Fej}{(k-P -z_v!fZ$eWMPrk&Z)``7I$$MIi(-&{Y~{8h=3^a)J|g#693}x5%|i0BL4$lCc*&qkCkBexAs-HxEe51o|n~87%HSf8kL%O5xPk -z<%juit=j@pUklWg7QspUtkt`$;d(+lFt{lmt`4u@g+AP#4eYv{@@O?#Sy?ev1@$T7 -zFc@hcP{NHSZ&)iox{u1@L)iG#i+!7Hd~o{HnDROzbNsH-RZMKi@?m$7vV{574c2c4 -ziCOi>Z`(adRtt|H-!xxtdh0A@X>hPuDeD1^4G=SE@c4U=&VbxKD+GF4exU#QkW3fc -zX@m%l%4{M(1J;NV7=P&alA8a$p)b9`V9Rf2zHGw3msi98;h0`T7QhQ_my4D+$ee0R7*Z~oL?t?wODeyMr -zK{W=0uqI`U&TZBIZ1HbbFweuSoYk~tMQY#*F8mV5;!FA=8NVGf*`Q8vjJ}^So{)%L -zq8H0z^=*4%Ke;VEzP%uah@dY7Rf3+8$D0CX2W_iOvP>)gApby~Xt$37N9)4zx4d|g -z9K}zca3D)5mTz?K%rcYyNb`Zw8%dLaA-kXpWj?*{m?9rzPODwvDwp~|(fhg%<7Nkm -ztrUP(jxnGh>sPtPC;IS(Fb4=_AS&zo7Gf+=@XnXH4oY3=O=QK1o(Mc+9Z6NLUxAqt -z)v-{(Dv6tq{YjYQuStH89*%Pf;V?=WiMESP({`VEgq#=gEG#A4F}mGi@>NJAuW8+y -zNjf20G|z<%{b&d-+rjw;SRljX)*3qR=R?9E%qO!30ex1G#CF!Aq0oKtN#mHd$18x7-a3 -zlFFj;dGTKWRD%A*N&jTlYkVQ -zB+cfZfpz{-=>R;Ufb5WGn|SXy9pP;owUxkZb?(%FdGa|HGEg99epC3CEsj>45%KGu -znpH49Q#Uq&BExo(Xq|z0!gp2vWBAy?CT1MB8F7O-!N$o$z(s!!5T(1*Id&?umOF&d -zBO9P!-ldp$xpQRXByaQ}3a&6WCESm(uqDE(NlC@q+B -zFwa1E%n8PjlTm&WOo#GS`d{@^#QNAItct%Cv6L*UGrb$dToL|HL;EECSpJOy0KvrF -z4ap~jjHB+E>A~l71`6Woj-tC_Q2GMh+KdJUFN4_%3G&72$t^Cd5IurZMxrgs6(lIL -zNIoQB-a`CG`Lr>_55D|s+z2$!5W8!pp4|+be*X+}UJWzi&&zE8y0;JO#Ps(1K7RhU -z{>ibIckzBpG_?CDtj<$wRj?8rk+-ScS-lyX0YRJ+%9ecNoe -zx>##V-v8^~*sE5{$&P%1&(+M(ef_PU_1`6WJJiijU9Ec`&kJ&Jxc)^_nxFb~>hwcj -z&Ck&0n|;zfIq8EBwBD{`e(jI%_Q&``M-Jw?`Q^PiXftk@=2&>ohG|1un3~$`T%lnULpL9n#xq^rJBYPFON4vMtF+^}J -zd3p4W=uONKMgM4gvhrZ;_#6au=Wyz|ty);Vht=g52fpO(x=sQ-@rJd}^4~88dwHf{ -zTNd)291Nsl8-Ffhd9FO`_K54=&&ml& -zIEdlrQs{!(Su=PXB`4OwKfzDiLrjDX*&dkpA{aaQw)-VMRzK%=lOG4A>q6U{j9chP -zC}jTarrM_5^Z2-*e%VIX)O|(-IOUtB;~8rCU2zZ3wa$23i6!(eZ*P+Q@r9e{ -zxPKC7cwSX|b;;h*j`h=1Av`2>!W}QHm}Mw~=edsqzdMtneNicQ$2LKEuLy~hJlsbH -zoB7MG8_vt(SCil04;AJipY|nyolgeKs2;d~OsC;qnHBSa{NiSJ;qwtJ|$#?K2f^BnMYuglPzNBcyfK2HWe2F*}v -zGKuDuW*q^oOy4Q10(o6&20oiPKi=bT;cY?Im&c8h8^pa+K}91RweLF=y@8c;S-nfJ -z=A!p4wL5eP2H=@;bA7(KsjJW5y- -zOG)Qv`s|t0oufN`rrkP4l3$IB)+!}B8MfZAM0(~Sn~1>$O_l}?a|0DWFMAyE)Su4n@T(0RZjc~RYiI> -z_W4Q>Y+&l;ZTVWZ;LAl6gR|G1OgNd$fCvTd62Q+=aPEAB+ITENu>p7<6uIs)bw1n%>F39lzI>>`X5^ -zJRABfe!~q>_y>V+gtwszxRIQKKgOqnD^MjGW<<`l=Pz4pLoOp4#I^Na`{=9-50J6DR(9>~Cx_EJyg-a@O-pPyV=^G!_Q#|!9_4wB#c -zh}vaOSEKbRDzISYi<>HnaY7RWIau9{d -zm45d&zbD3LB+<#*oivj($Pk|eRe)o*6uhY4-~3Q+mgnc8d-&NbS;_z{!R?G-|H}F6 -zVxbha(ckY*`MFtEj6rfc9XCyZe|*o|j@ZmAZgu=SfBrv3MOjkYrw2DbJgE+rmZxj& -zmml7_Ywp`@iGxSh_sc$O4vd@90~uXeK*z7fVA4X3?`X_eTmrNn -zI`*|Y@x3Lt%<8o>M1LCja0&?yB -z@NL{aZef>HczlSZ=mUO%7hW(df*x(WD9S -z^G$ARXo8J6nsg9`rX}wyazcEnVlzMvG^L~ -zd%!QARU?0VIdIpI&+?zD$TvA`HpR2&eKHb0ps^x}=6rGFHWU$4<5kGC*{2rtBO{0y -zqidoS4S%~LXMA&Y6A6^{GQ?q3%{7L1WK)9<5Rl0{^2$?f?x~xGed50JriJ)D2`;k{ -z;vnYD`LhWd;P^u5Lq>sEK3lz27rKS?xcBuoV66Ne5iC3_@Myf@5_=T;|oAZg|-E1l(DRvnH} -zKjhD%P(%mqB9(uuVkL(Z@XT40YA}>9*Y&bJgMkFe*E3U=oaWzoj8Q%w!|t*}(eGm> -zqLLnEkw8J`nv9Jf;x78lST@8+8`z2>=(^)#heKkMYa -zmq6H~qfVQ@xgK6Gy+m*-Ni^H(Pv8^)-VURpR8CRO7|=hw)^SBtdVwaQGec?DJ -zD$nw!$Do6Xdh*4JM(D@fc7*}N)E^7F6iSEX$Rl|<*1GA*JW$Wb-{ -zhKsv18KUDJp7PLM94lmq%iOZF@D#Z34jfAP>kWTFue*HcsUR6G_ -z00cY-3f$#GHSaYlLmj3Hx%Yt>3px+{Z5}=@%Mbrv@?_M|fLnRjw)w6&%BsAz~>o -zs2JkMMez&>PsB%(1OhkMXF*6g=k2hJ)OBxcdX8B3ZX0eFg-q_G8^?L2bp;-%YdiOUtvNq7n@0Lq#2ZTFq!2iDfsc-uR}G<>}FsSnpx-*wp!E;=Y{Q3W6jI`fvg -z+)3tF@Ts&*cjsi7yt7%4WsBh398Ch5iGnI@@3v(}g@pp=fT=YqPJCn3^kG-Vz^6Rb -z@_=8RUYZVdc=q{Nn+?(m>%j<{41t+9_{1Wd-{2WtViY^ta?EstM8X7jGx -zb1d#~=5gRrkaBhvG=rP;b)m)MHm;V37fu-Wb6p=Ew(1c< -zwG}4yP7+G!XjZwotAdR1F)XJRGO(Z>M}!Jt3#A6|000M&=N~ORyFQ%GE!;ULhJkt1 -za_Dpjf>!fOGOW@t-^byu-~8ynPs!JJwH?_yc6UV-&({zx+Vc&g%ZkZT4yb|F!znqC -zKM!0T^41?eeoAHv-4=C##VYFbA<-pbc#Wb1P3C$0)&o*(rhUC{&{*LAD2(|IR8S89 -zn_XZkJMRQh&_L)WeCaYp~v;?AXE>N<1Z@oyl-;2P!pGHy9pPo!d%0vYeT7!MNV?{x8dfT$xIh -z;{NrAw2>NX%nsot2L$eWOYDr$yN;HjNaQ}o&(GoO9+t1pyn|=P4BMjy8dV#yvZy6> -zUC$4c8+m@YI1GcGKS=~!ghay~Pi-Q6+)zx$6UU3YVR|+o&dj?C8;y4A0`@8Xc!iLl -z1l;;_KK#SzQ+OTx2BT7@r*7_K}|JrSLJj+{`=L|=?k*O2+HQewEWb^XL0ID+j^Z1mP1@u*i==D7Nea68- -zwZa$rffPiCi0?rK)s@$H49^m_jxypB4n(7tVk7pP|NyG -z^lA_m0gN@|(lsM$DB28sKUuQ^*6?Gy$F4 -zLIHSB$-)ykV%_9~=hTJOia;@|5}SK>w6({nvP=sQo<-q649#8_k}MnML+dcO1g8!C -zF_dm&HBR!@6BjhtW^N -z?pHY{X6OiZ&mSe}Oks(+#BvFli<1JNSlDx=6vpi$d;n7oXLU>vIk5Qz2Vck)S2pwqojyI9IvEVDE1LDH{BYXJ|5+Pa>m;7R8GJ) -zBuw7rYEAiRjLo-he&{>xQ%HFx8`#-9ip%3;)=Y$7(hkX{pDn>@-bAH={;c=Q*B_ZO -z=O2@S4};3>#A3;(HER;dEdYih&TPxW2lhJ^u(v(%P-to@U(j5Ub4?-fFueZ><`k3V -zCFs>ZcLa($-rtE!{EbRh9eN0J7-jYQ3*vG#pgTR^iVqW~pRd&MvE^&p;Q-%rK^J6! -zHjw2Im?&OLSfA{5u}+eA4b8t?CWsdQylWPRieKYmE+d#k73y<-4E|!r^X*RLcMD`? -z`mG%9vyYd1Fk%F=j|f!urFF?liB&)ey<0zs!`R9PQ}iI0b$9@X_x1PG=*ptW#UC0U -z0ck+if^vKQ6Ihc#QKtG|w$8}=Kv(Vh-Kb -z|MA|mjNnC0*$D8rZ{Pm!FG+8(7Hc&D|BFB7UfPFhSz}!|M4m6NSE>|HP~}yMty_D^ -z^w!Jq$K66JN|*Tjof72y@lt4%F?{&4kkK$=Ybm`*DTFTg&FEX?bP~gF9t2yZ -z)*hBGNb!;EH@rHR4`*4}-_PtUoo+>cUufL5$Bc2vCpUNjHk>+;P?fj2&mdZf2L}K0 -zTCy9o6>MC7o#i|A!QfUDNy2zhH`2c?(Ln~448{XkO`p&EU4ylvMAZHGdFdp8-X(!} -z1{(_H!v0~xC2$3h!mzdytQe$HkFgWF0&QOp$%(+k->fmY7FEqA{uDoRQv(E4qk-kR -z(d$n7QM+8%5v;ScAM*FiQ)7$04$$1TUMAEDJcfki^J|xH3!{%6uKO(iPZ9ZcF6S;F -zNeQloFy;Q~_a6mLz^aBUeXXd`1ZbFH+9>&z1@Z)1d?o>a&LoX{{Xt5v3yz)YgR3R_ -zv5m*C`7aLw^}>RH+uLc;I?M)or -z*5OBOU%w**zhRmbG#ne|mMqJ7bd+-#`qh^IN+*u)xfMs-R&ut -z?~wFDhslh*V)2sBgb8C!4s~aK-{Rk35>R(*Qxqy5F+o)!_f+=JMmAENMaw$Vo?-H! -z>3l;zW&nlFo*)_Ap;^+85>CLLf!5ra_* -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 -zNz3_kS#xFj(173$J!+7nG+D#krn -zu3Wne=9-|9x@e?d!mU|;pbI&nde`oGMF|GeZyuvT<4HS@}k<49ty;-LmE_QkWH$!(*BY&W*JBuSaJbEPPrO(IcTSd|G` -zQ$tu}mCF=%JZoem?eJ~t2pEya6Rh^b1xh*moa0mJ9UNrF6ov*we?k0hSGg<^kR@WU -zIl3a7Odelc>?YP=RH%$mHi`J!eLIR0hW!Z%WXS5o*=btc%5A(YoEl}H3R-tL^Q50273ZyB0t9TbN%mfHH -z+Xvu!&tN+6?AMaZ8!um3?c8v;&UY^<*1qX!M7Cy+Qx0!snY}t?=t|yeF(m+8yUs#v -z#m=Onzp}>ro|W{x8W6@`yAe6v(b8KqjgoD&+m=Ga1%4ilys|3<(SeHxPOc$vM~hm{ -zY_(t4mkGj2^onlzcx1K-PH7G!G8Y$pwFd7K`nc(v#>F2uP@NxxNin0`yOQzSA@?CY -zLhYMwqq^xS1lXa2kbvfuV<1+jkK;xD$)&->5}yD#pK&P8vul~qBP2=)ng2Z{XmPCE -z8B(AV*M^J{&baOv+Bxxs93_m|r(C{i#1ycu=m#9K%I!J4k?vExxUz@1F%6Y$qj9Db -z;sWf29#-^4unfVi8lBX<$@UX?O?kc^{2^*U6Ch0(pgEC -ztX5VXjDy~uybP~;KRhSm2TZ7$%hzXFw1vPo1` -zDZ`v70VCt!z+j*=H|4$0%JpphV9MBhlDz+n4iH6S00%$PS*o4^R-n{IWd4LNb&&ZF1E*kcdar35DVwk -z<<6W&NW_Y*LnJr?lrJc9DG|NTF<`O(OJ{L9HDFV`DO721#v2of^og> -zJ`@!Ixkvf;pn*~QJNF~VZ8}KJnZefhqtpI=YQcD7rvL`p3Kt#-^DSxpS;yo@ma`>J -ziFlU`V+LcM1z?iwi!Io5iHeE&dWVR;22id>BSFflv*ZbhAE%GN2%X_r2&p9r%c8sz -ziT4;umOOZ(?53(4J|zb;m~Ju*dvi_9LcAyZ`1#vl)6PMZe(TlV5bQRDd0fvzUMr6j -z2U4EAr74Ocw&KAz%Es#+0R)8YA`gWm{xHo!!oBpo{%d(aJ`kg>?I3qD)-Wj74>Cok -zxHi{a{ue|4V6hNCaXP>5v*|{(%#EsP49~e3wz)%1dUs3#k~APW?O|w-i)gq!AeGR# -zK=e?`Lti%xV4^PE=57;sjN0L-GJh+TdRr920e!}e9^rzqVmaG6heQ|N12hFW4-ijD -z!|B?^G-@R1$=izIBP0D~%)=lXmjjd}nNtDts5uSbQ+*1LGYXnvW@}Jsc$^~!)e1;i -z55@}$-evhskt@h2V`Hh#PLa3fpnRF^4Aqhaz^G+%xsAX8u~)UZbO~$dcARktAn)N# -z8T!K7M%M<&P*_;eVYs8|tXOavJl$cFCq^(jz=SznR_>=TdeG%OJL;VAjSrnvftI&M -zid#Sl=odq)%0(Dd%OK|k!mJi|;1b=W-s9&K5 -zCC6O#Q|ydGm`cY8Edi+Cp3b&PNFzRKI9qgMha>{k1##rS87O`$U?A5LXdGR9gv)fX -z%t9_BmyOca$HIrLnU{D_?NV~V)?}3 -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 -zK)Xr)RhicSTbAlWOY_ZJ -z(Bf$M-)73Ex(!9YT{ar0yli4pF6eaxw3Q1(ZUvQ!uuGgJWRpjI6r_&BtiVIZ^ZZc| -zqUXY@vEB|>=#)%@R=c#E#`{&BI5F8Uz@F|u_uKHwx>)T|?-$bwus9gotCGy6t0P`88{a3*Y~^+u=9pS1G9{50q;o6Whb1#W3&1Tx$Yf`iAV#fYG$}V -zB|=hZ*qPTM_b5O#mwn+UXF#(taQ?}nq(3atS -zN-ZWU0J@%d!osi1My8n@M1zxqbmTEQe$UtwSuxOsymoiF3b5x{0=zcOrI^zbYt+hD -z-E%1We?;E~zB^W+e|-O8M;9Q_WBFpzBbE8jbW4H(RLm%^I6a{@a$T=C(b8w%+iiC%K^b>Z*5fisF2=Q8I;numDy?H= -z$3}G=vL2qs#s;HG7{V}3gO!HzIO+E2Ik-8-eSRZ0aM!R{;*4#~Pv@YDc`V6vXz1cT -zB1uMH)+9U16ALmNNu@h0P1~&@{%seF{nmS?n3IFrJ;&s8P26Ido`+0b1)g`bQ$pi9 -za3s8Eg6AIuJM0$^RtHqst=>|`-6sH%On>Gb5vePsfL~M(D9E|DC2D+0sAr29>dNBf -zb~tpp*E0;G!JR_UAY66?d?@<5Ek%7Z9YlgjFy7`0XLxnX{(2Pz=o%BB>{k$-sJYm^ -z6PcrIlLbJ`=tt%}lcZPll|{!avkokA0mpQOC@*v;Jy-jmf^X`p<zp&s5=_;D -z0PO+kR!?*zd$+t;phu3}Cr9-P@>{1frB);-#lX-MT(YUbKm}S4R#)jhF+sH@UtDAH -zJ{8f4)3Z6;pZ9{eTr8(9X~E -zVPTYL7CAoG?O>2Z>&zG)W!XmjyyVMv`cWpNcpyeM2A#uz_Qo{4Ox4D%oDnFBr_CdP -zz#hylm#{3wl#jX-qbRCaol4~-KXYADIJw(Yf}O%CXh|VBg&o2J#n3=DbY&LRn4XQt -zcw$}5X}ym|5vAF!s{PA2^E`>S2nh{>CCsj9EM#*;vQ^L0mR1f>$pESu=qY_F`#6GZ -zL*9gPja%*+o^F>-Wi^+}sE7o#1E!2z(ZyzM;w1Bw__`whS`{iB?P@-4qs>F4B@`pA -zPkK;`4<99h3*r)8`YD#m8Ss4Cfy5uYEu{k@s};Qj1SL?zNlTt=hyB}CcdB43@bJ89 -zf?Je5E$Ix--U8za8GD?pzLu_|>xz*yB_d_>kV%{o@=nc)=jq0@Bi(EH#Q?Wre&&ha1lthP1_S1^wm0+R;))uL(<*#+OJv}%Vqcyje!Otr@Q?f*zAvMvf2y%YRn};K(sS+zunS_ep9dg-`$xPXlN7<+vB!w_@2>mpGQvr>57RX98?rrs3A%Fp#P9P=inwtMxocWCsEh*j0Q-#! -z3wFmt0x07TK6I*q-8)xTK;*?}4y7ljYi@8xJw1qCNifd12!MRRye{iHG1h}m@#v-z -z2W`?L78zf>mrqRtSf0|bcauEbY#O&=^scmT&w7pBJ^SX4u4|T`6_}g#|? -zkx90I@j%{elxJtyFk6o2-a!uyX^I@_Cm0{DfUH`jP^=RMQhi1$*L4f9nxfD5HCB^+ -z78HB7hX%=AcD(_$uur!WsJG+T>iPt$vxTN8mxcB~yW;E{h5Ii_RE{6!QpWwVi%nCp -zf%#tzR)WRyi9?5ja!=a5BrT(D_0gT+1_dY+))a6D>Bw!9X$CN3XetfTeM7f+{;iXE -z^b&&1P}-B@pAq}w0cERp&h;!C@b})Ov#y1?K`S0X?0kmycxxCF)s!#b@^7uwLb2vG -zh&P|u&2U5vXm=;A9%Nw}32)8HGFAj{OmF=gWo^bdkvzdJ6ixjWBf^ppdC}JWz1YYN -zqEa39!aEHYe=4@)6NS}Q{MKq23>yf)Bpu;TGiN`)v;-y8X~0Q-GEYaRON! -z7?X4%VYN_t)G6RxOP63#u?G&1%;knu>W%{Fqv_|6I8Jz~g^8V=h)03M##R0%_6LFh -z=66EB9T-G-n@V-nLiL2)!lXuo~ -z45D17Z?Fh-uht7iiHu`4j4k+7WUob!Pv&H1J#TQJ<QgP;dnqbz};0n{qikXOeIO1FRf -z`1O}xj(yCmtcq{m2zbFzDb}RQJb(7JVt+$Ld5e{b=3wV(aD2T~Gyx=h9blu2lHn-f -zi3B>V7={%BYYwnm*(|ljO&tf)#mNqL=Tq;1(zUh$`kdx -z%ZiQCNtY1~tE^do5NCG|!_DWk{%pT~n=hbZh_VmH9g9ZSFY#ICPi_=%WZmcv6aS&l -z8&0gwWd>%}iVp1J7|}B8wL6N-%W&ED+K-_;?HLhmb973yX-ia61r^M!_Ac>zcaUby -z5~AW5c&|#LgS1~P|5RlRYk3h9+HIIrJALzA;;#b5$11r*=xyzzk*^joA=u4!1`=l( -zKkh$Q?& -zeysV#HU%+wbJd_G;wZo8!&%l4o)Z=3)3uKdZa0pE}XMhXi@PRmD_$(~jP%%7*-q -zkG+PBij;t!Blexcy-}@1={uWwC8z)v*adR#;AA%fMe{d1CZ+vkTK!4Ptq*~3mG5gi -zhTV0IHI}CG$tQ%yE76Y+%|7O$7Nh+DpnObH6vpUF-S-qmI5psX!^0Pb69)n$u1XJ4UP{NqExkAns8!CTS&TM>A|~Pe6z0 -zWLX$p!G1pJ!{Dhh-@3TFK4a7;;P^L=De)(EBQ0!$c@YY8#)cxgHZr -zh1RRc_qaU*mEpB~0x%=w4Tw8&T<(+l=O!{lCM^Kw=SwA-OV#8oNZvU}Bti8R4pTYL -z1=v#-klpm?ZVu{MWS?E)N#l9BGzG{c_d)m}L<=qp+W`4EtrE3&Z$jG^Y!G^?^?(H4 -zQft!Z>`%w8u{>v4Uv)bv=QA|>mea*ArIux2$=O}TeQ1k{Hj$odM8z0e+UWQHD7&zP -zf0auti}O08{ua2lA$c&sA$D|Miw3?LL$ClFY2FO6zb#o&8s~@_z_0>jv{PtBtJP)IT`PnWyqsMlLfw-(L*ChY+qG}Tc{v+SEBXR<|x}NEYKmG0PyXUh+um@l=AcQr5iQ7YN;qj-XA+~ -z01`@fRW|pZb5(IXOg@r6dW;ePaprff_PSAbvAx9U^tqs7>46YNmViR5@}ofM;=mB13mXP$_No$73*kbQWi-r -zUnK_g>VVY-+B0NBFOlK`nBxHszluS$h^shqFI`P&8&^G>h03EkoWGs(fNbkT@3sE#6pAB -zYe!%uUk{@U?~kV>dLG(;{r<>q<#;bv^}MFTCf+WnN2osAZB1 -z`>=EQ7sYCHtEA?cn!Qu%CX&6_DI%CDnDCsWb7Ib$!}L=$P6JbQ?5*vL@Qe9>(h!w3 -zF-B(gaLu+vAQC|l;YNs@?k;accK$sbQ=CfXY8%H!+c6OxU|71`7%qEg$cAOxfgrXf -zFsza%--2U+p6Z;SBAIdlr`NQw?nh)*1Ak-e$j9$*35u5`LH1NL-_QdRUQ1TEto -z6;4bPT-^+arS#k^@Hq&}q<=BWO3~vA(S^ZRXJul -z0wgHfEW&J4oRueORxps|GgwwSP#r+Wb&e@Vf3#V1cl46>YXw$aqL)s^1J#6^zLLeOEm97IB5VE0lC)5jJr&hpQV5)#8hWH$HE>RaE?H~iVd}* -zs=8L(U+3~dXx4UX9*q%4weAC(O|`}HsAR~VlHglB-NMHblWsFBP3t$=&>z=5-49Iah*!)=BO_!& -zNQ3~?R7Uo+_2aMvJb2qV^0&z`0a#elfENX8rHjgKLxwexT+kV8(}w|28|1g1C$hDv -zYTP-mx)NW0q>`B~$yQ>zRtP#_oc$z&ce0JMS)lWwe791q43CoV;&;e2$g!oI9r=!` -zSH*0((i^gy`JXAjZ9jtOUp#IDMfr`@Pdj7~In|x%)k$iQC_Sv%>K^B0BRmqXv5MvXvW4XukA0H=KWW8q2lLWnocg3tvcPw7n7ieV -zU7HUUgCY1IHDxqRt8=S9C2L@sYYvlG!X@Nh!M@54{X<(MN5kn?#{9^Ki0eW4nuA_W -zM4EdK9fVG`@e6KL2yukoP*&oeEY3YegfB}n=>vxj=5amq1f2h4>U+W-!I|NdBQf`a -z+5_kMl!LT?a -z&ugl1_5#a3C7)RT6OhjEf4GpZwf)9tsH%r+mw61JO?t)zhItNF$mucB5jZg7jLalK -zN0{csqTS>Bf9YSQSfkKn&S2hqFU(Pwgt9?v`&O916VJ7%r6U~5*7k87aw*nU`F_@$ -zkUPpb@LsEaKLChbdktP;?U5|uxqVx@4`4x{%J#@T7h7{+b(tOL<6GlX1u$EeREE?g -zw(B+qqrH^nA2^>LR7)E94#*OR*(n69gPQhxFsY6~a-jZnD$E|>t%$wMPU{XbX_oiU -zXEv@mO>%sh0Cgd?PdChYgNnyR5b8NIa(8(SM*2V!p|MhjSmkbbb}8mzb~#iLxj)qO -zB+kOBrDwS0qHB&X(^@Q(p0M7uC?J+45){b9)K4QEns5^B>B?o -zj7G8da({r})W$*olzHzsaPFm9;4SZJzP~M3ZQrhG1cEJfnF;3*=p~D49Z#Eyz^`pa(BeE4S)W+j%33YdQ#R5=>#;t`5 -zS0vzF>yo{gTDYE)I=BR}yx>hA$xgw{Jj;u8cZt@myFRpF;2XY8hr%Hwkdv4=In)I7 -z_p+;&y=ik!$zk=H|1uZxN104 -z=&#w6N7^vzrhjRvM`?yL9ydE)$!+8a?QSmQcwH_-tR&?2Y1sCD9ZiFda-UleyBf8e -zh^A9M-k|YgjuIQ1^)@!qLv;gk{}ZX3Fh4qM9U -znw9{YIb=>L3K4KrO>I$uv5?^S;@j^E83#_&W5RY%K!Iu`BOB&wm4GXWNcTlHTw?_c -z2qnxNMVUDAhtPZiTmv~OdPk?WcM)`zu^1YVNz4jO1mHIHa6x=PmIFQdJBWy`=eU-R -zDnT?41C4~@SbFu44Do`do*Z!leVvVC8ar^)Wln*90A>-0WqmX+vF8p?ouIA?OJtmB -zdT%NAlJXm;q~m+PeIBom?Sc2;IkMQ~xFXxV#_rjJd^XQjED}k|(}A~T0(C7I36R6G -zs0+a6$7{x3zjc+|k_~{Im^=oYSCx0G~9@jz0%VSC#9Qy?=SH= -z=|`2HfWa&mLwo6*I;Yg-W(E*PVM+^&+>JK8zJc0Z!CK#76F%5(o?+7fe{r{kXXZU} -zI}5Uq5>9@$U5Ouohl{Eh)IFjdqi+wA$Vd(p5AOp&mpzXX%lS^!V!^}mQ0h4ymw3`@ -z%`K@!?}Nz_C{Y5*k}{Vj9IoVRy~cS8PukF!b0XHem{!NiDl;JmQBTln93@77nn+$d -zJq$Oc0rWV^;TDfsy)g!SVITdbO!w1Km@|D?;Jr^37+z5EH?JybS(W7$xQzS4PK11t -z;L7i{aR;M;0BCNxScDw+i2Ji^bHUTP2KT^pTCU{I4uP0=x_+44Zqw#NK3jzL -zXKsAC4vR29ZW1QH+iNIO!86OYw7=7TQ -z-RP}tRf_sxwm?0?wFRS9#KGrlthm9o0GnoVyoH)eG%58qRA@oA2E$kc7ptUI%@++t -zxf<*qUI1&vc^H1EJ9Xm~6~BTc(YA>s%>wDipk;(Hm{T?EQ-fkX_t+y*wPY|T4I1Pj -zA8X`5bx?sfWWFf}rLga5a1~HSk;(W6@d^!Q@1Vb}%`JRtj6TZg$8vD;>(jNu8o>8&qT=W%mJngE>#>j$kF6 -z6q3Th-p5}O7U4lr^0eJ=T^6g}FI_7erIG(K@+|`8F5v`?;WjDKZ_bw)WNgFF4sot-pbJ -zpjc;MR`i!EbHnOCL#+zA@1KN3^2_g-y?uRI*x!G*jPE}WUoLX`eE<2jy#FjN{Oi}g -z!oPg&`sLQ@KW>4%tmUuL<;zRHUh4ei^5l}D?|%F2qVDtJ&4hrvkufD&#r -zdBa-C(tT7GAHv3`UhLasON?8vGZh)9UgU8={bUNhjSs~EV@&oG_kI3>S-*`~BCmfs#14q~b06&KO^&xADXK9Tgf%IB -zbZ)EuXN!NkoOvE@<*cSHD^dfObK#db7GKg2$@uM<$p&?{WAy!u@r11G61`X!t8d#A -z`^jzT@$CgULqx3{{R%XdsE&mKR!Q7^ -z>`%fZe@*g(^l+R@2!~P1NVHvSnzsAQBjmh@XJIMXj?wKFldnP|c}?rqOwtM2qIoWC -z=to0v*$&P(zycX2x7N^kKOcGqVLq8P20`wB%C? -z&G!D*x7C&C2(XUEC`Jw=P?;9TeX^m2NyRW#kXO&b#P$J5USws(yX9_RkW?0x&x`*8 -zpcRN_2lvn%tB;pX;lmy38di+^0PCa0Mg8I8_R92RJm)IO#b3ST~X_;USgak0&u|2+mPOObuXr&L(vxW$X&7xlgY -ziFtJ6N0=ocF1owtx&j`9K^PbOJO3gV%C2Y+DsIO_Lmap-aqq-1zP}1#>(}3r7(v!D -z_>@MZc%iw)Xq%zIAZakeArZfrK)J<*<)TM$GD-AExq?J!7MX}d&s&K9 -zDAP73`oW}sjT=$t8E<#Zq_mqM)$gBS&Z}V-{dt+~U-$N5ZJFL)-^b7Y);~EA^DZv) -zm;ddjgTtP|ppAEQG5t7`nmrw>zx?n2m>qejse3++j#BQ&U~BiDJqI%&-0N-ToMV=={N4H^0152i3+6qdlvIa#~^ChK#7IjRNx7c)K?(`APh; -z&)&k#R?Wh%XT90AjfOv*pW%(QczOR3y_D`K$5`+%e`K#B_h|PvI-m%yB`=S@5sivD -zq5}|(X;vPL9iM~f?i^b^w^ggm_prJ!`&l{h2?qiFTnb%K -zJ8OoOqZq|H_$T;jdx(j!iQ5CiUqogn-*&&m$Li<&Zt~-xs9k8AlYR^B3B}L9-BjC@ -zdmbP6(=Xe&o4U`4Xs3MBbUZ^Xzbo$Hxz-tcE3t(Bc6cUEZtVyzyZJPOa -zKu=@wa={M$vbt3+rLA2dGbVxJ&u`%+Th~HH>*%1B!A|&NSTDmk@ZaKH39fr7)JY-` -z)k7K-2*uyldxSjYF!3F1+;$Ju-S~Mynw|sR?sXY@^Jt%_+UGIh$Drv-OV -zujxBwRaCEQ(7qo!TyXCatkdXCOl=ii -zf}we)+-aY0ZtCjucQ4dtShGXTTXG+bD)d1fEBM3AW_RYrt)w -z)eiTe6bZoxBx8ZpYsFwYG>mOg&=r}i>cbcNe7yV{;s@gNc3yv2eGQ*sxChze_L+Rw -za4t?Kk?#zGMgJS3JuG?o2Be7V{`P3(7qSn_JC}!0y^W|H@A@bHgsLJv8~c1E2sSVR -z^R|2~`|;%>iow}yjwzh9W`KtRgb5UADMfcaLhZtz>$=rzd0iZs?$*jXe8rRVl28I& -zr%fgQ4pp(Ep(;#_?)mXL%%+JVnLq%^LS>O4uimh_O|gTDf0K{57~_(^ndmb9lF32v -z{^Ixk4m54;!_a>Ma6SMT@(x{K*8sUY$13;}2ygwJk|X8IlTQH&mY9xFi^cL~Hg#g_ -zq{Pwr2XBiihbS2=>ZGCrRZEG4pja^b9l!`GNq4=0ft~F2kH+{v&Tuq8uqP*N?S7zR -zQvMva_n({V2WAOWzfH2?xDJ?IQ*VpEKqfkOIn}}~Wr6P`clK^&CbpcwDh8HQdSo4P)gECyy|G<{S|-Pd4}sofas -z7b(c*k3ZT<`1`kYe;}Ua53gaW#g32e=+iL=Z?=>x$g3U3TtLCTn<=p6(UA51yGb11 -zZ!=*o$LWO5Q*%wj`<*LaXb+g+$$_aSb8n&I=g&{BtobIU@Z$w2N(V7;eMIfDr>k*% -z73Ema^u_RA0NL^k(r -zw#30B>-%M&HS)bL2Aq6uce})}c^2%iu3wf#ZI9o6VZZWyiG!cc{MyFe|KWPoy(>-e5#w9!QRoX_+r#qmR=(niG8KaFDGz^{Y~9aa<&5;=^VaOK -ztEiU$xIcrJcEt6d#0@X<^E>6iVp7Kx)`9e{tfu2vV=&R7#&xQxTj-vW2}iGN7cfETS{zv$}~Jj_iuTINBtE`Hz; -z3zK)NAEM)Mholuh3b5D~{~8BL-fr{IVah_UOi~|wc#WULa^2(o%a@&D0z${j1^##Q -zpsT!fWJj2YUvkHtZLJ^YKTkv#-`28T^OT?wpw -z;2^vtZ8`9jGpgx6hAeIx9N2^Nt*q;TDa*OI1j(;|@7>%SL<1Mk27H4)+y<1~`3Npi -zB9(<>Xe`z(67M+sDd(n0^$>G|x3WO{+r9gM{;lMboj+=T$IQ+XzF2$>@;!hV&#I9> -zz8tt~$Y=RaRpgtTJe%U#06*yo9}rxTM0374j2l{ssqrdg+U!#cE|L+fjM3H7itfK% -zk<-7q)QJSjdKu!ds^%KQJItv;2M91_9(g6LHuuy`!#;7}dDBAto&=ZK2yrU&=49H$ -z5O9_u^dUn+ET663steshu5vR0;*~#(wf5mUkRm!qoa9fQS+42hL71PeSdeoTv_6)r -z+@KwjJx*&$C3!s+auOz@^a)A_v64NKDBc@p$8)QbNRXU!mX*$OFRM<OHT9eJkuy2kI8r0q3HK96H$GSvPhr^ -zbWO&_4{;a$W|SLZqz!pRd34=zvBRM?t;kwQJosk$xBXE(N3GhHkUD(ENPbHoo)Fw# -zcAp?+cI#Hak}Z7?b--{n9FNB90XDtxL%=x)aE$yDm5YAgYU{!IwRMKM;!B|N(NV$8 -z-&_x`mtG=mg#7U>gjtd}5pd`($Uo8H)yh$R5bl)YQ2-a2Vrm9yg*rk)DoFB5BSN($TH1>*6zIj}XXtB%5>%MR{6P0Iq(__%7 -zMLqdqMI*#yZaYGMVp!~%k}Ly^2lg|gIr;fl^{di0gNmhdWSJIG59BDD0F%bunGDf! -z4^Me$FU}Y;#AR;TS$GN%cn88Se>rs+A?T9{Qpe#UFG#153%`CJ6R#>CSpWi_1J&;G -zp_=y^m7xwJhTQvrj|CkL{x%OEm*t0lFG(|M2*Rzr`9b#FFrBS>@NbFBmkU8h%Y2~t -zt*ir@gEBv;K+Z1BxpR66Ai163zEK;WB{uN`%;WkE=kBHHcCfed$$d@i{dADa*yM@(z*g1)N$_7EdPjDh%Dxc -z?Ib(}769c;`L_Gc@&jvYYrO59VH!SO`_zZ)s_(k&2NxauwWtCR6P-y+UHc@HE%=Dq -zrMq)XOy1e7$FfC`Z;mF8%tS%8w|CpJqhdsXbHE52=pmvs6Y}4%pn8vUhmUHAh@3Sl8G`F*YWn^@Ftlb~aU1qL#<6h_iWDB03g#xN?l4 -zmE8)TQ>>djnT3*bSMxaVC`dWG3Tnbl`nu5KaT}M;!wV+*QF$_!yQ`B^kibj`Ko=%7yX-cmRL{$n%dDo?RbK=N9f98pHHFYB_W|L`19k -zB{NoOnD66o*KdAwAgko-yV{Oy9lN{2i|1*3TN$e#z|4teX3 -zA3r5Cg@}tfz+x436p`o>F}%jtfhO}je(QlRHq*Y|HwZ59e-zVv2P&usnoSa-@Y;b} -znll%dZ7O}c#G&ifc5;T;u^N@_5mGWM#i-9n*oES65~0b%8}W{{(*;f4o9fPy%lKIUoLE -z^pU&{egnK0U$@sXq622b&T#_B9l9OdQhOUCY@WJl33TPWMEBNyzPM39&t_s0KTobF -z#vVU^{X>5%(fih~2L_2X!a){`8zYmbT$4m?Q-^>^HiO2Ob*K*yMJKp+PWUwd2y1-| -z-+%44JD%mO%R`5w-N@95`x -z66=}~HArnn!Jm}b{+qG)4y6f17CpL-v%y7Au=@-ydLfC29QK}^T$+H+Z6OD|r)1%Y -z9IN(%-# -zM5+1Oukv+|aB2z5mbk;&oLJOeg8Jv=khjoO^3UBzFF5WPJk!SbM+pT~oe#8;4j&JK -zz7;A|hPw}^nXtAC2?>MKZ8-rwUP&41b4nS5iksKe-|VfU-H6Ek!K -zyXTLRbf&PxTw=L|Ow36&P%P}ZQi|zzMLvM3hO@e*wZKOyWz@z?F3e(lIFK6a>+THO -z+mC>z2iXHAm)`JcUFyvH#ko?%AdXkkEEM|)nVW76jv|lpKsj)2c`CwMHF>5BmFKLHlqtKS%G;a#iK!4WzzU4yN2dpE)%Saf8I5VL&dLgF_#gvq6+mnKL&rXC*G&x15zZb7*{ -z{|OXI;44!xFk5Hjec-NraDdjnv+MD+Tlr0MFMD15MN}rZ^7sDsH)V%z>;HIfT1Jqh -zrfdZG+qZB3_m`wMSc|oqfd9oGb1&^fg{`qJoG8zi*DG%d_^9$K#n!F8WP0o6_~ULN -z9HmQq{!ZC){&*<_%NRasYs2l0umgpdzN(SQrtftTB{jNb_Q6lPo{JeA$K<|=3JcCV$a$)~4 -z;S#t4NMTr8304eJsmIvaU4gc*hvcka;&0ZNT$rk66Mu@Ixv2p*s?or5-RN~E{it28 -z>j>6a+7J1ACatl>UIz$pTQ3t*1s+2}|M|7cw}sJX5Z8T{|EHpSJC}18(5D1(Lzr^^ -z^!twjCty`WmcCZhXaWSyFnW~y$^uCPEk2U~KnIk@z5XD-*9FH;#lqDR{n*Ci*Zh|U -zfqLO5jv4ZaYg!P%JOVx+e~i%XxM-0BCCae}ny+Nj`l=Lf6dMr-nvc%7Q=YG78R?)H?+cSw4nlV!$a -zv3N;m!nm;}hq^PrZ}D%?3aGoaDGF7Rm>{u`dn)^9BO9sC3TB-N(J*9B_!35{AI(l|2!>mU((q4*% -zHkfR@i}RkUtRstixiL5nefX3x_>FOPT?RZ*duV7xrc%Ia80G!Vo*bYBS$I>1&y;F7 -zhw$y-Owu)xF?EaDlHj`7>>@ek^z&71_BrG>{(+l{ -z;$zJEheyA8xy=%kYC5V@cgjMVJZ;ZGYg94p!NGxs8axi30&Y-_Ts24`XCdlg(33y> -zLZ8>J8*`qy0DE^~5l}o}hQyipQ7#Bq(bD`X8_{m;3u*l~+ThD-EYvu9*Bbj;SlM-w#T -zfX0!eyDtwmP#c_agy|BS -zhvK3W%>7ZiVen|DWQexdg;fwHF?<=8n`K;`9@J%`!(wh>_xI&sv5o0;bRc|DY$nk0 -zur*@lba+uRQxNROG~3t;3xG0ha0|B$%N4l@DhFS}SdCoWfr{?hPV@SCB$RF}e!rhv -zc_i!keP4=i^6(dapTe%j(K=!ymmBMOKsYCEF>~F+8=~cKLvs{3JlXfzb<9Vwj2)o% -zaU6`G&O;T3#t8wIS{!ZLmaKBynWIyw!-eTs!uqd>2Mr_+?^l4eTj3CxZGfz{@~--; -z{DpMI?BTZNz!Ga%d~BJY#b-L+g;lmC*Ner_*JVtMG(@Td;-Qtir{IU}u4V!&CCV1q -z!K8HS7NHsj4@fYTNHgEs_|;b7%5i#w*a>{3eAfDPy1q=$jG5HZ*7!G{j-#c`L!SBx -zJxUx#jgD)kjcfWD6WAc^cP&s=C7(upvIIF4y`a1$`6E2dtsfLFdGqF!lH7g6n{?g!p(*p|WuRqK$m+9P<~^X8I4&hW=x~P}H<3oc9XJ -zhw2(FYnXbLkysoYe`Si{0YJ1(D#k?+0#!VX1YZ5ATel8~=xndeu54t{nka38*{ea> -ziDq=>Z4ZrH0Eo8BalC -zu(!f>{)=c+fLVgf0TAu`=YtAJslSM}uj9ow6$k*)?vkpgM5g0{0gnfcFT5MCvH>94 -zX5ZBz_y0w-IRJ<@96kWi{>h{W7A)1(Xt?6>R49y;3%7%(aTqAhIx7ts#-2hnDeLM-$^ -z%Fj(<84Mr-LkA$*@&6#&8}e5_=^6!-0f;vLKZrJxs&bIR%OwEOhACvK|HM}L1R&Zw -zCMekeM4JJCXfFXRG=wMh{)1>|gy}C+r4^a1IOP9_XwP}NC;mmWlg}Ffh&Bf0KZy3( -zzlb)Nw*o!eVCIAt0MV8ZTP;tf1b;4E$t?Li09DuikihJ}r@{{v`3KR)2O!#w!Y5)O -zcY5c45pA($0HSTo5^&}^_d1PF{uzXV{uj|cDPVT|7ts#3OCkaw+V89O0_Yo1Ino;d -zL>qbcA4L0|6h)S}cZ>A&KSbLc2~^>>1oVh2O!!t|BGm|fDDxWgJ_?HU;T$@R{#+0g6{xC -z+a{%J0|}af4M>$G0wY#$=wC#;^5nn@6o6R&|L89)Q9FAki8A;ka??a}&`?Qr035h0s`8uV^43#rHYqqxDJKv&kv -zB$?swz6_~=Sf+Ii?C{ALxN{8ZFj%jN4I3-xYs8>mV9jb8@B^>7fO>>023E5-$S?4>J2{jUtxl}gFX($EawXQVE%DL*6=wIiAJ{GnrygOSt^SH~Nf*WtgIlB& -z>eaz$?PG_ -z5hxP-#)J-`u_%D^c+irFjK>KPTgv*gx-FtGZW|EeI^}((?2{%ouq3dm6$I&q!JjOs -zA1|5sCM}nO$mU#~^6uhvTD3s${T>6k)2=XL(ojJW{NbrQzNMBrq8n!Otl^g8vve0f -z_rZ5~9?%TYtSh$aOnL%a?x}$(>^zzPi@FA3GVM_nvo0y3xeCi%C@4K&eMDE;s7y{3 -z9G}_)KRC!s0EzBI+^PE1IW`$?8>37E9=Kp$*f;U={eZKXg^Ze(xAVib@R~>itRiRS -z6E?Vs)!i;j8NB`4L5hCPr+ptPL)_~}zi=n^^35qY&id{Y@C{@?Qk$TsWKx2MCQgdC -z(L9}Wy{!gDw;m0PnHKXgROu%bl9!v8L~?ZwRP9_Yuu?D$>5iG4W#+eUBvg*kA#SP~ -z=W;Qoybw;{C!`yJcR)MzA)3s`Ue{82KdU^+g -zvwol&tHVQL?Kz}^D+nJQM1@MrLW{6x%&_9)4@ka%t98o8I{~H$PFm@{KG(}$X~M!= -zudYu|n|&N4C3T!sl-yU93@t3NgJ?r^vQs4}fP3VmM2iz*af*ETDD^y~k*Vl+v|)5$ -zmYX_)FZ3N45;PpFJH}5oDJx?RrYzqum-jKLMs^xIn03LZT*_hnbm`$at9B}Dfx8+u -zBE8zS-ay&LhE1>=stcuANU8(3+-pSSKEcqeEYi4Qz`JGYhc<~?<5G|f=C2TQI!A0G -zkO7*&<1@+>ytT^^hPH{$Sl)bsSo0pIPbDgmWOHNuEUmW*Lyu`a#l;lC6a3}L$@nyE -zu%@d@OX}u}&q_#cW^nH}`4w0k)*JsGpjqj*1cB%OcrM3(CQ6{9r9hL}+$@K7Yv$vj -z)keVyp7`AJ>jMEL=DQx#5zQeV2BQw=6}Tw4NlJ|qVlle&j^QFpgMAY!Eja!tbVS-t -ztGM+*Q=Y{Q&$w04uxD10B^}d(o8m9r@i{!q#vdKDHwL+YN5fE1lvUdR9l6*AY<`w4 -z_N2nMh7L8WBe3@0RxwdKi9zqkmk!CruwpT&`QukC$R^#{VW#07^2=gWh>(&&>#tO3 -zRAvUD1iOjnFyN?`Fr8qvy}mBRzYv$GxTz)-@R0?KAGUS#7JzJh5qZ&0u;iCp&k-l3 -z-JeDsPrer-+d{y$c;kgtITT~OJ)dc(yD;THU2o(8DV}t*hwb8mL%%M$#rRYZk^1`l0(LloHCR8Exl0&^f!kq -z#DM3#0n)wo9rWSbW4bfFQjHoVxLrs_}|psVOPI(j>CVXZmq -zR(*Bf7o(C-(0lH0$A6*btmBHA(APm)U;d^jab9GPjpnyA5afqYwiN4dC&T&ydL!%= -zvcbM3w!5fI(jW{;1iVQzCQze5Fc$rhEFJtx#s|zGu&5q5S;+{qa -zbBP;89Xu9Ej^h?%i!(MHrxa$Ve233s1eJmAJR%2L`lfRV$yT|C<2<6HF*fzO*nS9= -z3*;IWZ_P=x0hX2y>sys)@+AcXPb|GhKM%QK#0&-I^!nMTvGeBUx?RcdG?_&?TPo_>!(Yo4_@u5^fBkoK;KCXtm9$Y&#!|dJh84WaqUNMwLe?6`)6fRtjy< -zDH>_+*5A`oZdn@?bG)>PwdDCW8@HAP0@}c=k+itDZY2^zPY4M_#h$NDexqRw$AXPG -z+!=(F5=QNF2~n>I#p04WNoH654sU!6AfQ_M9CydB+@PS!jq1$yXkLEX@Bk*t?@>3h -zjfvSAvLPzpf3T;H@2m};I`)hc{4K5d5k#vva#^c4wFRtMh#b3uzc{@I4}-0`2eI$9 -z3^N%FmVR9-=i{sJ9<^q1|fu -zR0t(Jp3=%_$~Ggx_9`i>ydVNlo1*wIk{^anAz=Qeo}a6C0X~Ef`kR7RCN+i%bp!{o -za*nojT_4{mf%+|p{PtY@w#*k}Ei!Q&7cujk8NHmt=N_&yKu9h7T{nj2@V_-Wdg@RY -zItHE;s>Jo$VUCID{+QV!Z@_LHQZ!{#k9ujN3;~6T#o-+U7anzLb4G}y?}oI1@x(8v -zP6}IWjka8pm`iR)FP0Dkp3VptWTS`7ki4q^IZ||H>o@;Eqcsm<8Jb=xNV?-NhO0tX -z=)jL5L!+I(%O+M&kRKgYg3cqhpAmdzTF0s)gAGueQgOx!1U9O-ay~^_nY-lpgG9JJ -zlx^`4+8SF2k5t;wP&8B_zNp!_!{pI9L@pn*;~oGF@R)wd8$J|FdAcoe-r^8&wS#2Z -z$D*|dpv3`yu2p*~rMz(i+ -z0P)#Ca~#)EGUpZ6Y5t}}V9%Rd`36@~noZrunZKN?*b6pTDUh~vGD1f%Omp(JQ>M@- -z1TPiWQB}Ey6>gS_fUX6i(8rr=o0=fzv*gfrGKwGxRt38^9>}b~qTcUOM>faN`2wYW -zW0aXJG&Y{plwIo8##~T-j?mz8tx;09FeSf%B64@J86ycM1#@_l!VxBQ1$O&g(gom; -z3?&CtVd@pjRVr`Tp-4_cf1@j$!m$M5jQm-Y*YPa3cOa-N*r_ouL -zQoG(2UyQNMFLyWCy~kr)p0-Ow90+A2H_%-eK_z205)Mrpa}J2?P#DsSdg6}9G${@a -z4XbvhZxoc13Z%WYpaS;usoTs!v%j6hXSRoz|EP^nnx9Kj7ZYXStQN$)ctyk#B%5A% -zF8|bc9hhViW}AVB-828_B0F`FOm{Uw1DGmf#^xvSk>?_phT%@k6GmCNJyNJO32*ic -zV#TsLMI4+gPLDYoJq$ucbxUrk!MO`n1D0?v6NFpZ -z3*TU@4Pben4sB>vrC7Gtn;?CM9lzK?*Bvx52&P&-8L|xpZV^Ji%@RQZSgj-MAgTsvmV>p!)sNNAVeS*iAK@(h6#6qqekoIt=w7e@-RaXMi|Y_CwmF -znd5;dDwUh}$c9fT=3-k*dGlJkA?|u4yiRA55%3hY2DNB9w;FqL$PvNPrQ}S+gvN&( -zJDu=P!?PBHGjX47b(EvU+DjT~kt#9@(o|o5UFjP)h9X2u6=wuaFb{h{p$+ERPLD>4He=bMF) -z`#{@l8{&)V%o(XhO4}wP@T%GqZQldojj|@Ad0e+%NciR=1!}6P)3A1~hBhil?AloP -zzWA(J+Km5mHn_9E`ivf>OFVLDVJg{R|C$ectS0?33P{&*C9D0+ -zeT&N~X(ElSt0JjQ?=Z;uw51VEA+lv5Kk6NM`M?I-hG-=(i4pgwMo>tLsRG%*&#r}_)e -zT)Mu7QC1i!~oPQ@GAO*}5 -zWC|xAk;v2JlwH$f6IFr-rd|rpQ@~6}>^y^^j?6rZFm5H}){W8&FW1gR4VXi-=Q7ZH -zs87TiU_Ytgd!ea2Xs5%a1EYXlaj_G5WBAihXBo}oZJt>THJoD71dUOC>+L|Gz>b!U -z#vqN>4phfvw17SAKIqidx}~czfbTMeV(-c0j*db(b89-N+Z_nBHd5nK%Q -zARoAd^=@A=2!5!HsVs!i<9gV;zX!A$SgsUB0GqIHsH>{A<}SU25Q9eE$x_#OcIcu} -zN$C{V)n|9~cB64Q>C%tvcMk8-Qp2#poW@WD5DQZFIVrTTK=5bN7%s>@ZBvE@abtQ# -z>j-ozPBj$L(TUQNA5cA>sm>vUX?Vwe?)6TrMJw#9!H7d)RJrQl?*QBlL0tN#r<~j6 -zVGuGSz!*~Re4MhXS%{pEdunkIhcMMATro_H-UJ()OnsiB+7J>u(rB>rGNek9@0YKd -zz^8c(yUN>Oa`%ZDlzhyY3s0wYS(xCv${@j9NvFWbC5;bWA4XpkdE-TD>tX^szrh~< -zLVRDJ|9AWokh?^3i0G;_gadtGMF{`jhp*S1Cs=%e$`fb6>sEOx25Vy$A#@!_(Df92 -zcBgWx=OJZ+4li5hbv;HUT5SsNw3aa#9fXOdJ6taJTa}IB4tT%V8ECOQavIXZ(3d4! -zktznAov{pW)4iYNPDSzMs5dg!5S$A3%k$gTnsbam-3^rOZM_^5kALNS{va#Lds9dm -z#c_mJR#ZZ4@z0Pzha0@&gL%nx`vkP0e~j5R$DdC7yLRT2$BmLaLuDW|?hUHEZqo@YEYhqf^VEQ&BC&O|1)sC!_VMLHmT%PCm<8f&D4+^5=wo -zYr^$Z`#q?z7fHreyyP+M!w=pbDpn~j(#CV@N-WfL*$Y+_@go%aemH -z%y4%i6&`Jee|+8VU&D@`FCA0I8Rv_8W_+)pJm!H`YDW47mjAZ1!8!K5tcN+_-RHx* -zAedo{LlZU;sG+c^RbeavbT|7W6MYIMRrFyHJzt8HL|V0d*sZVj#~JUdyV(~LfZDK)xgGaS##7C!8?7Kw$;?*knLwpf -z>{u(}mnAZe&E~@@1wJp}Q}H`c&A=5d(8u4;hA~_~s@zH{Pqzr9Y3lslMTAanh!bktD+A$-Wx+efdU^nK&Ng1oryk$rWFsmFp5xsI|1L6d98o7pP;m -zUJ|(>%9Lfy4m~|2g^8Un$xC!FfH|q}EG#lE^PN>9znij7G28CkxH^}_La&tAd) -zxU#t%k+Q9^a-lPxyOfWv6R0*S6GX|!s5YJRlXUoF#md)65tOE=4w~8*=u@{%-Ef`_ -z{Bhf}0ElQvv@u9KS=@5VfwO{4gHm4T5BZnKIuYfm<{(Rp=EQQ)k9C69b03ct5?+5l -zp`xXUAjJ*`zKtWI1ntF?x2A8(}$1LMrjBNH(yJs!dvMnL3!s%j={zd~L#GcVO%~0&OhC1Cf%Ie`a3z(U`!TW3&i%5F~K -zFq_~UFsF8?NS12QzzZOZqrIJDc{`wAv;9rXZNtFnx8gx(O@;`~8HV^+o=IrhGMIE* -zLy&`CezWU?Xew5jV(ROr0`cR(Te1Qu2E_yjOw -zQ$RS^4-#^Bt(dM5a98(H)i}vEGO*1AG8HvXJP6+vrlriRYJd6gnMgn6HJ{lEwRxQ* -zNXFRLF_Y_)*_|yyrpYU@fZ4%?+3kjU-KMxBEn;zH7=`c$Rt3)rTraie$%sZO{od0s -zbRf-dqF-d?S-H|x(1=d+w-ys@2;_<9n?6C20(3OeKdB6~O!r;yQdYREHXzwf)KdfL -zx8PebGXblpDKOn){izLGK8m7J*6e=xa>bSM)wf7eUJI*ISO4x>!RV}kN+!cf -z>LGR`MfuuNNvB#u$bROn8I2dd%4iJ%6m -z?y-#3fvprcmmw)B&jyAt^tgBJGb*{I=yJ%?YpzT*mD1jq$|D|^8#C^;R=SEdNcEZ% -zN|H#!{+n>zhprn*Z}W@afN*dh3lZrG2zU%Cw60D%g)F~m$)n(z$gvmr_RE&R$cM$b -zdVp-m-qoMs7W9l@ZwEK0UO0w)$q|>wNZQOTX0-=dkH3}huPZH!s|uHvR+K;YtJL9T -ze0$h%=VkZ2nK6euL0QGT@9$poYxyw8%^ML^0$ycCm@!Ed_xVZM>_Gg7wnQYyJZnD< -z(k=3p1BVNH{EaWUfLXq0ytHC2E38F>3dn)YC0;1Z;HS8;K-s0 -zyCB^oxRErq9Z*7rxAdDSbRTuD!2A$MY5fDd+wKq|LHS3Y7P!a|=q6&<#X_ -zU|`#iDc(T!8sYmY6J^?cZ~Lh1^qPBtiiFbbYB^9P;jx@7iew8`L20vbLZP)L6#}g+ -z``%e<~a^cQInkn>q!b~bugW1DpW#r_h^Z-dCrOpJaEmx@wxJj -zsDvKzbHsr`3{vBqvX! -zSgrRgPk8+g^B3FPb|cv5{yQRfSAXHI%hc2hjtLvP=J9=n{5i$SkPZ-HLt=bxv3V-0 -z%k+>(Fz6Fnb6uYhf -znnSrT5gUaNr0*JgPc%BWbph7Ls<5aQ1p`Q++bRg(EnlK@np++q=+5V3-MkXPT^gRSWaL&Gx?ef}qc -zp{*S+gxM$H*J%YBOogG#Pgw??IB}4vt!d|DV=QN%>EN_yg?v12d7yz=x-#wqkOV1Z -zOCl0)wy47du-g_kHZ0XWq%ceD8n%>U$#(JCi5bSLdmO-LNZ1IIxs9Wy&4yhG`Ylb{4Lf*Xhc1nq_TS87IXO#Loa6*Hdl-u!JSJDvbG^m+ -zDA?(tB!76BdHxV$8ufY1aTQG4fu}Rw@F7Q(yfHsVDCly6e-wEc2>$G$Gu)Rp;?*8j -zP{&|sA1d7M$uq*Fxk8IV*li-&6JB18rGm*hB}9`cx@Ak}7^>EOTCLs@UM+Yj=?j7o -zof)~xUBz|Hu7NaC<7Ya}B<(9|rqwdbbTf#Ar7Wij@hs$i?b!H(7NV?A7oNwWd7R^w -zW>JL?XMsrB;Z=sS-hBvAIh+o}I49K=_PKhfN=Z1WA)?B5VC3M*spq^K2Bn@Ok*nxl -z_pmFUsS@M})4^<_FQ(GsH;F1^X<50zG2Y|}eOLBap0ap|#EDlOA%Zj(F(I>a`vd-b -z<;9#%8CSCf-J$qxwyFW=7KbfFlJ*vKS6=1t*PU}&m8Al6Sc((XwV&hFW=%$4LDswk -z`1#=@!4`)!OWbwXK^Bv0nM2%GOtI~qkQufu#&Z$1f-!b6o)AKmaFp$u60_SK#t16v -z*yaI)y%@MXhL}=~`Yh#QiYt!XsZfi*W?m!>O>C7hU7*PcTEh%*ULX-rMnF&((JWSs -z9@z4Xqn;bdo%^yyG0fPhQW-#G9ZPnLQd%L=8M=uE6XB31)q1V8wYUT*K^V*g$e${& -zk0IOO+>tL?|8knWap|(5rs>oX3neWeU@$$2qGyXnrN}M^TSJFlt5VptP`|gtu_Yv? -zE6lL;T?p0+c%dZHnaes^kZ)9x3q0OOF!|cCr6NGGtUVzs_#Q|sr*&t+eX(7~qynxR -zICiXx`m5-|QqtVz2?I-AVtwBPyv+qq*DR)n3YjxITxKsOAt4Lr&#i9vvX@=XnaQ7^ -zU6>r*cYtp+4x1(Ch{%}Ip^+UiQ^ur9jjD$;o_ -zE`>x7=>Vi@^jOUcNXPScN%-;%M7(n2=-(857V^Bx7i8yRnH;K;as5e)s5bb+;9m#6a`n6(`}aDIC0SxIDPa8;3J -zq8jprUh(}vceDf&E3_pCYB?6?+Q&82Z#+4ivZ)%8lW3|RR|(T`(`J)(JZECdgp4it -zrZ>ydK!P$IxRHtDJ?3v3{_b1$>gaNvz8U3_+XUYQwR{bGpgBf|h6v -zkZblS8V%g|C<0i4H-*OVHrpL*AjIFroGW-a^__#6&rSs&l!6jRMF|f;A>1_AA{+62 -zV#L{FIV_Zk8^>SvW_+Y@`|nc1da@5r%@%*a7q^%CdaqbtT&=UayXZE5)Qtc72zQov -zvAH;=zEd)Y3}{XiPN)n*a*?ZgA3y_lVSriiE7usV()z9$>6b9h;-tldp2i-yhDK&f -z9x}%?7pc+&9tUY5~rka#An)X|__u#D!{ -zTi=*<&`h|~%*!Hi)pQO|8RpxWD=>gJrnX9#()W$J$$+$LXX2q~iV7mW# -zDFz5zyY{vqs%^o5@ZYv+zLQ892^&m^$5-K$>u7CWmHgXGn9&i -zf*jJM8c4_6g}VLxTj4tOB}Y&WaOkSqU;d+Cu99}7lGxz-rn6si3KAIA)^B5c6Hyn) -zV|Z9VxWi<`$nt$I?w1&(e-ayRJTS2N|sHlb6tS$^( -z%F!NN(Qjy97?w57?)eS068UPf7Q(U?5oW+*N2;A-JY=M7ABzSW6~Lk#ZWqh -zjDa;kYXp1Y?1!LbTs%SF*WFZOd}gZJ?FbGq111c3Hd^G#Y_HmdJ!OS`qtXuU0}py! -zeR>pmLC8BW8y5{$97>)Q+wrx}=$9;$}rYHNL3rvx50=eShR -zgRyTSWQoDSaHjckw}*OaH7W93@fI4UvR)w^UCx+%z6$5FU+3)|px=a3d>QaHSUUY8 -zXHf#3N&`r&#n~}m5p6ddj9fdh3N&fB8e)xQrfOF4De1opw-b~S2zzcY6K|Z^q*yMd -zQ69rgR%l-8?mgQX%w&;?j4EE?}fW5vX)Iz`T% -zFPM|$vpNVhWIw`D{$%p|`wN(T+$g)*a(@Nx0-0V1fWR$#@K@kwL8$*V>~wZ!|^b)e9#79VgH@*4zL9tXp-Ag7Bm7I7*D(!H~~#F3H;6>O3_0*a)9 -zU+AKWoD1+<3b+kB-9~n>7sk4|Znpo@8p-u750>K>Z9stvKODQ>jjmr4^1mAsPxY(COhF=)fVVS9TMu%wT02X -zKjQ15WFLC;jNgBrC%j4TXob%N1IslQzh}ALEMo>itZCevS^T-oMlW@=JDGSG(I-zh -zVKm1C1;q{~KIs(DL-JI~BM2fiEV&*Ze3H6LcAgU7=WT|wOtWa}S7-K$0E@h&nY_V* -zsn9nAP4m?560%*X%SY_M{`|#ST&52(tevLZ+(Dn2f#-=67Y_MATY*qO$N-zJQtF! -z<-q)+8sx+AT#|4NtVoTs!h1I^9eftiiLQi*WO%V=6|7uMJk#a#(%QnOEuZ3h$i6Pj -zr%muMh}zY_eyLu3Dd}@eIs=Gqz&;fOiW;5`Jm{!d1#P+L+Vtun%<-8IQ?H)KY`mSG -zv(JA3_ZI-*W&r@)k=Z?pSL9890q!iSjJtmT?&?J_6#&4k>T2^Z!2PF;h}zmHX8K|` -z%QiBAG>Bv{7D;kTcRS+YW6Vv?ak8@779YoUEcOHlbg^{Q;kU3b8|@|nTq9YcVJOcl -zHYwz}+&dzbc@hGD$Z{AgM+2k9!ebRI1B`GU1ib>+}>|ddrL6 -z2*^(__0Q|&WPdlgm5NRQZ5-F~Zz82b^OP4A%|HV+FAu|~Qiab^DO|5l7%GSYq -zQ0}?UytL$vAL10JXar3yk*+a>8xR{a_z?-Lm<9x;EKPZ^#xKbfrn#4W8(hx4Cfm%oSFvJj&|KM~fu9Puu8iUnU9SD2QS|E~ssjs>P(mp@=+?RtmRluB -zEI&MZ!qnw022rjTG&qMOje?O@h@G@`w5dv-XY+z44N*S*hhGInG-#f7@oHBHnEjw53Um3{)gi -zK-TnlEimG5x3~{mCmA4&G@c#J0j<{}rOgCGSyC()kj)lDpe2ac+T%zY+bRzC -z$!af<=~=q+vP}~jM%^j2T!vY{#sTil(Pi2>V8veT4z)1vpB}f|r1%FK%Cm7H;v>xl -zZ8|6L>oXtuoPP!GQ-Ht?9{8I3SKwCoSKy9HpyUS#+!)7n(xpO&NdSSn{dVhr1a2b` -zI>!GIxcxQEiggbvITf2N^wp^bw!Mgk82gp-Pa% -z$}qzkE=jwKqEx@5VH*BLM4wc&d#OJ7KLU4ryY;$GuB2f8CRcN -zKzICd5zcv|V9yab#Or6wFWtQ0M!p153)&?jj7pq5ohZ)?VFXo?D@0D-$mRyCO%j*N -zldQd|OKRg#Qx}T%mziUB;Qj{(c(4lN`3(c -ztHT2Svu^erj^_p1n>2RT?d>$Z&GvIPkbySVNSI@#e+6#rzXEqTK;V`LQq32KChzjS -z#qa!)R)5N31vBN8lJL_e!GwZ}Yt85fvX9+wn{~hCwj85m1-k7@+uG|9+$J{+9Vdj4 -zADpc&SZr)o=v+CC59IfXj|A{#xQVq9g>1y;(iPcPSj+-M*zFkf4-);^8?4@pt#kTW -z{|MZKas-m{0D=27nuYxzfqSXoufSdYufXl$Tmk)ZZK_TuuKLP%hR6UAxCJc%0=L8^ -z8$jR|yH%IETHa!bh}%-l?tPadXy2(#NB-5aemW;pxlU1s{Sytu=IJ1jEvEA{U+YXUZ#QI2Hcs6M -zhf^p#8+}>EaI5>hkc6Nq*KpWe%}uc -z+>QF?i}XOYR<`lY1X)T?8mT)jr>PU;3Yk9)9QAoN4vb2C@Mn$-Z%OPHhHs1g-8QLg -zpIQo`L{I+!+)n_2d!^!EfSda-z%BI`;I8H*RidIsc2ENV++hHK`^Wv|s_WoqBdCp1?p+zcvy8!0B~tYM`_e1J8fxajo>%Ja{lIvxyRP$$%8 -zAynWWvYajvh!V~P;(vfp75!taPb*MV?iuDKDC0`i-6xQ^Sso7}a8Ayxa2MACbLbOc -zT0j}11!&KUJ)?NtJkG$xFMH{4Wj6U9ngnj -zAO#aJcfA*69mb)j8)+^=vk4f(|8DmZ;h!opV%evJ@pzT^#W~K_tM`qBk?bt9buFiv -zN3{UcS4ny(mSdBKcgw-C^Yr-(CBONTasibgD1mRG->q4*6Y4ZfxhD -z!(OP1XBwKNHiyJai^_~M+u_86nTO$M;P&D%@4^5e_SztvcaOps5)jp;3X6x-$t(EPE2wPMdBj(Ki&Qojc -z04q~|C}nqn6yaHZ9zJ2~X3JO7ENbCTJeGdm0Cm5wJa|yPISb4HcfOy<*h#fNU4`c* -z?{Mw-hzcUYQV}g!g4I7c?4NZHE5B)PWX8TopA2<^fG4uZjYlZKS)o9XG5wlkyZ9I2 -zmQwu-a4$f|t1j2j8-s)3{0DG1r7->~##L@eTKNayzJxyzploNL%mx75l;90%e*ta| -zU+(`0;0AZLSN#ic!{H)pfh|Kp`~z@P{$GHb(FTIC6<&Mf;VlTB^sbU4mgR`x!r5WfOO?Q?G*!`G+IfH;+z%r&;ggV2{q7rr(A*l?dIMKB2=B -zX-3VZ1>HKxHI7Bo5bTjxWrFUF7la~c)mL%SB@Ia>H)%KtP&to@H@61y^N@TSv3@J9 -zR*L!47?ct}Rtj38I9_~W(b<1s6fFM2wJ$tEk(KI!SJg_W9bmv17@@XQeIzfUR1e-7 -zf;EWcfFD9MEw<|}I8aX@-C#>B(KPtPY>8ojaIOmTtx~8t#_zIEp~Hfc3Wo5M7{lgN -zz*5luzXb!dv$bEAFnv=N;}3T(R@1FRSp%T8+{ed-rmjFiAf2-o@C2nfs7OPD -zd!GA9X$OOgjx2qB*d%M;PO`Mvq{#l5UT6c!3=n^Q*olldIbu596>T-T|0i&#@nkrz -zfc#&9`#V7326;1x=|BA|a994XzTit((84%?P@>vF(jt5{#c#=*1Pkoyx% -zB+8LFvqm3QirEN3Uv0eXzx;N``_ljN+wPSA@!R4qd9cg<@2$F6$8I$49 -zT*gk`vG$=Y*U7vZY1OvfY%VBPJI30-l^`LTgcV55F+2Is57`vBv`VL09ugc7jH6yY -zDehG0ihVKD<&lctPEp{FYepU7T^b{@xn5S8UC$!)Gup!>E$I?- -z%g*s$bxlG~xr;T~MX1dp3l?W%9!aMycoDuqAZ((RmF4$rc!6NXcQbg9w;IC8%NkM1 -z_cBMB9*2ceP5w=@CiV&Z+>{{aoD)XU-#8^tO&pdt-%w{QtTw@zvj{Y)pbL`aEq48| -z-|-;jJVbztHL}+_4pa!N?x;eo{C&@-&ZJzxG{jBONXn5bWTN-^*5?LGj51(Oswqs3 -z-hoKJH#O~TDX}w1P)ARiANK)OKu`c0*slw$hsU#vO%L*HQ42<(EKwXC)9jQ5cC6)@ -z#FI$s-~|J};Zbo&R&DWvo_`e20RwJ4K{U&D``dwQaFfl7CUD*AS0(WMfita1fxz@f -z(KDSkZY@Xg;VLg{wT}<6Qw<1N_$Bc?7wB!sb=AYzjbni9G^Rc39)xpHYI1l$<`*{M -zhMnBiTE&Uh8In-0O+Z#EqC*i#L90#?7G!|Z*@l(gpZM|Z|HIckw&&Tk4ZDtQ+qT`< -zwi`QX(Ac(Z+qR9yw$WG(8_cu4uIHZ5J?HYizu{Pp4`UzOSoe9s{^1IQ41mA=iT0if -zluBksvW*rW@(ey0hsk2FfwQWw>NEIjY2Y!16~k8rzAPFveJOvD6C#VZ$2q%=1J+Ns -zk>V&l4d8Dp;bD{|C-Il^Z~*-6M-`{tZ!46Sku>~K)2FdB3s;(W8sxn~cL^U}I<>ws -z%6E4h;k&1VOh(N;URL!_wL1ZOa-RTs9;^8)3mYkI`{2eGhLy_5o5%6NjfdK`VRgsX -zC#)(4u~%$D6~p8MRu>q9#orJV$J$5y+Nzc;oX9C&omBkmV -zI^AxP0DfD(7@QUHm=Y?bJr7X+-zfwTD>3}#w^vCrBh?Js=o$e0HijE%){g{#%Q8Yh -zsMxE-MWor0X?X8WY+U6@c6RfU5f)I_VSMHhCFeTZB)4i%$Ch>!7pHHNx4A#yG53Wl -zn=GS9S4fzxQB`!{r`|kYpf&8jF$mTm}`^CHrKNK*!pLbLI7N -zs^#Uwx3^cq_e4@=yM0#QmmMD-o(p8S4L1?og;>_{wN}T6)X#VQMp9RH=h)C&rHOYe -z+e`KJhs(yTGoxq*_s?1#(^_qM5#9xGesxxn)`wP~<&W% -z_C99|fJGj!Rz4vu`xl9}nJR+MZs+C#B`Y7#w!TpUPC$kXmHOM|fwl)RYdK3s-1PNV -zA_0rZBfu|ZT|1rhr+@kF!P4rCVg1cl#iEvh`_^^2SDfhOh+dM8RQ_}4Woh?WF8Qt4!A`uk23{Ml^ -zTc-t?V(C{?f}1EugQQOqd?z67RwlN4P`;b}oMi0rS|a7Q?YYd{YV$pw$c@y@$@#-? -zuf1xu1Hn)t|I2Sfq!i-)!*6#+hS$Y!pf2bKnc4MR`h>?W&Afaq9u?B+RMf!y#CS!8 -z$@6V5@0fVv5EE?M97u1}x -z>$GiSh}4(6@)b}`i}6}b1q$NFmMm;TjC|DY;ZR+82>a3dh3eXQTc**AD19L0l;u1D -z?=aI0gkW}2vrErju)nG*S=O>v11ef7@A+QGZDP4OZcdx$r)eF!58<*c7UYLc7ww$0 -z!Z42%SV4qjAW8o7#$6av86HJXVD`pw%>=Fh@8K!+?zfz+*$j!_!fX6f&^wS*8q#+W -zCCO%Lz|nF$)RhAsUxOj|Gtq&%M*9bU2jDTm6WZA##flGOMEflET&vPSs!x+Ybr@8O -zUmID~mcc@tq$^i?e>kaV==FLQa19pVM{Fm&S*YeC-suVvnQ?TcpZwy0D_e9ma8;ge -z_?ml~XdxdQqxX^=bS^99!OoykQo?2%L7FZ20 -zw%iH54S#5TkK>Sq_}OpDg6Kh;c?|*GSO=|1jDq&}%`iU^<7dd5KUa6)3Zc6Gpahn! -z&|{l7#SXh}iOkFh -z$5-e8_{qL5I{m2-ubwa?`T0i8+4X|6HtOR_H1A3 -zASM3r+a?L0c#kW&l^>vkU=_O*YxcU3aJA*F!}>&M+3Q(WdnsK5uJsP1*Tv+#3kwJ{ -zF*T7p_F}RhQdoHXwq?*)MHRcTw|k1Pi%}ui@s6i2KlC=neuTL=SZ*15#x4(>0o!b@ -z!W9A;kvW*P;S92NLol;WOUI3 -zmMnWZqS-5{#Nqokr#`ULTRVz>OXur`phE59zr>}r54s=CA -zm2q?#cU(g~7F6lCY~8szAUHu -zyzC{9AGge;aJiXypT}sC?ra#1jgR^?%D{D+_kWz-S!yl%d|qNc(r&eKwdbz5de>w) -z?ez3qY>mzT%Jn@e2Y;@Ae7-5l8LE+@L9#dkjS!x8*;{|ld6GT2M08A{)1 -zc<2lcIwv&QJO5*+{>JL7fNp(+*?PkciBrn|&#!B4G$FvbFw(W`e_>>B2ZZ0whI}`QN{y2SJ!jg3Wqp68vdz?!$^czi=LA1Qj*$7Ubh&n}{`Uiz=$>b1$ZVH{tzA4a`svmM}MgUTTF -zR~pWudVTJ;4NdYNdNhHu|LEH;ckA=i-59c?aQZHBWwP7VDemm9gaPTGlTAO^fxq#@ -zXc(}LYQxWvI(NzWnhlQJ(R2n8uMFMS5(?C$Lv93dd=Mjk*3|>{X_jqT4o2;2u&oKd -zy-~NatM)?>$f-k-0`zUuKl*k7xK<0PujAb5FMz)7cM3({v^`@&T5Hhi9;rBrF34TbZVRthP|{kp4zNtiuPASB3%+CU*FcT>J14ClzE(0=egYXPXW$luyLRG)U=_%FyoBe6x1v -z499EPAO;qzt5Ie}uMX(%5KsBu^W*#DE9@=%uBDd9E>#vYkHwUrPYw>0Q|vT12Z2)r -z9T8nppjt2L2!k_l63t(IJE+Q`CGbs(q^FU-Xq@9t~& -zHS)hfB+Hykvd|Y0j45#di$`bDViz0`5Zuk?;IWv5{n%`%zd@tAfr!%o_)fztJV(h~ -z6eB{(xXM6|>GRHP+g0IY0u1E_m((c}YQ-<>ysuF!SB5N-h~|eGB*2= -zX`>Ig)8~+|eBgM4IY7ob28zr>vGTWYPzpm52`C_(s}%K;+$RrpQHx%+HYqV6itDOn$2HPbPKiVbvx2;{jnHpvNPHS;(Tlk}ITl~?tc_?a=o=-Zhf9s^5{Jpg^1cIA)04fokT0noP{Vu`l@)wdOCcQ(bu<=hBU -zWGJ!6W& -zCLj>HM7YOqf8t7?o!|4mwBrf=yO$o*AJ&C8$#qIryz^_)6?(0hrqXbP-Jd^r1X65h+cBw@UcBn8D -zRtqn!kh@=sP65^@Vfx@fb<3kS@7|3&H*^A-Y|dQk(X!EPwR@<&f*g#waH}+h0Bt(OD)9`cz~4_FD##X -zLN?EIw8;V+0`ss5SrCGCXg)v~LCLD)QLpEUfPvX?4TX~{6E<>PTJbXt?+&9v_{07A -z0{jF&(0o1Zb1dJF=9fRm{OP?AQX2q~_j}r7L0xtsCN;G0p*PPPrKJ}2j)n$T{^b`& -z;;qHk@?G -z(vysVk-?i+$~2Y9bim`w&rM{iGdIs-=37o0XJ-rI1w*jqTE?&+TK;dpJZSl4vwS*~ -zM@Nrq%R^BwX0YAkz}E#+L~Kbs=?%RbRsiSWZFbeq@9BA8-|lO)@FsksBTvO|B4`#* -zUI8CF=Hy5A*fmDjWRoZVnK>cjlK~sF86k2Rp3Egk3QDCP(QBO#l0;)NKE=5Z!?`^q -z()Ih3>V-7Q#2O(DAym2GR={`9S5&SfLCq2?gO=&B--3FcCt%gy<_r6lD|eY^DNh~G -zk!7m(FW2vvjPnRn+aI^v->~}=I><@;c6z*i_x752`ZsGnokP>e0Vz1g; -z2}&jJ95V;Hkmq25%31@S3*|UCzBnIWFG2?DD3L)Qh;2!Jwun-`sG?vY8nAow*Sf+Z -zMB*tu9hk330(nb<+(L1XOa#9V2FdKg5Ct24BiCe>EG956bp>DV!Q&_eNA+zSnMy8~ -z=D00=PR_u|E5w1PTZz(hosZ=??3gylEZelFIV&v(k#9jOe{XD=;3x6Kw7B+aw$XuDs!ue)<}1L8|X-})rpT|sgHLZj%^bK -zWAsY7l?P}eiF0ddRbDac8Y?zSfe{Wuq~N*TTmj=aDhmj2&!!1TQ3KAQTD^f!vastM -z!B}==1p2aFK6Qzi7}K-|S@Ct5dL+oi=oRkU@-v=>wp5(JgV_*9=sVvmZ-7LN=t-Mz1Zt^{=Yl#o -zG3^^r2vAm{xfBTHj4-{=Sm`_3Ve-4MJdr!B&3cU8m<98R@fMx9`%BncGK6re{t@$c -zVu<`Q@feM>Q;_=oH+XC)rf~0NE)k0`E=Bnp!$_EGc$qfrlvrW@{o8K{uR2Dj8ItK8 -z65pikzuLIO7kz(yq2c_ErHuPIBqw&uZ1z6bz16*G1})8;JxtDLN-T%ddQ!w*f%Uk% -zD<}d@0;vG(Dk)KeQxw;P^uPo)k?WHm+haMBWX{mH?Mw$^6{eXRhr6I-XQ~{;(rZe83Q?vGyXe{vc-2O_okoD|<_UJ(yGv!xryx -zxOdeUO!u?0q;pZTNWO&#_J#7f@O^#MJ$fH5W&c;a6^l;c<=LZ8S-UO;HK>_>)D8B| -zhVLWOGj0@ZqMaHN!e%04Huzp_LaYd3cv@L7Y=NlS1|%%MVbQ>Md&;m{iggejg;jpq -zQqmNNVLR^>T5Gde$BtXIwl^5a$jXRa9IF=*8?dIp++Za*@-r~~(VM2Q -zveZah)W*b^OTbqe3EOjho@BSsN@V`#rvW>T^{Jw%Hb)z`{>!poLJGzjy

le4~qy -ztp7Qv_0ZWbn31DzOJ6*rL*j_0pKl#)W6;Jw-X3D_e60+g&Iu=Qbq-l*Y*(fq!Bzzw -z4T6rTml=4>u|oLQcGt3ZowAwr!^ZL59EZZ8({RP%aRb3*7Y5qj#VZ|Nr@vizu!Op> -zhV;x6N*YP*K2GVo$%I0o_iR5*FY7P@q*N4Z)>k)mlxDd7!hekXW0V@!(1s@hzMe(bEtun|%;)|bhXZeV<@1e=!{ -zkhyW>tgJ5e8ugw((TLYg#~wddbMis2I_iFR&<_O>Bx!d{)2?gWD&SX}*(=FFm|?)V_P+JmlLb15sRRK -zxNQ!-M+13Z?MML*2U7h)!N|oZ__&GBB027)E!esfLs~?u47v{TmQc@Gs9v -z7!=Zv`Q(wpnS6fdfH6;?+%#qEFZ4|cNLzCUzEHYouzQLr%H(p%Cbgkv@PqAlvFm5Ls2|t&0>YDxuB`o -zTOv6nM)TcEOh{nEf(t_0XTmU;>I+A*NZY^fE7{}W?+cq5)5`e<7nt+61%-$+p -z#arBK<_*Nz**}3qlQr5~VLb(Xd(KP{z&TXxZ~a+_cM+xetfjk7HSrbRd>qw*{-LQE -z*JSIf%H!=q#6C|3ZA<8pq`-!UR{~blwoW4hM=e2;NA#{~!s2*0jqTjgPcn*r?=pG{ -z34znzrMqp;sEwD&7!aa%{*NZScPQ2%Nn$oq5ZBs^>$W=3KuZ_zFe)0Ldz>*33g3qJ -zfEzS`z->R2$4n0pxZktz9Bg6!2;8SDSA9t9eVMeY#i5xuJ52Yny^AY0hsmOBoiY*D -zrFl`N&KL4n5SshLIIk-^3nrkPBCx{{#!?~}%|@JZkCFIy>}o(P#3#CHn~z29X&x>` -zsdqNh$g -zS#oSHm`~1{-_BHH_kEa{5&eW}g=m}6E*MKpAkVt`cJcx{NI~f0JTU1jP(7CU8%(TXU -z6Qj(i%EAy0rwNu$S%=NC$HTYc1a`5EB?(9&T^XWZJFq08AQRgC)B~gW7HoaAzjQ+@D)zN)8E2JX=r^@+|ni7HGoe8XpNb -zCDn_$xf}*=RnDT&yn^6Evor>kJZqhD2m`h@!PE?ys8inVDY<7VnJU337odrdMZ;su=# -zg<%gtBHdgn92LHenX=B=#CUNfRp-SeErH*T@Ki#7K@QyfksR@Zx*E7EcEXl%yi$Y0 -z4*}ta-^!Js6*!_U&@wZ?d7Lo!bxa}0qQsaKb*H0gwW>`H(6LTTBl&w7D(J43=nM()#I}6bHR=B@-={g?aPcQu>(d7_Xv0 -zBbLbmtW=)P2PN&Ib{i0-MS(+|_!53REuH7wHr>py`g(N<_&r&E9zd@KxJjvG(BYW% -zLUoiFTi@^I#f|&-n}wB20FUSt*K5si$vc26@ -zKqehpKbKN5jD!W@%4X(Kw1~<+9{9pvwf+!C^fkFh89koFnQY_%=28Fio|`RKy$4eN -zs)78$v{`LY1RYRGrWtP{VKUtf$zo3Y{=VQ^W9tBICXF_M90i2G1U#RTvR?i5M1X6Vx$lsDx`)V5`h8tXg6)td!6KUm0UxBa*1; -z19|JQ!tb77T83IjUJ5tr%J(9g{H%pC+%6UnI>gjzh*Dmq%r79g{D+`)AR^3fAd^LF -z-i2BMPx0FaCFoeGI^b0({pFAvJ$@?zTOuYG^98X5k5Jh9p3+ttf(u=`L_-$D5MA-* -zB6=FYU6d4{qjd65qxhk))>#UWfA;kY?~H!yGg19w#T(Q6>Rd?pP=H87UzR*Mu4T7) -z0U)@wS|G8(;-9{3{X=jQ{Y!9DUx5>Yt0q>-0|;)FUBgD!{}9~I$-Bwo)@=1IcCFeRiv;pBdfWp* -zqm{yCW7y<=y+QD}%*%(Jn(yv;(wtHgoyKe~NuR1xu_*CLWL{DUM#Z8q(s1jr4n8)j -z@ppOVt0$u(0{e2D)Yth$Lf(=<@e|)HJq3TYe~27tCRp+-q-Kec(Vr}UPbVLVkgkKl -zm&LNci5-j6|FR_JwQyqCU^Z56>|^qm^1a`zG)dK4sGkF~T`Pn9k!+plr;EC%j2ZpQ -zv5fr(q7yNuY^@!^7ip$6uX`+bD}{AuvRs+>*01b#YBpXvi;9ul&~O?;#Dn?$sCp-` -z%ra|Hj;vF2qIQseO1MOkbW#<>Bu?;``YLF#i~fNM8C{^khdk)CL$8=x@v1W>3J`~@ -z?f;A5wrK;1rHvViOAUzkJN9Koa8lVHu=S(Q2 -zxa;nbB}xs^2ph^_ZGBUP@fzQQiMZ{t`^T5SY%LUiq|?XvcxSL>iPrv1iZwUN*bO>n -zB5`zh(XhVa&r9m`UTAwhKrK2sF({a%da616aB1^iy~_V3*Q#>zD*?=AR%q4lFxi+$ -zy)4?8^7C-sKs#Ik$ZLiRZDp-l_9p>H1a$gm_mG7{)h4!b1?oyj6!LVN4c0pMX)qpn -z)T&*%mrD3Q1~*vBxwXAIa-$trFI`8xK_m -zH;@EPqGPbS8lkxRi~}yo7%3${sPES8L@w^yI*u)Nfj}e_XjYb3J~=g4Rd2b0U7A>b -zk9CBR+JC-{*3pPR33D?cs6mikFP92>b62dU%uVk{GjyUNCN%+=|EInjs@GJgvw5T4v`9h7x-(Vy=-JQx+AM1aiXBrj|U>B -zL}A37Lz!yAvMa}pkyl6DVU4VV`V=X)vTnH-N#+(gRqWYnPpO|*8biK*@vI$M$3p54 -zT@#i+IoeT$ch-m0_;HUHNSE61jLlwPwWiaZ(g{iG+5$hGDE2x4U$`ogRuli -z1+-n&?7`4O1BkgTxL&;n+(x8p=pEk=jOpS5G>B_cBqBhm6}IQm -z#E^7ucX7cFonwJM`d#8fg;9LdUWxMcJoG-B`G^R^m{&aFc(G-$l0E|I=5%x`KjJ=z -z`vkD)h7@$CYhNldkm(%@EpY~ory;)C&L;EYsrZq>Q^|W`tsjt}Fu+TEv(P2-7z-}= -zjX#)L2D?(e0ftcM!4)~QB|Wu`6Kvm?<4|b+lS!G*ocAd1=YXeQ3D5~J3(baoy9;wP -z4z$Nzi_y&(lrQ!@)7Z!n5V6#60h|teb6k)# -zlC()T+>m|kb&e=ls545!9<29KLN7!%(=(MOnpYGTD;;i3btsSYnZTk!m&?TmUDlw) -zK9RuVf5{L()U{VY?&O{?Nd!8lw#fRlEt$ni&>CU{uZG(NGiA&@4(aI#=WsEY(rC_%6zb)h;}!ofyH75m7Kv6S>KECZ%u^0 -zu!KBLxS7%}1;@v&iPMA{Yso4<;)^Fx(G!Y0(RDsVJn!X0&?@41Wms~Bi -zZ=G*9ulauv?$w!Qt!Ra?sjMG!EgPmEI=e)9feVw0xDs&r2$@XLZFxYD98`oIT|G5K -zR%qR7?5U$5nO5$xn&$5NRFv527bEFNlRMGJ^8LD`S_Z$ViRD%Z|03Mt{~+81FjkI# -z5$?korm?L}q3vguqrV7uK8x=Qg?E@|lxHe4G_&J+4Iza8e?vpmfl;;*Y5P1>@3dEK|hzzyDF>Ok1 -zo#@{A_C`DNHQJs3iV>RMujWgu4&nN#I;a*ey55g_AT*E_z -z^=c0SdZhXX;m$!H5yDw(wG`tiyR$un(J4`}Sztt07Ses^8@8Rqvh^6wE~={JvFT#7cKj6DW<{QgQe -zo~m##(K)aZ-t#t)pkkx5EEMytu|@zQcmcGrW8UCC@fJp#0JhT5%>S`0CmRZsPmJn^ -z@q|ha6cv@9L|xP#@M*l~yk%l@s$9J#WWSgNFro!q*qCnPh}zIl1*la<9A0gZU0`Bm -z%*06InH**m?6%r>(zFocABbNfXxpk8`c3`7{5$34#!`lN0zgVMokm+a+L&y3Lc(^L -z?}BSz_k@k>EtLY59cFG|NJp&l6IVVo5cmBRyA1$35EFafQ6j_)d`pQ8(P``BSFb4Q_~lwFZ!WdS -zrNA?>bKwRFRH3Ty_t;bX*yM461siY_{a*wTR^~)Keeq?YkwFjb`!#nhqAa}^LBG}tM5T-JFO=O_Vsnyx -z292pRqq`Qdl_~mVtf5TUeOn#&VN4`09j+50I*HV*D`9Go#nMy1jbNfE#sq*RWe!IR -z!Ei(5Ol6^sZ`Q+~{C)$egThI3`>_eygu1F(X&o_23DK$N9L{H)rHHQ>=cCP2pSc+i -z{2vwWBq)Hw-OXzRB|90vDzmu0A2boI1_tHmbmSr6=Pfd)-Y&Fec;$A2t4U&Y -zDZH)4tXsBbnOuiS6zYN$D!-hA+MS`9Cu)P=KW~i>E#|B?He^o8tnCI`lu*kwp*S8a -zD^jdV^J>C=AxNqutJ$cp$UYvLSqoD38FU*$q3;$4z6G}ztdu?Nxj;#R)ucfF225S? -zL&>XWaOKwew$cLShn^NLy!!$u#g*aj+oz}NHPEku?8?IiN@{CrXrtVe`7`0kuUM>Jq(S~PmvpS=UXD-`8;)5)?$^X&@VE};1r56KpA1T -zA#8cMT3rzT3j7TbLJk^>`Z!-#z*CL^qUL7HP)O<1>3W^ya%bOC6&-#_1j*y`Vi`&Q -zgPOx0^6J;R89Ju>^wLtS4#`=$tC(fi>>?97`JCW;Xt=67(Zv;OV6NrL^+|25?*+$3 -z+t-)c>AQuYIkzGL;00oJ-88G-^8aNnT*=Kd -z=Btz-six>f8Q`M({7V_QINf5pwZc+$=Y~#*c$O>Kc#<=5a&a~&K4i&|;uo73M)vgv -zWqt-uaiVBW)nVj4jX~ixN&!ySOgfx+Gzz#SP!s=@rn8AysPK~)!NGGt*~4tr1Qp); -zWdjQfgR^zFC>#coaW&yN#3RXt1{NqUG&5N+6XkAPeocggjGjMV*(63AMf1_jr10DS -zUEzlRSK&TCwv}0tY5RR6C!Q!rT2u-jn!^PF(!zvk3>htb3AJTIpieLzL5$_@)IKQ2 -z8GG+)z`L9o5lb$vfi=pHaMbQuR&LA}q0Bnr6`~LPTzcxIm`sk_X+5C!2xs14ya3$ZwnC#;fbd -z6F)j1H=zdX96#PjG+}=>;6{YJ{FFQeDs4?-6iqJYUP$u^Kf~P+)q2&GzKPe^JZy16 -zn=w9(4JFyEP=oX#;mlUkgdF!}KFx&D)!?GSq%mKvVF#BUR<~3|?ayK8UyG;H@V}cw -zl@w6MAA?z3#-@sGfj3?RE}M@pXoy85s-Hx#9h?#qB}({?jYK8`@9fZ@mOSv?oe!mb -zckK}I_++P4Qy4>{2K(pC(;nNpyu&*7cOx+w>nR?N?+DuDavRr1PklNOFMKu%jFuKn -z^36f?=plkfFuJcU^2MX6_~4eCpoL>kC`EiH{dOerwaqdR2?l72+za5L=&3 -zKVh0C%y7tV%j>lvE>pptYPAngJxMIE*~t}Oc*~C0yMa=Bu=@yiVBdQQBTQf$$wD!D -z4^$PA`}q6@KG@$R*2ysUwT98_(T3K-4!&3M-gG#6;KAJah$t9p3E?Vn!-cuRyv*pi!}a#%uL4bixi -zDvVLd-3YFa{-UMcAg?S>kqD_ViNGxl5-gdd%8lX?Jip7(hc{Iss=Xm1v;Yh7<^Buj*vy*npvH&NfRPfWq{B+v*6+O;e>aFj+tQQ58 -zH+NP8J@mM6$C%5LQeg9_(sruv15~c8rQ*|%;r9pHb;n)+G@6nlBW`^XT}8V8TIz%0 -zn?_zZjwpwBvy4mLFgcV(P7W#&ouFb_tuN%HT%C5og{+{>al=bQvt>uxsyo@;K09&5+wQ -zG+aPuNL&qJfIvN1)OJ60^WfLn|?`Ufy9a9xakl}Q0E -z$K98b9APja&T5xJ6P=$B@Myqda(uAwA<6WO1tbE|3uiqVzAdJH(XK3HrN6YJct9bZ -z<_^wA4ji`jxiD?b$6QTlvAGBLV!-Zvv48}FmIJiIFYobHeyRCMr(yI=G{&P7h -zzyQ>p;9J@pdD3BcyRJ>SyJfoX#(Da@5_G_?jd!RgGoE0PJqIlN&gYW -z`B&lAO))h8ABFqyzZ7nUKMFV7e-!S*Grh&Pf&j4pufkoh-O=#h3ikm-I~sdxGC<)L -zNEUsD`J-?b0~BuRKMHryh8jTOE;zUemku}$lu(I>yZOC=)|u}A`SF}@YgQJ5Ol@2I -zTrOmLTqYY2+7~MktT`)2kDjG$0+@tcG#{8VEyg|Ftna}#xu~5vouLl-ELqdaO~P+mvvMbO6!EhS@50iOPv+Y)%i*>TVgL -zw*~O~F0jbbcZqkHuV1NnrJUlhHvJxfQPa=3v3ZvFpe;DZdn2s<9$8bK39_oE2qY}* -zioQvw4Z(b=cAsersZw}Nq*wD+C1=xW@bG|@JzDp37pi@qbxefV@fz`CaENAxpNzbe -z_~ARUr-es`ZvW*#Q4Yg>XjGO3w)9e=L2Ag|)^T&8kAay`Lqq~pYsVbLsiYjU9W7aH -zAr6BU9B4Y`N=XuF@}&xH%xSASZEzY70!Bv%ow4Q@Pg(I5QFW0r1W|=1)3Tgkn+Q{{OF4)8 -z1Y-gy^zV0`OO}FGKhsq1O;D-w5bMfg|YmdikJ{_?NFUHV7iR>esp -z|EqA*02J<=PJqJg_^-l^`j5i>%X0d5E~zyRN|p0ph1=#|g*)(nE8HY)ALg*KX1_=g}aF4ufm=6N8vWv**v7_%QA<)(N_D)QA)X7mQveMtoW!u -zw%%tm>TwUal)T6TaSAEieBgibtjcXDTWQZ(X58#r^UP5<#_2qsgfUMX$Q4>h^vWq; -zGRucs#V|%eKe^a@Fnvf;p;S%5xApKt*+{n)wD*pfJ8bS^cGB~*?a(e;mM`76WZ*)` -zs9{vbplz8G%zUb)48xPp`vfkm5p&(QA_=9rykU7k5)WQOc{bS&(B%e -zbiJmV2EN~8>v;!5qt9e;(lyH*?!n1jTn(V-onq^qEbSIm(o+z#a1>i?7@)p;p>t6~Bq)Y(Hk_ -zmX3iNI3WZ%$Of+tB|TX9yZb2Z7%TQAc%%=%-^h}sg;^lmnEE)EtTtaOax^Rn>#HW} -z$=D2KnH`yfZ57hD))0$UJ-T@vyKqJM7}I+!&Rin^!fnDwRzSnlQRt3Bqv1u`{AGdr -zlSuPxubVwrUWx5eGT%hcZph&StA1FUE;QI%fi{ppO*cLBz6uC00O7{Kz+V|GZ|urZ -zz}mY+YjD~9PShn5zCuq~k-j0dnHse1Twxw!-iSA2F78}|d^79}?jD{Hxy5739l<7b -zHYn?562dCQA~uuuFp4tThk{urg&B4#>=^H`^f|R!y!{Wton(GITaMvm?i$wQp^dv% -z4nVkRzn9c-S*andcj!{85p!cg@R#iF%c74^&RW#bNZ$v$mwVq2v-e!d{LU()51+~YpXk^i=pdO1p2)9X4PgyEINbok>RpT -zRRWifxs$}SX%nGW@#gf^U2$G)qRIc(0;<-!T;tj_PtDkYU$+mM@nnfZ7lqPEQh3sl -z4Hs^aja^>|r4z1^da)`m5D}0BJ(M?+r-G@tmKIWay3&@++97&dX}OCi8MqdVoI;*? -zs^n@EBnob=q{H7jGno=3cg2w`Pw5DwEeIvA8EPPi%!&l{HJw$hME3wWTNBe!yEag9 -z$b_S^;*F)EOMc%xNE0F-*-V4&uD+ajtwMuX<{Yd{2WSwkDv3YY7*D90*iP7Cg#HOm -z!F8;p0Y-+C<^yQ>lX_3psa`9*t&EpEgJG;iJqSdiGmUY>VgYdjr2%*u@=KXm;1gag -zICi+%Z|anZmn*Lpe>TD{dh$==Q1ouFB2vZrwG_5dgx{`Z1F9o(yZvrT;H^}nEjAid -zk0=nBV>1UPOHI{;UxlL3sF9&F{wmzw|D$k!%i1q^{i|>biKq^bik1mY)0=Pu6z&f2 -zo82GR6jI6&`@{7(!V#j-Vnm=Foc)E5uo%X9Nmx1Gga^1_4#Ks-+43beKw -z0pU1f+GI5;)hSaSH;TGZ%etISdFTO3qpxpEsrYrYe(3>P -zT@6-E9S`;){CH@I9Hv!2p)5;avN%e@HB3%L%l}0mei~rn~5_ -z+P*;TK{eN|1*KOK%w2^P=HA)y%IAfE3M4R)RbjwH^W10BoS@Lr%=h)jm2cJ^!4&#E -zSiExE;1P5=^$!7(j$A?6!qndIci@NKm+aXq$`J%TGsUljNJC8O$TvqcVNrCG77 -z4f@UJ1M7HPy&uKg_5EiPLPl8==`i{$;&VddI(*=dg4Zp4lN^?s2nT9XRE!&DTJq&p6dCZn -znIxlEP5?84q1Xv7vbst0>-D$)S=U{|#N}c8|FCsW(V;NQ+NfjOwr$&XGGjY4wr!g; -zoUv`&wr$%d-&z}MpYdPzRp0ff(N*tLeC(1K@$g(BhitGG^VJcjGidv$t?y9%rPef_ -zU=l3L#s_kgos3>949LHxg~_f93Nb{|rS$|5PE;##4@09AS)*82l#Q!JW95$~Cp^}6 -zdWH(1XMP(wnu4!ARGQe{VGq1IDuMjX(+Y7@B4lAG=TMN4?>^%IN%@{ctbmB2--1w4 -zPXZpgSX2-InYtvPvRl!jNF%$KO&Aow3u;Fy6=XdZyv5fOK@bh5-=30q!agzT$p1sr -zeTM^ryNqN483mE6RvXg5WuuU>zdu~v{o!z7WO}IJbt@(S9wHP^Dr)#xUyb^X4HcnL -zu|NloE+4#qUYHLVx8vg%JtY-V5JZl2Qe%jrCQ-_nWn*Hsu*PD7BLPRwz41rh9f0H4 -zI+%H&CLYPW1+YMeIKnH>e -zeiS%bbd}y-{XmK~W!s3yH0;s4a3))p`X3uGp`{48i&czDrt?Pdi1G26OYzfTh3u!O -zuqH0-!o>#Cv2cGTJT=eMmriVoI#WnRdzcPp(%D`Yrxf2ZxDeKsFaT?pi9(&OSF+n* -zA*)8o+C&d+4}v3RunGtlro6ze^-=iEIpwuR)3lfq1tB<6t~>s2Ql1H~I)Sj&DrioK -zw8p&X_V6SL9&mNbS)!)&7zWra6{OfpUWDlZ7#*!83dr^{+xu5pmJrk7fcF|}o`DAD -z4}=vb24TOO)B$GYa?VAa`YUx6-2YTdt00@Go;;vUtum`QNa;29>_~PJwlC|12S?5 -zP9nr>A2r@XSHv;{;#mC1P_g-&qfqIL2kI%_vu7??M~XavPEZ=4B3VqIx5DWLN$^M} -zsN2T|YCR750gDuJ|vcmL-FGeLv#!lP=Rs57v;K57vkd -z%sQWUQ&Ed7Y!4>y+f)mDj|t479={O>KSK4*hS3`R#M}sj>$eC+&;*j4LU&xwtZnb -z7Jk>slGD_@tCYiqt1OGnQ%bTm@`b?Oo(D{8qcr3cnPEIv4F&FcRP_@GaX|J(5xCO5 -zkQm%y+dPKoW(+ijTH|tu2%^2u+JbZXJSSxm$8T12(9qrk;?sg*3P1#Muj4%mYG?F! -zXxlIWZQPMuWXqIKLweSu<3X?nMT+C=`)PbuLg4+fZao<>ojU -zj~6X0DY1(EQ@NU!T*O`mKYZsAl35wWOrPu~n?!ct1tE6D!eFlGOhxFvjJS(A4tW;Y -zyrP@-#hm;IkClu#uJZ`7Q>?+cRuUL$gtEP0#Q;6ZtaKw5MlsFnQ(1szL2S(cz7z!W -zC*nDs2`whoIzVF87|hn;GYTmUu}Jen{5pWd{ZVfU5X+1Z3mpB?&cuHIa%b~hg~lnQ -z*u5U6y;%OBNVvpIQ-wkv>-wW?zdu;4rA~txxX6F+JnOmY;zW1L&><-X<>V*i)ukSJ -zp?Z44X6E&plQKgew3AXGB(VA~o`s0q<}f{dYgf4QXYVn`Pbi_o(WJ}^(^ -zo9&H2nG*>yaj8xmSq=`F*HK%_#W;^iz@bRqYLdB1!y{QA;7^m|U(dG0Jz$~G_?Kv|~>D{1X|VkZ>xl3wlw6b_kA -zs$mRVK7en`i}18SeaxEviI(A$xc?tAKgQpMCCefx%JV(U4(d -zz>k6yfTfre#UVF`1hb#!cG69tfJk`7ZXeKH8>sAJY%a?PY+m6gjtD;@k~r6UV6wXQD`#IRR6XRKLO(WHr$3b~+! -z>>8Y>^`cR)+SD8G>lqOpYL@82I_8g -zt2C&n1&oE<*%4&Q=8RSe(t>&~s)xy#hM{{mmJ<~{G(IogqJ{dK(FQz9{gqB@$Ck>t -z%vL|w;FAdZIg7u3IiMZmHW_jJYZ_#`319G>9X~nCdGUU5ifjMebAxX+Mspl -zKJDO}9*J?Ix1#|gy9*+b=0*o+!RFOSxj1l8AL2_~787>4 -zjK47Wyj`|CklZ`tW2b(s{)k;be42;gW4NPtIREbF9zQ*P?x7RMRGJXV2%+eul-^sD -z3M&=Lwi-u|Y@j(wzC+{@3~K6kU!8C-8DzWzMIP9kC_pq_1EfS?bOIfWU`o!DV3QmN -zRApl=iJXXXo;P2kzE@nzo!*CoSqL;J+U -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 -zJP!ecRpKv1|@2ifE~ofYEJtQ#sJ|=HN$P -zF4IQAoNbIAKBI1fa4wKK)zQjrx!Il)&o}nhp_RfQj)W9QPcU1%!}QqV8rMk28}8um -z;19xG-YM)BsxZIP(c}{fUJjArNGJyHqUAEv&F1jey$m13=8W}6xSaAPiko4T4;*DI -z8Y8s|mGD>Gb3PfaT;f)w0L>3^fT8MqlC8XQ;d3k;{1m`E>bh+6`hjk*oYK#8E0VWF -z)Ur;3dzhEvDuZuwV|Ul1i8Cn|P(=Y#MEpF2O3|Qw&Tn%AB}N(0 -zfrUhvT5o^^bPbJLn^J5Hl4Q}t`g=V9l|W=CgK<|oX2XNYStf_+Cde7XAh_@r4(aAn -zw3|k9S>jQ|<&fN-NKce3lEteWf9Eg76M&zK58})+-E28zi#;9f4-<)S>s8aLQvZ?vM^|{2G|M7S0b5(sadg16HGks`+v=8L$9UB!E -z5cY*dux2-N_^o0<>kL6C$|le@2F{@fIHO578wD&t>1@qf&7ZzC_s}z#3Mcn3N&75S -zAb|vnXbaFF_yyD`20cS>9ehP*!KuGwu}?R}5z$xKxj1@0buo{JJtW~DN&AH{(nUL( -zj5HYoA$p1r2kj&-i7)BDCGDgiNn7aTz%Ktt -z+Il~dc7KQ4$6tJCph8e!xFeLXs8&0Se@WVl3Mo?G2WW*Fxfwn -z_TCIHhaw4AzP8{VV||CP;o(1$wkY=fyZ-2pq#flhwEP%u=fbZ2Uy`=Ze@ogy|08Ml -z)BWf?|B|#(ekAP?H{t2ISZ0gm|0`+7%l}B)68|G<>(KtUq>cN3CGDQe|CO}uci+%Q -zP5)QYe%ky;(!S??q4`fqdrkizNjoKwXg@|Udl87eviM54Z#r4*<)x&f^*<$TP_2JU -z+SdO_+Qk1z+Faz5>F|~RA!)xL{9DpqLvj@9qmSk(1p0qT+UDeD0a9k+|08M3{9j2s%;*0nY0p5A@4jn8=_qhpg+vw13~;@W -zzgYYuX}_)^7w8Tc{2xiXx9vyLUPa45j7a%UNt==NN7Am9{XdfS!hcBG5BmQpX~+Is -z(w2PC7x|I2-Rg@IMeYBelJ=ZW_EN79DJ -zjf869u7LFL{E@VicKK-kSJGDdk+d;_|BmCzv+j&h)BxaM%fC{z%%KKa#dY*nddcZ|vsUHP_z%BWdS3$%C@}NZOj> -zfqmKkNZN7P|47=_Ye!WXSp3{1hyN>SNAtmgZiCCpNhO5+NZOEqIx;_!wxOGj-jAex -z%D1&IvFk0^mr54R&K@TI^Q;cBT5h{i*#T1@8+z!}bmceGG%_xL_Fu`AR`dC`l~Px4 -z^D2fL1jC`)j5@KD&49aC=|eMTZcaFQU>7N#ar<#m3a(a7Kh!dlbBY^%jI}uXk#u6A -zSAt5hF#hf|2!EK+@yN)bFBHi((srmgxDQFnIMVP%9X6uU*|r8ZacO~V1%TkwXPy%8 -zREw$=&RIbN<&7J)So+#(iJ^O%dmlWpC#sj$`^JF?1<9ug|VR?g?vwm({>H%6PR -z-zfNwfUZB(1tNj+F#@PBP-kVgvcq2|_dCkm4y1WTOAGa`2~(Nhf0D?!K6hjlOkha$ -zL|aR91r(LP2q^BxeZWur$0i?hcC^TuKRcP4VySUt;V*hyHQVvclMeVpKOc|FzIzV* -zEbArNaFziREzhiP(Io_mvx_uaNa>Gt7S?Y)Ek>sv8v5%C2KU&t5&e9T?!}C;q5Qbr -zDPN4dII4g^^9{rfv^~D+mf5zM^4YaDsaLiNf~!3M9-mlM(U%|v@FpxszSr?};0?*f -zrz{c<^>u)R$ra^Y0u4KIeqpR_x;lGPiNgeqn6DM5)zbH3E4MK&(JM(z;`=rv-#lNR -z+l%vz<7fA)MBw6Y&e|U1bTlSZ6I8okCnP%d2+7 -zR=ZYR&`OM`eMob$YF!J9uXJEYafSBl2P>p$Ix9D5%=xL -zTI_4uARkbA)}Ul87)<7XKge{;aE56mHzJUCR>aX3zs%k@*G{rAa^i8wtsEI;rgj9q -zjA;PjmX$X0eS9BXX}xekYIG#E`sE}gtA -zp+5FK*Ia^3o>~@fuOD8&jR%b-t?}_TK5qVUscUvU7V7!96;`%h)|0~FX>7L{EsZ=k -zVaVLoZeJkvUuo2Iw|QxzHE#R92Y*UE)5={PKkDR^lWjIv(|fYlv3wruxmyAyiq7m8OIA*zN7sR}IJlNp{D6UM;gVeZep1 -z+vtc!#A0k)#tP}ZY+R?LF5jWTCzT?2$y+Rplbrf|jgjZ0=Tw=B>wwmO4DTa$G!R#T -zgIc@A=WJ7cqOv>77~o1AjjeI|u!13@lzEB&H146}+~fGI9(w5neOVHekE&Dj0;-%L -z9msC_14cj7d}k>_SOZLD^<>?&4PH1tyt4S@`tT2RqSt7?VV*B1AqKNjr*(-&=L9_N -z9CF-V$K?USg5H#6y04D^0BnpY!NiW2en2~Q%R!AaHupE%f4{(l{_We>p%KNtf$pg3 -z&w}u&N!>&w95TUy`$D4_r~eSn2kS706)&#-Rl>l&X`T*V+xp^9O#K5{`-FYM8mD -zk*&aA=BNKa+fMb#U$i;|%a2Y_`()gfDn5~z|fzHOJW)0T5h5{xk;{j1i*YLB;%J7vyZwmQLEN}FL7y&oVi+4+c8FG -zFv7a^aXuVt)zizCH|a6b&;L6lnSk8VVeNou1VuIuf!}w`8dkODR16uWucP6>TSG2P -zzJ)^|<#J?O+lh)oS|>M8L*2WzR6Ek$OA+tNy21z1~bw*a)5iv -zd5n@0iF;t-2lbr!a4dRY -z7hN2_fwC-{0R*B*7uTgMo8)Dkx0Bg$-D*JSChs+263XiRa60=<1jf;duoeeEkTQ)% -zzZh&v$lRI^a66{As`*ZVOM&nQQSOd>nr8WOUrr&XNG9~M1+af@b56|(cPI&g(h%Da{&plq?_9!DN8h?*&Z4-iR -zKmvOzV(z$Y-!M?viYu;A$>nD9&i1{)Ek?5u`)fPlN8b< -z+Z*x;2tZ?h5{0O85*^sYXj($xS_1qLVb8F7RnACzj$BDT1t2rRW-(5*x1Lb6id_ -z*xY&na#S?!4a`9e~5ZWd1y7;L)?qyY?4IHj&L}q=!jx-M`YlvPR0y -zPF0DeZNeSdN9jf6`T)PD&t`pml)tE&X9@<-aOTQHmVi4X$@;bK9Z7|pw1kH8G?0@+VeT_v)e9-o<_=i0X(w*47q>n1(F9Gt|50?LBmjixh+uU0q#S-jX&`1fo+lm -zQ<`$;r6FG2pvKN3j_Ol;DDqmr -z)PMDFY-IJpi#EXG%N||`@mX|r9v&41*P<;05D_3BQ~Jdvxd6o%x5Ua07d*;c{;2%~ -zQ8qan6q`;_QuSn@<)R`&VF!nyUa&I2E+&ibVgloJr%Vg~vU*Z@$`fjq^Q;<^3{5b; -zi@|55g8TZ46mO`4Z69dr16zx0CxYYn<-dYe#AKH`+BXr?`|@?){e5#@XF-!3mIBPi -zUbKdLzA|%RVFjO|I2IDi{cU|l3SZ|XlBeLczSe6HhV(I -zzjccTjt5Fn~tuCbH8!EIwK`0l0;GSP?bw7*|%gIK+(@9&nR5age+F?QGZTZFC9 -zLnQ$)n1)>^g(8c*3IIHS9e}%!f?%`d(D~L-Z1DjG>R3&UoW@HOv(~XCBPGE -zis10!bcp>{7dYlj)BDY6=7!9d=hmSeK;Pns6YRMGn)=HmgizDKErpznwyQ;R&C)n+ -zSI)#{VYuart+<3Z^-AV%5kWd2U&=%*?ry|ewQOww=RVb(InZA+8(?){=d@!nlTmpC -z%1CSJK;W*qbwaFxf(DDNl|e+~>8)r{=d{yq<}0x|vMW@LJ|7HX>3-YAVe)d~my}#~>0b*uKihp#Z{lW13_;`f>tQ5KS -zY|qBPUV;GEps|VS$a9cIYLtZqB3gyP(o4zX;YIngv&K373lOg2k|za-1BvVC-aiUs)Gz<`-=K^7%zGBsh34l->!q62c$+F3@DfUsC&w -zJPrd~V`0)9h|!uU*sFdwcZ7mE;|>$CtR%9faK|J@$&Y_d771v8Ml2-?ti%=o8X)g| -z5RKn$hnBdL$iUMdPq5^G%y@f`s9OetN$?z2w3zHHfVh^^U#@Gd(XvMnt;mkKib*Qe -zKdlOLI$pVC6HULH2`F$w^B5*&qg6&M&5+(jcI&O!UKs!Sok-!NjH=Gm>h@4+ -zPW7e%*r}tw{3fIYezMSx;IcShJU;W@-JzXywh&$iirg}f+-Rpa284wQg*>Jt@0N+6 -zMjZ)$j4bW()1zA{DH%OxL4PkE{XY_VXt9+zOP%7lV*Ie}ddXR7dBiK7K1qKap`~R= -zQ|L&rRP)~h3Zi|km5TulD)AEooO*|KmK{5 -zH0Dl(y%@kPaI{QhTbX&tYHn#FlsPvLQ-wW#K21n3L$2u1ji^JJ0V6(oXdOP5pnBYI33 -zSJT`9L+kMzde1>kpR02#0v@?Ir)uH0_SNca7i7_K2*uc+E$(n8Wkgq6J?Fx?RxZI6 -zcClNVj05ev!wN05PH*3^4Ur@t>amp%%(r&`)q(u39W;XJGJE=Qb$FZ?gFIkW9E56E -zsa>;hfJ#4*uL6I7^LJsus7Ks5*9PE#=QrOdn_+xWaeY;X@MgycY&>t>DMeN#1{EYqO)NL+fcS -zuFYJUbZkU@b4J$}kE0|m -zNcOoYvd?wX&Pv`TfeZnw%jQg<>jc&ii7$M2AaK*6T9fGfRaN%$#gZ+|zFv6eKyVt`5ISba~FbyNE -zS`Pp?!n=8WF$z)=FBXMMq8LUq?^+A5Smo5U*M((ZTF>NYtaOZB>+%r=^XVs`#NhaW -zzcf(EhiPl=b?_@fuq#KUXPnD2wt6ZgHZLiUuj3wsjz^-J4Q~^sf_4pM -z;hfEUw)eLQ5EWdllu^pC83h#xA5~(irP!3xAAWWn{4u!8J@pc$G6e{p%odUODQ8s@ -z70JgjDNy*zk9&mYGUiu${Az@ZB6Ywak=~^<$AHP~0BrVPU2gr@&~|;XGG}n3_picW -zo4Wlh=mbp!+J+p*Equ>uw>U_YbT2Z4Om`| -zr!h#NGI|&BD(?UXmtk+qQ*Zbo_u9#4jAVm^p|{v$7ia5@Fim+A%$I?-Yog@`KPJf(I?OtJk40eTNK5-LaQ6(aHPEcij)O}gWdB@%!# -zoA$Ap;3i(x*&`Ko`G|ZA{bw$JxkqV-2~w2B*C%C*D(jVVNUVa{%g^-c!f5FYrANOJ!rL)>j&aY&qOKF7??P$AvA9&ASW^IN|Jyp_MYHb(dLt%a -zhd#`@Ru#wURLPHweyxn!=XfJxJy}(eReR5z4M{h9wHP0_sz9p+jxReC1soxURtz+` -zbAg%`Ht_}Y3eZA77HECC)SvaEDzAq}m@A5HKA!-gO|BV5tyx#mtRT%RA-1=oT0o?+ -z;O2JAIN2rmkg_?pXW_k4gg{N;Qk90q+n15X=(M3z-O|m%FBg>F2MQj=wMoWC0Gaur -zwx3`@%sMWuS_g$-#WB9=7kTH5ohX&2p&??gVoXivAfXIqH#I=KP|U`GaC50g4{35G -zC8faHO#SL&&HY;_>HxSa -zx!|*^oJF63mMi$T~`^g96B~XLeT4S_ivB@e-oXy01-fP#3=L>bR4g1D2x*RpJe2E -z0#$lxzq-0$V)LckYwHGN=X>(jzVF9xscvPM_itLo&u?CZJGn0}uv8YvC)&4er-M6s -zkpB2`;&PbRc9P#d0DeL-yr#h6Pd=wo#N)>`J;Yh7ALAHPIorN~FQ2_}!i5c?EUWM+ -zWM#Ss&QtBZakf8|y#s?Q*Yo?Md7M=S)f?M)PGvDSi7gyM+sr25+K4TMDA?mUuF1Yl97zK!oE9R#J -zA+8=)|Ewh?21V_NQ%tX};v>g08x>ejo;)buZy9*z?AO^UAYp8jS?2(L*eQ(e4s`fa -zIq{f)L8hhx%OHJHARvX_}GsYtbQz!@_0}-(O*MqC} -zioZWgJD&&=Du6p|19u|+s*j*f#IT1AhvrP$4jlihk6a83J0=3RdCZNKt3J5(%%sWL -zT)%9KZQARw-kA|wf;dscCTU}%vcgaumx~!FFwSj0*ys7RMV(+~UNB9dVjiKVW^E?f -z`ygC&1{FYj9CA68uIC(%3@_K5lzY?2eAGKm0|WYE9(cj`oahj;sL1n|)o+Gcxtv+2 -z@18Wf%o<6hfKa@ph{_WA0}`jBJ52)0R?%?1q}Vk(aC9JmMkWZvXx-8+D#kC_KS)!f -zs31)y>r9}Yya~?0`n^sYSoO`(vwM};+SwdumBJ_7&Yj#EUcj_YQhgHdZcb- -z6prhO89OxuAt4~jbZKWp`UhHNh5=zsLoDGXYEO -zKf4IJ&Li)ygwG}WPtwJt#n+}8ycZgkS|}xBGeyz<)nc=1eQQ$E$sn3MDR3mHB1O2n -z4n`mXFsa;O6-uV|P-RcD1-sG6>>J_PunD9@506(jO5YXY=aQk8Lx6A_AOFqfa3>g4 -z5U8@8t$#-g&if0(&eT1>&gimk^rt?!C_`ku5+kx~BW`=gl%m>TShP*LKO6qp!UMz> -z5tW$66nC46WlH)TedN9bFA9pMEs2ubhvQGpgR#2a*XR&z`GT6CN5^9YD-#RtQ37|5 -z^MU1*UEBzD0u)>UIC}XTFTM^F -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 -z2h7ACD1aYEA&><2n8yowY6B%N^2G) -z#IZBmIKkwKLK@nR!OH@&8eF56po8-MXk_ -z+qP{@Y}>Z&iEZ1qt%+?X6Wf^Bx|vUV?{oL5TlYtFRrl(5J+C{UdM-m;ifu*Fk(Y{_ -z=nGO|_Fjf+d(~@*OGaN1zE^ZS@p4U&VH!8yD=dxYPxoFq~ -z2xauacwn=ZK*s5=NrVD@gXMip~!erQg$g3>toLCSKzpl<$7_M{L~%`DTJ{` -zJ7zLO3d#dw#XStDcI3gHqH)v-ayU7l3Txr$wL)3#Us5EDc5UX6I=W?uqukD@50hQ& -zNaXMtlH)p7cYbbUww9LScQM)Ld%r!Z?-(NLAI@R$JI{ySd<<8=6TsTDe_$@K9P|3U -zrgZXF`u)HtDDi1$l_cnnDHR+@@VK3Q`{B@o-HF%fmlpTu%|O#ruJu6Z6F-_zCu -zXf98boefsvRIfnOFq_FFk=0ot%|BOoQ-B!?iq>EU?kKMovb;9R>fyb?|>~ImcogJ7DTU-WuhEf(^*Bs0jH6zGAQ&}`9+29 -z$+|)2I9hr{_N_61_6&jm@oG`PhBvOpht0v=k&pLm)-_rp3Itil3A#a-@zoXhNE>v1 -z#GF%K(eZWqoRDgaF+V!lsO}>ZF&{fNUAm@!p>aT*Y_l+v3?T}Y4UkC_(^2&LgN}#N -z*49#op^4b3OdZzumS}DfFKgs*j7x-|{&GMAadIncS7KNeM_cic6km7%Z{f0ujE$vI -zh3Fb=3k?9$Mk^g8C5vW;v1fOSW9ycF+F<~}lNTS^CRkqe(2=(CrGReVj612$w{E?B -zV&GvkC$dv)MIDF+unftP{&9eS>q4<*0BfB;!j|h-j23?M!}B)pi6aI8_|K5AFbg)_ -z#NI$^3%)5c48>Od^&aN|06_Gi7)XC}w3GVyn(-DL-`BXEno&&bn^b@t23;r9g#>=w -zvZ@KxR5v%`Oi_1(G0w1(w*-`-Cuqh9f72o`ZwV2=@tgxNG8u4@RFjP{*vaw^<<{j48 -zVVRcX(#t))9_qH$#g}~wm`e~8} -zj1Y0NuB3(-C^2$}z$4asuE3{bLCZvAEkk*Nsbw(CLVI=3taP#%Vs8u}y+|S4xc9K7 -zp^_|HA5HkB2tHB~E+Yl-lOdOf8~9K$dj@b%MfZ~c4`K=0bRh~z30Rxg;(9~hsskj! -z$7*|MBn`>pqhdK!v00s`jG~E-#FGUvC}ZU-ZS6)qy_0!LmEe1dmY?>1^15a-5|CY6 -zkgoc2`y4S|<^cR+jm~G%gT;p3CI^2-X#6uJX!3cHgkd%hqOm6sKU70;s!uvF;suXk -zFckdI+)OgcM?k5?z9)CD0)5-Q0rSg+*z(Hvrq6X-Mq5DU}-N`r2JrZeySI!LYQRj -zQ5I#%`~o@E0XP<P*)h2K2Dh6^WLF^1;VPOqzSGo=>tC^b#x{#c3v~yOl{S#zqfB*}96sVEFp{RmObKA0Q_w6w90#;3_rgq_0!kHm5=_mT -zEH0W-!OI>)EW(H9s7(NDuqAWe-g31XlsE$KNPxcD7Cl_mOq`VJcG->?w0*SkB2tAm -zYr>8Kdp8%K04QrksTW42&u^HHyAhHZ8Oo1y$V4EXf_1hVKuH~Zc!eSp&>nbNX7^vAyzMr&2Y?bH|Q<#n~i#b&DMJtd=Nm^FIH -zKYGo>SHoK0*< -zZW$X@Y0kNFytSRg_#0_GgO;^uy{Zg8YdSJ>6!t2}>tJfv5=C)Kd0U~4uss_pjkAlg -zgvsD*(r_JPS0nL+*1?GBs}}yDfp6tx$@>$Qo&7$^^Dj*%6ha- -zsBLEWe}HGm+o*g2>O6i>Zn+GAB2yF`>9QG8YA7=UH`1REJlB%FvDC$tbB9~MTBcs` -zM@k{ga`TY$tNZ22>lL7Xs-Ql~H&B5c1MNfA6r)WhsIQnK~Vhze=K_Tnh|C>+W^ -zi+~$mL`o|YeYN3=B0ulHJ>f_4ia13WVx+v -zVo`jCXSk!i!cuFQiiqf9l`eSKep*ieU|*4l%N{mkxPZa@DI8gf&a{?>ZoHB%t9s;y -zlS3GjG_|bWaOO3ZYRYLmvk}bl_{K}3_;h5XyCpXkQ{id!7R?|wFkrkx$j^q9)&!)@ -zPV^fPKVg+|y}&$5Yfg+cB~UKVMxX+TUy@wXU+wiW)mHUsH9xB{LHodNxz`v9r6|Ub -zo!VCv&*z!GT7nDna&(3Sn@D>q?$#}M7EO(TAgW7-F}L|0ZJxu~wcau9G@lbFmN;kz -zrqR+tGPl4Y48}5>?)vEr7?C5T$QFwNkn=1Al$o2yITv!xAfQNZu#~ZcHkqBZ2$j -z$3oTTMQTuS6ptprjICOY%;=X9UhOsypr2e+ES}EO5>`g^YpCAN%K?RbrE!}UHO<=C -zH5CgW4stG%b6C93!Ouvop -zfMIN($q+k4eDm$|jJH$+8e@QU6~BhlhI-c$qg@3V#y#s8KygFgZJ1HjEP|B=kz94& -zCC=t^MwA(J&of_2RI2fYz-}^vX_7$%-dm^Yl!QyCA@O*;0qgn{@Ly+vUi*MUDh^{_ -zQ9U~3ofA$77+V1^fx(!T9GIM|29RfM6MRvB16-QX-0*N{W%9(#Zi)X+VhBh5E*Qyi -zfYr#oC)cWYEt52_H-5NBOB-(nybI8M%ReTA?S6>@)Y-!_!b(G5k4^cC8ffGYr`qut -z&d;E^4U0`TMw9)Wdyo)zw{g@~>aSzSTN4rk*3dmeaw4rn??_2iT0%&x3I&jbyIB}V -zkankm8F$*D#Tc5+34_woLZypy>LM?-DWE7p3Il-TVkgl){lL24B3 -zI%ZJWwI7n(t+FR>dn-RJj3usuECgDah~(j9A#1;o(vA?Z)Ydw};BoX7e$|i7(zK8? -z0=$(8oHWZaa#0Qm*^kFw>QPH#6{%CMe8?D-|2Hzdx_i%safXBd3kRpT0AAt#Qxs!7 -z>i2BEyM0W>k8uWRr@5lTT2`(~fmY8&D*xhZdL7L1M@r5&SY%*^_RO4hR`Z0oWAu^q -z&=vFCD)CA70EdA}_Q!@Cz+%IfAik-orgXJ} -zR5UF_&MCYo8ux4))5WX%0L7NZP(P -zUQ<JlkFvWYG{#t=0#qnUXlinOco~i_gY<$vYd(uu$F`QNb<9ng -z9tP|NIZXC+cg%ZP0H~Pb$*|?Ts}+RT`A|UjLrUA> -zK@eN4!<|2wE#uUL&|Vc#`HxqMe8)NVhIQt~JNN*=$4KyO;PG=+^D*E*&_Bf^_?#jk -z=8~m)=_^3N4%XI@=y*wo8%1DD4E!B=vbdJd%Yz-ZWC_n<=)j41lsz}Y3hLUkgZv~= -zbW7(=-PtB?yiBc+v0(I?)a27B+E=O@Qwntx7kMYw#K?Xm9;i4cXjIb7!O}PY<~#de -z)3Kn_t9@)onV)Sso=7CR$Wofc6j=6oxrWMCnzhBtXz9}E6PsDa69Ov75s!un$}Dj -z)=eZofH+|K?k}=>-6Lp(M!4qNW;c4iO{<8>>j>&`B~{@+DvNU_4EvG9x)gmk;-Vuq -zRflwK`a|B&>e553vf#F09gvzgFE$r!pr68kCc(32ee5J`Ilb@4S$#5xyF}9EeIc)S -zG5@4B43{5Zezb*qMo_dCr;#iQdZy_Y09Tq0wt+^&4W0}6u#9pYP4gk~yR_rj=7FtJ -zx(icjUUSgShD#VU3O8`{Z1Sm+$sQ}-Mz{-O=>r$Ch`VWH#VkGW#fIa|_i)piin_(QP!MqzJPpZM1U*wE -zJaR}0=saN1N`%6`De|Qunhm0!mN3)Adp1y0-+d-uOFqH8CD*V#>vehrXY{#mT@jC9 -zUSm#*p9g3t(?){$vd%X&LfV7{6fYHB#Xi!}dcsx2gdWksUztZ%Rek++PGoR21u4Gr -z=P1cEM0i>I4gU6!R`u^;O1fow3|aP-G)`fEFX;`eqHV!`qY`KxZGD99_ncRydH>** -z02-jLHMNjDHBK2Bh7B8CY0{s|t9}84T7W^iHRhv+d|_IAbdnrH9w!*MT6erRBA#cM -zhSaNU;{#gtV~FaCngQpky7!Mw{@&rJ1IIT7K_V^n3#|baCMXSL1ke)4B+_Xpmt+b0 -zq-%f-_E%0<9!ipDTwVrj8WID#x#qaEjVL`@T-S(b-nh0%hfUU9`U?&L!y7_>7drArvpqv1kdG~?rq7Iq9nLAWC_hkykk-0 -zD9phVrYFSE&<0`R)t65N&BmDM8*y`92n%G(MvRR5VYjE$3y?z2elbNN$DTgyjnRdB -zx!$O4=m#g -z6i;1+8ZpA9pQHj_tT@0nL{VwwrGD5jVJ3ik#^*OdyF?9p9>n9JD^Rd2j+RcYK4^=) -ziA#fg?un8%Y@z)dY54fdfcCh%bLa|-3R>FNlDC|R)1(h3YdAe -zipDOs8pes|?jtkae8+0+OF;P9y!_F%GKveO2>aMi{e|W`-m(vj`pvU0TVlfe0Pi8e -z-IZew<=yu1M>lE{A$?;N#T$uJr(S?%s(pI?njL=!$D6Uht;BE -zf(nW)$sHKx?3colzPJ!3fVyY#c*$JBulvf}hP?DK1ll#hSt3Ou4Rdhtunva&z!LKw -ze+i@2Qu{?$6&-YUuJ?+9T~&iaGF*;Rd+lOFl51XtW6-8P8bB>j`#enT)lWfMM-Sfd -zWzE8|u}}-gESG4eY*0c8!8SypK+wl7MIw%HyiKUn%d;7xTv}8BaSaX1ssW?>(Q3p- -z@(z9|oj^>gM*wDct0TS)77O`|Z5|4@ehw8_b9_XcB#iPhX{2tu5XbgWaSeCLrW^mO -zmLY3x7|PsF(n-egPtrX0YUmWJ!vnYRZHi`uK+@nnD7=5m(wc(*=%~todZ4(-qvrjy -z@z!KjDJ)zXHx|$o8=IMHp3I)+BUz6?7GJ1nFMfx~4*8NG@K}UV$o+j~k&r%lFHT>? -z&T~N=f3V1@{-iD}sPoPSTmevMSMZtz)AoTDOp$OKbtzU*Bi`cIjR=UD^7HLwlyQ&0 -z@G$lD*e&&pz^oUoLP~EFfF-Jxc;!A=F({rXyi% -zhnaRrz9!c^s$-;rwNkm^Udz4UeYVTY1RN934sY#P3XdBJliZf0`IF#yVWmyv>D#O; -zI8r78=>9^>-|7p$Z22*P=M<#LV*p~y?xZG?(G+?aWmsQkBor%R=o8N$+1ilnEPDq0 -z$}aY_NKyR$2t2T9(^gRP%lmd+VRne~;Edl2zXrJ!RDTebEKw8Ixg3dG2v3GVeh_KCS&*nUp$KrBt>%GP8#UW2PwYE8?v6m#1x)amYOriYz -zbTE&>m|TryS$v)Jh1cXtmU0I-UhkiDpSxR(R_?86>REzgxd~ZxAw4^-9vRJ=F)qOY -zwv1l$#dG>$9+PwI!}f|P5Ntnw9Jui73P1dCJi=2ML}fhy)=;(?ug<@2vEz>NZQ-XC&5X*jTDXl4ns0QN5D -zL-h4{4>a$ben(~aU;@}_$X-sTZ)E2f0{IH^U=T^?&as7jqe9L=j;Wx{%v%0&F{3E6 -z$}&ZXRJJE84oK)k3+|D9K*$Cy5oHt{TlhZ!0FWfvMVOxSoD}ToqiLFFn?fU<0#$NR-?VLIoO -z_*A63gxAo%;{6tj_-ebNnFK*3hPX1)lSC3G)NBB|xcr&`?_kDerHa}Bw%r3dYY7er -zT==@A7!%%cu>$(8#Vc1*15)9VRNXf)Ud)} -zWac+yp&2mirJko&-i^6??DFt+{G4*gPm!Rz7?^(1L#dprO2{CWeH7))9KAIx4WlU0 -zk8nzu4(F_uMV6i8fJIrVZ*F1kr$7423@NJ$XJl#&wQ3;+ih!_%U>78Da?>H6zr|nY -z9HK0(YT>kQ!euW2h7nH18u$qhyIN=cgJB>=I0*Ijz$y-UR!OH&$yj0fI<$l%)yWd^xm)Rm&c!ds6`Cx=$Rf4B`R>A}h-Qst{C_AAYnvZX`xFbdx;0;ji(= -zmkHe+KM_b@K3jtxQHgl#8NXV^LixwbtO#s+-pzi)F^sCu^xDX+iIzgA@X%curiOfA -zl)b`XP2<{#RPeO?W@y}VX>p#-f+PeU=7({2p9gRu&FXqY*{QITA~g$%pa;RYvX32Q%q -z5?QYt)t9@Az`Pf2Ieps^EDdcQafricndGSSX@JXcE=s!fXVYDY3{)877ns=Q>@v8# -zeXbE&5#J^aC#RN#M=MZOoq|-^A>ibo%pzNo5e@AQBgtk$Sxo8pYRfXqUqYeCOoKDp -zhXdl$qcmegjOwJH1n2&BrMjG;by4`U@)U=9lg9KI| -zV+l?22Rx{#dWsjB*;pP$%B=QG!KRJN!<+L`HjXaxVh_{bn}`qGaK|{=op2}#bk!j@ -zz}T39yJTR(tAGSQX!GNYK1s$fOvCMlfgMpX`$Mqd2@a6TOwd!0#F@oIGX^bI`X7%%PnFCY -z{#0f%mXo-q&9U7z3U_RzJ~F}aBapy_8m=v-yO5W_@`ke|3!OV{-1=pfoqTw%{Pne{TY2c>YLs-P#=k|VWKAXr+&&C|V^ -zvG#9lk3wusPcC`Lv_6UbT(Kn=bsnT9D~e}iBqR|8u)HN2X=&ZB1L1aG=e%tlV+2%J -zzx6c(wK@!!v=ItnjVGCfv|b1Sl*c}3%^`1SE}vhgtUZII;cLxGuuZHUbf#5u?8kW< -z0=lBXR%_%37kaThRLA_oxiEAU_Z({^gZl#s7j-6J)iIylnElT8=(XhoBE8JhcnIfVDBIZoYVX-~0zZ=rm*zVy#b-Hgo~BB!;w`@1%kmqC -ztUgFeyeq&c8TU1`Ogti_RS)ux7@w#HeAf!fgA>Z)4-bnx$I>vpxI%s}qNb2WxMu^$ -zlOp_|lqnW?9ImvZ`$=T`>)7%uP)`tz5U1$DMd%8-taB-Fs4MiZpDzHkr2`JbCW+*cjch_flWzY2?0*71;2roK&j%z4_0EnC+sLildN)PMA`I= -zjKOrVnOPtzXy}Q;uMk~d`){?M#^F*)(H=w>iD|sm<$Ej42yac_Ds!&5bI6yFSi$lu -zc5ePSZjB5PgCE5yDl*0qr#fNj5QW%IQJ4~A;s=gF26F`4)795pk956o{#aI@SCej9 -zApzt=!18M`gFktWrGk_YM^g1=7rr9pvg(WLQfAzban5VqN*_LeFquv8+PW6;lN -zfXf1#FXNwE0BIsKyqnfE!xxx4s -z&1>v=g@*IXae8EIlq%Dt;nC><=<$epMPbF4i;q#G4X=tn0s6|513$~Jw(RFOq#Ap* -zwidm7wLEOLYt|t^)|W}3vZP$5@&+QF&GkiY5VM$sWr!eEyzxjeE*^(GPxdssOBN_7 -zX(kkixEci#vWrgiBX>ow+kZBiys4}^M#u;@dzF?nccb5ptZCSnb0X{>CC!_xtdyyo -z*bh%F;)5>6h}D~P&7 -zV(JtD<}h2cbus1y)^%#zoc6q6S|Y?;Y?|9<$)N;MyP7Dr#&A~RYgsP#5{!(;&Z#?Q -za{z&BOLySzvWWl<+3pR~()~~vKBI8#1aGKTn1Vd#EIESx?j5y33zkhdpwn1t4rWYV -z1DzCHc6l}cKJylLG+6^MWz&v~rL)v^Yh7r8E;WBm7Gg2R!-s=^)1$yi`Rf7C_j7O0 -zUcG0!K@V(gafLunh%Nu1nqusHl(H~3pJ{Vo$IGLkZ%F(FrEEmvTxu&X_*4$~u0dt( -z-b&yhc%^VQGIGD|SJsGDVM(x(q+i?Ri71yfWwDheP}Nb~Xi*t|FD7fV2f9)w!>LMUV<)vypQjD!UtJ}K1Yh~CaKWH>|!FZZC-7q -zgR~L2VuvuVG5#{5?ZaK2Cia~f3jm(uzWOdQIDB0=rmYv@5ol(y|k9!Oa -z8)wa^Yweszi+;9@6KbSz!maa;O*;PrCMuw#I+_dM%DemY%6YB~q1yp7_`q5Xx!^5L -z(!rz@4+#MGX%+-FzRq_!4%*go2uV1BM_x{x%J;MCJ5WdGvU4x?{MKU~N0?dPpWT~B -zC=Nk!eTO+AgWI|^4wG@PW&a9OTP_6mprEfm4g(dj5JaO@1}08@%bHk3UtY%FA(Dgz -zDdmot@GD7!AHrwy;!mJq$`4iT2oo7{b%1DE_w6&p51Pn`xu`;nokL=WV}jLZ51pvN -zxH7Y4L#OFmWq+c32~t@0J(}8k=YgTalI=Gsuj$7^ak*aol*s%pXa4N{Q%7cCj6#Ou -zU=dr`)B)25#lg7_)UcpPP;{a0*)c?je#0{b?k^g^}UZZktv2 -zxr50s%_lj5&t;@5jZBgg;sVRi%~@lR3i+gQYjggDWX=P4;2hdVj?n0q0d1L!^-vCd -zIGY|xgeS5miBXgDwxG{&#tfB!Cg)3a^GbaGZ@T5W`9O2o& -zF+WqjZmQ{{WynsUZm$<2ILfZUCu?18eul#^-gFu+eqXF|b1;9rBvY4jlw&@8^-;{2YCd&J94=;18HXM50y=hrZsyvUI}-WwJ{}1ZR_-!A{s5L76zMaVPD8 -zIA3_j8>@Xickpa@qz-d%kWIF7wcQI -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 -zZ)25yB1-axW4fIDc!H!>bp|< -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 -zjZ`^bj#SwO#N%)KhVf}A0F^}Y0}Sq!#KAy2GE -zuhCgHysXYjUZCrs(s&M5Gs(526P2!#4CVvhpv5JYazC!TLMabfg?qXI9M3d@a;3)S -zpY2}y!TI6}$1@u?$tRyE5M@8*oh{|+y1AZLk1^W4#Y69PD0iASR`P}E``c+fW -z2*wiZ3A+X3hL|h_LCqD;G1%u;0`=CIU`?G1LOP;$W<>)G2-(7%70QFJ$&!;RE`Z#H -zIvFAC4Xk}};cqroLTuD}9!DiSm`7Y8X~zLmT(Nd0QNq3;1cH1hFH*cp3#9l(cCH!_5bpGlnJWDXQ{I4@l*DU#&01Lftc7WC7x|ODUMElWSk! -zFQj(;wGoNTyY6$#vX(Vf5H$2lo=u-jB=q~o(8CNW?JL==}XLU|&nI%*IWK|jt@Eyaqm3&wbV -zRQVi{#Zz~?sIoY-B;Fqj6a|b9iI@z|oZxAV%PXissVFun75p4iC7VbbFSMam&EPqE -zK70RB*&v;>u=NE!E=4(r$xP1QZdj-rArG%!x~3DWEasb_eW{)~;M}CD%6+SHX0 -z(W1x|>O)!JaD&KvGjA=0&wrS;S9FWn7i|rerKaNwbMGlxdqPY)&B}iNH7~IF9J_I` -z{v@9G9A?FVu`12$6tq%O+Tr)gg(I)~rH7|2LSE1HMTktG -z-j=KZ0(0YpgwZ~1zP&5WMeWYsPZK;)+=dz=5;N4Gzp8B4qMInsM)qgHHM&()cM$KJ -z!hQkwG1H^V$iK_^V!%JDD4WhjMyHvT#->9HymM~f_(o&Tm-VECLOe2piqm!gjzC9F -zUa>>WWXfOo4VO0syf3Ek4MZbXkXYz6&d4G6v_n -zSG7J>rU#oPk?K<-?w!@JxHyOfw_8ThIun-Jxh}Eg-kabl8z6?}GOCD>#cr-2_<+s| -zPJI7`QwM7D)hcb0m9Jy5W!+RvWkQLc^$J5A@nvc?_?P-eIQ_8LyF6NxufhZvWmHG6 -zdeoNYDATAFYo+6B?IiTgQzkIl1?0@hJw60E#pA~gU^U;qBkHRC?9(oIIgX{uODav3_N|3TMpE^8mhPw8-8F2v+ix{X_OT$0N=i -z$9y~sB6wZT^+ywFxZ9hL5s@4W9Zb#cs6IR&o46^!p -zOeAOZWSRoU={>t5wBtVOv_MUwHTa<|-P;P|1YVCGx=ScIt+2~x&O6G%p<=`Mvj32+ -zN0EoFC*kf+@5dCdU2ho))FCW~r<$kRI2uYhrQ|MOM+S=AZ_B(rUSo&#H+a}z1A^~< -zohqc@9_>U7?`$y!S<5q`D -z0Ob@z{ws1{YsP5W>YBg7ei`^$Zom7V$bDG`AUXqz+lnFv@(h&qPMR$i%(su~Ix8b*i4Z^otZIfyP^b)`I-8Ike%5!sKOKEivsuv -z58E1E5c|fik)3kE8e?!s`(On0;IE19U(^TZdYMBMGcn#72xedw1(3$T92CQvT1;%r -zi)%z?FO)K)ESbne$;ul1|?L;u1bo=~_RwNCXQn83MN;?Y}5vY21d!Ntmx+Q}_ -zO}>nYk;Dke`zCucZ8rqz5+;M2uC!er$ws0<9sQ83KILFsw#fPzSrW3QA6CkrX?Us4 -z1!ZtMu*Dk;m?(FsN6FYBPzxqUR95uE**GA@XH<}`v(_i}9n&ab`b5dBf?coH0V^)) -z5rh%bpAp*20r$OM@IW+a&ZJ)Z$#a5aKH?cfL1jjOU47-Z`;{pk2in7-!@xsI({I*e -zljMX&Q2ErQs$idVeCXRI!I5vc&g(Bv|c4k^iXGnIv7gaE&eeKFRA=85yO^8%cprh0g6$ahEq&Azu2kl+nEM6`u*u2m^A&Zz~8xp^>GvA`oL2QpDn -z(ZYbX5S?^Bi?uyR93$)@g3sd&1-A#6J=O++r-vQo+{T#6Lt`6HPt&DCYr%K+;=3M_ -zcC@CT_l7Fd -zpoGjA`f5VBjpP%p{0RzFECYgdaOw{p@a+t8PeODiDX>_Cm1Cp*kbI1g&D5p^U}?k% -zt&@Il6}7Kor@+bW3yB*aHk%mRd_g6QYn)eax%ccv_4=k41xD_2ZaH}OElb$y)m2l35mhoS~x&a>hV{@(ZewOHBTlT>T -zDyG5r!vYHajd;YRB)*tNq1O15yCp812%vY&PasKJaAKB@TmZ{f#GY8UyY?$`ISG;y -zJPVXvunXk9${RGDdIGEGjPNYzh8tg5%^&euRh%_f9o5IKg(hkYH>el%O87_QL$L-tIH4px16wqwcI5E( -zLgZykQi2esipCO1(OfEj3V>-{L|;6?xecN~%S2AbUWz?IQn{yi=xtG2jW&zxaq)CkFNz(BU -zT#*M4heG#>ev%00ZVGKKNHnxJLKQj0E5X3)M!#SE?V@vu2zDuTYm*07G#5H52e)8(5)LIw0&hqow-e5HOm-!O>y{Y -zE${BKg$UGpvccJ!^WrW9wHxbZVlc}>AAiZGpju$-#7oF>W9m%7Oz+i7kP4LYo;G*q -zyQE<2J6{7b^f|JSpj^%~xLZ_Csr!b#8EgGu!T1_;za$JI-P6>iXlzjKi`alfo8rKl -zgEy;$@hH#8VQo`xYV_HzV98-T`K*HsiG~^Z4>B_k!@;I?jAX%0<+Ij9Kmp+b4bCTD!Btl&qz -zRR&2i#vLMfCF>wxp?o&P8mT6L&?xtjQ7N``#@d4*W3+}1&Ri7&C5ZehZO{0owZ-i*S?$)VY0{~1Cf-n`}2IE -z(3+l;!SVSm)V`zK(jjaz~2Zbu&SJ6D21D=%GlM -z=QBcj$GP`|a`TTL(09U>hRk`E7}>DxJvd0SDLgi&sj|S6u -zU$XVm7~|F9*KaUM-zLb5ZC1cyn0%2(PW4uAw!3GwU#g32GMJJYDzovlnCCt3#8zrd -zT0-6)ZV9V1rDVq9la#^05&M|^h|GDWQf(D&@YJVPgGmJWsipYTOdrs5nR=xN;&61P)vF|n28GZo#F5*+x{LEZI>h*fFT%kc -zmB=cWRRUB3xDxZy{l?(gNq#rhNiCU1m26SGxc%F{2Ph`uweC0RkE@hv7WJq#PZL?W -z&m$N(3duoW$(dtG(6F2cc@x=aqkCQGH=xf*wNTdSt{^tS`$!GdOU)BbsiE4n{1a6i -z%N)}U-$Z@N)Ryi?d$JJA3zbG9Fu4uMh(qb -zSfos6RqW!(Xt^{|iKpf*E&{*}@n}0HASdA5zVR7|V5-<*{}_$^F8^JzCR_lNr!{QN -z%k_q5<^Msst^T0gs%3vsZUi98oj;Esx{qrx%-8*@|t2Vb7 -z1Xhs>0iL?dzy7r`aULd5?H`nTD<5u!?k~!nRPz_*PS~K5F>4)z)Sw4nEzY}9Ob`f{ -zyXgxtk(s>;Z(CxjRIH8=#w>`N9}-{u2+=FjJ_Gc)BGi%cx++cceYjYZrF5$UUv2iS -z`BjsG&rs+X<=YA!UWNGJ>qSr!kdSmg!4oJpKj~83 -zVzrYRaIK^Kikf);K74ZTUv}pWFBU_Uxfb8N&!Y0n+#L%KU>WceQ{M3rg-dRbd_(da -z0J31S`a}UGJ)@dgJ1s|heYL|;Ej~*`>gA!qxAU-6s_53pt3YyYlV&p0rr&j4QkmYXBYiDL=0kYgV -z=>M?XiN5KcwD2HBZ#5ahd1!bOGn-mQo>eN!~<%csC!oXPR -zBmrZ$PySc%qb5W3o>`XeDee^)>ZEBg1%d;W^xV5+bpP`(yOYzt?59!T>&3g15Trr; -zQj=+SP~qU%6;WIt9B@jIgfkK`GCX>~V=O$KuNvyf!2s!t!NfYY -z)QRvLwHTR`2Pwcn8D$W&P@vE-S~IunjBrp7QpLPy?BYx^I=rr~+)7hQz#OgHh9~+L -z=pU+6Cni3=GGe73vXr$|%n*WFdkd>(^Z`q1WKWJPlWdMdeWw+Rx!1l#9ahhf51yVk -zBeD*)w(J~cz{qo4y>N|vxd>Vzp4Vj2d+OeAO*?;6B?yMnatPWW@Ll~cn8Zt5;6LB> -zia(wWQtVAq59jv1F5xD?vZ0mNzD9mX=N*dk*Km_%hH`&$(NFY%HuREB5);{BI;Gjt -zbe2*_0^i3J6NAEFDOhoD&gRj-DpjbwW{A=jv|Nd`Fo--r%i2Pnv!BE(e$<2~vdjM3 -za$WA1-g%CiJ{0#2Y{%6uwHcSy6R{It^ND3W-M+EJr$Bod?Y~a^bmen^~%b -zHgCmOYwjUlMCr@URcMR(IG0>w`VE#$HKUBzA=(vFdfjh?o!;&A3-&w2A+@5QFHP*YOoj_ck~Yz*zHrXvE&>xb#J=wIwypj -zJGd$Nt9G2{2sm4BkXBr^&CCo_eJsVz8~1ZU{j_vBRc)?|zmqBEeP^n(U;*cKJmf6D -zoo!fNXk63^1snZ;6p=WaF+ZRZR$?dFK(c%;4jY&Jsio|3i+h^U-IE4OrP8a1Plu3r -zsJ3F!9lp81ZwF&H|HEsV8iq6ZWIhtsKvbq6dvYXmFe~$=g8?6M-;sk;@dIkqZb+$TZ9mC-c`!@7O41savwe(w?SWGn!EGnsq-8+AEMv;z!)@Yd -z7;HyjEx=Fj@$yjEcR1zII -zQ)iBf-G(`N6*rxjdAxS9obcJ(Xkn=|KXK>OeZAZ_zs`b3P8m90q{2$ZY(Z~!Od0U6 -zz4A?YxIe!=-<(^%Rud)fYsMCyADKQ)nDc=A>ePycG+0+1ppnQlm!2`?3xpCw^g(X8 -z5*l#O0w`uN!gkeA=UY%P37`r8dOKwy^N6h1D`h~;WzKY#S#I!CoIh}Vs>~>5*5P=P -zS8fWSlcZz1t3IOvn8>E<_mY-~fzb$2I`2q9Y4!iaa>9#IqgV7uPE66lO_b#f*4XA4 -zrT1Maux~{_SJ?@RpgH9}bc(CumZQrj&1}3NS5wUbj=zT9Z2)rWb(gz~)`$&TlJzJ= -zP(B>kF4dQ++}fp-j6m$2m!bq)g9DwDify|}Cc#_`#`t91ldZRcpFjz6VtH|SSH8nq -zbB%wEbqjtX%lt`jS+`6mW!-S-D4RVDCs1cI*%?`@^cu#X5ui>HuG8%63on1P5bPr| -z8?YLX2DR%y8qDYt!-6;!cO^9$GaEvl{RFCed^V=7Wx@k -zh^)k+buz4_-H5Zeyynr${;$NA2Q3WV-_vrpBbFa`Ag#ROR8_7KWKQec> -z4)Jwc-wPng -zWo}a@pv*l%X6A88^;hQ3`Xh5+<6T@iM<|Xj*|o_{+VmJ=#-gVof?uBf4){1FlEJAF -zoakk10*MQ2>VX^AKR4YbcnI?VH;iPr*;swtqXGX07WkIA0;*|fWMiC}%&yBhE;3b*Q-|>gb -z%kXFBgV{Q}Ro?pr2&6Ob2q$Z9qQU`BLU!^@aD=+LV=kDISIc -zuFN&TLX);P(jQcaTbR%Y+bG}%RVqJm8U?x-o&=k?=M$dfUuzd~ -zO%l6HjEyBBnjI$h&b$n4hFyQkWkJ_xA{fdwCBkqd>PEdP3gj-OOA?viQ!J#?TAZLl -zRan%?ZVqz&Ka;6v9Zjj>;WI9N&kYzVF~);=A?P?c@1R~3?_5}70Hz;_VdVF3c`><$ -zN^_pSk&y|lI{zf^3*8eR&)epW;i2V}`89MIVBXCpYbn8%!!e2Wy&vD|Rt_8HR@9Bv -zZTVxYvfPj%>YBZ4mga2AMV+B@)-l=P5udBsVKNQU`B0j{6{DWG*W*>?T-;R};ZT0y -zD3^9hwdlf_BI6i+NNw|+YZa$QiNjsAlUzN|!eGUJ3rVu>P_tCZSmXmH(uzUOtZp3L -z6~Psk$~cN6#3g$j7WU_=Q;mzikGh6bvcaI)mquD)Hw<}RmSF<8yz{Y_lVEt{3Kt -zA~moB>lY}v)c#PZ#qj8r6Rr0AJ?IyviWfe#u^`iyD%(bp*(Zv>qLXKd6$dY4BSknx -z$>knvZEfa3BoIJyLGu?Xnvuc1IS=J3mpYFM_Rc(Y)HNN?pdiVL(3vUcVt4E_DHI8n -zVC&#j8!(IeR~X9|IX9?>d86!e9~F^pi@!5KJBetQ=mbRrTz~Kpxf7p2Gs)!yOIu4Y -zfwI7+JFV~_whjHhs^-Z+#q>5eR3BiN=$pB~%@P`Mo}9Enl7 -zNJ>jgCj@;^?%48RE4us$9B}R)7+oTfJrpxtB?iS-C1f)=JphZiJzI6>At%X>VH`8P -zopmrl@x@wNf*9I9K2l$>B0!Xu?!gtlJqpdFUkU4cd?$}kYmGu$XyUnHGit3UAZt%` -zDi!X*s<98@p`he;0?0Tae_GGdX7RsN8q_}g#OF^_=`Bg}4B<{e_d=!CrQp!4{z`hEqaYQNuT>ALM3=NE(g0tWOi)=EBaZW`dVLpVI)o2`ys0 -z;^#6+0zvk-!*_4>_*g?z>+K2RiY$;&Yu9x&a2CJkM~9bEo8Qi`-!-z3+1P1=w}gE-&2I`|)TKy*?nNO9d|H~qha=WV8dO%c^^H;j -z0?~%z%-x+Z_Wu2qjB>mznZ3xjrzNP+4$Wj(xL!M>6$PO5N{(xJDg}Jq3t!6NjpJKe2U@URQgh -zWb8x7$WwfwNHO+#i@H)qvlM-#7s;0<%_H$9cHkUqVbjjuPJG)DhDWrCwLjwVWX{9S7dXdl*a`zR)MmF -zW)E(K%tL+@HaotLmR>>_29k9VY-9q0l^kgX@r;CHz -z+Kn1MLv@wm06i4!;f|( -za(NH1$@?SCJ=ax9Vc(!p>S=(Rt#GUEtytDshUMHw(AK#`(}Fv+y_)=MPOiRo -z!wdg+koSi1vfLW@l5I>qp`+dQ&;97o&E&l)jk=Y*=OE6srE-mxjo?y}<*q}yc8OpI -zrDs-OT~lw>;n4Z`&|<-S65@KOo}f)Zj=e;`5M+yZ<4Jprh{Kxd*AU8?h<_V(DQp%p -zojhJH=URyze7RTp9E+)`#ff&Hj->rF;9s44OuI6iP6DWNv-uA)Q_L~(y?)qpaPKY7 -zBB?2r0(I^Zpw9gbsB?ekawC^VdD|5+5Ee9eQ?DxPhe1Jrq|ik$e*aSXN9R71SEZsb -zBbGG%p&`BVN9Tqs6MuVrK?-X;ITuSG#&}sW%Wg0$#Ck6QLB8TDNcpmB!rhj^F$Xe# -zocpjv1K{dL&a>a&zE2*{v!#Jj!CRyfhrrX4lM*2<)j||Qq{Y;+n?Fdi;bx?^HwgI9gEVn4Oe~6U -z7QbcenbSyBeyz{Oz9T|rFkn^Z -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 -zpGZfmjs~I8)E={{VA9jKB74 -z9V5FlO4K9gexNsRqQ~P2vVYtreF84dE19gE{i?5Iv$*oxJR!~^32-Y}JPJ^pN -zcVn-sSXK}sibYq)DNk5QQh3b`NCeJ$PxyH7#^?hd>_R{4T2-hIW($-eTxyV6MQnV2 -z#)=!f7a-DH9dDuL5=~0I4AoeWrNJ;3!NnqJRrMmDC})G!!xLbQI1R)1WutDqpx9TC -zB-$2{q*>tm=(UV61aqo}eX3Bb=Nh}M6fEftN`nS@NZT4YP#IL)4Vmwnf>PM`wRZtf -zMv<#gm1qb~r9=mBrR%V>-~=BI;T7W>tHWa9BqedN<9!((+=&YG$ngplX73=qt<5bQ -zHAWxh^ljNY@Ac_gVGUq{mJI^3P_cW1w8507bO#U;jtWWPVDIfW35)QcsCHWKA5GG! -z-n*ujg;L3X8SfSVQ?N)sz8OWaoE(OnylA&?9iEWg3<+voMIM|uOM%o?R{_qLx56^%1FDE&EKL7nOKmRQ*{Pkxa;ZJ^cdAYRmmrEceYyQ&Oy?o^L -zRHv8EzZ|lE`Mdq)4spc!=`~F7ZZDrhed_7&ms@msxut#m{P*&4`__c%>G^%1qNu=a}$vk+d;QVU@58JHRJCGBHSX^W(7zyfs>5A;2zy0JM{BJ -zwmo@3S|-p?vCd#|@A-m9JJY^AIlv^GG@ -zpuyuGdvqq`=3XGs)A9rT*PCRz;7}t(a8PCw`5UlCl)(5$!;h5w?+tzF4F+3YnfS30 -z|DGQe|A%9G5m^9Fw4OUHZ^(Ne^33s{AMaqghRwk2bDV;e7@VnmuKYetM}{L= -zVAgLVmdNYx4zU9w{#*z9`lQ5Lkq^}v48pQ1b98E}{$q>3yOMbtZsn||-BzRquH?cW -zaV);1ACmFgHj@SFM91j+8RH2F*(G|hELOj^uk0t+xyQE;q!1A_hM-E&J#u?e!fc>% -zwMmv~j1$JV}n?r%yPLtrWL!a1PBplYU#L1EV*RCIds(p$la` -zy=|BxA45v3UFj;7`asqDxb(wj8;PwHfL4wnpdjmKxx_pA@R>jd2xTBH>+2SxEKu@J -zr@8b>Vd+g|#fhE>JYyYMi&Vb?LnW$XA%j&CHy_)RFv&l&`bN4r&LxDyC}kwt&K6DG -ze5Mg{p2R(~lx)Z7a*M0qg_YzrwOcbuCuE7Hxv;(+48dh9I9&h>WSHDqLgW2>NEw9b -zWY!>{&kB-Q&RUeTUmAwg3nx*U^|NgzdzI|bNhvtTi5^4Zy+LX(Hzy7LV&WN1ZJS_5 -z^CK%I0d(>K72FTwz2m?MwrR=Lr~yJL<&xlYV%{@K7TKC03K05a>$cSyf>VV@V1TGN?^7c -zcWS^q`5X%wC=fG0DSgWlM=Q<<`E^ZADjc6E9IHUFVLM5*&Okijt17)2-gdBw8P{z> -z++a?ya`F&x(w_rF>(yx;8U#2DfQ1|Uxaz_uu`vZ(fkxvQCtEoUiySKX(TqnOpMq&Ehc -z+uyrRoSKC`u2YjTOiYVL=Oqp^6iP~;P#qfip*j02I^?#yB)y9&-i^rVm*Z()EDnp( -z-XLvBZ(o=5-;$0zeNAF_dIk(vEl)=+w#)OcU~JR>eVg6}ZItxQz#4AV-CYk_=ZO+W -zse$~*BX6>lm&{7f9!%+B!KO50+QB>oVKOHuLv}`fB$yE8uk?5IC}M?dB38xVvY1M4 -zt24hF)m)YajD3A44Ox0cfq-D>W-$nU|_m~j%`8(gP*}{ -zh6MX!{p1p7R*G)HDJ0Pz>N4m$(sdo}hM@L`Az9Nd5X5 -zrgS&VnBTj}{&lTy){$xL^KJb6SAEMdm{;+ZKmENQjtjd7Lp5H}!1V1*LiY7o{Num> -z!|cdSP2K%&Oq6mxhFH6nc7EGrmpWUEOTPc}TG^)-%gv5-g7?MD&~^DkkM*xPiaV6m -z54~I0Hl8QsAaQ+1Qkx(8bjtO+ewxS7CY&AVx;puT54L_>hV*+K70=Iq -zqK(oV`2-6d=J(`PHP5zIq-Vk+3RP*%=Df4#iyUT$NSZn -zeX|+s&s6zy5zBMoUbjbFw!T+RXu?4(KW~NJP}^$;lcNO1()$s7x81}<*s$$^xi5mU -zS6_BN#mDM#{;1O9pp;#xtCM*Poe71`KV4K^?>v1;*2{N=5|&H${M*kZU7S3S0m7NKq_!|jr+5$M#mDW1QF}aCA;%5L -zP6qq*Z|SSm{kPxzAOA=@P0s-tauD`r;D4gKg`(r$l&2=!iRRSh34c3QzMN -z2VOgqqkUFscgHwEi7yL@luX=52dn92)%E9T@u$i6@0$v9k$3wMz|Tj6XB4-7)-KEE -ziaNS(arw80;}@Ou()=D6rm$kJ%=#lcIi{I<2edP0uN3T1Eh}rKQQGPS;$jjg{&)`$ -zS-KW7S~CY-3^u`U{nGVA&wq<|C9dwFC?|052_XttSe&jdUvu$pww(+Aw -zhMof6=F#=7d9+Uy?9+tst=CMYB%^4$)2t_;rRghWQ9!RN&%kFh_s4e}HoVQq{?gd- -z>IQLdRAAAFNA33xMRDNHxy)V{tjXy8OYIVM!GJttYO+rsZtBYOwFk;FEZ3pjEoqNN -z75X5L1=L|?vzuv3U&ClheFJJIWh?7>OrJq>`g3&2&-7cTNz$ir(ps%VN5k$nERpWH -zQ)%<#sjkRfo$2^Cp-HnizX5Nu%j<>~g-Y{lm{Q4G#razf!`Gy^ge_)7pl -za{;>Z5o!beysuli1HXsxtBdTuLiAP>a>C6KSGhMXlMx&o_ii%=h!q+Bnb%6 -zSSTtI-_;sSx5`#f_HR=0W)ocUo=Gj^ox}@*?`N<3H_)%OgQ4{V%zOYS%{V7HgID1Njam_AKnpF`cRTrl&eY&6g7nrg2KS; -zHQ*3bi0<+M@^y07-zua2IK$EO!0sHfwd;X;N&a`(p8u{cZx|y`)i%k7L*0b -zrROhOZNn}D8pWmch3z|91*?1TaGxV~VHtty!O%wXzn8tcfThW@bDCt?Sf}*RK?syx -zpcwDR8HRSZO%c_zWaGS(=k>asnyhJ);b8?3RKU_4ljq -z%F%NFJai4;t2s#;pf$Li5$ta%f1NFq!ZP~(*(u*Q%Zf2jZoA_{Q{eC4(y}8)^MXqq -zeox2$dsbPN)b{Sd&38|#gQex`rS#Je&m1<_ZL-9{BkOCoPa64NXTwb1x2v6E*gOmN -zPnQqNqPE)~equkBEUXg8hx;3aM>HlDf3Uui{NgZgX{_XF=LEB=07xu -zVU6Hi(@zsCR~T3hfA5FSmheycR--n{kKw+(8K9-}bnH2jISmXbPuGc$Km7%?NT@%= -z^y_-wh{mlf#qhYCn!tei>)3#td)vPc+uKLjB^4fSVkz2y7x2LjLnHXZK6XQd80Vqi -z`6?inpZJGF4fxO!_D(;qxM423!7>j5b@2!1SD3t8{SeKDD}=0gC?H~M{A=hXdHb09 -z1_Ks)W|I2g;3fVN%XN*{mmfRB1cZ)V2miZy(3M|0vLg(`&#BqYj@I|{pC_1$-%Eed -z>a}tK(dJ64%RXI8=NbbCA?m^Bxhy)}uSecG3@fzW5ep!aH%qd_PCi>Ynb(ZDnEul? -z64l7N#WJtv=Ho9@fSGoQCg4nm;S6l1SgYZ=r(U-y&#YKjUS*ds`ThGj?O==0 -z20!HC?>5j%#1qvzZHy7jiY8Tvzdz)%`YPC{qe%&2cv|wlEGNVfPC}4*-SaOOoz6|W -zc>#=$ph6oPoEOuc)*k1G=*FI(7U^L*AWDugbu*0Rcs~ctml&@r1s_u$3}I{#nhklo -z7Nw+TUJ48&x=JkR4zdP1c=lu5;IOHpD}j~I8ia?WEeC#bLN(ndki|`d{j#3pZA#iw)k<^v|J0ZC3b{`&PcI#Hak}drXCBSetoQ%fjfivxR -z5YWv57bE{f<)YoU(t2=yZjHgM_z?(vG}LYLFPHt}p{EFLC5dJm{R`Xzz};bFlnN@! -z9RnI=jLboL$*1%X;A2MDcjV1?CnQpojT!LnL$<~-a>!}4?EvflaB3M_c8H-k7U|l1(a=OXwyyy$!YrxR5guo#<<8siNf&4u-5ak}6ZEV=-6j?x+ -zDFLf~Ck$Qc0w_tYyoJ^c#H=^V@8Soj5p^|6&^PV)kly-pG@FX1Q=LrJ4YKw$&zwoe -zDFqu=(%36P^ybzX$6}L`*L~(#CMwVJrCYB9i@Nj0ibm+jeC!DQ316{iN}ddm9oXND -z=H&06#m_?93@VY%X=PeO-H?MU0t^{9XEH>`-QVS*Jvd&-5SO`SW8o?A-wn9F{Nq$# -zgqBa@MjiT2KCqq|F8uj@Sb0`y%K{K^?jFsSI`Tc>yigeT%7Nd|!nY?DBw?DM*x2kN|6HbqBF -zd$aW)okAyf(vD-l(z*f{)Ntg{EdPL5hy>;e>m)n{769c;`L*lL@&jvYOZ?ay!!*1- -z_OT6@MZeYU2X8v4Yf%Lt96Irry6j2fS@7w!uDNnTOukty$Gk=GZVo1i%tS#Iw|85z -zgTh0BbHMZ(l_%aAHNDxHG4RQEwLIWQqo=0B9iDyO7TH!VjVzm^|EN)Q@J@0U%YmPWo5U#P0 -zVnj^F=m%>7*z8(Re_9^Dg3YE~Ip|p2;hkd)t;AM1PIlkq$;?!nyO_s;M?uQj6wnZ^ -z*4G;?9=CGUJbZA(*q`hBaI+P+2+FN6s&|r5LPxan#a(2igtvY^wUL1dZ8$2F30x>e -zfCm8BfZYFR;o13NcW&Xzc`*#mqn1ObLol?OUy@?whWR@5SN-K%1D;BLzA0_Xma(}i -zvUs|L&}q*%3@$Gwx3WhKwCqpmfpk1@cF0%1fBzwwDfC;^0cLkmrx1xQ5yNX#9cVI7 -z!+Q&8v6=Sex8odF_cB?t83o=by2C@e0Ey{|`jG@F+655#@2Unm{L^ZwP -zV%51V#3jp~Id2&6w|xKQHX&E0Vx_o${bSuoku@ZT@Q@7x_r0y`jL^FdmZ3=GKE%(@ -z{&fw@PbdDtGh>GBQ3H*tjaXUKlA5OF0p&vOFDHkgu=6j8fU}UOzv8KlgpnJH$@t=U -zavzwY4Tv+-s=`8}o$A0s#Xm0)6qJBl|4y5~AAB0Gf!_eo@O63313F+f=Nw1i+acM( -zCAHTv!se-)mOxkbOLTAT`-=+&%xtD3@#CavJB7nr;=cM1ynt+8 -zjtsymqd$*Nd0IeUHHco%z27Dr9MmiPM&FQv=rHj$sKC1N8xP^0!`D$poWp@=)Uw>j -z285Rn3F?~XeY!6p2~2g^CmF@8uSBl~;U<8&hMc-)L=8=w0PrVUw!bp8-k~&Y$gD@# -za4b0M2{xa>^)4jwkj>tbj!P5Jsm_#u_jR@KM7CHnI`KL6VYMQV&8)=g+8lN1ajM*= -z83@m;a3F?eFEeSD4RfMp=v|7_hW{AM5Jd~}I7F%G+%NKTw{Xe`%aXXl*_>F^R)YHb -z=#aNi74pyBr!F|@7(CO)g0vMXR0g>Zr2p9Rkemk;6zRv}zLx#6T~LS7qha-{tP?YI1iR;-l60*6ZpF+tZ&wr3YC9CX!z9X?10y{NhL{Vi3nG -zX%>oggv?Es2B(k*d7zxNwmg-Suoa1ucR5>AfEr@;-b^?BrX7XUXR?5u#UndCK4#5C -z_#<_{+7z@UIMtK5G|->r-o5_GlsWym8u&1%>`u&X`M4x)BDn;>P{f&SX$ZkyQ$c%M -z12=`HuK5S53v#Y8tlSLGZ^4{m!aN7P`f&%KsN?mSz{J0(q}8E?K!;IRKYt+3M+Mr` -z^Q$3EwCqns!Vmj>^>v!18wb%v$OV_O^c^p -z%PZA2?{)Eos3dUt>;Cm8QHN%0fBEh@58y{#lM&#nPrv@>A6cJZE!JuR{ughiUfP># -zTI0TOm^__ctCT6AqDpru)^6=3(_6aZm#c+ll-}a=H6_aV<)hFlWBBlLBcox&mRy37 -zk_b)ki_x#h?j(laJQzxbcBqp`)*hDMknE7`H#{1b5ocN0zt8M!J>81Fo@w3H$Aq!S -zI~RBcHXIv}QRSDpPas^02L=Gsy<|6N%UHSmJo9hrgTbXJl7#W1E~G!ZMF*Kw5*QC) -zHGMwMR}J=x98vfEN7qOIy-Nad4>lai8~ck1m%tT33d7n;uwsx(-NsJr3bcLMuTBUi -z{$`1*Yf_bL;*aq&H8ns)H5gc~8NBYKhuY=5j$oao{gC$)Uya@DrHA&m^)jJS;4vhm -zpC7yYS{Qu%aM>sMe~QW1Q$BYAX-aT5gfaC`zkSbe0#-F->1#oaCP2#!Q%9?xSs-7a -z#b*)#=xoxkmv5x@>agupCtNMj_iZ?SPQQ5&s3(5nn4z4wtTO_bTfp)0W`t}!>**RXYUkxxa*_SxNtwWI7zJ5jqzGJEsbQ~MzmMqJ-HI#M0R8;M(Z|>C3 -z1FPXiYw}cg9joSIU{<8=_LTE)NP3||WkzB#dr4=+q_HN4x-!3Q@pmu^sJpc(3KfwU -zp{|g6D*I<83#m-vWsPajFnQ2)z9KI(fWl@^BJ^YQPE@1uD9auw6h5o_z(dlSquIcK -zutH-uyABd0UQVGZ512p*xQaK}!~@z`gugX3q1zkB-4PpX?|^nLL1tvr&64RW18??M -z*q8`wyqeAWAR|1J4zQz$!N>*MIhBeUOcw37p63=-IIhvmD7tdnp#OV6yN!r#w|fM;7-|V{qu(@F`*N6WQ!C -z_jsW8(9nonbM2~rkndOf>HsY$!kZ|3VpGFDgl`8O_bs~kP*N&@N~R5}gBavii^mwC -z7gmQYrEn6n^}rB-ZSp8d-Q-!Q#Si(kpMt!y7i0&LvB0M7_=SuRbJ~~HVw9&tp_$A>u&U!Moj5cyCz3)v$b&@DY!16VUI8 -zpKByp>K3&n!TVyfi=>m&%Tm+#njcXplm>Le#?`C4cyd-Y-ovq&#y5_O4?QP(#G}fY6v;5)0I_ -z*f-bGB7c%3dN$!A2^LhWf%{3jOm>fx^=nQQNZ@P!YPws3%^-aP48Uen%0-!>fxn+g -z>*I}r4g&H?vKMkv2b8d^`U@_}`fwf!39WU=Em7TEnwA}07tg~@kvvWeT<^n|Ge{zL -zkhOcqJn@bdS)ms{3XzUhK-Z}c_x;J&cF-Rj)H|bGP?F_JDS6~A>dQL&R4iHoWGDaWF -zxNTz@T{jieB4Q&O!}NOC~0Yt-2yb* -z?KEpA#1yzb@I@?6tY9qOR^7ADXb1_)jPF0DW>1mqkDq^6=1&dme*T@p#um8@ircll -zJpwk+>=>bWh_#E(7KWiuHh4CtHeDvn7h-Y;-W+ja0_KK6!^R*1(>QZtztL)(esdkV -z3pqo(2}57$4bs;UxPA2xUehK*h411@XUp{>?o)gcYcu+I7E-kI;-ll@2Mur2ZM~Qr -z+D<8&u-uwsBN9T@Q3Lu~qn=RQws6mQ8Wf3c+Hv`*+G-Fh3kreW#GzRqtYr1>5bE<& -zSR$l`#3xPc_sa`oYqOaWbyxBOFXz0rb~^XVY9Ew^7_8ja4fa}Bjdnv&V_!<3O0pmJ -zvjoyf!b>o7H;dg*`HkDC&#xk_GBc9rv*`RRSj&5Pb6ffXKq9$vm|CmJh84*z7=}9u -zeN2XVUi>t*VDs`rk?gArBkyTdyrMo;%r@1vi-$3t$i$}56gq!;lx?-IO*GhHc}_(v -zu0o0`2JyAKGZX^-*t&`Vi2zhLCNDV8K=#}mGDxv>R!+=Ll`ef -zp6@`TkbRG-K_bMTyV7X%IXQ3-M>Y&IgyYAzpFn}XG5%1I?LLk91CohS#imF~^~Ffb -z!9MpeqdTKKF6gOJ{W&aC -zWh!=EKYb#IXvwoaU(AGTt5uj!<&(?zk_8F!pGY7(om4V_C1iZm&Q1tc^~pWlnA3+0 -zAWJBZ$$23Y!!rY=b;*eKQzzdsd>_NSt$+2>>t_4JsIf%%#Qn%%3YlFcS1m{6LY8%U1|`ECPGGCz@4Y8u__X+_gNE` -zi{tO*p|t&Hik0MdPtuMa&r8RbD0x9$-B>YEJX=p7ORO+#Qqf)k=3yJO8w=G;)$2qc -zve;s{6ogTee#%Zn)(RHyDJHWNTnR--P9rrUeVfF=Ay_^Tcdn7lvZ4edaY=!DlF%|A -z;g~peWoJ?K&t^$Cp*Rg6mz2!Gupq<{hoJy<1|GDYC^}B=!7Z0TUuF+y3oqLadLT%s -zDIF+Wb#|R%cuDI$Dfu%AYq0OE`(-4^zP;T4JWo^I?c`xVMPUW -zUISIn>G$zHvBj1kEVdo|gVjIoje(eSzp-sKHfL(gH2?P!^fB#J# -z&PrNIgtVLFxwZ?+SXTSyd||*Qo}{6_{XUL1b20}RD04SV6qG<54^;(JXZ|anNj;<}R&g+_K+v}FB -z8=wrv{o0tleHG8uvPxHSRC{X{mHgE+KN9;R+!`=HONmNP%9yab*Nyux^sDUrKJ7OS -z*=&${D$b#UQci8UMoF_QdxXeo@1+6A!->gyVpD5Vl!Zkkdj(d4dx8p}9VzS03Q9mg -zg!N)sHykGRW!ettHZyL!OSbImqWN4twfJne4x{Lpo+REtcH8lQF!9As=w?b|oIz0{ -zGw|HS0RuA@Gps*#Mm3GCazTcng{aGF{a0UBs#sH`fqk?Q#I*$C|Gg?gIH24sc#Tly -zT3^)_wVWPI*QPx(_19}}nnq$ImRM#W(YFqxizB21UXnB$lpK93VecT~wI$4a%c;)= -z(wte+s8m^-EHW#~?whJd4V%%6nj(p=e#VuGJxs+MCBXXr?R%z;jf&$arVKRwrjuF8 -zf1{J0HAhj72XPXmsW4RF+7CtpH}hV(b~XG8p;0HewFbb)r9M=lc?y0GI^5G*Idq10 -zR*y_~GLJ~T2`c{CUXz;*Qcubt=@C$Zt&#UHYwlBgmPWx; -zJlFDp2X+=elP_PlNtW$P8k9CR)2TJJ=H%2>lU>&K84tj3p>WAyQFjK}^2U%FtSW*# -z_sQH5i2~f`|pce-7Ff)ecSRrprVCRo9E4 -zT|_UG*CfJT6E7KjtgLO&6Ygm{sB9Aft+LiVRz7TDoXRK&ls+@HO~!vAjh3zBNB{3%0+W(-nI>PNe6{@+m1kXtT&f)ST9B_e0sr3R``4X?*aUS -zEl{44BqUzR2FspUbW6-jn~w#R*8)YE+RQmZX@3eto1Grg#3@IjDRgCk$KV3Nw~2#U -z=EcQGO57r$T@jYD5o1{nf%E`6e0Cu6k93}-ML0m$(bk6q=_>Smy5pf?iQzBrbMBf!w8U3?V)UG -zsom0*?^{H<_YUOM;De1#-6Lvx%2OCX_mzbwkS8_a4_{(1)qH-yBiSBWxoH7;sm3T#;a}$LrGl>>=>lnsysjt>Z4Dn6@_Sg67l|1 -z^U6mUQFP;^V&GyN=goUS`;3Q!!i1gAHLjAGnyL(l(HC&NaaVxg&S@h-G?(xMB1puoGfdZ`&)t?IE(1hma=F*u?cW{bbcI;HO>B -z89~$$#GU6uVt34fT~)I}V%Pgo0##xLHm#@RA2?m;>$nXVkE#dl$?>J1SNc&e`k>N+ -zTFI20^-9TZ#)qe6yOTx`dEdj$Z!f|4>{ViZQm$hb!hZVhLVuw5}^lh=$06h$bkT$1$3+A|q{=z)gV+-GR}Fo67?A)wzN`!VLDQ -z(Mo$Dls!BU^JesVtz|)N;qdI0a}032s)LH0Q3Ci=*RT;|P11|Sp9iXRqolkW=3@u> -zPnF~-5lKnHmlP=$Dx{#qpbZhH$3_(?4|@7-y5IE>FS1E_BLxZST>^+yZcEDpn$Ptw -z633EE^Le`BEFx*ypRRANWl@c26F#8c%g`5@8@148a&~-zYw#O%`i3N6ixHC2O_lryvUNI8X7|9P)M#*u|lkWkrhdGPhLoX96Pr@1Kl{1SgUxbfs1YSENF7;Xd&ANdt8#FjN5sq -zsG?0KQJh$j7+KefxX2=vDQtU|$Vlq`eQbyrk;fCP_QM;rrtou$cjb3*lo?YP8W4Sf -z0Nkcec$!0X+E3Bt2sOHyxqd||b7!__+Ry`)(Crn?c@nmtb0yoF`<>Xacc -zc`e110CDYt3$YeEvt|vJC0_R=spr*zF#Oz&$?1xo-mGbqETi3)6e2DV^l0RjTp^ea -zTt#qnF@Y<3)Us!b{jxkv8BU^Cw9AJh(M@nnvmcPTxcaMgc<&I(UEeh>e)|CD`O%vu -zGs?XSslOd_AJ$taebH@{IXx8t8*~s>zIR5S|)T0 -zE475o|DIa3*jDZgsnm&cL&gYaTs92tocThw66WmJRKBUi6tJ%78yxz|^*Ozt>j -zr_q>Qktg5Qvyv=Xt=x4`4tjsG>mTKQcuvFvjHsE*&nJE3<=$AM@MM&gOmj;EUI=Qz -zwAE_ACBTeqc(TgT1l&!7Q0&J(=G7O}aJFXtc@H*+Q++-S6rr$I -za7z`E49Nwo1=4Pb67vdwnZ`fqUIQD&!Iw3n_2io!o;CK&fpQgtP}9+gM}i1M1FB=KD`Xr@O33rof -zwpw2uJ8Xtck-)}TDGT>t}Zg$oaa -z`IU9~QO4D`EQd>+6Y(k;#stbd3&14V7hABW5)~8k4WL|>MuL<@hsjqYejGmn -zC3M1LA*7ZhEUEKKB;H~sS@PhK`kN|qc$XZ^aJs93*sIIREW~@lw;z8PZrVwR)<5)Y -zKM?Fz#CcrKLS8M86dO{Wyrn4$BevqfJN4srjQ|6}c9Dld5`UQZAn{(hU;nf`AP2;( -zYu(G03?&T8<&9L)Yh0?!F8_qK8ROkkoeT&Hdmh>Ys~C=!7yC3|ZW!hwCpg&v{9T(Ru! -zltZEm?*W>koO`IKto`ZQ#WZRp=*ioH=_6zPWz54M8>a)9B&kyY^C&qE;A4G?k24OM -zeqw7-d3c;82Gt5^TK7f_3gTsXCCe4$$XHk^xRd3rDJY*u+e4*f0WfNbU2Y>VKVi0O;0zSN -z6)=%&2{g7Y4&i!TEOS!U7+F$sv((CV()0DQ10UTw7O5%p^jB>OB6;>@#v}qIg?wI0 -z977>jg7}xbxnlXm;YmQ1&8tzB)LCpdi6o{KCoQ4N6HfwZh|Z#(x%WomwLza(&3z^@~GPrW_g=5|Boc5q(0(630V -zw*oYcS`(!SteS*6zproe4j56=^M>L1knd^EzF9e4(sd1q6_A2)%<3#+o)@jN6b8OTq-T@)0k!(-#F3$CqxZ}vhPc@P8>7Sk=ZSlo_+T|aMnm)}z68-YmcK>g -zY#0LKVeA1OuM~#N+-^$EXd8GH=i+VKNtTL2L^aAFz6I7Fz){~NvRpgP?kfo|4_@E( -zl&s_#FH>z+;{%E_$Go@gdYbHj -zaxer#c!Rl9(AP*7*nUVz(_MBfb=nr6B~`2tdWmrh1*N$x -zPKk3&>SvhdZf;<3d>Zw^W(eG%5S70|#KCzNBs| -zhAYw33^|#0$R^tBP`tt#*g}tOJ`PJ^63utEHi+dFXdVO6Ql~_`jRVS79V#qJ{XA@Vmfd=g_fttFAhw~k0W{h5ZpZp? -zoJ1a7C?Am+32qF>>B)cQ9ruhF$mW`A;~Y{l#3hSqg+#>!vo5OYt?$TV2;dNvM>2$4 -zA6CozVX3u4c-~bF4-s%@1&H-p#uCjr3r;+6AG;*$raj)Rzox7OvDpc;^ci{a@=wJL -zFtxJx5H%+__HjIPxHHeT5%!JDu-Fm-rBwAUzV#aHNnkN0Rl913Ug+If43t=L -z#?4-~tS}DVsLtl>Pv2*i&ayv`2Q5KY(48fAj}nKieRF2sDx3oH68A_0dp!7_$B^ha(z!eBP)eRuZ#rRI@UD^@!8Gh^zUfh1!DV#`E(0V8+;wU~wk-Y@)Gx(NcWkR`3&W;k -zk_a9nzwy89$++{mB -zV@+&Y0?2~~?d};UZ`JYWp=9Od58{DPyR#od^+vKs6Tz;D^^XxAkCjP6)2sy&U-TY|(YLPOyLF$j@>N08DqkL7Q8P8J -zV505fhpbn_W&`)>;XPC>kCKoXAE5*W8hl~)KFD&ICDokLG^m)b0YiLvP>yz{#ONn9 -zWevC6A+CD%1t*K~PZy&0{%4#t2F -z%v>W@?UgSz?~5rgnjrrKAT5y}4-#w`HkC0YjKOm!-UIF(SPjr9NtF4##W9R!g?)m3VXVm{Y?NgF)jSMg*XN*j(pD=mQ$; -z-5yg2jJ?QWVvfX~qt+HjRBo&yK$xQo*ZT&%G*oVt3zQY+j(56(Dx%gdnZlh` -z33~!^Xa}+HMme6d$kfb-XNo -z6-{DUD@&sxZ+gJQJ*?k<|Mo3=pfmVJsu(P)DjV>91wn2M5Zp#H@~szwl2_mRQRwCnfd=jY$;GTXSG`L7Q2)5Otu -zq#gm&Ay!G6#8HL4TqWH<^EHp~Z`tU25-0C52mV`;Pjnqp4 -zq|>hLOAL^lr7T&ahgNm6s|K4gu1t|4>P96-GzdHqNQR~PX!cJv+H$9STyBU!8n38| -zBf_uxnc7djZ*DeOG$1KV7^*uM11)LQJ3k;Ko~9iQuSaaIMyt^xBwn{{VPIn1+=4SF -zDjd9EOX3~%DD6}h06_OwD}gp8G?bmUhiph%d_twj9JM5{?9IqRTQRZ6+KsHT(YA2^ -z2TlelyxCi{s1`|mWN6|IFbh7<^Y$lI(~7N{(u7q0kJA{kk#`dB%R -z6n%Thc7Y~@c{i=++PY^GP98s)f?RRqIvCB?hEQIsHOH|+3Cd$&sQi6}X;wG21p?Drke>_y;R>3-u6uIfF!qQ9ri%H*9 -z;5x%WIZ@fOcCINV1E35h$Uoky%7bQ(*{vuE3?Q$5{HPr$+4EVwPvz -zhJDdbr#0R6K5ozM3+V0a-iwvmSk-81#-Q7;7F~f>*-V2ZJ~i%^LHi}a{jJvc#GVLR -zMokG+{sz9eb}K-rZwB!Dw?hB#yCT`bB*~%0@7NWT1uzewuzwBzkv7SRcvf*nECq2k -z;BKR90tTIhK39%Vmz(sWHEEN+DDsE-CGW^e9WvB%eoB5 -zB`&!mpxKr+LhG#-KGraQXWdQrC~?&zD2EsANu!QaAM1&+jTcg_WSyj(Q6>+rm>qJI -z1Tv8*sd6Or45jaVyJ3!IRW_~luAu1|gPwN1+XZLIl5dt^Dc>!UR9%wp$jOHQ+3L^W -z-P=vMP7~iSJO%o<8%uW{(=UKLOX3FtNPS5R>~uh6RUDd+eh=ZeI0ND)KXq+-_8(|M -zwN?EKblKOZc-IvtOrVIGds&F3WKqoo%)ZF&8jLOO)g`v1BjhW8mzA{{7C3i54m^_u -zgPg$(dtY6TB+_DHbj2J74B~s=d=4Z+Ddv87G{p+|*lb;ed_2~o4Cl49|HwHr=;emSbm{t(e89JD3gntE9 -z2cLmnsmnW=a1zzK#j(QRNIqpCDST;} -zf7`-QP~5I!A=;8(75(kB9%?f(0qj;|QVPlI-f=zD& -z#W3g188#ctMOw*R_CKdwPF#R&oixTz(6*I%fX&{bieJ?Hp@J;fZn%9qj-@`Yv`HxM -zLshDz-nzUNx~vG3B^i>nBnDS=`uz&c6g8KX7_DJDlu7suj|g-$xkm&iDZZt-zlZBt -zZ-hUDzE<7Y6`koWM~{uA7GRqAxQfKJ8HQLgk31bPD -zRQ&VzlxSubQ4x8m2_a)hi-8B#`oB0_S~Xa0QHS@urbD -z#o|;4=@@yH;izN-Sk+x)%%W%Q$woV&9_2k)n1YT&{lx-1aag}jqQ -z2Z_cFXdlp#si>2oV;!D=c9Z<8I0tAyVu|0u-dgQ(g!W4Ari4kX(9@c>jBCjHq(9hF -z)kjrAm?f*Hx4={`4VV}7+;`nKY4FWw4CoS<7}LPK*nYJ9Cv2YCK~e$dGxXJHkw?5w -zB(ret{-m8moaZ{lEe-4v^KmwGG?4XmCP8PKdXZC6Z8Z&Pai;*l+0Z=-34%Etl>wQ~ -zs}*zDnZrO~Ypvo*m|h39)E)GdRL=k)QTLYg%MyMSI)S2_1>#=oJM6-ns{)elC}!k6 -z=Ohr;`sZLJB!%GhAcF!^ag%xik64E4QOKg0hv(iD7cYtCflwhazgL}lq=t?;HBTnd -z>I(UoK7j~f%hvMH(g06Du)lou6tp;6{tq+dV_Ao+-!2P{Q(iVPDJS$e0@})%A-94` -zLD(hs60*soJTg|tep29}<9U852+?!luCd+@SLl>Xy;i%loW|=_p*S(wFuNkKF?ImkyIqvQ9CK9Lmz -zy^)vZDrW)uJWGI=s_L>iJ+Vf${M0ptvj3d74NP||J%9i9-S#Z-XV}%<#Ycemxh0fAxH0zL6M -zk@J3zDQ`)mK+F2p-$L5`NdhC14hMZhc6=lwd}vphnblcQ)|>x -zLksroG~WC)s`eC6d1)0<&JGQ2E;$BdZU1=ah!hH^VQ_j)kXa7L3U<4R`_0EOrg)or -zE$g8!J2am7fr?v9c1VRERiV-XM)GLX#UbC}X=Q98D#su6>x0Vx|L)@n) -zMg#W=vt`U!#ymPFRLoULibD$*_W{{48nPzVk#AM7;7AVLSWVh44S{bxThO;$6Sth~ -z(B?j@KG4J^rg?ctoK;|WM;|3rt^h}>duDciAQ)gjdC)nayl#b-Jm5Z&hoty3w}=p3 -zxdi;AT3|rVwJqV|Lt;F;iJ>ekP_Fw!$9g@rFaq2$WSzlzN2G^puNzSmHrIm?Fp0wJ -zRN4%WX5Jr$<8Qw6`f?(Dob<&bDY60T_C&* -z&B@DE|05%sdbJ$7)8syQZL8m0>9M<&3L1rf);9tM3#_;7aRUJWf34iUfs({Q_a?s$(rei{r5gM_h2?s?x1Mn|;H4Bk!kqJm|qH6P(;l1uI;cbm$r -zlQ{*gB?RZLLtLQX83=|hOrI)Kvhm?^9vssil -zSv)1ME=asqgaTW;m`>YhgAnT+vRT$UJ*WkSw;Z|!S&3%-A(qOi?|jUGj32x#Q%q8QmyB62kk -znZy|(5j8jd{hN5J{7!hbWK_iCcs8TS$1!bfJq248o^h)8&wKU?#R8 -zi@-m(g(2u!PE!*McbgYeNuG5ypdj&90HK!)8nRdq;@0<*5>BxmI!4FVyia`5o_dDZ -zO16#i@LH_01?H5N;JlS2y*+GTUt-1Zu|LUTk!|eorJ&Loh1?U6g`|BFMofx!BT29l -z?EvVwx9Q^IQ%dUEe_}RSNyDC>XdNxH6u(=_aS{*_wa~sxep(^C5=_(p*&>Iv#Iw5Gc2eZR6LCAX+Ch$fm8VL3JFJpu!`Gk+jSo{;KVaip!UovSMA?{L<1EyPL` -zCZ6I~ha`4j7L#}5Q7o1MD|SD_9*j380KP_|S0%w(VS30g)G@Inkn4*9NM#0(7)QY&P -z)9LrIqj&9ek>B86;*-+{2%AkWS~VRk$2djlmjq$#qc@1T0P -z0IO;xLa|PmMD^jQRM5>(Y6?5wmspH)ENJy?Hw}`T^P -z2CZrYnez#%*^rB)l~%%UBVFF|9Rj -zl&%?bMDhfikahEG%mzzBwc&bSW=97nvNQrrd9ckpsXs%Z>A*| -z)@wdZI6(btGNI<`f@pWe)=&AjZ6~nAfhtLFB&-%{jynFEis%w7D(Jv*k*VCU=8B_0 -z_-Ojsubd-1b;88Xjs&7WT;n3|iT!~Tfcc%!ZU-h1p2ksKFHwRRSE|QS7}2kB)Tiu^ -z*s^uC>5a9KaQ^&LpJIj8m5szWmE#qDUmM9M8Y@Q_E*2W$O3*95@eH3ZN(t=Cj_yAj -z4G#D8v%}2O=owX*XbOT&F-jCj@XZ_v62$&@NEdKV*FM!LDK7&2LP3ERgIE9Vm<5c5e=9+l-JY@2gT8crG#PkUdfwtAsQI5#SRl`t&NJZ9K^!Q|2 -z&8(*d4wyU|0?j%!N4B9&?^@O-e?go-hep63x@O=f6-EQeierX!_p78sU?;#F!GhrU -zq>w;`Md@J7UiAe;;oJ_Q0*AGQ+G#T1B||(egnOX -zXW*0NSDu5Q`C6hZfoTEMDwdG$jvJI_fBXLPH$NRa%%pURPu>VX!B8m3q(}sR_OoJt -zLqT1Og<9sI<*BfJy;L*;9en9wqqCCXAmNDwI;EV_GqavK*&sGeZ?qAu34eDHwLzN -z_1+h=Y$T7(oLglF>G26oNu=N)LD|Mbe7TnuE9H^SBN|p&lk_0=?iBhDAJF=>@A^J< -z;9!Wd4u%~!jjmtfvqYR+DbUE;&<#fYLz@#wg9c2j_XBqgRq{cc^$P&tP^Eb=pYyN*&|eIh7Vf$zNzAQJe{Y4aYukp+Wr-zjP2nR?2#puQ9&eg`Oj#{P`vHLW -zn3yP%r!awieT7_mQcj-`v`j6h -z9&fgdSVxlZq~5{Uqh?IfO7M*)yxP737NR3%VQ}sG>EsQAr%FU`I(0tbL4Ydx!~<(3 -zH<4n*m*YXKajL*C4Z*>zQhE=he5 -z9)vK#d1f0RZKp+|_U1`q+ky>ZPPHDeg0R%O^C|n&d28IBv#hU*oz(H^t9?u9;!CMz -z?pbnnmvQautfEbb=Mqsd#*#MP{a?y1Ea6||6!YS|4yQi_u60;F7~u3ey02O1UX3B> -ze~m3~g3RBxT2UJNhMr76{ApT<9&?5vFrYCAg5DP>2_lcm^Ft6L4D=mY*j`C~a;*7C -zyl0jn%@BKf{ -z`|=?do}apA(Dcgyc=LQ{ch0o$bQcr&6YAa&Vfu{LAxsHYrW25x+)&%I6$t5wOaV>R -zNII$FijEy8aiKVkuNW*a5oW81ih|?)u>$}gp>$IubN@LN1?R%#ko3_*lmLjszEiQ6 -zmAZ@VAx@{=U8x(a`mEqDE*-aV8%v^QLV@5{hEs(i<|V2L_=;p4%G2-pxCmKX~26uwPFQH0Zo`1Xl9%P*_@qXaO@|?Hu1XaIi{VYZx#z -zePuZ7Mmd|v@?yJ)D5hYF -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 -zQ_DiBZ+>%XUy`6_T~$5 -z0;+u88xwH4%vtkQ0_zPK;Lzx$Vy96z7`{+OTt78m~dvybp6KfAnKTKUT*kdQThY3*J<@_MS% -z%jaJX*}weV{&I&n;{5a)CV01(&!Il`^!Ljxy1d-dzJC6Ddijm{^}PD$zn7QK*RPN9 -zYbNxIiVdG+!PO2hDY#1 -zA1==Zc3o6?u$rvgSus@^0V?7!7-=6+!iBEhuvV6IAC<*H*!a|weVS~%ar)Ev@){y@ -z{HoTAnAng+#I7J^3DcwLt=|kPv*MRm>wT5179K%pJ5h6G!vx)o-SR+bc{G;JVO8)nTzVrrzEw4=c*oc46 -zkBa}pF};W^fG1kdot8J`y$^Zj_|K1b@La=YVD>pq!AcCyQ$AOIpQa;Gjb8S)O@A=! -zw-HO^^>>HZ0TF+$gMEF{;jPGqY77QpS(P_BwN?MI#ot}WJPo&UR?}`PQUlj<;g2{L -zU(yfB_-&iX0(F{W^!<$Sgmml@y;v5jU)xvqlk42$+XqsJ2ogh3CFmZxJ?UUJP`KJ8 -z%e3+j@(<*RcKIl9)GiU~`LVY7|IRti8X#}H7E^|M^!9ewyro&$t3ke2mz3rQB}c&F1` -zdL^**CbHs0PXwN^j;uwhUxA+z)v=JlDv6tq?MayApILn)-5lo@w^V|2O2)$hVe@|xPMnWPi4MAKYY-wuZ0vK5>zfCVy4ZY`nlem;Z@!gMlg -z5YT4@Ni1hAO4=_CL+XW-Ce8ZUHj}+d_UNP(oa01~A@SZIwU?Wd27fW}jHb3tFr)dA -zm68BD`G5xQhq2yq;DlQgFp8y#ol8w!LQOuUP;Jj&eY(369Rb!+8O6w91S;d~xKB2; -zFsT^E0=nu+k=PD^FI43f&C^4a+d0M%dzo!IgXG>sT}bF_?Hvn>L&7$Hd_ -zF3!?z3I}{{N#00u#HAr9@T4IHCrP#WF>s&17dilsC?GlH$tK<#PDgm#Mr|c9Ta7z4 -zV4i%Ag$xvknV)pNWr?E|XLS6!rY4n*PXvxtpwzIPBwA-6p72$b-VAR$*u;$KHX&{> -zCs;Xo2pH+l0iyNlq>hb>t)&hjRLOd%Sor`aDgau`C7Q7ZD5b8g=JiiW-_jt#$)XN= -z3jX8Yi~37|N)jUxFNO$1yuk3|iTu}=1lARm-Y|7Fv#sR}#qX;5v~m!$+LiLg0CW3$ -z*NIEBz{fReQhte9(deASVTL+M>GP>WBR@1}e?R?sKs`9{uK;u`oC|}+n{Zdz8P4-?O(2OK0jTAmm~Kt -z=f7kpTTSWTL$G=jX=i*qh1HFZ*eP&PuNzpHTQj_cNiyNAt$W^A;9@WV;}U=8J946I -zhqfT!b}%&LfZH7KPVnOMrx35czD7m_xtGDmGa}^*%}2&GbAX8=c%-{)LF+V8;wLqT -z|9IprmhzI>=-ERlJuJACX3RR6e;`Qagk;Fh$d3dAqTH4Kt{z2fkj=xY5L^~f$!&Gk -zcO#n1l7O+V?<65huP6)UT;>Ie*f9SFPHOFv=vihNS -z>)OWigd8HS??__vL!VB$e%DX)7}|ofBVAXge(L!d%|LRLpICZ7g73DQm -z?x*-zJ<8VLxw2ic>`HTp2@-L0YJ(TiVb`AHX -zOsHFlCG?%AFUflOu0X8xcpF|s;XH{QZzIU)~efNY24+;HnM-3}-87kpv`s2WB -zXKJ+1D(mhDC#djcA(0Y^``}vNi;UP=c -zLPl%lpohU0_^n^Me(3pc@vcPGJrv_45r`@v^@@PvtK}XcNZF7420OORO_er&bjZ(B -zz}q~!zBP~biE@3K55D!9rw>iyy?d!WqAnPWXG|^j>BCK3dA{~QQHI4j6uTwq(WpWn -z}J&)-VXij~O9{HJk>nut7G)`J;mFQ>K{e~sdJ$I^X -zemqqbxsP$mv6AEUDND@@0973Jv2@k94Mf`E+UK$$IKXQ3k9w|{XoqUC-4wJ#Ml1L5 -z!#)@<|AyRwIK7?c9~Qrd_t0O1tZ_Rgztx{Nr;*5a0<)sOhiDJCJpTf6!)1SZH1dM1 -z!~DwSArw!uX~(nTi9ewtOV5Tjoe6>s%)UI`zM75r{3eRQ*-OqRoP1`$g#vvE_-8IY -zcRoUGzn}MYE0_GdI4RvMg}3&yC+D@G6+E3bj{HX`vK0*-VS;nd!|N2ACW@p00Tv4- -zMWVY}1L;=T3d;UXBHnC%OWre?WxSJELGbGb3%V80U6F=&-oe$2*A>^>=Dbo#^lp-LV~>WXqznSr9FC_+#Wn7sxR -zf{M^xK0v)rzWQ5b#2;rknjYAlBer%uP%g>;4%_qJ)#VLC1gh93*>GHX46UiR#XAs& -zPVG&#aC2VSJ6X8nx6+cG@nM^1L$}2*xFQz+ApDIWH`D?*QdIEIcz1{eYDN8o$hq|V -zWvgw}Wk8#_w63syM{8hp4;Jooz%DE!Fg+OANdEV-cNcIpS$0m7EF0^T9XbervI`XB -z{W!zW?zXAxQ;}kTMFvwu#khS53YpT4vHp;vYkqmt?u37TTlO2`S^n|p$5QP0;EsMh -zrr=$c{0{PL`ymxjus7Wd}s>%{aadgL}*@csl)H- -z_J{XS!~2azD=B`dBpSzJ7k%w~?jkKYzz_8<&H~Kny&83G -ze@{R9_cMqW@8Q9#B*;HBlK?JGJbc!mxJn@D*RkFF+=kZw;R@BQYfJGF<5%rb=m#I$ -z&GPbEe&UWY6@u?EO?{bA-H)I7aP;hh)@-h;jF$ho--DNS#Py)I4KMQJ8wJ7Qs*Wiv -zJ$YSOM#oD-FqxssS2QLqx&Xxod0V3oHViI%BROUMX?YRMt#gn)fj?#p@yGm!1~IG= -zjBEO7BIOE$%Hi+*@W~SXDc@?;X8AGPw>JZHbe@hqNAjkD|K#a9@$sj>fE5Y#hnRj{ -z&l|D0m8BRSms1ZIKz|(?kaKVQ_hEbc2)m@h!%Zwj8}I@?*kNP@f7r)vh!EpE^gCY# -z;PMmykf;G4TEgDx=M^=~MK@UHL6|Q7;PeWUcdH+w)o_J~6%PeGY>j^ny(DiRQ{P~` -zLeET69~`{IUt+ng@%r*(XPAJ{vFqS}HxIha`AiVFIv4; -zE+E=eX?5ABYw1j5U?4<2_&k?IXZ!WYTZd7F*85=rH1cLime|Q>OQ-UhF%{E)+D4)h -zdAC^R)!cmeWePCUF3$v%=`fsu%@k`jJonV;Hr<&O3(KqQ5{8_U&Og6@KW80m5!%>? -zJpA3pS&4U|Ql||uf>+UG3i0=cTvlHN8+0@oA&gE--k0TsIKoK>GOv67<)YK6X*Vwb -z(GgN;Lxb~Ty3^X>91-2v^V1?dEC&S1F{EyWu^jK`nE4Xpb*0#2%7Y<_4LY+SZ`Pue -z^vp_uQAAgWCD}pNJ_pNwj2j#_6?7%A@=1g6khJB%Pfn<&`~0!EX^>y{PPDQt2gWO> -z>=Y!w{$p>Z>L3g_do~~%^r<$$9l$aS-$W+Ws7=oq8xqh)P>J0s_PbBz-Tl=U>kVHMRShG%?Jg$@w#$=veF -zR&DO78T)M -z)qxGs$>Ah_^2~Bs-)_YB=^YEQ&w|#+Qk5HgL$bzcEvX%^yFzxtNO(Tc=wMW`M-s(* -z!|Zr&butK&Y|gUMNv>tl5gGME{wy+ebdWDn1-QuWWWNSHbJnCPjONREJ#5WjEJ5=1 -z#Fr(z`HwWrD2K<$yR1<3`)0#SD -zsq7v6vi#fL6wgtrnkB>y?=h0t5>O`ux83feqs(sI3RtqG-=P2)&W3Z*_&iXi9S;Js -zIiOH&d;qeuoXW7d5?ygZT{u5e?0UQ!K@_FY@>gHSpcXz42)7gMVVtj -zqKtt#2rv1J9s+z!==zSl`R;^3igGan+N!|Dm7!#DhRA=ckMM&PO4Xq!Rh(K)M3i>MoNkVSwIvA|QnF>DDawgv_jeSGT_&w%hmd?cwLaDi{nV>pn@6>JeuVn5DSsMTtS_Lr@#WBoGHI{-C2HMZEcAkdt;b}x5qxV -z;j-wry8Yly2XQT`00cuP_EHx;Nh}LKo7Oc~&WFi2tL2!t2-eNP&)Xu~%4LydbMzlIs*XIqM5LJ7M%j*3dhOrn>?ABT5}ikIPfS)Ihz9d!PWYD -zqs8M^u9=4qju`rLbsuiF;ub-;6-M<=5=!WRR=&84jFRxy&!;Xj5TOkRg)(^yB?#~U -z02`3|A1ypPKkUveTsbXJb`G#pG7@sDYOKDLjyl2gVNh>i6$IBr}D2i#ovUF6s;-(IsMdji>`n=4p6u -z0W3DtzFapbE%1L7%zOnZs0EBo5~A?ffm@mq370J@{kp`V%T_nChuEsN1#*HCaO>Y`^Y??#;x+IaAiQ{8Uh{wsm`ypy5$JXZc5q4U -zb&Rli>ZT>omHiUkTl@avLIE$EsYv`dNuC&c{P_8I`df+Kw{|%&L97uDvRGUgDMaO* -zBx)NQ1VpkJG`=iDd3Y!~!nJd>uL3ey>tp!+OS4_^EI*nwZ8+G4jE%Uj{sS){o0lU4 -zuFB}o<5Qj%&{qwj*K_Z;2?q!53ct}eq#!yAJ;^BEqsHu5dOd7PXb2{ysY7 -zEmVd4bN87G&N&9pv@!RQLjhIb18tYw#Cot(j)_@75SA1GsnFzl)P>LAD@k*M7 -zVjUrK)1|=~l%*7To-SiLvXO}}YJA@P|kVCV42PLGdSGZFqs -z-LEzSZ3#~GBrOf}XSsK;e==oGf35~T3@W-4vs*qcNtsA40WcJCW?LFTu-8<~-qyfP -zp{Z;Bf$D;sYYZzl!}D7(riR${YlcH+1g*eyUqjHQP*Sy`0CTI|M^GOCs>QMnt=bso2i%fri#|M -zFB~OLr`IZB3dSVTU5d3^d&%^c?)c?up%|sN_;6UN4I#zn+g7WVHmJ6lh;qOWI4cl9x0DDut) -zo`DU=22@n}W$qK`R^oy2zjQCz4canJEK5&u-B{9+d>f16WO; -z&+}D-yCO%_egDxl5Sq?n7HILA -z1OPgjH0o+OZ0skj-S(S9t7%%pEzddCNArY0Ol5Oe7qSU+RgD^hoR%K0}Wz0i>|qp+C0q%&g9Sd&9tncuefJNN|D-P#m|N=S^* -zR!BXS{j-vVR3_=N#uR9nJZL&!k(C)hVY4R@>M?pJs?k`KWe*ezpVfWfA!*IQY+yiG -zp|P7?2MH1{r%aUxOrQf?#T#tm0c|Y8-x`|G?TzE^hz+)PKsuKoGqUMs$@GT$@{OTqA -z4}$n^3G`SK;n0Et&SQ1->{y0bj%1|06bn%>S$Lfjo~oWBi+iatIP`7!lrZ>-YId1> -zJWzXRXhg2La#cUb_p5z%fEM)NO%gtFsbL?&w}XuP7F~KM=@dXC)5g?63v#Q)V+>FW -ztHYL3IEmSMU@+{QihkV*kL0;JlvIEIiVAFQ|LPm!#?frb(U4xR#Tkc?b3NFiAv>R}L)Km0`Rm!=s~o;d@1*RcqwA!2<%W=t=M1!`IB -zn=5INJxLNhn{bf?3mVqI{iIzcyT_^eHKz)s?=^ol-7UdpkiG#1V6!RZqP)<+-_IoV -z@kT)h`S>K*3o)q!I#^cy1(RfbI17b@);i>th;A-T%MPwf=i#PE9w!E__uC(fL -z&=k7biHc}ZM%}jPS{BW6!9=y&T)AO$Ot*^I&9z8Fz+~(I6J}zDlk_VQo7?GJkdI=h -zz}%toix@AbTH@HHYoRFb9DQ@$n>ybZBoV2b^r)zH23WD{uYnsqC!k#i$f*GtqYq}> -zwy}(^nu=)=v5}48{QN0FT0h;Z0 -znza*R3S1x9A{M7rFb;34?%8KFgal#6_a9TUr%3k4&%Z10rv`RE|4vzBi(Cf9?b_ZR -z0UKy`jL^D -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 -zZ5wanIHFd1P4)O4!4{O1at8xC>uI<-Ue|V8)Q -z9wo=p134hCejOTOn}Lo@SX?pT{(wSq>cDKluIMl -zO>1uYe~AS5A25SYB)8QKxW1>1)|PFA!F3vOq_}T&(YEo)lBHbV0}OwagdM!H$-Wf4 -zuV>^81-AC6#tj9cfGU_kM -zl7lLT-aIE7uJwP?u@V^ijU<34vV*da_=-n`r=*%I9D=s{4ULO7D-L;qF*<;i56r)=)`p|xI%NJvj9B%Ue -z_%0jv154KYk2q{HX+9tP4C-HC@Gv+ydujUh%a^hk!khfPfJ|<7zf*t2LgPB7dxNl -zRNZF9ihRC(S>;}CxW8T?y1ut#-euk5gb0^&v!NHJF=3jP;h=bm<6wn8YD2GOBB2;P -zqg6oj&go8k6(bN*ttB?N!`Lo63|0RrqDuUm$36d1>0;v*#(7`duzD{ajJ9R9F>k!O -zFxVOo -zuhdP=QHtu&0!j$DfX@CEy$?&032B88EE5(`!}#ub&l;^B1S!BEszG8%?Rq^vnf`)? -zIIgOHCwB4w=Mzu?SnUkbyE#ob0zWk)DEiylANbGIBeON+oXe@R&VP{5GpTFBLJZ15aWmQbQ>T-DTcN6$yUXyIR@vsD}S+$%sV6Z)&QIUFEr?-ga#EvsbkGR!Gt>5+^x=je0|$1 -zS_#-1DZ=$n_ZV4hlK66JE)N$xaL74dd2xh4`VjnKHZW7egvGtNWqwa>@HBX$Qh3g2 -z=p-j2_~~6#lyKrZ)#t76ULxA~+iLFbZRf^$a(P}t{vv;>QRZP90A$#Rm4C}0Y(QHE -z3K6bC$arvs9fESXw@>~$Sn#V2=DN8}+xfNT^^*q4BPg12;>Z`HU_we<(uZlu@}*ng -zGj=v43Sp)#=G$XF$Ui);$-m4r-660;l!X{tj#VbGq -zMG6Px{xccoZ!y{LoX29AorW;alsB|c`-c2Rl{*GxG~eQ9cto0^!@fwOF-b)8^SP-2 -zVo45`3R5eI6I1FdM>m|vMLro$pXShS?66hNg{8DlVVb(L9e?GDCN~>k+|(aRHW)WI -zoXu&`+dp1geO1IRIuZKxg=MsRb#t^+6_KLkJaJ8)ikGx=b;3Sc08YF8IslyZAqL!_ -z9O-dHA&1ZZpUdDQmlY}?)%IHIBaq)W5}d{y&H8eWWiv>C`$qFpCzssy20LxDzdL|9 -zQ38gQis1p>WI9!HRq+wZKkaqol-pl#$}8c+Ck75J8Y?hv3A%q1jHF>N;eaQ|yu|84 -zim3}%5%PpZq(Kdz2rRRVKjuwi2%ij25Ehb=pi8I2QCxL+cB5sM;yKrc^~ulU$-T!p -zT9awdg~0{a*tNIdxv6FN&{K~z1$8sQuhw#5kS+r^;*hT8iTQCFSgxoV!eM0v`u~UdB3S6`3~#QQs{nLxpN-$A6QDF{_^jZ -z>FOsUIT-?&B;1M_w*!Izm;dCk_zN{`0$6UZ#HP@>y(2XD_BQW$Hf#OQX`otvZOmco -zZ7^P<|1)>pX^f8a2Z$OV(OA#AKVDKv-TOCZ|Tc>N^ET8Z5;*LEpo6TCkhk^XMa14hwcAa-I3vcND1CsCOG3C{;?J@suYLoz?%FR++&DOpdA0S) -zOc)lJiAy$@h8A}l+tByx&x<=sK+gQRAQfFs|Dbd3badqPGHpHD#kZu -zIfy%MaPv;Xe!>B+R?pVxNEeC*0(&l!{5`7jqK}-B14O%iOJA{oX@S;I1&U%0P8!oYi~ -zWJ;yhh1in0!QP6t6c7S-HMAhC10cvkQxTTYWS9>JSY4m~$mG6<;gw3GCxZUUex-=Q -zb>?sq!#SsrRdMH(g->Hp+yIv3Z?%V^2n!Ul3`wJBMt#c!|4iaClUD4tNEtEW0?S+w -zGXZpc6Q)fI6PjxmVpq6>pU{ZWgJ3UJPr`8eHXDAThH`ll1bU^5eqiTSw5KYww0Ak7CS&cssO-X~MHJwHOkbGDq@IKQ~AK?nHZ* -z?iq_n_LLzxp=EXNXGdyl8Re%}&EAe4fs?hj^YjbO(E5X8(5~lU&zrCQ0ujf+eqjrS -zyU;OzAPJpZ-P(X3I4LO`yfaz388bVH8CV3&>b~|qJPX->J%e&bIEC8|QXBQ=5@K7) -zZnn0aW^4i0b@pJMwdl8JusdaS_yPzkL-Yn;>-HodI>O3X{GWvzuZh2WgVz7}1|ZrB -zQZ$BpDXRD&f2OrrdfpGe6F1I<#_@MQO>dXIvAL%C%*Jqot?2Gh1w(b%wsS-F-hX@p -z?O(nj=6`&HpHr+_MP_pZZiSQqnj6wTz9A-JX4EoCzze$S+baD?8FT1PXp<+Cc;3BK -z!W);&xwo;Lw)7ITebSDpS#Nl`_6zhww9kqG{ZluO&1!&o9{_~?TqpN7@a}?gY&x%{ -z;^amC)AbhI8dh?q(x0Duvm7>aCj3kRgmspS7=1V -z0cz>gNc;W&BREvOA@4=>dji_f^%mJ${rDM^ -z@V#NPMv!`9F7$x2)Q9@IfugN1yp$Gqm&1KxgbU^e_+)ut&5lJoxyP*Ric87_L%x-N -zv&Uf!2M~QI1~TAsyF2nz7s^g;%h%-9uHSsLb>ek_YXX9>Y+a9njNbJ&*nZtt(g$1_AF}*4( -zhW&=Mo(kyT7LUKh!5Xg{CCxUEXA{j4ld_I*JZ`BLyB-+Kwkj~8k2H8JcAwP5x_O@{ -z+Dx;t)j&?58kf3Mde4~@19f7WR);&xV&`dLvZQ{EDDsmmNc!seB?uQ}MDZwVg*BHN -z!-OKG=nJhaP=(w^EK>90?%eMN?$|X1kJ;2*jq3NeaFVIUQ7+xX($&nES{~A?QtT=l -zGY~NcHmc4%$1sJ*EplsCO$0#abhji_9xe3a%XU|U2nWaPrJ~OUUzYW6!AY>SDzq8M -zDlj!jVwqVdf%%b#DDaTsW3i+GH%}eTT{`LZvlfJZ}di?-iPSI?SLv(jjWNnU{J8UWO%4S^djEy%ndX<4q&2(_KwZ)hkd -z$+Jx)WSXAZAx8ju)! -zESpRhTZ@_md30&?o`7{nas0b(wa?qb?F%7h+e~IGiiYn{gFnTVPcI&wK*~}=!9<>c -z4>;ucCNE1EQ6@K^Ld%U?*5P*~9y>?Wmj`_FQ!o0k9;b}9sLVsB&rcve*aLgQ5?3r_ -z{NhQ*Ixq(8rNxYy%2d#S(_}ahx5`)e;hZ(z(?RkGQ6Mmr+}96}$C$^l=6A_#j-pk- -ztEFI}Acp-S&(f-1v1qHQun3(q73z|U|EUhu|F7!c`B!xSR)@70PX$=;BcSb3sWwUG -zBl)K~h(%6sP6EAYmxrlFaBj8x@w9JLrC486-5wnx0adarBn1-Tpt@q4htu -z!!o2#RSiOIP}Ee(kS~>q9oo%3O`o -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 -zg{Wx=TdY=_pAg$1BQkO+jO575}#RFI3kCE -zs|YX=7G*+V#<{kpD8B|UycvJFvs#P+zt4oC6!s+YX%E2coe{wfeoVdNQb;dX&Z+TsD<3PdBc_CRXy;$;%D -z0l`*Y*hKGRvVjF{eK}-ECk=EJ@h?sybBQhX}apV0RclEjZag_qW=CC@tIlEn6eXN4auFBZWMlJxUHZjoI} -z39Fn}aIs61jbv!a#(J>336kOob5P$Jg&wu_Q&rK3Xk-+*cI>bs$hrj31rY;^iV54 -zrCLK3ntB=%zHwvBj#`K`DQrP2_$0xk!aGPO;Y|&oCE$|Rffw1uVJ+CRM1q*O77^N~ -zWG8sGeYKja@E4zX0gqc@XztJl8G`e%E;XVr)Zc^uaIgtRj@^L4^>nRBzy=YkNLV8?#)Ll-Fw{pV{UIi0t5!;$Hfd*{5 -zsYOKZi$el)b{_(eE|~C1W|)>0dZR-_`dW|U?2TE6HgEY70Fn%67KWDgXR3$X0i0pP -zy_kk44c1SN1NMH{uYVXL-GrJtch5@S*K3f{_W5&*pdl-RIg4UIN(VYXBB6xstBfhx -z+!!nI+@U*5az94CWxcGJhDUMx2{FF+p7B|HFedevNb*%AB}hA>ij_MuI=jG*LBd2vmBx^|pglf)y+I -zRkXj2p3a+PeB?oW`h7JvzTk{~vM}-w!z6F+;Z#qJdIj54#sY)n-!Ck7ZJkOdeBS2g -zx!o(Vr%<{f8Z-U&`tv8RB)n3_6VU;&+SdsCU-?qtvQ;xKKz@HQh*R|QZwvxFVp7U? -zGj^>u|KcwO!BN;?yM~zDB>*Z@`H}M6&4u1X3aQ`#+vPwq-|wnT^QD{)bMA|PkNGpI -z+GN`+^|{jTPrW29f``^y)xsf2><*$w^|1xaC0~nhf -zd|yY~W1?@^fQT>KiU8X6;fhVrTpz0UMptl|cD+`NB4<^9e{!D5g+9^kT$&@XSTY;D(GmENI -zbwpAK(MFPZ9AO#_+)}&6Bo*Yi+jx$fzQk6bY|<6+82tdu=Az35SVb?-Sm!!8=HOE> -zv>zr|umt4c)1f-4VWEId*uEf1$U}xEtIYZXq)Z8&X2;pY>G?qII8)2{*yxWV56r5e#c6-;zfkIK15DLg}%TX+=Fpd&z9CXpPs~>4HM% -zUDZ;leWnb3UmOeVi|?-pv3-Cr`7J_J^@7&etZ<|62y=DRim>TL -z6Oj8y3)r2ZO(AG1a5mdL;Q9VWU_9*{%`$+1F^5UXJ70(-6U0?H3dNT~KjDg~>yCdv -z*qC5&pQRScpu(iN`5lEDAYk}b!RZwuSuo_d(qKK$_K$>s@JoSWGF$x*2_bKyR#wSENsKLu#WjWWV+Y_?5!)>5 -zT+!Qe?l8)z0>rHKNAbd1^kc)P89)W!UtMvw7n1eANLgbt!+#y+&PK?+*+b6*h9tyb -zBwlEFjx8#>b5GBOHp4Or!Wcq1*Edx}mB7_|0Q++aumSdmiCBm(eh+ABA5yRv>L8{4 -z?Nlcs9GL)vMV#L$13FNlH{RnQgX?CW+6p8QDT^+&4I^BA?epx?xsAJBj*0^vF}y** -zGNmMs)yhoc!S$3lZ_tZ6o3CwaxNe(?9urv)9Ej@0ql~tC&>D~_?+W{rt?$O0^fTI^ -z5B_b$Q8Q@z{iizU@`n7elKsK?CW?*c9us^(2fN;WOd)OS7}t93%eQ -z*ZP<}mL$4)+O+Vp4FN~Luj3awt*7}|$l;1VO$(`HRYJC%06V{2@@V;3m9{>oU4m&| -z_|7FvA08%o8i##pHF5Q7MeEKy)RFbu_?ZlaAtrIbkLn`Wp=2Pc9W^56Q9@C&K-4wz -zmP+3J+($UETqb5Pap~LL~_6*W9J}> -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 -zMH7FuBc?&e?m6Tu`1ZTB`Jn=K>bFZ?NOlQC&z -z6G^M&wU+fU@gWyW`6>-0nCQVm?oII*{ru)IpkBRy41|aCgaIOo5o61z93VemNxO4y -z?=u2KOE%Vh$Z{MpzKw%W0RGO&9ip-OtK|K?k`6OeKc~|ET70IhQXt-ZfD`5As-feO -z9%~4UTr4@&NeS3Vr)Uq3vKB%SG2wJJv?R}>!xk60zfrk%WpV{1#3Y-ARhrmA5k5fQ -zRTZ93>pEb;Rpv|uryl7NTEGYUm}C$jWKsKGsQ?QDH}ZQdf8CL&I+2d82}ef7Izsp- -zBmvmv2^Lq;a;@%OZp;9I_*yO5&Au-KqTqE7L0eNY2bLvf0*>LG!%9xE`^aZm3ujzD -zJCA^J$!3NHtm^o5Y05(v=-dy^B0?sR6I1hFKPh`n^+-`SuyXuA41Gb5Hy#k24Gq7o -z@lyK6moy8MvkpmgsQwgg8RyF0hRNKmnWhRY$Osv~tJ;phJ+c#IuD8OND~Zjauscng -z@6sCLg{!;f^t(>y#$;Sh!Lh#>4S1u6$DOscqzq#P{#ED!FvVGZqIU#WYi3_;`x|%e -zD4VAY1pbfhe54h!oCfe-DQz!TPw#aTM(9}E%gv5u*hd|nV -z{6H;P8*XFWoi7tz-`&fd1O@W@hNWw1LV{w#vy2+tvJm1Hw5Z3*U& -zz3OI8rhjQp{|HB<^CmpMRF`P6h(!L6B03?`X`hJ{QA%LpK1mt4MztGqzTQoa95cE1 -z2~+$%VB~AjbSw)_ST-9sb7);<0$4s==9~SztkxftzW4uSIZ0`zBH~X|M7hSAxn6Deou!u8 -zNYw?$U{G8r -z8b}1iMegXkjH$z+D-58*LLZzua99!*!tyxJ+TCQ1 -zI@Od#)0(N*D_^g@26uwm_1M|(_uLudvo6}~pZrafp{SAy14t(|a@+wYt96#-sGR%N -z<)ou|ah<8-M*eb*9TFAwXHQwd9hZSEsd&n5fvqYg?pc4sO-vCeOKoXQ-O>HMk}1!U -z8F$9C9K1bir?K-j{;^)6Elz*@1)O7K`#*?ccbkVc89dcLEzS{5h?;Q#or7%(L{*r) -z5r;NY_5z_im{iV!+R(0x*Z+Z=&ona^W|@EZ+!ZC^K;c@9%2wN)3^ajq&36;rujUzZ -z+#Y4i0(8%Sa~xh6$uDCQFJ~(HH -zV(Iog&_T7hGaU?kz^b=p!MF$4B+X*t>?mtyky6v|y`NFQ4*eo_uL!+55{gYUggZw% -zP+Pb{0{)@ow|sH0lh0+=8xDD~%SQ5ZWq0G%b4*L}HBmo_RyB+Tnc-7?y+;<&6S4jP -z?2swCnA$#J#T9)%(Oj(0PzKD|^-ufLqE$_1kAbvEDExC~w!B?AsU<(MN(U7*f%6{K -zD}TB3qW1^y%;QL922g*MgY8pj6e%@@flKs -z&7$`c;S&xBg#K*R#rz}TF>fXcjbtLz7DXLfg6`gb6HSY{WR#E71Ccp3P5a*ZC3VLI -z9d68laCM+EiCd)n3lLDeiM44m=gL86ra=1cefimJU`HYWtFEZA}b -zQ~y2wnfl~BrJFatBjXpr4+Dkmtfl9nxwtc6x59=%eb_s4^uI-Bfq@~E7@=?&!mA!9 -zZ`e`@7ejIVm_sY&RCMoWZDKP1V50J~s9ErKl?sY-Xg^aSW>}fM^{Htv%ktgk9ou;D -z;Y4|sil2ZnpY%v>XyLbJ{G&uvqhu}?#sEeKW7bHx*e;XiB|Gc -zn?*7<;cdbTA2m|vEy@nZQ;RI`%1^D#f~egtRG)92EQM0_H~EJcT8Xk9_2ARt*Na0R -za~Qa+giUqSK`_nXoK~j4k&4rqfEV+Xv#w%E8iKdcn43vQX8i*&)x2x21kV2Pm$>m5 -z&v&d`fi%C9e7^G%8W4t}Fg32_08#0ppX{pj8}L;gcX((LX6QW&`ZZ&3pw|{RDY&OS -zt^_VG|UkRU1_-qW{An9%k>xEwo -zuY>}-?fXXDVsz#IB`^cLU{w;F(wcEz{2*TMQ&ga2U%*gNWJuY`!4$Q@(ie=;fctQD -zQP&x^=#)QY^=cf{;t&E|z)pFctp39< -z6TvVf$^IB5_}}(+l2#&q;==N%vR>0O#N=4UAr4o=lzawVCvB|vIYC+FIZXboFSP+? -zg0HH5*|gu^*ZDuA+*IDE(*_*XGvL^57#$GTeszC5uK?11%w!S?!^1Wh1V9 -zlFTjp02l8xMq9J7%n?pqHzH-M9NiBL)2Xir&4%n1^ltyCZhwfNqAi4Vk&PQNk3BW= -zcxSiAOB9(btqrx8NsED#@zA5lDD)9?QKkbcyW-UmkG?+NcopT;PS^S--ZB!L)y@3g -zBp+s3uc33exN1x&>XNqpOU1Q6G>>&r`R+i#0S-ytamP6u{7tsqN5I$nJ-O4A!;b5d -zEf*`Lr6rLMq)4Qqg>k{B`S|mg$_;`fA_zeX#}Ka?%65yF2~RJ#Pt~8P@2sT`d6fQ8 -zdW+;t&BIQV^7toUx@U6W*$r9(RwSH)UGL81!9=Daw9|2~_Vtr;J{`^eu46x30TWa*DDhj- -z@QO66{1*73u@Y7MAVoQ^#X=$h5KQEBr=$MHP`Qs_}Z1^Kno_eVg{?}FUxx{d -zMEe`Jj`J<2Z>W;KcjP(CHwx#k2|_RCh9%yx__b1NB|H}@1IbD1V|L7M||@SE8R4fPV*JdCO*Rbnj7vX^zvXx7*JnA4ktMvhDMxG4)1 -z`6dF@ZTS{gg1p3H%JsQjj(X&vKSN5*m%3ej#_o*7{SNpIAYj*in|M -z<1O+cMUoQ(law3=-Sxi?I*|W=qVmT(w)+MP4ic$M0#F1urJX_Rjiav_=-cxWRZ`4g -zEHCK$v-ej|v -zOwf`hDhvw0{AcXf%#545QW&-m -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 -zD~=9rat*uH%4eceXt& -z5MzuQu^eh}3HoFZQHSH=8dJWyMKCGo0 -z(u$8yuRf^ZIft-WE*& -z)?o!2`g+bQ&24kZjz-!wQ>MlQm{VG45)eE&q9JX$Mtf`^My*twv=|Q6C0UFm<+VU$ -zd@R9=Zvb@ULpQq$vRTZ{)-j6iE@w0QV)CjHd(9o+LgN6B?M1>aO4||-$5;`MZn_<~ -z&Ad|U^@~zU*y0dWv}Te>2QQXOUbYBOrdsWzXtCggSdw6Sn{!R$J}^CA(?`ft<3hiBYo_|vD2REp%Kh<%7eI`*2&5Ryw4 -zi6wltM@#>Z#;m_cqeH37@fT@yTKX4h^!Wdh#*=@M#?O!cCXJ>4CXJ|nkw(bxQ3mSo -z8$~|7XE|tv@fS%SyVczCbua%GjS>GP8YTZrG|syHB^t^85sk$EB^rC`tjGTmjk=#n -zWz7E;jWKqbBmwWwU!oB;asF=H&u!e%@&^KR5-2t*5bEk?j6s{k%!tetb7s)GiO~5J -zJ7E!tFu1cCiA7-<54UT^Nanuu);Bo(l(2d=SuvrTu5%y|NlLtO>6*%cM6}p -zBFEC41%|nfHKMEISXhHVFFBVU=0P!>zH2s6nSOI57YUCINKXf@P3ZF4QO?5L)12_n -z*}6&){5^7)8v`<>5(*zKB3Qh3ZL@wa8}pMdnoL5~;HCNZ2ohb8&Ke#+dWP7>79j#Tbh*@xud^@C1il -z(wb4 -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 -zlOwH=Etf2|bQ5WVO+BYE;UgJthq0{s$b8 -zAA2#%QSKiv5fvNZAG1>61Cr9~#JRd?i`)^l6`?tB?j_!L6vUsYQ}IwADDxMMp$~wW -z*pQ8KHUPZy!OlknrM{(>eh7QhTC-z^=rJQZu$XFl1?svK3$Yn-Mi4pbLPAa=X|e2R -z8I4U5sWHi`UkMezF6r*{=f~M@G5i^5a+fvqR#8(#42nZIc^4mke@Kg8Y;i{YeMN*& -z3AGV`6h;l4TTsm-2NDdsLwQJ5VT7UQzR3CC)z@ZXi&SMfx=))=m>Y -z=SroGsj8`ZF(DdE$t|RASl|!J!SP;}WL9MFdPzw&Gn?Db8`u+vwXKCWoXTGk`Ux^a -zd}A`9>SYWBqK;0{#DO@?q{(j>qsK4cMdTSkR^vIBP2n^(_7Rli2Q{T&A>=LBS)S{s -z*lO)cW&SdY#PeTfkrP}t`v>N~&7yBhjs+RoKW6cK*3ahOW-(T7foL}e&E;>in3(Xl -zSsW5mya$`m{l_dW|BCzeWftYG{xXZbMt_?{$ELr{Vr{{6uq<1Nsu9eWS={^mw^=mZ -z{o5>-3<{MG{V%gfZu0xt_iwW(pZIg^Z?gzI|F>DR(PcW>TsnqCE&7jH{G2(%NyPh) -zS!9Hf{;B=0ZV~@w79SVW8~!niQU7BWchV3g{>v;L|NJkr -z*k0NEhAic;@^7>Fw34CoUuN;Q^9sX1X3;6*%Pf+3{L3sxpX5e3A51UVrhl2mqR_7* -z{qmSFL2>qPu5qb#!-_p$4v}v+n^xaMvyYd}L1c0S#uN47rGLREgo?kIV1(>Lw#6i@ -z#`7SPVfLWMuP<|7Ml2Dd=D*W8eNU6G{LQ6em$D8|SWCiuA-9LXB!d@96+L%G%0THo -z>@AZKKsOZQ-v-qrRmGHLwzd@?v$#eP#&Tl_eoy)Ms7t~WEvIqAkZ^=9RiVZ^-!rLO -zi^1AjX>|>fRJP9PsYgYO7TbK?TQ)FFqZC*%qIWcPdS4M6+weY&Nk!Wl&_j9vKF0Y7 -zy$+pGHY33V?}CZ+4jUk17_0?@lg;>^E1{O{rN@zMt+Jm>H%Qqo>XjozFOB&?feDFkHosmK{uS7R!PP-OiUF>v~Bd*}q5q -ztD8Ayu}@9jt^{-PjcozKg_$R39uz{NJCoU}9D4!n`RS^u6aLXLMb^$peY5{f#N@AD -zChPU3OAx(CfO@kNZ17otfJ^43gr#;DvQHfqt-lPYAnzO{mv|^1l|0A;Aei|^y2}1y -zK<2?}q6W0(eZR7!rdjjOsFo0>&c>!* -z5yBY|Lcr7m;a!aJ4+56osSoA0_T)DnW|N!U?k?KdtOIgYvG$<%u6ma|%*xXmH85e) -znt*T`@!>5Olh#t`S5GZ}s{(=H -z^ngS_4WY9Yrhnmcz=xpQKFNLo4+gPwCAPr!{6-(y7#B-Q@Nj%5kBKu$y@^7p=64m^ -z6AG@yA}QYbu9B|bSC%uU2fGu7i$|N&L}U}uI?RwUqG8V*>xPOdw32G>7IlGAU0qL# -ztearG$ -zax$ytc$n~SNGkP3(c2oNWB@H;cD+_ -zd_3L&4ZywRT6wz1=Y|Ni5{VNe!z-tTzEz)ukZ@Vn-;$`DOhPyIl)Pm`gl98>u{G!)IA}L*E_<-aT^lEFuQl0npKSl~m{pUg%GE|WJ?JN9M_#`Ev65WoMbP-2FR{Z*kPmA@78=Qp>%JSN^W -zwmL3~bU?JnF#)RMsj@~6FGEm`-@m}j6k9q(-$05L&1oZy#^nTUIE%3x`J)9ARW5Vy -zlKtJ~x2dVr=p^75CFHE_8t~V`zD9w@@vhw}K=kHpI8rL;2A7nwVL(xv%dbObCg>f7K_i_5P|)hL(J*E-mP2WJi25-6;}}`%}T$ioiE-miZzS -zSt(%lG}-J5B!KDM7AFT_EzQ>{VKmW|mwr@q%#&-#bEWD11Ec?arKsQXdHt0;dqfJk -zrP6%>btLYP&VRf|c<_qv{^2ccEr51oi{%*D3q@_cJZa90UxxJ8pgO4DZtJ_=2yzBv -zJR@)Rjb~c@rMi5wv#y9CctM5Y-I&i$+--DZ>9%einzN#G+< -zxLkxaRAR~ux^h!&Kb4O*={VYm`Sey^^kvm?&jIf7=u6G~SN^c{mE1U<6dpC^!`9b? -zn1cw5z?}cX*gdufg0Abjj#05~+jdg1ZJQO_wrx~w+qRubQn8JSSGu}Kj~;W5z4rPM -z@0aIzulsB&RGLWAl8HX)2>Fr)ZV0^A+sj(K(RE&cjSUiwq$bxHhwFFpCbxazwfWzy -z$pYHVgRc(`Edj2Ahc!u}rZ_RIN?ZCcR(aD|-9YEw$yYxTz=PcBdwjWqiz~U%l0o6a -zS!L2LWMF{9U8afAR|atbFijze9t9BH5*jHwwB0^>4_USMv8=ph{bkW#cjM=rQh2MHnP6zv63`}1i0AJJwoZH3>5Y-cSGhyP;7X}c -z49&pm>nOv(A=sjUhMwz8v!pwqX1Z?k>fBOucyxI9$f`rFb|Oy12Ys<4-Pzv?$3p+1 -zf2qHexy?Ovt&|tVxIU%P`WG!3edO^kTGG6!h9K&8Ufn8*Y7$&GoQXf<*~j|)@MLYHgraqQSd*wqmjn-BN2nq; -z^>8sr2H$P1!D;*|{cCrd^$Q#IyjcF8z^)}K_ -z*F`OF7}a`0Rt2&&ZiCG={w!z71RHm5iQ`h@Ix~g_*FMNdD^$iQUJtj2E=fDrp7;1` -z*EitT{3SY4RV?vX+pIfgq7Ui(b6aaJx1UKzgSYabA+JWoh3ZApA86#QbLf0~9!>2X -zE>!}7bfG&(n^Kgwlh=798|ZWvr7o^64LQ=p`tUCjwmrqEa{YS0m%A%mYLY+1$Z}Bt -z;HWg3m#6T7l0t*+22(&0E@1HleizVlsjyilW@D(B;nE#g)c24#UAX**_Y}h$!klbU -zG7I6gxyuM}V(5R9k%AZ<7VH(pELo~_P=WJQco0`AhKqy`3l9`<=e!=VY^SQ7*_{PE -z_B7oJrm+6q=(=ybAQ4GzF3~n2|i3ukZy{W3+L5s1-zNhqD?&^7~)X -zepvzURqfUCQ$E2KKw|@6keGY@I#gT9TMKn@^8-;%@MQN^=6@rLY(6_c%@$Ha(zF~Z -zi9RISj0Xc=D@J@bGCnzcc>4C5zN0!zoLs+?S#2H==CR`adOwUe7)*?S93vd3k+3%Db-a;mdCr~rq+emHhmh&g|JyltP1%X`9;ZH``$ZwaMWIC&BUt1ab -zglX?ylhm7>;FU54cQ~7uzyR{H=J&iaM|%baE6)(5z!K<7=|DPlzldCVZPV?>&3OMiv=K*SFvgXfi6ir0D5>fNw -zIv{|yZcRw$B{t?8p{e7FUx5;F92Vkws~K?tO*mz>fjPJ`-&Q`(1xZc5&E{)xnH_U3 -ztB4ZTw)TI2-pTV%y=LXLI<`T)AhjS%x56aov~IZ@V1Tblf>i14s2ij<4!ZdnPJq7J -zHup0>WB7?n>h(l&a@siioc|g-J5O3K57fOaTWS_#T6g;A1V1@ZK&!A}#{$N(w6{jaa;N9blnUYp -zoiG`N4M=T7C?H<4yqJqaN@A*@`YV9t8i|DWvGMo~(r`AO+s7A1PP12i@zwL^WEb3A -zp~jQEU$~C9rn_Zo1F56;Fpj1#`^_7&b{e4eK$2LO^9_j}b9X~ohw|9Ol}Ja%u2!}f -zbM&AzzEMk4LW6z*3>Q|(m)A7^dX~GUNYw>5T=v1qBzH$(j)}|Vy7iVBnzW|AD3?YK -zmn#ub#b0hvB!Gxl2aevLi@3qJ9uM18Bqju-^xh?|w{VWK&^ih5nG4T-yyS_o9(@Ik -z*s`Mn_;u538uVuQE2cplcc4C8u>C6IVjQUBBC$zGU~_9mQB7qvztRpJe(M*(a+}Oq -z2eNm*4FBCMsnX-pJaK|HlM(wj1B5T4{Pi%1m!t=F`l;PoF7sS#Xl)i1NV(DT*_uNu -zQ*4x4s9D5!S%)?^_?@}{&{sOWdy0OX88aFhE -z)JZV;wgOAI2%@yJymw$K6B{c61I}l@G<&6r@FN3Rg!Hk1O>b{77Y$CqDcsZ=U{gm~fe?EjhWzWdhIif0~am$VoF|qx<4U -z^R3!-z%;NIi7AI55K!>QC*9(iDVo3R5h2yV*dq%c6A^Cif|iC4KewK&FX~nXd`3st -zV4z;BM2mZvN+dY7$<0d^&6qNK2F$Q1;cb17iR4SI2FhvQuEH0=ey!?>mE)!gQQDcX -z&=Sa>{9+9~St)?}vf!nZJ>KSR?kL@;F`&tq_=8U*Hi -z*HD*YgA9_iXVC-#R5wP)7Q>7*$;T~c>>xHvK&APZixf2O){t_}mn0uWa%gQOVu&<; -z*9I4@&6TKfpG$r%gBWy@IU6NkX=yt$nM1GZ2>)NaBl%TvHFrp%)l|)@9_^gOf&B-^ -ze!Lx^AL9(?knBuTlAG_O$hkB8{MtS;VTaX!Xu|Ly1Y-oPj7mY89R6-B(bq0-<08T%wBwx}lpn1(8EMt$`yKK6>Zn*l)-E%qZ@u!>2NRGEZe -zc;Abq59V}+)fjXFbV5`bZOB<0@MoZQ21wtVCu;)saT-Ko+^jd}KT*d`h+>T^Di)sL -zvi&Fbg+hZJ6~>e5Cbncc;eUvZg8Z#Q9Vlce{xCnZ``Rdor3?bHmm1KtgqFzO -zMw82Ilz$8s(3~9O&?i}f-1_sr=MW3bf0K^l;b{HaeRHbt -znB|#d{P`C&$0;PQWsX3?bP<%H{j^6LxM`^A%(nf%7-fNeR`|fE2r5A6z%i1Wtqv?8 -zxlTHn=_Fx?8@pagUtjqrt1njPp6vYXISOFwbI-^)!xIGMohVA)PHN8Vm_2n*CdN2n -zg?qPSGt0QG4t(dHIfYgNp9t3kg%b@DK?790M70=hDhk -zWaJoRO^Ls3r_kMB=m+p<`{3q%S^f!I%5%D_0l&I-T}JF+UVd&n12+ZZiZS=SRNS|e -zX1MC(Nt6?u-Oa1OPhGId*TqQ2m~5lRq4{|{109tR=6hM#PoN|SaUL7f27&Q9e9rAAA0ar>8fF;7?2<7-C}F(TPglxF!PL;{VL*{$d1*|6&PUZ -zV?ITCKxa7|uaQ@KW;YL&yfSm=>)(kMzvh}e0Q9Y-f8epGyi_4Gym{0XhuOFusAlB_ -zWw;`zPHU+dOC*|X2H5ZGOg^8TFjENaxqUr5yeHygRs@rP5*H#-W|F&!!zCLQq&4ut -zaKiJMbOxiNl}S4RM4qRj(DDdZVcKEyQ)4sv_-Q4CSM<6S17kr$l~1Rm&6mXmUk;>* -zzCrJ7Eb>cI9l@MgIelRgtT+I(&}xIkda)2!j*V-^{^d2@D+7@-0Zk= -z4$UW$7(u4&1{B2sE!vP^uX&sRLN}|)=r>8s;)AIws65SYrS)Ce-xfg9#&l87`}X;N -zg&@{wswi>0^?s_BW( -zEVYc*KxMY8wV_|xw+ZU!;9mvjkrxXKC -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 -ztuk%WIs)MZrk#Boski -zbxsm^GgNdk5^3s-AG99CJg@E+ZvqOe&I@dAO;!ec)FN}6oX@vbL6QBx^+gP{<=^^Z -z!5{jf6TzzVn3d40lr%@)K;T3?bzKn44qP}cgvUwLZGI%U8?h@hZl757n`|WvX}$2P3+T0e>PRe;0um`5r&NIO8*9cq2G7^_M^xINaD#mfQ(e -z%VLKqJ;Ly?qpL4;Iq(cMj+7y(p15@^t>~kh)Z4IM%y>xqx+!zml`8bh@MmCu)m>1e -zH`+-DFa`m+Ti0?^V%QfE|3Z~*w$(IoTSXCKhUJg_4hy>bsDLI@LL9}5%@((Ebmxb+ -zVIO4_%wZFzj1$R@|0|>H5p#%B^ePj87MFN8ZEi%krMTuB_i65v)McIAfs&G=Omw!I -z5LK+j3GDakU#3kxt6D=F>jM(=&jjGlkLN2FWCzXzRHWbIW|;_x1pzG5iH5}S=VJ|-rV#$|wV(u{4X>?FO*&*{G6AX40HC~QQZi7u8KG-(|}t&YE5LiU_< -z`#lGn<*W^YHmqwr<5W7|{Y>8+7JOu-%t= -zmHfC59{K5*W@Hvpw6Kvic_7TJtYNwsH4@95!e=SOVJ!a#cY5i+E%(QD&bDZEj+>(Cv^UbGc_({k|=9Dt#zc^hR3 -zb`IFU$L@~Mhu)$r<*nE#G -zSLTe247mpO#CanC(&a85*lD$t-ov+<@PUz|lB=XpeN!lBHT95r^x7C`A?Pb#ZO$AZ -zN=yX)f`iH4MID?7pnybPoDDzaJ1?(QBeEhZ+ySYB$U82!B -z9_Fa7rPm{dg}%|gQE&oU^prRqJb!bqPBPNEMebu?%fu08`se;^CB#t -zFlBd3Yp6w6k0-#yo#XQZtYKaJrzbOL)~lD26|E4<_PK(p?p+uXE3!bBbAY*QMwzrj -zqM|f{V9^pgM?IOFw-AV8MpOpmu*&O67OtPuq4)_fn^9>uVtt2~Ks^~6ZO4JQTtR9( -z^yKkIlzS(*!=eV-zn(5>Uus@m-{b9;+Co6?5tD9WTL3Y7aww0_GJ8kcfSW1q<@j&e -z|H8>_#}d`7^1rN3-Z*t0_BH669!n8FXv{qoSLr4$4lr}QQ1^BWxddW03~ml|uR?Nz -z@Czy%6Q4L>|NOey?w&w44SILr{%vp|hgA$`CpFz`r|hRx-jE4bOoRT6(8ruYOgta*-6FzSLUp_d$3YGB9{mOGBbzf -zGm3P;)v!~b7y^s-wkLd_%lRvH*qM!Fu5tOQi$znmjNDpcm@Q;Rn%2XRU7~lS?gRy$ -z%iC#PEo_;qX5oi%{)|2>Vmoru#10e^H=HmNM=VSvA!wO8GH|WP#F$|B%!aOg7>(3- -zW_mi!!s{lLM5EMi$t9(q;hRQ`2g+JP@Mo*Uf57fhy6`hs-i6o)|NjhLgjayM`0`ZXAU$(RM!%$KT)aM~B_zU1SKgUh@#`6uBcT37dJ||^YO@n-U?(7~owBjpk00yhqf<7-)Jk3;3 -zNjVlE3ZkH)w#T+g^a7u4_iyCYL-MZw!QEQ~_`YKU<#E7c-wst5izwsWSUV8Y(?3~; -zhm2RRT@V9KVN493E_(^gU&sT4I{vmOl}QSnt)hO -zie0s5nKk70MRsjA)j?yaJym6Rj8c{WT%O6y371&JC*4Sgix--$5b%zEWFIv~z4IE} -zbC>WhttJ6cq -zNWno0z(f1qCZV1}n|ufS@#LRykFY|0NTK{5FO3UC9A*6DEblWasFg%vcei@Y@Bz|2 -zC{YQ9c@B3m)|IXrs(N|ovy#bL>xJ+Sva0Y%*)G;R#atq0-Ukxtru7jHK6#r2T^l}+ -z9{P$HvhHi2*Nou)Abbg%SeGB~!yos2Ywy<|C+i>6AG;r@x(-`Plua^x(Q_U%<8J~PL3CR`sp -zTl&)&z7WvVYnr*BQP`?=(_bruO94?#iO!X5_HiE78@I2MR}g$}bJ_#xutGn&?_BOs -z;xI?hWbADlwCyoQK{33NXGVX}s(rEK7KoKGM>r!hK)HLS)R0|H%ZDhR1ana291UH5 -z?NoBCS*)(GrEuO!&D*}X=&6qPQ*O9nfwsn~3!CN(_{EeQ}_ -z)l^xu6}MdhOJM~acW&VKV$ -zH?`jV%HPjVt^c?=xWX;l{`xDTQ1zWnSlG}BiH+F^*vCz|RK#f(oe-hvvwUQ3`CUGG -zLu2c#Fek~z)xZyJPTZ>z#=cMO%n3ZqQ&0@fqj?V -z!^2=B2!ME>>^S*e2Ps+pavMdmV?W(S#80Rd40&pUW=X$;mOwr&bH0TArVAW~;c;9*gJ&u4KS_Vst9^vjTE6ixhUjxHM2PCsk -z?ZL$%zz9t8k-}D!zxIf2_<+3!zTTj-`C|kO(0V9xph9fiPrIX9CkLln)X)uXkZaZH<7rig+RlTm`%59X@&~kkUC984OHsUa?ma -zL_1K9-;20{EmY-kD}sQlWyaoS#D1aZEuGnd(j3Dt3DqkB?F8I=`%9IM7o(QXF-x)#RA47>-zRq$bip-c0FZ21_&V`DIecvnl+?WWy|Els -zv9a8GK{|{gq^^Ff3LQ7u<5z;Rv=s*#_#!Z2Oq>Hz5GwK6e~SdyA$y<427CV!ZZmJb -zi?ZP$HM6@&ZIzDZ2nX-L9Ca=Q{+Ui9-Q)ZYB<&4814%LM-+|<{^3u?C&(x0TFNAhd -z2}7I53UM?|(^(8iCW~I^u20CC8{nUP5zZ1#tI=>UiGS|e24aZSst1g{B=#lG@R!8#^D9?&aYa@4Y=*Rqf -zhlWx^!hNI=LvW&`5?YAFF2*x~fZdtjxMR@ypSYvb&L{3D{1@&>d^I~*0teXm8A`%# -zo$K>WevMp(Vzuu>V*~>BH3LtKA%+b50T-QSMGEY_dP2uDf}Wr$zxD_3*z(Cc%F}%E -zjuHT!a>W~#yP$FsVF0uKnG+Ea|LHq&-0y8QzlDwX6x|N|+>nXwUB+FL_Het~ -z<8-j|5mw@0p`jPTT0ieJi6O@sBF&w%NJ&EEVHJySPHc&Wcq@cjNZL!J=yWQ?K?~v2 -zS)u;=^V+-)GllQtr9LL7Q#-QQYB*WW)}lOA5+S7|&K5gHUr4KGL~&}>U1hLADQU+( -ztj>9{0yw)6e4t06{r=NmsDfTNG)tP|<0 -zd@)1$M=x2_@<%U8%q)HRXD>-1`@5GszZ1i(2CZNQcBo}=o~}Gmg!N&rCq)yqnv=Rd -z8+Y)g#9G-$5y|B?eYM`!$3{EX(6$;t_=V?_{Sql2`Dt2zQjfq%e^HNFoaZ^Y)hQaK -zZ8{&6n$|Lr^U474X`1a-Z{yJ%(fY)OcBIaou^n#>5jJs2toHn)eckMbmT+X-9{}-Z -zu*qHI%$4_1XYS=(?fs(E1=vw&S5F|&rhlfBgt3I`!VsmsQb>pAvTrH5OK~GaP}_CU -z_!k`jnL61}$5wm9R_G|6*{S0Vwv0K&dw8LkcMcmt;JHx&$;nTu-4}NSI(GtvppEeZ -z8;1d7?q2RZ -zPeeV-b -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 -zyiCnY#EPsV>$zc&goA7?ri6*@{n%z%ol2 -z(=U6ong5tqyn+@%hQw)L9pKbK*ywRHQ0Nd0Dh2WgT(vVMjn|$^>JeQjzuOFzn?vI` -z?AbRF^y&yK2+A8k!V-OEe5oS=8`ylp4d;DDm3zcBG2Hyx5VbHq@()3>_EV6YGnG5~ -zzX_5fe+iOn^PO%hM)Cw{g|aGcb7fR~_{7;oz%bRz&~^9$%jfLwgS`NNF|DAx7hUB4 -zkAh@?pi~7B&XAw$@rQFGQhl?Td?gNuOH`~RA@Wci&d@3v9Lhjs^R>RDOM>n4Q_h0X -zJjAhee<4}4pD&H6eo{o!*nYV9WjGQZRj{7XsYFPG4esG3J!%CV3tx&`6Y!t|_KCxz -zoZ_%6a$ylqMB26@o>u*|vci)Y{^RlMBR{x)be!(KzF;oRss_MhS_ZP2c)fvoUR|h8 -z%Z_50kx}W1!!G;W*|Jd8xZ=`gho%6(%PeW86`xuEeUF4A&sQp0`GMl$Zze<#-BAeD -zz1rNG%LQ-+jCeRDP$sO1n$eVs+<9h3@+n45R!AtvhBUpR>UIG|6yb*s=j-(#B%$*P -ziWc~6`saDK|IRWSO{M)58d)$GORDU$f~De8!!qQv`@Bu@CfSLN#@lJ3>tXp9qmh#w -zJORRtoo!Dq>s=g33`fC0MiKXY^I<17)vB<6Y^4Iy@qKU(BG$3To96O$!xhguhtJc- -zA|>u>MMOt!1Vj_9p@(b|%cte?^c!B1z(g&9%ZL^B$>nO~su>v*H71D+!1D4o?!4Gm -zJXbSG3*&X9Mcptl$61{ZN}N|%lq4sD%M}W%<|;GHjb1I)n21D0ee#5c&W~G`+dGk-{5B}BLjt8?$C=h -z!{@&IH%U_Fr$-(q@*qfl3~OFnb9Pa=mD-Zi-)Uyif25f^mj6gI$MpVAGg0b=qT~6? -zfJqkFdW$0dizR9DmnFF-sKh1)L}I&#crKKvH#iZ6^VMn?c119o6Lef^L%r=b)f;qA -z9kJW{)=CQc%+Y^J7dt)18}4VK6GH}>u2T%p3mkLaTG>0e$gcd^p2nqx>{f8*oIz^1(EH6_L -z=mf8daX86-LWdvwc}8r>B|lrq8QeyPfGC7(b6s)1YGe0aw!Q -zF;!NLQItYGMiEvk!8?y?rxeR8>pbkk}Q2g_%If=7sNPT -zY>$%Fw5OUxS)~Ejh>=DtQ05Hq`WXDb8qE@*lKHkuS0_#$WU{~eXw`|qe^ -z=ijL0`k$zz&2Ln)VcbIz_77Cj@S+{y*R>T;;VLd}a~}h$c<|m?<*q6Hg51MZ+j}|Y -zbpCvysGv$xS$6AQVGaoV2ZQ^B>$cS9V+l3euHJ@j4*{fF_&Fpc>j&v~ -z6Ze!m8*4~X*Eur$dXu<4i^T#PW=_6vkCg2O^Y=V -zNaUNM(QeM$bNE0+O8PX4_cQ2MoXT{r&YH$MvCpcc8(3+~eMn1>au6-=%08?W*LZ-s -zcOVwsB;i2~cb35wrJE=0WoaUF6rzvLqJa~l_O~Z$-O5gNckG1L@-okUwOZ6E`1h-b -zogDTbCu~q|QJ4H>LEd-Lami|j4-81ja9;TZj(`~clT&fln4JYIv!CF?(?i}4i``{G -z`X+)dVv^w6LY8Q5r4`uT7|U`ii7Q9rUu4+-b(*w&HJM_EjG>sIINNq`Lw)l8@0|vE -zkLV=Iujx;dXkXQNg9mQxzfJ%R&zU;G#UpAYzGj1`?z$9SjvBPp0;bl{{NOG^ZpNI$*KQ~vLuu& -zM#8mxBO$WF1$7i`Z4oV -z|1Jnk$HtT%WaKK<3%(OH?|DokUj0%X(-EA^#F+q8S6~k#4jG{C5TgJe3vVLq7Sr;2 -zc|F!L`Q7NjppA(qOTg8m8wDdjOSR@t+7V|d&2SIJEvM$#nMiXKUnXkLssjD7R*Zt6 -z+IJB8oHB0x@#vDY13M*5g4^7$*gZGpE!(wP4G%#)=zn@4ceWIt3u9TLu+IN;x>RH{ -zaQ?nn!FTa1f`4|FJq&q~_A_3t^ThDTmR} -z5SSB7-YHaTSJdn5D4Uv>vNwR@1-FnoIGJ5quBrvl#f;XTuQMk_RBI>#gG?J|=WZuj -zIYf?OR%Ko57T}hp*r(2IW+>yQ4q>(@(3fM{De16Q`US8QqXBK- -z13Zbivd=+H`D{x;bdZA1QMH1t`@p5!VCPkKz`1k)%-CUin3F*f-&3X40Dcli29iRk -z=t$cwTjG*o9+}~htktpxAd>m)o&d5FV>?kQr9ty}mzdvGlUJHxVHk}eySAHfZJ57gyTENcFE)WJrTgQxQ;TE+MGXu+&j{J4-%Zbu%VG03YNYd7A!=)LP}|q0ZYAK|cAWCU)jOeDi!jv|0o;>634YE$A8i%{Q?$rAyrb -zO37Zffl6|7-$&DA)TkJ$55;;CE_ADQsQaxH1x&9fegZnYsyI8qWMx$Eww^wip?Ld| -zlg4LFeejXNf3BTN4q#;IqX|$-kW)$4kxMtAA%bQBsr7t>!hdc(8)m9&pf$V_+FMSt -z58tjl@W5t9Zde7#f7K!F!G9|Rch!+KyKEN{kijnEXj$F4rPoz!6rU%_vC;|U7${MJ -zfU39bAeA=9on&M|wD-Tiz{dgKsNy+*q -z!Uf_RyT;jXKI*X#Vz~4F6`Vz%f;03}a1vq7ApTa9H-M8vz2p28oaX-#oFD%PPRdWg -z`J9?|_mALIHt}YQoK{}26y+lY&6lFp-SZ|PM{nA#LQ1&qjGQi~Lq(9j1QIk?>Hh;wxeNbm0pcC!2x^wt<+sw(lGz@DV3cz3!VjCNoMv{Z~yoo>-NVRHPPVyXSZ4t}aq87Pl; -zDG*>nQM;v$V>c;?YnkraZ7;+Q%TEgske4+drhXt4kr7QcL}YQ(ZuRBSrS2sjKdPQ4`X-l?_3YLUnj;xP;vmK!1HWCPBqJ6Q -zwo5YeO^iaVg0WvI=8AIOy~{N6>7{B&%*e8zU?6&rTU7=)Sop+jQRh=Gx3h&*2o}*4 -zrenjpdt``EEagQrx*<=-r@r?j0TH40%tPUyq=%9N@^^Do4SQH9~ALOJ*^;+z?d?%jdP{ugo14gL?r`90cLi&WuUsw+)j -z^>S~?RdJ`C+5X1w0z9*G1xXlt>479mK@y0YJutapPj9QD?;bOwog5@EO;&>l1(#J} -zx62}%Y|BY=6Bop2sQ=R@Ddwml%e97pL}W%OO&kqLCDosQIKx-FLD}G(wa_?ixr4*8 -zy-W2>$lvJloBvwEIh;bc_RN5j(frvvrJ$_%L>yQ`H6tO*`XWX)Sv}cuaoFum@#5O5P(1&EoKByR^L*tKauS`G -zenL*3e;}uky@z4o&fkzTq}c+aCw_+#>o3Sz{}1HskFf_$l`Klo`5STy|Aejm3v%Wc -z{0%u{+dd(uz~7KlpyO}I+4M5+{2$24st$s2CBu`7#zplP-WFOU=UFUV>9 -z-;lH4|6j-%cMR|nf7ZZ&dEN9*ZQj_iryKJtFsv%1D6Ofy4hUSH*OaP1q`$G2kkTp0 -zUyMiY0#uVrdo2(d-6^wCSyTRyME`mnn7mL*Zebib(jsI|#Nt&c{;O2=44o5fX&jfh -zI&DilnRHb=x#xcB9{8%>9Ui3=PrxN;~NxS>MpRB2N -z{-{}Md}83~nrwfySDvRja?Mj_8A;+K`W=v}uQk{=PM$vOO{ft7ueVw6&D?M8;bs`4 -z(2MuI7{YJ;vpzIIJHw0OSUe27h%zK`}~Y6CNw=)>C}9JT0-7n*dq&tR}mrdf^Bs -zFqrmg%mG1vnqUbyd7F3hz;1J%7QP6G$sj~H2snF37?y4FvlGh9ECunKMxci!KFShm -z1=vPq(v!+EAt9f_$&3r-9X%Af9K;4)WucMxt_KJhMQXe{>#L!vy0e0uV6vc3CMC$h -z-K`p-d(n+aK-A)Symcd#RX3EzoxM2tPGBmGE0$vQ4`idR&1|m!8F7;vz-KVV -z)Ch?p(rh$QYV$w{EqUV9+<__AJ{8p>QKLE}OIn-4+iw|ft_<7?zkW6mp+`I#{w|(+ -z>=zx1?#WG=CoR=Nh}jUyz?3x=0^kF%kz{+*pU_l|DinHnC*`~X^rJf+1_>7Yqwrm%TSaKRYyHCUz(6|H9(J&Ly_QGnJ0Jb -z-J~tDywnKJEqNx2$58=YWu6-`b(zX+JSt@DSHL1l8V3u&qP4?9*FqS50COJ@d300j -zDxUq@lyB6VfwtP73EzG+?hFKcxn#s?UCcG^h_^9W99LQo+Murzr-ZD^CFrzUIy;Ce -zxQz`YzzS$^0?cboZnmh}36`YKY`Uhd;wp)ZdPuJ+MjT27quoH~C|&fK)@{~hHVi~ppY2}J)=PGLt)-jl3E-_r4aD5tedEY|;^ -zoWlP_IRTZ(B^XZM{-vDpuAh{%@Gr{QQTRV7XTR;=l#}OQ%K7yl%8BA%@#TL~PMNJ^hz*%KbOxWT6@!{Fic4YyK~kGlJ*8DChWOYi|@gK^G^AF{0 -zg+8MHn{o<|b0|%5T9lE`kdQ`49sY-MR)+pJdw -zBisLra$<8OEuKAT|3f)((OUuKNUQ`-KjoKw5l!>RX%qr6kdyD_tT)KERM)uj-RJyD -zJtb&d=_`9jm3KnhqAL;P=$)a -z2+KPhtpUM%AndyH2;SDuGC>#^-uh#LTOI%f6oti3&=8zeVCAq=(w0FF$=mq@ba7_HqBwe -z3L*VL%wf(hSCvvNNNH=7ZHttmHAq=(Fwigo`w=lF6&>DY2>VD*OjZlMZwu$cgJ*ps -zAWoBSbBIk*p>zb3S5Q49pq-nu99lPNfd_*`DCg>X0?Q3Ew#4!Nv%iB`0Gdbh&?1Iyb#*+bX0*DqR -z9)BH~K2StrUhB<|4(lHWOXudjbwp9#*q%wTAxZOFs8{Hf+LphNUJm#uF -z;Kt~*=rR&4G}W@K7;Nxz>v+M9jzckE51ZP~r0qvRmTB -zB?$d4`)!tMi;+ErD<^px#sinCBxGg33x~dTuNI?2wy)IMnxOklrlED>RnJlMhUT^3 -zx90r=gk)_p(4H@Is+XHmd4@B=%0Nyg` -z_%G-{rlTKGAE`*?UV0D(`E2B#8UD;K(2cN&X}m*p?%z{nS&&`FO0tuFifJewFjQ~6 -zAgrpn$=@HRPij>q&zh2m$DP2PE@J0qPrTvl=9ml@`;75}`guiy;j5EqXBzO}4X?|7 -zfCj7LLw~5=3b;IM$u{-t?kxKSFmT!L)^378Y+|8PDrgw9oz;^Gl2y|P2CGJtOH=Gu -z&K5xxZTEU1>+4Ofdf`cgne)iVS#nA>reF}-xwfPGIqcZ2e{E^aHAzuo+^uk~>5K6; -zyJl#AB8YUBjXvkKvsS7^*CYu=Bq%2z7q< -zyv}C%t}80A8pRdbFN%3YVd0vKcmUMz8BaL{^KtEIGdWPqDL`_Tn-+9lb}B_NY08t_ -zU_L7du&$7N3r8p7;xQPvKY}B4U^?>AulvxG9=kSexc=bG#36JSdL{ArR0m|)3gA8qL>>rX2Z6t>kdWgUs}; -z$M5&3f1);|*K1$jPQNfAMZ9j3{WJ&4Pa{5XVW7+GL??I06R>q6#+{Quovx;UGXW;b -zL3D?-H2}GJVEr5#R(0b0jB$yEe)6$Hf+pl0nxtfI(rPmrA)) -z&HN^1Ck9;=j*s3^#(HB4u4Tm%19w4h5=94Xm)|x-B~H8%uKNuNDAXldT~MYhKQ(Sl -zQX-J8BT6PUm|sevcL3IHahEoLOY4(ipZOSJ1!=9+ct;6%dR@R|scVsawgfykPZU(X -zl4rR2-HxulbzUL=LV8IWrW(auKj+AvMPg{St~E)LQt^P^Nrzpk0a6JgO%^hN_a^_wbGGUrfSQb5Kw)XHAqcuBeJj59V^8PvBk0cFUMd^r0Qv%6o8z+Qbf%xF -z3bKrNaQBaO2*PkI<_-kZXM -zmyKx@aZp5#`sYlXMHhe=xp7|p -z#)*@RL`^}L-41FAh}6r@n$gg_!E${#r}u-n~9K-^g_#NqMG}Fa~B6;6In`62yq+>3a?%rC4^$p_fA9qHJ0SK^)9QUJ-A|_okrt7BbvAk{!DG^&Kp*-V~>6tDEqf -z7q*J=`AZQ1r|k1`x`_&(;K#$s4dZVelx7{J^)X#wp~GZI(sGR;Y0s}4;rj@0-5CB6 -zN=Q)B14BO~_{2Tk=5w_5wb{Fd`RWG3@ZcIx{v%HMEdBsC{=r$dv?0Jh64Rysiy`;; -zKm*m7l*{NDdT>+?qO9>X1&Af0u{_vEK`)f1P`%Ju99Rq$N79S^qp~xak@&E<>8=fF*OjPi1 -zk8iiR=mR8dRm;hei8l@+e4E3P$pc=w+_Sf;p2c1m-1ZgHdd_}_toKz^L2J@DRl3*9+(#G9HTxb2&3uQ8vr0UihOd -z_E6VOYmuZ{+6P8;AsewqRLqI#wl>m_5B2RI?2DD0{1V7R@UmR3zCkAtlvE2-Ob`gO -zJ&MP;P{O?hMPbEgV^i)6ro=2*b&ymj%>t)7ucik&xMXT+@%HuIq)?lQsRFIqI;vie -z4n}?3pS`tLR}OXWM`qatQ%+q~{=_h`+iRvE=Dy8DiSuC-KZRUYpfto0+=`c29AL(` -zBN%~t)&_IqLYE!)3xo`^b$GnCR*D--WFgSGniKgbaA|Jv_47o+smM#ZO=gG%r7?3m -zH)RbayWT*TxuwJSv=jrq31DV~DA!Rb!rBWYNxb~C3o5c-3RvQ~AWNDvDSCfHdWc3; -z(2%oogsdk#)`kV=`KM%5!dMmCdsK?eheEfzWu^Oz4(^tA`-YrOo|3%U_W{6$#f80U -z@LpRDLH(>9lGi}^0x26rX>ipS9>!O3O?By$WG-Z4)!Oz7-3LpEEL2B+ldqt#^ -zpmqsl8qpuUN*OG$QMFO_S|(A0V{qxXlb0QpirnV}k%}up#E?tHOpCbaNoLrr#EB1O -z1WbjSi0tDS3MK?YJc^~Y)z!?eS~k?fcQpJLSQ*e;db(Ow=%X -z8h2A6S`h+&MEjQbJ|NcBCq&K`TC5E3o1-1R5?UxmQ}n|E+QtOU0NlMzSOu^cI7W(z -zZQpZG11oDeF6_+M8Zxx=jd)YXyRuf)+#BfeBaXB07yRxVc2IdH^)5NM5_h4w^AuA<<206Bhh!U>+v9gNHJST-Qoso~9<5#V -zuoDzjTPmzk(F13aC}w^`qdh-?)Wu0XdOG5s2Mda6pLUO=m19l8mZ0T2N9SG4+QpBt -zqUyQmTSghKsTj{>GutwjSFd_$2YO5Y#JVPeq>pK2wL)wrRc<`OX$i~l9o<^M+T{EB -zokD1)L3m*Z&!$hOQf1yfd&O>(@p4Xyr`S|(J0eh~>14>IZIJ<8=iIESz4C1+&@kep -zEF9|SZ-{-{2c_jI307mosu!)HjJz;8HV{Q$U -z#<&>(;fK8!8Y-*bh>rQW-9n(-0v?qDv~ICOHv}BTh-RI`JuP?o(b~Y^mC}z1bVZ%d -zeYT)KYS{FyH$NT{KQDp?V@1QJ31^5m$=y|wM-}}j1|WeB=6SjC<9hD$W4wsiJ|`vb -zya=|*n_*h!%%zwA+FaIpnSxIMTGp*6o*}qmu?=#rZN}cW2B!_?SX2EsjAU07wm{o5K -z48wIep=t{deXSAk597TC9*gTyRZR2`vA^2=vYyLc-0=%kd%q+@ZgDWtV+(T=#MZlt -zPEl}`6PrXC0#%_eYEbN)Q*TPXLkQIPF|>3AX9q@PNyq65*G!RH;y}_Q+B5F(J%XtS -z7$bbnLen9oc7bRb%r9io1E(ex7qD5{ry4t2C@b{{gJZuh3B2Z)BNu2zPywgrfCEWD -zuVhru%ROBzWZ0QKoFYi9*NXn0sknXXP3*2f?4`3upLL&E{PgYlyLKb2dfH*y;VVXQ -zEV-mu?V$olt*lQc{5b}t-$IF(H%T*IofnB)`9s_|p?G=va-!#q)g3Oz6jN=ju82Z7 -z*0E6=))l}YY5!U{@N6rcBlByv=k4to>3;}P}LMYzUQS~a^jL -zvIUvBpUB!;a{Wj?nrB!U&KKzhe;`pAuF`LqKwa$X2r5W!*zFhAYCldm%iz@|si|5k&5Rq7zpptOl2>~m#Ea!kXUUkS?kznjK|=hRlJ-cmzv2WMzk)lG?lfDj -ziMJaiHk{#(c3LE=G0qH1?LysUh^o^^&dBjh)g$)T9TvAk&Jwz%ucf!tT#W2@^i1iaC@L5I~>18D?>?q;>4*CbyCa>t(ODL|mhN -z5!WD?$`eaz;&>q|D}-Tl)!%BI)7yL|vl$ -zV`c8LFFPKab$jH(m}_#*#o+?yetu|K5}=9pL-}nK#xIG4xecM9GJzBC({5BfYOCH* -zCGXDA569{>VW)sAC(nKft%Ut$#w(JAhQs{9JIP*HNu!A{98t&ET$^z@X2vmdm83R2nwByWS`=e#5Xw$?WSWU66G5hnf|W%f8go{AoXRwC9! -zcE&DTPHe06TWP6_`=W30X(67&R96brPN1i(Y+o)bS4dXN5H-akXRndsdZdBhvv9Pc -z0A}_Bl;@XH4+J$Q%q?j2E@>_&tZ@P-^Uk3iuu!K}VkHLso75_-w|um;&*h}}>ls^3 -z#)1&gQ1!#P<`Xqy2KqK!7cz(qs2J27XFKhdCYyYx5tj%uL1-M%Sd<@_+hB&MHBUb) -z*W(1Gz0uUAsdc3B&7wLf%|>igNGw5Cnk_RL&Lg~&Q}D -zr;YSS)f}l3KgD8cHvfoR%6|Z$h$fx3b%2ooPi4t(csH!~uI1TWEZ@MfmqZVGp~B7g -z;97A}{c}Mj5L|MlA7-@vLcU&NHQZG@8eTI#8Y>t^7o<1RZt3Nlc=Ylf@i!ll4JmysDhPlXnEfD@=2wdi}80Oxvtn2uhHM!V{- -zRXI?fdnVL4PZ<_G!GT2-@%@e*8U?SAg1G~&uabwtbVNbxPA(77@hy=VYQ@8%Nkw?e -zf}s(H?WN|EMc2ztz_oU3MEmXA>8!5?>h*{ey>dLJDm!OZk{7SQdHGj3R32@^5h{FP -z^U$dn>~L$#Bc5}~qiyapj4}$B3@X&`Y&>DaR7+nU43Tz1kRTtDNvpD)E-qzr2-$X@ -z6jlMsXsWihmu21oDS9adhbRF@rff2Hl6i)+Hg#rjRekA}&>*XU^+v)KAg-5th;B1g -zB??oL5g^uyjIgh_Zco+w>~9mO79z^(OtM-}$n^Igf{4svB*10ohCrk1E?q@fWsck} -zC$%m|MJxbfwYVhNDGj*Wp-R351$+$H@!E~Fv@+CceoTLTb*N0Mrx%DhAG_-Vy7d7F -zIz*@)C4x7@F!qM5}oJSPZJ4 -zIl1aw5AIvaimqJJm!-qla*TK<$rb)ALao^8IWPR=aaICYM@x_Tps(T!$K5R{Rv7Yg -zxQ_a#9o;G`-df`T*TnL=EyJ-!fO();2EyL8pET;EyfUOQ6;OK+tDrFmd^f0uWNSHE -z7JIG6fYy<49@plYWGVMq4=EQ%_<@dzU|L~tGu~Nnh=AL=0JPn7H(WkTR%IE^wnIZR -z53*}8i;v*QI$MpDRo^@@p{)LeWSd8FDT_6us+Gf1g?)ISA2KzkAy>K2N=!!P($z}s -zb(Qc((2CxEJsD|wWdpJ7sAL=*gAEaNRioeHy%B+OSxBXVF>!&@3a1m>Ol7UiPB`b* -z2oLMQ0R(8p36(thlF0NLK+>@&6PoTFmaQaNt3hoJj -zl#7Eyt;l`mlbx%j#cRTDgRsoxr)4z$y)Q-fl_py`NNlU-gfhC9g%rk@8`iZys`PIJ -z`&}DRq|jh0Fd1o7XP0uPcD~!8S4d(ktHYjY96f~@^FF21d*5cma?)b7In**qSd6p0 -zj+=u3O`f+$U$$6Rk*u2*(u(kf<;6WBRhW)k&Bd1(kT~|(;y=_U@A?Jx(SlEdzEX4k -z1m3u@u1Zj*ho&MG8#JN2{yq~2B`g^wl5=N=FDA&eL{e2Q?rr=IvXTnkBeEZJ8f3ya -z?>2!kB}krit(1t0vb|`a5-|sk$1ENlG31&nwg~75k47RuTLWg -z?r5r5O@*q@H^fd#8s>kdV;aR`Rlg=mo?$=uF1Oh8#X1L9I92z;gN}Pf{zaH>8Yv74 -zU?wY-E!#>Uzih#bN`?#v!4C4Z=DyWmM=P6KiNF>F*eTp8A$kjN@pzRttLcHSBrEM*|a@ -zguo4S&?#~)wNDaF+VBB%q7Q(aZqK_yS+oj+#eu_^u7S@!0{qdhJoewAQ+0caxU9~J -zXuqN8O=1JzEuXnIHR+$fl{ -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 -zo*_+fnh`e&b~|<@w5n>BzfC*^g;!FIO -z1(i4lFYt)5%uPkX4i6CLp68; -zG0c=z2BPBGza%HEZdUI$whLu{Tsh`w%Z=~2r18Vh(M9aIjB2oe%&_iQL>GgQdl&c_ -zLHbXf-Tg@X;Vg%MUQ3v}6CKCG%sOVFsQ()w8gCHCK!YE!j3M4>CZklxs(E_#kW5V) -z6;Pc!!)>B)15HmFm*oTsueX|OmH;l<2gypYpyDRC*U%xJfQ6+xcznT6rb4lIZK{y# -zNg49dpLmDIUMSB}3C}0W#hA1vM~s?7OM-+($VO*#oICtpl;+~Zq7@lTi2ZhH7HzQ# -zr-=#nCv;|K4OJ(Id9qomt4o!cC*=XkzL}<=gofQ)h($fXXe{v-ra>dM7<WhGe= -zUQC(0v-Af`xMVI+$&rxC+~;_lrB*k6`_ow@h%}!m&a|+o%+L)R%VS50_eqLA?Nm0(&cQgm -zxCLo1SV7Dus%J*jpQ*Sp+mk2ge@F29tWr?8w^*#9$d4}w@=8@ -zQ&otRjWe^{F^nx2pgC_)uAo(q)8>P@R28NVi6PUrdBEJygc+Cy@U@CUj~~sobkM)~ -z`UX{2!^0R^-Vl#Q9I$sH(&imFV;ikqJVlSWNEdx|lNQS4>NmejE1mdF*+@|I)${rk -z)WRSs(&U6qH;`|^s|{UakG=el`9KJyJa}oPWP2cWuw25{Di4u;w{}0 -zzQR5$i2tt}m`#w8dj_mmBV>oIQ`fYEUyaRhB3NiGQQRdKCeG+xs} -zPh*Y?b%Ud{SzN9MNP|smh|JQzk2+qlyXjKWZkDp+ODa{Qhj3zO{&9C>Ex -zQ-LgwYPuHwjPwfB6~JJ_W#EDMvvYE>D)L=dc1BUv3W|qB5Fx30dGibt1%9-ep0mKk -zJE?#N+Mn>-87% -z;c5#rfaElU-cR-K8_ir@I8nlXF)&^>ulWYm!)>olef2`*6OUCdkls_}`Cu29>m~5m -zst(hHvm$KWbivuWs@3g_a@1tYKS#9ZuPG!~o-i8~MOuc$?iGaR6gQDb#yV@iK&6;%P!3*Toc>05#Gsi7+A;22jSUOOh?4B& -z7M)ODjpwu4F;>Oim9+)X5+JCMl#0!wTv~=9DVI=6x-QbA%Cuz{WfI|Wu%W<;aX)mK -zJMjy0to4Niai!DT0D(o{>;TAf7a`3rJ1a2n3|#WK`rUNa(hq|?dh>k1{K0Q1AuAPU*Ysx?=zC(Iz(TiQCtu!itGPRqh9fapU~SV3DY}&_zCC9wQf8Lb%*y -zx5Nv(U>vNnN`4Eh5D* -zr-4Q&xe7)_6sW%+7sMQyd9klZG4){{$RzgX{Z$2%TIO6XM1VjcBtqNrrZ#!;&&lVx -z)rmEo6iCsi7!2-g$$sSm{*fl=qU>^~w4Zn#o{+{2ig}<}Ni0aW&cx5n5IT-6!0ql= -zF&rrYp-c+m5g%nnDCWj-dB_rdkM7eQK&6sYXB7_lWDy$kmTR2EZR!4;*)X|G2BfMT -zPoZ^DIQ4ZGi@@k9?V!5O)h|It++KkYQG8D4<=VJwCpQ^B*c#q#Ootwqq3F&r8z^cM -zoYKd2RReIb8%u7Id>Pzrd0xcH_azZ+$bDiaiR;<(6i8sF896n=%J)1B%wn-g6)NAk -zM6iL1lV%DTg)_bv&FzF08}CD;$$l0L(_P?skX}LVq{^1(%m|ty!StCteB1hM5+dju -z;w-$yXb=X?FlK)7h6oIYr3qQkX`t-H05`Q((G0&;ZiGm~QNM`_{?dJ8Uzzp6p!(}r -zaRH*v`Gh*#P6tlFH}Wx~PZ%A%t-;=Dz>Xxr6N(Vy#(0C*_3GQ?QZnB_arF-GdVNQ5 -z`#N*XDa9iCj>rg>Kmt+Hgh&4x1a@y&p8iE(l*s9+GCULV4|KSkXw@*eS;rd6s0^+= -zIs~lXpD0v|kS8Liun@CwAhZ;X=fW+*(C -zwVSsC90-HtF&*`xrw2twyhQN(85f-+kN7#i^QTY+Rlrir%M;b|AheFz$T$$lHzo*a -zLXg(MFSCrb9d%NpW=kjvZeq$Tbg09HzziX9|DVp@!YPjC`yM7(a1z`hKp+GQ?h<^1 -zJ8W=wcP9|s-3jil%K{r5g1fuB+rq++=ktC4g14$`s!z}DIn`BDJ=1+}-vh}vl4-el -zs$GcVK29-f`q4|aWEWd>erm6)02hytkl<3tUS{c9dtVon&Zz!*o;f5v%t>KqXq0Nt -ze9}4nlc3>RkFI0Rzv3_HNo2HzMPA*!hHhek-T6R#V+0&T6(h3kxxbaO$+vR98-+8X -zXnqE{RBA+B9}^lzQK%3G=Py`-pxw6>pS`=w1;nP!0JiGSYe=YHzB0#?a8UCFY=2-O -zooT}Qteo6Xnxxxr5l>?o*zG&#fc0q(GW;M0oawx?yCa(*cs__lGRvr}45^{X2y5hl0j+d-S6 -zfp&=GN!!GR@Dv2!Bb7bX1Aef(JAI(w9bstxFHD@=vhs -zu#$G>xcy60O%~>_1sjYO#0b>1mf43jNBF)NO`d!AYCdQhaDspk{Bb%&G9d`Z^I61~ -zc}O3Z?Nl=Kn?CkT4&v}UDB>$E_CAt{%LY3WKI{-a7<7s$wYYOFT)+V -zRq!Z1MZ8h!5#nH!3Z+8?+ -zN|Ayz@BHh4s>58Oon(4W4MvHr{c -ziYff5gQ>f}ajGT1_A<v&!(fVZ$#16l7468RszqXZ4o% -zk@c3npJop8K+9xN-`QLItDW<$Lyoi5Sd%>{lBgA^%dWfm1=0(#rv|(b5DWjQ>lwuK -zQI`k6qa7rpAfX#5D<7KZ)!rPwg;OouC`WJuj -zqgyZE2x0Z#h_>~p(m!sDsxU=bJ6*?z4b@u|*tN6@!NH5;loNx5;9-WkTAfZsmN$@&wF)71v&TAA&2aW6mv% -zrT{tmDy+7sg;#+YN0Isg%qs-HM`71-qwq^dzbG8Q -zQ-P2`v3g+SkEvL{9@i-JPhpD;jyknifobxW0;?Ifccxhf>4|98U0UrBV5U)9k`YwjDE$o9p^YSildl-O^yUpC~xM7o) -zQ$&&-YfVQ71YCMsrP&QH5L#|b?qN(+2M!Ra0u3L>S6EKE$IHU=ob{~c2_vknyh<<} -z90l@gz8mNVZ_3>-&r3!oh`IiF3aDOrCR)z$@^|1bVZdbM%*dmHsZ1y!3VdzE4$M@# -zTKiafin>UzN~tj-Fg*2uQ}6>{zwV%mT%w*eVl*gRMi%3krN_eeS1In35*IO*X?;2a -zMni27))6Akme~;s)^et(wh1?Y4ZV@n@C*7euP6DxtxWJ(OT-y}*jX1`&qP}J!U -z)+|>hTultFW`L18+mc$NbZ-p0D=84?A>0hpOVD;xD}Ke3=VTC@N_|O6Z$)HIx!2VA -zMrN&GI0TQX8mYQ~O~C|Aq|kV1VytToH*<#JebHou0Deb9d(*5o7_Dc;Ye6t!5iaO# -zAYoqQ8WGryF6}H}K*g?wY`Ika$|lSpWFKEu8l1I!BHQ~Wt0whnarEOud7kjE!Ap#lEHQBs -zS>VZA()yniRV6W-M1nc>X7i1J0H+l0nPbb$c(G6w?X~B3PYS<$MfPP7POXEDBx~Nk -zQ`P+X+cT)rz4~l^Wz)B(%%KuFsaa;G`1jJtJwt_KZ7kBaPC0FG1^An-8uL)fcCD+2 -zq!X8obTKH@rUm}6m+D(v1n$iH!f{V?E-%HyNnS*WKE2T|9N -zc|1yfH^mQPdViSBmrjgA-RgimMTrxa4kF9pq;4pVCHPmsKf-q+-J$6n9nQz3%1+AL -zhX;bUvrIFw0UV3~(91qA;w#=M*gHH%6~5@5j(*e3=w7IfU;T#{!f9`PzM^$V-o-=MCQcVR(OMvQ^4u*Sf7eWh$m~EDQtP} -zgGsSV`)o*BZCF`KVoR@$W|J^WzC^wPqB(JYv*B-=CCu>Za<$WV)&%wdYdb=?v8?od -z#6`OFjm^3VBfm*(8MDns_cSAP7aHq{yZ+Kh`tIP26&CP*f)t}njOBA&R8&5)?I{X( -zBvnrcJ%v+}F)f$%Y_^&pLgJv;U=O*QXYNM?0DW(m-*`}y6nf8aCczgm6ODQAgLKdnRashok^ -zXdEww>IV;gUT#5|^pp~Lp-~&ne(Ie$R-m&3F}?$rcSakg{6U4!$vy5@4-3tkbSbnM -z#AFn-()!pap~0M=L4ot>;`3iqaRXvZJudzlGJjJMwi&dF{^0dwk~xAW(-i1?d?JBm -zTQA_-T;Vh(kPH1#S6x!py9X4#31+`1rdNz -z#^tN_&N2ly*@mzm69WPG>vKhr -z3Ydi|q*jZ#`-LVy3Q2YUn`W#DS8aL)DcwF!bN>KZe~j4y@qXBR$dh;OwK#TO)%&9g -zO)rp&N{hSk_kgc~`Ub_n{`8n+m`W}u9)UPO7uBc9I9)|pPuI-MqZNnWu^Pyz3>SW7ld;v -z)0g@dPCp4JbKX-8bR6k^e)7!cuXyc?anzZ{jLob4j^O}0@gqytH0RLAX^EX@2aWH!b&;PY9Iex?Y008wh?DIYj|sI=4)+I~^3 -zb-Meu!~E-1=J;dMVw<4*D(DagPfk39jC?P}5iQgndD -zF_mv+@DyYkd&6`C^yd^fce#a{ih%3*yYi)d!%#-CG8I3H+MprU$~Tqb|2{Sg!QAK% -zqS1;+AWk~uv@S^V78d?HR2D7^HHW$n|2`Pwiu4)o2s@Y0lznJEmNlupoukdjjsYtqFw`Hr4PA}dCIJP-&V$NKBt@gQ@>7`Y{_#YkIrLSE-RHOJMaS17v2$URGY -z_@QtxUSS2ShWmGGy3%TZ*75oa<-0#(Z=bySc6Nh}rertGfM>$Q)8upI@`G#hLsJva -zrZ6w|&RqJrK<*X16F(Qy&Vu@~y&D2tp1RPFo4sP2`#V{q<&${t!;faiJg`*k-JX&p -zo(n(E_G<_)NdM&GR=ub{9PF|AVmg)EJ4!&?whK3d5jPf-} -z=S##1e@Irmp-d9NByX!w#s+PnPJHQfV%zUks+hy~@_V~VWuxG*A>s_O7(LFIicL$Q -zv#KzHY8A1F`*?n(ymBxT73R;>;J;@HvchW2L!LSW_{^ -zHH1Z(5@+BJIj80T16}bGWa?&imZ5YsiTZVPx_;+-j{Lfq@1K#k2gm4AH47Uwl|?uL -zrl4&RDVzWj@{?v8(cO0{?`*W(j;IZHl&p -z;g&?F#sFoBi8OqBh$8+58nk`7HDfkDt6Uh}>3X5QdlFzaL9wd5`24{_2?vAhS+M^` -zdAn1UCx{5-T`4>|pF|z%5~cL52p(z7QbAio9h0G|c0Q?2*sL2#$~d?pej0~B(uuc5_`y{QO6+m4IG6r##=l}CFz -z!-+(DrT4T}4MB%@xKExC$h>767z2HRqD@THx=o~X0{RR^WE>yM5aP@*;Oj}=yk=1}z -zy;v&e?3=gxq-m!)i}6O*z@M#7h0n)7)^ZExW@fz4x&Fb8>@|KU!!f|1PyG-@L`8NF -za^4YN7NaA$`}pbV-SoTD@hItyt$R)-d}?|r!{&$_FM?;90_w{@oF7m#g4_wZ`m-}G -zEmY4hW=gx(YWd`u7oCFxdIjuZA3$z#8$tR%vzE@;uFJ^F4fTZLGJKq_8bnD#`Y#U% -z^>v7uEe?eeH6~;I>=bG9IL1yuN?h{pHiJ~phzqrvj6nxit5n6Gyz -zMR8I<#-skrdIS}}0L1eEa!_V6w#01d@H6oT;sI!`6}fQ(P3AV2=O%+v*dO9wZJkHv -zx0kA@sDqKRW+#DuT*A-1rvk0gS@pv#3{SxbA0Gc>_~Aj`_un2S*Kh8Hs-8QV-Tg=5 -zC0mscbcIrZ^r)$hX*IMtc6!Clx -zTGQ;2(7rF17n}oM`fpLBhLjFV^^Fs*#@LC`bYE+3dhZHfhqgBm4|V$xExn{JpI&;* -z1YRM`hZfi-IK48*(GcW190KT)zY9=y%ZjX{1T4EBz8-D(9Zz^?EnY+KnJzq|B9Lb- -z`vN}2heL?)Pe6BY6?Y62-?i5W@skQlIzRNJvch-?P8|3)!zcwBhjtmxD0K`wkp+?JgYxk%{DD-M)p5c9ICAg`X6#Y+Pq(;U{_PKp5AO7!p_qn -z_P_q|-8|pQXEdcfnD56TEqoVt -zjN8OzsLtI%q$3f}Ok}w_Ci^K3pijUYkNSAw>ctixSx+SKz!FT~aY|LVs>oJ=9tMLI -z?jg>QI)(|M0y7xMC3dIba^WH0gOnB1iGjg9K4?ZY*g3r}G{(p34+N(k3Id5%L>iJ~ -zYtc^@D34#g4!1BJjD@^E9+Fb8`kALI@%r}xGEu6?$w_l*ZM=d@t_L-xy<{@aqHBE3d{sbzY$kja*st*QjjWw -z^0%Me0a+d}{g+I+rGiN}yTDVP1fxqhZo9SORA-G((1rHl`}%z_6Bd76^7_p%3 -z#T3OyS^YM_UbOwqrzFl@t=VVK*e{QJnjMQ2b!|gSeU$vF%_ndtEln$}_)P)&NA4>t -zdl6B0jg+(!&yD_gl&`pL`hVneV!*)HrIJtu1ye8oIl;I50-Q&$jprHAHC^zm%+9p3 -zc5?2WLpsCmD(-gBo$9`w|I>Fn7Oc8wN4ygnC`j&C$+qy^9i}Ubf8&-~*ZKK<_}c7{ -z?(7b!$4PIj80NEb&aHeL&yC5}&RvJjcn0V@3p1d4N8WeX|Ffe%jr%o6?`eVJ(*0X> -zjE=M7Kxq5T{hH2k-`<{rLjO>Q58OVZ5tg|m{TYXqh>C5fm~M#TfYwDwPE5E5RZfiW -zvGkT+u29+_h6Zj>!>k`WK4LR_EQ$1_0QY>%KN~*@PBZc}2NxomB2FwJ4NDno -z2T4d^ypqEHgqQ1?tb;DtO2dQ|HRDPGs& -zS)it^>`g^n^H@hsnb0F(;$J3xWdGm7T~*EEtH-&s!E(k52uG`pV0vTKoNME)(4cg6 -z8PJUuwqh8eO#R$e!4z%QwZ}@8bu*`DZ7gQ(Mh~U>^klCK%R`7UVJiQLYXXmx=_O4D -zE6;hMKiJ^8VPMRk3{wV`f<9X%hynJ#PbW_eQ#N3LzSfH-J(Qo;0%Pt_;B|V(!+rnd -zVMDXO1F}Xq`Y`zM45V(!BHKJFt2;LU$PEAf3tMBpG1-RrgJzpvuUfITr3?3oOK{6biACnjMjW6qipS{oyScv_(i*2AEwLID8=A21#<( -z5yiE|+CHXJeGL3i0H20Ns^Tzioi9+t*|j@swKg1l3mR?J&!O%yb6iOo-VVJx`B*ZW -zY2*K5*5Ks~`MKKQC9hm_rtfR#`0{wOex=jwMeh(9G7I9?7vj;?)pwN^W{EwX6eF(Yj8CCmQQILOJq*&>Jfup&FKv -z&Rf2ib{6yXt5)XJ0qoO78U-`Ye|P(D6CKYzcvh%l9`E+(Wp*Bqu#?3yWxsw_!1S(4 -znDze$HTB*yvL4Mc8(wd2y4JCs9uFJa7D^Zz=1}6~KesN$*A>m&Y>wkPV61%GyuGx# -z2klt2{@myVEKJ9%b)^Qs)L3@^5hu8m8A+pw5l1@Nt%Estk(~WSO`@?1b1kLtfZYEjCrKh&@ -z%ey!TY}7GcI*Dcy~ra(xhW4YjvuZOu;`I0N5!@3^=<|D_?`e|X(r!i}4k=1SDL -zQJsR@QGJK{1&#Uwh2N*CGJx!QT}`O0hw~@z&)K-XXdi<=C=mjPp0v3X8fO^Da|8?2 -z`yWC)0%J;JE;K}!Wv*qdgZTSqB)uO-=+7h8P8441T=|0tUrn%0Nghem2&#>DC*i8Z -z)cMaRh25_~27OuTZH*26l -z-fx&E!;kyMsHsT_TE>k$7AB`2?%mCBq<8dQWekoKRz7VL8fNa|dIb9(%vkfOdExIv -z&9ul8piw^Nn>p0Fk6i|%Ny -zTzJS_75l#q^V1W?GZM@BLu`-p>5-f+Jho>k=sOC#;zNl&P2s6i&RS*mS#>Q*V -zNG9ZY`r%j{ciV=@@?=UfnjH}nQ=Pa^_CQFpaJ_` -zrbg|TL$Ihek-u>4Up$t~bVSiaF1D=;vueN;6_Bciy3Qj{_f0M89D*TKd -zL{oR;J%$6%IUIgfCF^iVkOSW1hn3pR^1^G@<$vR!zwxzO8) -zpV2{-7P*t_9((Np%76R>LoSgyM5UhF->lG-Rd#Gj!qk)3q;Nn`5N^ -zS?$-hp&pl|x|9v@89V{s%#Z6BM()j%9Xzn;>L#|bXH%3X3bbrnd5p1W$=ct0j&4`{ -ziu!G)c%|Z^l*YSR7M%rMJYEOUD(J>gG*KIom#oxA|feMMB;_AmNZUlR3mL~dHFyT|n)p4WR^7xkd4 -zFzrr%kl+dnHVwPyJ2;YAc|4in!EH{=SOf~_kvXIn$s;<{%>FnQvdM~}V4Ua`D_FS9 -z>6iQVmoB?LJ!@!nD&6rL3)FnEo%Ibjv9I1dMX|o1*~b-q6Lo9YWP0zkWpN;LSs#Pa -zeytM>E;vt|@8otpdU+;i*r`FPyXVU9AqwFuc|W8H0KINnBXhKg32k$blRo#;ZsN+d -z@zzHcI60~@$3XigYkB#9OV??WF|U0vk1SZ-D%BzrVu~TKk0rE^ExGu@HeAqGHMF&z -zC~2JVR(u>AEr9h0#U_*TfCjeFBMBd!Y?-@b+|?tA_-e(ZW8B*#M23}NTyL;&ouBMt -zje?q)?^Ywfa*ZO!BeWM9RJ4%70Jlo;PX`95s9D4;+M(NNuwJj -z(MELXa)}4_h|nFpwPDMw?^CUp%snB{hx`&LB^%7tHppyVh*VVy7)C6lv-WhSv}tM;gp|VS&Z;cAA=X -zTxA8$v39=Q=&2<-F`Ufp$=46*drFyd&}z5WYB$um88*BO>B&!x@m2Dujla< -zS)SKT%(lsdhmpirMj@@ZtY(8-y^+K?Z#~6-ar}oy{y(&H(1(EQo}*Bgo782Jxf{~!9u=fx)dtANnCm;BB8?FoF; -zdnlTRkOf-3t+&e?CEXik9pH_U8}LT?hCKfdg_CtG(7tt$f1|YdZ?u{6^u^GAT3(+zsT6a)%J_?sNUpc>*GavNe{L|6>&hs)wctMk -z=)GBVE#h0oql)jdh^J;s2*vV~8lAQZHDYD}s -zN*~LPzuWVv)q+Bx#AT+{6j<}~o#yNFrThBpe5O8c!N1kNik^FC$JgNbjvH@|onb8K -zUQcMtdBaJ+-}OsS^t!po=iqA|o)(^&@2|@{@&#d|%lR?v)~f5;yJla%K4#o)@Y0m$ -zD>nO@w$RzN3{13UT`;{gvOZe+JeEWanPo5W}r&YEAwzs>E;*U%SYkHV;CI#AavJZ%ePV>`2JmMF+#peUTX0eGZ`)=B!5?r$~=l?Rs&E -zecl{hKgkoB9q?wmGtX`Fnk&lnKa*vJJ#UdcY})KUKAR)be2HCZUe(|Y8o#d$HY*FBxBw(f7%*UNTO#-CO@%h=8ZD@@2wv=6NpsT5ivlX)Y=q;v%B%B8BT&$lIiBKN&EHyVG -zsHH1%&`hsaGeTqw^j}Z)ul-AqY+uqVBNk|%hSB=jruXl8)*%RILu= -zRte3YI{jn6l2JmS3ZP=9FUz97PwpS>PX{uemRl(8{MPa#28LG&hcFWhXNwi+C5)-x{mL -z9o_hy4ZdfNW0p_4(O!=reS?GG$z+PB#sv~CFHqdNISJguHC@J+YYb2Ervp(~15Tg* -zjcj^&X5(dJXBRdF+5|p*7dBQ)B||`>g1%eeUJRvS&JG~Vd6U&aJ%#y~wQ~gl2~TXBHHhYeyg#`L6|#SpJNV^T9*&)) -z=eTmXRuHPWJT0tX^$5MP_rQ5^FKMb_^-q0i9?O{ZCIOx|=8qAy$!BzalOt`vky~x| -ze_HFmU$k|~_49ClQsvjHJ{M^(DiVf3x!xqF?FZppMzqQO!4C#|Pctho+}~O>a}#5R -zC|*z1W>G{A#WQ>#9Q;#t)>qfp{XD#{as8%Xw_x{&!rkKzLQ7Atr_)%<)V1K<+qaqE -z;*qqO$^dqPDM%yYE}ok?X6FsX0OS7yr}H~6{wDO(34D4Qwx?`H-y4=~k@Lt0hzxP0 -zQsmyov6twu--)Z5N&L)}=TmRktH!!f5_A~Kn{nCTK -zOZMM;7is%o6f(tPn#bdTkAl??$30^wJH&mRgPAn1t64_Vr=_~QV#T870I^$49us}R -ziC3zoF3P3!85x=@w&5iy&>#S4QnU!TevIFx5u?&JcPm83%uxVaAGDU+aFRV7+SViV -zG3sYoz37?5Pxu_U(^L_{)}-{r^>wj8N-sw|g`|Nd -z>Otd4NVj&3g~>A^t!3Dwh)a@>1me&U3Fgt#ClcuwIm~?13<}G#Bf?nD)!nUX-uMp2 -zVwZTi$u5F_Y&A2-2pvBy4>+D=A`G=nuF@Jwr?ayGM!5-NS#&qy-f-SAX^l&2g>uuY -zX_1P_WE?}O+?C2j%F%}(MGza+bQ -zGoB^7f{)hD*(x*Y6Y7^$ikw~Y8W#Rh9mE+kC@tK3?-+xQ6-5!C|E|lXWoEXG^}als -z%SN{5kB07|F>|BE}Q4=CluFB=(m!vLSCB5`s((%Y1|&A -z_u;pGWS*zrC%lJ!OG2d^0b-Vsq-RE-mBe(&0U$V}kcHjlS^6jkbKp`)Lks!X$1I1}F0YeT>j-l=$7RO -zj(;^O-(IS$?~MaSMJL-=4qiB}tg9mQjyi;iO_xCrk_~5GmONUF4TMsx6LzepVUis| -z8gn8X&SJg~-SsGVJLtIt79+X2+=O86i89s$26=8y*UJ$dVCe>-)RPW9q}Gh!2egmb -z=)Rrh^Ii4Vn^|}YZCHV@co%U855(~1In<=kVnc{)@(tvM=871w17}h4I3Lt=Y3q>J6Jxf2u -z9dnnc^8R^~(klDIJ~=7VLZwmik~tA%hy~#5f8OtI#1ul{oB~xwOROl+>YM!A3^;2T -zJIPxR3&^F6Z(!oRR;QLvr+++Bg5xu83oO35!*G -zYToCjD3{Svj;Eo)X@Gs9a1y;>Q}wsr-}m*I1z!KTzNk+; -zYDSJh_|Km!{#@7S{MSsmNFWK_+t!3|tgc}}7~)JX*{NRP5Uzv-9$%74?%1jQ&p$4z -z3Eb2*`1pi=GTd9H^Q#@Y2v?8bshCN>FuT2(_`jhBt -z@jK|R6}8usZe0GN!e*+#uu!|zRS}otv)8~3g2@?(1cr&>+TUs4u`(8A3l51sr~v5d{@uE^RZ#9qW( -z5-ppYC)aXHl-QTuGqLjBS09=Raj`ldRA}*V;6Z+W -zd6TLLH3!bQrO@5&U4y3lgHSu3u{|fh9M{25hwd(zaWkUTym54{Vd$By?jh7 -z$VWSw*pzE)y6bCpP41M?@ipK37Z~hx^fsjilxZ1l^1Cb)#e*0;MzvVBe)5lwd$;&} -zSl;X{2f57y?~wnx^!%yo^{X%RBkg!_Lq=B8r+ +literal 844912 +zcmY(pQ*bU?w5=Q4PG)S)*v^b?+qP}nwr$(CZQJ;Rv(7%ZcGZ0v)xO?a>ks2;fFKGA +zim!aj7zotF-N?k=*}~4&(Z$-tiO$*G8R)vlD(Sf0gZ#6{Z)E*ZSJsZPs?JGa7}v}A +zqm@sy?r+@?AHp1%cwk03DKwj)sj8}R_MUI<*$8ZWh6-=uYU5uo=HgsQe^MwA_q#T~ +zuUa}Sy_>%Gyc^tJ_co6wxjNswDE{3IOM=teGQF?3pSY?U`o5p5H$T%~HTSRQr`x`e +zi)TFB4{mOVGeDm2!|hDhn_aIj;Nd3iZZH4WZfAM(KdQ6!d4$<>r^6rPWDf}lsX%ni +z*0%qCjr!f}*mWuW?z(;ZYE?HHj?}sei=M^ZTSIq +z-2D13onG4XeB6Iu(g>>R`sn!6|MCvU$uI`XGY_k-fVKswP%2%Iv$Q*b!&GC +zvUz2F?N?0K;r-UV0k1oLxxL@-2UT%ccd*^4R;aq)3k2VSH&q=?-_Dq)jvqJVU2SD{ +zeh+11M{~cQ1U~@1&)+wC*RV@J@3%F-$ELjR7dQUjlZUP&`aZxNKj0SgR}P@|`}Dnc +zeWP~Q$M(AP{KWs$bTFf5?e~F5@cUyHR#*9}8q5DH!X9_RkNa~e*Jk=_Hby`6``J{N +zb@Y6)cSG>m_X)5YWcSm^Y~v?ryYqdRnUj6}k=x_w9ZVl{dozVf+OWk3;VWdW{l&<-$xIr#TU};lQ^z>o&KUTRu`7F;&-Bgg +zN;S%+(7K6Tz2%M`aAnriy3oyY`@t&hu!!~D9?PY;JE^-Gl5g>?EipNrIBFRfJzYp$ +zF^{dmd)XZg8&Fo&Y}rGojp++wHEP+~uhy?9DQim7;O}}FvSpR-K3hJtx%t8(xPXt- +z$gX3(Y1W!4W-?me+?{cFT{6Gd@Aa*Pvi-A`cS0jW5bL^3@rDtP^y;7SE>UW8(~JW% +z^hkV-5fP#!3B7g`HB#+mUHN-g!b3aL?!rT=_;E!(cG%{4B{NC +zxDdN$prRlkve{#~P~6D0+>1uor@cY0y3oWm<-aI;{Y>r2s%)=@Tx<3J-o-!C7X};P +z9c2}zkdx3hnRdMYydd*^_ucwjy!_bEKNQ04ethDP32R@g{iC^6a%Qg{nNN1qY^PTS7Gxe4~F!JJaYw>lo^>#tU*8Avl<(aif +z(5t!kNwm|!u7vKFEcej#w$<@V{^N;tbbH&w_%Nn_`0qvx^Ev3v=o48|=c=COD6V2n +zYUx1f>){>COB3+^dewbOP_=qEoY_08vogDXwE2Fc^mb45lRoDAc(*$?qzUgJ6$fDQ +zooQe`Y7`$6G;@_!;*kX?_~9jZ&Q>wD}HuBo76K#1P<| +z;$P{*e!;t(_+iAO7{dYIyIdI>eAIPDp`nedM($G{h*dBSb~q9saHWW-a60 +z2li)O^W~>W&s>$EAY{l^%-)=&76^=VU6nO>CcjO}`aEKk9f0eX^BuN$<0_eK9)g3S +z3b42W>*y~dTqEUvL{56MnSatB?ZqKBGlX^W%>?jzA#r#e>U +zX4jWM8#U>o)-yVt1x@&zxHf}Z8}&dX3D8WdRR+_^;5}9M$i0LjuC43H=DpYaC+2#u +z&vvh|vi-OMb1MJ?e#%n)`}k`Hcu1rH<1Da$A}=-bA8bZ=5b;`Vq^R|U3x8gTEO1TlJ& +zZ2&f-xY_+*{|b(ZquEV1us5`Ao_&wfl0VzfJzB1B*sjV*UV2R@K9B#ylWVfD(7 +z_!@X9Va`m2gyUHd1ZgYn?cn +zhf)x7j#_zea_D9f`v{v{;wsdBaG)h1B%sEkEbjVHtrAruyVm_gNkk5%?Ese=9&v@y +zIG}<~G5NT0*&pGMNl_vV*6=M +zTW!otAi9_ts2kK$JO)QIv>}w!fe<5^$6%8v2LyY^LsAdie(3&j$Z2Gs1L{t5FR?)$Tny}mbX#C3vC?zO(P$0j +z22nk#<8;(Yz9B!VWFVzmEk>UJ^!zYq5p_Es8CTedBEoj+QZ&}uhC^RGD%|=yQXq9+ +zmtjS3tjI`+sxzFIksBCUO@EDzB1tqKhW$a3Y@ve_k#VLnqH4|(vWxr&2Ypg+Bjmf) +zHerYDJqI7uEG?$Bpui$Bpm}n7b3k3pgIPT`1(a%sd~*xU2ReNt~RQYO~%{ +z+5dp;?@wEfu4^NbuiYkg3n{OG<{o8_fjoPzqiao~MgXm^rjl^Nrn!zegRza!!9JTk +z^K6LWHi+#!#kS8Tutu`@J@?B@Ind*U6Tg3x%#yxRC`w3Dz4$ZReJ42*B42Sp;eiXx +ziqI0gv*H!YW&Dmt19<|8Ofd^sf|8bL$?_OXa+Jt$2F3z^Y>t9%Sq}`abKu((r#V2N +z9=sS`AH7q~fBVCS5CXAyHvAEiDJWOX{Y%3BZ+Uk5h8QydNGBfZ3zSCQz~nLkWa(BZ +z(2_yxUCs)FV><(sFrthqDIf{ELV4ZRg~PY8ivx1_Z@kdTcT)2xHZD0HC9(PVM;z_h;Jo!Hc)i#GEeRQh*aT~WKTe`pNH6o$4Hce^<)fR2)AX)5&VgqzJ +zrF4{xAe+OLK|Vla{dw`PewpBTZD=R4@oXY6{%{+)uKQs^Cy+b71={P$94C`7Vq-eI +z5c_b^Oo-{8QmKN#3gnJJMD#v+3{T?JF04g64|Llw<8JRS0#0rgR*Q{ +z>oO6&Er`7=He7bbX<(mB+#<=wk^{&vqZ~?TAOfeQtcx7&7QWKgWERK_aZJsr;&=LO +zrU%6$_Zozt1ia8XpA1vX?T#oA42*u0xB3XB$l5>U*Ec)?Np{hW^$|#srGlq}CzTPb +zXfZSHjIm-VbAtEq>E#OM6r~yV)98JI;_021sV{g{#*U43i~8{j0^R +zQTaXgf+m)Dw*<9GO(zQxQ-2*Gw1AQKISp!(IYG|s;q3OhPngK?Ru;%g6T+jsD-Lt@ +zsbS_OXPY5-csI&@j(KIdNX-*2`o*u6|KO;d*N@VYmKXR_M$1@eewz~$5+jK#Q2(6) +zIv3Lcs&9X^h=?K0qMA#bi%H4>EypcK$!9_3{5ooQUPs6G-=6{M$A&i-S>)sO$KjWc +z_rOY_38ED3aPZF#&{3NV5;_^el^!)AJV*`+xOzyC2s)M;HMW>T;h;lm(DHifK!nsR3|k9B4yCwIS(QGsyc^DbOgu?z*h!SoA_+U&h_F3 +zKut`!kDG^~tGEElQA(pg&~BxJm`S`wvcL7(KM00Q2cvUZ)WUr0`GI^7{uPN#q|~t5 +zh`aR^T{VA1tf#3cub>`{w}1lJ9Y~RE>S1LgJc4{e;dnB@f{}?5h}20^u=6Qsg-T6{ +zJ%F-Md8sNu@bC%U@G1As>3ED&=z3wSQDv-`7K1+RAS?=P~3VDo_qoRXsD$YR>BCD*n86IXL +zH|p!-yyckX_Rl8b@qn1)WLqY=d%(N3I!0g0cN +z77t&)kOXi>z)8{Lx +z5qeuNw+PpDW45zjA1-JnOAhYoBa7WxGNrI2JX6$C>sC@=kGBDRDOfaCxEg=R97(Pm +zIb1Y?Wc;&MH3yed(AAa63}<9Cv_fSZ>?=?Kn_3yBUW;_Pf8fdcvsP&nHr_1SKig0Ny?=M9t)a +zcqvu6vSxLajQiFpP3l-^X{7kKIF4gja(Wu>1^?bl3h-Hkx>Qx +zJ4Y#oz+cn|DLd3!7&G+9B9NNSRXc&~2)nXK<>U7;gJ`cc`GMgeM}qxm)%tbq*16Qf +zFM$ask1}S&_b!Nny&@`I*fGibQb)^0EVoob_ue-toga|dC@JC2oeC(oy(_GQ@_WDO=gmx*VJJ8m*$0AowlF{PA777X5trV6c +zT&S;|j{fn9i?)l$owKWo6^QOaLC)s>a-n2XLLohnT$8xK?!=QyUsjhd!cMRqRfIvcW>#!O7TOI) +z3YhtWdn;X!hOI86%Shz=07`)wE$%}u&}x^zMnZfJuvGFwZc!m`WR3R)i(VtFo#Um- +zl5W=``-*0MS3MSTAI-(rm3eh9-aMjT?NWK^`MS`8lQfMfAtM1QE$6y}?=G2>(OZ(Y8yi8KG!JQ?nT +zx~DH#p60d%`*2m>%#2B%FX!Olo-bmB1H=W}2=zJ0DH$)IN{ArPdHKMbhlBh*ifmYR +zGW?r#@PE3VZ>OLeFHP2~3)vX&J_@-gReKgtWs>0b22=IbHW#_%o4aU!E+Z_n5&;k$ +zMQ0z%N66pwqq@mYl4qXdl{BLgXeXx9NCMwIN>5A`>-&L{uN7(h_Z}{dMexggFI~q* +z;-~46s{)6sMk;J2oJ;Zdr#1Mn3U&XAm1kUyYliJZxxGMHN-KT&BX6XhyCnBq%YdEi +zmMRf_`^n>AF*C7+_C45*JK`&8#7zJpB}D&Pddeo~5-v>+2a8$&sH}VR+v3cDDIG!o +z;3gNWcQ67`ux@-I;Ju$(2YnX +z36aGs)q=f)i_N*@x`FDsF5gTXA71{*#Puc5SUj&l^c1iyA5!4b3bI9w!QkAZ})zgheJNWS==|_so*_#Qj7^1)E3j +z9^8r&(I>naA8k>uR&Vr2)?NT~;nu?%doZKM??8DL)7_FCA~lhLF`M;po)lEsf@)Ee4qf6#hk +z^RdD-GY@CGJu)Bk$kQVEHfX90QWvWoZ&~K)$ebsc#74T|3wtZ(PON2luqSF1ZM3Wb +zMp(fynPpEGsjg@oW5RG*aJm-7m!y~`7DbR&>KNlBUHpa@x+?)*vPbwRE=R5Ga!~@dX?;gUrZU1MThS>dIbn^dD +z*4z7x*Viep@6&(5alf@*aaoSr&GED+{(GPtAG0&Imz#HbvJJJd$LKFI8y^y(nXbem +z`=N*TuBbTHHRVEmzo4D#a7#NzYfNtd^AVR1gkiU8*xWfK9CXA9mZm5eb(g)WUItbs +z>W#(bT32Oxg>butlNT{FCw?B=*4mFD%eR}YU!K>!UfJ3QOHpkP_5`ec?c +zWcHKc?2dnnX3UICS>jUi5_|5O?%vxt73lqL?#?Yf(UZP)xFrb515zA)?4XZ$`6Uoi9KPvrXYR}af9qUv&E1Q}iQu7hR%N~%SLxt~A$6iUScy^(`) +zhXBIt3F?}2+xE(eN`jPNh&sSNYZ68HUw|j<%(B)&A4ZmFh^N_|M}Q{p((1N>IM^lw +zx0k~5KL3Jej@q#AudA65J%>(>X|a#?fY}LMsQc6MJ}{N^lE0-Td&yknF@iWSlBGgc +zu_7+Cefz5ILgFG;W(;1wNbSY(S?1ZpKtD_+ExsJdsVM8*@0}!daP#X3mA+DtIqsDK +zB-={N)vDZl5vcMtT^@M+vtcu;>4^taKTcM7A!y|EiQ4u#A1sld`Dd$I^=Kax{kVk2?gHNGUdC2{{S0_I9Rd+S +zvV?4RKfD;ugQx8sW-lby0$pH?5|>k*mKbIOk9NjRGN-)As`I(T(;G2X|M(aEigyDH-4h3p2PCzt8=fc6JY}D2>21$Z%y4%`w+}`(queP15)NXI#+aDOaeH8n5 +z-kvh)Ut=BRzCFRlJ!pvQv>B+fCn!|V4RGLJ3Jj1ftTBHs%F{fz=xFQ +z*8L4FPrCp1)8!y8YbPAuE+$lTlmrFO*x|a2Y`w7S&-sq+)nNdi7}q|Ggrmi)5X;WC +z0$PmW+71rR9i9B+4y-r;p`K@HODEQ_RGj~#D6idgc>8BzWzP=)NPzhQV)z#H^!v@z +zt$Dt7n}b($W5?3_K+&B`yZ6-fJNW={pTq3;@`ZMvv)bp?1HID-c=LwtK7;E% +zOG|e8zZGQnxw-!seD@hfy4(>je*6-B|vik(%UdLK?CbiG& +z2jMGPx?5NZP{D$E;wb>lo#HqQ^2f! +ze{p)=pY3Rr;G8tPzfZ>E>~_1qFL$!)c6&X3e|Fyd>@Ajin{D?9-ysIrp?=cB_6g2B +z+FTc}L)2V<2pGG0*>h!tUNRnn>So++EIw9(a_3rE$__o<`Y7c3n`XaIw`NxA*WARU +zO0eG+Alf_JN4_W3Sr8Y#OfCb@j|T122@2sqIt(5?H!;nRe+F=+yYt>3H2!qkVec9QeMF)_%hhqtxX}1gc+Za>s{6MssOF=~b>?E2;ewK~7RJfuxWCdI-KctgRF +zaf>Ive!G^*ZL2xI+*BzEn$_}qdhOu|t|1P*MRko(&+apU9We16c)SmqxDUD94~ZBL +zKlMjM$uT@Wxcp)rPAqNg`8}-u`jfX-}ja7ul(*9|*_29onBsgam +zJ#@*?{Q!qR1Wj-S9lh0~hXE;#GZYAET2 +zB`T(wW5F*qC?^%%Z+7_ke8nOx#dbYLKIn}*yz}kL>irGEw4YZ{gt{b_msM{Q1fknp +zkuB@#IQRA0TRHl^52_&J`1)yaXS@AUU_XQ@_?7B;fXe0i>TuWn+3J2do4E%)ncth7 +z^81_PJq%{`+kYKDcHfPbi$8~m5IZJQn%Z1ByEmp6QtUpRYu5VgGh5VvQPxE}wP@tc +zk|l586;`W?$aZKxG+$$>Cl2xiXnVtTV6FNqfFPc7-|6E;@O^VT#L0`R<6N28Kgg7q@c*w?`19{4GjC~52Cz*pddi=5~GiE$@ +z2VeS#TWAPfe!bDOz6TMp^|c9)R~T(N^n^rfL!J=M5~=l1=>0#`5Cj{aPeW$>Thrs; +zQhnzx$c(1I;`C5CzPXW6PM;fsGT2qj)uJi$png1O9;S6bMa(jEk^{y{4R-;aqlt=FWX>mQvAGG8c3ie4 +z&=6HDrNwL`;h`CHN{OKNDSM1Zw +z4yMJ7$FJE3{3e8v66JYsNn&)9$d3){jHCr&_8il>Q`^M;5HR+0dD9+>d3reAJ_axX +zu1in4d47Lx +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 +zjZuEVIpdi^P$YkgX~Lu**gV^V57- +z4rPxN>!HHi*#Hx>TtTR;_6^!p;S1^SwU%Nan1($g%bc(8&zUD$n6KApPgZadVZqV= +zJ=C(H(L!pLiW5C=X0%kK(E_WhcNSlh4pZzlff^z=*V!cQwXDG&7uwd!1k5F7K2>CL +zbx=(A%p#z7B%zN^{N8y#yPB0%Bj$TM7VRHMPGxqj1nFl3-)>a+>lpW`SAB0t3E&yA +z3WV$Q>go{s_FtN`hMbV){2fA;W=V;fQEslD-Mm^Rov$yjicXL=15bJ+>)Ba5Kwkw_R_mPKNmz4^DeOC{`-{sTi`)sUxRqlnls5N-&_;3Mjv^S$puac~x}h9C_M|5vm$ +zF1vBE9eGRcsy(^_8zhRtlb}l4O+fAF+>UXNv^6&LC{q`SC!m(pi^)0j=O%gauJbQ-w5iqBwCP3QEEqvk$i# +zxw){UbQ2M}&H!l3GPTHvj)4&e +zZ~@BERozgF9dXZ2pYNpiUJ2(6{~s_<<$JIQ)%qfRy6x|hymsy&!4 +z8!#iP)BGA4JdcEeH_@bY#l*5WPSn9dF;T1|&Eio6c^Tm@5GG*rq@wVgv-Oo4!g1Jz +zt%uuxeU!Z@nF)&`alqtA9ZB(k-vzFEj&v!uOA}OD`MTo>L7O3FS8$1p%l;*E({czG +zTCyMAg?hCViB^X@$PV}CuZsq-nvxA+%0=jbv;`|ky2Mgi{=2-EL54NN)EE>`vo|A5 +znLHLlBa#!=6^c;a7YAX_uy>2m>RK0)u!; +zZVmFmW4HTW#Vy3=RXs?TkTq!|cQ-PW3r)NVRoVwrDafwJBa@5rQ5mE*DeiED6VKP8 +zQ~N6#WvDV(mMZGAxW3=?e6??l!X)4Jx_$mU{JY%iEDq4<#8UKKc(NFMP*52d0XMvV +zqYepxQ?sQR=TU8y+SA+%{EePO4`^HcaLmP@TdX^1bk*Y!U+ +z-3Gt*m|r5qTr~`Ec7HHaw?(=O|MV<-{%K`KFNQLpPY+)W{x|Ds=Z3ekHpp~G39`Sa +zE0?zz(XsRc>_{sIrDamg{_v9AndY}}v6LSdxDM?S0n8w)3@$Y1t +zvP^Ecdhtf)#8AHjS#7i0ZAizm6O$74YWWYzsfN6_P1pqc_jEF@h35d>qc|yaJpWEn +z;?+9pBr1Bttl9;eKmjF^8|MnC26mycJyB&ZFtpDb6}-3lESDCF{#a={AG5+{DhvBA +zTtI-eyyT7ow|K*`adQiLZ}F}?+<;?yYowBkuuCFW{;cQ5W&k8d29A+z2c&kf1wq*| +z+6o17m}|D-wUlll=QIVFGJxxyH9?rG9bl^6i0w2d3LUbMK&MWo;IK7KqYT<$N +zK}dr0QmrRPWARezoF_Hx^@{D%JoRU`RK68) +zJSvAP*%Qf=+0&GgEjNHJb$sq>U2Ci-widX|WR`7BHMnl%M}oJe>@RODMBmWo57~Z4!sfdH=pa3Eg|T +zJaUH3EzClcRe4HkCS+^YRzC|rPo4T8cHUtUQGC@=34#Yv35Gk=krt58GQPB=-Pa>Y;Ucfu2Xz)SvM3;HEdOe+B6?+Sn>uH4Li>#Dp_+vfrha(D%P>3*^z@Y#%7h456k9M;q`1aQi4J0`1<+S7!7~(3L;_jP +zTWB;VL-Bwg#7#wMPJF>On4H4C(lF1IiFNc5yMNaBIZ5OZT6d8SyGtMzdPJJUeZ>x3 +zY(rx2FxieNXb0NjRWbYnxxVrtj7y>0p_O@(ix57etD%pnH-5^cKD6RpzZNjv&QS-| +zAMUj&Th`Uqg{#Z`$!%7d+{h=Eb{CcwyQ1R7_CyQ?hPe3r4A@y#@=M?I*K~BK>sa!L +zm8p651z3H_H~(L88k +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 +z^ds0v6#FY_c(*T +zr<27*U~9H1wPdz;P+DW)W1xMg0#uZBugI2;2JAGX5ha94HZ{avNb%XlH)FQPch{>IOB-Uumj@j6Ki6& +z89LjA{x?>;Yl!LaX^QH*sOkvnSsoJflZBi!2c_%(>Wdf2$oPjotY+(AjB1Fs3!P*N +z+?mpSz;=ixRQ*9@7Nf695Y?J_S%K4_Z`DvN4ez8#7=v^)9jdPh1gK7>8<)fDy%Y9J +zcKtACZ)@lRCVb?++!0axtb-oDjUHg50u-_evFkpZ(`+vN5jFDncMI4dtg~mQz9PSC +zu(QC6_!9GYJEQ~8uT`|C%7vC5!>*V#e8x8ay;&~eHG+87ktB0vohqKS=UsRxjuEzV +zyT%^~=h;qJ)EJIZZvW%!5*^_lQK^26cH}a>Optmnk^csiBahp}MQ~af9gOkc9p2=Yt%I{r3-67qT5+Pi4PTxntPY*semU2H3XoX$+= +z2*==2XMb(%n&qBv+5PCofNdV?Ris{BX2|@qJdIWah+BuU(!i@|Q7m0dN?SjIP4Dy> +z^Nj28BDuey+LYNXvd*SZJ7wS4&Ams8;l3Vr>v}2h04K4Z0fFruO)>l#3OXvhzG>b% +zP#W2XVaOZfxTze%WO|LAgtQRfz?KS_wKcQ|F+JI04$J{$`hKGzR6c3$koUYm#!r)! +zo70Ok$c#Wa4o^5&yN7)#zBu=8kG|UOOS?rnGk~^Q3mQ#jwh0K%%fD{uOQs1-p$8l9 +zAStYi-X+Cgq-(z19jZf+*;fm0xMH99Psee6>d5s3%Rno?YcnA55Q^P2HgzhB~VR8e*FoIV2Ik_d~Lpy$Gxn|b* +zC~C9jJu8-jc)oNUE}SV;LnZ)JC{BA+jp-A+khOM7UNPc%fe*69Ti*T3y%eptgkO*i +zNtu#g#Do%0L)A=!tVa6EIyRa66cMRuL2f~k&z?zSX6Ni9grj{gTQ>-5ek9$WM(4MK +zb%8Y+x6G8JGO!cZ`ju;G$3C7d^$by46o&Zdx_SJV=X8xRf%2~4n0*BC-0D67sZChiTSqUez3ft881M@hqoFz +zMODsaQRN_d_KVFf_;LDhy@`Kav=YmoCM3x+i=e!qwQw +zm`&&(8wI%u3*zCdblCg>Feawtbg7jVi_vgeYeeT1N-A1y{6>1)M~a^%r~fn8V!cNQTA-FnK&e +z;)%)u76C@E>b>kz8&q}bc&ZRrN{ZUK;X%nzFSTI=GoI!r23tHa +zi*qcn_OaFmiNWaKS}R9({o*ExDd_W2Rd=!{r!QlVi#q0^#(pH +zzo5vvOi4Q$&kee9H7bM}&kxCryygiN4h=|4F;&t``v8$KYO0NTCj%RG7`dK8uWWbE +z3pHg(hCR680=oj)(PS4|TbDs?U6Mf2OsCKzST2`nxj^(3bz^*Ra)3t`v%G}Tdyh*- +zgfJ>ZARyNYFg%%lGBL`HDfOj2=8WLxIJ|ToFCDvtq9ZCFm588^3VYeVrF-t!V^agmoT=qm(cV2K-oBsL3rftP)u}Dn?!;TL`HmPVBEBil*Dpts_!FHuj*00ovr`9DtQV15vd5?7ky3(oKf`73_d=GPi) +zUT_lg;`#iN`VphS~Z5!Z}Mk!{iK*Eyo|(w0~G0lV@TaCEN3#P6Ji9z +z_5>5_ +z7mC`P2~3=}J5X1z;7kK`(BW2>pk;X;p1$`>-yq1g!&=SosB8diDM)&x7<ep#PBt>3k_)x{?MOx>i4%)jLLu5FF=BV=QL32X%|OnijuuIotsOSwX}fA~6{7 +zd0Jr@#2Xc +z|YA4B#n&+VGBXkxLa{Le~8D2ub!SD6HvId +z!^O9Vw11V#Vk`=gfV<4gb1#|g5b7{7$GywiljJ2=E8tnnTc`rH>pc&lNm#Q_z{%Uo +z2aVG}i(3=cGYp`y)+`@{0Kv~rMYm5tu!cv$@ryD$@8wHUVDPCdio)TQiJ1-qr|KsF +zmiuMJT3{W>5!|f3&JEed>1=%gANoxokYP2f>pK4!O%Q&%bty_yE{f-fk1W@icM1cU +zQB}?}y68v?r^=&&D>}`kwi9<%*8~?snQVe{`qoBPrZIus0SUvVzk1@#M5IbW#dAG! +z(@Lk0BMXgHP0NHHEN(TV4ips*@0&MNt`mbmdYk#q#4yqeyJO`I@>u9&!?P0Uo*we?cFDZS)AxkhTPncCP!nF6 +zPPiM=gFuTRqnk_8V1@4_*KB(Zh22?Xjgo?rjP5kw3o(?LNuLcp&p3@Q9omN-T=Qo1Z4xY!@(UA=iyk-URH}F1sN|-;A!dO#9 +z8Hxa0AcYdVirIZ1L--;@1eoImx0#QBOEv5wH~8Q>pAWSq%uo`09-TIDgjaQthdW#s +zX?-)d7BH^z&>|Mgi-#sa7v^#oimprilj`z{9V&~G+9L1g^BQ^ztq{IDNKG!1$5Ec3 +zu?=@&{$nJIl~&3l)_S(0EmuB5ek-ArZLwwSGmDHSK_4+HG$6ZQ1o`I;IB`9QeI{EW +z7cIE^Rxy>#(nWxX1$lW?Ij +zH8~AEvX6_@^|BbOE#8O)9k$u6uuSWlo|hb*Z`8lAiM39O;h7!nq=eIM*y+S;NI7UZ0p#2xGFz-8OOUN#J9JP=>d +z@%kXu+NQRG@-!NvdK2l?5?Czxz1tLv9#~}NR7s1Ii6br>9*WTkURkq55}))=&Lm1a +zI&`b8C6=XCE3@7q`$(QKL`1z}P^H$P1z@FJ^6p$S0618I%%?>H9n>qAx{S{H5@DPp +zj9Gk9NRNUcwo8dQ+g7>BeN@PB;iN=MbVMKWO{u>JJ6w8N@(d#xE%di&@Esqev(n5x +z#D+w5j(!X6v1=IBVm495<%t@D;T&Ro3zo1$M=uJtc{wi!Rq%5-r!UTAk~jp^lUcNDj&ydMQfwit%$1-Gj6* +ztV7m=`_*VicR*xyw76Yz@y+iJ;kKVX9PH-xQdw00r@=rFu88IsDce&d{drS +zYI?Gu>H{(Db?}jeleFf_6cEY+)a-3}@x1hMo*{R9?zk%^C^3S1@rha(JxxsGQR_>0 +zn>xV!GhsrGOIHF3Ra=DN)Lj;BQ?c(o_&O| +zPlgp*8A56Z(j$-N5~2n#Y6+cUd|wI;-NgH)(Zq1XqY)7+sf}~7{rhTQ$X_y8#Zje# +z{itZj^v*Q9O)0EjZVc4vzvVZOHvqRHs;QJYPB$qal#`YkqYd6M +zQM)qWp{LDc@aZHF6i~XgwH0+nz?l4Hvfx1CWf#6q2^MLVsz|Xc0~6n=WKAwVRM<1s +zAr4^a)vKm>^r$;?2#5r~v-1-NupgWIEsHz7it?1|)vkuejg?+S6U}H7#&}9&|LH~6 +zG+Wcg5o(`dH5?8~Nl1uzfip@x3(rKN1I-e#mZ-TMY+E47} +z>dA1(zRK0B`m=eBzt^LXHd%KHt~Qv^;Uin8{9$DpY&8}52f`NZWgpHw>>(OWuB|kx +z>Zs4td>RDFZn2IdX+>v(g7$eb3Rl8j1|AUO&+#~Ig;6rBN) +z8p0qh3SV^%Zq=$f3CsW*)pe{eRV$zXYx3D>L5oSry~FvebPZr|fI#%<3_o(D+8KyI +zCqKVtxhA9S0|$C25G!iqRI5q^bm?mOm%Q_8wozZJRtmbLmElu|r+p%Z?xSHPcHATP +z5W;1{zU~5U$>%R);wr=XWI;D_AZk{cTl3=yqw`y?E4Z(R38O&L=QLq%HYggZX+nO7 +zMW-#sL@gVVWRr{}Eg#DNNA*z#8O@CK_m||}s*AE%L*&`%2v#$iH7Ff67yKRAw&!7w +z6Bs_|eX(Wu*~R#;(ajCOB-f%X5qX+79wGaqWatTLNf9v#G0_-*Th5LI7RjilZ&>yGoJ$(i +z{KTsp!Et3Ae@|=7M3Q}*lM{hq)|O@o*w!+=Y?7PUnrl)z)?TQpQZ91Q3W$KNDVnjo +zIAthvOj-LW!rI<WOsH5(oa*YEmzhs6J;OajV;w$1gM2oTdBDZhk7)1i=-M) +z3L?coYIG>(3%03Qs5Uu3bD-h8Q(=n=7D05{rA6EynS+gY*s>=m5(LwiF$n> +z+|X%mU0k?BqN&}Sdmt2dCmsRfmZ2c$i7Nt467P{L^}4fiv&jJ=w$ms97ldbyj5Wwy +zn^9oJ;9-dXf`aHL;$mI(4k=)^kztx+8eeE&s??=NiD@V@Jbpq&y$!zgQxyEw>!k)o +z@e=-~U*ZFd2oMY4?Y8lFDYE4#3LvIH{Tr}41|$E}7EjWS6t}E_?y{F($25kxqyl7l +zFnmkn+6m07u;H;uyj7UaEL;+h?!a(`D;;a1$62t5JSvO+R?t+a=u> +zPZaJgad-_4QJVd+KN>t`6-{>2Ic}$qv8pFCp^mOhP@(gWM+KJT$^f#F69ghlS1JS4j5TII9ap7w}8gNXR$>n?Tn9V;0K1=X`6&LP~+~c0PvOVZ~ +z^dB6Wu>pSzpuaANj77VOl5knzhTW#at +zV0ao`nVmNpOCqglTiYVO5SbLa0>R9QcBZOz!Ito(_E%jKF>!TvG4oM!3gKzR09%Z6 +zl<0S1^m%2SU^`b)`~Qw3fHwa8|3BCk|I2qJ|4LG?|BmzjPs;!3epSbw{wK>h{{ptBt@DVT|2r76TX_op4>mgf`=tKOF{bx_ +zT+M$3-wyt#VV8FQbG(KNbqO}T_GRQ{#Q#|F*ROwD0F+X-oyL#?pX(MjYYTr( +zn2co6jkE6O8B!ZYdTA+fry$p&2xEOgKcl4hK>Dtu>Gl0MB2+ZNrts8ObC!D#)5MHS +z)^DKu`nveIV)_D-y&ddh>v-zk>KK;f8Ofe0z~;n1v;2-EB*ZKn0rr+kjeEiCpZ~@g +zjC3YlK`msBt6uW@gG^|mMkC8CZfIp4y!fH)Ey2H!yQWacrOuF^Y^W>l+v4 +zx!xH=F^np2+WOByK>xN`fA7^FIpFQY??Y_J)9oEz|L*-)_s2roD51lR|GwM8PckC^ +z2i!PIURivvWF*KUA>(c{@B{YO`@>Z8Q1VLepUtTf=mvd!&NORm93`}ELMpYm7bE~d +zRGYE#!m|^BQXDor_WtxL8sR?`e+tQ`#^1d!6{RE3ZG9)%CL+kanU3TClsHW3q-b$} +zy+NCN`nx>6?0)+_a^p?t2dp$D9Gt)WoS{?kRTg#`pWmLod?x;SA6NK3w*R>gkMsX< +z`yoy3{n)&p^*_AV|CV|(|K;>{^K;MmbB&Jf_l0Jq=D*$T!Aq28jsx|89^z1~JYguS +zixr7Eyty38dmC%g(mU)>-Tg$_}irju%yDs%!~^GS$tCa1nw}UAo}|%PVaMl +z_xr4Jwo5JT9VDSohLdkSJ?tx$!S)u40sU-nm=<2N*f8Pm;&}<-{-J*#(=0}Kt#5fF +zRCTW2E6I2U5Za5hlNCG8F$!Y|VDBI6n=8hB8=!_3dPb8x+rot=i^KTS0{5`2*2Y82x#%t%vrA +zJkUqYs5y1>kAMv(A!hj`-}Tp`_+V} +zDFcjOOrvlZa3yQQZ&J9SOrWUQ2lmesu3tYL>OUX&@mUmMv(R9xWe{p1=* +zNZdqSZMUM6QZC~hECNVK2hZ);T`|yPg_HN3l!HmpG +z5W>n}Z(6fW!;VLTDlSc|_b-o<$tggsDkV{)}e~qq>%H1(n}MYHZ69kBZt$Siwp*)D&^A)Z2Y-ipC_e7@{4+EriiESueZs!q52Me~wXP-@+{ +zzG_Tc=OIIp0p~FI@=zufx8kFB>^=S9p^+4jnh|JAPH9 +z-l`M(p+)_ME^`Ep-!nbZ;BUxg^DRGJZZYaJz`oPVD{C3^b2bx;d0gNM6N46X-rTG3 +zLQ9@V0p^c?(ljiyV8QF+P@`@MO@R%|4ThKHbTa9$mr~u{oaGU`P{}U=C;J=mCf*XM +z>g|&3alHQ$^5n-f&TpHzF4vf@;G2Mn|}w@pIsgQ^%x$=)3KDHSt&4LW-dq_mCY+ +za|!)6PQtsUi?Vj#O3GrPZMMcrONHPS`^mOCOXk2n8U*VlvV3t#Cp}AfXl+l?uW>^R +z`26%=usH~G?~uA*92-pN+R+G@;mDB#7Mp80nuK5`9#Nu7<{O22vnV#?F`;y1gC!*a +zrStkNfg3U22zy&XACkhlC;s9rZ)|eW?^Ighb+x!SO%biaLHb=1aubvUZPm{j=4|?Xx`cUJT6l6DkogpUFxc&s2eo|U` +zlH;jl#Q{kncKO9>f6{+?1?Ht3336=J2_!Pm6~hgvPuM?$-;SF6{Z +zfIZgLd=5ymoRfptt&1+Z0LGZHU_u~1(>ALoMZ0Jr!P!{d^yU??LLv(yY<)px0h~gB +znGAX$N;Ms8mi5s8D1SQpe=J{w*Xs55yb9OXn8V#O+Zd!V78F0neg54|sXX_`=soxe +z|EpE@Qf_X1QnCE=HT&~j8=>+}8J5_2dbsP%`TeJQ^XE+3`|fo%*mi3vZ@Kk|aN5gc +zWa|rEzrNq?0ol=M6Xchm2yQD-awV+J5(_&V7-2qYO8~U>tRNJHp6sk5CkihA9!vh& +zmOb!!!AZ*1)^=<*yZ!5~#oJB;ryu9x3CAhOA7hNbaU2V_w=0l+hsu5e%`uu92LF3_ +zml-Tf-N2`g{0%1;+)_sbyEwMI$ZnZKl{0POwWXC@GQVaC!3?|!+CRRVrY5@>o@tPR +z&IlX5o`NxQHKiML$jhjsHCHq+4l>@N_n+iN*3fbze~x3eK{nBZJpXE2Fx-0!X>LS1 +z00O|DnpYIqz6~~<9fBB?W806Z02V=d{|p)a;MAgFz)|;Jf|6KP^x5cy$l4`R$@MG_ +z6Q;GZH1f+K&WI`u((i4TRpwAA-FqhwnIiMHSMPPX6?dGn8aKG_`Xny%K4E%v94VUU +z_xff_3D%d-pB|rao+IvbO&_bS<-SMFdV|NDvFZ!;M(lp5ZVpntR%wfRml3$H^7~Bt +z;}HzadwWyGO(@p+bM+W_<3xcRhFN9 +z*cVB6bDSX_G09WjY3}5lO46X>jk@!|Z6xy^*H;E$&?tG|S6>wbt!d=uX` +zcr7l>?&1%14F`UA3Et7Vc~SMq3j(!JFzz_WC(w_2{MEVHLYgvb@BIpn%}A@pAmSEq +z^Z(F#e|ks$xPG?H>fAhabi`TO7tgH}mKK&Kgo|=rbBwXYi@e{wirv +zl(%@>0CnVMalU;=gcVzSjV(LShUT*H`x6ktEIip+jYXnv)j1(4vhCOn0?*3%lfAiJ +zR1`?OyQ0b=11_7A#i#Cuj-k?(SXlidLJW|NNjE+8FN8`>iIhug|K@g15Eh|d_pPkl +z=)nT<`Nn|}9iS*MdA2&eji+|p53OMnFH`t>Z>aY3E6hI#gG7-kPd)1(>l1NS(8A8k8R{^qYYwC)+_n#AFsNVUPqW}5M-&1% +zj`!p<5^IW|^YDUMq`Jb_A64S8hT&lOmXowrMz-vLNVPTHmX!J$T{g&eZ8daR&2qmp +zRO~I+S9s~TFR^2ybDFg&bLy@f{oX)U=&I6&uhfYd$Ea-3PjRacp5Ulucc3bGfB*!qzz?an=pZ6kD?dDQz&E6&(W{n_d5ewWU9W0m&%V +zic($zW-Sj#MO|4*sfjGPNx0AogHPO#Y7B2C$6gf}NDW=8gKU=@&m*s9eYbNKcu*wbpAku8FxT1M34fR=OhuC^k +z!LvYUOTN?0gD$z>x1h$rZ(dE?sA~_65%DHk-@wzE#-IAtw0?gw$_R%p9P>cGrH8mB +zBsI2>uEZ5Ru;aF5Pdm7f9fM?#whIoud0J<~nLC1hrhRdIJ$AoG9h}2OkK-DIaRs1h +zAguf&WXRgmG~UcmdC)Akd!t2-nA0$5oUK`Rv|a&2hXmb+z!J(*UDSbeegNbQBR(JJ +z1$oI+zUM{>cYLyaAGmdW2HMJIA}>m8wdmmind+eTZ=HE=0nY*jXv^ +zO%)XID*XVn$@FIkE^(b;Rf;+Y$^#VAdkSVT8nGovrKnW9nqr*46@El6gn;XRw`3t$ +zYkGlL8i{T6dwx9Ny$U>~N_uY9v)dM#l!PF_Wj(i@eW(d7zn}8o#Rsd7>?PlRV5pwD +zykAGL&T9R{&y$6e?O=H?5|M`NyZ|G8vU%{gU&+MWiqv^qXb +zuNu44QuLoLAPdm9>w)pgtAvl9bl%+yA7EX>cn3s9&H}7aeSgloUQg(;Q>H(Al7vKheS4e#0r8oE%ce}1+Ft&OkwqVeKx^rj+9>u!aic? +zRO-hd2nN*w&rMq>`bdyJuT5lPB^#=B+3VME#+l~l{8XG0uetvF^}F5$OOF2mLdB6>vRly8j=TY?syHoT$x46S(3iG(75mcu94w +zC$3&c>|D^Zt4YngI6C%fZ$Dh0oPLt&Zbu2~RgL_i0dGj8y<&d~qwyCaaF11S8&UX? +zaQ{Sx2Xc2;B5i>i>TeW%Vk2V5b4GYPDO*ojED>?H;>@i&>|8`DjC1eGJkKz*-16@# +z4`}tX>g*mGkR@d^;;;?=;?;kV(d2QCU%0)bn@K-3_B;8CrQ=@JZV} +zy1B+1Ez$A*$3HvhIBxG+kTk!UKn>g-YVB+2umY-^+@N`YukdokTb|&L;rr3G6aDxw&OG+Wv?0V{?vkGq`{*bvBP<&Io7TT4rN*QUpQqLTCa{)e^2W0C|i5N +z__4fDV588{fN7g_cxA2&W%)E`Q?gl=5$goZ8>$R`yucTFT?yt?b==*YEuh-J2ly8?~L)+GkAY_MREs!U?TNm{-8iv^#pch#d8CkuSsbao>=5r!@y#e^F3uWgo-ZwF)<9j~6=x!&C55Y-Xt +zM=tM|*4RhY(Lt4d*xjqM&N`ECX>lzFu;7iUV1lm*0Y5r-P=>~xK{n+-rdV_l4GR;=$)HR{-osz?YE>6onGRET*E +ztOD(t%#)M|(U +z|9tm}5UH{&l;+^P=<7~Y%{cm)2yzq#X|TxgE>=S6me +zU)8mJe%#itQIFPDJufHtCF}om)?oM +zu5mn*>)mrD#X8)x#@J~4P)LA_c7x*7HlIGS3g(9$VX;l2m2$>%fOy^{3qqYJB+bJ} +z->J{2zkh++xDis@yV1F66JYxL5Sxgj-CN{Jbv|l}_F3Q!XmLPu9!^d&5xjK_|3<(Q +zlmA+CdulrKOb-FB&}qI(?rrX`J$DnQZCYgB-oaT{mEBBucLFQ+s~BvNf1auRVC6#% +zLoiC%EZ$eGrtgi8|2)1s7<=@6{E6SCne1**tCa~}6AYI+VaYA7z99FwHq7X33&c7j +z%^c|laZ`j`?mr`gl_UjGa)86IuEdtFK;vf9-~$do_TAS2FZ+%{fKy_0ljyR-X@EAl +zMb~tCKq;_=GXiW`HICY}yBs2_TK^id8CRoi;~sO$THGgzaF!xVv6Nx(^UC&xc)ivW +z{tlEZfs0x0evtIYcY$!gI@S89E4PGl{0_UN&Y^xz9@m21mym4|X=-NwchqL;+K;z$ +z5%c+;tXBq2O0NQZ41n! +z_h;p50nP=tE*Z~MdbpT>Y0*fpuf%QgD3H)^GJU_X)E%f +zJ?@BL!?HN6wKiP7_Iq>H*!(LqTMgvl_-h>nH!d`5yM5R1$RtqUb2^u}M73jOw+OP1dv>aYL5C)am +z-Hs@~^zZZvynrVNH8nLWVdLVJJw|K(DR#Q>5P6At`dbOs*~a`RXQhuQa*qV^Yo(61?qT3pSEGzz@g +zCOLh{bH?g}sp>{Y6tZyjg37b!k}n;%(pwOTtUdt^_jWSKn6^ht2{ecM@N#mB)Ln*r +z#;%0>7vgy0U@)gN3?895Q)_ZjoUg;4Qfj34H!Lw& +z5y(RHzx4=#wovlU0hD4BjE#l5Ak75=`w{J7WAW6B8U50aQ)|>r=;!M@U +z>yLA9)P&3nh1DYOQ{^tYh2kz~UW4gk&6nie*ocGxb^wGqaAA2G8ytq5ACe8YbxqRe7ztLg5loAvmqQK@%ktLf6zmxi6sfo(31;6>baNR +z4#29b&&7Wh7inz3O8x$4B|tcY~LNF~sAc{$a^~*Y>l2e2; +z$CvC=4W;o1ky0NQ&_zS5Ey3-x1j6ex7|H>>HeOZcUHQkaeR3CGj_fuHL%<1S9wM9f +zAKUSIB#swKi7Fl7PGfZuReM(pjXoO*ALt198Yiz_=m}|!VRs6jI$n+GFKX)(E@DPN +zu2zw4Yi7&_cOL9)`|;J(c42Ns-4dN*z-pPXWZqJ??bd>_ROh@)hg-9^Pm)RTdtGG& +z-p!#%8BvhB&+#OOWJ;6lHbR9Tue1Z +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 +z#;r7SMr<|B6d=14?L +zlJiL$XAihoRkADqFli +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 +zm=9Ha&xD +zE%G1C5wX2zZLmp5v!Q0qDE0kyRum|I6ruQ#&;D66P&6q}cK`esoua(pQ$#G>Rb;@z +z5z>~N*l#Ed<|BB4S#C?z_TWKM0)0Twhmaob-M^+J0)^iY>v-6!X@kaLU^YN=E`cVX +zozbHY0nx#|-P|^c=B766lD;zXz}0X9qyF$3!kwLbBSM)<>K1gd79Ahjs|a^qMwas` +z+Hk2LVHEb-GV#h=uARFijOu`^ICv*LQKnUCNl{FY^K!m~kkBb9TLji>rKs7HBu_!} +zIU5^I5gE%{e6wY+UOEZQU=Px*%n_x* +z?E2`ET8`O-P(ibUsS=9M>~xuE*IG1>I4L>qevnxk9|z(06HDkz-vwR(^^=qKE**2w +zyT>`ch`OtZyAexDWn;Klc~%(4VI3EvUlqiAf+rk;x{4HNro+0d-dJ$XQK7=0=F% +zVnpk|lLFNzeym;RoummaEy$Q4GZ$7nvrEP103i3{WtKj41}Voh +zHWHK;@AzxamIWENA?~%DTw%U_9uE_c1|t2YUT#=)xK6D$!>0YaC`INSOdWzfy`9iN +zchW-zjPR@GC$oV`@9e;PlFE`qC8x0Yg6ys^*&ujb1(3SvT0zYEw1s})ZhX}s^yCki +z#5BdBA*tIXxOmge75Oi692)fxmxx>TKsEVWOTYBBlxY)5z +zK*Pn=Bb{zm+#PSs<}DZ{@&Xcon=y^EL8rq;=tul>K`Dt3$zjS>*;R +z|4O4}RZXraUv558jgbxzuuqpxAu$<6Wl!Vr>=}`0w&s{S95{11pQz1hMN_?p6S+T~AasLTc))>4e20_rF~o(==1Wy7SLQV9-%9K=Y-4oqo7 +z)X++qPN3oPNlYNE +z|41VGCeX`Bf*f3thxD6Nnn{&n$9!hf+~p%u8-e6TeVYN9g$X`Yu%zU2_go@GwxZtR +zjxJTWmD-&uC-lS*<-u#S`E!xBb>>-!cb*~wK^&&!5{{A3!z*2NT#KeH>5w=B{iB?=kl +zWVL1HtY@jM2u9BX7o2qbItX^*2GWfHJ48eAth*~2)O*|&C5X8P8hCXOf!v +zoo`LpSEyXtB(Q{B9C0JbQvkI-Pu^-9Oo~jeOZYI5+y+IZIB*)hAT?(uwtAfOofB2s>_8ki?Tn!HUtfB!ZLH_qhhji}_9itA6YE5yCh{7c9B +zICPz^m57A^Myp%&1&IOt9-m&SH(REj8TtmdZl7al4`_z#f;z!{n!Rqf%?4c4EqUNE +zV?O8N0EP9Rdzf7KpNC@zlTC$N3X(<@w?LEF010g56|-0&yb|k_NUm;bC<JJEJyID2 +zHNPt|g!~_I*Vf^n#umTIt~?geZXG*_j<$(moNMw}bN+VJT0(zw`7Fe?q~p3RkZc+J +z1m_OgT5Km#t+NNs8nx6?EfyYg9DEOdVm8-mw +zhoVN1NysosQR33aV@}Q_pPk^QV`K2x;j5_pl7@(N2)^4DDjyNP-s5DpRC-%^k;MYU +z3=(|A@s|mRFo3davR4{rPV%w)7Q=HXJ!ob!8Zyc_h6--73UjzUE$EgHQMyP*&8TtE +z3RLAn!+~9kI4b4E{^oZq|L}?O#9}+H#&V+-%yO6wpv-9=t0WbaRfJlQgd!k_;X>=m +z!j2}GiZJR^g=(I;Hc79UNPD~%qC9T|)sHo>yBG#luL0z>maZ?btWng +ziehE%fA2O4qGe}4!38ffXPe|1pNO42>?!<<*5t@Ty_c_$n+-{Dyn3%{L#tIkA`>4R +zr4axdtru_hZ~_`;Mw!brU%Ua(Nv(6lrrfv~x$%o5sxvbem?Y=}7J!V<#!8o{nH0D| +z?22D{mNj$8t^GtOBLMCrV+zY6zVtRy`CyI>D)^$_JDw;z;r?$t`94gb!cX{Q%*DkO +zDN$2{>th)%MFGhODKIB}ITQgRi1NT@51%kc#`Cs0ps}LnFtKV=fbJ0505DCWo=6wl(cPt^A-1rgV$cGkK;OT2py2Dw@fw#!dVD!H +z1!j35hd?1nmR+#8tV`%(hCUFDLVD<$4e{W?lv9r_R+I2f(7J&S$Wc3G)h(d&Dsl@kn!Gc+n +zyueP&ns+)$!bI6i;iz`>!emzph3At_C;Im(d0)XiZ31v_#ue}}&!)Dh8meJGCLUAC +z!qQv_aP|Qdg&x4f&QCu&HG$a{vMD3Rc4Ga+mJ?SD?EBBq%RGqKvOEEIUXoO)hc>;9$u0xiqed{;r+0E#BE +z`;nd&>zpBv`Z`Ea;J~94dXdgVEUFOp1;<77E<^WN!`)z +z9M3LGo5Vut!~$LcO_EBCnUIUCAw#H!1`N=Uz#b8mv2IyvKyw1m~ +z#09`*LaRbVj5?>!8Wx=lw5XoQMqxOd6<&}#49AE-DR~k9NhE#hr1k$sF)DEJv%4#Ka +zQPnB0G)=1c*gtU)2u$Xhq+*jMoon1k0iL-y0wcHdkXkt^9h>U6tm$$IaNtu*zlk86 +z)Sjuke@!7!h%s$<_(zs)94=81O=cvr!LwL}>J}SprRi(aKg0#vox8^(*H*N@@HH|7 +zT+-ad?5mCd)M{zuq-Nm73+ +zxar)o47I3Lc!kqPxXH6vRc7m%1v!~}3ogTQkVnn=+`u0G65;0{iFv)s=AmL9WUt)x +z4C^_LP`c!`rh7t7#R2y6YA-hV$IC_mKs^jJA1;wj41?45Wst^8gP0V!W}x2s*$-U9ca1S^xB6_*nvS` +z8KE8$6?y9IM*4UEpsps_r*C{!@g+;XEsn22pONK^!WKka)=^D=JNDd(fT?PtJLyD~> +z+!kqqA@eroB&CZDNq3h-NqHO(ARwd@Z^8|Dxe@88K^4`SvdYFV+lR(9d(f4#>Hac) +z=3t5k{((ctPg)AvQJkpcaM13OAaz@!dMo%={g9W+ugOWDWhE}tV^$fl8w6QN-MxA# +zp@%Hl%65HL$R>22GT_+Ffw&tcWa1aCOA%BU+*phGEH!PW@jqYZ7n@jvDeChqltRTb +z8PqBAZ5bN6w9he7xHl +zWEVI@-+O7>Yd$R0ZLi#D9xc5*R;Au(9$;&HB39izRlWSP{vo;%>-|W_8oUy_k)5Y1 +zCreET;B~9F0~7b)Za_>_b>q-)DB4U%p_vgmxmY-pk^#yWr<{_Id$Y9Z5kj5L3R0lq +ziFnuS(i{@f5fCF%M?V=%5eX!`k}6WRa4}v`NxW@AHRoDJjiSXkPi0JBk4C##T)oYU +zv%Vo8dSpsOc*@wcPdH%=j8T1b?)9dZTag@Y1dnNyGwl&vm{h_c}bg0@L^4WT5G#cMm|_*y&c~%z;AA;JdtHUqMzl +zMA9#wkoQSi5QZVUU1G=-Pf`Az6wkK&P$yO2&PU%bh`qF1%vEp9tVcIJ8?!wyd69H) +z>K$gnN1cahrJV^TT~XYH61=gX7kW*W`zG0tsF5?RgL|{*c6_lS%~Y1LPKj{~2S%`?oBa;5cu} +zzgYwZ3Tjt?=q9glH=1Y&gc11<(;6p5LR=xex0``0WO}E)dpxW#1QQJOFH{j#6A5nP +zJ|yAAsR?p>EHURS7tVQXg?o$z`!ZRsSC-&yJi3hu5JU(Khy`xR`{0@I0W);3dMJhv +zsH}hsNhZJW)S`c6+%_@Z;Xuib&BTliw?2POyFK?ar+iudOwvdWQNWHZqG6koY20R6 +z72be=K!Aw&C|sFOoa&3=S+Tb@hG(~t9mDp-FE4LH=2|4FVb-qks0t6+nTe9;w +ziS#B55!gIjaV7i-5m1CmRl`ZQQYA9 +z)X$EG2K)s>Qc&P!3pNmW0O1$pQmuDIfxx?GmDt=|%XH;vF~VjWfb2^}k)+$1!1$e^ +z%YBrI0x{FL%-4&G$yvivj})W-K@7X>=McI|?DYRBYb?$C-% +zkwo*}wSPl3q08)e2JS7bW!9;s!$&<*-~<#^@lsz(p?2bEeODIa=P>&_vtf2^*tGBy +z3tdXa3L}@9`TB3%v>z^2df*UDl#xQRKu8nF;4jjz>`H^-k$v!dl4Cpr +zkRvn<34=elQjJI1*-WbuCTJk0R$z%tjmY0Bs!VXCRT&23%6`ifky=IbgGoYx>pgj& +zAmY!Js{Q2s%(f-!qEKtga2&eFj|W-`-G)c9mO<8W`oe!i0P2k(!aM>MseMEy*972C +zLzJ^&z>E<0qnT8&GIl{prp}QUxPXg@$eMhx2++)PSpi7c`qdJ@t^tL4UVo)F9gCjL +zE0Zld=jm%BK#U$hFGrJXRE52F2~y2b(5>y_0#*vQ(CUEO?Dmh#=Pyxa+ur~-x}X`rM#eP5jy{a1xGySXRoCc9 +zHpjxleCJ{+46WVjoO7^{{`ETr?L}V?3-qlW+ZL@U{+kC;UDqE)X{cJlCoOfAo^N0? +zU?e5U&I1>Nv?LjFEqy{1*0SzGrtVu8^+Q+|*7xse7a_1+PneuDQb%Txas|__DFgli +zmazf?@yBqzkY%>xM6-64TwV#>SDu|!oDKV6v%vRPftC&zOs<;S*MWw4IHk1jm;Q? +z7v}3rQfqT00Yk**t5|}>OI!*~L@SRREZ)7dsZ5Otgf^cGFZ~A2Q?ToMkYZdG$t0a_ +z_kDlk2qgFAYlqT|cI{DyE8A#gvTOT;MHY9Lh)8X)0^O!2RkUI}=hHH*pI*wCTg~7{ +zc9zbmH5(%(?W6^@``oWK_u@+I|2okv+xu{*K(^38< +z^lMS^i9+Aoq!ynzG9Bq-3~}_hNL~voXG<~9c}M5XM&Cv2O;|uiB=~8%l=`sV=gYa^ +zug2&I%G~4xYSo@`V`i#FW|lQd@zlv?3{xT7CQJQ!{;9jG_{~!cC5rq9NWo{96eg`F +zUs=QuLJFBygaR-HemHgF#Nk8&b}1xR*eoiBD(P=&mB#HXC9GVNLylros-EfxVJqMz +z3Av8vedecq<`UiOA(Qj}liQ6pcHUvGXXBG5? +ztDlP(qz&FtgRJw!{V +zV;^?up4{`%YnWH;X4pIqr^U5nC-zNFAP>Dy)538o=DzjoYvy;m&->fcVD?Mhjpa!o +z;L>h#kn}xSV&A=a>uQI!a2$)@#AIB&yxrc6!|B7}`<8dxw;7*R(^!&}ydBhCyfuwY +zJCa#Aix4azETZYTWG6)N&E5rz{Rwi_h+n7kde4Sf7E!p3F5bGYeBd9iD~y&;!QiI? +zw=~%XFJfUbXP_ca0vZZ(vO>6?aG(2|we{NiXT)iz*vU2wz*^dHNlF!jFC~*gmI?9W(i4n``oe7>U3>yk-AoJF7c+PPI~wU +zWZg?%Ou?_*5M^F{U$yz0=G3Pf`lG|R8HsxtVLe&8#&koq@X-gNs=SO3G2xc<11i#! +z-XD}s%12@AFhLb%U-5CJ0@T>33YzZy$Ocgu!8DPK4o&`m7X@XygF1LOUh%{Fi|F}y +z0<>U{DDSjrvx3}r8PZdXtlB50JDYUF1`-b$QEg!5X}93nu1XA>SPGZgHK9tp$PtFcFr^S-bV +zl7%E2b*?in>R~o%7FI#*vo-rmqF{?q2Sv{M5FU{(zhTW%<5vTjn^qVHLh`+-F5C{@ +zByDryQOBN-#r(^;U<1;W5e-GdZEfzUZC{mR7!Cfqa89k@U2#YF4zddObijJpn~q%~ +z^8juNWHZtaa}}h`=H=}v)hEWP?;3uJ0_C4$zrea)<{>CA$;7ccFPGww9;uKN0cs61 +zX$)d7ofjFa0>T}m +z#6k@_ZHN;KZc+&?KGWc +z^D&LAJVIt^&Y%F?m{ucWIP7i}*c2m0omTcS^m92~;-i&@xldROHL%bXz2WugZxEi7 +zw*Go}M)A0ShQjEr$|R^E0qMV{^E{(*5Kw-vI;OH!_dFt|?LX?4_Kp?;O +zUE=hy%P{wa2G>#(LZunkcj$(7_D64r_Ljef_v|pVI4-+}xN@J`LW4g+zuIJwBd<3V +z6Kh0T<44t~c+N|Z1yW6aBhPY#?j^u{BAME&3|5Lx>);s$$e-;7PDr@wr>ZR=7S)^txCD<$-=*+Y& +z(;;|~mB`lYh-CKR$u7C6!|TWNqMqevHaU`)c1?B9^lcL@GoFe2i_!PIGZwW1fUdC_ +zzX<(baJ(Vi_vDBrW2Y=FhW?PfmxGAl-R6RE-QVv!-~N};xY#*@ttHv`sQ!xh +zE_NwnzftB+5Egzf03mkf-+~t{{Q10y?7ieX8*YD_e&tm@)+f}m +zBpcmWi%a&lPy6Aym_#%Vg1FDtwFNKalM|V^?Rnm&fY+QgW_3` +z;oH0BW~QA%Qj^@@!h+lE8S^$X1%C0{*t2S{T<%*;UFpYaCI5bZ_}+9hc5VAHVVA_1 +zXt!b^zb~##6X?zMksY~Ba3{e1uF3a5?3Di}8PPvDVlkTXy_~9Q$B8+Qljo0{7o|;H +zZ8wwvJ;l89$+zyr3f7B0<9#jNnYu>WyE$_As(h$Q#+$YW;O_Xg +zGYg5QBUj1XuUVj8r0YMyZm8Eq@V0GzJUS#{e)?_1e#=h6Tq;dUk@xFME;gPZG+* +z&!5Fh?Jhc%SL>Rv>zA0_Tbh8s&^c~ +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 +z{Rp0BPrD|5l3Vf5?7 +z<<)8q=QJs)zYuw-;h&jX%d%bFu@F65w9|axOZLTYdXVWfFeNb*Xw22MCd`DUqU+jY +zY)`)!&VEV_7mAi~`Ajbl&Ut<1@mzBk05_6+>dbIe8FH=vcNw>g>yJS}b18$-8|$gs +z&`oqWgFA)KvTeI|ustzk+G%v8l6S)2=t^?xwPbjy{a$IfQ=PVCpU$Z1aL!zL(fe96 +zgVfol(@9fj!&WpLT_NxJJvd5J{@xVz;s0Q7uhl?QUJ_CM&Wx(2zS{7nIrafj0FL`} +znEl0gOexx-tGc4#IH*$2SO=7W+*QzImx9*-v_F4xyYcS!4qB{kc&33G@_JgcuEkDG +z6#{xjSkAiIg0&OR!I?<2zbJ;(wM@YLECtKDgwnb|+xk>%#dEvGl;17AW44@>VLEV=7uftvJFo-uj>?+RK% +z`Y4-hOu-a*^3j{?&u%vhX*ad@C<+80taYPc$GN+Mm%){E;Eu#%X|j1D7rP`-2jB+D +znD5X~2y34^?bbmx_A +z9aC~vUn$IwfCHTdHwK#%lo4-Uzx$dB+kEKY26#@cegr(8dw(Y4QFqmu&ysIUUFYs` +z9B5DL(3)%aH4kx$*oHttz4- +zW^f%1g;)~vf#29k&fWbi5;5t%tP`t9pD +zNCI#th+stZJCydGqzpI?hr=&8K!?&X(y7Cs*(j{WZ&I{eS5rg-z9WDw&)E{3qC@$WO?G$uvg-iI(8cRHuJp +ziswhw2*Ud)Qv&Jp>oL|R6VPnN>pQ@@sZKMZ9m>3aK&6^n_0fvFlk@W*)Zc%E*?|?v +zcu}Pd82+@ESG;zhQOof}pj2m{IxUMdu1rSIERR0e*lz~7K!^ +z_v-3}&K_ocu3xaa?OW#n1Y8`IzivD@R?+m3QHZ^#87!^pXJF{B|Mu$} +zKYPI+H!P{aHE;jJ=szmo@jrf5fN-?wJaq+0vSc?4RyQoweGz>_fv#mC42v(X +z&ZmhkiW1Ea0!4lPj?@Es`Y@c8Qa_z2lUSl=UnF)e_F7?U` +zRNaF6m{gezdmQz>6ELH@UN9?`(B3azeN?()o8ViOn#jOM`>w^HZ*_!2dTawza&vjw +zoSA0eMarCQBouHnd)5&A|C@(@7}`JB3d`I~bIL%RVT&bM^w9-K7ig2i22OvylE`~9 +z;F6c1aJQXfUvaYv{%NXHbR%u9^f($v^qJ4`qxtSLXw7r!rQ7#SrUAXry^Z6zNyclo +zGZlvPb$i%n_43w$o6l3btpC8}fAz+8rlw*^nKqV$4qd#tdox?(pG3J_N!Pf4_j;y= +zna(UCdMQlgl&tct4no}pq4z=P4EhH8HVFM82>me#eP@5mGi*)r9$y}s$=+Hs(X#kF +zw6-r9t~~8Dw_D|!{~P@on)9Iw^(mZGWo}dVV>s&Tm$7m7RNh_E__|?yU_@E-EUN_dwTEDHjJS>rz +zJn6svdi13S#H2&*27gp`1({pS#GdWok%B*h7cuwAs@djztbyq&c{gbI+-LB3RCe4g +z_(wAF@0e=;E(TL*N^|F*~9)(#U^Ar=qa;SyRe9nwCXtcl9=|$w0(A{)N=Q{al97qaeK4C0EKp5)C^~V}FLf>Z8KE*d*|AUZs +z<-P`%`Wl+mxsdn2XFps1_S+J6IrGrGs_KtgM7~n1w*}^?wp+7^Wmb)M@D8At28cS6 +zHeqoYLEf1A^EU_nJ?OdDGOtZj!S;dZwlB(B=` +zPXRUuS|n3eR;3KYDFhpN6G6wEGnwn~Mu637y7Xw$0@j_>tm^NRXj71S-pM(r?@v{+ +zp@7_$%3Zy=A(U6Z86XpB-#m?T2JWxGLR2~;UTKS8ufjW4i${Ge{d?XBm6yM)^u6}7%Jjo3r_=C_RNeOKzxv~(NsXy%AD|-@ +zPU>o^_AU#S>)_b;tUeTCe0fDBd(j#{0p0@Q4e24}66&P?Tb{LrFxRGPUMB3R7PWcu-IH>!@4(8xtB2wB6wr>FbYHO>#r(CwwiP>&jy64xv}*L1U3J3?(HDwZ +z=C03HY*|ya<1yVqemNn}xJw2M`TRVfS;Dq+ynH2Z-WrD8SP$B;7F5{-C?-=NTw~yj@qm38{xk-l#h`|1}X)|sn^R0P3L@xE$Zdm6l=Swb} +zBkk_1*>p#KP}cr%?VGRv)BoJuz5VI^SAX|+pFe|^PV}<>`knfw1nfJA)K^paxAH2v +z`f|d2AEB@NsMI~i3X_$~?kF3``%)#(!*zAXk1>@%8`0IqSf~8xEa{6{#yJO6-Kzcs +z=4%d}P9NX89Rbhid)9WbM)+UkS!A@#n(jl-h{I{)*8~e>4!FlOqAhiQqR{s3|_LWYd_O+zI1QprOcW*dP +zvb)!Bf4ocI{`lqxfU09WQw4r1H~r_~YLj-_nSPn3&ihvG3~%L`5cpyuy{Y&0FWt}Y +z-oI7unme$R{ZB*5uit@EDwNzi<+o7tmOt_8mvsO0-QP6j&))&J>}19}c|!K{Sn;d5 +zM)#pcax85xp$Xf98n2|ss;%j--?eEY>hAkMf4xhz`oukxv>>JuN&})p7l-5CnXA!h#bh6 +z+$JKMAqLq9NOUVN|K5Tc+KSydO&NQNN@n&e&GSO%@-a(lxGcaX6M}(#{QxH!UOb&FFnAQ=Ae{)=>g8;pz{Xcw|OOQ +zMN$814C!N$OZ}nt9PQZY)DvvRKU=?8Z~rPDhhOb(_^Zr^zZf5(Y;09d?Qb4x>qmdE +zdLI7F#xBIvaO`Y5qQ={?UN<}U$J-rjs +z$)%XkjztW1iPh#)4^~sh2WNB!?{DYGvKYzlN;-K8JA9$pZeHEAZ;W{~ +zPiOczOw@@agSNSO)n_Uhl)5y3Rg*&WeKl)B^nEo$LiBy64LPsxYnc$D@2go4qVKC2 +z4yx}j$R}4b7gXP0h)@38hs}(*OBJYEpnh(3$?dD#q^VA={Bm0L(BA(2Y;SX_Rd0+a +zZ2x^m`SsOp#?r^zc6<9>+b3C-_A-Wsi7{idqIzz(n{ek7u9J0}EZ$@fMTae8TH34h +ziZ%p>nBzVZneuux<$M>M6HMptKd1@OTmxRjUJv-xc{Ue^C+^%_`>CD@B=40m`tgOz>PdH2K}|&3SY}yz@JvQ65~0{*7Wj=A@`k%(Q$qAXWVyqJHweR;yFYsmg)CrLNs-x +zdY3;wzdiQi@WY!rz477`uWr@1vRXU8P->Y{o4vetT8Q#e(fiAyjYkZ1fmwbDeXG8& +z`JeJKU~~JO(pwjB%!Cd-kqC7aI$1fNo>Bgge=PLa*76kML-z2?tH06bBYjt0CHC=` +z#WeHe5k>vW6|DMSJ~&M#{N&qF=ThYJyH5kYJeGw#K)kZpd@>|Zb6)9{$-*384 +zoALKxgGkWM?(fbTXv{=w$Z{it;jPGS<@>BV{fy2mMR%;@G70ZgJgf(+g^ZI{g-XKn +zQ9YR;QJ?7u->$#SvclVxS#732zx}&!g?fTPe@#9npK0~O41f4HuWs4ud|$ev3$!6$ +z|LxZ%*ON|O>vxoiqx>{#wlA6E=?)j& +zkLmoW-KcAt9nVziB-Ejzig|5q$}QDxHw203%1NklRF9#a+P(g{8MtpVJoDyMGvA!u +z{6AIOO^FHEzcf7m`445at@6A&eO*>nEkFJHdd$iy^Az|hSHIroeX;aTiv4|-yvyF* +zzsatuZh!dk%^Og+df2a7nGJvb6RX>=^#|kn8>#{D&q`xzp`Em+6i1_45yalSjop06 +zzW!&ExLUU$vRV6`l2!bzA=Y=hx-)N?eUu4eKMsnS-YWif5YIxH?cY+-ap=C4C!c&$ +zRSJ!c?HoMhDQbuJ@4vZOaX? +zfBU@xTHnPtbc?(X@5C(hn-4#z8VPSJqG7{3nJR;TteE~VhTUsm(zDeQ@!Xi?1s+m$ +zBOZ$i%v8G9?BK!W(@7bZ=>u}GncRa;{eqwBx7=6tvr1GOhN4dGhSK-+$JCR=T`Itq +ztUix8yTT$(#Kq+F3Fwl{Cz3-JL41`jIyK40YgCUtAT>lt`$V$lduwOo!*Cez(PIpL6-Amwo7rE +z>1?)z25cJM_IcM56~N@TYnV2naWU_q%sXsC&Q>{FDH>%p +zsV7?@St`g@I)s|>6w9PaeC08!3r9f^D#29(uGo9BjD*w{OG*flz^BDl?>2)KViFLRs}3>1UtMPezt8rmOgAQ6|3#^X +z*Yehx5}rA#d?v1LkKcUI*~Ff>3@9q?MKIJ;eH||IMlt;ccxI--Hy`d^>y3FY6SuLN +z+Qc2?V`!A4-S#z8TN6^SRDZmwp68ucsVK;{a+lnQ1N@Kj?|E6JGAVB>lfZhwlGjY{ +zt&w`@nyNoifQHo~lL~ZhGx*#e*aM}aq*9lSD~yQKsUPmpA=cC3UuRH9gUiHLRev;SzR}1PF`7!kWg; +zmnI7)sCM$aP96{VWV6LMK+*?)NAE31cbbQ@;8NcRpMM68vA;t6%&|_EJ@PG(Yjd!b +z@$8CcNgUf@Sqp3*EQ{dU08i^XdVbREzAksQx2vzQh9-2fqlI0)>uTCbw@%u08qd|3 +zu8y>{qNfKP&FAPkPrG4#hBX+Wvs^9Z=p{!JVcmnZjjLafM!`D7(;A+ha5clA3tZ`U +z<=vHVSEgMlcI6gJswto$hNT?$QR*z5xy7U +zyGZ!##q_rt7OeMSTlrjk>3i*Jrm8Q0>tXek`5V8aZ-KHmdw+K(=dC$;riFy<{Jqr* +z@7N)NJMCej_SD?TOz7JPyC?=6h(G1nj!+?~JAks=GcgSAv)Zw=OPW^wIzH`lma!u% +z1;1$zYZv6-2Qk!cet*{Z!6c&3Q0!nK@NhtpHfw%V)8Q%uiYz!#w3Bt9XkYENrD9cX +z4Ki9XKvDS3fudlE+cQb739}Fs1FF4{rlsg+#pu&*aNr> +zIMn%2CB}ck0BFS%u>JVh4uEOHPPswRXI2-CREi5mp-u-(h`t5i`+@*4qsvf?YXV7> +zvjCJ}IS=gnATAiW94;7zZe1`^{u3BQl>sDRX|Vzw0Mrr407Lp|03ek(0Fd4p07&IL +zREgsY65yRYF{jQrBv3lA*rbdQWKJdsfxCeabTtq{joCmH8MlCh0&}3qL^x0s7k8j2 +zqCP?WfcXeP#%_dcef>W{W@ms-!bS)(UlO8si#VJ=z)*~Q0F*wJPEUFRTQ>~0&d3_B +zumHXuv^1Zm>yUOs`V46>tg~D#<>)0}6CvG$v<=cPNTVPf;%E&^Pq>=F(gl|ETk>v6 +zIFe~kify^ICDoQqTN*w2^CZrfF<+{DIr1gPmK9q%Ys3lw!+FzgT51Ej%D~(G1ywMrI20XD1TF(me=|4(OsG#32H>YF +zPf?@kA?Bgt4IV*{wY^R%%lDJlanjIPn3bGbnR*|)<89XpzLPR?1yqPm11M3ozxi-? +zr-Nusbrc=mlMdy+n{CR`w$79zksZp>_Xwuk_n(JyVk2yU{5{bGLLUAELfg#=g!WMr +z2n7K~5c;ZT1mMVk1w;ET3x;lxSunICvtTGHV8KxQ#D)d>M8NoCl;KTZep{Eu_jiUm}g>_i9sfom|+5H*#p}AWj+5A*AwimPLrU|_q$D{ +z9;?2JH(+%Z;v1_LVDm;*g$;dI6o`bH>RWx-uLkNHB_GIz2 +zh>7^9hq&-hh7)khdwZc1N=2@xvhHqq=BC~^AMW+{g)%Kakq(Hr-DbGy>LaOu=9Vi7 +z(+zRvp}gk@aT0jAlocYYS^^+1*lzQu`?nY-F@SPP31n@K>+@V2OX3T@Tt3*`s?N~& +zM+hMoV@!Z(H&T;?)PH1Ns(sb*yx}VM8gKe?hpQZ_ +zs(#?mE86HE8lF*sibLN#Zwi)gPMqiu{|zYw;wCg5bQ8pClicbQ_*UGoFv$ +z5TK^8yrMnw2AE#}rxS4TAQut^;s9`D9p4-pRvvf>U9>`8aVF^`?{rh0$ib;4Y-Q5N +zO7aiNmoj7vz#*WjmO}JM1$)?$=M;C15F&0kK*)gJ2*klT10q5{8nRJ*)sh|eP0soR +zlw#iyf;}!1v5q$VDT*F>*Ea;~9CP4{j>1<%cuB%4IYmThC>GSBK{>gYP~MXL^jtMS +zN=E@&3ZhgpMbbUsl(8qtr6k(`%d}D}w)i&C1VVAP33L^EWDJUDLR_QanhD!5Sf;>L +z{*Jmg3f@-ft`c|D_N1sM)jTOtvDxD=_^O14kraTs61c0VSQ$4 +zumznpX{kvs*_z1KJ+`*7^^2`hJRRa_4O>spn!(ovuJmJhpCsItX;+Fzxt%0+lFdmP +zE%~!0&XO@KRgN4vlH(0=blb(f#@Pwj;RA>YFg+`mc&wTvI67N~TFEJ?a%Nygf2`Z0h)yRu`vi#Mr +zhm#j(fxqNT>PORq$L2YF2e#Y<}>=ksk +zk#^9u5wlU51`p8ql3szHI-bq5hO>g&6$}uxa~S}b*9`z|n+5>7Of!v+_dx>;T_qR* +zI5+74!BL@UmiTso4Mg`vMxejnwp*cFA2tx(RTzNiZid|oUA!5I>tFF10O%Tw-5vT2 +zWTfugIOxVlRaY5h`E@xW`A{7%tcD;a(Zwj@p^MQy6J3lxLeRx%_p6JMC>zvi1ZSc$ +z^0|)LFp2^acU(poLcxNe$yhLiZTm2 +z0#lAgGUYg2sLRneV5Xen76U?BU~GcYqH6&9Y|fM;1{*r^`F(|+whD{!uexkBZN(IhyOs7%5!iNhoS6U$Fb?y&X5$QJ8P%sR2> +z#E=2o|H5f6oOVr41AovQyUROTSK8kXU4{1dV;#WY-L$`#PfwNDBCg#&58W+oe8+l# +zjXw3ytCTzfEt)wqSG0|bhuVSD^xrz}rcvxC|N>r7hn{HYPC +z`f2W7$rg5EaMc}WdAA>bPU|6mX|=Evjs7#h4ydbxbn>P}*@-ks)H7q`Id8%qSkhE1 +zOIVo^ySb!K5B!OzERpX>s<%gRC3*LvZ=STyof|3L>*PvAb5X+oOV)`*rgxw10Y;H~ +zXCNH>1$L_u&*bALy755p`Fgul5ZLTEELdkR%JF(H8bJTRfXNDo!> +zqyuLN5zRi5@KwnJoyclk)$T>2U;CJ?)gAA5)qIsh3D$7;L|~#GriON1mFc$x=ni0n +zrW$m?OcjyITimnYs%b>)@Z(IyryC~Y`y|f-FoD$v>7jw8ya6g70OU0M1fn$IKwYRv +zc$qmh=CDkfv^$0>Xu+yErw6hni-gO^_wLCp7y#uvj`Faf<20Fg9ncKL)9%=%WXJn1 +zRgX6Y+V1<^9+rT73#fR?t8yo=d$%Fd$nKwcQ<11QT$BkXA58$D=!R#3X8LY<8eA6T +zh}cr)2ZZ_KMu}~A^dTp;r1P|qv2jq`Ak*o-k|&aQdZr4jKm+_0sL^G55t6=@)by{V +zdbL969JeQP10N6esTYrOC1?B4)XI5Tk*^OTV$Sr^XW;mSjY!)!{KU0}@dGQ8?46HF +zaME4V9|g3SA8#-ocsK(YC{IlLBr^(ja;G%k|5Rt}XufWBI)zM5BILPjDU%E?(pn$s +z&6D}51byFxj5$99R#GiO)$Iya!lp`@Yf=sL?N%hDPXO9WTW5L%+xyzaIgYMES?zv0 +zJ{5MKW*jEpMY6pi!vC3fb>^L$!JY9P7~5Cz-4fpe!9E9aFI-Q;b{epo;Ccj;@u%#( +zXVN_*j?Fe{s43HITVZ5yv5EDJDq%(^!)e(_*DCr3&^LLWb@S|*W5FzAMcF0W64|zg +zG&7W8Aq{}7@{xAO`rK39j+UO$%b$%=`fTf9TisF$)>El7+S5{$Gdginf3~I@mD-&C +z@-)_@qe2_P7k%-fFJAP;i@tF5#Wx?`=zB5pUYNX(MsELf&X9*HdGq6I8r<#xSMs6O +ztlHHgr|z=wNBL|#0g$)=#5ywB%BO=@F&usGyAo+-Xz{voA= +zv^68Yme~XDUB3m!Y!3F$Qaxa}H +z2~^XV01NGGx~{4+ay2{lsE9=kc9L%?cC##U;>kP>o_YC1ZG4}}2fNlh5@;`^&8`-M +z;uZB*&LXHwLYkXhQhF2^<`%H#f5u3IO3|0I%nJsm`YP!kRW|{OXgCb6Z!#T4vlF?H +zM`XA1x^IpJa+ezH(9M$-G@2&rOwF2%gT9OK +zgour7fYx7PG*~lzS_xI;%u-gUw_bG+9Chz{xxn5HxGSy^&YAoYULSkw;Xzv +zmkJi^_Qr{vt>_Q#BbTNHiS(X5F>tua2PxNNWy5sxQN#1M3x|mg2)hUdmj6qS46L9} +zYS~lOW}>U`MLy6zrC>WseiL!niw56JOsb;fyGnk4LNw|*IHo;s=3cRc!n$DvS8RWi +zVz7Fa7zg5DH_%lb&aR!oPCTDPpUGlL`mGc<7p>IOxNZUu~cXOK~KPd|0>Aakihk78>X6}H)6WJ +z>jb{52PzV_i0CfsN#yyS!8RM;`g>w^g_G>9iONoL=1A5gOP=%)@`5D9l8H$QY`(WS +z-REtan;rhOICkREkt-cOv^j6&HIKVIe)2fTfmr)-wa4{!R&-dyPzda0 +zasJec^Ua61uZ_A)rYFacDji^0&92KxIt}G^9$=PGE0~48*rLAVEJP_<`X%T!{-@t% +z$a_R}0kbzl13(pf$}2D$y9!`3)d39NnpLbMe;@;A%83UXRQUnFJs`_B<&NYO)uzWU +zkf=5(72q&!h?g5w8$rKlpLFc;!A5=~Dk5@*^F?^dWb$^5!)vH-2Olyh&!BHk6zV^MyNMI++*6$PuB9renJ +zZb$PY_4vv-4)I8jp3^+dHzlnJRiEfVFl#L0Ne<25Gdv{2$M}gA&8l?yrk!7=G(d6U +zg^>|!;!PmUVbqiD237~C*B<9#-8|QB$h>p|Y#tZtl^TtIK&t46RkR??FaAbQ{<%d; +z;;AFmu73(BD_X$A0}(IbXzs+%A&qU&hij|sw=pD>>6na#YaS+p;F^F*>APy)RqT^0 +zpOm+&t|tXOsbp6PPiogyw3BLemFc8DU4`kYNLMLNYS2}DuBvmD+oaAW1?H+OS4p{Q +zX;MV4>Y0>{qh2P3;;IlwX-sOuRSd2waE0F$cUQn&k#>c65?fbL9no}!(G@>e;9L=# +zgvzSr3eF@du5bkX&lj$L;rhQ$u7^E>$)Bpvmf+vremI0j!6toj%Bwo(HFXVm{Z}Z? +zxYS4i`Hb!YCi|la1U@l!OpgzfClGRs(mhWPTb_$YV(Pjbaz%A9iXTp+pv{j4p}oS? +z0(lu4gj25QV&7HJ#mK?b#b~>ui;-WUi_u2I)JE}Djk~`sYfn{`k!Q!lWbsyDBm+(U +znURSHI1HKT255IOQ6HrgSi$o)`#B8fvDnB|BO5u4GqQ@q93wl73@|SFxX9zOjte<1 +z-MCox^4JS94K@L0RJ@0A-jnwUN`L0r(!<&;Y$vIRIM!gKg8(0i~-m +z4Un5O07{g}ZUFcZlmSrtj^POKPwPhjjnz%(J7K20pBoz8{Tcw*I4YVJ+ge_;pw<#j +zi)Jm8wJ_6CSj4x;Z4uZasYOJKY!jg-(pbc>ra$}{VEVtF`N7{CZCY+0S~*3TTD;ud +zn#{njWIo{E&4PmpGuf;Uc2<+iKSnV9g~Hf}ArsOM`r?rKge+$@zCf@S&HYfK9 +zTzYMIp`WC~-LPj-gJn4ou(WCmA|d3FKg&<#PBd@G +zw<63-pFOE>3ShF=nA6l(01>MaAfaQZukV&V2uZeulcnf#4LFWD^&P;PstxGtfar6- +zXMKB}$7rX%0@zrU00}bX-m5eh(5=k=-EHce#f<%1$saqW&)a`Xnfw4v$L~h~`~2HU +zJnP`_Z>+9!A@jeDPiLrNefN~5d->(HD#`ow@Knn$rmMyj>5p-9HdImh_}l4sS3R}+ +zJ~5SHAGBjl#!IO~9E8;VWcUSpli^R;#0-DJUTF9ewm-w4u>1L~DoUZA`S2#J`h=}; +z*>+;b8`ZCRdPF`%Qm|G}O_w@zRSlgoYjCr@wNQVk9WpEE@LR$J^Z*-fjb2e@e4@`o +zUyhWRKDz&{c#<#2sFz+e)OsT!;S$~s-+=zM@8ydhs@c$oDnB+=KYln5RN6J5?A3z{ +zzx8F8nSQM&UVbxMJ$5uP0ZN;_@Z$?V{<-j@)Q^%U#S0U@FyWt4DZVh^3j_Y?7!b6e +z$y^7s=yR@0UJV&ZrZCG3AHMM6m*qnl*c*89mG$7)3(LK*+*Mfan-4$gQz@SKH-*0c +zt=o$x+sL;jpR77;xr%rBX11Dh*fB`KACO +zVbA1efo<0(#y0o?z`p1j&XKC{fwLXrdrCXefe{dyc&aE|Eb0?&&4}op`2fIC;1S20 +zXMY9E%HVGUbUFUYK$oK{W5Wvj7xGOxzD2Lg(YMHX^{FS*%(Ldu)j4AwafME0ENG~6 +zh5>?Z`AHUHWnZSEqMkjJ45l+bkg!^`RI@B$_;zI?@`S0kihYR8%GlR3fhUF)6}UAj +zUjzY?ce*i2O*#5J*_3mibxk>97gLUw-jpL&VL2;UpA(6ACVhavak$U;o|PcHhz0I> +z!KLSjAuUgQ8-I9{;Y&2tn6Btg-Oj7Y7k^;bT&;!~>fkI-5hz<%=`VT +z?C0S0Io8XuR~8>kHp#U@j@_Xwjb&S`$=deA_AEW?VR@4_#5ESkJPh9D;6e_5;@}Jp +z9^c^B4ZhpppbcKw;A(jW#xg0E5pm7NWGE)nFd2hM{Z9&iQt^{g_tdzpxGh!fD`!_7 +zI||sSTwBSyYSmGslj@w5<)j`5FLP3ilPa8)pRMj(1!t=?TZwsU%TrW?<2rb!whLK3eGMoJLT*Dfx-odz+T!?0Z`VqT633JDi8CiynaxLV-H*TQe{o +zDs<25Vyt1c^qo_%XH4ZcL{GfS+o@N02YVX8bQzczt_ye$FBIIEc|EZ``2m0Vyi{X7 +ze~djYFUnNaFZlNFzWr9#{Q7Ud&cyNSD*qRynEvhST>Oj3{tb$6vdjSgkFQ_pzsO!1 +z8EV(?KW;_ScAIoB^6Zb$o%s`hvdbeq6j^zF?jp4ZkiF26lEbQr*XtO8i*yOvW1n#;Lw>MMYP +zRSA&LcP$%MBr-F9(_f7kQ3 +z^s%eJ_*0#4KD;w$QTohLlx^P(&*)wuqCxZ;+VxP?0Yz=FPdq6?uZQwXq@v`*?Opm! +z+@aR=Ixtu1JgaHWx>Jt4eR>!%Q%N +z<|8P7-nF;#aP*@nq{}y?(9Xyxa{B +zJfTP)Op)u1^yGUDt1asIKsAL0G47(>J-b67lJP7wozuSUs={<;&Wv99*A^t;q5Z6} +z*>ZIt29|O&VYbjl*JEj1wJfe0kE@o)Rg0WL8&|E1tM(jKEn#uh;s}y#f~*-m_dHHSp=J>&S5Pxf59$NQ$eLZG +zM5wR1BWw1N!l+_P3l}VJSfmz}Rbv+q +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 +zGZocG78QhvgjmOcbo~kC#33k%cxFYqZv;`ZOB +zKS0G4N;P9P!fFXMz5qw(fv?`ru|v}Wd1DP-wF$>&f}iJtpQnMZ{>V{>tRq;}3E}Gs +z>2m^ghXnA^(FbqH-hO&9{@eu6UCy_!#%huT=MMk?oI$O?<}jc<=!9XaBUIYWVX4@* +zBeK!*Ff++>Dub){JViUqOd%IcJAmRkDrU+I?TMGhYBL +zskFF-PKm##|2ck>nUY1}+n!{1f7}R~z1!3lHp|Hr@@UDtbCjHRbNZ&@V(WVHY+JJn +z2HJT5GilESDx6pqrd^$|-0n8A7Ql$m$m#JveCv~dlM1s=ZbrL%FV1B}Es#k=&c#tz +z(o*AQR_Zz!d3L;a*PsIi>OwWG+D?u8f}^^$J#|H`fPD;QbFqp){0GDYnM~$f9sN3Y +z(w`5XsCXA__njxt3B&0>y|nfpu6S__RxOUC35=TNilWzr*hiaA=(NGM5zV#0)?Gg8FhDC2X<^bGc`UT=jxyv +z;R;6laMYdqZx49uV!H$*d3r&Vu3&)n#FX?s*!6QkPU>4WIDDqN?k{(+p~hJk%njJk +zu3%akPhftCo$VUSunT08_+MMW=agO!*!c1n<32CAp9!wI$R1$OMK3_(bH7Xb0qo6_24vC-_TVM$pbPW_BkF^ydeIBRzDbyutsM;~BVHH9phhE%Gi7zt`T&JHfBfo|P}wtGW~g6K$8) +zmn1vb9qsQmviOQ_+pXRSDi(UZ>f2hrm@-KMo$t@x5M`HKqEc>u*)BQ +ze&rC*pJkSW72aFAp$JB5{=22%MOaG&RaZ$BiaQm@C0EXMrt4+3){GW>9V_UAZU8O~ +zn9y(THm0w`g)EyG{gh4RVGDb*BvL#6pzU_iGo3R_LX +zi;ZQZ7wKV)C-S_iw9|P&$o=4+COpjan01n!eOn5;l?1X2$Co?v)v-sExvg76wXcwHWB{DV2{bMSZ*Ln$O5;u9EE?V{u7{ +zb%eMTHx~~)tvIi+A^-WkD?kJR&&-`o-!B040Q0X+ZPT9%8l=jE5ohaRSYR!>8W^&} +z#*4M7G?jtpQ4zE5t+HIOG3lak=M{2nvGs$u@@s~3cFLg^KkG+?O1?xu_>OF5P8koo +z2MfcCKl{i09xTC~7^&J}tQz_Kf|~x8Dy5(h&+%eBr;S>1=ov12X(#GWIlf*oPY@H! +zIBk~pWK!XvQ3-*GA;;m!EaxFLO$Lp)g`4{J(l;FXDx&^!+rfR=a7Q;Ghp|V#Ycv~( +zDh9MQ2zQ?v+X}d1$?}K{_TI=rcW>w^iO$qlcEsVNv%dww;2FVNgVzm*e6jy +zPWqK5k@*6daVE4a%6kcI8M#zH>`?+TfH5h;t_)vqxo^7@RQa6NG=}FI%dGb3d*&~s +zXLnWlUST`I^_WHOla3mPo02J^n(Y6k;B}p|A9p6)N-GpkK@T`5huSgm%Qg_SJyiM+ +zTUE;ZPbq55NVdLx_l`fo={?;KrbsPD(**|r#vC((NOn)Lg5?>a=n7{>m%L^ruWDoI`pK@UWEL4zkAx!@7`6MM<*_?vybQ!cdKSsk$kZ7;FFrJH +zHI0O$mUWIy<+V;+>6vS*H@lf%+jzc?iA?w1TyVHd3SlN>zZoa3hhHt2?zh-h6eJh` +zuwp`eTfR*UB1*`)n0VSKtSCBT$<4Q!Hp|G9_9LqRpY0zt*J9W89(B}OeczVXeY^Rx +zIg+1ELr&y541P}u10`}HD5X8} +z;&ghO!6nqJ+R@aB^%F-6n7z|w5p!1M`UossKjxH%wjA*`&dNQK;fT6mZoEygE088) +zkE)VY`YMY;mDEqQ$i2?e5)@cfllaRqca)cq#gQM+ +zy4pu+Ba~dM~V!8@Q_3 +zt!f(;{X&7ILo46r-1O8M3al#WvEJfE*dlV@4%?K4GUgI=n=Y|rXwgQ>de(t-!d~3( +zbqA;rsz0;6o5ORW`8=HLmc!wcReo3M)_2kRZvWrpjtis*(#o(w)t&`ralT;TH?K92 +z4iB~^$DFU5<6Dao%SMGCN+5n0u%-sO$!UuCNF%R6BpRBK{lu)T& +zLiDg+@Ovw|)t!=K#xn*-;6QG|>SV6rcUcw-np1qpy+1aseskC*iS?xhZ50r88=Mu8 +zzuPT{eEys*@g0UR-1jn(Y+9&D;Ttt7W;d1=`TB759LP0Z%zO9so5~T +zb~p6X#ykCi1+ymXke>~*GX8y08J>?Z>t8T;*F6;L%rI*1K!={jEqY!0_@cS_L4&0+ +z6?$hut+Ga2DQBWvUxkPG%3`HnvaEWtTsooTXrlv}PK6D-S}~?GxrWVQ8uQCm-Z~Yc +z6~9S8{NTln-HK^+JbW-z?iMK_r0$=Nj59Q=`iYjBIfmOFh +zJAI=b*bgp94VT3q%n5gR>H&vUG*PQPp4FV9B$Patxr$YMr$n!agl_W56xff2oY97s +zW1aWV+6}0b`Kr407y08k+i40fEge(mAvr>%dHE3pdZDryalj(q4rD}CGf28~P4sx; +zkTk?&;U$;l@Ez{W;QgPfeBm)$6-}X~*jalCO8H~#Ph9W8sQp;g1y&nR_8pM}A|xU; +zyWu>WL!^eM8kE$^UU+0}7~kVbKbVvA)Za|Pt~rp=l%{{SM^JaZ59PBcJ4amO2c{ZA +z^ZngpRd$IVyqeLGAvtEr5EIs^#LR}*37O$Y5Y!SO{Kr2ST)_~#;M^XI;IXsEB0_Y^ +zB_hLT*H?qKBBJy6F0y>wpix2fd9qnF`;ya7H_u-s=&g7>OjW$$PqaEsvF=BQ7i=f1 +zs(snIw)c%fDrC`d2T{ebPT4q3GYTy8Nrx_thx(;s(V7nLpOTsjRGsBB)Og)cL0x!{ +zm1m)`I*AIVKVxsHjx{7ErL0BgL2*KymW;yY#NiV;*MT!U(>Slc$^KBvsZ>m+W>_p85NoeQL?25(q=rU}G9#hBH +zSS1%cHZus9MIY>7pXu*4-$vqJY8kzw2h+0XA<}; +zZ@aJ~M=o$h&2b$ji)ugMPI6JAJO7gcnH-;!yA62~EVb9*XNY#>;W-K@GClSSs$t(OdQeD~t})2Ii21Tk-Ft4s^; +zGW_TVq5Z=kvb#}XKl{4f|nCiF>oKl%k(E}wJ{>kg>o?hH>F?u_5zP6!-=JR|xWVTx +z%pQ9>IEC)qUWG7i8JsoLrE?{2=WY}F@-YBi9$ns*+RHZenLpwS8*QpfFQBq +zgox{n@oR?_7UF?AsuOxmL}MD3lW>QJK-@-#z?7nXVZmV2YbmW5`zdq)50NmBX8%oZ +z=58NhI{JDM;VSBSIL=D=Svx6J^jRh8hv>5$u=U_oJV%`EMX+$0^@Y2|%;=S+<9UZInEuJUQJj`VxXtP+$pGUeFGb7&0 +zy;ZbnNB5Tg2ILgJIy%4NJ9>J%6Bp@3t&a7%r4*kQwua(B`f95a4e3VBj)l3L6krou +zQ85NRz4-~B_`F8PQ8p?l8A(+88F9OjpC5R1q*$7#_Nj9?(1Mg!^D+l0E)ut5#IRSKE-E +zmsu}4?MecwEl5++dF#o>ErmIsqksQ) +z5GJt&GoZNqCB(=Ea%=;4pq00mo&!Q26a--uQLPtMsSL5>an60_=pLN;v*xgN-v<;d_6Nuki9XP1KU +zb+HN*8RRh8QBkNAA>=S$Heha+Jp(3ch!T>~0*VZSNZQj#?rc!uyp_O9K}DXdjhJQ_ +zHZgSIk`_kNJbWh^iTZ}R?HF|k!zo8H7(q_`JB!2rh-dJPJ0OlfSI|9L9JPV%dl0uO +zmXWK@dj*?%9&)rY5r}A!4 +zq^*`PSe)>m3zGq)@B;z)7@kNWa<_EqS4vX>q(2P(o`JbE;&MSW;>!}U+zl%wyt(DE +zS+)5aAU7qS=<$p~0Rg~u;xs?tBvFqau$Ops;l3W@d*QwigL2_MnPLU<_*=tx?$J}z +zbLP=jBY);mU$cGcQBh-e>QPwp$qmR#jO7L-ClYf5ViIe)0RAxoTmZksX-)tjQI8Yg +zn0UnjuuAmh02n8tZ~$}?bJ+o^iHz(3`NSS$Pl*&p=tYxh0TFXQWea_cp +zBRfK*vlZpxh+nSr^+_={&Q-hSpJI`mYi+X?(XQ4_+J)8MtLM#Q#gN$62$sjVT!-o@ +zYA)=ngRO|Q|0~Z`JCpyfJU5Xcx9PE{_QyBAlLJX4_yRh{(|gfwVA(Rx{Y!x^qe3mq +zOVu6bjm*)k)gjM$4TuLKZah0u`#dbOwIpjJSCgp;iJhsbvhp;dW2Z85c4-4sDbNaa +z&FIt+Ga6jUg0#$jKH`*ai)v>`pVlUXo@*glC7L#JiM~d8Au!&Tx4IZ@+eJ+o#E_t_;v>cDNj;SDht-gDp?8fK(@;g6i8FTi;O +zP||SmoK?kophWtHCNxwfMv{<*768Rc4ilUpj(|8Fg^Ib6Nz!N|ASK#b;2BgbMFQq(srX!kAMymY`m7F@(O)s6I$n7xA*G0c@}4TJXpS*nboFs +zi#=4VoS`akF~R^5{fl*d1Tr#0h=aSJo6lhX^q(m8;{ym|`7A_hopL;yHK*1ptO4|E +zKleF*ERkZBjLGyXTjnLZj`w*ZYoQB7%?9Lmo+{KqJ-+NMvwHe0LF>xJm)G`cS4p8q +z^7K@+e<@6WE|sUJZ7lL=`uSU}iyK+88>ezT*?7taRqtE(Xa)Z$AS3c0Nu%FOGKJ%d +zsp6CyoqPp9Nc=@-FoiH*)RVk+TSrcmH;Yx!uSuHzFzMd~1=S|-B5v;cG{Vkz4&(X1 +z*NJkca-~ZqCZ2n;N-D~#2I*h$F4FQ)SJIUv9hLOW^AwEgL>n@h;{|AdRK#7V-{c_` +z5ff#a%DuF$i8GL{DsrSKhVyro`o@ave%EPQp3}cBsE`%@ws|av-^$bpqzUXw-rcAr +zAF~$PGWPj#Dp95g5me;FI`tJYNahd)JwbKS;L>6y6nGKhk5D%u$dIUHG!i$IEwIFb +z!mU`iCjCtu;%-<1M-e6S;~#-;>mR{&Hq5qZg%IG!9m2b_2=dB +zD_>L0G_OUhCkQHkua(^DF4?-&xs!>sgR9#cuGmt#6wBs8B&f93lkBtvh@r_>q$;<> +zcobv)tQN8;mMoL3!nIHd`!BJH8rH0wO)q@bGEzag#&KYzH41x0v~Q_lEk^1^nX} +zx%!_g@kWgG`}?Rn<6m~%KeDwum#YD(leP2ru;=%$9Y1TO)Znd%<-a%LX+yCA_ec`9 +zuHZsh`9{p*5bp?<4+jNx;EsaMq!xTwc>1q_>cD;W?p@d5&ae;nEd+lHI*#N<54-S( +zt-1PTcR?7p@4YD%-w=QRz7Vgdi$YF?KT9e&cVuiaB%bXRMF!^*UZ%_lJPxTY^cL=% +zA&r6apSr-0MdQrx9dqp|eJ6g0D*;+T&BQ91(njm-D!%`641WCNJb$*B+S)nAn}$u} +zBD9L>_ZG8I!ix6PJcR0^8VZ!QasML6q(4`u=@-4qh)kB8%iepfX;vpWVv4c&>P1^L +zPTbix2dP>+D!RmZd^Ol&MZ?FuZkT4TP5#Vgq!$~@8d3q5#H{jsFkCkxRrKBU3EIRD3#q*7CQfPHYR*6cka|f?8h|iR{Q2k +z6e8ungD4gXHlq9`QABxy9D*^FcIHR8NU5r%V +zd!uKMsn+vQcjw}VX4j)jiGbrTU*cA(X!QK1shwS>0go)n`iTiT=wC0>SVp7kcB+2` +zr#AO;TYu}+)9}vU>0#WL(34waAXGAyu6-F4R=n{QprG*VBHUA7lX94z(Y9mlI>j`E +zqcuF<;U2)-l*o8v`pY{ViQG1hMr&rpcuY1g!1EU122fQ?;2#)GaYdWn!L@K-2EQ6I +zmCX%>5-yC5uMP(RN_~uGIFSFA?bb44VQ$jwp<@mjlbQdP!JYg`XYY%RE2XGFK)aV-4&!%2k$@_)Qv1GE~P6QzTl~+ +zB^J(sUx|Su5?HZQrEt+3(chE7yw9Um)rLCeROJxlk%7zM2$hN#BH4=|H652&f+vdW +z`0x*NKWaJ`rK5MwZnDqePo4Mb>tpVX6!Z0x$nufO_;?CP5((>;KGu54euc^&^zdoD +z$+7vkc^A{#a*>@t!pFfu9W+{ozwG+bzG5F3%s~bCUmZgwEJj>BT|P~LX%1G +z2rOeVvKHAv$`#~vca(;moI)Yw;5y9dRVD&uClQ +zDRbrVJpIUwpF&PHIphmpmFe8?zIIE4(~_YRL6Ku(8DYG%CPlRdI+z@~?unC-@SvRIA@E5xTcl7r; +z<}y%REy*Jaq>`$koxV|7rKbtc3qu>Z2I3P@P0xhvEW$zpE;*~S6m#rcd8K~kc+Trr +z`M!TEH!2r?rD(#-SieDC|891*XQME~5VT^M_YTu;Veblubm_Y?TuK1w*DBR^9J?yX +zvKk94*)Sf%DIw6^uKd#)RJ)YZd{6MMUFnAJQ=-nhXq-dX@= +zMUl>M2u^v+hAoBjWT^3Ec_v9JMEgfYol3fcLx=YXKq5B!tE0td7bjUMow>yQipP=w +zq@lyen=gre8FdS`?e?3Q@(y +zEkBsAIzOUpakR5LvQ$EUw&SY^MZsP;EzwWGpJW9GP*FO6?F{03n~->J2o$-m@E?>x +z=U>{QTBQ~Jiq<%TwUwSHKhW0}$#Lap$Q=tJlkxwOuh3Y)lm#6o!&g(_s5mP3rNCct +zQxlw6(mnF3s2phW*6(~X-}UKnKTe4#7<=(57lv5AgM#l8sn>jdKZ2yA6# +z$(@p$;zb6__&O|Rv*Xtsv|E050%b(`aj>@h*i}os?-j#7af&EdPYR~ +z3PkG&FLM>vFQ3g2@9GlHR@`fm>DU_WV=`#pjMViB+`@5IP=8E22 +zF5WwzRy>uBeyJPH@2dzc!5;`^YDtts(VaE*#xtRb06v<5uaS= +zrMi6EU%rdlp`m5BJuKtLirS6X>EY1YPo2wKLy2K^F$O^^M#4-d#gTX%Zla(3Aiixe +zrYT)pxI>^uhi7ElSntXo%9V*n_+&VlwJ4iG(c-|3PvnT&jj~*s1d7mPjbGDh^??|X +zT)%h^>X5uI-FjaRZ?#cWx;NFvk{C8oajnG8X_2w4ZGSnai?pBxQ)>_b{&_&KXWsE! +zmU-y5$Zx;3r_l}OWm!kb!0f0OJbVoQ7III{gp*Y +z_jzxp_>UFZCEY)A?=#$5%}YUd#bin?WHdj<&4<^a*)w2GDtp}5YTmK5_=ASvSDY#= +zW)}X1$W=s6eVGKBiKZYr`S!OA%bQ=3=Fup?1%t&y7USe`^~2j@toGp;jmeTwS#+(f +zy5_3H{NEVS@I8r)wnD`vX6t2BF0z|vw}h)E)6g2KZaq8hF|eIMb7UrTPou|bp_ +zAd3EEYZO7&>;xwZcRY)-$K>0g0*)a1kz7s0SN+2*E5_$ +z8x{mr7@}P^wBEnGTKI +z%r1MY>^lsD+BJsj^sz{3KZ%vIYv}f8$`XUAA^AtIhj8UJ&NUb=nOYCWZr!QJ%D(!S +z2{%V0=;XBV;zCHKAT_FMP*TCYw&;J%-&HAFXw?cs| +z_(xHUCFytw=^~E=@0q;cQ}=5u!oun-m%zc%-^I5byqGvygSvF}WkbR7SWUEi8pe;H +zKp8oTa73K^G*rYl_gO;Dp#4FMGW{qVhjgS$7^5H5f_q}WyA(okrtJfgwXHOnSXwb#njOy2m)(u&#W~bX$@qa|-E5|aOcy8kXkCX>Tfold&>j-wW +zew;8XXTvpox7%NS5PI&7Y_@n?Zab888?C|S+-QO#;A0ovWG_0~8Mi=@kI#GFK=<7L +z{}W(xrR0O3r*szZNp<(gpeKF#TQzmt!@VrwVY8F*y1OB`G%$+Yu(veEg5Kix?*;)K +zE9bb`Q;tD;dFllV(CW#NgEe_h$}Bf})ZUz^bNofQUdapNzF-Dev2Qs{PSKqGc0hd? +zf09sYt*b}J%&g1os6o9pjh2>2Ciydi=%5Jt>kAGGBn`P8e6T_wV#uno^jSGkR#hL8 +zR?4?z=9*MuRndcU)vJj{ig&2DgUP8}sQ!6Ts=6s0SGtp0ryb;zN~1)A8c!XRZ)j=X +zHFU_T66bDtgR>)7B9crZf5EM2*BcGWMqyzHmp$#nnznDK$~|YdvpuZ%`-e9njlpB? +z#P?z&t&oXTOKn2DVI-GgRPfOLgFTJ_Ny|m_XNfS@eN`its>zVs`?*+`+0Np1;igp& +z^MIqHqAYtS3WH`Of`aepXV@9%>|X2QK>nz9QEqvA4%h9W!E5nHnzs+-v4+V!CK2em +zesa*mpt1C)e;|AiDi%L)d<@xNN}!8~p;P18XA)BcQY-q3IMQp|MPGCgdRCD;tTZ)h +zb1&2bjs$~aXD$k(81aP1DE^E441*QRh58gxE;dDg2u+(=TDta=F7{T+tmQ>M +z*tia)t!XypjvK-~+eD`7E7d!n;@2~>S^F~ur-n$HQgvrDi}GXq>O`!iTrrV6Jg4uv +zplA^%@y@X_IdI)pc*9tLhNC!e;7J6hEbPCVqBDQVD12!>lZuw=@l}^IwF!E9jfZ32 +ziRMy#dAE4x(@v!(wxSIrfNv#Fz*A*Z{c_!#qRQYOnw)h;A-AMALPk;OCn-uHbFy!rU~ +z7?s(qwQuJWGHYslqq@49f^F0hc~TFl&E`vQrxZHgFbzBOcr|%$j8S7K$7*MiHJ4Wq +zVJ*JtvFkq*2X7=B3u)V=H^JB?F#HKJ=XMC{1Gx__VO){H-M7t{uusURSrANJr}%0c +z`I1719GWP87)O#-UuUl_Bz+sVRp-hrs==K4;8sSgpjWaWT`j6n2B~dZr?tyrWYpy- +zWd235C7imDp3}}H9^w6aOSA=5{nru+5I$AaVpmXs)kpoHPTwVA)J$cb``7ZK`7sr{ +z+(u~D_X^+h1x%D4zOn*`dmtT4w`#!~zB-zxO7nw(5s!f|%8wzDQ-7Z5loRb49e*nT +z(Q=#dN;uZ??J<(Q_*bQ?g4S&mC=19ah5RdBhN-Qo +zWsSkTZqY4v?;f(~*7DEwghgos&+Cm8q1S>+jddwvM#~r2vqKyVI_OfXa4^AHeTG>8 +z{gBN(*IaAoh==EMyHICs3aa&4CKvF01@dn+ez#}EVI%6Mi;X4L;Ow_Lc +zbIDBdKQ$X|{ku{ShE9XyVFrXX1RAk>jDsS`rCjGbRqdU1m#6uZw@akPe{{_|5=!Q( +zjtA(Oax5r&2!1gjZf3kkuX~z5?ky(a0yCkCE=qIQy_l~v)OZwAR9d~Z+w@JQZ(Z@x +zyb^sv+;wZHdakTQI-i1v8}VL|+6efoc>|srTS|}iu1N6ITNv5$w7tDW?&sy*8jN={ +zFcv&MUnUEz7S3^?3x||M#A#JcGeU#U!)DpQ)G)I;5~tmt6>y9!oUI2DSL=K{={>)e +zj>Y2^rfYt7c +z-$_(XGgR}hH@)!6{4&n_=t6}Bx|hm#9Joj^=^YjN?QryM$cLAo>FKot`5bP#G7j>x!-aUS{l^Vf%?)hD_;jG|Yv)W^~5C)}T1$x-}M8hb7~$v%JE +zmhEj-{(LPtw3$i}O>Ixn_|~DyQxusDi#sU_sCcEo`AO71UTKWC+H%IKI4Z)5gk_Qv +zkSjO*ctw=!>s7UNVfRmCCwbM=@OS96wW%YQsUec@#XD??>a5n!E+Xt%$+3=u%tA#$ +zrq5p>T9t^^+DiGd*AA^W-rvh!RoJvOA3|Qe{e(Z=Mexk2KxJ-kwR*&DJCTUu+iTsc +z_p&`+z(U#qbh9q)na1z*D}O&e&%3P>H@IA>-n@N+OFCNzYN$iqbF1RMl&|8CmZN_=bMJ?)nZ|lE}nB=Rx$urfG5KI-qFr+8d}Ap +zsJ2kC2j;yRD4jPZLKAxn9LmOfQw{ZlZ|AL?;0WLng9(meQLJeE^=$&(xQVQT9W-t6J6>ny`_Q); +z&5k2TJIS=gI0Nhj$I64tuasDX9`eeUb-S$Oh0BV|a1_#0b4tm5Yx^`H6fXN(s=)dX +zf%vNNTVp?8=R;v}-bYO;@|{+TKx17>Z+8o=f*u^+B75T;Gh7Mj#@D9E%1nHRT=8|) +zg0!RGtzCdu4mw-g&NI#%wK^qn^m7H7Nt0Qb9hssr31@<2lt>}{u@mtXz*HmaU+q1h +zFgDMWc<6-V2%1xaUcm((qQqj +z=)Kk+C1_+(B&B|n>Bbw!TpJQo0o_*WJ8_+XWazmvo|U85#`YjhkST=1KBsKae!T7k +z%cXknH#}AGV5qTEAZ4;rKDWMfS@=q)=oCo8u%mDZ#uurUPv;0=SB|jr^D2#@shTMg +zg)7HPjUeHM>oD5NZyH?;sk1?SQ6a2e8o113A94J{UW~D9mPJQ4-HtJ!QLk`PL0S0t +zbuoT4n?|0hl#znI*b*z(L}umv*kRSaGb{=7bXC_8{^Ofy>m2NmZk +ziTi5Dq&^4q?M05Wf{VDX1fRvfC7l7|^=&AkNbnJ&mQCmD17~YT_4pkTBU_eG=h0n` +z+@*N(iO>=q=X4MG1&QLVSZap?D0sP0DBP%5Q*AsKu9VU&!Hk4kPmL%eBRgAVcl0WpKRH&ki59R-vxV{E`yJrh +zoLrXL#nz={+<*gh%~xN)=gvXp)Ot)%Xuhf?d?<042|gGpAIyaitu_}|r&oQ}i}Gua +z-Z;|NjP6F}qGx_yb-}2Qnx?6@q+SBy@402IXub>gi0hTtug7!K^F9sQdi^C)kH+Uz +zUUMzd%mJc|n;&2#66pnN+!xESd3LY?!m6CoMTS;ag7os?O?4cM&bxTdMng)HQDmlB +z5)jgrEy<>|xI1Oo%%xuAkWXW2Z8GR@ohd=%?0SgyA;~ +z=m3857v}6*(0;CZ#DEpEyjs1oos@gtq-7~bh3zy`O`F}Bb{vKG%%Z{88eRPbw4I>i +zs&Ix~X^~wjnwTk-Cu;&uQiGXmf&i^nTN`XUt>k- +z_5l$8M)td-qsAGq_wh-mp{nU%aK0KKJ` +zi_*Qj_e%X^y%?a@Y+!%WZJSwPvo+h|U8E-fu9@N6lt9VaSc`5`wMt$vwy2KtdyKO{ +zP4(?+_qfknyj@04?7v)p0&^#j7WtI?fav30SJ~YNmV8E)_ckqjC=DHBi$NUfb6-~} +zoDiN1NM@!_&j3NGThfk6u$zU_swP9?MRwv*rO#(^CFEh1-5oaIi?;gJ4p9cu2LWD-%TUgss_L8zJA_n +z{YGe;i1^m>6a9WQj(n8E<3c^i;K%*5rkhTon-WE9fe=cm)6x@PMbMSB1Ac2Oh(1xg +zY-`k$p=)9;3a7+H3SVH6+}zElY3nEkqj-jDTntf;Cx*D54t%Y>2|&Uzs#wZYI}_Sk +zIJJ5b|0|rEwspWFGeJl+Ys@{B=oJTj#*j)T#&x)nj35;jN?oF0QIq4_8!RjGRE>(< +znA=GpZi{2j!Y|S!4uyv8%Qa~s4#hh_HZd*7l~O$Z#^aRVl?dw@HKmh=(7@ta&Nf|DnSNh%%-vk +zEhbVxK|JO2FvoG8{^0DYTqOa$8`ja`87IIGLJ+?9V}Neo7~8O3SiNVI@JWFZKghOo +zoH-7i0d5_Vt9!BBi7&FazT8bDe~W@hoYyP{)xxD7sm$d}vX>W6oV7&VU!EIt8?P2O +zZ{?uu*9$q8Y>XmtW+PbiK6sTRV5^i}Ej*j4kOCy=x!UEo0%TPo!CQvdIfhv`Y`&hRkNn*#Db9uN)DEpgl00uI{5QPnwbL)EbF=YlvlUsYv*Q@H& +z*QfGim&eP!&X3*w^qw6D-A;E-wKeT|piVA8Es&L+e}Am0jc0z^z3uWVM1A4`(lk*I +z3-Eyr4zDKZ$GEIG4%H8D%YoOdNtR=Aua#sGWRTVM^NBg}?E%{vr?=gsvt6t8wq4k3 +z<;wcd#(MEu=i~b8>ea=8oWdK1!0~cVpH*tZ$I5Xu-S#`9My00?@QLvIWVDaUO((JK +z)?jT-;&rIHuHKJ9lb#RRd6nDj&LDoO4%BmHj$V&8@7K>V&-C73h7L{`kE>5Qb0unjA4I&t#$H2hPTUNT=Q!P+9-=JA +zcHS>8t}hFC9aS%Oo~d!x`gVP^G<^DeT-0uNb$Lj)-t{=Y+9ms!>=zpx&}w6^zK~(N +z{119Sg}*M=bl*DR+b=%k@BZ!QpT3(?Ez{6{Z0$O)`rC(rddjvTeX&9SYj{j2?$)6w +zX}>>Qd=TdT-OH=1yPMZn7yBd6qMKEbK4#=MH*fEL{QQAQTf2t#!`LD&Xmk<(QP!kt +zWBq<<)MLXRpKfHL58v5ijhF8lKCbIeYr8`iYs9P8bwGD>=<4J&PHmN?fa4D^$@%eF +z9!y8Xyh16eRTvGw(4KUaHcU~+-gr!o)!iyp$@?gKck|tYUuEI$>j&SB5NeGR^G4hL +z{=4PlrXR7YYMsR4HKz6886~6jJLJ!YFN>c`S*~*xt_!roT&HUji}mLZBE+ZlE}{Pq +zctXKNP-p^zTYa!DAO2JM;pF(^d5?FZ=sH>m)Zi+^ +zbpszS9=e>zxAzMMWiGB&BkfdSyrHk!I!{@zJa~*|r$p){Xq1yN!Gw!ChN|a(6b_6= +zC`FXjD#~yO=ybHutiYjUt^}rIBV+w@TXTuS?^Pwec&=BWdH>jF#JUZ0X{SnXXC24I +zdOFtA6VP9TF5OYBv)7%dB&f~!qfz&g5X;rwtJfbqa9vhT^PB(Ak=qttZ5V0xmKBNL +zuo{ctaBXBnM(4VzTe((6wf=(PNBT6{u7#vE6m87O_4KEm{#i-%kkRu`%!`pIKXU03 +zQE8(@zE+Vgk$nBmOU(`LW@{ZIe= +zQN+JGe9mS67aA9nRERcRkk>N03E-hK1;x(M}8@i%`yJCPKgLq(4XkpCZwX!DSV +zM7c1Ap3~ob{z-OjANqR;^Ay1YCJ4dq2;l6sQ$jg^b<~eOL~bk^tI +zCb&lIv+tV;?uFZKi4|89lg^&Ry}mUcPCV^axLb^XFWvfFFV_CkV+{135H9%n58wWH +zZD0GNsMMOY!QaDldw2c4v4wTN#Q*K}&vpG%{4-orzy1AB|Lyf}-yN}_7arz~6&H`7 +zx$*RR8>XK8y=v~76El}_DkEWWYy);wyVoQM>EBcL^HF_qVZ-!_0CW0xv}(uh +zn0_SrBmR`tG9iKJ9gU}$>zhCSsS!1)?RVc04iM#rBFY6lDOosaN=e^nC_}`jbHy@$* +zdg&Z1Qr*pqSQf;NeHIsNWg-Ro34OIJE!PA(V_C1a*X!XI61`KYEp$FW%aFz>?<@(l +z&3gNCO-w|?9O0<(y;+loq@#?;xxU`ITB0s3aW?n)+r84Ay~Iy{_;(rp(Ng9*%4D?p +z`(J+h-Dlii|5G>`!C&=ZX^3;{DC(d255g3cD1p2o2^WWA_3?H^kd-VX+k$TWlk*j< +ze<{*GcIDg+JHDMUs*-tJSOSrEXl0j5w;K;xPrC;U?+;Q#mMg+|CYa_3%`5!jjfXS=Ffk7X4oD}S%7$UTn3Lc +z?D(q(J`2o<>Hqc*KR@`wn={kzFI<}TL+`zL?9IRXmw*0(TOaXQzcLVK554fr5{|BX +z`QR&GJ!om^!bfilCjO}P84R79Ume;>pJ9dB>tW^v=d8ln#gBOD71Sje(Rla%rWgPH +z#l>URU~#Z>6NrQ`0n$ER*gs=I3iF>Ju1kbqU(i)mj=UNw0w8uU)pdgQrdQ +z{^CPL5ap-X%%gZVrQoz%f?&qXXjr^0&Bbc|!-wz2DF>HR1?1+r@VLL5c|mHO0!R-| +zkpD<(+G912f$h&b`D?4`kGZg(<|(Wjt6biB(;(W+ojOnRpoJ)d`+Oq6@I=oRtA|8P +zp6X$QYbsgW-d4`i=%4uX@Aqq$zs$p>eJ9C_5A(q)9oqK6&CXZuE?kgpj{Ufi +zXYSs}>mS}aYFxU27G9>c2v1znl3+!jWxnK(?nGcy-OXOszy~I7Rln3cyTMB|n(XoG +zKh6xB(F?dV_Db69&*jM?l~mo|yY!{^X13gBCuK!adm~}uxGdI#r1TLvxa2+byLQ{{ +zzk%5>TLIdtLZCBtU|Y8#zXl}msm1w&vzZzlDUsVe$UZ}~AN`P);x^jYll9h_Zk%La +zxC~vH+p@{p(C%qi>z$GFy~=cjG*`*pUe+ecW*1~C&1_PqZ6mOJRjtXUZW0l>g*;gA +zTxFYdw8ry7aN?pu^v2cUb`dLYP7F_sh2y&UM=;s)QyP(PM5xU1ePU+YN&&6X}&=^H(;u@HgSUW9T +zbm9X0Jt`WHPpRn80;z@Qj+O<)U90?C+k9MfJG(o4S|?55)31+CDOXLC%L}t8L-IVyH@J1vIqKJe6V+;CI0LpaC*1ARxhi9gr8N*hrcEw5p8us +zD`=gY+&Y8uHar}lmLk5o9uIJ!_F*_QH5PDj1ho-SCXO?8CaQ}2RW9BgsXEFf%>V-& +z{=6e9BFJ%MWW75xbz-fu(yjvQP}~U9@w|_Lh>hBr4s>yF>o(SS^zwojeY1EIo<#x_ +zu;=i{&Biiabo6CNq3GOIfUJK@L{IwiBV4tNN#>G2E!yI^xVY6)xf36ciEGleJflpT +zW`XcX{4LUZs&5)nZuLp=QIcl1eaaSBkY>-FTSa|B8;R7Y6WS^iVRv+~UxvCfH>s-g +zb7C%$;2uY22jhh8{rxQgwfZ;*;%E%rj3xIHfI?<~ZS}gO>u*79#R7X2Qq?4S^p2_G +z@OM$h;GS? +zgWk%rBu=hhEzgC4X@d4Aj*$m5gM-BjctV`gsZj>fUz`b%cHmXz;sv2f6T4N5H*=FXj%fY#|X*KeBZH^+2186#1)#C2P>6+5XGr=x2Gb%IzQu_^>iQt{@^@~>oZ +z6iOeFt2u$t!^!O0Sd>Rdk?aPA0Ds;dfgvg)sI$E06MLf;YGiNu|I1;c8h9XB)_{PxY*p$U7Yn$F7~<9ei3K2n +zdY6~cNR}SpVN`gULgpeoGKSfl);Wpjj>9gr3}iq~L*ws%(z}1vvlX<*aDj2vr*_Ez +zBy|?a*EctBxj*1Cf$|~nnNc!ZzMvKz*{eY;w?~MMY_cxy+GT|j-tzZz7-wZ}quZJr +z8ZN<7$f2bnV^P<#yn1igjXVK)ypFui7KkK-ncFbhweNa +zyPOMGqHrjH+oCGOf_yPrc5){j&|5SFbIF;&iwlB!YQMjW7Z^>LMlQ=@+unNF*)V@S +zk~_veX&E~dqFUau;_CIy)e%mwh>_A|HK<6|mmT-ET-XY_FA~kPJEYa~pKg}5N-j3X +zbxyMjc?T9u77`?~j@lyz6p^u69C0Ud0>!}*Y9RUtrZ_^Tf^@aq=*lq;+bnCg +zMs=cCW^-P-Lfs{~*y?&==|f>uT_54;-BJwC-br5G&3vrYHhA( +zQ7HOqzGw#{+q)O?(J%ha+`qfNyZ*ab-qGR!HKTJR23mFXz0I+|yZ-(mci$8-A7jbI +z!6IH?1in7u%*`mBHZQ`?#@>JZ;`cTlhi@%S#H*!Ovq_3YwZ8brfB4-m|NKkvzkm9t +zfBBbx{^?(TnFYyFl(iK_g<^C>5WGa$qd7>Nx;_+~?j-C#T%V4==nk}Jn5Jo+nGH`P +zuygv)oyq_Dhd=!CfBxm4fA^pz@?roYow+ +zDo384%df1;bVhDZu*@LVQLWgA3#4>LxWA37}hwgeMG#?rB&SVeI?_cuO$+@ +zLy$0^(gCkud>CcJ92DV>_ShK;VW5Rx88fMyopr33W=5Y`+ohTl)G>%e4jt161h|0x +z&OK$k2$$nEz8t^br5)z7ALh~yb2(b@Y0BnMIA*u?t39aDD5(qF^XekF{#uV(jUV&X +z9?~z|*MGuL)A#is^>wMhKgd4iFR*x3E+UyBZd!k>NA-o2AEt$rU-5Blc)2zFdQV#Y +zBfrg0@h^@1YJAj}WYEV-mpHHD8~fZpAR_YzGIM|W%B#8jc>CJUo;6pi-YPVtsYJX~ +z|8h+qd6Z +z$@vkfo?B&pHI^p0vxeY7AqzX%<^vPDnBT!A=&H%(!nGgajhjti6*ft)XwNRxst5>P +zLRWsSq{GdIq?*w+I|UEs?S7PTU|amnSHhzxUJxus&}3~9mh{)b#bY(tt9NLp*>(Lz +zzwf^J^KSwXRzW7r-&iT!5abMpfBpTw)e(-DUF=DXjf} +zW80?MO_)DU=PtChFrE#XFXr>F`prG@^Zd1I9C=>*xr`gl+FOrLbMnxGaLrOh*kVDL +zyMMMM(?vLV!RadL6$(ibKy{)F>wj}ExHCxE*^z2@dsu=FTVc2#|Fu!!B>Ojn7XAN}Iu +z^`b6=<;io9GY~iT3%~KyleR7uI%Xd%av_a0M$M0qa3S07@F)x$%E6me<95b&Q*u%0 +zIuzw*X~zgM)GHL}%x5S}1}K7O9b_k(wnlyCk)=#)Da$^6ZC;X4>Rpgam#;Hl&h}0% +z${pzWDAT*;U#-Z2;57%FDFfB4&@5p73)6Vrm +zKM{0`LrGw7iD+>FVe)cwWKH>Z;_aJPE9Qu$@jW>my`sq^DcNRvK70Rbs%`yO+ScvD +z&s$Z~j|-H7ACZ8(;&P~kABiN*iu?6{{!4+iw!*^V`R^M=Qb-{;*mg?z)A@DE`Jg(!387d?=uak23~Pt-54j#nR*_U{(6^k7 +zhZ2z7y*{RaQz7_6Epss@RtyTkN1QB*5cEaDlla;e7wid%`g!zA&eOejBiI+V#fEi{ +zN{Bc@vi)O6x{0b;Oz&9-py}s+<{=qF&p~DFLtIoGxpd(sR#BLdJh{sNJXy|_v33o>F +zxX1rK*P9OA@uSk6BUq3Mif}qg?M9=`DaKP@?L?l-1_wgB<2R7UoC*IymAO-KypN%% +zQ`m)`u8A-FOu>(#bSb-jPq$j%uUfMwGpKbvarU=jD@L>`w%ZPiW0#N*?C?i)p!{WL +z8nQ8P0<}NlgjRtzub-CDnI48?979mjA3-8NweFk~-h0}C)=b`?H9rvxO#3<>mJ|co +z^RVf~Xj=(gr1TPYtlcglnMsg>kK^=}*liUH*F_5%vIdFl{9!|)Ot|Oa1}7Wb-~>@= +zl8%=r2S)HHqphKZCl+n;&J*apNPF%h5^!u_`J152oug8JIhwh)#fVSr^D>mh6ZK#& +z<9C=IoUxw>2Qs18+^vZ6~YzwCM%*q}c)DshW8fu@I$h}c~+UDDNnfV2_-^@r|G6N@u-+`$& +z7# +znGrKGTlOO(Wo(v=4Uw7YF)=pwy(aR8#C~cv>?cOTevF>?GXr2hg8Tb1xZe*@em?;B +z{Q%Ra!%iUh9CSktj%7CJ~zu?et%7X~%S}o#sZ@2>dT~QY+F% +zS!Jn{gmkbwddw><=(+(dRkbWsTTCz_vl>v2VxVk)vWsc&nZ8?JcWxZmb#LE=Ui+~W +z_i~lb5t3-$;-#F`%_s)ab)v~ku(%yM10u>(nsIoOdpH6kSmtbtrj{NF=9*vJuey7> +zhtZ|HYhtZW1NZT&JMHBWldpHe!mzgLoSftd+jS@eprf%2##9ySdpTwbeqxOiz# +zTt|jjAh{*ynI*s@&zM~C$HglS33tIjwbxv%97(S)K76{EuiY}4&+ALaY`kn~&l%#t +zvF6$1$hsXc&D;>5$h(8lXZ(cJ`~n-C*r`= +zr#knnJi{Mu#z=}T-#U{G2M*>zQkMwkt6qzft)ySJTA7boV +zTvQ1o+x&nT1`NEkdwz?S{F4hZ_k;i(`7UR_FMBeVgvZFYd1Rgo9?yf|&cq6s&t>8r +zJqR@QzS8--FMCdxRO}+4Kj4|M!*wpFXYSV{^5pQcMd7sUyPaJ$F*laPcJJj~c;m6( +zcTO1xUf?64^@&e-K7qkQyuMiA&au~cP7A#cd0m+L;t(}YUCE1+TYj^dn|Xfc$mu)} +z0eKg+PusBnd~^gp-{eI%^{60t{@{`SdhOdB9)JXPYabuP`MZap(|p0Fe(-}A?7ia4 +zn?3iD&+ni8yg+edr~3Tvqo{E1aGwi?vHN`ixcAQZWr5;c^9Qi1cht{*nYiuekDK>~ +zdDJ>iLIHEW7zYNH)WSln0G88yBj(|Qg9z^2t#ZI8qiDl?j?>t~T!Q*Y#M10%!HMHi +z`Y>Fv#7}+j;*cz6p^SrY?fh4>6%-cAf=_PUtuvJUX`KBN({+s7at{VXm`K(p;JiQK+N3VIG}Ye4Epcna8h| +zrQax;wR}Mz+d8&dy@&Sr{o*KjPeWu&SN;0MzqC!R_2$LDqAxpp;NT1Cc}BN2X`Hn^ +zL~t$a@xXnhp0+o0NP!)P{tGuu<&>sx~J1gOfu +z-A&&IcsRHSaTE?EtWwz=sr{JG;xiwFQvz3p&u#gP@gMgRrEXNx1*EN2jwU0ss*b0B +z(pDMufalD!nEyTgCwuPwG>bWm!ne`eALS2G949}%xp~4Y=C@a`-rz|4{>gnB^U<=M +zwb8`ceNF4BgUd2fo4Hi6T9xU(5M?X!Do&W;!+H-2uwNQPv+bX&@_zqG6DlnWgnn1; +z{eIKpqbdl9h;4h%-E>wB-5+Q2UXd7DiF|)o2Ep4aQH83!&BC|w3SY$6B2W0I?njZm +z7Ri_svW3iGR#*!Xhg5n@E=Yle!Ln2(QHt;zmwpy;Aw;b1MBqck)yIGJ5@^ +zkmB{HmHSfPTnqnBS?T|Z>iun-5xuOW+_zQRm}aY2wE=RibyTVihBk_a-lo^#^{f1c +zX2XNNlvm-Kt2cg5t5A<;H=dg6pJ%rFT5p6&Yf*?s82p-V$zqE2)_rRHwN*dgB6fd~ +z>@Mzxzaz$){;IUUGw#2WQ9oKgPu#WjpG@RZhWyS)?y0NX`1OoMb|bp5(3{uEDopw7 +zAh^lHsEEX?C~iy~UK4fJ{stlMZbd^&m!@f^vbVH(H(ka((pIe?qXDO=wuH+>N#xkH +z136AoriKNS#=msj8rt_}^jqaW@bc9}xH^_5CbgPtg@}Gww;OsA$$*jxANYvAif)At +zaf+nkQT%?z(*91yGhvritta=FDK0KG!NIO+w9Zzya!+5m*%2PuAST?Fx9x^0)bCu! +zL~*~*T2Z1;Wx3jxOk^z)S)^83?LLtiX*T;znER3#u2DftWI|}lkf6%i(R;UM*fWj} +zy6qLU^Ls;9EEf{mA}U)*_$)7;<;AnSc$OEZ3oGrfXrqzooh=Nd^_nBaXG3Q* +zo~6gL^zhPyPi20V7|#;pSzNnbomfoCc3ECv30q`*`L +z+&s&GXBqG;1OCcnz +zuTn;g`TTOu=a*AHzwG(^a?0nINBI15%;%TK`TX(}pI@Hg^U17<&qtqAd3lb{{X1o) +z|0}95dp^G$@%iP9&o58#xgRUkq`t^$jO$)d>^H@zLjsad@tncgQBWlyz${q}Ss!H?OQhv6S +z|BG45iw^e-=WqY+neLzI{=Y8We@lH9Q~Y~f%4t8ISK*uM +zmoJkaUcHLmycJ3Og#CElyuP~nk$~GzG0y&W&3N9oB@dv)J6c_NaIEyb+z?BcOmXA+ +zuq{p2maE%ppGum~&fw3o-LwT-WzpX@i}+*T71G24ZPp?BjcOtnbs~UwVdnn +z6wfAucKq~p{r)7deTqjmvqxS`N`s!_2~k|mo{^0X&i(QyaAQylhFoX2iy3uH*YJrR +zTel&7D63lE`tIg`k>{dST-4UGYQx3mHKSR$6S9NZAjh(`o?>pQ+y*7id=YV>?%a6} +z^q^41tI@hZd +zOZwi_(L1}kAHVzR(n+w458@Tx?#{L*{d!N!LOcd^LzGScO7SsW>!uc^$&pO--gX^y +z?;j8Y5TAYB8PPU_u`ST#$F4=o2bVw1WBp@PL1JYqU7Jw*xNx`52-(Uy$6;E9Dj`I_ +zh;M8sN4iv`f$7ZXtpfKNkECDMk1$2=?p<6z3hms;+H>M@vygMeepCrW{5~@6=kA@G2{-h +z$-=KGtHSQ^i5E|)j?f8p=@Aoq`%51*`~2(ZTM3!h@|!;|T)Rp% +zjw2*E8wk=5x@>4pWbT}~a_M&wZv!iRmkh3!UaOj#TyYr6==JrrxVj?SEBWyWO|DmO +z-n_bElj{#MA}vw(El^{LPOWuE)2;1KUTQcHx&TNE9oFs?Npy#ADy`fRZcR%{R>9Wx +zU!8ggoR4lkBXs}SqbE|vp&%rC@Cr{k+qJ-U6UC*E8u;k2yoZk-_DI|#GHd?y{<}(7 +zZT0AlTOJxDHuI7_!N{p7D%(Kw{b^kK+0S~A_wQmoZNoPe;a}&Ow|xA#k8v%iq_6YX +zFMY_#=BF1HRKJTvKp;GL`@`$kS6A0>Zb+tGy?l9dx;g4soyyDWAFtp3`0CA%*ROAW +zczyHaQ(0~#t%?*&{)OCfhKerM_Ep#Nu2~l!Nh`%f%Y4Az$5NLcvo5a1m&n-j6A)qg +zk&i$Bf~On}Pff}}9yR=M@#Xa5%fpMIy+4ZTV=t)bug@NU_8qrPucaTpt#K&R@!|T1 +zSMm-6ERXJ@;$&Ggx(J}m=NRK(ZEyD}#JG7aUWYft0MS+S!`0iT^y=Qc{_)3af*9_( +z3@}`Od4_GgQkmp~9f=pjy*n1+(ul&e_M|PmSyM-hyNH?tdgsy*&Wr!;=cgO%F(ZjT +zWwlHQMPgxST|yjIN0eF)RxrWIFCEw{j{LZR@$Mh%P~Uxw)%L~8bFPekX=L%_13rF# +zc*v)nU#M#W-5+IMJjJ*NI~1F!xqhlGXC6DyVNXO$Pd2h$TYI40$KEJ%Q2VpgOo7p)ta|>toy#3Pi_M_+7Kns~gScJFmzxUC*i|^ZaQ@s7Chg9nBD?h=##(4YP-}Y3bbt0Q6TYvGBz9;J^ +zS0yhMmjG4^J>Ae9N6~OL$(4$ounmpJMEhko$1)y@-FW +z?qu$V`uGG7m_y8;+nSHw`@O1AC;vywW}$ii#n1ZCHpNF58*{gR`3fxz`lYKfH*$W4 +zb<$+DZqw|=FJ-ivnLFW2`S$gjH*bEpc_ZKa@ahT8o!2klynI9E&cBiHR88+r6>-q} +z`PdsVv_|{Ysb6pSZa&=>XEe(?Yuy3Hqhyjkmf;Sngc;uGU1>hGqLw%^&mKcJTnD~S +zEJ#RNBT2lZWUAv&vZHt6-lIXT@#gVTzZ_SBjPN0PV(Gkn^*#iL>=?#yl_b;4RKtwv783SXIGgn +z%4n>#0}t#;{oT^aLrv_5$9UZ +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 +z{lpQi{{{WBBPURhfj94w*b2l6pP3P +zM_x=@>hdL>nL^klmfm@=s>qlWmPXoACLAvEP>AqHVBHr+c{^{}JwO9yDobz%Q5juFSxf(-Wsb;U9L0n3lXsEK5i;j@r9~3E(n>D7A0=^8>vIaY%LV~Bw;49Z +zB}ws+G_MGXHVn|(8t6ers`8d})+EGL@C(O%w27WYmPQwVRUK`y1`FXXw&qbM2#(zH^%g%)=lX(-A}>SU67e2oZnq5gK$) +zMc56iLS}8rp+T0L77D^lz_gIZ6G|r=IPg8P6=-A-7Ndx<-P(ils&G6Mk`(}<=B?+v +z;lu!vSD{nssJw;R5#EQG(OQ|Y0hqFHL&hXyRq0>_nT=p<=PXE-H+MM5qjd~kq901< +z`|sl^j2`TA4iR;%Cn;52FLxc?X^~XKO3J-7`gyTjSnq@&aj +zqRS+3Nd|WM +z#)br8JbN-@BLXgkntcQwLz#fy1o#&+gw_iRj{ueRX<&jtJhE|tG9s;eoLOQ3S^5+W +zj^V_l;zv$Br`{#uWMxfBdTSdz;5Q>RRY;^?)u7x45iQ}vGo{K&*!p>jJ->D3<9;OB +z2^|$-9|dlq$rYI~Rc|}M*}{MZSyGN399I$_%ev6zI82At%3YYh)*Wn80JpmLfOBTa +zF6)!a1fCA~-pBSlo4W<6lHBnbP0hfpZh}|?vwmuw2#h3$8t@uBv#(mD5s~c5Vf3=# +zLCXkhvp3G2PUgCW#5N&?WUq<_C+6_dOm{vxBfb^I&JzeJ|Gddyo|R4ySgCK7I4m?9 +z=pC$yTsO8;okfYFc4dw1GqThUfQ*3XhI9$gILP0jaSj+F#lxjqdb|>3E>yH7LP?yQ +zi%4Zh+J|jRA{E|dhcY<71=2sFZ#|a~xu$TY>&jsNh6h}c~`Yb +zVg~V_AP<7%BN1s!6a)-m6*i}7=n4)v(!h=d2;lUO3&_aA76>OU+X^z(**zqkX~*GC +za=BugT%iwQ2xG#kQ*K2<=EyBUnlx)c>MUEFL(%05A(p5c5g_s)9Zu1eW=Dw?Sh12s +zH~@|`nY<6AOG4GSgeV@7ib5yeFJ^sza0_|4LFi3}s)x8F@a{=43cAUvEiE=%NJ@sB +zY<3V6wXq21X$>4g*NJ}xmixrurL}jOUW0CRo+BBs35wRZ=$xo3q)^1N^iaBVf&tDu +zI9|LBsgOY9>?2NuOXSuIUtNu~-I)K|8g4&&f~Av^z$XM3t`sa8z5FL*B!+9j$(MWJ +znLe&e7DvP$`mVplfV>2YN5R=rH06}&OOe>JX_LgNc?6=g*K=vfVBLC<_v*D>>xx7y +z`vwqXx2vt=&gV&t(FJ5*1;EXW;q&z9e^rY$;~Yr2>3!n>4S~zJWM^7HsF;&kAvyi+ +z*anooVM}tcRl+#CAClTe2!~a*@DPA|(i|e<89QYw_1SB +zhBQldRFEcF;3e|oXaw`8+4!ZbcSjekI*FPOlOi4cGrZ%jFN-p +zZ3{igRCAOj_IF7RZu2??Y?ctY4(9?`yVXAHRw9T)3ZrszF;pC5bPNOKB5hzvz!T|Q +ze|JbFk(|{eo%zZk#L$~$42Sz%0t2%}*&N0c)J!^_V9z +z+ctF+H!+?QrVR--;bZP)6gbR=N-Rg$N@{GB1%OS^l+}=wbDLa2ALpG*L@H&VdpPd$+6(93ZL6*oZ}2Koump5|zTSCY!m*HmTvtg$qL0w5pz9S_XI;N`rmaBvn0N2_^7yKPn?Q3{=TzSky}I0N +zy!)WwfS#qMFJB5(aXhh%z?0O^~w7lCuvYZ(U5Q>{9O*5S{mY +z0N~YDhuGXxw@-F5Hj9P;gRPs}-|v*q_85HmfmPz8Ye_a +zE~&UoEu;Fr38B;afku;guoFu4s002)m)&pGlJy-sU$T2&!keYXoEDb2G-#}$ +z1^^YDo9j?mt^@+?X{&n(3|?es;y4o<6$0=r7Vz9Sj{v7Rvd^OIlT=M65&ezn1&PAE +z;w?9lxGlC($Sr#eF{j=WHc8~L5k!^J+L!QGS;GP@Viyq%y|1Isq8dD8q_bT@Zq0qY +zVME5+W}=-K!E$+=LxMxI<9h_9XM?af(F8;-`#I)tQe-2 +zTd1}qGsZf(aO|o}u0u56D>aTG&{W;hGAvQdPM{@K!#imu1ibJ}TnQ}c3C6~|`$%a@ +zn`1^{OppUHw7&D)rW1CjxPm)WQ^uuBOQ3y@hIm}1;ZNP#EDfZIv8m4l1yd9W1~NVn +zk(^G_fx5d<`k9UT-MqSc<6bk-X0U(ZND^EKpjdeHF#rS5DZmYsXC@jGz{3<6VksxbiMJ5pEStd-xD`#%zc&y{|DdqFw^jz(5LM@yuy8Px +z^N9(Y6)fv6@ +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 +z&^`?Hhr`3-V%$C1J1q&jamjPR)>#gTO1t +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 +z3+HmB(xweP8`5r_9HK>yTY0+{Ij5$YEO^ +zcp%=JJ-zs?g)3l*9O&YVAs2Tc^}x-f?iJCR?q3-XSJ%|xFENr0Y< +z>ZMQchPM)~?_SK?mK4bT^+)1t(1qQ#OmzCDMQya_Oy_?haqG*zo50hxV?&wMI>gch +zzSarQxaNGvt+hVNkuS!^1CZCVb^7fN_zZ1VGR}htCQbpd$+~vjKifx}MqPVpXL5V` +zNM*0Haeic_Bd*Zr7pLIUfOF4A$K=Gt*0B-$kqDl|En4+hF-B%38jbdeYOO&&h^-|P +zxpYnS%b{TyG*#c>&6b;&*a-AU9uk4AC%5m0L2N?CUeOJB(8pE04--(1o7wnEnyf3} +zDs-`m{vDgG0Q)%i3DOsFpaEx^_)Od#TnzqLA?}^!PFf?&h0kv64RS?Dg3nvw@+sfh +z0{v1dw6{qR&s0{k5S^uZXxy2m(I~B?kAv_aoF7JK4_^7CDdUJ8+YN-^voW07}sCeYj=G@L&!($ARb`AFr +z+%D|G&uEHc=e(^-p8(fb7!L-xY#q_pQOMp3L-hT1ZSqQ0p;*v4rNK9>$?U~!iMfetSYks-RyQ=DJ +zbPfiV&tR|_KO$Bx70m9D$wk@cliAY8h8EQEY=lm9oRWh6R0a2u3O0z?aS5&_mcT78 +zAF%I~ZBI|JS@C|`5&0)5ErVX%-<3hY1z|KK>*!n)0OBg&GHAods*C2Hlupu?r3-+{ +zRImr%)nY&!aPI>nbJtA6*y;?T0@^Jr&wQJqgQ7Xt-Gmv(Wo^JfpEA&Z9Km +z(1Z)L4L5>DcZxc9Vv-h#rf&}wu(LyUHu5_~FX#y=R!D5@(6ui>2g@P)>7x`S_W>DF +z137ECFaCm1&$z!xIz-?LO=|>^BYaaFPL3hO606jQ)Bk_M-fhcq97z^^KYwxF4|8Q^ +zWpzz|4tSFoA_*ozNJ$V|zGn^~HI +zzpRb2>h01?K!+h%I)4zli($W==x6YF?Fg*o>mjYQj?n^U;MqC1Z>Zo~B*=|nz}O9q +z<+KQ!`8uqE3u~zJDF}MuJ-;sVS^`2XlU&$`oy)%{R-;=bHP2-1osuR>ysH}-GGP8$kwj~0C2vP_)LS%7wK_l|<@9CK0 +zRB~0@05;l=iRb`B&*jE&*+WA%46(qvVrcom5&`R1s@F=hXel$X}FJg2~&_dgZ?W&LN +zFMEL_6(#)rx`pkWAw{x11Gh?XLfN--E^fT|bPJ0mW3c*Xxh{GyX+!4{55t>eq(KKL +z#Al4P$lg>h53qn~S31v`A$qz+XV}!^ytyUbP~pT3!PU)xSV~_$aVZa~cbWr1!Qml+ +zq_O8i5(Olu4jU4OfKImq+W6E@MqE7Ot|WyjOn)kk4ADZ!MW4XYns2wpvXgU3Y=8i! +z%|xD7`Sa|9X!%k|VD85jSzJ3v2<44U)ry&p0MQAz3wds{@+8d)2C{qx#7YOM1L(NU +zG3DrwHf!#VUebQ8z^Y61(y4f$nsAfcjpQ7QYj#YzHpKCQDY8}ld(ZRqq{TMG&)k$# +zNKD8q$s!|IBmSW1fv~6EIQPl4ldEv`ini}PRlNfrF;fFadvQ>{lEtenQVs+kYyHWR +zv{02j6;)kQ(3_nadZb)6a2ACwS!?5N>7_QgBvxE~YV)($(|R6xYwW;f0!Vm}jAzbc72%e{zUiog<}-s!KbcceVL91)Vhyc8s;N8ByyBnP +z0%vm>vu!ggP3t$=&|lX*-44v=h*!)=BcotKNQ3~?bVc^G_2aMvJb2qV^0&z`0a#cP +ze-{O7C5XyxLxwex?9Ul&(}w|28|1g1C$hE4a{8H9U5O|^QprV^WGgXUDhI@jGPVHB7d1xCGSxf6Bk>xmSnjti +zEZ2DKll=clB!)YfmmUMuCux!ezKa9fEr0CVe6Sb{!T+c!qhVT|P4yvJ1Jhh{n8Xq; +zA@>UQRd(nfY9curPQNndM?OSc55m_R^l}E$+W +zsc}nXqe}5@l>^)~h(;nRw`k5#vH34dI}~k_5UGR`Y9L(&Q0YRSfK=Eh>B0~c`RO&t +z)(Ly1wKkT-iD;^{&!-lQ57JWpQv=RviCzm-C#Xaskv;95W$-9SnQNYo%r;+RR0>@l +zH#r%qEG{Oi^AU6Z$M>K8$r_g^8}&fgCoz3qQw6XW==CZ2jQXDtbcX-Kg$%9jH$Fqv +zIb6HUTmUuFGbS+1bFe~Aj~R}@5fSHLCha-GG^Y~n?%)5Tf0<&9LX$azdGEb2M_9v4BV=gi36 +zvz=wLO(H8)ee5-;>$b&v=;B&Fr^C1?EXz>_ +zI8GEnK)F0qBZE-^%T*;C5Yt(Q~F3g3TEb6 +zP^7y_v~Jz?p#|sO@NGI24k3Y@#Kg&=CLp|*UA62@s%h#5aCUnZH?g03f-`?6#XqTx8O{OAtfMQWxK-V*9qXMzv{3srfOn9V5~ +z#6i1yvnS65^yYGF#l#;rEFHQjH~Yj@!jGCH +zYPw%EG2qii5 +z(heB_PaY@2#zz;;GHr#owIMqq7#=7jWYw(Ko;w4(Qx-V?5&r%!8)PVEtZ*kVXb2Jl +z3jBP=a#Q2swy)f>z@wG5W(~@!IKbxG4>w$59Tqc+BdBBjAm1^qX?qPe)Ecg+X=z)fT_-8T=c>i7=)P&ASFaoV1$;v`mWH*i-j0OUrx#eOJa@-^CkFL!H +zPwN`o0@G=^k{de&V&3WcVRE}on-BSH5!#>G@Z~xz!uF!|~Ba{vs(`go*>?&>(R +zYKPtv+!ANZeT6~k +zW3?AR?*FxpcAe4Z=leMflU}blUSi|aPPzT4n0u>yIJ$43+=vh#Xhu+G!7=McLW02i +zG;+5;iPepdAsNKfHf$5~>nj%UkxWp#P#h&Ct$EdHt9149t^en{K8W?+oBc{tWOqjS +zdF0v;^yW?LcsfD$&-=v(@pQpuy+ax)2b?UvLSiIKk!&fbCsze)oG6vSO`^ML&|NG$ +z2oc4qyW>0q_BuU>z_$u_F{4a@_@Is>z!zg(FcR{tGp)x>@MBqWk=zhn0H +z{<5&Y{%#pxe;(d0a{7Gz`D1zgSzP%0*FM9)eC_&nYxN(uKql7mSLyQhlJ`rU-(LUr +zk;B{1{U0mD5$BiRVS;yidmZXiFF(I6(e-UfhxYa7`RzNF_v;#7e_r2S-@ZS_w{^O{ +z{XM*WetP@+<^BHN{(gP?`*gfL^5*NaX=gU{{&joGas1ccH`gyVe^qfLeL~U!A^-RR +zX_1B5-}|P(08Kg%5!tXEbgR6TlKR~W+I}FyEpqJ=K$;nxWb6fx=pNajpC_{I#RJkZ +zfqjZ~28(;oUwBlGQaI&x`C$ZT?*8+8=MQ{#3YxOQ`xSr4s3~q{ttHU#Rp%1rb +z1G}!KJX%dwR#r?^!F-B13`W`qlyIZT8`esX?xV8!5H>#bVqYd3@0|WLqP&jC9KWk{ +z6%!k>de{x5EMb0jgDZ9KN%B|Ne)-J#@}W1$qLqdLixsWz5Yqq!gNBK}_vlo|-J?QC +zr-cT3sxQfDL6Sx=;HVrX@-qO8D0cCOjxVYC-y1s68%(qOX6DN#{Cjye{2vbFMa28O +z&~~|KAw&N5Ax{_o`S}f0*02tka*lJbVuDkVFO9Frd}KD!>)!YI2j=%SOofaRS?#s)X=$s`rj@7?Na4=jFnTFwya13T&jg%;;4H`G$gmT10`G0 +znT*llGj0Fr`ggq~PC +z;}=O)u2g}75_Pap04Rx&kNruFTQkP1AOtd03nm@hEH}8!x)u +zV)9i;q^W7$Zb{-GTQpCA4gF|XE!)BQ23QKijMf@D@7zPHAj~I+2BCXadc=0t@}qsz +zIOeW5nb53rZPV9D@&xm&90UMIV`L(SQKd|aBRtuU8|FG$jg8t27-0r(6~(1{}7z{H5*Hpj)tJ=-QgGZCsI;>;|urZ&LmmKBU7 +z8(cfW|4yb+u#YsGe+Jh1N2R0g@b}sE&NkcLaSp;8G-@k>&g$HK0o~*iE99C$bo?Ua +zEn6H-H)Gt_JvFN`eCB9u0@Z}=BGDuR#f0yw{KxRMgE!2`Y%{h76M>D>gn)GZ92H78 +z=WXm%Pc8QXAv`ufsLDq*k?U*Kmbk?M@RPQ+>ej#Wy5(7clOY`p6#U2k7TDLojbzdx +z-UUH~_yr@37h+%A3)oOpal>HM!p@bm4}ViVr^H#yW>;1l!^G|1E*J4-7TdV~Oim#& +z4jP?rI4n>eseJ@>?Bt7<;-~1C+RHWTSTylrOih1$o;JSXxGJv=@{;`L+j{<6@{O0b +zNpMbwfa$6Ab3U8l0yj}lVTx>Jve~-aR +zPGpwx2^1DEKH^2OiF)6FyWG3+E6kGY7M*W;kc-Rroqv%FWyiAzv9{x#A@$pr +zn0De5Utfig^!;}vJ&?5wK7kP_MQF}3=CJ|{4Z#&XT<2K_hBEi4q4=kx?4s1y!Zbz#?oCg#q4G%^xJ2c^Jz^_Lz*y0TxNK+fHnw0x7 +zNZPHo>)U3#)x~;P^8R19#$L5r@^$13e5_`MZtHLTtp6!t+M#ZK>T2EkcwUgB!1XVZ +zyZqFrQ>P#LYJP@x+3b^U$=Mxza`odn=GXrCZhwqFbhcown_u39g9hVv`&l`$2M59WTnb%KJ8Oo6qqM|2_$T;jyNijiY1#vWT|`|c-*&&m$Li<&Zt~-x +zL|tf`lUfU{2gSy}+*I3?dmbP6(=Xe2nYz!2_@;c*bUZ>Wzbo$HvDO(_E3t(B<>gJX +zUw$Z7uwIMj-+!+8=H!8l5X7`CwS{p$MR_m~K5cJI+0(%iI2NS17@X7pFFN=vORWAlRWsR=3KNw6!Zl!z57r`7JzU>srWY-5Rth*yX+t +z>tz@R{#(2&fpbrVF-ZiX>PCZtocP;%j}V(2CccAB+3v0?8b2>c%yYooJugFV9_s^EPbb}ir95U8Tf3b{CJP!g0}@pU!E&YZV>lQg%gcg)V}Xf +zmv5=OOSYp?g+9n*1vi-4>~5a( +z+c105-T}+WNlH3D(}&EQ)*Nl{GwarIk^E|0w3Z{$vat1rCDJo@DrkPZ6b^Zgamlff +z&l_@jT4w%D9QUbqMYjzk+2J;nk{|ehWDJjbtr%K|BC#zBIv$hNdH7)f*1CDRxlt +zZ*uJxBUdgsao+5-Z3@>}Z3+*@e!`SX)2Yrcso +z{CWar(m~o=A5pvP>1zC4MFAERd~s9dFpgq^2?wj2Ax;4ttw4|l(<0r$X5!__aZFj% +zR-6EbJc_9HKk0XGgL-0oMlzbL-N`38gZ1!HZ~{0uOHqpY{ml<0VR?KWx`!Xlk~Is^ +z``gY4_OG13E*45*8~y$2lpmXA#h4hk)A6Ax@Q?3#+Yy9$#jTEi=g>!)Q=+x@p+*spxw +z;^cmw-}SL-(tZ2p<#O*3a>)F_?r< +z<2xF|6qf)|2l=x`AM6xd_fB%k^40Q7kh3m9&IEo~FsC2OFB-+LMv$uMs|kjy3=M~$ +z_rr%r_@lh5Q=8?V;l8~ap^@|Q*-Iof8YoU)?h`M6`3Z24(0+*N*ZsT^ZrfOj;c+>& +zeu3rJxd6HLe)u+SUmszYRCv6LrRW2Gffrsd6@nk^Wp_k~aT$l5zXhi96aSE?0WVs^ +ze$m$}FqoTew9JD@T>QWR6(;XiKSYn=27xMm6dnA!uKRqe +zolFcQgQy3e*RtyPzJBs{!8Ahejj#Zwc(WvHyvS>7XX{!p_%eLjL88j|Wwp$!yZe00 +z9AKthdI><%aXbT?Ikswe9=XMB(lQAf%d6}XhMdF9zkd8U#~ExB+GK}3{M{y232CAV +zr_CvXI?*Hu@$-k=*3bl-Wi*K(Oh-%JSLB5Fgp=`ONqhO`>Y{_uZeDO(xQ~~N<4vSLsx$# +zpFz<#2a$e^8yq&(aV4t%?;s+wyIuMnmN9UwrEdE}Ll+T2q&4g17> +z=S>UodlFn`BgBcz4=2hdYJhVJp${1ZV)<1MthEo$f$-4z-z0zX +z%yLa%cS87d#e$r(p!Km_~UI4>cZ=(kdrVGflt6WNR#Z5MDgA*JDyveB!T3U +zv#fNMds%e~M*WaKi$eJv{EAfgt%{W#Qou83O{&54yzSaO +zcucj+4n@C@nTTq4ltltXmuoUMeu=y2H>1-KBWXq(7`v$zwM9W +zIcim^gmB>_MsimIvs +zR$C9wudOqb6<-1ckB)k5{^ojkKJ^koo+Qz1r$2!_0KhuTgi<0!$zi~gjF~uSEBP26 +z0(=bN`iZ>z>4XM~(k%nOeaO)`CQdO;c3c2b0^MkC{bKRY6D<$Raryy`E+*MNd$4S`c`M%JJ;1NnLCAhta^o!Ge3DYAgDP})`fP8ct_3!p5x +z@+Y)zAX2?qeiuK$eW<%pg1&jji*)JF*=s75&TTeTcgWS#JagzAmlSLoNn@`FRh#?8 +zNEExAyzUFU@wH{A!FNYs-rRy0B==3__bPt=M%Qxai-&A@(UG$%j*s(w}4W>D#K +zjw90|>VX_(6JUzCJCh+g?%^R1?aBE;hPccvI}1+%@a{n7$3dt?X{W4{j}S`EnuXXqgWbzm-)zb5Q076{y&yId@Jk0VKB*+&60Dv&1HTfO%ZM;kV6bTJN^u!zuM2f*|#0{GHb;NeS5pk&b +z2V!fO%D`PF3o|@F++*y9(OCO?qEw@wko4;^Bo8 +z=K5T~hlj1YM{sI|NxhSV5;}ubZtkjJ9lQ_Asd)@2XvbNgLcu~g06YM|0p$5d3(u|( +zr*jK84uoMc9<>}g9ipAp{F3#mG|abgxal|FI}lOw^<8a8wvOFR0mbt*gp2lk!|3{9 +zvXldAp!INS3*^rODTloE$B&4WK6q{*ZZyUrE +z_&{yM;>B^+7K%(-A( +zZ+ZXQG9g!{B&E22{UL4Sz#6kdc*+5R``!{eBlNDLWhfH4kMZ+!c;CbF)tO-M%$Q+& +z)Ig(ZBUTo*q^|4vfpQ~{w~NEn*ZGq~z(q(j-0;*UqQ?!zWQ1_MxDSlU2E>_pS7D>k +zPF+AV#UHOw43vOdf6j-07=7HXgWmwB#ryVJMs&bzkU36(wL_DGTWW7(gw0boErG6_ +zm+0Qw&lfiesMky=;^)cZ#MtBKuYc%oC3@fb^}vv@MmWe~absi&m1~lyZR!vZ$!5^_ +zvJUm(q38tH&gs1dkYKHk;rp-McEhv$=<-0}Xg4x-;=YCt`~um$d@^vVjQ%`6|gz7xF~ghc=~4M}s&h#H7C!d~D*5N`!xkK6 +z44!FY;G={Bs)h&JNQaO9K)VVRDnr_b(@a>~g=B-lskEG29_($i4%PiTq`8 +zPxY{FSJYwj)3Ezhw}}}#g5C2+Njg(lVlJ^IL(WC +zG|->*etG|qDRcfY8Tc@$u1+kLd|I>kklX@bDB{evJbPfjQ=xj>19yd{rt$^N6*<=w +z5)Z@cpI}ZgLSBMi{c}g4sN?OGp~T;)tkj{00*7%^zrG+YM+08d^R4(War*g69Uoi1 +zrX3CtI~Tk_7H9)m4kd}=wS@J_UKi^mdDqbV%VmO5@z1+vaj5t;F6J_VGE|{H=f~hL +zc06D1M1HqGKc?TxDL(snxd&rFF#Cu=WnWs?rj%F(+|Rr9gE)1q#4kk;a#@EvfOzk} +zrx;gOM=t)*_ykA;Ru+`o^PfPE1THca`m%LK-UnXVJBMTKJG&lFyOrNGx3bs8Uqoej +zD}V2Ae^G7dw*HUzrey>HYRX1{zkT`ke}74Ofwfqx3HV?9G56BGRJ0oF!fEk*dA)L? +zfNLtRQf%GYOQyG8jz8`eqENcT=kJsW=Z}{{jEv#K+d@Xeh^?i@A~g@X;5Vahk<&>G +zzj-i}4DF*%rdWGez97X%vfuFRTqm4mVShifvvj%@{e2;3*B&#bAs^h}1=w)vz&2Ih +z=01Z_B_5dj%WKJQ&{oiH`E{1>)CYrGQ6vfDMcqjMwnPW1QZg71U^RU{uXhc4iV{)x +zrC5NTIp +z_1qWYH%_|Z4YP}W<9p0Rv9zyT0ynF&Pqm?)dGbGm)BF?_Bax6NPtD~DU1Io$!T +z012$Yl+W@#e>4u@>i?=&T8qR`|6}J2i;vYYB%mxFGQohjl2~qE{&aTJakx=|)uo+} +zvElzc{mTQj49o90ogk*O6a;jNfB*4r96~oH8jVY#7{@#BQ@ff94vfa;jY5P}OuZl@mO^7*p!8mo2Z|`EJ*x)_ItUX>>xKi6=*g2(!Dk43ppRr< +z9|qmj2>G?V9yGnfbr-j3_y+HB!eSx`w@Z}Kr*w3YI9f4Ug~U3@bP4zoffK77 +zpEXojws`c5@#RE@DIVbWA0||shckP%NJTvFCL6BT8~i1VxXTlar$t8K)!5}x6Q7GS +z&3G9X+mvpc|4xc^ca&33wJ~v|XNMRoM9fEl_}eg1Hx&SBg$N%zt`emTU)=L|BN?=X +z@WZa^E|U)a45<&#XY1|!Qb;ojh$(|DAK^6Kn;PFZgir&gEoV@2nhi)8h-;#lj6K=B +z5Q9Hu$q(j{%8!UVAq9-hc8nb@CjF_8ELu^IugIq~aQ;T!G)5; +z7y?A*u+<`mh(!dKg50BBH1sWuR3_}CSS;Sd2gm0p4Z4G@snAYQ8%5_&wk|+F$FGlS +zf-h`)l;1&F(I-ap*Wr$xzFjj&Nmks|N=j2A`Rs~QE0!vZmxE(oA-H%zxgWkNp&Ekn +zm_&pZPU|6D|NLmv)p(ZqkHH-s4Tx35I=%wRlD1Kx7Tf2kktRSQNo0;p2QUyM!|K5Q +zkuq`N$mTaw34-M{qd$Wv-GEhM9{{{=Bh^dw!hHV*>*?L2=nyF6vw9q=w+viKUHub8 +z)5M!&AtYpt=QO3mwpM2jxwi7qK#?>S8HnTa?gR{bjKJo0mtk(ySVi%CC|x+1xP}l~ +z6vDJlIUIUwjCaNyz>X5s%~7}D7FttC{h68a&Z=ve+~*^D)^Dkx|>z37uY6PQ0U_q>Qrp%CKSADx- +z%@P8pJQ|!LA +zZoih})txiOx&doS0zv(zEB3ilnrS1bV61OlAQeUbS`D@+IVi1Q?_OP7?lb1Qc(#_n +zo{2SarK +zQcux;G!0v8ZFMkXF2!=mJQ~+uuO#Evaysnm2EP9uqtdZN(SzSNcPOC({jPP(0z`nQ +z;FK|P{t$ZKB4CwZb5WC<31(H(08dV0#1&`;_q8j^x9t2r{r(6x&L>2F|1#Hwl5`kI +zHps91mL8?~6TQdkz-y{TY;`(R_sF_})vWaJ`s`j}lC2G7xfdu&G>@SXG4Ii*Z@xcr +z3f@DBGomqv9i6@D3k3T!A}F%n5XFCjW<@5AltoCrOi0WLGQY7LaldX^(yDM1i}O=a +zFcv)WrzY7x`lPkF!@9eX!nC5g^=GdzW-I8_oi{q+an(2*JGrJC{)jLvBrEuKW>Ib= +zsb~2}AvR-r(I)X$p@al&y&0fF@*4Wd<#4!HD_S +zS$wC_7w@=%G7JX6?s`EIK#U;7iCfHG5;|KGQ?R^@bV{;4G?xQg0*yI!pc%89?1c|> +z(=pe1Jre0}{xihKI7X#d2GMLmhK2^g6DWmPZ8hIDo7JI%7fz2@O2Fql4cPNea)`8g6XkKlpi{8i7rY29csj}3al-#&_U6#`9C4gS3{uN_^cyt&^F|2)CF*IrQn26t +z{s9b}obmZG&IQE(Q`QnM#-nmsTc?QNCP?^IBL|OmQV|Ax6v>h9CFL9B(``M*=cg5_ +zbLKMg+Q4>U{$HgmhVO#+)#^ytS};mI@`MZ%SEo8SW7l;K7)1vn>-6y<`AmD(f%o8b +zF5*1}cGA_6{8V8AgD@115Ib?y8`EzX>=t9G*;@F05wKK!u#dSL-NhfUGLM?GxF?8Q +z%iH_pyRqYYXJwGa;M0b`exL>OWqUf6bo|?J5aIM5U!`&6iTo&qH)J1mxj|g3Gku)8 +zm<&8nh66oWl)`o_VLuKyy)z9F$gw?br-n)z7T)NDk3i6I|Y%GW@gCupS< +zic^*$#5fFrDGCImEuJ4;t%l#-ZD)nZ{~$|9ONB=C;!m`JZW?Ub=WcAdr|Qtw>sZCv +z*zZ(r_IaI%mwAS0gT9*ADn3kPqRP2%di)F~93LZo^f<1Y1(zwiA`mP)Sw7K9b(v}c +zmSrI6kp&>-WL9A_wepK;ZHPIk8&G&qQ~vcNWbf7#fPsl<)u;Im86N7K9tG4fAGL>@ +z%=FQB&Ali`&$qc?N{*qCIzl>a#*w2%)Vm3~C!-zFL_KB%p3=qPFDPipnX5j%Q?Z+1 +zdRMdqu7>`#DOqMwA>J0}64sGAAoN$0gn&&!wMf>S83~~sP?9*yC2Tn|sqrSo}ceTaj-f@0+3I#Vy;HNTKC(D|RZ1^tS+ik~) +zFPDhByfOEwz!}k9QXsF!-|@pB+o<4^Gn(!nu?tR%{ovre6iG%k@j#_i2!w!;bU6d@X{@}W?WzGZiHxz^{Sd +zajS2LvQuDkCyoRO|Khd_{=y1wu>6mWNjN>E13|ywI>ZU7q|hO{ZNp8ZXggSM8>gm% +zS8YO^^MliA= +zysS(DN>^doO@ltf>NWv@gt}9pBQS|PoJZj*J-hGOrCK>dnMh&I7}UHp9-*OS<&Ib7Ut46;JxC;tVnhzNn}CW7 +zQh7rlUKWfzf$(KCKA-3Tm8TEjbQ5!n)UE4&I1a3+mQ!E-w@pCG%=x&UFJG%u-5)Zd +z$fsy2?0OJNI8s;U2ImCl>VH7|74ZUvW@tqZQp02PGt~KpLJzU1(Sg~HT5NaVH?a5! +zFsN?4?HK@O)(=b(&J{lILlW&+3vM!hvU~~PQ<|0Xs}n{2ROV7s2XYJ&qF=q)wD(o0 +z02drLTAf5SXIcr=c;9uw_Hn7uK_};nh;(2%!l!}NKw_*f!P0nb|AcRYF0tEt +zKsrXy>^J3C#2lt)-)+bk$=2f6)Awq9_J4}>{|Xj^v?g+LU5nV*kA{|-cqPaqdhRYx +z-4hIa9;_JkDc>3+4kjJx*C`9)OhmmgYcoI*aY_PxlXDFy?-}HPn!)I~wcb)oMTAcU +zX;EWlme6E{5)<33cTNSuZu>QcXG{Y@uC@gU41r-+OkVi!C-CtjJe9e2v^Es9Ie5HJ +zctCOMVe*L0Q-FTZ7_NsklD~{z&H|}+0F-xOoEwTiOC~##B1%d3rWcW^N)!}~7RJLH +zjf$dF!Fh(+1c=`e?7k&Ug+X91M8G0+?I$O-8@_(4rClO;U +znB@v~t{7B8aa!lg!+Q!GyGwjW*UdsFK$722JJl`eddqkhz{-qngHI+~rz+~8t16lVFbntWx1y?HlRyz-Dc;X^p=Q=%oWFm)z>mPMRhtqF}3;n60fM;%l5T2jk3R +zV@mM)WbqP79zB9q{5k|E!}FbeDCUBTXEFxo1J3E8hHt3;5Q7Yhz_lsUP8>x??+jzd +zpr$fTk|FDN+lwm>Ht-V#!fD2HaLZO}cgD7dDi>cL30~2a^Ic!G&GClk5#nK-O%5i0 +z#Pq7c#oJ#CG5?fh^!xCVoV*}?-l$UYL={CzO0t|dqTdmRWl8{-e*@XwA}xkxppSmVu31uW3iru4k&SXsvo|HM`}h +zgATr1vx}AEczH*cDK^ErZ7D@`2rL&Ts=I|6@Hlk#Pqc#BovTh|*1lf-V}a&~)LUR9 +zh?n6WaGWs|IXz^mU%l`ZKxX${>Uh5bO*tDgIGmz*t26oUZQWPmP2sa_tHRt%>euz0 +z5YX>+f*FB+dE}Ak?_|l)HB1ilXpS58bgf0^f*4sOc-4vnMT;C +zT1=YNzUez;Z(rZp(M}Tx6?FGx5nXPPOUC7vvr4x=klb<^j8g-1vRDXFPRMS@%RJR& +zmC4OD9`pgL|I8Q#FBbTBRML{abvX4+fP0-z{M(W#O#OJ`%|$JVv^rH4@}=O7l76Up +z7jZ7~9T?T>^zlV=+{4#pm4PSIlyqtPvEWaT7K5E@77q|&Ai%)+Mhh3*iL}aA+;IJn +z?6~MI@`=L=THPNT0}Te3Gq}Xk2??%(bEpobv(|&A%w{= +zBl~gJtj4R&kIBxK54htm4hE;tX-Muc876l#;Z&3K>z#$nxR7D#!B54^I|pDya3a)L +zBOUjo6(BH~D)l6F!RXQJLa*=G#E2bqgJLcez+X;NIk&r8U;pzPy)e1v5$hZ=z3*ZN +zzp;UA2I*m%PZc*?UU~t#_pwb?i9;xWN#g16jJ$CK)2mJa0vqvk?PM-TMhP@C8A;ZS +zBipw#3O3?@t*q%Q2y1qosuyqY%sG8BZGZ}GjS{a)GLf(&RF&u^m7<~ka>WNN^@g`W +zgWOw`CkgGs`p+w{K%@x +zx4Sy1^2{+xcv42|-vg@5dRMGFxeJI`iWWAF6Eu4S2MVOd4Rq?e<;B4b?i7D`Eew`_ +zX1}4*vJnoQ%o5(!P03Z6oTV~hX=VRIb}AuGwjCb)W$Lte9FQp7xpmP)TM +z#EAj8`fRxAT^-bBq&w(6{~xxmmSp78J+D>*C^wu#-a2!l`c&~KP)hmTMYK>Q<2G_zLt@W^2VTY(Q(Ly|y&12=z_jiVnY +zH#Vx+myc^ZEA+{@g;`C27%VeQZHpNMtXFU9bcL|GaLe(6wY=RIf%_WT7F&ZpQ_$3$ +zGn_2AsL^!5<=r++ppsPJ84TvIQ@<%=@}B?4kGdj!j&{e@2=r=`jL;TlN;^Csru|n1D&y~uIv%oXRhy~!OP3o1*tTiFmj%n!@T;QO`kD9MA5=o1SCCrg7T&UJo1?M#UY|%R!{Yh0&~y;x3n6T +zLjAmTm^*0pw~+hJcJm0FwG&DSa`Wlnpe(-+R-pIfg3kWCNlF!K;S +z^G~m{Q`z3Rt+ilG^ +zs9?}nD1zTHH2i@izEj5CdL6>_Cpxi7`iUW^#i@ +z#hUtmgoU!ET*uVPZ67j~MqmolG20asGp7zyI)-Wd!YXfX5y-~U6A5s``axk{-f^C} +zyz8SaZxBt1+Hp{NT~%(|zVXY*%jAz`FWZbdkX2_Ak}bn=i+bT#xN8DwpV!lk8__5h +ze9WitpYg|#4f<=dppwmoOf`LomtKc#!hlD((e!x2ae)dNzaj)W`kalVHM0k|QqS}y +z@3i3F9Q`Hlp@%}%!)Re47dNZ?3OCZp4>Pyb(_)6ktL1A2ZR!P{FeB2qTK8>f6yh$| +z4U{jh42PnxSA%=>rRabc;A`OvChDs3wuT&0OkE0lM2r9)47lawznX3}Sd0lfv}>cB +zH6{_#7)w-UVH*5UU$s_=-&4u8NST&j&@PjkS@ +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 +z9$Lw{mpuI#+U!>aNH_#6@h +zacfCQcp4KrdE#uoEmEBMLliI<`8jAL3_^oPBr4&G{ +znA+Rf*4L8K<9lBu+}6xA4i|p79%MKWoWWSHg`IesH6tPyRirVP!*6{bC=wA$v_tRL +zRbcNM782FK8NyafRbnuIEyQDdnPQ}l36|`(1Nr;>e;d!0S;{HO95)P!fL0%(Q)O5T +zN%o9yDMcDwm#o|;dqVBz1w<8=hok51H8z;4v6EIf#%{e|$Z0`sdYDN#|E?J=V=;8Z +zQ`gzaG%?an_c0eXZ9Z}E4A4<$R<=4leI(E>c+Xa~Lyuh6aswED93mM%s2r8^`5Js4 +z3yB~zD*niOLNewS22+Z?qgHUe!#&ICo=$+JR2 +ze6*XPf#Hlloe#y(6$0d^PmJV&Wv0G9@#BJs-Qi&u(!Q$R??kT(*+@|PomgGvKp{`9 +zhva)U4&yzR2Gd0<#cZ(H+QtFv&uj{C(i=I3%>z0msnaK4&XXs@;NuGu#$RBz+L@5+ +z*R)koVpH^0<6$>pTjfU@mrqjJA&-12rBRo?Q#OTDQ4E?%L>tmZ4y@&S_VaRz&KnU6 +z*zLktp>y{U0^-TOA`VGM+F76C9l0-TlGJp#e2TsdzV{YXNeF)4*+%Tl_j?5V%QJ8@ +z48$Y0X#A|>GuN>b&Oq-E7D%vNgQY>rRm2ksIlZo5aADY!_* +z=%n=DfPnY631hKK_?`3Jrxzq$$l6o%OSX`j$F6$Ug_!`~~3v!i`9!OYa +zhl7N_wq=(zwGL4lgLTO&lDeDD`BbCUYj%B>s#j4)!5%YGX;MLiKU-$&l{HIgHSu|U +zKWNB=nlL`^D-Eo!(%c`uxIyk*iyruWt?`N2I(2`&4tB*HFwO=Tu;l< +zI#E_NmJ-paAVB8AZxkj_r#>tYCR}%F(+4BC5HQ-6k>rkEILk`<1B{>j7V4(l?Ua}Cfx=dGkGDWJPnwW&a5r@!9zZ8~!oRV5NwtU$$pD6Ey746aC +z#478tF;f0{<^kE93?*t0k`i4fokeMyDCUE48#7efFFf-6p@3R&HeAuL52tpKDif^M +z)sj2j7_Vk!TOGXXUmFF=ySU)9J +zmWeA8oE+S9EVqYYUaV*`BJk&NbLW^!px7Mxev>8LNKU>+ky_t%s_^=kpcjYZPQ&Nt +z;X6E6i*Vkdj$WMrWOofw^WZ5#{)${}For+AZXqsL*gREP`e1JVdIDkI#U{D~f+vP? +zD%Kh4;j77w$`cJ+8a+9$OvbmY8=0oSNYInkemj@EGn)=is(q<&KMOTG7~wj4d?bpO +zbsp&F%8|GbwIiUv)w(e6J$D>hntP%K42+<=mGYuk$V}gq$4VX}q*#gFrtjh`CqZrTWLj0woB_z=o8{KK#$72&KJCX_+ +zYKR414Sh1XWUKdV`V{l+BXp_1chHEFxs8!OmznCc1~5?=8~qvag-NTKd_#dq?co53 +zzOA9MZ4aAo*QL4Ew$Id+o3(huOpa%9jJ7nxXR=1`*jj(lE!k%Ul&gL$}|>9sIvj_Q{+`3JljnRc%W3wqcy6ahE3f%m>B27H$%MHk}-~ +zF<6mE$KnTqf1_sPwbI1)lF5%Vj=Sar;;n*>8k&&<_Wk?FkKP|Es$vPdL&n?!RRd1{ +zTf`bg&{Nn{k(|X}b;V^Fo1V*VDh6HMc!^gRKNfugQ}Y!h=Zg;wQUua0de?0Yyhp5N +z9&l4N#ddf|rrtdNXCeR#%Gknj1p$A@T6$zP#cFdN$)S;Fm;VBBXXr8+YDNJQxRQ^` +zsWdXAP7?W*b(+{awO4L)g(}Zm2|2uSi9o>Q2fCb3f>klf;vn7)cV#Sj9VD! +zYSR@5AeIe_Kbp*D)2!@>-pb{roH-2Wl%*w$x{`yo#Jat2{WB{WF$4< +z%CTutt1GUKR;({2!e&O8%u!52bSC!qoo?5PmtD^F(Qm+^YhZMlNb1g23j}kt! +z?)ec&=>5f;3on33BZ7{?=zh-D6v+!?c^PbIC+$RK(Hsv?LZSyt;Qk~kjpjAD#2sy#C$LQtb324r|=*V74?w$u%gmnEmNUB5)OEjUR(bhrA*g%KBFbLlkY +zt0C2cq0$<(jT_Or)^^_20JWkzT@;M6!u$$h&&Q_XFM05J+H9mCUN; +zSX^nFS5tBEz;eAW1ckTR +z?i>UmrWbRr;Nnzv4rac*5PT*MS{M;EI06-O)m)5h#PVW_6qRQ8M)%x0QgWcUlxB06kWBV)IndjZ+;_TmpQb9yOL!xkkWDt^z +z9M$Up8n_4p%$y&o`f!!jA5BWXgmD%pEhgx+cK>w*QbV%kIi}%AKofWnB#L=44|j0r +zh7->#LY9Su^05TJz^ene)=E@}Q7%LD<&k1%iT3_7nnz!KW7ctV!DjOgtHf>76+A_- +zZ&$8BCEl3Y8o5R!EsJO=O$#I!y7?5vwx48?(-%WJ(`~x0O%@Eo^siL|3QZa!4i`#_ +z_u?(7CAe*M{OvF+1zToBSpc_$_-%#^GXs{evSq?8PS?njeeU1lbR?6o%{<&+xYa+1 +z6xyxMS>_u7f8XeGNoix?w059^&X}Law1d+t>U;uI{4a_ys#xa)dp?H6!h#L^JGdKM#Sup(k>hR=wWrdD>vd1 +zR8+PdwyRAUtaHDUUO@S0alU@6!lx*d1LJ*2a>;I#(>>9xlYAQFXv*ET4XvAWlwiK_ +z5U_G7Rx{xW8mlJl38~VRXmiSQ2tnGgO`M)aS+F0RpM7n`p?Vw&q?N!zSBF*=BLJN- +zb%900a66co(6N^&d81(x$nu8|OAabC%3NQIP{5e5)jhH|@*{yW{6+nD(+@W|B~V38 +zE`@ZI^|B6w%EcDrC1IRzG!8IJ$s0gJN +zt$!b7_8DX#ou}vi_iMw-vAp-6bZE)9@DI@=S}72w+m)2S?( +zheCowFV%uG_--#|1AIYV$f!}08WV~cP3lVQLc~MA<48myT)2h`t~);wNf|}?Tr$$M +zTaIV@sRo3<;>?ZjsAI~}HbP(%?rtaLahE@fy%{FU>hL0F_Ee@BBb74x3W^jsw(3#H +zm^@b*+6a~sd((RPFp)D~c?N@0#HR_QkKR%sv{33#?H;p7Je{pWVTvdN`zuAV%-3*O +zNyz_=;sSdGnMSUGijzlyR?$d78ogdo5X7IoA*6Cx*RIGjdy*X;5l{;0ZmJTLzY^3W +z)E8+G3zgrSm3ZZ*Fz*q{r}_Jc3wE=HZ3;aNTcFk$*286|(Di*aR{!_Q>Dt(gRK@2( +zEC41<%8*R8?7g`j{S$|ZO1nmd6_Qat_~@#%2>N~h3J6Cx1x_4V9x!h>!cc>x>1?wz +z$yfPebIFlFDd*O~o$m!1Ro4nX5828iQTBvkF>3ZKv8~*M@Pt7(7&=q5;X);3= +z%Gu$BBj77~F+Y3R@&SegZIKzpixyj>f6y$GvqQ5oi9JUc`YD{lk*k?Ch0s}zLa^D# +z9Amm_<&K(~a@cs?j4$N5!9uomcA0FnlvZg1Loca$rF-yZzc-yhDLTaT$d)P!ZqcXt +zRZ)byazjSgw8d27_I;8)tOw~Iqv{knx4ltLoWp=3TAy))fHKGWYsar%JelXcm?;j= +zney2W`jGQ#^3)BHZDL7tPV6#{&2Wf6PW6IoQqNgBt;RUWR-!3yRr3+T3eM=^yi!1R +z2=sSs2YMAL4;AS&xb+PodEs1GV_|529Kgbf33(&W=V=E&TM2W4-|H;poytF;>VXcv|q`z +zl0BO{=Yd2h&4)aoH8InI=_ErO0zc<5|4F4cBtjvshC@)`N{*0BS+a?t7n +zf=iMD55?&yaT|<%UPdp1LThkxCQX_ty>d(=vCAm|5IjJiRpcB2k5K-vZt~f}2H{fE +zBwzP%V&Aiq1-uXNCiqSS215tC1@ysDi_+>&Z?uJBgXCKE5&$--bTxN&El*z8$YZXl +z-^yKi%*^tcwlvbNG{w|#d`)-6)*>pJP59pxtx*iE?ewRAimt}s-$~N65l=jMe`uYp +z1Rl)&FRre7(L23ZBB+2^di${by|fyNSZ87RGWs7DRgrkkAxzA9Oen!M@T{Qm;>jfrF-sUH=#&eD +zQ!;of^HxAo+&UVPsw^O-%Iz$D%)GWv#KML +z3||tTR}2b}}Gr{AiC@tNASZ +z^VoCFLeBj@rq7X-rYhqLilz3KIE<1q81Ea~Bos0W`jv&55{4w5{tEc>CD0PYJhO=~ +zec~ZV$Pw_rJ{XlW^S7mLG-hZ)xfsHODNh(Uv2UrO#Ho$I{Gu9U*701ta0;wQjm?9@ +z8R0w#Xdc43?A6}NURYt9T +zI0J6TcX<4o!!>M(n4NhIx#)(>dTP^|l@BzT-upcLbWhsE!Zb;`>!H~beYEO@+N3OV +zwO2XK?C~d~@(7MHgDmHy*+@=%gk-q|4tT&yV|yF(ApPmDq_E2BFlOe)5bG8SuoxJ3 +z2oBL=XLl2F2i6PNtIF9U +zif0l$=!wb_A`5DF7U-)mP%m@HWm9S~OQjbqUX8(g3(=~K(+HciD6FNYNFosZz8E>n +z7rEFu2xC*uM%~xNe*+e`iQ?dHjn?Ljfimd^3rMXBZL%-d+3{$kTw8+%D|m%}%5}k8 +z5{E0@19KNZLck?J#Aj0@`da4Y833-=y*Mx%v$8}hWx7y|)EdLC!oeux;L1#xwwNxj +zGYLw<6U~W)hKr9PfgQ`&qS)_t*+Aq7b?(C56f6H-GCIP1E9F)(_*}j?jzk-x^9(Ie +z`{8Cy!!4aY3;|`ZIel)K%0I^kl}(Qhe(GnFIMNy%qOiNJvXF5BrI2sYjMNP8pq5vn +zIUtZWhopHS;0lDd##x5@yj*%xB)2%YLcQ7drt*U@JS+o`dovRG +zA%#)jCc%jmTJu6Ky(pyms-og2xnS>Rb)M+7(tm;0Wl|g4U7Egm+$F%W!ks^oxBA3^ +z>+JH6D?y^G0~-R##sV%Z8x!dSG61_ZL@4fGGQc>4v=7T2N(~JP$Bw5z!FoSU*Evgg +zrU37fsrvsiv_JoELt6mte;eA@|1U$E8uot-ZL0r&L!0scV`wKkFl)vjUck)%X=n>rf!O?yq5bs#Ftn`&{xh^g|1-3!LZU$`%WeZ+qWsNZb7oB8I%jHF +zYWGZp{dM15xEV@F^cYEEW1^vnkUdqm8HV`)-uC0tc`=*=fm_TzS^{^p-;-%xS>4;}C-C+uqcHwl7!D(+?K +zC^abkfYrKw-$I +zk~~k4xF5zBUc>l;DTlVi3~#}kK@{QV4II7V0 +z)HwTPgDn6>PSK}u=q0~Gox(3<(1}tMg%FFXK;?8HFyoQ2Npx_6iTQfLHn|PzTGqyr +zIT2-2pFUOt?}W4`{3H80`RAR~$wQ+i +z8G?Z~f1lrt{2Ir|CPl;$UzDXYR#kvEuyKA8V)bvNsQEj;j>O8Q-x0IQz)bt_t)apt~p;P2dSL^^Lz3B&JTp46)qF5hj-mszDE6`Oz**Atvsc`~s +z1%EC~Go%N#5qryz_3sp(ApL*KEwTZeH*MZvwwX +z%`%Z%Cr+MjlxK!6f~v?ZA`x$7bA#0dGF|6+*3pzpTBBNN_83$I_6+*0IfVvG>Pfq` +ztsQ#v#eoUL{)jNd`Z(}J_cKqi;&tyf0U<}L<2*n5F86Gfw91z$p*dh80(DlPfv!>+I(Q-R3KD4NotL#QL%ddASjR>1}%6*+{tDX$4jyx-#PLPJ4LRmbZ%)l%!RkSNxdU010JWQYHu23gpy#Lv?DGr7ymYn?vcil&~51FNla+_e5GX;afH7Th}f_ +zY{oS?YURdAieb&A$A<-RQ&C|Zmk*D0c~NNs~HSYg90f>@={^8Q?tAdYYt_}+Vup9EvD-df9rBF+z?iLHeUTPn^TAz`yZzsx^yBn +z6sJ!@8}IHoGJf&WIob%_SS>k`B}xK&hIdA%c1)KrB=@PjBCLei4!Q)4qPA*80+~DE +zJQi+Hmi7}lOBc1b%i{PlJsQcOY}_)^w=V~u;osP4$&cFh_oqL9!jJyhCVn%`mrX)o +z;Y2}`+KWo+iK}7x!o^Y&K$tHl!_$dPo(b^EY3V;g(8~B@W~BcYH+QKm>qn@gc{w`b +zdZa&jTrIaaNI@gD!|zCh)1J7U5JA +z2(Tt4!aKK0^{3*Nd=lf-HG)8}pq$2e$>h8WTkrwb1>&Oj7AvoILv>ARz`>6L%tFaP +z9J0MS2>A#H0`b4`a7EUfb)>~p3(~_i#e^Jbdb^~2DH%?*T5v +zHvdKFG^m;$+Bl1Vpv%B0A+;H=n@;8i?w7zPf`hx?Cc!YHQ5biS;4ng>g8n&k8ur#b +zHEL#yB=4aM=AJSH&KB>`KuTr`3OUp!n?h{D+VM4+l)kbu5a>UORsfm^c`Y-DY +zYV8}K^=;Va8Y~0;c5DqYKjC-gf@?}Zlk;!Y4afHniK4?^-Y&!~v~zzL10bWq-+&1x +z^2#Gle8?vo_6T6w2+_%&X&@$wv +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 +zok!f*IZ;tH6TSHQd8 +znTm`!(r|SUo~b?7ySXvb3z8MGx{D9%)w-Z+kX<@z4i&Yh$fO|D)jRt8PNl9~6aiKs +zt9j5vLpFpccOK`l{eX|2<0{eV0jM8)D`jHzig +zdb~s96Ss`R#0ljM$FTAW?by6`JCpu&Q;KK(wFpdT>XL^sa@_*q2C%{1H0JY;bW}%& +zFUl{HX2;lT9bUURI6e8z-H$hy0W%ZP0s*jgRJ +zM#3B+$}B4F7kfyG-;(jaoXA^O_X5XFhtGkKJ0OpvNqf4Gqsfa^k9R?1;ZJSc+Cxj^ +zl(Uj7ao0g@L=qFai{JtGO5{zX=wzRY9aSaQB8WJmq00HEi)Irx?=zMsS{edZC~EnQ +zwl48(^{Z~nRSIGE{Hoi>Fq#M?y7F7H~TK`Jnv*tf`W;dbkSrM<6BOn=QQs)PrNiunV6+Sfxx +z8Uz~Yohh~tC>kKas{;j)Dk@f^c`BG{D`SeXPM8zX-S}=WZ5n9^Yd7W< +zuxZS(i-v&D=e;h&!5P^E$lwgax{jOR0_i^hC4(t(3LOE~Po{S|U4bBqWRO5Kx`_8|FEeW>StwoC%-9SG9;x`-UN*8zDgU9{ +zjK>{=PvqXixs;fU0#^EUXVc>sdc$=>lQ2}FGd;$dB0BLwGC}Cu@F`a&6!d{ID +z@pN=XlOtQo1l`#6o^PuaO%ThuLxEh6Io<}m%bM=*KI$HSEXIKlZciyK($JQh)5c&} +zPl^9+fjiQegWqm0`MErF=A}(xkgDvW?Re8W)#A@8@k;zPo=k%l6rFq)SZ__7F>{>o +zE&#&gRy&!p7!LU7Jn$T|^-9tcL9b7@%3i%nPv#C~4WktpSrZ^9ir>pM%-qMDz?;|% +z-`3A2DLBDZ_u-LW=wVrKV24PgxHj +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 +z>_dxV6Spzk5YV8?2@RXRWe~zBVE +zy3a~hl&9T!*&?mo=N)*hHU6Nushm2f%hO1rL>+Y`=fn6VJtnPA%i&ni`*tQLY7rLn8hnNS1HH|Vs9;YqazdX#4p+gwbio&z5zy>&iLE!OA9@Z7*&Y*6!P7j^x=dVMnbNUywRR9&dGF@=tp!| +z&`_|>ENv}PM&<%cSGHju&uv157!O_$zp`ers*}>w;+fC1vV_y!fT3HBbcCUznxEJ?KA@wO@jNyCn(ULgDpF +z)fjLxRe-F>OrQRC12NzaNVh{<6voJE`<=5_`2r?gdAcGK#Sv_J?8rR}tggwr&*uo9ZumOML);Ao$?50>-F3cyM%~a6DY9}zAL73di`Fp?oT;46jhsGz*Dia}_{oB(N +zT=+HjKiH^@MI5(fD+a_PnU5Gz{P4zSVvru}&I@q&@+l-#`;wAi&f|I +zWF&&!X$AC+HcQ%hXi~u=-;LMESlrN$cp$t0hERZj(LIN(T +z^8Dha%wK)9|3sd2GDkrvF<2(rn#&Cubsz&1bSL%^- +zFQECP*I|^I<>sC3z4Xq<&3q`bLt9+HvTL +zM5B`xvpu$0f)%F!Ozte+Uz3|FbJEp>RVFamfm=LsV&fmqa0qHdr%O$EK8;f5K&n|p +zc=7e_Naz}p2T#8vKTbYtd!Dj41#t8L^`>w(xaNKkZWle9nh&rg5lX*Ub=nb67xwi3=B +zyV07{?5dR)e@d_WoH==qj($yUjbD?SCQ9;&#l$mZTNH-50YnZ4$at4HU4lotv-oFZ +z72TAZeXBTu$H=UT^5rFxm`&*l75p;CgF;q*-AA^)6izF@iPxL +zLa1J+1K+m7R~Bn@qDAv&a^NT^75-D#f+~a@h#DG>j_Y2i<=^Uc!(JMBx>^XUmObzxr&ac+sNPzAaemK53$YG2LdmwGhe1#H68Vmpg|ad!{UE3T +zsJ%KG;07TZ9Im${;hQ+Wqx(~w5^bRSu`88iCUZ7N2ck< +zmj`%WL>&Hm;&oh5z`i4j5rVA4DaQian>6Cz7A$b;L*p+`QzX(V)J1TPLUqQjUrk%^ +zaS`tRh@4KGJ_|g$crhs`^4A&>EUimWU}b38+A(180x|>;Yud+X(gD_ymYWF}Y`u^T +zr!RdT7%U-Gb?=xFK%*-J=2*C7!1vPy>#foogS8{@@QhSentvdfo0E~Wm>y#Z!Q!2i +zD?drBW*6YG5^dxYck_1oVY2C7rL}bqkeQk6x=4Wa4ryn$WR|+|lDTqUNy)<38LEvC +zjJuEP;T9YIdWn}-i;-m5u#Yt +zh&dy07Ah%Te9O1@#UWg{7jneUpCu*A8n4NAt=oIJT=g%Sb|dRze35Xbz#MsIzGOj_ +zT1(sjdE*!*A}NFN7%3~ex{s_lxe3@=^5-@Rmo;32qK#7W2imk_256-SoSXf_qHdGE*&M?f5To%%@D +z(6#EzP*8y%j=(~^T=KR1#Iln`H)qs9e63Z0Je-AW`%6*@Xegf}$#)99G!FI>GP9|C +zUgI&Q5W1`Sx2q;6D2A*CUgCB`>s>nvpIUXVP-kpKMaGU~{w?22G!Pt(Yo!suL@l}}$jBlyugx;n%_GDuhm%5Fj5J&)@F5-o*v_WJ`cdJlCq2J;;UY$;c>dO8L +zxlpkII#S%m7cKm~oa|ymI20Dz=82t81yWmb3?)?dw*{4XoZ-7uTKHRC8Dq{NJ#YW! +z%a6YXoIT8qj~oFgNGAU2M4Y +z8tXAYC59BbV`mT-&BGAn4Ok|f*{Z}7sv8`4rm1kobMV-IXI{ppS?V!Yh-=9VcXQpC&A-b%} +zDwTaA6kC4lKbCty7IiOs=5mIBJiwVMo>bk_K^poFh)%#-c}$NGoODvVMAbS*cv6ZR +zjuwF8KbAXOn%GOlFZDDOOc10Ix-kLREMK9{e@6#8zroo7LhacwGf8PQJaK_d`pddZ +zT#ueReyPSNAybInZ#j`5&@9gshA3WXjJwL%h~l5z-cO=|8cm+H`+KyayQDxz^?BzI_Xep)w!I5Gye6>*^hGL +z_1c!F>2wztz}(0QNESv@NuP0rCDA&a10X%Zh3ue`1mq~+sLJN!j5mp&F-grq#ii00VpUs7O?=TBHLfYzgX=87E5O7F>tTF +z=Z;xtmoAfTtEFoIQkrYi$dR0SC~dhI=)-(sjfT%7h&&Q=XItmXSJh*85HZ(0UJ +zv|TwDqi58A7)mEQR(FY4MCcyZ1+v3g-0gBeg8{r_$OU{+gBrBAbt83X2JMB^*X4gqq&dQ*SGG|-gtEyr+SzpFo%Vyq0Wo&U +zgarC`OXxgECPO?U(HFoo;l(n$hzgQX__y-dG0#Am_8RemMjq#kWH54jO(@W{yZ^5; +z!nOp;n(lDP869^imrayg4wWiI%TQZLAd&8I*$^jL4$GqtyPG|44-2RPBM6-W#Plw~ +z)w-vyjFX=Pbo(~KO-;dA>+}l)-+Ues|AGy5D7M3@Gbg6&7}3Usf_E5eeK6i;mqRKN +z8P<)p1$g(U0RV72&96%Gn% +zmvRQmr;qx54d)BF9r}_yf10pkFa_h)`Pip@j)<*Jg<~Q{ByEh?#U#IDTq7|UV<+i$ +zhri622Z`g&LS2S|8t8xCSLFXOg4D-M5MvH>!&eP|)h}rh@`(T07UtN}05a@OX%KOk +z$wqeD8l{8mvxsrKu%omLuyY-t>CV!1eM|cX#-XF(6^@0B^TC0)0hTGgY5yTM;&@OK +zu4NtIpIGOKx@!shOu~?n_^s0-tns+-4KCHsVN{<+D;*tVP}vmw>2%X1W44|*8g!mt +zbv|>@DSkJ&(!)t?m!b|R8#U8>`?Q|8wex~P)1+ETjq@MOy;XVA!G=PUL}}xyC~Cty +z88TfmKcFN)wxHxk^)9ZGq-;|ktnMix=Eh+FsTxe%ZHU1=Wx9SiU%^#g%&28$%!=OX +z!(gVxPHq|xb^O5mBv!0r%!Ed{r((>=%M#Rt7J(NdRXBN0G%A{F-`|p!>bR`Vg)vm2 +z7C9|eQ1puU)n0#1T7KQ=nxT#0U&Iaw_Su>BR>EINQjiQ??5zH+LAzNIjf(Ma)H2_{eQ7Cw_)V1V_?1(Pe +za3v~;S`{cyJ|h8<(KMDCA~Ga=y0y@T`>@YNPLzwneQvTHmx1=04k=rp#oDU(JaK#A +z<~fo!m;{3LY6ZkP)0>vU8A{Nv%&kTkDl0yV=o;<4S0(LN*r48A-rv_|;vNF1(-yz1 +zrL!c>+>?PyW6%n-U%KjKq@<|5Ef%^3%C{CHYpn@17Q}G1k4O=A?*2U2b^i!{CorbV +zkXeeJ4z=f4ykiv9a)u=FuJuO87m6ZrQK5NbvTW>9H?Y7JUp+5!Yj5~nv_9%%varlz +z70`#?5@z^Va$(eZ&1~9ZX`^{O`9)n>HG-PmqSH0u&1%hNpLe|@{ButMnQ><-t)Jgd +zW11JF8m6c;?JE})`G&(V6vll-VHO$ZE2O+)-;3Y)XO?f@nCbgaWNG8)^6Qo_iz6EA +zy!9)!WBY8(KuqR|%h>Yrp$})MUQ5=Bi%T9lc#s+2{uXUp7{$wSR+3&!k>!9vz3TX3 +zo_phP>Il6fLwFQs&lZ=%9Rrbho7&{7W}GD3>b0_)sp{B;5mXHMUmid)>A|63Htb;O +zLRm1Qd(BYiU^j3T;6MqE09O9=U?&x8&AqY^!b6I9dvj?=iQJ1i#i8>(R}bQe`}LaR +zxNGl$o!qrkrIsOsd9*<=Fjn}q3s?wWe&5a&V|$-^lnmLi#3iStt%Jz%2oq2+XGeNB +zeV?>&j9R;3hC$Dr9DBUfl4eL3vk`~#!6K6Zy#QPd!E;VDFSb8xy+Gs|Rba^p7gFT; +zRQz~uPP0`5HbJs?h+?P|o$)2LiS9gkl`S|_gyBHuRdA&w&z3iuz!!NmJIUujQ1O{5 +zgnab5`&O3pL5$#=$`-zTd57ol6Sp_6-DFQBQNvV9iDDW%ul@nv%1f{B=NR58jAXKdW +z?N_R!BhCn*xqRO(qi7c?SM0$npEfkH%{*q7HR7^}?KR%Dz{JEU1bV*sYgBQ8PD1yr+O()tJEa}(g9uc@+yqk@M+rlBXo<;!?NQqn!!W4E4 +zuDfSsP6cI(`ZdbbGSd+SzV2f|Ew!T8;RV} +z1$=nc&OaM)&SJJ)RrQZZKZT3zq-}C;3Un$f)jC#=$&oEeb!36oI@wLU8nr-Y|JmHe +zV)2OOHB1WEHrS!%unHx=HaFh?Y;Nt3EUQ=n2SR6`A3KiSO~pGEo&6I%6Rz +zymZ!a9IUyG18{oL2&fIz9_oqPGHZBWXRvJ1XpBLBFx?9tlhEb=;oMcy){@#|Zr`aH +zEtqH=yZ_=ABGopu?)D`0)zktoO&zqa;SySnQkvD|aG2o>I&q`%r9| +zm4V*C%Ai?+o28I^8N&#!-NuH2JqaF@Kc&)b^wU)v^<=a^3*mwKz#e!u=?bLDdl3!V +z)|3er34WV~Mfotg!y?U~y;Sg97JN&d#z5}%BO?(9eK9t#5q5uHvFtKmk?5Dp=?6!U +zGB~ny!6FT2qL^ve*3c{{oiu(f9XTBU8=aM~`2{yqj{(`dqNtJ-A4EXk8n^Ae+;EhA +zaxIY6cCso}oVr~I=~OiK$)p)boFrjtM;1OzY`{Tz! +z_2gUWQ*o4x1;RwETaC`6Q;XB)L`wQ&Gz)@>Z9PnJL<+{%UA!a{kz8da(kw|ZJPI=7HMs|c +zv3np&yp9s3EM8o6@+Y(?5maBp?TIlex1HSTDtIP&Ro?)Li|uXGm}+JTsxy4}ipwI+ +zS=#H`NYL+UL56+WQYYRzUZ*L(0Es-@PYa&A#qB&BePIwC02}A20G>7y+6^ZK+= +zAQW9l;Q*IpfIZ(wK)du_J~YKhqt_L88&{{r*f +zl4X{dk1SDxW71DagJ{Mn=O7i!HR6o}n(KV*od>y$*`<4|q#P=%qZxw|z@AMdPAE`c +zPTWMG^ucx*$MvrPK|_n`U9oCikmfm@luV^JKz#X4>Q>tD7gaN`C_1!p-wOL$2>mKN +z$+qIunAeOP!PL`izmf!0|AinJsN5mhGDvO%%yLt_BqMxX3#FW{(gJXS5R~66*AoOR +zu9GD<=2|lW%OW`fq4l~ZUS?*UZZ?|u{{gB%Rlm#sHd8*9b;#=NGSS%OWgU}pLC+(g +ztehEgOQ;ltU1BXEnmo!Q^Mf(H3W;3mV%;6|gLwm9hSX`=*Y)5b1KR?A{z&rxGq11I +zF-yo6@Q%ckcESogHp{<|7T=+m@H7yrCWZ@SA|&*8* +zXWue)56U>A8ECp4k=z{*h2Na$9n@%FgfbS)x}GNT9~T@cpTHIb +zzFu<%WoL@)!L+r`TtV>0TkUjCVMAkKxV-)&v>@9DUdQG=` +z%dXBL?$ZnFf$tl$Mb((bJUY8rY&(-Mh*mJ}10rY?ZB64{TJWA~7Ft-u$LT1%*0PmaX-jQ;#UFw%bUpnO0I-jXr7Q+}co +zNdstGC){}D8}N&2ffG6Bwz!l}@dIrTLs^(JUH6B!{(AUfbh=~6s)zFqZx9(_H?&B8 +zt_NXa;;Gju{TZIkyg#2Ak-9p}Cp8wtD@qP_>xAgY=_DZ$+YurIqETWmZlqZ`Em0E8 +zaRyg)0T(bdCwEu5k +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 +z+c$J5B@<3h8(7@4N?5Qtg +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 +z1*PYTV1*N9J-CT?H}*P9;`V_ +zfzVZF0j`+o6Rph`vI(d+9?M`dYT|@27o+e>m;(?bgaa +zZh@q&`CDuE?JM6eb^7-GZ-?x^y>9;)A+|WbyoV0n?c4W|pL%)yZHO-4hP1C=Ur*o8 +zF@L|V{`K|p?fdoj$M|iWF5f;6-;Te2`@H*pf8Rd8eEWPnzCH5l>$9pS7WDpcddhPA +z$M>tt7mL3tPO^SN{Q)ljaD@uV%;@j?q(B4BdM+XoXFKRtDJ~`SyJZajK!ls;+N=O+ +zCUBCm7d)cx$PWEHk!>$KAT1M!s+eamzxRB@y>g_&sl>~J`MXwa0sXHz>Pm~?bbnUr +zotJPqp&e-4lpU@N&)|tZ+@3Y;y72N~IawK5F;y8!D*P}QX>U-%jjmp>Rwi|CmBm3= +z_|%Ji>1@2S`_nk}8X|N2uGWi~*pP(AZXjg|)3fPa)O%kgeueFqV@};wZ<0wXbpvKg +zTHT?$0SX3n6Myf~S&^GZ0hdk_4cw`|B&G$Q8o_{ra+t_#02q<%;){k~Df#aW73dA7 +zS>BoWwGn^M&x-$HLtccx&kL>RP7@jO*;Sq{{`q(V>ou$cx}4(_EScb}<#XjDG98I{ +z^s={YdcpYKnkf;%KO9U4?ECq|_w_}Uw<0&HaTSDRRTk+~K>g1a|8iCH)W*uLOdD1N +z0j}!8lQ`;L0u71nZ9&OYbkbu~_>9|xwIswFC=FWl!hQh(A98% +zQN?VaceP18X^9?08i)w(_L0h{T}=L(22aAE`02e2WG=<<4bG>T$IM^rbfC#b0%D-W +zy2`mqaCr=dk0Axnu6mV{dZ6unUix9PCBvc#;3>xtkb3p2T;c;2_e`t<)G-j6^?3_{ +z7N~ls%UpV;v-EPYB0^8Bo$-sTMaooxtrB^#kO3%(kdN(2jpW~1eIeZ)(GtR869jy2aH;VI@sX?RHB72brR&1FUZc!)n-Xu-4%C&W0uM#IZ{RBHUQB6n;HwfZoa8ipedYe(c +zwq9kFIkKb?;3Zcm;$DpdkF6zKq5w=RP3&BF>Jn-)CxvQz{pri-iXQ|3M`dIphf$@B +zvm-oNxZvZ}n6?CG=H;^`>xy^Aga?dsi +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 +zq<^1IyzCzCyh?!lp^*eoavzw +zHgR)>0q5{~KfKR`FXdN_+AKeY@9oV1<(-#f&yg%@U_*JiPkjC56_6vLzKZGB`MeRC +zTUm(VemNC{0sGe$0=f3Ke;c;1YuF_e9`0f(+JHCk#SRT5cwt|=!$XYo(C>T~@XJs9 +zAzlN%w1mCW?<i!U@r@Ucgr859C3r}6%Pe;Y>mH$UV^vl)Hi6h&?}SB +z2L~_lN-Wnc-oBmebQ9n@b{+QL&7H3N))5_{F@8>kch90rLIy5e{UNZ|Il{ZVW#7@3jIJYOR8f@NVq+X_6k60}|$FSvSL2j*qkHe2MY4QXVqJ!I04gx!I5xbdgGW<)}bo +zqHD^M`XDQ@gL6N|4I4H!cg3;tzJu_Tu;suhCuGyT8(Fq#P+|8@yRs|?nk}d75+uI< +zy*E>J5EPs}8_*7Vj~l>p=OgH%cq%iy(U`28#ouufRJKo%@gb(_Z()x1+pYP6My|w@ +zjX!E&$jr_Y#h9H2@g6XZXV%CcUvk{l<+J#w$l^^lppEgYj-M=rcj&H2pgDDp=7yf) +zT6q?7-R!6tCCLDC#^{P_88pDI$XVcA@kAVDy$so~is}->E83|-1qf(mE_vmyw(Y4I +z`+elR^P+|9d*WOsBgE#+t8;1-V8E7!(1wH;v3Rz4$u2ZADa*|S$gcdEjkWjKfg91O +z;v|0Z$Z}b~?nL|Phy__^LGxoN%MJD+nd7vURGZgTAuC}dSfAK*@GIFPiL!gc?09T- +z@(Gf9&Z5#u?q$)28Qq8cS!8dSRKZO))cLE`nqo+YdK +zcWP~v!=nLSW+>`?j6_uCBTo`25M6_@;Y+rQb~EM;G13OWqJ+B6xY%IPnx15-Tps+f +z{B0k~&QYrVCFBqvF_PvIa40yp-R_N~jBecuSg@tPp&S^lhF#M5J}{>p4}v;1kTdcp +zG8gT>l~#lEYikUU#jil@qoK;1|G4a*PrXF&EQvSU=qvCH0E372QL3pZj|?c4(LM(m +zChypTgO7e)Uy*lTosdgWW@bRW4_O+=$cCrUmJ9GqU?xqaUkv^^ysLN)>unc@B3Mp_>6>>R>E_kO}*WB1GCcmtfW8NY-I0q9@W}u+@+`CQLK>?(|IiQn` +zDim+@n!fDH==kKTS|0GT(M!`t505_Yi!3V_QkKQhUu$F?d3^Cm(ZdbDK_kD0*bZz& +z?0`1sG?JYCkNrBc(fz^2C3zr&qdbHt^Be2sM!BV{snKUfO@ +zYuAEm)$;fijyCPeN5|w2M~*(Ul3d|9*|^D*nW;Q?u^k6H3PR4NfZ}kqejjMraVuBQ +z!xu-i0J_!>7h7?Upx+9k?oQ%LXuDQExr>aT@ZQg-k}^=E4cmq?u?wXOa0dVjkn0~M +zJi9)u&Mn;7JBB8DT4*T>q9Y@Om=vB&c* +zgkF2TVRWf6S;_%5(0aIJ2=eEFzeC>o_V!CMQ)s!U11wfiClZM+5yNY=9cVJo9jReTVJ>|3?AOcc6kgK;0xE3ZDmXOLL~=vQ4FLmpF9Y+bCy<9jj4EAE79-Qn31p +zgk4PjT_QAjcq87iMqPk)f3zIj1+gY>16hOh7G=j4#!%uZ3GGapgF8^^qT*o4S#@qJ +zk;`&st_9GXpxnsw+r?o(?D|O};36a%?s#ewf#!x{GVVBD+&d;} +z1LDlQtFX~%r+P3_@y8p)1ts9tpY!1#MxV@!@Ef4N_`bcC5gjm_c}^1$@R0A|mO9#$ +zVDr>XOQ0*~CAqiu^Tmw1$$+#n +z`t$gdmj(1yMD%){{VwC+pk(0-{Xhz$gT?ota_q`=Jcefpa7P(&2`8da%W@MN5MDkc +zsB2k{`MHKHHr3;t6m+w`6TKRQMF5Kp`E|{R8s0WT6V^6V`SiFJW-jE$5-fD=Afd4GRSl +z^?;5de_1-VdRX@x>M;6g*!?Q;#0(w5?)9T2om*H^F0u3>^K()Z6bpN;lmfn8m=9p8 +z;i_(FE$~q)8nvm&^La~pK +zx#`y6MDi#PlyldXr*bN`A&K%KS8HleV`_fH`JwN$PazGOY+z^fC@znWSu+uSNjq#d +z5p4-h^CC12^k;qa-+yGvoPXR5d>B-MClyORty!l?ZUHb9ab|lSQ?TD{z#g`O +zar*g69Uoi1rX5ajKo=B37H9)m4$+C?wS@J_UKi^mdDqbV%VmOm@t=3i;!yExTueWL +zT~why*T>*5c06D1M1HqGYNp%Efj|3rxd$UlF#Cu=%^%j=Xr1+-Lol~U{0UNXJ4KmT#J(2vq3zJ8~qIsbSmbjuh%d|Sw57_qgKW28Jn +z41P2E7CD{7@S6ui$N4Y(Iv%M7WVfuJKHX|qQ5V6@7i<5;N+7V +zyZ{?c5yVvGZ5}hoSJH_Q!Mv922JHnymtSZ3PJJ-A6-AOTUet~BZ%cHNRV9P*09MoI +z^Lp1{vM3RCZ@>B|0rVjW#536VC>Qo0CR_qn04WS>E5V9ED)ksU$t%$I^{_cPnE0DD +zZLUvMvxz^YkKEJ%Db;9Txj1^=Nk8h4>pFvVmX1^Yp1EsmvDX1Q+}6v4Vu8nykb(X@ +zwUKmGYu-~_B{$kNw}8cl$%8Rn8Uzp_B?K#R{L +z0MO~B@uAF5x +z4L4eom(uIh#G8Rxk-FPcF5e;Pg^ryWp~d1Qoe8tZnjGrR{JEz;!7iZg)}|;_P-248 +zLhh*?AB}9JIt!Ua)1zVXpy_-=j%EOb&7LG^$>>TnlW{7`8K@LKtLMN&(w1Y|z<{tq +zV~gDe2@-FYXq5*{AP3yU8|>l%Z7jn7G{(>$(Q$Xg2HRgiL6;#ja_APx^p%ab_$lm6 +zgf(6*W_^$mUP%X-Qp8}C;_aMUMU5u!$JCX>qc9r$^Lq*s1cjp#veD$Li?Wu?(}G*+_dS77}5y@p`8}Rdq)e_i|%!9J=r!Vekv_?79qi +zp!U$vh}=pYt6`M)H^=4xEvUnrKzwFa!#RX+2Q~L2xe!rSEr4RCjk1FzKRqb;(azNRvnLIfacX +zhCMhq&`^WU!BfB;0+Oo+DWon$Jq)t)r(fvv7UP)n%mvuHo<%?n5!(}@V|q(0P|IfD +zT~~`-N|NZ=go`9tP_zc_C!aDoJx<)OIaMH;ulcL_X$dxi^c^q&n@y=#Wr+s!gKJ< +zdCjh@oU!vgof$6C?ah&q*^o0^2Omw)i~~|f7N-Ku;A9t=h%EjBT>-c+>V|Fk*2A39 +z6uR4qis(>A-S_0m7ID2{>e_9tEZCCrQW3kkRe1=Q{2k!M%sg?Der1|-yPO;HQ4AHB +zJ5;t2W9d{&oceq(l;~ZOAFgL?%Y#8mkv8T>MddTVid~HjOz9;Z?KVPO4agXMFw?$I +zb#e_=OpAz(jE3{`rv$07Pg`09eAI5pN*+C|Mzod=wWei*oAZ@#4Jc`8k=+6`JMA=U +z7sM2}J}^qGPQ74^-d5eS*Jua{QjND?b3Ae+`|I~#$^xo^-S59Ba%_>ysJLA_+Y?{| +z@xTbpr&zn>%wZV%WP@jSn$va0d?6-x;LQ;yW?*g@HEawLFii_*`lD9k^qt$--^d@@ +z&lvj3e;}0|f!lX~;XNNBRQPVLdbZwg;y%SEu{NWRXC;ZtAU-;+{-NP(erz|BMms1= +z6V^vOcOoHFDK((4HR%PVeGkuq$w86mrXyEgs_h1`vLG24OemW5!A5rP0nt9cgf&5S +zNPN=Fe!u);>TEVsqV7h%;M+BCon6lJw%H41BL*w?^`rf+Zzfw1)Y#V=sFLD~{VIWU +zlJF8N-Ep<`l<#;<`urMFEHfi{y^7wig0;MFf85uh0+2}V9H!Q4vSCAV3%222LLZZ4 +zURJ+ME!cefqC_Uvm67+nDPB>ZDrTG7)`i5FP87mZXbN3lJ;|{;wwMfdSYJ~St1FVC +zia~ts;cSIKKX$HYKq3IukSPn!3y?hzhYV6Uos|=_Ak9sd0A*zhN6@T6-`iL!+W3F| +zFWDIWkYJ9N@m~P9|9?)ja0VAP3HFitzx3MjFGRkHOCd`N5j+=omA9$hfc2U8rw?15 +z!{mBd^8rW->G+r*WQP2uuZ>rq;{(rd785aJIDh^84Jh~*gAi5S9`dX|aG9uA>rkVS(PA7ibS*X#W(|OLP1dNbcLWJ~LX{)`EFIxAPsy_dYKB2GN1R?cDYrKqUu39nR1j%t8lNMo@2R +z{PG?i;a5%swg~{s;j@^#Cq+Hb+3A>b&5Psy&Jc)wVqR53OpRpGNhtUWc>I(`R#l^Q +zoi%H@IS5}KN;iDufJwghV(u95ymW?%8W54UHDC9(GFmsZtSD +zy-!3Vt8Io`MJzR0s_a5!uVC|D>N0D^oly0pK2l3EbXhGN3g#oh=Nite8|p9;oK#qo +z44HWk=giS7yNYIbwM}|b#dG+~q@)i92qBm_j1~AZ@SycV(ROk-ZV3&VGe@}kc*Swh +z4}zwe@`J)(7xyXF2Nikk)1cb7`1t`*li2$8%z6QDe^LTS!yPL6R<|SvyC53=tS+q- +z<+6s`_34j7tsq)Qa6S*)Mj;*)#zd +zg_46+5!{nzW$NRRXv(ui=4LeMAd0zI5j{Npm%cKdC}O-3&XA`l!3_X(RM +zr+nyYt=NkCL{5TfF0TdJl6#VfMyaa}iEv>8P(6cY(df17tr6oN+nj<yd0Dpa#=%k7jSbtLbWOrLQ@!y~kBGfc47HOa}?K2H?+Hqui6zCYpT{f9jW{+LNyKy(ZQIjaq-Ou1s0f@Pxqbyi&Ki>+mY?K`*F=gQGH{r}i +z{u}M|qC<+BJlK<{RfWj{7lSaixP@!wV%G30#7A8S*A^%r*Zxq+<~jH^=!8#aHPHoP +zS_9JE**qczC@2AFXH6CxET7ax(oaAgw#gPKO*2qahBFyD9?kbGOmv|1%r573f&8{( +zSuc(5S`5P&HwsO-v+p7#TTRftEXB&r9?&=t3k*|T64ZdE4JsU$Mw?EcvMGyT0OUX$ +zzXCmG{^~v5=J_lTKK%`h2Virwles{}icq7*X|<3FpYPBaQEUF+e-b$%w*fBJJ@2^> +z@mU%LQvzLU2p-s3{7eFUJtjrUFS$@Y*vzT6+@F(6SCMwv+gCgQzlG{0gGD_VB-NWj +z?y{;X?lNS%$8w|Op_YGy=I=|r4)|)&-DOlgM}fXknumokG-nIBFoEqq#*CN9n4LtF +zbG;xF8nhCk|ZQv&IZ+qwvL +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 +ztE2Mr=LTEsGf4Vd`z}4loJi|ebv~x5 +z#p*#-rF9|Mqe-CH#Qw(|kH^YnqKR9D#23AXYVxD&YquQ>cD~AJTII{*D@v=T4Ro}9 +zdYAob*lgfFJ-mmseEq}Z2{HHh)Bp4NQ!UKR+a +zS3VHnt?EM*duq=~FGf)`5-`{l=I3*8w8vG;uhf}Cq72|}T{uJ-2|L|8Wy3ud`pqq3 +z)j>&9%f6TbqY3iQ0MZ)y@hHKDVN)4X!Wg`E;yvI#fYkt(QVAdpklo>3)mm2hLsAfn +zl_$Bh*xd6Fd#aR7I!7JfIB~poY_(*&Ux_zok2y6gF&H$~Fd+a9#O69V!Vu74?~jy2 +zV4Ou36H6ralC-usp>kst0m2+z$=(m(EmFQ!ZcuiZJKp&YzKB-4kPlW27piw!CF}*r +zp&i7bm$m0?uO=2K5nD&F_F6|qQC$@>@!46H7Ty4<jK3NSr&`1;$ +z7WWIPCi!susDS#<7;mWag(vyY%@AG~)#-f1Tc(6T`&7ao(4)FA#rt>oI({vF6-{E< +zD{It{H$PzF9=5kXfBq~U=mOG_CIySC>Il-WfGC4MAM*T<9P|tyz^P=_fNV7{3NY+r +zG{Tl#^MuzEAGgFy>Uu-dAUOQ)^RB&Oq*}I6$1G`#7P%meW#Bq=^WCYjhj1I*H!v(2 +zc$~18h85LGwGgPnb8{I{@wa>TPH8U>XDiy6*bZ`_(}$n7)Uljm19xCiZ*6LEk>}i8 +z{kSEep88Of#tUH$Q&Cb5wEr-XDinm>eHQRD?fU)t{qdLGW|y`r|JA8}nm8Jd+#_H* +z#EJ`3?N^)rzg-3QAlODn2d#~i) +z6oB$`^RUUH5lLajP(48#Xi2NC{D_cvo)0vDMc-xDOfw6IO3r?S?aPW#P +zi65v(X{WLR0D8Dv2{hIaQg-qlQX*;b36&yq)RMrmHzONu!^9qIH?qqnJHo@?xEQ4H +zW^d7=S|wRRrOJ`rjAgqZ|Fw9iAZEOc4_msMgu74QWHi|{LVDV8=!s(>U<-3GcF?Hj +zj?m2}^X1{J7=n>US2|pD^EiJ8-ebL~^juPMt#Rz*P@lVpnmWd#C^aL`C-~F{*RJ_} +zG40Vn?(_NYfeykP<68UE!cy +zsGM25)*L8RTcc4;0*|@`XGgYN70O4SK>CsNKvtl&&Om*1T^N%NK-G>Em3@2wiDhV$+Wru`2L@Bj=V5z#NkgM`>LzTtFa%Op;L^8qs(sW`BldnZ%QNlcvFfYy +zp6&;qxo7tU9Cx<%Vx@LgHDb#cbpNMCSD;lf(;$gYi`6n{za+SSv>Kn-6G6);)3at8O0N;LA`hRbVWDBz-hZeu%R8SkhJb=RfHT*}~Bp2dY#TBts#My}Ba;!V> +zx^sRU3iAGjp2D(%K%#LN5bqd5GT@2vw5FHM%;9PuZ9;W#J;m}dvsNtYI-a+*mX3gC +zTlNU8w_5nr!u(xzH$9`oRZrj@UbQEUI!=3T7sfW-$hT5-l1f^cGPq)P$Wan#MWUq2 +zkar8|%5S3sU6@dFE_{z?q&d_rke9GZ`QkKw#I4dO0eb&mu44>Y0Ls{RLb +z+4rY-*9{j;pop4#*@(4dQE>)lU)G25UrRn}U?FpP64~_CF4=(=mmna1dQO0_070R? +zMs2eMyj%Ei<_lQ{IE-cRlo2XciULrBv8SWCrH-70{LNpovv$J*m+r@bXR=|CGnio? +zn){iRT1=6yTEd7yeD9ktfov$%GK`nf +z;M>oiZ;L)fbBbabmjf08U>(0$$wW77!BTVxV!dK)N(rEJcy +z*#_MTJ$qvaP>q{4Q??bC5A^?9XDLU|vmQaSa` +zHMY=YMVKtfknANfxSG=+cL=AbxopH}jr*x|!dG}iprdI%A~?zMEzSKi+^>3@q!m4f +zPgERCA3U0h&({;CE4tsML +zC~R#_x>(cOpq9Fa$dZa003_<(l73mjuSzFS^sqqTYx@Da@a58gq&rFldCxToguVVT +zS_w%Zcmv3wKvx`dPvA4vq4}(2Q!L|aZ;G3jZ1X^eQIgGc?nt^E&sQf@~Lh^(QlWH#wjnGn3N0pJOkRwg(0_sN=4Wu&Jwc8vpx%I +z$6;3Bq2qb}Q4pf%!m6>}4p-=uOoLXtw4BEKRkb)V*)YJK?mv(B;WMjawP$_wrWjyx +zFt%4EnM+%3hl75wZ@|ltCryX89X(~>Sim1Y^FF}N8yXGFGO`7{BPo}ia01WW>Mvxx +zcPJ(z4Wz1>;R2NiNj+|P&hZ)Rd&pF(8=GR7J+l5oF`$i_*=UL4!L7_e38&g3^^?Q| +z;1k@k{Z^W`4DVBFFj#f+K~d`tkegaBfmMbbHJoH&G2mko|f$wx-hfSVrh+8YV5$Eou`{$Ce>cz +zDX**|$T^^+%^k;htQ$T*bwUbt(=a;4CI~IZa|5~E%;V?ltvNN^;Dj#iSkTSMI2E*A5x_e?D(2Q)s%&F7i8#WXDs +znX(Ej?`Wfh##P`*chAJmKM3~MFCJ_TsIFU`rHr>P;2|0Q%qt>7S1JL&s16X2Yi~=m +z_$eWtEn=uEi<8^o)Tv(2EQ|zq3PodZIS}Zf*y}bFb8M~t#+lYUcJlRe^%7c^+#K^{=^A}Lwn1)Z& +zv~eqE#EIfz^XMNi2eXSMEK4!nqwd70i7Hm5wsL}>IWDQ2+-)kcPT>@^ln|V{4q<^} +zXCNB7GJ9%F&BkLpu`cGcUPq#c&Wx)n|1!S3PU3rlfCfPlW>+)@viTv|s#i%%D+Z`w +z0L={4ls=VX96_=nZ$g>IE%yvhcgUu)T1!7F5&><1DI->Nv00P2NIWI3uE@Jqg$hTz +znlIaEa}e7Sic!`lJ*dTnj}o~BX^FV~5=-UGcRuAn!Vlh-(g2aoie3V85~$s5OP*+l +z{X0~3s$ePbu)J!5Ta;s4wks%m35Y9X>S?mN+IAaVRg7dQ38|WgOyZ1?hngFI`zhXP +zy*5sDk$%B&y1~ZCA?o8}rq&?)7V;f4U1;J0g7D$@bUP&*SO_gB0`QN0WdwRv)6@jR +z-Ildfa%Y_p3?$wOAo6lWKNkBz-1>1b!YR~4r|8(3_kl0kQ%?{(Nw!fP-l|QGz>>2P +zT(=UXcc;zkORN~)j~8hyl8v3d6;wW>k~INWNIoZF!k}nBkpnBU4uFz-pKmTerJSzA +z2S$^XGwk(=w#gDp@w>HrPR1dk6gu?TPb-2~f{7LwTcog-x7KlgdQdJ#Yi|3&&nr7p +zvP97kn&?r4_0pyH2n^WH@_}TDLMm*fiMGCVs;Z*B!%@?%5-U-efQsK8a@dhcOxcV_ +zxu_Z>hSsADdU^>U2ql*zF%q!%+`iVoWBl7igg4zjOwYt`$o2ph=*F=Vzt1Zf;>Iz= +zt|{H1A_}wv>^CYa*c}fEpo};8)M*BG?Oa;{kr$&ml$@NVxxpFr^dNZ!!MNfQfbjuy +zx~%7Cxmg9LusG%WEkt6*C)58r=RjUw+b;2O3&qn2X +zZUItL)cLWdYLd@_UeEr}AUS5&8&CuLa65rIJC3ccPq6x0Xo@mfXiu~$u6|Lt|CU7M +zd^49a9{nLUO{E6re>GSeES66iIt-M1((Yx`^4VUW@d7m{Fqv?sfIHaE+%B1B05XQA +z(jeV8bc^TTI(bJYA;=7!JvsgvsV^Q-wrX^aXW4*%A91_tS(q2Jq7kIdXDE-ihAmM= +z`2r^Y(n2ltYCZ??<`cUZj)Vc-?xa9_b(u^pc%sJ7y_R?A@6IQT8;2!EP6^ZBh6D4|XRF7k_U +znu1R;lP=gJduNvOX#40x=I$?n06_ +zcuc_GKumPlURM}wJ$Ij=B%sJg9>a2%lMR#bk@rvAih2hjT7C-}Jn_F^o=ak;K +zK5VRstLGt;chqtWq8z3#a0qm*)}E3?#;qF07Cb7l*OJF4^JZo}Z*ZXG(GQ5*7|-HB +zo94CbO@4zof6k16K6ERvPb!WEjunRt>FHNRhrmXFIf50z@x>s43X8JAn7tY*2*bG@ +zL>mcXz8 +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 +zeL>e?&QrQ0*a#Uj>DN!=CzgxD +zkdqhfj=jedvc-^~)+OXYh_hBmU3C}WidjC<-h3raK!wi-BLdF1xrpD-1r1D*>0q_B +zuU>z_$u?^I4a@_@Is>z!zg(FcR{t4lRmOe&BqWmGe#h+X`^&=d`nzR({dxFyk<-WP +z&+p6Y&*H+rf9+@Zm#E9cP!tpYk2*6{r39y`(ymJPPcD=58pn2`}X(#`~7|U +z`|aD`r}Nt*Z@xa7c4kBGU$>_m$AA5ObNgcRS9M3W4+uLTfc{N&W5xc|Q>07P-a^Ak7R;GWLRJa*yoL&kNc1;sI%yz(K`2gT=kqFFYzo +zDV!p^{4oEmbz8vfYk|7bA~=(uwR)E|+%9Mb1~{N;-A85dA#8l=#lB27J~;hpba|1;9KWmWCMGsy4Y4~&S;G7o +z2iNO9HpyRM`{gs|{#|d9MJo*h7AsmkAgKWg1`QMcK9Un2$7h9*P74k6R9}+Qf+~$* +zz)?9&9Q# +z|LX?`tzjK7<(%eV#RMlLUm9PL`OKW6x1;Ow56tgvm=YQM)4_DWzF$xL*j@y88`7Q{ +zS3y`eC5X-q)c@@1PZuoDW2~IYv}HvS;DRmu5=Y%jq9M7x9Vpp~&S#7cpK+UzcU|HX +z%UAVn$HvZaTl#i;K@JANRtQoAJq?c+!OI9Kt6lO*EA$}KKt^b{k5WeKI`Qv$@gxmO +zA3n=KQc^76=v0|y&iu8_Cx&b!AqHBkZ=9ybx2S(n{+c55SWY{zT +zJmnk%O0RyEYkH#NUg&UuItCiDzHgzu0>SQlnd_iTmEJB^MCgUJGk%e+%9Sb*QKAkO +z3IHV$@~OM1k^D8AAEbvPT0%IDJVxT`V$-zoBM*!7BA$g!WaCA*TiSdTHqz9zZnq?H +zkS&@gz=m!#td{NId;=_nVMc2W(L480EC}<(p+V@Ll^(I3wftz`G>*CJO+Ga1T-)^Z +zCV8UMPjF%r-Gt0=gCt%SCy)4Iwi)efn^i`eqbM2yUh)pH+jpb4<7f$wC;$^{OucJL +z-9k&|q|ofIZ+%%^iGu*(XpBtcG^&(oafByZSC~l*Qw0I_EIn)=fHXx`R{U7*`vpl_ +zQRD3W7l6;;1YIcd9ej)!ZgX6W+_P;0G!vmcBF@YbYbpeM>{-W1vcWYH{&(?>f_D>gn)Yf8Wq~^&fXYRRW0`dAwM=i +zuF6L>k?U*Kmbk?M@RPQ+>em0p?v^J8F1B>=Q1BoBukgMGdL&a1@m>fe#4i|Uypa6b +zj=;8}q8rAm7WS{4iTHWF0SWlMtP50W(zV%coZR +z?e$wQo$3F6%wMDSLxwoAR6BgT$K`r;6~2A)@a_87;$oXQ|9cEpcp|@y&!Mo4@t%4` +zDC&I!^zw+~SC}Q`E&8|Dx&i=$Q5To;yZ#~<%D!g@l5IylL-w~Tk?lk&zP<{9>G$7} +z`asq)_#8%}ETOr`l!ps2Is}LGbj@cS8_GPShUK5mvX@fd3KP9}B&8n<(xe4L4dxz* +zhPkj8ax%(Kg8fjAO8={VikKi9d{x1>BA}9Gb#`}Slq;hBX=tBh8_T~@ydT)N=hZMv{_JP_*S&pM4d>tH^03V2R+6e!#k^ma9Ts%hm4u4jpXs!ctdwv +z@{{;&pS_27TQv*2p7n0mHX6ckeufu5;^p;6bW7q{4yxc`zGbf>_h|PvI%Ej0B`=S@ +z5v_`B}LT2qz)? +zTnb%KJ8Oo9qs+uQ_$T;jdx(j!nc5TMUBq5*zU_XCkJZolyUCA(a&@6?E`lvIAQU10 +za#L+n?s3oJ-eplSXbFDMHR$>YL%gdW&zq~18uwIMj-+iq4 +z=H!8l5XZDFwTE%O1bQ$QKJDLFv!|1Va4bl1F*v9Ho!{C#|MkB`_)Q18G`R;< +z9%<&?0bPs5%LE6M$?8_wlJ<6mfS3e|zkY;I*}4`oTF(Z}3ii4m!`ctyz<-N(C4BBv +z!Auf?sM67(P$&MjJ`#i{hl%fCYc@VqQR7#S^gIW=@v|Q~^JpKa%jZGh$DnCSP2$kJ +z(kv#RbLl%}Rot$t%fM$d@yB}{9lS3{{ql72<_7VIDxzroqV|2Kf;F&mE~VE8>m_=d +zQky}2Fucx`d+GDLo4We?-6v`?tjeLPEjf=y75X606%1i!v*SGHw_yUMeE^)3QuiRUQM)Iq1(OQ&5Hcdtlv`sNvYQZQC|0w(X>1+jc5;Dz;Iv +zZQHhaQt$5Wy-#2L57xIe*I0Ahk2}jP^h)T#x4&JY8!|nqW`gW1q!OPUt<#AFf{o$e +zuF;u-`{aN)u#LkCj!3u51Rwxd4>DPglGcuw_qbB+ym8jpK^G%3)Od@hd$Zqx(%>IA +zcNp^pr&3#xhc1J1`EbKk^*fxXl@FjzNHm_IYI3?owl*-rH_^TsV?LoPEtBap;e`MC +zbNA^JuEFG@Z`uHeg%9BE2I_~t9snmdIQcU&h0RA+0`b9Eq8#8va%zl1WdE%Ro0{QS +z;r#RqxSbc3GzBNssq6trS;{WB;Ee7gcQ>rE_2na6jPva*KbFyROYh8kcXnn`9M^Yp_z&$T5a99pkTP_0Qt+QhTkekv+LbiEi|cdq@@H6f +zkd2)FR>X-A#qA$-P@k#UF+~EU=BbFBOW9rLl@kq7$KXqgpN&uEkQKNB&EB%J!OlQ# +z;Psd*Uz;(XU`%9VlNJdF`Z~8l)${_Xf4dk} +z=oK=g`@YYp_HKRmKY?#(e4lZCYo0$J$M|p`ZC@lgfVwyKr9x9IyD}Hm^I+9Y`egRs +zeAtkU2eW0>xm((#K;FbB_0XYI}!D*G}A)P@XT$HeG_gw*kxda$fGfs76NN=l>D&nua8O`?{yVgiUHtO|#oj)uz=0Bg;=+9j{?d%=8s;)frSWh~Ay_VbK +zi%$5zD3qWP^e;}9@E+z51V3JyBkJr#=ka-Kq6%MAD#oo|1;zW#TTEt{k8|Zo(~H +zW>o0Le0j2aq`7xJTzP!|0`sw(pL)QlLu-vh2JVpOjH7T_=SV)*Ci +z>oF9ZCNGvRq!gOJ2+V-^X;K&E4$z|w)sagU?iYgkRYJo1riM<4N!}GUQ5Q^K%v$VX +ziSHeB`8*{_B!Fi|#=LhA==lLrkXBt8KiYC!18lLS8F}c6FX<6JxNr%UHevY(KhAh@ +z5};z?Yf*H%>92e7>It8FbRPwRQd8_Xp0x<5`LE%_v99x3asG7b?)0oX6`0`l@9l!e +zlrp$CzY=o6x`wIT6aaYH+*I4g?O%A~5gk(8kCHs}gf2Zx(k$_Aba}6!k`Xwadp>V% +z1XkTH#^V|sdXMlrH`Q-e`Rb<9cG7=|lrN3Il3?T8*baGBXDPxc2bO^AE!CYObotzF +z8j#tft&xkKj7w!Ps5ero|r9rInJbzDG{wbRt!+!$R3`oIWXT=rd5FR0E>M +zr-aB!Xv%yZ#awX0XF+3!O*!kqR9SrJ$2ri}4%lD%zV~DMW7j*<3|LGMUk@1W(gVah +zLBeDw7cZghkqfwORZxsqo3(>_*DzA4#@>9qiiXZ)N8Fk)bdU<+9LrVQ(4 +zZ_K|v#4F`XS+sLxrH)c3`YO`z8c-5dlI3XAe^p*^9jjW%w%yyZhm9$~m9Z60bLOF$ +z+97})ojG1WgI*X%bzxo64U~!X7yvMAoVdDS{xEx&1qb;li=DRrO7dq~G{O0^OGabu0WF;ETNaZpqL6w1YNpUWolURA`6EfW;w) +zWbA&Sx*-eNQpDID7_2xj*W}6Z-!u+_ugNpb09Ib+a0mCJP!E55k``P^eBd +zG>R9^RH_ckK-rvDim;~F2W@;dQ~I9*w+}K=q{S~+JdG6iu`4bsdB;zT$O@pbbrQK4 +zjyvH4MoY40#`GuLl +z`q$fvt>m%-zqm&rY~p1pTk{;FXb7lN+?Dx|M|ocYQJ`17Lsnu#s9vRP6}d7HoZ2Sk +z+VNcz>AYG2Wt0^;X2>o8&pxnB;qVTTf@Vn0E>jDx9nN4U8;*~h)&6`%N;Y$!Gn#G{ +z;e9a_Mcy~ugb(`cuUcj%#RcPlJvS3`yuG_RbuF?1OBOtm|5mv1h85TVO~dz+VP@>% +z<=oA4GKq}C#@3lM-JnukL5hBLWkN;9osXcD>`jkBH%XTT>-k1uS5x6@003nJKb+s@ +zrN?3==Y3G$*t34`*ZlE?0pMp|yW;AUrltgGcE~ +zM&)yqKLkfzUM^~N`9Tgy(u};$Zn;#=@`D5_t{k&M#mDOuW&p3v!6 +zw?a9NEXz@PIN){3a9efe@f0KSEY0nRos9dlR+6?qZ&WTR;8+-So+y +zZjUeO2kNcwwKy?5e?%AJbLbH%2kQ~p%@5JTFZ_si&F`=ctx`w3b;zKZxxx01s=wX` +zs;S9plnFH9mT_e3xp|J$k?Bx7EYAxtwh|DZdNcu;+g0XMQ--P~>R;r`IMG~N9HR1) +zyP$HEDl&M|g7Y2N?>Me0Bsh&gv$jp&I;VH-vC)V6pvh&PTBG3MwH_q&7oie8$RSCc +zkjmHBReE@zF;b+zF#M*6!*hj(gwg`zj_5edE_03wYD~W +zBu$~x(474Ss7`ALXGjg*qT_*O58dBq0M)F2d;htLQ{MifNO^%%mIp`4AQ9QQ1F*H2 +zwAN}Wy}v*Tt@6Y^fT=ZNrOF}hH&h*!(TlH2yu_3bY`QmY0n~y!inFdLo`GbY-DUylbkITawCK~>q9D+1>VViq$3{Mg +z*X8pi>PtQIwpmFo7R=f!h!%-WtX86(C}N`|B0!QMxHrZ%UmTi`tj%rqj0F(b`2E~n +z10OMFFL-zAJLc?6qV{@y+&=!+x_p@CDq_BPIk$Cwoe^QW)%9B@I5;9yUU~Quf=;H- +zc*-I=7EwdjG__|G#B@6%ES4I!hQPgJp&-t*V~qSuan6MvnTY|Ci>~=K1#~FtE>VGt20sU6Gj5C+gdu1-b`gpW +zt-3~*czcV`XtZ|W%p46AxFJt-5`{N~lt%dB@mseAjIL#{jqpiPz_!e@Lcd+KdyP@Swu(`1Saw!u +zI8w|ijW9wB5JEI*J%tSM$cb?J +z_ki+-or>N0IJeILW}%v1Vr<24N%9(vC!vY3E)&prXCodBXOsGamR1b%EzBPI;2eT>0b7@ +zA&m18$#bSGqEeBn0s`L~d=O0PQh!L#1Zpqt01|9IZ7C&CTalpqntQ<&0Qpg~3Yz3jT;s +zpP5tR&y?VgkMYT-vC88sXvy}+Oh)9FeK7j&5G9Z!W%rCB7~Nzi!&mxh(sn^l!Onvv +zjZP(e7+cYJk|=a%;*T|?EE1U!eICDs`tljLaSn6~!x~{XaT>EX4 +z`dLMLNnK`|SX$@Ke*H}kOoU?Fj3g-8{O~VL46o-q9^<$8mV?cXoUVYNQu53}luvTL +zov0juG}6^h|CK94=JgRVl|d_)}YV_;?_v +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 +zbc%y(#~8UHubVY!_Okyh}yH-yZ6jB(E +zu~)q@oONk_N1HA- +z!nSH7O}GnW7AvN^f*SDN{Qyjkj^0vWLu=NwT75RgvP0q_3hvFr1Pn^f9*US2dDf{p +z_XHWfelNSXJB7_L9osXXs&J_z33|!!9`}8@K(<+7`+gqid|FUK;CYl0fqH)EhUja5 +zRzD(K4uEHx1LbI?QRWyCNhN6fE1Rl;L-i7-bSB(Nco4!&+ZE;_6Gk`&N$l!7?8RaT +zrLJ}l3}En!^hck4kKJxC+L)+viS0L!<vVltyL4y6y8U}=n45VGN8;@^`+x;JlTMQf;pp}5i9`+xLyEj4E +zGi!=zF3sGHmr9(+Uy267kx6}tVA!4Z2A5=_Fr73QtwXmBsl9zgB$~(_Jgz{HW?oYD +z(DrI^`QamKZe-a#${})W+u4q4eFe@G)XgN9I(A&WlDg{i84se=6V@^XTxTU>rP< +zrj*;9MG-~Qy4l7~-gAxxK?&}|)?A=kw&ek!NUB^&;sh1&5G-V=-c*;DdwiyJ5hyrisf$LYclixug9-)2A{ +z0TGb-&>${)4A3FLy3EggJ`>?ul0SGHlXilkp0#A2XA(Qm5_G--d=Cl~z5f08FzS9{ +zZLP9j@vxSoe5Z^{h~)^7{yfvpx|qJ-a`~!uTM(-g_oNWW_R}>PoVS5ZffaBeB~8UK +z!}W}lDoqPa_GQfoGO;?Ies87_^^+0?@3BKRuJh!_VCau(fk`dm0oq&;C)l^tKn{*V +z({rYfK||lWZgx&bK0V2LmJ17fxf3;t(aL!R{viwbm*k(jHeCFEs9Hdit<=Av@k7|JOA{`5 +zj!)WvnKro5O3UwW6PrNddEVHJko*&bIE6@K@)EcO-=(Q^YQ1)^Nph*gmP^D>`r2co|0Hs_Pb({4YG#0UFxx9BiDS8)YoqrsT4jYQL{;jUJ@4z# +zZ$2T9(aj)k2f3K(Z^Z$l9y-zi51@gu2uQvh`)5lz@XDo?5d({gS>09N2>giXwxJC> +z73$)x#?(f;zJS{Z*PJFG5&9cD^) +zvzYVE^uS4SiIqfE0E&zyqdv@ivmr(egQMV2@W~0bh~S#Ul<6I?<-G?anPf0aKn01d9D+XbSScdAJytyWP;c-Cj?b|S!{>$PqF +ztSm5YuJCbOow8rs3?O*&!y{XS+bf=c_(`?3J6 +zLNaBz_Yp2^N;-S7mW5)yISHjJktST5&IR%9aR9;A%fiDf*tAmyLYZy&$4xQhJA`)z +z9ESk`u*PB`g3h>)T9O(mJ9OMXlfSA4GVz~&f#fh~yO}K4B@k3rLSdzQyAx)Qc$gvg4BPS!zZLNyPj5}H0;Hd}t=975kSmCx +zODT|u1%UV2d)(%j41HVND;thBnU2ySEyj$M2_>oeiz*Kt5A?SfK<1(c@liXBLB{{G +zxTpTx;+A;gS~Q>3__^!<<}@N@_ib^9{9|!veOufa-xjy(I)MAP#jW5NV3hM)_=xv^ +zS==fAwzySWtz3>n`LdP;TG9Sm+^E6!@{&5%_n-IPswWkpcXzq8$E&T8{g(>6H7rhM +zhn1RC+eR~4Xng!0b<6E?-`hqe?L-1B5?#yY+*2uI+i&P6?k +zRC|~WJm{)@<3KhFyxfRjZV_=wL-)lzi1JDRvHF;O$O$B|611kOFO~9k+ak$k%c7cgiF{87IXR_o`(3>g_#Hk^?$)R`ysOyWQeI|Y&{_T^p +z!`TB{5gxzQorap)78$I$LL#>rM}zIE`oaed=kh@pc2&1g#iG`P_~~0ceyMsvQ>*vc +zV)n{bA5G@x2eoCr(3weBCtI;fZz3(|D(?~LBYV@eUJz? +z1*_;fLU2NV(f+;iK~$-?@HSnBRt}yVyBKU7OBV1G`3+x*7mqse*KcW5B)xmQvXR)T +zYMoW|b1&3|hS6U`YV-2Zkoyh4+!FuC;+{TG__nx}lDh>0g}yEB&%YKoIQ#!^aYM>V +z?%Z(ntI&7u7&CvKiOp|*?FL?TX0$}5pFZ`a46R}g8;FnFU_nnjm>9zvu2&Yb;-k|; +z2lY|oLtLvq5JvDe9u=a0FLpp;Sd-m7;NV=?FWyo+A0p5Iw`ifmA&T|?c>1yO^9m~O +z5Uut!7p2TZPsV=+XyyW|R8{@8?ywrJqJANE}$$^>vjcZTUMX +zW!S)IqV{)Y{!YTPB1!Yx;?~1(_&+ReqJJ!ImA@8u*EwToH%BB5S&GCtsilp*(7_-T +zP!MOE@gMwdD{)4(R>2j6OSdELWn#?>AwG3R?UDnFL^Z`N9Y@MW%m +z#w9MMh|`L=@Tp0n#%nMM(k+9eym;ue5HU*C`w`1!f3f`38e8r>%LI5=d{p@_%str3 +z&TA6xHq2h+0xsOx%XCP?X};uZaN|-sCHprhy`k!X>U>EWPm>Fl{R#NgmeBjXtE;U@ +z@HW4I!tkE_vNm8)b%CUw99Q>GPdJYd_-*C75P_z2azczpMl1vAD)-*A@K~)jr8%xV +z3j`dWr#7ove50 +zt@ne?KT00)p@|V}WKDrM$Im;(w2w5!%iXvf3tAZl+WVaBX8g9{CB=LwMK@x4eacB7 +zAQ$*#iY9?I?Xf^UzjeBDy7)e8*UpW&?)0*5io*+ThIxU03smAd$_mDbj<+O}01DGYUAQ)EUR(X)aJ+Vu6gc +zFpEZ%U?*eD5L}B8V5S@{Uf^3cm=t+w+eQgskt+`%?y&a>aZ>QJ!)MT7#iN+QEFhBv +zq%@q4#zKT2xr_Imp|-a(+T25gO&z{F>0{bUji4pg(2^b+Qk;!Z{dnC{z<%GH6@ +zFe$zz6ih(Nk*8!5r-h{PWUiY*B70PCkJn*aLB#XfGmPua_#+x=nQRQ1OeOBZoN^KP +zzO-uDq+MEEyYac>nY}IartokR!&xikocT6zOXu2pw +z1&~={PCL)IFYrv}YdTOTWPrLDqP#VOYt>#pt_Y_$sk53$U +zE5wjD%V8yKUPp%&bu_^{+tIAtZlfPvd!Bh}Y)lf$&sFIcA?36-;@GRDlFnLL<-*uT +z5PXvXSz9aN8=l2aH;TzhESGIshq;v?=eT$D#Lm`k=a4{$JO|SYO~+j2BC&#W2vuju +z$w%u}s-#%mZ;Km9@E?o&&yzPs!GBrY9l+lfHv_CII=a8xsD(frjr05%XySib+&RAZ +ze=TlKvs^p9&^dGN0Solua8%mL#^dE-&f{bm8_%!};2g@syBgjz6Vfp$CrNAo>KNw5gu4gl(H +z=^Ec6Q9H~G)vR9;(Tq4|toE||Z1TmPV)zZ(18NM4D}2yEpu=c*)Q@#=E853{(FufQtxnwh&qD7I+Tm42`w1p#l?M>?O&PDny!|S17RH(z +z>6_GyB$cG;=yt>kp}1r&PIv;9xX_gRE9X7-p?Lz5b2SJm`i%k5n?$@j< +zvHfq0+vUG4?iIQfzi*2>*VFw!EpAFL4)_onV4OiFw^0aLYEi(Fp5@(5Z6mo5q0dA7 +z6^#r7f9a>aZsrw+Va)Lw_=%6n6RnkrzEWKZ5Z`Y;-eN^_@;OBrqsQQ&0c&FPDva|Xv0o4!GF01@ +zkm#HO!6E|l$#jE!`bJYU7UG%*Ph7fGeP@}v2e~B^l)P!hvH%0$I(AP7NwDX7&%u$Y +z%6Vh^phfBv(ln{rbKqBy{v1_!WFS;;wh1HcWt2ycsD)>|Ui%*;V!`@j2j*$H<>~Sq +z;PyL(!2QP9k;^^ZW}fDD9w47n%+GD+P{qI*DXtiEf{ktT{Dr!hf3TIVfM889RRGW2 +z7L>rl_$!jPk%9K^%98`?bc2;fMC-Pks~f#CbTvu_U}s^TlNd*$2A2P30Bvhm2U-uQ +z2y4h>d6_6te{M~Hk;cR^WCF}FUX|(B-4x|7WOM>?^4J^X1{)JR{rct-4-DF_5+cSX +zY}=d|qtYpA8>G=U`Q(W5r>d4xY5rfI&v~|{<{^lbwgu0ng0`l1 +zGNr)Xv1Wnl(*tydWoeB!~6LP@*E;&4A +zMUUf7=hfLB#@gew!RlpG)hQxr?bxx5Sk1NqTP*OGjCZtt`0?35jD2O9Wy_>;^ +zJL%A33`PHIaTk$g@wre6u&KWzxr`?+6hx0z?iSBfyaP!0dk +zn4^~h0+Fd;6{A16RnwGdV3jTwoY7C^tKYF;13%sk-^=Em_Q`bo20edUg?e*_y1W{SB2v>Bf|_JhNJ$n*jIc8ePYIUY=LVf?4R +zR8S$_63@}|`Kjk{e_6OJ<2atiS02W+*o1Y1i2af3VQ!F;P5i5*Ay5tUZ|kn)2HL*2 +zBuyDr04Ls?pkTdU(K5`OVPNFol%rWAw3CA+!x7(e`NsA!6+eY3r0qrvy8ooO@n!7v +zdyQ~kho10V`~b!J5WBR!@!a(6>Xwh(a~9!gB3=Nq4UGu6kEW>1(t2|Qw-UYcO4rZ` +z;g&It&8z!gi{1PLA^xs~ +zgEdbX2rQ;hR=po%Dv7(8Sne2E0 +zPjha6d{A3GP~!$x{FhgK|hN=00d=vY8ejw0`Y1J%d4WXv<($D^WvRi +z2w0~?vFSAtUk;tE)>2mHoD<|p4cfP_|WR^@2jn%lHV0!9CLa&ii3wsc9O>k=bqE#>M)chC4{Y68l!fQT_hv59+#9kNp +zO>u|p4{tck*AR?5w<(uNIOxLg$o33mVnwOs0vaqNUjjQSYuyg8`dledXPMK5ul|eT +z-c$UhxEr8pK6ARiDo`!|p}57X_Fyn-51C>(xMu*r?szdbzU@34kSo&6=CLXuesRts +zCzEnrFH^CMWx +zlqc_)_ekRt+hvPZC^G}l&;pQG2qol6U_nIH4i%#*H{1%z7Y8yI-~3Q&(>Kb>x}(^p +z65S#ZmI#b{&m+V{*knnx9%z1Ad;mPa=x6xn%@)_i5>v46%Tlbi9AxjDxU49vy0=C} +zNDC&GOdW@Z1}Yj-PuSm#)f1O)3l0mB9kEBQX9nFnfX5BrQe +zQX1m>6YD#Z?a{U@eHyK4UzUL5PkKbrVoR!U1)s6`OPz83k$r_mF&6h*;@12taXbDa +zaW5a65D}{$5&-BtvFYh#N@41T!oyHe2QI%M+Y}U~?YdgMWJXDe7&x^U^H;j*LXv3` +z*v3z5qG`FV%?Ud(YC3vizIW8|lSLTMt)?}wY;Q0fdXz<0+=t(?Oa?C6?|Ik)p +z@#Jtzr>aFt4ljS+AS}R5n@y^8M~N*HG&JWO&8_+c5YX+wiA22PId$LqdD*r_$B^mt +z#-M@RMY#5zaG(yAf9IQ;55pe1ZvPz+_)1X&U$a$GukXr3;>U!xBW#Af+~>FfDxw>8 +zDDUSmdkAJWKNooX0Adsq={Eu{b5YlZY{dIa6KjiQKTRfO7=JUs{i@9EcR&g2$v!eS +z@!K9->`M0Sv0`a?qu%cFxXtuMW2f~6{;2SJWn-#nzX$*Y(3&`u;0~1VI8zxYh!Tp! +z0HyR}vOY|uF{G~UgCO2wzrmP~<_e^iS?W^8Jl~`N`NbHT0X}F-%-tmfq5i<_5;ti! +z?)PxKPr%a-)OOhd^Z=Iu%>sFmgLAWA1tplbo)PPanc$e2r+M7E$v4G~_?O}?`xnJ+ +zsbwCKuVD_)LOXf+O>rlP96TG)nXJ>dFS8^QrhYBxld99?a68FUJQZ$8&l;|(;%`9O +z%cnB+$O5{?#jNwBnRYY(2gRK%PXA4D!}5Jo+|B<`+(%JUb%4HCI$Y&isdx=YNXFA< +zB?-+TEDDV;KrCO2^0W=sx`A$Y;k>Xz1AbnvvsgkY74g@L6*NYoHADA{0}7X>FsLKQ +z=Rz~9c8nC?6!$ONe<*GO_5}m_jzs&LVnc2|1zno~yULWFn&@lkS;S8kN1%IYBYB}L +zu*=SDVdHEj5k +z)xK7mBZN=Ry${_l6*57oV@~d(+Fx!x;N2g&q1wH00u4sfXmK5&x`eN!E(u_ +zN_u6K5UdLo@&$P&b~nfwjW*IB?Y0s02r%Z&c(5Rl&Qnp@Mg!iS2JX48gjA-%(jv$ +zx&Anbe(4LzZ1KQja`&YjA{aG)1&a}YxB4SrHJqy2w;Z4%`lxyTZ2ZG?@eT~!6mP?y +zE_y=&$9%3Y<>SfcR{m1y=}b=u~2LM4TKiq>>s6_NbNe +zya4meH9_U=nr3;4iNlQjNdI>TcvAJi(ZxhV!Ok#(I4JzitoU=+={YxXK@Fb+P6)1A +z)=?x3T!BhMSa;|3T&K6A?-=gO!Sc}fXyx-^v>z5sGSQE+@kcW~>PL2ElvedpXSkSb +zu%RVsQRLj-B|x?|3d|U!Y>C{y2m^J(KZgwM$+SvVTl4k=7MbTiUHKm11az#hbKx!B +z<7AF#r=up0SudKBSxf0&!(u2#x>La87s2L&#+7H)x)b)(VIw@1^t;rSIyLtR+^r8q +zsJSuXHEq{!}belsaL~)QqMVLE5_Fw5!=dV+o4tvbv9)1evuxF}gjlt~yrMSl!+rBAo*Kdk@r|zN=U)X(>nP~O!ILUS{ +zrGx~A>RIDLXZPtccQTz+WPtHHCRqgBqD%d=^c7?AnTV-jjiK7*^{~BP4>ToK#UXrp +zZ55nEkG5N=CgTEzXOhWh)3<6co%hL@Ef&jx0yY4Am-Axe&=r<#epY>26ea$_u%9|=ArMUp&~pq~PJK6Cxm>FhLZysE%OqeM +zAYN5@#L8ca+u)nxCdBuI#l-%mxWO;D!MzJK!)IOD?xd6eMQX9xx2U$3TwvPIu&iig5ANh3qSXuu@YB7=MQO#}0J~pPmnjm883H2?q^w0A +zR8b(F&T4;Uu5Q{;rFtEVM3qV8=XWf=fh*#A2P;kiVqizi$cZU}A_ +zn99sb#l@OluV(up&b-tyv^9NrC4}`TnJlv73g+ApbZ2-41U4pQU^4BeiVWjs-{d~2 +zbcBS<$AGZ&={WL|B|%lH#b4Qbf>;h(y@14th2bE0?;fv{C(p=QhIwiFO-%igV)|7! +zq7m2O7$*^cMT1l7&;UWL+nfhvK}M`6F#{q@EP**mpOhJ?d>54b^6s +zcPT7_v8f^c`b)vZ0P>6Kmpa;!v*HKsPaEM|eZPY9<4!aiFV>K4Ahy#E%>PH$J+SB1 +zHR>9UZL_g$+i2V-X>2ELY}>YN+qP{rwvGL?-}|m_?Y)1*JmxXSxaWB>du!C@vQEPD +zrF1^^)uZqoz!~TY8aRV#VN${qM^WF3RFj6^;fpPAN_yJn+wyO+j739+lEb>QU2p{6(qdg}_1SZgjFcsmC1_8PM+DrRKRq9-vDeGI#8xdIK@QPxDkJGiJp* +z7+ahYO*ovmqmq;C5@9}-?s^m@#BIO}ptwng67bp~8HJw{9tkY4I9Us4d`tZVat&^)^i(^VMM +zdt+lcP2S)tsgc#N!C|%K)TCqRvFNCVW|ZAhNxJRu2{7FL@D-(t(_9Y980(_^o~J>^ +zHU)N`fx;PcGa!dd^tEU2kTe6;ZWFICH}@CLQ>lTCm5IO3_-9;Tad`+6b6t={BN<2% +zR4x>Uu%V+<42kXC<#F<^%8lxp0{d!Y$Ptjp{Qlt26%i3YYPqM?fJ_P@pZ6I<7W7W# +z5D%Ry0haOb+bkR_a(f2wlL+WBv&30_LOxrGE9{pF-N{A*Ryn(VR%ucA9vAR<5SncX +z64qB@@k21W`i$kum!pqbOiowD-mNLO<;fN$(lwUqax~g_51zx_!8G}%YBgqvGOxtb +z+{ajUd-`j}b}4aldv9U)3$?JbulEl?ut$ysEScDiMH=z0c@jhp*q6mW^((hej0I^6 +z7_yqU68_ho +zZm8uq5#Kd@?(}FP&x68rS$$z+DGc>qoNGuiM1Q{f!DofSjJJR?)q0Q15|l5Tp(!|= +zt6_b&3AEZ)F}8$+>ZkIF`2nS8CB-OlAUkLC(%eF)W%~8o6#G9E!@-E1If|Hz;E{H)Gf7l00 +zypf`vk&hA*+n-u-@oO_wg_@O~zdVyOLdW9^T+VuiC??zBH1j)8FUd7dnc4+|hFazI +zGR5;}oF<$TBLiPxsXQ?mtUD%To5sg-!?P|EmhY#cvUp!Tci)L}Ekt3<0b>Z6rtk&& +zS=rgN0GhZhYr3b=c$9l^^B4aruA_a;{FcXQp$iq}} +z!JkLEUshSXA_2~#h*ml7nDfz`($I6e1 +z<`N0JYt)dXGs^#@x+6!UK8IaDEZ(8mJ^p4>^gJ9J))@%Hn`YaMmZ@nReXQH`Uss&;dHiwz3M_cGYHWm^)_?Sej4}`t?jt=q?GTZE&jS_lnkYwxhGg0k@;wAN+-VPgJyHir=~G +zgkm%HjtB>SQar7Xudj<|JY#f^qQ!&&`ygs>H0QHZ*Ua-wE3iv$AuEg~*?f(oZ! +zsLi#GVha53z}9AJK$f7TSkUYnmzrxdF5K#nnc3X$&P5~)D~NxjHqd< +zzwzPg_5n`+@6!|P*r_orVG#S25Kq^ +zg53qR#Xp+a5|Xgz8)~pufu422k|IGHnk@@548~-=-wVb)I<>@`TlUGJXMw!~WegLf +zJHK{bC($Bps#wX)e!jb`L}M7Gz_X$56L-fJqcqWO$OYoPD4T(Maw!T|%-f_Vs=O8;8iDiFLL0E;^um*6ri=J>xBcMQKwA;99k0a)CeAsYaT +zJ7h{q;D0Rcq6Mz9KNdItUyIwi9{B+t>=I`21tRTg#PJp`4dN-RjgFV)GGu5U6v>o$Y_^@BWICs8lgiGsfrIIDHJbzV+~2=HLvsbY`hNdS$@DUpf3te5*GvVU +zJ*0@x7!LbbsdCaljmKE8Xe%uH0>QUN#>l@nT@=a>2l(x0oXdTm$crT6=GSB9y +zW2Ol{8`Ih$@E&&xdGN)R%O&7@$uYBS8_9WtVA9DXo&n)OO>$M1hM3mzqYje=&VgGc +z&V9DtEv0A?*zoe6x9%N~Vsn=(5y1>bwAvL3^%|%a==GE#!PQ3xZ!vU6oNoRPk=TTQ +z)nV&)9xQk;LA$X5;=N{x^(?J4*vv(?X2`-hTQVm{sQ&i3`@TKLGH`>I`g1S)O9z_cYh#c_z(SRGYAEi>#T#f-m!iPThl+Vro* +zo%q+{76@60m?FaNpJ%s3y*;JDxQdZgm{PzaGpcl1Fe|gazp3~8T^v +z80Pdd`SWWEE#NCSa0bYl<+0z{bmGzW&8yv@~|26RElXfyh`5HG&Bv#6&*5L=AgfNlmUJvRhlbM#S9wFjEt-Cs4Fpd2AA +zATGY&A?ne={hE||ISfoq +zAujqS#DR}~hL8G;PUSd!*(XB7$zG=y3d#sWm%+osy^)^R=LU1X@Y=e>F6kr&hG*B3+oUD0=i!~PsdoaJe&oZZEj?eS*BgLW +zv+4O!E4suW!(D$VFs0LJ@a(G9_d0c&wA7?S@H@$&)$`fy>E`)(Y>PqX@^WmeO6P+g +zU+0U7cbbA1zh2FBRl8G&F^!x*}qD5G3cI(#HKkBaKx-2^g0TzsWb5r-@^Qca +zdMrnpHOukIJW;m&fmDPH$4MO&@&*S)5~}r<^IOLJ<1rB74q}eBE9JQs`cqpQ{xb;F +z1^Jqvp}Hw&Oz|m*_FaU6L3%TK`T(}oC#qWOMhmWfcy`{eKyOf3QZq1a>aB2wz^+o +ztBCm4UUkZ7{SU;A^&g1a9RP6`+X5i&&_57&Kgjc6h`aqi5O>HQh+Ab}8r_si5fT>M +zI~MABIcr|>BXtk*cqcd!34tUkrnz;Q)#@=OXut(|s+YX>I(LnZTqi&@HFfbkkrbg; +z>=tZ!Ix29X7C+s_yMS@rv?AwrlJ5?-*WK0>snw)F!qS9JV3i}n;KDTye}a37-6Mlk +z-u?wz&N4SG8rwR$e{6RTS!bL*&%>&2)YJ}5jHFw}I=Zt1dj(%Y##t0NS*^|aS3rq{ +z=}0iK(xO&QHEBp|$qm=HYi1ZKL(E5lP5mJq#C!lKN8;B!#Gy~$`O!I(!Ep%jgI +zI_4+%HVdZ^MW{O{4@uw}9wy17Wg5_gC}m7AOI?4eD=>k^ceYr|pXX4YJS!4C{IixH +z*lLFa{|n+C;)1f7F0KIMF0*?Cw~v!AkG24rxlU_uvi!xm5gwrPIA3mlozheTt%B7U +zCK?BahT2(nL(q4Ku*pc$Jh6-;3&t*o3PSv1r$V`rF;=4-(XbBdkF^4HO--;MT3Pi? +zV;2LmTYh!1RO9mzplx|>8!AE4fPY?h!9G~%N--lNUxs%JzxgT-;R08mBU&<-cIYje +z>v4>!hjx`*DDS=*)zQpF?Cd?*B!xY3ggI#zkryRkAxBKg;9*e4&+{j8JKl)NTr1nB +zpYNyM)2BYMJ`@V@%ctr6(o8soXp#Q7_2B!Y;~HLDBh@X6>lR&jc_>+M^!UUWH-G6O +zxIHZ1h{?fKZ^rLj|83jZ3ZujC@?`sN@vCMc{gV%ZMkK~+ut-U5zIh;Q7yZ5y*vG~G +zw@ES?Fnw#wVJirNUk_%|GtVbL;-)u61hF0x6hUcb_;t}w+t~%9ce1n<10@8IxK+gS +z4Rg50lO^C8CBYu=?DEUxE&yIA2|I^qS5~ZNZfm00222dL2^qQ(X(?j@;o1l){{Geppfha +zk-e&{luoumT242i5#ucpawnE>%Rs<>j>JzGsXNgYUr|Ghl%W1;jo?qpE_U*#o-D5j +zT*U)y9j6JE`ZS`sO9H*gGCjw4my~mz#|J&D_A}f4c}p!T}_1{#)fNxeU*vKN7bKK;ot_albNKTyq$&dcWTI +z!16k3|08j?GeK4i!sqdpf!qI3+z1TME{nJUNZf85bk9<6wNsnD6W=F%t4%sq8X^KY +z(zA9V%A8$3kvrlpD2KjZF?t#PBXN8GBXLKBaOLh2MCkmLxcy8o@bvhazLkvvByPOl +z0Et^`X~gr7#4YskI>5*b3A8=zN<+swoYAEtE`t^^*Jz`^(>Gi(<`DDY7-8I>67W@h+6nOZp +zK{e?L|6EOgkEd5e7RGqmwRb{8MPO_$Gd_a){U7C$oR8ia`*`o?dp$bNy^MqEo4t1yZ4)pg(?-CE&Gt +zv8x}PlGT)u{3~(iisJVDN8&E2cX6X3zrp(*Ye164u@~P^4#E0sy=XOIi#^&5AaP6k +zZG*FkK +z;?DUWi5q3W!OQKx68EO~Y^2k|KN7dcUy0krMWZwE{jbD*#x{f^hr`k>1l$UCQiqn! +zLy+URG3Bsv0+6^7B%Lhw@jG@$T=Xb?GUp1Ty@E=YXQole$sgaG@wMkfW5x-*b#po; +z6;y4O*9(`02D(PNG{UV$wq(t*y+#ZPoxQHzydYESAM}nmfGG*Q!CZon#ZlNqJ*YiHKFSkh0(tXytj6!sij6C=)zbM^M2{jr3o-qR=B>_;*~4A9uZ!QSSy4- +zp2CSRM19rDf~B71vZYZXA6x(QlhT+knqaJoBA +z_Tx|;Mc-RMFrd%Y-I|DBxG^1mdD|e3ylhHg#N4q5IV@=@+ZTU( +zV9B-nb45~xZH1z4Z%ZIAd{De!SUJmwPe~@mHSlnen=lgb!)5|OT2k36c6B}H^wUm7 +zi9BA_sn|LT0wz~D!)wfSR8)r#8S9v**Hh(J5aCgYV}md +zXyEgF4R{}Yq?5ZieAa6E7I*PF6x4yMp89cH#oPddzX&)tGTQpkV>zeomfdVtTzZiI +znDv?@)NT)gtcoT4oRt0*AQ5iUAd$o1ZiP5D +zrtus~F{%R9S;Tv0r0*c$mB2C+HlrV$j^TRQ>2LNCF-R>msrC*0%t1{7UJ)08&x@vNZRjboPc^P0SOu>S*jq0Zy2 +zIFz*kRp8M6JQzf$4j^s6`nt2$?6KKPUvl+?Br^l~2Ex#;s{|&nJoY6R={GY1j~8tE +zKI8|HBB*wK;CpVBYBeLrhG`1qOv{sx2#xG!g=cVQAHMMSH_C2ZjW-KCQkS*~k)RTo +z4rVEjs~t8^lrg|(C4-J*AT$&{1Lo7##6J)>i025tBYTr)`X?{4rn}BZ$oHxw++cRu +zRn5m|ZJr*iU`Rzo{wkw|7|-{;b6@Cy%`^kxvuk6iMdz5M#mVgkT`c3LYClo7n=$hg +z)yJ!pB(84RHc`~>g5S;%>~@w5SG;y>YkS5h?1`!?WN=)N>0a+ozalx8$?MG!U7p&$ +z)}S1SHpr!Efo0@Mq3<51tuIc4rP;7j5y{HRY^v`0Kl#Uj8%nu7ADra&&01@FXOP5B +z8-ph;)E6~ua1piE92SYWsv!i&8nAD`8SwE<9pA7Gy5(*gO!^Up!(-IdoUP}^-^q#l +zK#Qt|kPQjV$UwGuhU4O~f3qj6z5({Timl)8R-G&^d|j?-Hv6fKI9XL&30X*exQjyC +z_0i#EXNUBz!HatZ`@)E;@avGISu{iiBQm2#tx2-|w`Ea!9C3rlxYgz;$hpnq1!`$i +zti0n#F)#)Tk9@QKHQVqbkT!3b_{Wp&b|q2PzQDH_8{1jSP!rs@d=hs-T``o2=iO>6 +zO47o?vS_n9dAeo^@oGl#B}p1aAV)E|$AejN6v|Vh;J(sS3%JYbLI`}q?pT+-g#6WY +zWe)h)eviYiu-9%Vn#LskRO4xJCa6-~D*@9%aBwy5jjm<%_OLA@6JWurAC!x$LC1o= +zN9jLf1ze0<3a23TJX-aICe^23)GBTLj3pm9E6DDD->VEuB?pgEK;er@KS<^}+a%*p +zRmklM+K#J#=LT#+xUus*hqJ_Tq7f#=sDV`nq!FmLQ|ibUbcuB;PmSCl=AdG$Oj2pN +zCc19n^4xjJH;jUEw}xaz?|DaweTXO7uyF+jwC>UrErVm&^U=j-9EJuEf)>$;Ey&IR +zXO3GB64!VQ)IWr`udqp;X?@&;f4Z%B=*O>AXaLJJ-to=9_b&Xz!>NL7zUxH<9>ODJ +zzL8gB5~KvG#y=3HO3U?U+Ljwk +z$Gb~(XGH|&hp>AW<$tpm#uTGU_BrO?GsQ!tNF(Q=2cq}!Wo`1Tc{;oy55b%DNb)9D +zQ!Pm=)kfA!l1sGp9JbZI$K16L9IFlN9^oMQIi2eB#_NEz|0P4;a{c(P#0^{qkhqi9 +z!4-@(pHY8sAk}Tsc7<_V5&f08H?IK_x80Yt(89kGckKf};uifQaVr2MZsFsDUrhP~ +z^b}REz3Q?mnfqU(go@Da_rlO4kfK`7q25CbYfPkV;TZ9jr@{~R4s{l)q}Sl6V=Zsk?R}!AA$_NHGym)6D_oid~<5 +z<4I2w8NCiY7(U&t&u&xgiwVN$TQ&$)8|&fZF`4(CqwlM@m3!iHKO$q)DM$K}Jccth +zXCPhPppvcvQ~y-hE;dqTa1<#hn056ONQ~{|njUt^?dI|kp3m6^`#ODS?)nH@N!^z*453D@R8nSC@NeszR%4N&XyB8;Bo^^$PlLtB +zbCuyf@-C(Oz+K!OtQkjFXSX$@HMVAkTzGvI|4`h44Sy)^CFC_=iGHC&g5U~0YEY*X +z+VL~2@JoTuSH!N$;*-jE} +z?xuKu`WOkg;vh*@tw66cs!yxydB!I_w(8QHr`F-@0){!Wib%8m5LbK&Ev^7h0kk4W +z*@n>TOEC9dg@ET<{5V=J-3d_GxA_^7T$%nW90ADG@!O{g$kAolSJy4V>h4cP!(05~ +z>@UgeQo+3zkN}H&{a=e)V{HUmf5=?LQ9^R4JU*MBL@z0*OX?qsTMkoq;|m>yeNT4C +zn&6^thuBI@08_lPv@p-y_BMiwcCj^Ma5;BV0+JCI%c1YDj{SF?MCcY~BkFE+>U#(+RgI8yc_AyW+t3X(1ACye%16Zf|e* +zi0>7mml|DPu<#b4Ak}HD!^d-MzoImJ#Rnl?fy2>R%;D!n%h+D!nppxOFTZDU|7=*h +za87KZN5qbFBvGcguxQ@F96s2O^U*T8JG`c1fITWhm^pQMcn$aSGYnw31EmUym%#W(6F!wVLt8;h_MbbgM`t~6RXJjAIjod-Y6-%hyCI9ed21vxU8%(oDq +z_in(3^-?l?wHe&xi6@6rzdPcd1i|F%xgcpC{)=(D+5Y^Calc(=#s*N>_P36#Oj5y= +zq5J47kg-2rnEqcFcL)8Q8arGN0ONlDn)U?1xCQC3e*eX|M*$dj3I2aDZhb|!|6<%u +z1l`-te=u$lLIB3?zz4v%-SMDY|6trN{ONx%Zc;)xxvG7C0LDE~G*yx!;U^lVBmie1P)3NtdrfoERqyRZ60mQ;;$Uv;T1qNxX1`wQB`by#<@|hF0sg2uq&h)$r0OKY;OcmbM +zbN)mfry3lUnJ)9XfI@R<@2X3D!c8dQzEjv|>^ynI?B6%-c5v-PCm@#-&?)(CFt$|R +z2V8sTOEU~&ML3p2uh^bg&A)Q0pFw(wlj_wXTTT1nvP6r3-ZeO&DLx%cJ%9Ly^)?WB +zxRx<|iD5c=r@^&iLcs8-TMlJRfLwegbLyIaQs#~5+T@8uQIh~ycqBxBdIf}Zd3s4T +zoq!$}Ccw&%KI>fqzW?w>p+N4FB|Fe%nGy5oQ})o~qy9QsIrLwQTQOzp55~O}kJno9 +z`MbjmTPQTO7J1udtMh$JCw5bpZqXd%1Ji4~qh21pcChuQFRzYv6))9x)@T`;M$<#= +zaYfSasI~xwc>3#S9;2b>-vvmN22WQ;M0tAsi%L#0+)!FqX){g3$E1N+3GS1^moVzwA9uGRCs?41M +zZj{cg&L50Bi_>_RtkO&f=oae9{f$Yu?04>8jQa}!<1Q)xUl?~&#qA%ATLQwf&zp*q +zll?EoeN?>9cvnXEdB}JBD}$gs5VvAPdDg+awaiC7rgaU#UlAP#OeSI54eXL-K#L5e +z;+;&sbq;h1kz`*i7E-Ek>HFpjUzD5?L|Eo?(PijswA@@r58o%p{nS +zlgKBsC{Ve7pYjRHr#r0i0oDr`#At&@A=Q?5phisY21)M6wcG`^qV4@;b=;|Sifkic +zU;Y58Y=KLO5owYvtg3Gtkk>OHF26QsI`s>`lI0c*A%@6PF+238HfMDa80<_(37FZ= +zvSE@$WA&@x`>_w2S_OSwmULwUcFo6pR72LA19_V^baJ#(16TKDMbeE50x^iUanQ;CW6Ca*A|Msb2gehnuZ8hT-;CXny759lYKqKfhOG +ztzVR5sDe0i#)~}=H>Lvy;YiRHeTmAPAuABNP=ZV@^LrLIwDY?`wyW|&+5-%GV6lbW +zh38L!zTkG7ONLCNYyU6CJqW<$k)v$-rni`>mP7;R +z>C9z(Pxb4<_M+#eR2^0hqt~7wt*Jw!m`(}4ydUhd%P5o{7t3W(!J6HS^9@xf4pc)z +zLgJWTu{*;w3sKoF5C-4{6bA_jd|bhLXt!C9yBvU=Z3Ku3!XvMNp6I*E&?<}>Z)pmK +z8%o&-4ZU +ztt|U@^Z;#ls(7xO)f|O*1qhyjmTC9$-|i4s;<8srLu{*+(QNh&0&$pK2h{$D+bQd* +zTIyT|Lv&xT>1S*vGGkVz=`+toKjuPSuI+V=+BgaFyr{t +z6~QyVO35OV+!^L~wQ>n6O_mZN{nm-Bk_gbrCV^-iSJ)JCliKUd{6le~nO<}YtHl>!F?~XQRn@=&Nxu8tf^l>2TN6tK2OFrDVd+FtS(7iqv_C +z3cK%pxb+<(!SgN}Pcl2iMI@_D-k!Le+#(IVK3*h_`Pr&p?-3Wm>1?sln=DM+KrFM@ +zn1pXpEHE>O;Y6}5uK-e1>tr%R{~kg+*KR-DIDB4Ugb+xf+0K<`5kTWM!C_EE3D7o% +z^Vk=Nu8ZtGZ|l0sL`0@`S54y3xK#a>wHv3FHZxQgTVaGmfUo*FeZ?g(yTCf_crxXG +zKZB1OgG3#IGrg30=eye&U?Q}VEoqM$PQ$R^=%=P$4GmWaHSwZL(&iMzou$)@lfyvD +zZ)V)3Z-o<^nUM51%GpQ>yF(74InaxD9G_dCZ-yV_Xe=%CEcEZ|k7t_M651i7W0 +zp}8-t8}8#Ton>F%aBQhqNL;!?!*swcTy#E~D@4EvW7fH3D;5kzgl%De?1cIA7k0Fl +zd#3!Te!dZli7%rex#XhKR?MO{PFr0>?@N|LgHbkx$O3_?8G{WCSZQT`sh>c0{>)@%gNi +zuch{gvjIx68qM+9#iMtzWQCLAxC2#bf^r6X=XKn-uM_M?f+>!Hwdz!PN^PT@0({DC +zBTvx59XMiCdw>swUVFu)G2H(&R>02ffq=@}r#L4*Nu(e1$UwkuAtg<1H;X-&oFo4;6+Bn7A@_cp?W& +zq2aF5j72zIPfp!1N)|v;z1!2!sWkr9Xef5547~r6XB^>sMv1aENihQ#4Fk^5P>1HL +z<>6Swk+4Th@`QR~;OIF#emA~MRRO-^X??*{e#uU+;k($q{heV01ZyuluP?+ERO{$z +z6l(Bmgt7GwvgbiP;U9^+N*^X`{I1)4$YT(wCQ|<^ans?kK-Qd5r|xVh +z9ZR7L?4riU%3|^QPwz5**PZM3TZ9!u9nEMh;4ob{+c`Ty9}*IPQZko@g}KyPFIpy^ +zKWwn@Tix0{gnX0Le_kRP1ABW)8~r134>z@n10?RQt1@mfrTAVPxp<0Q%@eA7=#vY2 +zy4N?e0bBeP^tC?bf-EaOesxsw%L)z5Gy}xZF>wW!mXkeg^r@p#Kuc+xe_lMUG>dlI +zJca<;z?pw6uUoP*N`Ov6tQU^R7iuHedz0n^m)>%yJ5`H-I0C}E1K}idWh!51I%~Hk +zlPB_vJ^2Vg;>PE7$KjyvZDKXrcK;L4WI(WNpIVxeE4vP;PU&HVmRgMJ@^=f9Y)4NFS?NO>K>{2dpN +z27<~?geb|Kp;;+G{=L<}MUVL5 +zcelP~gU~1-IydZT8R_l{dR>C!7GsPrnSR+cq}*Y=N-K5jD~8{THaOrf2PaI$zov*f +z35a|RAUSx6wAFuq`pBCe7Du*4QHE&soEx*;>zdJIcqu5J_LB)g`IgM`6CNr|3$rr8 +zLana~iOykHOGDRF^F|~g^>BMB`GDZHeo$!+j_M)pls2AjHNw3`xwlmPIz +z6>^Pi&WUaX>=VNy7gihfC{qcdRKBTOkY}sc+RWMY2CTpunfaujCRx2xsi*Ev6s1ig?z%Yw+mo13b>Nw!a&zdwaUzXM1WH;UU$i;vKne*JMQ}hbf +zE8=8StsGa@On8C10)CMDiSc3Y&87)ow3K39FdMcF?dBO4BzpNDJW~CDtY=fZU>?l$ +z6Vgc@@9V`%jSJLF?lvYg7*y66mm>~s)6Rs3#|hKsv5^YSVE%^fUVdg3jd}6RS?rF= +zR9U;k_nqI;ARUGZDxM!^;p?Cmk$hSKm7?nL%zhQD2Vx2_&_Vr+4pw|ci``uMYLiEh +zvaQc-8@_}$-)x@|{_Fx&pghC!FoF((pde64HT)>~ +zAU;-%Ou@o=FhTdQ9+lf?;9Nr!(}cA%K@?8x?D_)_oyS$Q#EGL}ZI6!n;7Uw#qL8^L +zX`HGTDmXF+mgLjof82zNcAes5pUP*jfZ1%Rt +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 +z*6`AsaCT$@!Svmk6MusRu|L(ZD?z& +z3mx7G5L6sFP(;}o9ID2TB9IUN<}DWG4ko9&lmyn_h=u9z5_j3(CGHBljz3G>jQ<}c +z?s`;fDJyV}>FYUJ%`Yv{F1nLlmC#o#r|31 +zo>R7i5AbwynqFOA*Z}Q;%{*i|)BHCQclGSwByL`vzewDs>HmRBFis;$&Dq58_ceyvq1EWKx{;WxD`@mUl+80*4W)7t$r2@wx{O*Y +z{JkzTc+~!==8eAO3##plIW|mb*66rwRveEV42b1kttedP(H3H-dJb=QcIptly_qC9 +z^bPLGEq_pTTPofZ3~hIuSN8eCi@c(kYYK^pk~>J=`<_Pb3HqWArnpzH56|2{hM`n- +z=u!Z?{QO3_p*W!JjJGt@F{mVwyI#~B2@+yS<>u&Jv6R^wzH6YeO^ulg>G~DeQ0^(lS$@I-GY}vR{0;i +zi%4FHsBEp3xC6Ipue*8d&0h|E^RToj@}j_vuGC8rkSZMbzTp1&YGV<9=_*#V1(DhU +zDLYsEewiGv2jH%YBdk{jp%-WgrVeTTlf?v0`LG3<)M0;Zl6#$qN=M_0r;?C%~=2(#oWIqNp7R# +zhSf5yln8&=b47i>+I@Zehr|u|hs2G|dP7{4EeK-IR_RhqqICoYivlhp-45{{l0;iy +zMra#7ckWa9VKoMTeMurNbKi*J3{KCjVw>@}Qx +z#ACX!7UXunnH7(*rDZMEDX~6Z3{PWf!3<&p6JoO+>~Wpwf-r~4nQ9Q^3#<&DDl_LwswduS~0vmLEQ) +zuN}0u3Wx+!%=iuxFjdEwT{uismXv6WN_)N}E%s1R5YBWUl7Ix1t=VkCJ$QTSNIWpH3Ao&a3!t`ML()k=aED~ZGta(JFTVZyK^^0fOrfoy0e +zaB8=a8Y#=OQ%mT)hyz^XCk#a;;pM})ya{(MXAcE`tD2iVo@Fej0z9StBv|E}ZAj?Dp};=F`WkEP~W +zHzNZf;SP^h^t+ePcTGx}uF@_-t+#5t`X}AFvlQxXqb1u`W0|u^tw6g8sU)cY!lyOU +z8On;eB#@Y_E`XKYd?;^&pU;(Fo<(cHDO86x1+TbMTZhn}P|zA|iOa(?zEuwtu=p3bx--`)Dp +z9=06DTuCiMDd1a!*O{9fdp9(2aZs%(cIE^Tylakx@!sRNgiIv+>@}Q6<{HUyQJW(( +zg40*2fJx?iqLh3GORQOgLV)g-86GIe0FIn!z_go<2#)sDK7M^mOM?SB+dz#IXp$7A +z9RLFP$K<;)Bp+o?|NKx;58XAk<=`zk6tT7fwYbMUae}k^sTm0|s2*&7FwmPFx_c0v +zTDXbwcBlWz{`9u0Dzw>t8KPVt(9Q7B} +zY(uG?B#H#ewKZgR-^*MwQ>`%cWFK>etldZ}D;_FhBagw=aH7tY#Sdmx*0yu;&#KeuyICR1`0rR$FX2?vbD|Yh&zzr5a3Jx(S|Px@|wE%8%g6il`r9z-2bv +z`bn>1Rqfw&r7Mfpn#B(d0;UuB(hn*Er@5MEB2VxHQUxoOgBt%vC7|euM3kB2VdQwK +zYU&M_id`( +zP?8@qbIc~-!jX+#a$$nUn=_HRYlzn{7)o@$?2ZOeW>dRGsO+y)C{d0%(jm_l>J_%K +zx9p|_`5mLkyaq@fi)sU(XNYacZQS+_?1BJIGN(5B`4~r)v5WK>ZbF;;`_Iv%$@ElF +zcN>9lVn}CGP>WwI!ae5(h`&8#g&iHVejTmNxP3_&-D3;(vy?k^T$fP7!Zg{Y0ry)TIs0W>!B;^i7T{!(%ps4{P&i +z!(Qpx9{>_^D6-+OP-AFWDO3=Nzcu)64n=n`uU7#C3sGL>l#^Pp%BHKe`#7m_EbJ&g +z-!$B5_1uD+vO26#psjcP3G!iDDQ8$cg6zQVfNRNq(*}sCNZUY1iY|=8QyH`;kv~1iaZvF=Z`-gjA$d +z&Z)~crF>@-lGq(9;!T}86Rvj(GzAp|V4Of1L;fT~ES)0PU6n~Ql!2`x0e%7m6LbZ& +zWP?S~jc`O%Nk@}eSV9xbs5GER7$83buq +zkP;rH79I%TwDIcYY)@tEhRe%XQUPOdDcca8Y!b0mx$lTXg%~`u9sky_<4&4t=HDVB +zXsK?saV`r#GhjAxZhUn+`jJQ@Z|WxPMAMtja>@e)JX`NYAl?~wqG_LBX`9tjX7*rr +z`iUF +zJ!RH;lo2L*JTnc$8wGZsl;NY#Uk*1nUFaVUw{?vguj^5++=ckB6zNEFPj45@om>Xv +zfDE7uJubytqjbP2jC6@Wr>$w)Y~NEQypA9OCg!KTC-U`9H~y8fEGFJDus3HX%_N+hy1&?1&y1GzOM!a8lvzVxgPq3cSa9al1g133}rPr~kvs9lX3V12B;vf`po +zbK{WH^w9#4&R7fyrXS`J0?y$9J$Nh8_9h(tYjB1MaR~kUfAa03NsscI9A*x@AZ^^N2tiXpP`$>I>cu66QMa +z8cgvnRzX|dZoj=W7Y%@wQ-g=wQ<>6wX>*N`b5e_9h@oNaj4o1lGKR{gmV+Q10HFA3 +zgAe(&hS_=J>VzgJd5w!mPQ(XH&CB0SFEH +z{GB7dT1W!l?+2}-uvV+lgISyHMN{H;Tx)4JcQ+lf#@kqZCeH0aQ&H_WTrfgUz5-(>w +zBkjJS$3IQfHFs_Bf(EYPSbuDDk1g!>5Cn2qxcT2h+@`#cN@|JNgJ%nJ0?d==1XOm* +zniN0DZl!Mq_D;OwCw& +zHi-R~BZduc<-IBL!E#H9(+WYQ-M_SzEngK;A2PD!zoG +z`u@XTNmMs)z9?~w9IrBN(!4knmw5393AZ`?^kWHTLIcuX0pwR}Vt3e)mpX>_n$IMO +z!Ie_@y|n1GDL2FwnWOAlA~bhvl9Ha@A5^Bl076HBMly{_UrK{s@rn#8Dm!NmF%MAFUEXFHI56*rr!t6|!Z? +zS5E*Xtz)t^8rl(p48TWnFwyc)_(FzvujB91T`xG;D{Q)bwG +znG7bJaIIqjt7+EVGNP$a?B!$*lFF`5XY9$)A{Olf3<2RhnyAVsl$Wu%W&n_dzo^n) +zr&`O{NyzZU@p-;O`msNAsfuot{94xCaeC=XY8R-Tg8Dd_b>NDvC9xnQfv7WPSEex0 +zDOhDH#(Oc0o5YZHvx6D2FI+B5^$2gE{UF9JJq|kPi2f!BVmQE=o|Y&QKc<=o*uhEA +znprV5AzT-1x%BBgKG>O)LZ&X(SV@S8u+052tkx?hVB_x7 +ztbY~`-L|-IUqB~u4?3J@rG{Bj(JsAFUZq3(1+8~$gN@TSu02w}%T$=Tr2`H`<>o$4 +zQ)9>skcr_UbD!;Jjf8kqwPZ;FqiL5p9Bo +z&n}2W_m23Q93vD*bghL}%(!fX!7=jbSVG3|u;zi73fd1VIb*z}%jpH5UHPhFJ!3ajhhk8}y=2%mK +zV|eJc^f!e9V3ZxlAq^wjvSx5K{$}c|FHD1HBYz&72fB33O*9zU5mc28*nraexxbK` +zaiTsISfFQ{(*Gypi4YlRe=!_3QmCIybKv^ZJd-3{w!JEn2x^fpbu`S3;IN2p_hPzj +z^I#pai@22^K#}xbw#xJESs=uVf|lOJ5SqFcml(u;wDdx3+9UvB1nUUX8jb0`cseSK +z(KAeDV^#@V?k?vLt%z@fx})nu{DUQ^igtdA%mDC0P{vOi5>rjBAw!8q!WbN>AC(qj +zcE5x|k-zm%ttTdkOAXVE5J{>Lf8-wd*A#EE&`*ap0!JXgE9mw%QsXP)ALzE +zS)i|xrGHPU4m_vjnA(p-M|ckvqwI2o4@FFgwdq6l2gFVJA0ciUQZIGZze3zte?Z)r +z4-f}1jhV#51q +z6PQ#wpV40wlME73lAIvy&vF0{Z8NkuJZw^Ji~u6O4zLx@?UIJY!FYB=>7<9}`G9Ky +zjnN$E?aZ>H4*nzoQlxO4wHbA=*nq^=gJUU}JC?!X>3#czgxt{`gLngc`zK#7-wWBr +z7U7i=@?PHXSk3^<+iM{V9qsp=d2UMUy~UAAe&n|^u;R}eF-(l3XdQBOL* +zv5yMPPl(lwMyK_|&$SZz(ZFImJ=oa}(!jkZn>W57Ak7^K^Y{X(Qq$Gjtf!C7D?=t& +zNQ{7-@%lgxIqvsZl}1d_wYL)we+m&jX!ZUR*S|vCkpBd6$Nvf9hOvcou0S@2@DDB< +z6dyl8f!)c~?pR4U1oCifZ8q4E#mNKE(MDchFH>ot+ZGw&;*)Y2Na>)Z-c8y~l3YOwa|%uLD|;d3EyW-;$TlrD4Z7C0XJ0!0_5c<*7I4Pt%j+Ro +zIymyjHKJGJTvPxORAAE+MpI8Ket!!RV(bHpBtPn7u~-pSEkjV4VbXEj!Zh}$&}lCqEnp5R4^j2) +zUl47hYA~?F(&JFlAir7f?F78|tAKf4z>mVJ+_fY{lL)dxYrhNH({y-BH%sN+vap0)NVlABfZB4IkFZ?2(via$rI&t7+I@lGvWzWYD^ +z=BQiVYav?e7`$Ey3}Bs5ra=-Po%3%t26Co#gN*B|D}nAlxLk_r@HwSwCC=f%SoGmR +zj7QHSG1XZm1pGa6F1-A7B&bo;d}VAsoC>iB9s#Y+a@uh?*-iKL!^79R^=TXkGZ2M( +z0RjdqAjt2ZGo@y8(o(HrGEMRrGxs%l!gVl-Zh~h`U+{tXPhXZakv!rx7;%2T{9cZW0i*ZIU1H8!RmsaKZB%e>z`Xc?#;xc)7EY?^-CkekOX*h`Q +z@Cd=L<>)tv)_~!leED@e(<}&|QV)QaTVsLg(;SfB%UG=H>g2FFqFliX`~l1^O4WjJ +z9;1fpEfss_+Q1&WoiwWUCgJ>3UE6$8*KL*#gg7;W9>_zyTHzuYe78uXd|Kae0Qzcp +z@yrW;aZXmO<~@Qu;;Hfx@(TxcVOXUD&P%-&b97zRy_1=^Faa`!`{5x7G0)5amL&$3 +z-TO~w(yy>qG6HTDda=lFGLzL_Ei-SNXsGDbZtwpFCY=kTl*H^K9%Te&F}Dogh=|$R +z6hID2hYnO2wV?O&0I(H@p?;kA9a(I?@0 +zFkFlcqVaz;-?Q;WD96s}GeJ;XtC5zfu2$<7{U*R8WS{tThbr587M7>jymxh;2CCtA +ztW;Y^oJ~@g#%jHWZ?+%f%VHXRdT4ne$f9d4a#<0R2Czj|$6<^pST&){r$Ruw5 +zrkmMdKB7y;4GJ?@*!YnIg)I(sSqK>3t&R_g4-bXu{kve}sM1ft;Z4rsg=NOkgh&Ty4l8e4;93#;bRIYX#a +z=R5FWHGordokNppK+b)H_Vr{G+lX5r$%B8|)jVFO1c|uGq3~MAYNn8s$4V}ZemCFi +ziVA@Cqg4BezZG4nMh7P(qtn3k0G%C28v@cuM*;7V*(i8Y_6tCD{3iV2fZ862Dv%e0 +z)~;vU7gUE`L!wC%?o0o@E!?!w_ +zC3;_YU0&bUo5!)G*RS(5rAziOMRfD+!)i4Rw!?QL+X3hE{&C`-?JpE}owwitAmOK5 +z;QDay+2v_bH^4+PJR)Wtu2Z>Ia{S8%G?gzwFRjBls~&C~!Kn6a~cas{Px)OWtpT}4e3tCEnEgsP}qlSc#>_~QYPbp7by +zKU3TbE~v=Z@%hWRKWX%RoCC{U@iX?SYu<0tZug7WM)H$F03%T=@eq~)Km$X=K|QH^}6Lbr1ne!Fyzm6;Bj>oZo6Eaa$QqRo+rjrq@NydES~sq +zh9kos-Sf^JW&}gt&dFraKcBB*?-py|QXOI(YYYPB66m9=hrP%`W=>}wkHHTfS*5~Z +zK92P`^|o%2`I^|CH$q5C29*&OrH}I!f$#Y|-`4iW<}j#>zgesQ0BP}p?&_C+j5iar +zu?3fC%CE;R=rdg>Gy3X*9=K8VUaPHjTu<)Y(1{BWutN_(5s>ZMmHwy;tXZIY{)y@l +zXHG!euqH}b;JompslhECxKlj!EiNBrjE&RYB#r5F^8i_hH68(&*2O%t93*AP=m|#= +z==?^dv;^E|bIBRQmFt^TIzYBV3}B&Z*C-3`j6J;)2R|;bi27EuoPocWYumW9+@^#r +zIyDiq;dzvy#Y7&kg505`JLX#E@?G!q}dF&mv~spHN1ALt$Kv#=`u^N`;42At^S}zZd`!Y1-`MGG(WtxC1zMl}aXIwnIe#%c9ZjGY+cPR>lyO~(g2rNVo$n^nVau!dhL +zppH=uHITZOT3yA|hs~#z=piTMLHwfj4qN2YKkXMbD?a?UfHu>7=$u;sl>T{KLDzxA +zJ5bIhNGKQuFeZGY?MT9}%$6FS2S{<8uxui=n6SwYcQKfb(5KiNOTz&Cx96o6WaI2B +z=Otm0U)bN?KQIp(uuPV6QdT~kZSfaFj?eGC-`;HB6M*S2ci4SjwtUzz&M;v{-9(pW +zW0@dVnjP;`KHu@{iQ!qCr;2A}N8d4|&UM!A&+9i%47_RGKc_qmt2Jl|x#mE5Rhfhy +z?^ApheN(2-<=FU~8ZW%Z(f5Y!-Xr&z`0kG9*FrnfbMms-UVpwGM8We;c>IbvZp7a@ +zkG&Q;ggt0`K91%vW4XZCSEtRLi#XvW0nxTjjGY=>`?VII-7ouk#~|>v+<^3Kag9*d4W1^jGr?ps*dSx%*wTnbbHU>ZjRT-HqPaQ>L(E +zF~n(WwT5zM=)yh*c<0`E+qc&&x4u>I=S%dycJ5|9O*Dt>OsKLfz7JCT_Wh&|U$WeB +zJI1c32j!`!_SdFMmx7lxY+pJ9_bTqwhp^MlDTzViOpq%_N+*Hy3QX1*B$U(NIlqg~ +z3CViNtYl$45yLy4n_ek-Rrn576Y#(b&ji52gRMVxyt?dGWL0$y2TIAx%kY^w{O3Pyo9H9~ +z=8JBQfo@KJr?`v%9mRd}SBl&DV*?r$Yw<{KHyK8(0LnY=5UP`*er1EZxLF^s&>NsE +z0V##nw+KF)E^6G6S +zm`4K7b>4(ateYJtq~}QjrMoV|)xP)?TmJkOJlojsK7_9|?T+pc3u|Jl&s82fvL#fr +z^|i99U#pJ9^tNM5b)PzP`52i62Wo;vjKDZ3xstiOl7MY*5RIqVOU~6xH*M?$84b9sE$@Kz2+QTjDrUU%u79)Q}jM4b$Hv% +zLr+#_arK?Qd~@glt(6z?NFBu!mU^ +zo*~l>(h;Yb#D`kOFA!fu=~Z{FdNbs)|0&9dL;cq{BS#?QwfYqZyPo8a$d~ttP^5Zp +zKG}`FDHCx{up{sbj(~US{p!eIh2`(QU0nNzHtLK;!{<)x%%C4n*-d{y+%NwHar1JQ +z!X+nvjqUyhaXA%mNhNZvR@+nd7juJN?v;T)kH +zQyrrhSZ)L1Kz`EiIrE|EGDGRZ5@;x@CgZRA7KG!&D}zt59eYzHW1Z|9^7>#Clsvg+ +zO8>*jJeSA)mu&mnIXS!oN5b#!YJ&?os`<3;&?^ZA2e}K5b +z{{nH7{~hAq{r?SdC-;E_#iT&LU0w*Nx}OfmFaUP_gyYK4#DC7g>=}40%rU$7X!SSi +z`#Eu+dfA8^Qd8SLN~bS|XZP`Z{X-PT3VF35l>4o( +zNDb04U!!<}EMZMJB?=^6eZE4-L5R2xEp#NNskudz)AEb*KCl<9-jqAXwyznv0FRga>&+ +zH%NYYfBbIlQDLAK-ykkr22~r9+Owa4oA|234z;P$ocEd9Ix~AU_@S!$60%~FqdjE2 +z?k8tkD@XVTZ8q!^sCO#tm*EIOCr^|VY-mceNQ-pIzD9ZYQ|uf;F{8PT|8=e76?Q>$ +zgq+KF9w0I;i(ISr32V<2fc~KD2VW;ji{-HCv#j!7MkaHHflZ((XD>L23du|+J=|J| +z;Lf5Os>9m3BJ{-%M4G4>mRTqmKkXlL9jy)FAfq0bJ2hnoSbba-r2^m(HAZ;uq@}En +z^U{5c_FL|Af^XR%DI*Z}P`3wrE5b;2E`)c4fI>7mm78VI8-g|tOn^H{e36Y0`kZkD +zoaC8%vf1iYYnT7zaF_ir4)-^E0*(V3>a4F-kgOFi| +zk3qj59G?0q>NT5zlC6$COJ0M^x7nF>;O&ls@quDE_>J~*O0@2VbTq&0^h%~ZR9ztD +z*qAo!j{^_4jyoiQ5|SCKVm^O406nhpa0ONoNW<=|C=QMz+GjI7ATOAMmvFDA;~=^S +z1qR?b@6j1{av4@>7cBrSAW(CQcZ2KO8yh4Jt4ATA2tDmWn=%iPAZ&{&A1yH@eO4 +z(2`&B0iDm?kxs|A+^ne5hpcI3;6~@>*&Japl2EL9KWkNkW+!$H`XjU@bYg?+Q%ktV +zGVlUrC{ISvsj&$09Jvr)kVg!r68A9l*lThyCq}0D%5##MFqMe1h({a3JP1TrKvHQg +z9R6pAo9M3&x8B%a9B#vPH|67DAcQNN5}Opb1+V!M7-tO1y-n~inj?m*X7?v=b>25m +z@pyS50Gs^@_`1Uo%H}^i-0?4_P=9y0-4E}O_#L=TvVq +z4K{V>8iaMxN0{=v5%I>uAhh)GLJE&^*oGSaob)s-a0IDyeYN{V5phGX#6C$~NlhS# +zdx$e}6B`yhtWgCa+pDMtC^wmC`wO3jucoPKaBT*&X#4Rr^~Fy6UOQ!XFF&vvO&P!- +z7umejGK<6k6kq(8lWR=y2v^3v)&oS{#0<%gG>Vd)2YpQ!rJodba2V-}tB8yn}N +z7*C1C8hBUbbCPr6a8tba}2b%cc*5cX;<2ZfrTfr(~ +zwu~9+n+)lBeZ87}pPUD{lOsgO05iDeZsFkD4#Ffs$FN>020M+IeQMD7r)^O0i}$ao +zFRXYI-C_oCt8fg>jO%+3QBKKZP4fEJ7r5cLp%f;o0z&NSy|vA*TcRcRw}X*Q-nHgK +zLn}RmudIT_I}(DBI8&5uF3R+XykI03zk_i%?0U)NS>&|?-~s#wxOpoGHeCvxYYpWJ +z?Ps8k)qu-_L!7qo83|IxI(TJYzt6zO9j1JKscItD9J;6?*nP(874huUcammQ9|dHY +z_89g6KECCjC$xQkdLm4t6xN&vL@O^T2o+8V`zmpOV@^A~)`U;2O?$ZS6w>qmEEqoE +zk`v%zu#QIvUIJX7&1`A5QaoNGh0}g)N?_`bStvP+iHlLE6v+B-4mbY)(cyOQY1zE_ +zpdSm;O8b_y^Kl<)P5$L@vB@xk%l6F={vC!OiKNN!j5)10Xm`la0`ye1zCS_>Ov +z^SW704i?JND}WY>P3%~rl^|@b80sg+8aSBZTp|lELf+ycbI0NbY3U8K<$M0XmAzjn +zDHKw$F+3msie>WzTIc?3q^FAc?(Q`@2J})UbeBHmlVfKWS8)~WLjXDhx#KD4?@Y>q +z*HBE +zHj_xxr^#7|ka<9yNNm+Ejol3L8E;^ume>wqXa_lX3R$kB=I|%pn#p!JPOXi@*YZrS +zg-9-jQuss%*V^i?l6ny+#8kc=LC8S~G*2>aU!F6DmhT+d2gW#p9P}W&aOv@C^^J3E +zTw|cI4#&sRl+61wlaNC1C5Hb3^{Qrom82d6z=0 +z$crw7fckbGwB(sX)Reqg#Q{K=?%iBJI%)7Uc`9B}oiW~-&wLgf3_@b`*gh%557ClS +zC1_IO!q`hc!hpl3@^}Dg7Qin=dT`eFqsb6Z3KduQsc)%h`;$noBS`NUANC_|I%rIGMu +zh63qP?2JD!$Le({3V5yo!v`1H>_ewhJ5*6xal>5t25=0hxkGx~PvQFK$2__&BKa14 +zQx3%|!}-eWe+0B-!nVlVYF_K_+|4C%@-}%%b7c~E(zOK8OoP?ooFENYLY^jc&@GDJ +zROLOVjDd{pYc&q3$xjFs_d53LAY>`Pkh0DB7Dof5*SvNJjiwqWKNz?R>5I +z^Hs8mO)au9-S2Y%Uy=U28A{zyn_VEAu39x4p6#^;LQlEjvs6>9E{SwH6D|i%1*d?cSG_S*f}U_imvIij5k9I +zsz^M8&V2Npt)x>tFRA}EfXdwAti`339@fQPH8FNL+MPn!^V*_`Fn{_)hW!PI;YID +zCsAqbfDSl>jV3+vEC`;E;N`RPaC7hsIpUIG@@H{?7gvfS`g8$^yilsb=iRHQKXOeO +zp`C5ua?crMrxWC6X<`7J4 +zzq2MnH#ZP3zHij@NsHMJVA9cA@bqeDDod9b)l603sPPA~N$XSYpH06m{0W>}@x{*y`n +zNG(BVBW>&PiOmdTeq$9Sm`YSCPDzX>X}A7Iv=aG1-DHqyDz_QuR$LS&zkWSAVm@OV +z(uC38hyxf^@YD&%Rb0b9H!A}{#q_d4vp_(QmmT; +z?lQ`QKL$GHF>pe8y(BQ+1{r?Q0ppeMFf$W1E7VwE?7vUca_~ccyD9?7p_sRW+g|JG +zc@L{%Puznfh&E?B{R)sa>@a>03u@GtrOfQN0%icoP35+{VR1*ZxEA6#FD9toL3aQW +zSJazx@e=9@;J`mM`9C|{_)$xsxc|oCmi?>4P55_*yZG-8clf_`xVgLk;&2Q9!{MI&a=07vV3PmlaAyL$5tF%v +z?P6K04r8^g=8Qz@Dx&r}UJ2VwR8?fw-l9!`q#QjShz(mEC07Q$xN)tya`kUCP +zKuZau`TF|-tfPbWHaVT@%lyOPzVQ5$!#(%qaJMR(L!=6Sl^jV0*~R;i@;d&?q`r}d +zK~3dS(m*WORg%P^Kh`N3_$ADzHC06m57sKQO2mj7Vj{KX??F +z_TXJs5LsxTA#7!2%FgF2F^%H6GE4NkKujq9tfkw+X>m5Mq`}J0vGb-9kd&6TPSek% +zILm}qNXq{d*t!1%2m1Sl^#YG)bV!`u)YB8At7wFg@7vqo9PZ~oJKS6h|Lky|{mJ15 +z`B#VgkX5IO1gc{k<3+-kz!cYi&DD3C2bW0csfy0FX|sBVcYwT>wIJ4%RCA1gm$T|4 +zZ~O6WxvI$DMb4M3BKBfEJV;J_-mi1$BEm`Hwxo|b!Q6L$Y-fV3Wih}j}I +z_DTo%{PP>qB7`^LwK&u3`%PqN^NLh>8}@Sm{ZjkA3&+%{34LNTM#Z`-=DBN%Ngb#_ +zw0EUH6=mmgHIf)PB)!1UMrBj>4Q{M>j;;`$u?fkS5Pn^*M|(Mj|L9x-KoZXtTH2Uy +zwH&t|pz=hN7i&&WU#?q(X4UB>PqKe9I_$ZLQe7g8S}$#V8lf*m4i!wv9DJiH>rfF> +z841Q!ajVpSGFwn$fS~KiPD?l)+aZY_2f;sJFdA?RWHi-B7^oy>y5CPD=9omvufEcY +z$ZR?N$jTYf^y>SeJ4;8Q;mtKb&3ruf+4b2tz*;fcW(StS1o`m%(&e;$Lm$-h!t&+v+&!xP!^7b7tmi +z{ejwb)!O%ZDwWgC9yp}d_zmm@Bk`O@ORD>Jq==KrX9}IOM>}jZZ1?f}fzo=j6D6)} +z=_wxg31nX2R!7sU*u@NRj{9=B;bPx&E<>oLia5lN$RX~5N)%^hau(+wZO$Eh3uc83 +z7&Tcz-RYR$?W4H)J@X3$*zx(kjH^eiz!{{5=U& +zCO@mlEkQK8WcuW;G)DI=fG?lVv@}#&WCkv~xoLMpuFG5OVQcuu4k0UJ>)eJ7FqlK! +z+@3&}0lkyQ53s!w2D1JrNS{Z@A9B!!G!FxZ85hGb}#_11khA)S^O+B2Qwd%W8 +zJ|Xk2hVq^IQpA_Tje2|*_P4{GUhw5`OCK=py8jYDNoJs|!NDnsX~P1a9)vicfTzRs +zBXBWhP%54;_sE5kQQd%BiRiU(P+AKf)$Kc;%J^nElr66#?p9>-<1|r}!)Zc{c#gGM +zgB|q;sbYC8IW)f`?8zi2ZAXNO8@sZH;!yN6Q1Kxk1c9iYBMNPlDs5RE)8Q+tQ;v@iZbZqKuvHddzu*LSmA%cx60@_Lc<1qk@7Sh?r~1)j+F|&WA5w`}a;U&ND|$wO;m+;f +zQ6Rwb`@Q?gC0+^(J$VzXAvgP+Hn|&G^uB5pW*y2oJG)#fsXxz>bHl*^Ht>{rO`?|+NAet7 +z8`ED7w~XvZ+%(RJjSD58iaXpt4mW^df+F9U%dHNG`Y(t3Ya0XA^?w|0q|@NZe;n>( +zk0zeK9d10x`&_IsUNYam9Pa8|&6qET+m7p)DqP^p;qK0p``h8(#Vl1!I)Wqp+u^Qv +z%paK{;Z076&8n}6y#?O!c_N;@x3HnaXCQ6v3v +zm9-Pc)d-8#0I>BQ#ex={HqI>>{&4$V7&j^k|Chtv?34Jn!>z@zUQ9U~C>ai;g2`+L +z4P^wU)v8Kw0N*22s~pnN?Dy8X9}2@d(^n%n;_X2bM;|wf9rtJY7@3M&aF3tcvVL{< +zu?RcC2PC3ire454133TN?AYvYv+V@jIe#t|t(=!HhkK;n(aKMwc$Uk>*NL%0Ihs&sAhV%3+! +zZT{tObK?8$2vH^W739Dv{*obT(pG_W#Y)&Rx>QI|oZuJwO=GzXYz3dt0akaSJ&Qs7 +zyOuHJIFAT}ycT0LjY%qUO+v(arII;cP;XA^gzlxbWl$M{fW{MNGgyoZp<-Jktn$J+ +zHd$^1Q-cuPf8La+ee9W`$e_V`owD-&bbckcJ5&<+#zFIq0d9PIv(3Ez-g;**Nt^KA +zW&~M1_HwTRVPokzxB*^QkP7 +zq{mW$H;u=*5(Q3Vy?k!aNeH#m?kU`*Zw&OJiu>r$mld_k*_aa^aHMdv_Khg27hWkyWzK{DqeTzb()L%z8vm~zZ`CE$0(eA5YZgW +z2cacBo7cXjpY>K>4tLfhl)Mri;lB>|B{KLfMXh>a?EmL*7cbuP|Lbt)|Ko7?B6DEn +z{N-@Ru7myOaEJWua5wzraNqsoaEHb@RK9|FmLUq~d!QCDeL386e>>b*F%5q^+%DHJ +zc>g)vtr8{{``^MGDvTZn#hS70U8O&ywd3z5B}U~|CJMW$e@IU3%F>Dke0J5+-TqVn +z{>65o*-HHLTr-Xw|4(C}O?>irSTWlI76WLOfMMiMP%@V1Kp2vi55hlv%CVb!Bq>;^ +z_aO#Jz1v|LUGHWH313tASRhrA6j4mLAv1_b7NVkLGK(B+ +zYf$)39hhT~n=AJo#&9O_!x9|&ObH}R*+yyubbjWNKyoBO`nP-g4K1-bXD+>C^^tP4 +z8H!;Z@7aG2_j6udr`1Rl@H7lF1Ub;OV@;UkpFq}#*{s*R38}g6de3Erd!^yQpNe3UNr}$ZaTqKf_#DPuhCy0q +z_USDavBYjXKZQ#mj(XDa;3WB+qnQD;nZ>j~xr|Px;6pAnn!#7K@A1krhshVCxBJVc +zML1#rOEg4QyE=v(a2XpMI^&MIb25qX#*^fNG`6u?vT +zW@Y`a!!4Nq5T`^CbLsQ-^vWfqML!wukLMiGr5PS|eJsTCRkG0UJ{EW99rE#1fr%|B +zGgM@h!O|J(2s0oz>4g^X+x_Y@4K{^MjoNX08Mioz>2Ox{lBkQ(kt3;R^~`c`qnWr^ +zq7pW}(~YD8hS*rbG^BAcq0ywb>?DxTn5hIdcyq^WS-{ij{=PuDCK_r@C8C{oF*i!n +zCS*s@nznl=3F_+f^Jr3a#MwJtAWNjiEHBoSIB$3Nn334g9$EeTg)cv~!+W9i`3XMg +z^hAGtlJcqg5Zo2jXB9vHQKm)dk_8sj<&@A0=y{w8iDq%+miY5&^VFCjU(kv!N^Gd890;CpwY_V=E2C=`Z=V))E0fYj&T|AE_JI^KU +zbVXI6(;Grzz6e&Qjyc{S#4amjv*pny`OOlm!(-529G>ujDKTc)&-b7REKhS^(lZaw +zDz)%~1#5-o?rz|Juo(tLe5b;ZRr#{BVgSP55Mt0E^c~e)-inN8mJuOhrzpn$I6Bn=#lq$QFp{1J +zV`w31#~N2&D4DavLskkE2T@7~L6{%|o#6wrRsh?A)6$Y!iq3uK#WeXH9q@~kajrn@ +z*h#|KMnA4%Y@&5`W;n8=vPUReTH$n`N;b1E^;P}UAlmOnqk`J;feLGWCX5q-C=0S7 +z+FcoX;zq7ea{}$z>*`!hng>P4G2b1G(TkznFj5KC5sWCS>d6nRbsU{AuNuq#eql2V +z>en11QIYsY%3iA?-a#fwOY`Q84OQ$3Z-olEvmCaZXzS9u%<`p>k|795iBaG~!yx0a +z6pEj3XK!V$2DHZK3CQ9{)uLM2Ym1!@XqLqXh|rrWEsZcX5AE^n2}&%e1p +z7_#4MqWPoj;8-l>fP6Z^EfvlPB0L9NKj9*hjzcj#BK*Z8w5$t4zFLDsaJ=H+2nWEA +zKV*`!XckR!V4*$5wwuwvY4x)*W8-5t`&DCpOrA$BW>>OMiq6Io%nQnj-;#OHLm2CP44} +z(|oKU+Y;+S1lvBy-S5#?jy*;{10aD0(f29pf1mSZ+K5bSu4WG3WJSJYaxWGmj-V1s +zfVM8+hdj1I#Yr(M;b3Eg;Y+rip2wt1F9vTcT7xtxaA&C$I2AkCMhbDv&bH1mYcrbD +znsOh-o%VbBm9(A!186qlbUM;RqrrIHwU}a!d3vMVF^vx#fU-!_srB($A;G+6<&YhR +zC7CC!;HjBo7l!jRfz8kR%7g@mXnUv}z+a55XjKlV?v_!L7!tGdHS2*en+DliP%sG} +zE7(%M=G3j2L?qxR-cG9Tdg>de>p(wXU}?A}Jz28RVCe%(xvlO7p%Ng|7)@s--%&*o +z+q2pVr|Wi}XZO&|JS~e_A(Q;7_b`=^AVU|Uboyu2FKqFj$xWw6Xv|YejJSuZKw;h6 +zk_*n!gk~u;o +zufT2@(w&Cx!Uq!lD$?`|Im&;pUjZa0asGz5kHG*aM+G@;PqO=mf=Uu?me%+;(}OZH +zcpAHPjyiZ+HO}~=OwB&od+h%Mar=>fLEJBYLEI;GaHv|Cvp{4=iI5)D5)V9NB{5*A +zSU;zFhEX`FKw6r1%VFO?I?3%cdRs`msHFxiThJi+(>g}D3k`CE1- +zfH4&k9zyoo#{RIF?)=Q6|J5Ec2qWI-XObA1_EO^9{yz|R#M=K0aXYdx4R49AW0FB| +z$W@sehAjbM!OwL(14Is1KhUEa44}e7Z=u~f6|qzueJM2x@pfhYg}7nO@#dp3_VweY&d>Mw|!@C)Le#r?k^?gYx*p-DY8Wa)_Qii`;(f0?FEv8o0h`=mrT +z8kdtYsNp+N$5O(^c-qAhPoaY?l3{rzaPa%?J)&S-TA0nTp}H-EZrah +zyDIptUO89IWi{*$e!0g9LEDWZ9f(g!O@wR{j8eH77!04Pn?SBKo`?#L0l(8qlty?b +ztZ)o=2DN1i(4ZsfkmVCpuJ^TS`f|Y7loC2E5yHaxvR4Gk(J^Qr+cARe86|YA?)d)j +zRXQyTfAB!Tx5r%(*Lfy!SmCs1xmPB^oT@vO2JhtZN?dG}?xsD|>mcXROltmCeXrIM +zGx)YPZ-SvRvRtWcN1x4>0zw_H`l^)8UyzZd7)Up`uJkQr09vY+$QlcEz^%^)ogg-R +zQ9&h&Q;4Lrt(~9{eB&%jU9duZh5-ym!6kl5y*NlIekf`dZd#KJnH$N;!9%uBnUsska$HlLLAmK +zQ1EW!g-ZwRqn{?$b>9tgSMV5VS)PX|ct8#+KhnCg!&E^e^5kuO!^mFliFDl6o_Xd{ +z_0%0Ayl1#Z>#Ua_M&9f^^i|cct*X8q{|9l${tIz;^Mw2bai{+Sam$mslfL{7ac8<9 +zY3HHe_)YtTO|oiff0s7q)~|vdyOn%q<2X4hBjqjMPWlhx#?^8^RnYFU)&Xckh$FS0 +zF9uy`y#1uKiTLhnRSAnYP-4^!gm|X+BuB!V%h!3>{YqAgpq6DhVXMVG( +ze@+ig`d;jfk!vJb^ib)MtFdJGkf%A{9(OS(a${}yX;e01^kaVBNh^2|qbtO!Yi(c1lFA@QMQeid~lSfF2)!r?~kP1Who-y;sx#;5d=f2~0cV=r;#@W+APRTmfsDaqz +zB^x@(#l$G~pqsj!B_D$>I#j6|AJXp6GhtLuix~+9Q3VzNjQf@+c|;xNYuRd^>_( +z3qSR8us8^_o11D2y2>{)s<5H)L~YHL%>@z9sw54r?|6Dp4qrw~lW~V$IJ;>qCo3%z +zCd)D-F%bOVF_%(5(yV?DE>mzXM +zDd5A8W=VzGMsM%@x#?MjCHzNCRdz_{FJP3XTJN{_ch6e^48}MXCUs>MSA8JZuy4=5 +ziDo{<1!r!cvm_Ic#8sJp`x_7xA~zRhP;`F%J{C`atl(ro^zFIUbUa4HTdWD;H54&v +z9tOy!_@B>Cxt0#&_dDC|^wt{h+V|^Xt14403FX1eO#P@D(!1K?F2-=@(3%?_bcqAS +z<9}})$~i*CX$39zuq26!b{yNZl$8Ic7^p|f1&`Fl +z3VUDSTbyCW7A!_d-r$HqeRmtR_m>QEXa9M!-ffB^i_hO0s2zB~hkd&oBd@#Nlq!nk +zlWFuT-IXqH!iEz2xR3-5JnKQR8%d?)N_ycBYlW>93feCtx;`-t`^1fP1)kU@etZkZ +z${;+m$W13U13c2tp(0yqyCXY!dgbXV9ZQ&`il1|3dEqygrn0bTmWK7GzzFNR +zfzx|)m#&NPvKsbOnYfpD^Qd||uP>zbLEfx+1Mg-3>{2h!R*A0u0oVR%K8I$eGRY#o +zzhKw|x6S~4rT24~;!$Mw+nGh)oh#$)gC}@|H?tqX4$XTH;`jPsjRfJy9eZj@RDFB_ +zgHP-a66*xm+bUu)S~PpM{Z`y_gwCrh{Lp~Tp1ji9D*Z$=T!=yLkP0|)Bc7jaqbA38 +zO|fkG?JYTmFKHTIW!!i(mS5ZR0u6MYLCacnURDMl4qGxal=e#~;$do+5`{4fIa@Z(|o`WH30nbLT5FDz0(xNYD4)i +zr%#yEm5#($cPdXd`k(&f%34dl0;%4<5w2TyeP9t~ZK=`fQs_%ly%!U&j31T~vhcLV +z)N;g`)0YW&X7QoS9)a;1H7Kl}#NA>^=#%!?_3STQ|$GAu77 +z6`A +zL<<(K<9)$4vjW!gi-VD~w(4u&DzWF6IX13V&Ssk7YHz3G52f`Y6-;|~`D$9*?GvNT +z4ITrblb3Qv_P}#A#-x8HXHJJ&g>O5mcFCBjU2jo^-%bq;A65>^c)#{Kn1~AR4(p$y +z>y}~2nL{#V=Lb@WKC{a^-(a0)x9=uOP$|r4;nKjx94amUXb%}#@2Z5coV&A~qJ(0L +zJDCf`(h-u#Nt+nTQA|sDdE&(dKf1z3FQ9u-!P<>n7Pb~8_q(<@%R)lHT@A^7HjK2r +ztqx`gSB&2Oc3~ASQTxj}4>P5nbHF69O`Ilu;^ibsY8ZTUPQvI7%vviQa`l3@0#|f` +zp<*=hGGwFlK>h5uWMA|s1@6z2w=v?uaszZimZnok~qLRGhC^O}#Pz>~@E3KsGwN`Ox?N9=sPq%==Ur +z_7oBkvm%ANy*h3qcsEf5GJF-@i~uRAd@?cL2rtLaCGo9t9JH}T{lL?%navY7zbA2u +z$^d|K-+0`$i(Sw63$a=GL18J*g6ixSFJrPLeGe5#a7}Ibi*|pSVARijX>ijpcXguN38W(avW(sn<{^p0_jikI5c* +zkf@8!o+=jn7H64CkH>m*zy;HZ{GkjcnqL>^y?&!Na%g^}rr(v@2+!H3Mh{alWTqv- +zdSnAzAN9v+2^JGy08F9R4mEPYXAT%?Zf0+Jd{Ki=+iESUS_aU#$QJUJ=;=ytzqD^z +zX*Rgp(myi?Y@G?ps-DXuLx-TW2*ZyRq>kp5mv*y=kMM3-^F_aAn+r?faABX%J=Y;u +z-GvMNHH4b|TuDpnQDk@9wBCd7pAd#biu{#XnY8l&MCBu_Q=EJqulRtPv*8jsv?E0%fMqH|s2^hO%;13N(7oa`_jZoO3vCH|il@Aq9gI40V>Q +zn~9|n|JVm|%k0=cjXs7llkhi4IKUeC{FPb8Fuo9;at^^I)>!^2=9~B0WB`_}RDB3Et#Qkj{*!d`Z6{=f!ED*!HRB`%k2>3a3>ude0j1{}$jC)m +zeQ=P^YH;s;e_~U*OX&u3Brl+q6yLs5rYWf{V3gI4xdTor@Fa0@Kz-jq{G +zSFt$@nMORv>@J{Bh><^LR)^o5WGmA)5}ZPp>G4Uv{a`Vb8875%)*p=bYHxUL+`!Qfv8IF%rZc|F +zU5F&{WJ(X%Yrlhe{{GM#c-Tdke;~Ebt2HREhR)J5P)^dFV}i+hg&IM>=RkNSe6#{j +z9g(#m!I36%Xie=HqSk_2qb3+t?QdVw8-V$JYUnC^7q=;s6wWY(|J!Xk=}5rd%>(%g{2eo7)bfOqxAn0WYdx<8LaLo|n{ +zM8@TPp{lro;G``aR}`>JjJaF-dbAd&kpik~<}nbkK$?!IfkuP^fiuOhl5(9$Q}V%^ +zwAl?ZFMuub +zJhq5*n$DcxXh^tmFkn2T1{if>WUEo=c+IdAB}t7;b;SwZYWd4zgK^02?n!LYoH*77C8dQ +zrK5Gp0fuBSAaTyuzn6;3lXjh-2eaw{VO{)lY?>)lJ}oIT5_uwv-$SMD7GO@2^$Wmv +z(O;^_>YQ8nd4(_vSzA*3W@t8)>P52qSm$b?ELE$Xpx^{%?)*t_g)D4`!kfFDw<`)( +z2HF;W0%#P{8zXk`0PFEsGHdB#mu1+bAc_N&whSlf2* +zw94?ExJzLD*<@x)pIlDn{b8o(YV+MZ9+*?m3-)o^RXjxKyeN_9#W{%P8*OLcc#J~M +z#oVlhwmz(fdqNM+zOVyg`8#0Y4%(|hbws}L!c0-zMu`MvoUA9Z@_U0FgGh6lNp%>fFagA_0=0WOeM;0F-( +zU%zIFR988tpjkr%q>IW*6%5>oBH +z;Qpd8BdG5Eso5r9g;JvEEl-W+3Okq~G#ksRn&^d| +z3P#f$TvC=E{3tR*%pTkSUP?-R655t@+lp(rpd6(Cp%&QGXZW(3ZzR-4ajDDpv-t91 +z?MF~xK~lIiOl#n!bXTG|1ecK+HT=A{aEsf=PiFUfK)|H@ZsI|%{-1r|AC)e$&$Ku< +zD|6Out-*VOm4t#|-XY}fmI5eC84QfSZQmD##*SIT*mGCs?bP8~T`A~@Nc*s%ZKuY+ +zse-vn+sfb;+YC#`^Yqc9X1}95_9q~@A1%Lkt&ZXuD&al$f6A?Qkcq{Rjum{mVweK& +zmQRkKVG#6ku159xh%l!Zbzm>h;_r{`ReVtoZyY~)y%)adCyl&wZ6 +zDk^_I|6KZp>GGBH=jzWjLGbfAhm|Z_@Jo9u$Spxto`i#Y9Noq;O=0f5WMsqQpc3Vk +zlZ=*KtI!sk)k!{Vk1d}SE16@Ny2O|R0Hyb^#LN$QA$L%>J5VUNSYYhFQvaGu#3p$ezJdl{+S +zEG4piRmsO+ckd*2)idB|ie8!p5F7J-lqf4W!Kf1Fy=P_kR +zGM>`;_M$nVY1W0EE8hb!kB%iy9;}6Xob(CZY}C{#*=2JwYq`f4#hqZRKjZjCaU1+a +zal3XV9A>~rcq-|4sI7Es9um4+9rMsYLd7wpNs>cB5{>g^?@x49tx}dcVa?T!X9Ppr +zyPPm~{;6HQ=3Q-RgCqb|{vV2){EOmtGN$_#R`)r31W%z_nhTuOQ~;{QIov$yap}K* +z_wD|V!XKujQeKh*>*+G9%w`cXJ$bxuY}jBJU7Nyzd}vb>!p*(;JMy-k^G +zXwiVcIwYs@1}}yS%s!5LTN`twEBV9Q9wctM?!2u>7`K;|jm)VDe1*(90U$547e@3J +zOzVh1iz7v%@jSs;(zNVCBo(Oz0OrY3K1^_ +zUwqqCOK4M;nGQJ24io_->FA5ls2K8-obA2_-X*-0mlIgF=b5>YULao!cxz?0-H*w_u8VH7-=;s5_Bc8(Mz=@4 +zD`m;Lw#KkyK5F#o>8RVBFr|o08H4pT!IggH?6njW!Nm!F-Eo}><;sn&|Vobu6Q^HC;ptmHF_sVJw` +zNh`PMbzs-7pG8j)V_caoo?wySEowmhlf8HsQ_Xx~2mhl^i41@8fEH#TU$Z>z +zW54X?ghrD}-2gF~w1!K_;00W!Xn=ySjqYtxFU<2C)Kp#AT$=!_HR^^+?ya1se;@|g +z+k1QHJ2uVtdS1|R$u6NUl8D}>^VtbDlFX>~)wGS?gJC0PnhZaLeQY!eK|U-N&oaKN +zTo+&8f3wDDN@n;o;HYn0S`?!3T<-}F0Ad)iS-&Zb?0zhE;K}C6q|&OcwB3HtXQg*5Dt4rvgQh+-b(~L*-<2ZMz +zJ|+H@xQqUgxPiu4ktVB!r*2JGM4Q=RDFZ(3TFnV4w<>Ury)zVNz$1N+LuQc1%p6!d)hpH8dOmQY=cqW5@O9{QPB1C +zhI%h(Ku(!Ls0Ds2EzoqVe^AE509TaR0=_}}oJ8lyoWOL=)G*iFF&6gS`ik)xYKwIm +zieh8Ypa>Cz<&m>GSb4G|Nc9G`WRv)2;-dHklVP|i)T&OGZL%4wCyGO5_p#|<0yPQx +zoVyciWme2*|E|ChJU&sKU$CxEPOC<%kWDl1!Q9KXKd?YQjicQ8=|wY8Xx#P8ZA^c- +zsJIYQB(`KaWYsp0Q=j>A?cQU}A8@J1V*^_JlD#CyZ7k2Vl>KW-0w$hPtZMBH;pC@y +zvCzT#z*%_9ZO2R?QBp_ZX~8h6rirhZ8>y}l+Qhpx>;!Ah2yRDf?|Flg*L{Wh +zURV37j-%MRDagn^q_^0NZ`dVE(5kr!tc+8vp%S!v0Ee1g^&g=h8QRVEF2{a=uaELsH +zL#zH2>K4YMfR2}>%!im)0qUS9g&mEFPN0VqjL+Q;u*$Ym*0eN|$OvRE%`^{&i|6Q>-7l?o_oAMmvXD@!|N5~g1i9> +zC#)*cp1@|gYy?`Lc*)Z@zNZrF>)p3l7597C%;~^jk~L|)j5B>OoOr`rAf=*NDe2Ou +zPzzZ)EPNl&sUJTiSz%<3;f@P`_u~#pl;JftGXz8P+-gT^67R`3H^*+oN!2xvKUHoA +zZ7NLrKWRSv0Tzh5q;m^y60Q$Ad2AkJ&=(|}dK~4&&~nswPRBbv&{|MZVboet3E3uV +zKIelt=uSE!;3&dZmdAcUz(fgMa|f#mY{z@j_rME06xcdaPUG#>LiSA0UdD@>r@hXf +zu?lj`IDGyFd?w_R%Q5L57%}o4>5P-v!POmM_)UO3zfLh!{m916h3eP>dz%quRr826C`j#g|aM7&Vj!(F+wA`zwt_fOIx;!+J#18{eP`?nG6m;PP +zE!yz<=mV&)JUZ~B`~jcS`KnlBm+so4dnYBc*>=SmEWkQ49pOY#pZTB6F+T4N*sXV#EoXH~0sqq@*dEczq%+o)y(5G#|TdvsI6#mTa9wS<3Zd +z%kq;Ux&}8aJvXG{W`b@z0uD|S3?6-&N5hMmjUIC1KM;5N7sOrnDGi>76s-k|VI$sa +zbl%>TrrD~~&eaN5*GVWxAfeDV$zvHc*dcPhtV5tVdjoH~P;LhWeMm~ajcWmd;I*bQ +zF~`y!YXiBecvzg*gxdph=yG5@p)&inl;F8_l_oX$tnu<~tP|adSK>HT#R&<%)c;7# +z^|@M$S?4B2zLd)`1WCQj@M{HBc8m~VeJPXIoj#BKy$cP+cm2&NOv&akyfTD280zc1 +z2)@wfRgUg~a>Z`=z+{A`EgCm}U@925rkg;KjHo4cu=#1jOvveLlnY#4DmoHj$-cXV +zNF^X~jTAH$cWAkw$^c#qKL_z9vgmld>3iWjOmCnOaMZdw6jgJs;p;Hw8ctyGLK$v6 +z%pr)0eap^ +z9aK~%+3n0&F90zj>a)MzxQ3vEj9E0Ad|dSdSrQjzo1CHsX0MOOkF;tXhQXAVN+U^5 +z=Xm;GhdZ^`71=4d4ih^rGYu^Rs@M7~U(8FO;xC7LHOywEH6@1HfDc|NI%r?r;~@^N +zPV66tyLy-@8V~C1Tb%$qPy^IpJzs`g-3fwRHenr%l<}ashppBb=@Gl3#K=>(cUG?6 +zAJFSQN8`FN`|r)3(fbXcpw>B+>ZA!trJ%MGU}vhc0K(883K)J9`h54tte1rs;9Wpnpfok#O|so|v41qJOh;(ov`0hxdAHo3cJ +zT|yJ@3R5I8fMyVONR@;g?Tby{@}8Y?7>SUotNH~-lE(yjt;JoC`$K^#!yXl)(~I;9 +zHwcHICNh2v@Gz-qHLa0DE+5B7Q?e(Tb(@@H)9SW$@97&pv*x4x0*yK8z|@$EQ0b_w +zV`Bp3iCWTFJ8Itu{fPH=1+(lCDD!OC;T|Fb`ZlzMo|FDGdPzGfB+2nIHw@qhK}=O< +zqvT7#D{O&G|8lq`zZ`DD>70}BFNYiTKZo19z4goC_WE+T8=;fv{G%k&<^OiLW&d-y +zasG9jRZTX2Naj3{2kwzwZR!_-1j-V+Y4tDU}0vn7=hBve(B+#EGHOz);;0r +zThcw!#Ced7NHV{j{3ws|488T4Po$bmsagoo +z9Boxl#h&14aiKlHrl8R2I85Hf%K&bj@^9ZHOe8_`evE$K*Yg{g4daRJy0Eh;`IzwgUPRshYm|Y6+VGa +zaQ-}&SSAn)sF~G&L?GT=-|R0{TsEJ=6IP*#s1XZX1|m1xA|iw3?O+JQophIU1!LVS +zibF+sDUSrwt_CNBsUaFdA{R&vAC#lcON0k};RM^=0LXo?U%(fG_B8 +zfx7A5s#6BFDghb=oyo_{{-?K(efu=ITKyLArlZ(o1^xqEGBy}8!= +zgY~gzxnkR*`so5oYD(wZ^su9Q_pW$iTl4uCKhTofv7;JBGR@F40CxRx`K8r#y}en7 +z+w7z`nd$lF^mvcly|;&~3M)6%ok{qD`x!+Upp +zUTAL0cK>1TId1^Y6ymbQc_l{-@ +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 +zk-X%9Y4A8> +zKhKauv~MT6ecoEg|6trTe=zP4^>D|0)skrXfNwKF0F1kReQ_EL$BvbV2u?aoNizIGZ3_N8av7~X0i>R&ksN}1MI)X&J5$gt=5g%Xm&JA19 +zt61w$CZq^D4ymcpO3PQO-${`mpkY;Cq$2|JlMrm*6J0s2Esv%24{pJClxCAr^tcMr +zFO-IMi-p|zI6Ft%vN6juBcDwFZ0|?{U$uLD0-pe2+yw%b`UB&WD3$77@Hc$=7}b9;Zrp!k+_#?NF*>5XbRDgfZB=8Je^EXpcC(z`wdhk=z`Uh +zl>!lvsAT^O<6ePsfV$mit%oMvJ{CR}9t>9J*XmTp*cG{>e9+*w +zC*&sk2jgA}Ealg!B|M@v_oh{A?PVtQ%v_8=x%QymCzSy^KnX;^C-Wqg?BE!WIa0;2 +zBc%EVG!x*C<%@An+9D +z6Btxkg?J9%1&`$jBl(mZjr_KId`wv>1U}1sR8~#p{hehg=ZH`IaZOP4YdCdBknkR_ +z5xV+-4C@~m*4yVC*0S%=~Ou{gw2@@qe9!h_xuWa-d6 +zU|0rK+3vN5j)z(vl@n5?LcwM?T463l2MaXkMtKbMBg(^qdwOT($SBF^;McGtXUHSE +zinvdgXkqGt*m`c79%&P3OqkQ80FqXpGQV9?^;7peKLva_BxrajP +zIQ=RLFpl;{CDCI>7f^=W$|h}YP0if~DwsFydmFvW+& +z2d6Tt$R%92-onu2wcV3)ciRb45Lmj~G5CoO&8lUfcuATU6l0Q<(M}x(MbPI+MFNV4 +z&4sTVrb$WX2MNUK$NOo%vvR-Ve6cf$#RNB2kStOn0@RSMhis4(^30F${rylJjDt*% +zz>25NCF1)4=2SD1$N6)}4B3D&7393&=}tV(a1LZPg8OMKfdCmxuxTWBk0F}NP24du +zQ-|1;Klv?hmkSV9hK1fG&mG#60E~4PDB3*mEIG8o6R)3EI?H{s4YhZBf8Ob)7?;SI +zdbHF9)In+z$h;cq+3wXPa^6TE&UFmi2}s3j!GRw=6srTyFm^>VB~KG$2(p}{xfwF< +zy1x`G8l=c@xsz77d@_p@9p;kO=BG_s9F0F3I;*eoV>+sDJK|^OmgMCLi4e^xZc>Vjeulbq=OGm2gltqR%8pNeInx!8nr#gxJ3y8uU`C`E +z5U8zLlA@|v1AhW4#;!U^UIZa1a#YB8(M}y`uqQ-WeB8i#NFnf-L#%_8A@1CnJ2{oP +z9bi)ICyY^>rA2*(O3Sc?m&K305#-Xdai=cP!-*#&aBM7oVJ$wSn?&?3@rL<5X$;Ea +zB<|quHJ%=RCB14;KVl|rpN=79kt=Xo@cBWabojPsy4{zn$Wx|%V=>_&>ImzX7sj%7 +z%Ng)4dvIoh$cviZmc(FgJKS1abIsWC0ey(7bU=2zAn+Y5f_pIXerdn_X!;(nMb6_3Y{U8W|_D-oCZjPDjG2&}f?nVF-x7M&R +zK;ll+DTEV-^I>^G=gR88%77FZndUzs{*T0+GgI_0iJQJTznkIieAQ{tZ$AO20|-a< +z3)o*0w}k3!xI$0IUlKRU|4Q6)0EwHAEbwoM+ha-pkHjtD^Pm87EP@Pz~e`ZIn +z4Wb4_1!qOm8zDq}kI9opGyQO1!v&rCl)+|GC8AOvE>IM^J`eOfZ?50U>9HXxa1wXQ +z9q5uAqx6x@Woccz1njZ4I2Oe0KNJ_|`N6xt_Ukw>?38KDmy&R6@?af&pR#ujsd!!B +zeeb^|?iZ6(fj<&A*WVI%$sdWEI7=N)Z3U&yt@jnu`Ox($F +z27k##M^KZHlRZ1v!5T;*GY~@x^9@&aJ(_j8`87dYgPx9|O_c=*ve5Q^-eHOgjnt@&`zHD_q(Sk!FeF +z>WcOOIRi7|ifc=z)4-@JDej&yVu%7%iz6>;OICM*;woI^;F;~5Eu}b0a|jL3x=~0{ +zJ&yir-Cw>GVV6IIV(Gph;Dv4Rs)|p=n55p1i>*r6#(^Y6FY!#2m2=j$q~HYZO$Q@F +z2kJqYE}8UzHim|X?W>-sz!!9MbFo933xRJ2ZLfe +z#;WoTLPgiGpK%2zq}l+50Kp}geQP715~lN^EO|%WS9uebCDeeiUX8J%lwdqE+MpG4 +ze-67zf)H-jOJZ^)gUGWKi%~!M4HCWk76J#B+OIXkDPkVRDKC3v5D9Y$FWrKb99ze? +zdu@aMLg(c8jZ|VIp^3DGp1oZHhU?u6EyWw5HQIN#IQ|K<{$pq6T-UZ9tSEi*BtES! +zjy!hVX%$-q&ePsLHxI%lu*8oih*%9?Q9>ci19N{*u6z23Zjk9H4YuYxU!)&4aT7)V +zz+JL>Zt_G|yAL{70_jXWG=^kNt~UI-9KVU9M`o^`Q@P-*?ycJG9I`dUZytRh_6)`9 +zQ3&|AcVTJ*JJdU*=qcvTxH#@SACm>WEAgfhCpii8N)g+%%|mn^S9={s#7JWIOw5+v +zPzDSn5qv`P#~AlR?4J?B3|*+daNW=4DOcqo+8bJ@y(;Fsz^?|SuaJh=R;%LJoNEP? +zFuD(@gO0Y-*3xw}xQvcGxmmRH*D^>*>WQ?P5ctz`u^>sKX=TCFdnM@@zi7OHzX03o +z%|ou;REBaDP&qfFpv~k(wOx*&(e8TmIXA9pYt)b(6cM{R{k%b9bm#8zO?%!ZeIIo` +zbmijMFTkW`{9al?JUCdE%z6K;OF7U^3V^tmlOY4=iEPGWBVf$@(ArP1F=wP#S8Rg9 +zu;Z9s^ozZ7PWCm+QqjNQV8I_9$w9{(<}@`xJ(bSHq49XAN1M~(SxSvTa2(NWVaw0X +z61Rh!yRKR+(uYymd+W!jXBqaUwpX^9RnH(H?_&x0OkNNFI0GCiRGZ}B&wSo93-m7$kr1P%y&@W=Cy_$(XAvbXy3?U9f6#51Uf#(|RT?H)J +zWVc$Q-=lf+-lOuW-yjtizqEKiVrO +z;v*g1N~@#n2lrD)6i=G6ke%4>!*=Q1F0LH#+GTXgvm4d`R>rHBFaN*8-8+b< +zrX}|rGgLTLO_apU62J8G_?=pP?Db*D8;=?&e1FowvXUH!owQjW?Skx%>Gy%j{n&iK +zL^Fewv9=DD`&7m*+I^W}Q<;qpW7Ka^BF5n2>HCEQ+@D5~Bl@BDY-qJ@H&DRXs!jG_6WDj1(b4(QpHrX2rvd6U +zfraj2+po>+cySFRR=FM5zDCFl4WFJrFy6Z1ja^rSQtqj@#=3@Jo)8V}zW-bF4M`YbjA!OFO_SSnHSF};^n$_FlkD>ySIR+f<4BZ6)} +z^iRXge2{gKVo)Gw6tZZYFDWPWKe__bF6N?cm(Nq!6k5Y^@yZ|u{3d&p%R5GHwN@wT +zwig;H!4#K?>{N%Gg$rBr#m8JuY9^zp*6;h?{Phb+AYUC>l4#H^ +zfiJy&OaXPt+pF+65n(QwJq9UBaxw=f18DA}sPVHYxYDLZ!ksBR-=UYz*s(4lU%-;P +zr4zDdR7fk-=pm$kIxYDNZ6@|^N2vHynp3b12!zuUt=R2|Dk9K#?n7;K5)!`zaKoI` +zy(CKIKpj>bm^*0=h^=r@Q&~op3&9fqJ*ON@#$G1z0l{YckYSp +zE`=!k@@2sLr&fHRjy-~}YKnEltY%;Rji|OXpUnou!1t64?~ewUw#n;=bA$8QsV4lK +z3Y3CJ^reB2wLr(lFTZ6zxLei0x!M%7z!+N)+13j$DOg(4e-DMM@Df}pG>|S0FE0ChA(XE?u(hT^X~>ablrDs;%$#D<+wGv&uM8yJBxns +znpVm|j;6tLo#(v12Fv^Vh|e7km}a4H$}aE}^Ntp`e3IOz8suQ|kPJkEfV=ODu%DVK +z1x(h&Tr@SvyeP_$=aOc2s`4Np#I9L>Ay)-GZWl$qN +z6l@Syk=e`k{GNhSLXxvE$uawjk$tkV$Hb+kg^$?lB!Q32CnA +z((3(3M@lea@ImxE2N%C*BIppUX^^H!l{Jo$*YBR!TDfsti1ArklC`~J`BIB9VR$D} +zo(>TRz-(A6lT$F6kuxZ +z3lgRPE8HJ)J+U1l$(xzXfwyUbGViYN5;szoLYSL=f +z6^k2x;;}-(IhT7v?AXQst;tA(p%q|r_hE8a%C^*B63=UWTkEV?9GxJ}PeEnsRZhWW +z*S8KN93opP7AZelBTf~>N$>WMYj)>{MUwXgr2+}VJ2$3BY9Pigb2y|k9y{V86`xQ4 +zJY@)=*=H9VYdhk5B;uDY&@a!kO6vvXiOd-(svasVg^_4WL}Z_Wd3ZoW +z?6J%18PQjegLu9#j>D;?j%$Zoxu_+kDl0!A$a{W8t^)PD1x>GdB?w|ejG?rdbYzp+7t5>S%mxV?|CzJ25XHZ`Zi!Eo-^NJ0 +zoC+$DABIeJ(3dDS*Je(vvPgVf52FoX_N(BGg>)_>rKi(TaqFFZdzjL!$oobN2@>I2 +zUlD#&#t#HN-I^bGU70<>KokZzi7BMe;c6YdgB0i+$WN<>=0eYn!ZyWhPBHSUIUoua +zDWR-8qv55n8(7;sEkba%hd?Rr4ovaL%@XEn!HqG7w5LpQVuGRbvZ5d1lL>dw6y{ml +zEWp5c(u1zIap9-q1Mg^(QX>sLa5mP>cFc-@+1#H1n_DJ^$C*VyQ7Sqe`_~_v`v<`0 +zCf0A=mw4x9{_WBFI`!#6u-m@yB2?3Et&yr>gI1(CK;|)Zh{@3p9>vQ96r$_5ei!&t +zOGh&uIoMH`M9|R1@1&^6)k?4X9NJ`u0!gy~QE<>zaQ-g7gwYQl8&-}`$1h6(+W)Dsi_m(4vE3Zw+Ex!sIp)^c7( +zP1SqN+jZ)L{<674N3v6~+J9#MZF9c>Z0=3D6#;vgnMVf&>Fg`|za$DC%r>v{OyTeDXQU0d-2?~Dx +z+dq|~ve}ac#}cu`tUB|%-=0de@_rO@k6wDHLKNEwld3O%>Fl@on~T%}yo1jST9t4K +zm_}(Q&kd=2)I`h%huxsnQsN|`shX*&5}$q!$)dWQ0I+*1U{U(!gL7cM;|GpsBgx`t +zUY%(49}SsuOZ;k5NYUmjG5^821Bvq-x&b(M?IcVBWHAf?=eE@S2j_Mo0^rED`q>a-UZRBs&KO)U+mwG9_ZB_|8W<{bIzW>aZC^x$i +z8{MC8zsLGL_@iHQKm=a6db^~G0Jzrq>Kz*$=wta_} +zNu$%y2DeIAq54o&$(NOMK3T4gB$J1eL?V9o>VZU{v~y(mGBlogK&u1WMl5af(Sjf2 +z2Y1x<@0iW4e2YZug1#nHVtS-!^Zg_pBFrz^2KJ86{yZKlj;25NntakN|KQv|W6g?- +zwmFaf;M^war(gm^`R$z++Hdy=$#+hSou-MNYVpB5>;l%Y@~_2fRQ?`i;9|~5>^(jQ +zm|6KLDAeIhrSG1f8pH9*Z<($BqBU!!*K;c?r(G{ +zcGyhd6*Movp%0Fp-`oK>_dWe5k*$mf*_t^ne=t38MsW$6_ZM1`q@QAAY<6{f0Z0GF +zx$&KT!%$e@k#j%dF3@ieC$L%u1kl1AXyl1g5H;I&{`?!~F7$tb-+p8&`y1zO0N~uC +z|HipNX#qI5t4ciC&m~?5u+3D%kbj&H_nYbgwhGXxrc)P +z#<}l=$iJQFC`SCjxq&;|qgN<9z5^Ly?~7)+o5YA~E1k7rl_b>OrtYJs^a8Gj_tfK! +z!(5FDs^O<8C@q2Z+&8Kya%uWe4<7R88;+-VlU5t>i_9Gl4$TZR%PvC2MkWCcc? +zqdolUz_`R +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 +z-5jdTXrBTRiH`Gu!5-t*R&XM$$-6_k8I +zzH>3hf%T0&Ixd?X*JBqGYWbIT6dtQoJBf4sj<-7}O^E*fOcDad2JhsSKemP)HD5}i +zb`0(-=lsz{UUAGdrPRdJJv9G)Z=+Seo{T4J+^g4zQ*I#R(6J`$I}lP)exrOz9O%yX +zXBL`dH0sFXU>g1;39;nzO^z56G68%??OZ&A&2OizO_wV{2}6itL~4gEv0_7wB#9~C +z&x^hUZ5`IU3=E=An{c4Q-_HEt2AvG1(hH+j;=PsejXuFy6aD(4E`6n-y1w7!iaMoq +z9vd35L2V7mOu~`%O&xN?m+5x~thO2_B?h(GVig;t)WV{Q?b` +z(oyo-J9GoEx#6?_vALI-AvS!Qk6{|9O|eO@EowC(&Qri1r&RY)Jc-S*2Cz%t@H(6~ +zbp747;I?B0sNcH@B8*|{Nkh@Q_mt)NdwBhReXzZWuaaWyY7C&&D)+C1?KxKPT(vp* +z;KJN|gk=A!3oy!ez(l&l)MUwxziuc_nHb-(B(M>7vEv)KVX9Z9J>|}BZb**tGu3*4 +zs%+MLn*a5t@CIQnCn +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 +zrH7o5VCgZox`b +zDu}9Ma1!0T-k)RAvPh +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 +z;3`2e{R>uN{StnykfjV%-e#JP6w3g4sgL +z?zW%5wTR4m!()Y57^rYVw2Z7?%s96^6qUxZf|lHHoA8 +z^T9Zw^yh|K4&Jmt5>sm;FsHLXZB)m{HO4PqUun&^@4K(&uLPwie0Z2L*1P}gc@yY_ +zwy-?eEq5DZYRR2k5v$uqqOoq4_odxpGr|}y03a9+Hxat~$rKz^cfSv#V_`e@|0ddg +ziO{B!D!?yo!^eWZ*=B(3Mjd(fMDt#LdK&pjWQ5(JLaMki<2w866>&x<`1{$;*zB4{ +z(uy?vB|m{jYf+o2s<*3|lpL&X5w;Iva}W}fQy+`5$-Y@&ghH{@r}8w3>X@gI3OmDH +ztFd|(>8AKmy}$l>1|;<891jdMSeV;-%_fU+rAw>`9bcA?LY$79_8;`Bc}%KJ3U8)g +zI1|O;>x@eZwhpFK#{`+yC?SeJi44*;I7xm!VC;4$N8sAL>#ubW#mwA+wY5{stxay9 +zw$v~c%`zE%{+51Ru4>h?DQ?(ne|{i*ADR8du`1*DYQ~R8{0J3l*O8ZWGM=_@aaQ-d +z(is+qI597kyK~fh?&J%%lD-9BXO@) +zSmkqOw$0_HgD5QOj1p!4ZKg!2YU{x~TX@{TwRruM6=`$#)dPR7ZmWAW?53TaSX$+M +zzQRS`Wn*Tm;a6&j#Zr}AZQGbT5n-!= +zI);svySUUdZt5Fjj>?YqPgiE52_txR6XLf~)x5E^!yL!m2fWpFHKFNy%ympX-&15l +zjxS!;^o?KX;xC;$+3HK@UVPEy5`=+Nc*ldmm)Ej__*I}jI0wM?Zu&DQqP~6+fWXw( +zpqAsxZxXwB_f|f?mwT*Zewr8r%LW5J+r6QzbmT-(0@z8l0h7H@3noqSv*0DjOL(gH +za;H-f+Kyz*%jxizI2?BaM^}}4d~2^E|C7lZ2aJ-zUewGaT{3~lJv@97(CN9jHUpN4V;p`t1cB4LW3yRos? +zNo7_H1<5Y*)B0R*n~bTx$1g4C)gmk3(XYq|!cWN`B169-<^;rgtFdno6)hJ!E?mCa +zNWGL{Ek3%hQ?8ASg_lY-*PYAa#Uw4}I2MPv@*DSQ^;C_^Y?ifVEFAto6FBdtVRr4(|11-Tn +zPF0SBcroI_(4v4MqVBV +zo1SOd-I?WR0-SFUuTuOUxL4a5x8hl#O&xt1yiF&`_l)3By*)CMA&D(;tm +z;Gv?+5$S^B8&|bf)Bf^c^@%HW=S1pvu4#;_?eoT^eZ9O1Q�L=!NfcHTX6-R0#-R +zzv;;EBkoV(YPHN*r~ny-9U6?O-lq8z&t%NO+kjQT2fVWFg)x;7@OMHWM2|tnT4(>- +z>`ruV@FlI!;sNoK+kHCyK9qT8a{>+D2~9cc%%tz!o!4unC=m%m`I;(8xz<#9NN7l= +zSHSVP2``c=$tx^HVAog8h%p +z4YYBgQkfF{M&{9ntmx%)RlUBM_uB5NyvGf0b;LM7R0!!d{Ayo}GrBi6Awr7)ds)sl +zml{F0bxczy92K^jDsl6bc}nF;?}!ikdWZ>F7vu%5#b@VbD(!PR9rqW_9pVy+h7TtE +z7tQUPZF_vsb+S~FFa-1yt~e)h2>|2#Eg9G7o%qMv+l4SL^yf$Ox!ZGt_s#jRt!W^=4TOzoO +z*2ymS_GntJy7B`_=@|gcD+ya??;|qVQKLrsI`*w;`!p)UGQQ3XHHi!BPjCnfkrVg= +z>#w#Ggf-M@D}?@ZW5+MCl|%e+@x$tUQ9~>TD<@!qQpyWOPBvG}+jt-N=dL1W!H4g= +z&Z;JXUf9%**mp_?P&DY4`Ji{w!J39v#b2U+UAAMfllg{?DeI@t3rNp^7S@aKrH)h!a6fY*9EQptJ#&kuXUXxfJ +zBwtJW;6cpW0H_5G=a$ha5Q|1TA^)A|$!bQmhPm1-y>@y4VyCSIMd?s%JVW0hE2t8>k2-BVP=@` +zQ9F>H?+)S(j{OYEV-!IRl%Z@}FA1WM>rG%59o#0pU%24_e1aM;dTky22aYH7CSOU{ +zkBSi8v|v6?j}SG(R@9X^w$mOTIY1E~`t0J{V +z&#VoBMuhp-Ho2BDjo}{AaPMmm`l!d3v$Pi2H4N^WU*Pg%8RQzfKYmtaE?J3&Nq?Ha +zMzkHI4wBS7UdAvf`KP%uQxeIB?KoQ(uaxe16l(sqn5q1wo^683v48IQ@$wE>ebP^y +z(G=L)`qVx`W7^u5&lx!m%moKT~QLggs +z9>BRjuZ66LGBK6PmT-=tu7WsgnhvQnIx-neCgBu^^sdxe)hYNZ#v +zJ6QP%6RPcwE)lXJ8JiwO7)N##K9yC0cOzg@u=fvDp#^m6IxRq9m +z=W^-bjlJV +zkVyK2YdUOHkth>4;DnJZ>&O_@Jbui#KTR^P2#HL}7Bp^624LGxW1&=bTNt*qlxnY~{dC)-n7i-0EhCv-X +zcO(ROAvdDmA|`&c*d;G+zpZHo8Qma>`!p)M-!ZDa-<738rI6p4YWaYt025u$@JiC7 +zo5Ta>eM>(g>f3+!w7;IMI-|Y4tUxuS9vg?teIl0H!&<#$U2_CZhwdmWyN~MS4|7AG +zHt4+Al?SV!X);=+mOh^wlb3bFo~q~~_JaSdnS!)}U{;Bc&Jwq51p9K?>oFXfl|h0E +z#WHBH3)3BNbz@QEddS>6m4I1G1jZJnVXS;j?RE +z>)mZMQ$Y~jc4zYG+tKR{-C|I%RI_(0l5(RpVv-N-Niapp1SZXPgOkrxrYxSgET#3< +zNQ~TW#xuyF<9mdevtKRih&%FxL`o6|KE6eFov=E#h^ExJh-bT%VFYaNJaqUi*bKKT}Kdz;q{@ +zbpO>6pX*NBaSH>WR}eCSz8(lnl#)UTQ$QjbcC*CQ!tNYB(Qav+*$x>lGbn9V>Qvn0jdV^9-Nr7L}zGJULGulannwX^i4{r<5q?I8M8VoU~aT3VZv+PXt+0nxs- +zR4M%O89-qCr&hZ!0RrAE(6J=Hw)MgHKyTXUHl7IDyh+WMeFhfKJ}>?pnz5efW^0_W +zLWU%|9(*7=foi{`>+{!I?iPEaBP`A1`0<@$Vf8Pbd(P+}^o9MN}rwUrzt+d_=@`^e+Ri1p!hkQdNxB!sZKiq1O1}^})RF=icN5_J=4B9K22OOiseg +z*iLwim#FWJz`myGD!`Byi4N8PPkkxyMN;{mpY5B5ld +zyF=oXG|ObV>nnZ438T3mCg|n;I+sXJ4Ki6_L4QV8#vT{_ +zcHu?t98G~VPu^So#>PQj%R`<#tKS)RwsVbkKz+oZ@@)oNauv_VoOy%A5bVTo91tKo +z6rvnSzu;^>vQn$;r<1y1GB%f9?$Hrb9|}))s30H&-1@V0WVS{dkdd5@)sLwekB~WK +zk_H@|afqEtiWOgQwXV1xVGJ)ZLk4((5{h}S&E>@nR1L$6W3*%C$i--ZrB0MHEicw& +zK-o8G7Nl&A-7lb9*Mx)~ms_-Ark$#!33x7zcnpKp@mg`dN$=q3at949h1#Lt)X7kR +z$KjN)KzLI~XDp}P&7}5-*}X7kDh>~()R2&h6n~QxES}c56fS{Kmc_sXvmOQFXu}c1 +z6Hg-Tv_XX`t{Bo7?PPejOZB~8Cq8Vp!Qio?2bI*Bv;9a4ntPdPILWXzcwkCGLLTm% +zOA+SDRfEsJ?3JaxsI|wd+H7G!N^&AUj5Ch#%*QqK;(%QKOz_Zuv~1a1GnFRZudWr1 +zFMKbV6=slEXunt~=zS!JSKd`eD|0M+B^_<7UAxLc5WeoiyrkWCeo6?1HLYjrC|-wv +zutAjMExuTUq!x^vx +zpCwXmw%*{V@w}Yc>GR6luVVflpe$slv;ufzE;7n`Bj~flR)!^s-RiE7uyL@5-L0$i +z(Y$jT?Fkd0mQo>~srhYGt!zd&lB-Fi^poa}Khv^|Px{Kxri44C=T3VhDZ3T^WS%Xa +zNb3#B#1s{RQ&N7ANLTMZ<*ww|2j@X+T0bmjT8RE+^MS;oh>t5HPYhu@5JFjBo#!`g +zS@ZB-h;EkIc~nK&i4+BmZ#~s?kMJ~VJ+)j_-vJdbuwest0dCJey+>X_tm+g|ue+a_ +z7Uz5`+SrCdYz|Itxyj{#sa0@_R(?07ircl~`L%16ik%?kTv3}$Z6SnMV*d$i35X6w +z)^cPPjU;XCwG-_osYt}~UGI(i)~J+~RR37(El{sizjzg0$vZ>zYbaqcmwxZ)_H3fN3=yIwUmWE%iaY+pA{@c7 +zoQ#Q}$MV%%_X>v>gDd|M5GzHCaL)idK&pO61^M{pbL0Kp=brlVxm~b%2ETl6m2Pgf +zU*{ZB+B#X~hRA-=dS#`+lI6WUju+b=l;0N_mR-Oq=q|#%vwvAx*QOHCY^aV0>jnVg +zkOF)!Z>M$Jqph?zF&j#pJEFviwFGKpi +zK&0cb|DjdpR(kRt_}L;5X`)ZWkq +z#IlDW+Xj_PHg}EDA6@u~$eBOcjvw&QjEyG~$8@H0C(*|uOWX2hhb{CU(6+#TY^$P# +z4#-50=?c@wK2*j<$`hhBtSnjK2v{>~MrYu1YgZGY$g%MwJXu9eG(d~`%v|t)ORd#P +z;9?<}np@Xq5XtU7Bvm?obr<|A&LJ|+{g*Iy2;pshe?=WH!{M9d1O!rvSn7{WBkq%< +zIK0r=A^J{hOgs6)p{8>|d8rMV98X+bt4PEW4~@=mmlUwzec!Ny+yzmoHVRDmh``$W +z{2tIgC+M&Wo4 +zadl1e;+6L@rxK}dja1oagu>)64{3f8$+YV3TYNy_}SnG{;7mvTi +zUC583v@E{1KyN7#xM$cIMV2yuSFwLyAZPLh%7JbY%X~(7`RDM29aetqhDz>++Q~wZ +zl+UX+ey|oY44ze)$mtr%KFE7NUlt|;HXbpk^lb<8^>_0{-0lSSN;_<#|0xMOB-!wN +z%CFp%(XQ5VjI<=OnFa(*=-OPfFQ8k~q~0^LSyT)Sn{7#IKiT6>mzMxVnkGm3%J4YP~M-?3*VRTEyN!&%>rS +zR}h0Eq)ofp1S+UT8oB39LEM?RQJBbVBr@}Nx@ORVvJbN=57<_lSb|V^L8>#ON@WJ?MeJ`d +z97VdL$$&TG(=3NOIG2| +zBQm=0jb3M0okdrkr6*ypXUojtCx?ppZezZ4t%6==*RPm-2srw@a0iA^;hq3 +zJomSb);g&^=*3Tr^b+;<;|>G!SK|OPr-XSEAwObnx7v(;Iq9AarqXq+0RtQ}*ZY?A +zn0dSE{sYO!nepJ_ntR}gbEu83mw=YW@VK4!w!>A&_OVB5FBGRQq8mf;_kF$C@Sq%y +zuiVpvWuH0E4~srWyVw|Us6`3*QmYtGL5KA|(me-xvbM63gH+1~!Ad$R2+za_Q{UQ@ +z)pp_fX-0zxB>aT$7KWXAn^-(&lV~;VDTMCrhfNLR9@=U=@)U-(&RZt6PYe&{pn-S* +zMPQYL_gX#jIN4p@z=C!iYu*En%L2acbg=Pgaow8TUA12A&GoSLxl|yO(X9RjO7nvO7p*?vHByVU15IY-Ia)Gr~=kR +zgYZ?&)CP7v3r7r*^xApUh-YH6&amU41kjCdgYV#sr~eQKCCQi_4$z7FBohm0u5KWs +zS;;@K|BNhtXZ!?wK5l(Xe=aE(y1*T86hUhR&3x^)5cKCeCH&E~L=P1EOLPq%<2pM96QKij+KytOl@rHj;=)LweMbQpQT$OIxt@k6 +zR1o~IWaR#RDq#SA>B%f^3Vd*ofSX`j4ZeDAnOsH7@P1F;B{Una?$b4=IC52;A}*^) +zIr!i;*a1osCiJ#Q%{+!CK$r=(5HgP(DC#qp0gCWoj7$w-Pog|*EE4x4-+3tNHv?sZ +zZ#>K+#3C(Un1>cI&CEKg_R{oqT{9NqMFIyAIKvNB;8M1l*GYRs{*6V(C1j+r4-eNR +z%)(sA5AMrm(6N)%nJYN|UzD%+##9q(KdQEksi=PUBvGiUMJo)tl%C12KtSD*Eb0Z6>@MypAa>p;+*F6 +zWAGKN4a&r>wpv_+AVY``rZ1#lK9Cp`QIioZgnYde7FI*vca<$dsZ`WK6Ty?jyqNm4 +zq-{bsaAZe(xHYyC! +zY)<<>dwj0fQMq0uo?@mMZo2ZDre2+3zQ1kWHa<1Kh7(@~^&z!dzwg5AlPuf(grxMuq +zdG=56f6VxR=hJ|HUzX|9&;nPfJoRB&s|7(C7(mf{yE)=?ZbCV%R7a)9${CwJw}ZZ^-gaQ>HJwB#J0@4NiR28;3pD#YhKFw(vgn5)ca#{%WQawodfiaFSh+4YgsJe6H5yRG<^`xuiGtL9NR7l_)oL#ts?mMfagN2cs6CT(Vj(2+j6je6sl%Q=Yn+*7k; +z5%JLVYd^6$Kwk|f%+&oXX)RA>4}#%@A<-wsZWyjt@w10@N-sd)}*2Np1+O_EZh}I`dQ8!Va*$qS( +zMAihZsZ%$2k4vXduxQcCU2EcE%|=zQ#%$!AUa6HAt(2iyHD$L^YArQj;ZsN?nq8H9 +zQXmdZX`qfiIt8>`m0-CB4D3=B!*#rIdmGVzt!;j*48Ry^3nGlrR6fRMstfB|**5)| +z9HBDLPXJZCZTj~HA9ds+mKyfB5QoJmz~><5CARtwyK%f3lT->5_=Cf +z(zrAVGUx!pV96r2>R{p9b}e5=+B(5~=n?SN +z2a|%0T(NMim$#6ZNYzXC2N}DNEvR;dR=Sg3y;&J%bWS~80FUb-zY$@bi6g{A{nTk= +zEjC+~ZUF6<=^deWvDTpAg9}vrDq&e7y5?{M`laQ=ipl+Vi04;o2G#`t;Vq{_) +zRAetVF6fdTu9e(+*>!7xN-B|uW}nn0>mlRvGsrD20+_7#w59au7B9F`;dqIYT}W!KBNVo@#>);tzrLwRx6D9Diy+V#Of@yIQbY8~v9 +za&#jN_y9T}&aM+g_mB7tN{S;-|Ku{qWnDaOQ}2tzy!WM5j3+axVu?_2Q}cCGpT*F? +zR0N}f1Eo9SnP;1k@w<3M{v;Gg6oD?z|4B)o1?}c>qjam$g +z!xU$iaTV$ZOaKs+#Ork3T{P|)ADc_)dvTeQ{t_%{wj4rzvF1>W)=7*3zk)!K9h(s! +zy{EClq{-tEZ67{1<}c%$A>t+)17)Z}9!5tZ3yu!1aHX8P2i4NFN=TAQWKI+<_W8NY +z;eaK2r0NF+Cnxr>hLnI~8X!6>XdqZ;n!Xw(4dOv?`ydIh9}p|e7I=d7hVKe>zn5T~ +z^E1`U$0Rc8aFe4BE8@7t+J*R|>K1^;4ZjYd6;EL`DUpZ|s132rPKF8fxG3e^EgGiS +zhGbRARfo_k1#{d(tUr_48sYGM{`Su3V=ms&ux+4fw{Detnpd9G9(OviV59vxLwe>5 +zEOU{r37jStcforGPD^0^5~wZEYq+vk3PivRnsKPKMz|t!eD@pnIM5P;zVoIk=c^RT +zz85S8Z%v@KS)yfYJ0Z+Yxe#m?81Rwf=W=@r`c#R^cV%O$q({H9cT6g(|;c<2yKQ=~pK?>f1@KVr|r#O|b7XV^LLZC!No;e?2#bb-EJN9K5p +zZk97waSMF8Q_}f_?SfWj+q2mPOwgI1C0*wKj) +z{!~`eVBkm0WX?at?^OZ(Ln0_`jP(evep&Zw#%DSe9_b5C>d{JTE1>LV0pzbm9|EjY +zY{!^p!vp;lHnlEi=8F^%%hVdgOWhL*g>4iy`+`3)Tlhd*9Kh;QZsb8R+s`#-_St8( +zo8?mK$;7c+oC>KjWcuW_)lUX0#Mgj6)Qed|=%-G2>qReK%z@p9Q(bCkTP +zVuFfpS%dR{XF0+fY@|@hX#9zggWj3pGu>{Vcda?B+bdsdYg&9xXXcd!gy>|8T1n?myy%bNx73Y`KV=jGPCPxw +z#)%)-8x-BqG%yn9%roudS}^*hiTq{c`)&yY(YIljOhzwa`Y}y;I5w(owlGl)FEXk{ +zMXVkR;!R?mvzevE377lZX!(sN?SSPx89n&JPTn6hz$?@WS+>X#eCnRNgLZVXlU +z7UPTMlzaU#}4MxyB7qE^cHjhSSOZ8(so&M?UR+;*@P=}iGU|7Ef`SbaaufV>c +zYzw9%q5O~z{{kZepP-NLy(VgD+@;P4knM~o^Tw0>OW}H{ReB0IT!cDluB!?5m;b$M +zAJ5OldMv$*`utmNWg*?^LX*rHk#;c1`t$psSzVrlA<2#Rq#RHCi&MG36PYZ7>Anzfh5P{uh8EdQ7O8I*IPD$7 +z+1IdKzhVxl;GP+Oj-8fKSF=K~NB^=<6;$ +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 +zQQ6Kt8z`z{i8iQuI!vD*NOASiompTKP +z=njW`=VTt&^LgD$$r7aVOb}zv?(c&%%EmzMqV|$68ZNR#40Ht39yIsT=?$cMz@g_U +z7LfrkqiJqlSX_>BjJkYNGg>fG*>-=i-Aa)_8-OuhdUI*qu6M@mVhDq^Stq*o|A7CZh&!ujS8fP +z-J=#Jq$+jjA;la7!C=T+FwJe*iGYhD +zv%`$(1O|P55MF_)l9qaGvV$(Ce(iRegBO!Dx+u~1&ucXCl*?pkBM|Rt83z%~2Mm+r +zjeM=RyHo$IkTc*w#PpPrD~=Xt0os6V0EWb3PnUnG&otNNoI<8JCNLu|7Hkf8pS*%W +zd%)|TZlQnG&7*7-83ar0$y^YmvH)Z@+Qd-wdot>q3pNXs`RbCCkmha0diUR{5RDiq +zfUu=ij0sIZ1B(IK&b9p+*M-3p*RnpA&M0CAJC-hJ{`=z?LlbEdi;^!MsZGm+LSsE+h0yCuuBpM_pwSpbMOebN(@_ebUK#V#o1l +zT2W^&n1%9-TFVBF!B=wqy9?X|vvW$=dznN($;aOa)~4Ok{o#KyWR<=pak;{Ov8tWz +z_SGrq&!?{rYeugvI0!q7A=xK;Mvtmw>*NHq+$qDg<~urdE)>jDUkZG1rU=GN;W=8uPi3hEOSypY6xU+%&2&TI`4kP8KsD +z=$Mv6WJkpBOkIVGQelY|rb3P4ctax~(;gGMP-r{*!h~zc6GT8jdJUUGDA5|IzQ$Wi +zBUB#8*_BO51oAooLFBEqV>={@ZpA9A!c^8N0a{*?9@mEAK3D59tW)ONah9>#4T*V( +zq@g~VaGXI7>5+@{L9_rYZ0CZw8hqTXqKZwMb53!7xVig8+kP)GcpE)_PEt)7(AXEZ +zAc+}=HTRaeUy&%@;1(85BM9x7kQTS6$#&Z;>x(npkGN;Iop7WZH;<5 +zvlcr}TZO}{H}t#7t%Io;$3xErhrIfCld$nnt=V}sq7PjAh6HIr@{fPT3BuTBoWeED +zSBZ}gs7^}>FCL^arx%|HQt}ba&*u#a0eaWuxS=5Z*|D1d)22I699-*QfWxYqo)dkk +za!5*xx~bG06R82j7F{H-C-%LQ*8TD$KrwVKz%K>%_I(OD!+%TTYmk9$-^^-I;`pxI +zqq%%yo5kt9j4FBF$qeMjdrd4uW0E{>cuJ!^H|ixgd3lC1R-{NaPC*h+F!HET4|C3oIwc3MM50{|YaKdZbSC)bz?4oV+GOn{Sc!;cii +z_W#D6TxQ{pVO-G_O8)II1%yCb{&_vnOb1VO^Qwwg7x)h>_+f(1*_wA-+yy#hkV4rI)e`*>GUNErPLZ)PW;5rj9Ia}Z^(q>7H-BT +zR5ISI*xW`oBZ7C#q+H;_tA+f4AKiKyPmO**t@)#8ARKtLXX!1ZnzBX-MbsuF!2T}V +z8U>H?1g*44L`{SU{qpBBmK$$N8hjbP-gX!V7Z6I+5p3c2cHU>I +z9(UzjJy5EqAv!E4*j@G2K0HmbP-_cxXh|l3`{R3R{C2E%b8fQ3$Tx~LZQMkrAF;fm=)VjCFDwxd?A=@=Fftg6U4|RS@GoaU%e}0@YyBot +zhS^zG6wSKgnSzXeUjXqL%Iirc<7!mp_QdeEGz`|QVYY1;GfrAI5&JT!7M|%Vx0eRV +zi~HQf29@<3MCpkatDm3es#WY>kourLh5{A<*_|hv4|QH3d5LCnuA*)ilH_`6%Yoq! +zGdK1bd4}d1_@R~mZQC#4u5Vo21;uSe<5R*-b8d1MdTzxNbhP0N`h`($7k-+!Ha~oO +zy4TUV4U)c~6cSUwHUqk*ql#w`J?NA0GVG%hx9-cNElnVv^kSLPiKpD&33$XiF#8x= +zD&8aus-{OegmXHODTBW^aDr%XPexU4-W&K~vnwQFwNZvzW@(Zm<2T7de@Z!b=s8-T +z|Iv7$HPfIwQ^D0bIG3@z3L>MqTQ*5cfx&G#khefLPlTMj!R?Qy!SiKMO +zT02Y^&BQ4W`196`F_prpA`P-b%wkm$1o}Oj$}e{EUX>}cS|NRx75hmeCp#B{VcwBtVOzLWsC(>nhb=r +zHozel0wXklCNj@lvC0na*A}pTe +zd;l9Y1XzH+Oyo)OLgQ<~*A=KArhW;`vQ7~oYOgFT6*-X(#&7 +zK$oDpvgfcWa1yL^7{$=Q-Q=I*>^ym;787f{fU8rQ_BrW-E&STGB1ea3uWFU#V*x_X +zbdvG9s`cq8mo(M_z0OQ=vW=*(d2nwxp|!RPbLEas*4C^EC<{R;lnR4b-87D$f|x6{ +zI@swMvu?^nD&Z>Y(PP`vE4YJKzsEi@S9{HD39S2xme2o1m@rAo8GW6Qs=r)t(mbxT56p41F +zR#gXb2$#0qk_g?#UT&i8HhA4ENy(;@i^k?bQ6ecwqz5z<(;(Fs>NqtfLQ>hs0eE_5 +z(UvwFPu2dQWg??=_zy3hACyvmqhg;OC?X`#*i-1GVb{4Y#l*Kx5ZiRxWZn|eact07 +zd_4c*Zmca4T*{nDLV=<$j#hT)2e_BU8%rcCMqI@>Yv`#G!ru2yF|a=U_t`(idq2|R58j>4$JFT67A%2Uo(V39Y}-dB@R6j8P+%TpWc