diff --git a/.github/workflows/rerun-compare-chromium-versions.yml b/.github/workflows/rerun-compare-chromium-versions.yml index ed014b374d2d..013ecaeed43c 100644 --- a/.github/workflows/rerun-compare-chromium-versions.yml +++ b/.github/workflows/rerun-compare-chromium-versions.yml @@ -5,21 +5,25 @@ on: branches: - master - '[0-9]+.[0-9]+.x' - paths: - - package.json +## TODO: If a PR touches >300 files, this filter may prevent the workflow from being executed +# paths: +# - package.json types: - closed jobs: rerun-compare-chromium-versions: - if: github.event.pull_request.merged == true +## TODO: Temporary workaround for the above issue +# if: github.event.pull_request.merged == true + if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'cr1') runs-on: ubuntu-latest env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_SHA: ${{ github.event.pull_request.head.sha }} TARGET_SHA: ${{ github.event.pull_request.base.sha }} steps: - - run: | + - name: If a major Chromium bump was merged, rerun compare-chromium-versions in all PRs targeting the same branch + run: | shopt -s inherit_errexit set -eEo pipefail @@ -28,9 +32,10 @@ jobs: pr_ver="$(chromium_ver "${PR_SHA:?}")" target_ver="$(chromium_ver "${TARGET_SHA:?}")" - echo "::notice::PR branch: ${pr_ver:?}, target branch: ${target_ver:?}" + echo "::notice::PR branch: ${GITHUB_HEAD_REF:?} (${pr_ver:?}), target branch: ${GITHUB_BASE_REF:?} (${target_ver:?})" if [[ "${pr_ver%%.*}" != "${target_ver%%.*}" ]]; then + echo "::notice::Rerunning compare-chromium-versions in PRs targeting ${GITHUB_BASE_REF:?}" while read -r pr_number head_sha; do run_id="$(gh api "/repos/$GITHUB_REPOSITORY/actions/workflows/compare-chromium-versions.yml/runs?head_sha=${head_sha:?}" -q '.workflow_runs[0].id')" pr_url="https://github.com/brave/brave-core/pull/${pr_number:?}" @@ -43,5 +48,5 @@ jobs: sleep 1 done < <(gh -R "$GITHUB_REPOSITORY" pr list --limit 1000 --state open --base "$GITHUB_BASE_REF" --json number,headRefOid -q '.[]|"\(.number)\t\(.headRefOid)"') else - echo "Chromium major versions match, nothing to do" + echo "::notice::Chromium major versions match, nothing to do" fi diff --git a/android/java/org/chromium/chrome/browser/vpn/settings/VpnRegionPreference.java b/android/java/org/chromium/chrome/browser/vpn/settings/VpnRegionPreference.java index 88d85e3a5b87..c774a806a671 100644 --- a/android/java/org/chromium/chrome/browser/vpn/settings/VpnRegionPreference.java +++ b/android/java/org/chromium/chrome/browser/vpn/settings/VpnRegionPreference.java @@ -37,11 +37,15 @@ public void onBindViewHolder(PreferenceViewHolder holder) { } String serverLocationTitle = BraveVpnPrefUtils.getRegionCountry(); + String optimalString = "%s - %s"; String serverLocationSummary = BraveVpnPrefUtils.getRegionPrecision() .equals(BraveVpnConstants.REGION_PRECISION_COUNTRY) - ? mContext.getString(R.string.optimal_text) - : BraveVpnPrefUtils.getRegionNamePretty(); + ? String.format( + optimalString, + mContext.getString(R.string.optimal_text), + BraveVpnPrefUtils.getHostnameDisplay()) + : BraveVpnPrefUtils.getHostnameDisplay(); TextView regionTitle = (TextView) holder.findViewById(R.id.region_title); regionTitle.setText(serverLocationTitle); diff --git a/android/java/org/chromium/chrome/browser/vpn/utils/BraveVpnApiResponseUtils.java b/android/java/org/chromium/chrome/browser/vpn/utils/BraveVpnApiResponseUtils.java index b30b98b2816c..3e70bcf69af9 100644 --- a/android/java/org/chromium/chrome/browser/vpn/utils/BraveVpnApiResponseUtils.java +++ b/android/java/org/chromium/chrome/browser/vpn/utils/BraveVpnApiResponseUtils.java @@ -14,6 +14,7 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import org.chromium.brave_vpn.mojom.BraveVpnConstants; import org.chromium.chrome.R; import org.chromium.chrome.browser.billing.InAppPurchaseWrapper; import org.chromium.chrome.browser.billing.PurchaseModel; @@ -65,8 +66,8 @@ public static void handleOnGetTimezonesForRegions(Activity activity, BraveVpnServerRegion braveVpnServerRegion = BraveVpnUtils.getServerRegionForTimeZone( jsonTimezones, TimeZone.getDefault().getID()); - String region = braveVpnServerRegion.getRegionName(); - if (TextUtils.isEmpty(region)) { + String regionFromTimeZone = braveVpnServerRegion.getRegionName(); + if (TextUtils.isEmpty(regionFromTimeZone)) { BraveVpnUtils.showToast( String.format( activity.getResources() @@ -74,22 +75,28 @@ public static void handleOnGetTimezonesForRegions(Activity activity, TimeZone.getDefault().getID())); return; } - if (BraveVpnUtils.selectedServerRegion != null) { - if (!BraveVpnUtils.selectedServerRegion - .getRegionName() - .equals(BraveVpnPrefUtils.PREF_BRAVE_VPN_AUTOMATIC)) { - region = BraveVpnUtils.selectedServerRegion.getRegionName(); - braveVpnServerRegion = BraveVpnUtils.selectedServerRegion; - } + String regionForHostName = regionFromTimeZone; + String regionPrecision = braveVpnServerRegion.getRegionPrecision(); + + // Determine the region for host name and precision + if (BraveVpnUtils.selectedServerRegion != null + && !BraveVpnUtils.selectedServerRegion + .getRegionName() + .equals(BraveVpnPrefUtils.PREF_BRAVE_VPN_AUTOMATIC)) { + + regionForHostName = BraveVpnUtils.selectedServerRegion.getRegionName(); + braveVpnServerRegion = BraveVpnUtils.selectedServerRegion; + regionPrecision = braveVpnServerRegion.getRegionPrecision(); } else { String serverRegion = BraveVpnPrefUtils.getRegionName(); - region = - serverRegion.equals(BraveVpnPrefUtils.PREF_BRAVE_VPN_AUTOMATIC) - ? region - : serverRegion; + if (serverRegion.equals(BraveVpnPrefUtils.PREF_BRAVE_VPN_AUTOMATIC)) { + regionPrecision = BraveVpnConstants.REGION_PRECISION_DEFAULT; + } else { + regionForHostName = serverRegion; + } } BraveVpnNativeWorker.getInstance() - .getHostnamesForRegion(region, braveVpnServerRegion.getRegionPrecision()); + .getHostnamesForRegion(regionForHostName, regionPrecision); braveVpnPrefModel.setServerRegion(braveVpnServerRegion); } else { BraveVpnUtils.showToast( diff --git a/android/javatests/org/chromium/chrome/browser/BraveSafetyNetThreatsPrioritiesTest.java b/android/javatests/org/chromium/chrome/browser/BraveSafetyNetThreatsPrioritiesTest.java new file mode 100644 index 000000000000..590b8848908c --- /dev/null +++ b/android/javatests/org/chromium/chrome/browser/BraveSafetyNetThreatsPrioritiesTest.java @@ -0,0 +1,64 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.chromium.chrome.browser; + +import androidx.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.components.safe_browsing.BraveSafeBrowsingUtils; +import org.chromium.components.safe_browsing.BraveSafeBrowsingUtils.SafetyNetJavaThreatType; + +import java.util.ArrayList; +import java.util.Arrays; + +@Batch(Batch.PER_CLASS) +@RunWith(BaseJUnit4ClassRunner.class) +public class BraveSafetyNetThreatsPrioritiesTest { + + @Test + @SmallTest + public void testPriorities() throws Exception { + // Fail safe option for empty input, consider it is safe + Assert.assertEquals( + BraveSafeBrowsingUtils.getHighestPriorityThreat(new ArrayList<>()), + SafetyNetJavaThreatType.MAX_VALUE); + + // Single input must return the same value + Assert.assertEquals( + BraveSafeBrowsingUtils.getHighestPriorityThreat( + Arrays.asList(new Integer[] {SafetyNetJavaThreatType.SOCIAL_ENGINEERING})), + SafetyNetJavaThreatType.SOCIAL_ENGINEERING); + + // Several threats as input - return the most priority one + Assert.assertEquals( + BraveSafeBrowsingUtils.getHighestPriorityThreat( + Arrays.asList( + new Integer[] { + SafetyNetJavaThreatType.UNWANTED_SOFTWARE, + SafetyNetJavaThreatType.SUBRESOURCE_FILTER, + SafetyNetJavaThreatType.SOCIAL_ENGINEERING, + SafetyNetJavaThreatType.BILLING, + SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION, + })), + SafetyNetJavaThreatType.SOCIAL_ENGINEERING); + + Assert.assertEquals( + BraveSafeBrowsingUtils.getHighestPriorityThreat( + Arrays.asList( + new Integer[] { + SafetyNetJavaThreatType.SUBRESOURCE_FILTER, + SafetyNetJavaThreatType.CSD_ALLOWLIST, + SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION, + SafetyNetJavaThreatType.UNWANTED_SOFTWARE, + })), + SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION); + } +} diff --git a/browser/about_flags.cc b/browser/about_flags.cc index 8a8cf03f0ec1..bb6539e69f48 100644 --- a/browser/about_flags.cc +++ b/browser/about_flags.cc @@ -743,6 +743,14 @@ FEATURE_VALUE_TYPE( \ brave_rewards::features::kAnimatedBackgroundFeature), \ }, \ + { \ + "brave-rewards-platform-creator-detection", \ + "Detect Brave Creators on media platform sites", \ + "Enables detection of Brave Creator pages on media platform sites.", \ + kOsDesktop | kOsAndroid, \ + FEATURE_VALUE_TYPE( \ + brave_rewards::features::kPlatformCreatorDetectionFeature), \ + }, \ { \ "brave-ads-should-launch-brave-ads-as-an-in-process-service", \ "Launch Brave Ads as an in-process service", \ diff --git a/browser/brave_ads/device_id/device_id_impl_linux.cc b/browser/brave_ads/device_id/device_id_impl_linux.cc index c4f937eb0426..b8f994d7926b 100644 --- a/browser/brave_ads/device_id/device_id_impl_linux.cc +++ b/browser/brave_ads/device_id/device_id_impl_linux.cc @@ -41,9 +41,29 @@ using DiskMap = std::map; namespace { constexpr char kDiskByUuidDirectoryName[] = "/dev/disk/by-uuid"; -const char* const kDeviceNames[] = {"sda1", "hda1", "dm-0", "xvda1", - "sda2", "hda2", "dm-1", "xvda2"}; -const char* const kNetDeviceNamePrefixes[] = { +constexpr const char* const kDeviceNames[] = { + "sda1", // First partition of the first SATA, SCSI, or IDE drive. + "hda1", // First partition of the first IDE/ATA drive. + "nvme0n1p1", // First partition of the first NVMe device. + "md0p1", // First partition of the first RAID array. + "mmcblk0p1", // First partition of the first MMC/SD card. + "dm-0", // First Device Mapper device. + "vda1", // First partition of the first virtual drive in KVM or QEMU + // virtualized environments. + "xvda1", // First partition of the first virtual drive in Xen virtualized + // environments. + "sda2", // Second partition of the first SATA, SCSI, or IDE drive. + "hda2", // Second partition of the first IDE/ATA drive. + "nvme0n1p2", // Second partition of the first NVMe device. + "md0p2", // Second partition of the first RAID array. + "mmcblk0p2", // Second partition of the first MMC/SD card. + "dm-1", // Second Device Mapper device. + "vda2", // Second partition of the first virtual drive in KVM or QEMU + // virtualized environments. + "xvda2", // Second partition of the first virtual drive in Xen virtualized + // environments. +}; +constexpr const char* const kNetDeviceNamePrefixes[] = { // Fedora 15 uses biosdevname feature where Embedded ethernet uses the "em" // prefix and PCI cards use the p[0-9]c[0-9] format based on PCI slot and // card information. diff --git a/browser/brave_rewards/BUILD.gn b/browser/brave_rewards/BUILD.gn index 0d27c3236ea6..5c06726241a2 100644 --- a/browser/brave_rewards/BUILD.gn +++ b/browser/brave_rewards/BUILD.gn @@ -3,12 +3,12 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. */ -import("//brave/components/greaselion/browser/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") import("//testing/test.gni") source_set("brave_rewards") { sources = [ + "creator_detection_script_injector.h", "rewards_service_factory.h", "rewards_tab_helper.h", ] @@ -16,6 +16,7 @@ source_set("brave_rewards") { deps = [ "//base", "//brave/components/brave_rewards/browser", + "//brave/components/script_injector/common/mojom", "//chrome/browser/profiles", "//components/keyed_service/content", "//components/sessions", @@ -25,6 +26,7 @@ source_set("brave_rewards") { source_set("brave_rewards_impl") { sources = [ + "creator_detection_script_injector.cc", "rewards_prefs_util.cc", "rewards_prefs_util.h", "rewards_service_factory.cc", @@ -40,7 +42,8 @@ source_set("brave_rewards_impl") { "//brave/browser/ui:brave_rewards_source", "//brave/components/brave_rewards/browser", "//brave/components/brave_rewards/common", - "//brave/components/greaselion/browser/buildflags", + "//brave/components/brave_rewards/common:features", + "//brave/components/brave_rewards/resources/creator_detection:creator_detection_generated_grit", "//chrome/browser/bitmap_fetcher", "//chrome/browser/favicon", "//chrome/browser/profiles", @@ -65,10 +68,6 @@ source_set("brave_rewards_impl") { deps += [ "//extensions/browser" ] } - - if (enable_greaselion) { - deps += [ "//brave/browser/greaselion" ] - } } source_set("util") { diff --git a/browser/brave_rewards/creator_detection_script_injector.cc b/browser/brave_rewards/creator_detection_script_injector.cc new file mode 100644 index 000000000000..b8207cce1d38 --- /dev/null +++ b/browser/brave_rewards/creator_detection_script_injector.cc @@ -0,0 +1,173 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "brave/browser/brave_rewards/creator_detection_script_injector.h" + +#include + +#include "base/containers/fixed_flat_map.h" +#include "base/feature_list.h" +#include "base/functional/bind.h" +#include "base/strings/strcat.h" +#include "base/strings/utf_string_conversions.h" +#include "brave/browser/brave_rewards/rewards_util.h" +#include "brave/components/brave_rewards/common/features.h" +#include "brave/components/brave_rewards/common/pref_names.h" +#include "brave/components/brave_rewards/common/publisher_utils.h" +#include "brave/components/brave_rewards/resources/grit/creator_detection_generated.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_isolated_world_ids.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/common/content_client.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "ui/base/resource/resource_bundle.h" + +namespace brave_rewards { + +namespace { + +constexpr auto kScriptMap = base::MakeFixedFlatMap( + {{"github.com", IDR_CREATOR_DETECTION_GITHUB_BUNDLE_JS}, + {"www.github.com", IDR_CREATOR_DETECTION_GITHUB_BUNDLE_JS}, + {"gist.github.com", IDR_CREATOR_DETECTION_GITHUB_BUNDLE_JS}, + {"reddit.com", IDR_CREATOR_DETECTION_REDDIT_BUNDLE_JS}, + {"www.reddit.com", IDR_CREATOR_DETECTION_REDDIT_BUNDLE_JS}, + {"twitch.tv", IDR_CREATOR_DETECTION_TWITCH_BUNDLE_JS}, + {"www.twitch.tv", IDR_CREATOR_DETECTION_TWITCH_BUNDLE_JS}, + {"twitter.com", IDR_CREATOR_DETECTION_TWITTER_BUNDLE_JS}, + {"x.com", IDR_CREATOR_DETECTION_TWITTER_BUNDLE_JS}, + {"vimeo.com", IDR_CREATOR_DETECTION_VIMEO_BUNDLE_JS}, + {"www.youtube.com", IDR_CREATOR_DETECTION_YOUTUBE_BUNDLE_JS}, + {"m.youtube.com", IDR_CREATOR_DETECTION_YOUTUBE_BUNDLE_JS}}); + +std::string LoadScriptResource(int id) { + auto& bundle = ui::ResourceBundle::GetSharedInstance(); + if (bundle.IsGzipped(id)) { + return bundle.LoadDataResourceString(id); + } + return std::string(bundle.GetRawDataResource(id)); +} + +std::optional GetDetectionScript(content::RenderFrameHost* rfh) { + // Only run scripts for the main frame. + if (!rfh || !rfh->IsInPrimaryMainFrame()) { + return std::nullopt; + } + + // Only run scripts if the creator detection feature is enabled. + if (!base::FeatureList::IsEnabled( + features::kPlatformCreatorDetectionFeature)) { + return std::nullopt; + } + + auto* profile = Profile::FromBrowserContext(rfh->GetBrowserContext()); + + // Only run scripts if the Rewards service is available for this profile. + if (!IsSupportedForProfile(profile)) { + return std::nullopt; + } + + // Only run scripts if the user has enabled Brave Rewards. + if (!profile || !profile->GetPrefs()->GetBoolean(prefs::kEnabled)) { + return std::nullopt; + } + + // Only run scripts for known "media platform" sites. + GURL url = rfh->GetLastCommittedURL(); + if (!IsMediaPlatformURL(url)) { + return std::nullopt; + } + + // Only run scripts when there is an exact hostname match. + auto iter = kScriptMap.find(url.host_piece()); + if (iter == kScriptMap.end()) { + return std::nullopt; + } + + return LoadScriptResource(iter->second); +} + +} // namespace + +CreatorDetectionScriptInjector::CreatorDetectionScriptInjector() = default; +CreatorDetectionScriptInjector::~CreatorDetectionScriptInjector() = default; + +void CreatorDetectionScriptInjector::MaybeInjectScript( + content::RenderFrameHost* rfh) { + injector_.reset(); + injector_host_token_ = content::GlobalRenderFrameHostToken(); + + if (!rfh) { + return; + } + + auto script_source = GetDetectionScript(rfh); + if (!script_source) { + return; + } + + injector_host_token_ = rfh->GetGlobalFrameToken(); + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&injector_); + + // Execute the detection script. It must set `braveRewards.detectCreator` to a + // function. That function will be called by `DetectCreator`. + ExecuteScript(script_source.value(), base::DoNothing()); +} + +void CreatorDetectionScriptInjector::DetectCreator( + content::RenderFrameHost* rfh, + DetectCreatorCallback callback) { + if (!rfh || rfh->GetGlobalFrameToken() != injector_host_token_ || + !injector_.is_bound()) { + std::move(callback).Run(std::nullopt); + return; + } + + // Call the detection function set up by the detection script. + ExecuteScript( + "braveRewards.detectCreator()", + base::BindOnce(&CreatorDetectionScriptInjector::OnCreatorDetected, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void CreatorDetectionScriptInjector::ExecuteScript( + std::string_view script, + ExecuteScriptCallback callback) { + CHECK(injector_.is_bound()); + injector_->RequestAsyncExecuteScript( + ISOLATED_WORLD_ID_BRAVE_INTERNAL, base::UTF8ToUTF16(script), + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait, std::move(callback)); +} + +void CreatorDetectionScriptInjector::OnCreatorDetected( + DetectCreatorCallback callback, + base::Value value) { + Result result; + if (auto* dict = value.GetIfDict()) { + if (auto* id = dict->FindString("id")) { + result.id = *id; + } + if (auto* name = dict->FindString("name")) { + result.name = *name; + } + if (auto* url = dict->FindString("url")) { + result.url = *url; + } + if (auto* image_url = dict->FindString("imageURL")) { + result.image_url = *image_url; + } + } + std::move(callback).Run(std::move(result)); +} + +CreatorDetectionScriptInjector::Result::Result() = default; +CreatorDetectionScriptInjector::Result::~Result() = default; +CreatorDetectionScriptInjector::Result::Result(const Result&) = default; +CreatorDetectionScriptInjector::Result& +CreatorDetectionScriptInjector::Result::operator=(const Result&) = default; + +} // namespace brave_rewards diff --git a/browser/brave_rewards/creator_detection_script_injector.h b/browser/brave_rewards/creator_detection_script_injector.h new file mode 100644 index 000000000000..df38462f53fa --- /dev/null +++ b/browser/brave_rewards/creator_detection_script_injector.h @@ -0,0 +1,81 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#ifndef BRAVE_BROWSER_BRAVE_REWARDS_CREATOR_DETECTION_SCRIPT_INJECTOR_H_ +#define BRAVE_BROWSER_BRAVE_REWARDS_CREATOR_DETECTION_SCRIPT_INJECTOR_H_ + +#include +#include +#include + +#include "base/functional/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "brave/components/script_injector/common/mojom/script_injector.mojom.h" +#include "content/public/browser/global_routing_id.h" +#include "mojo/public/cpp/bindings/associated_remote.h" + +namespace content { +class RenderFrameHost; +} + +namespace brave_rewards { + +// Responsible for detecting Brave creator information associated with media +// platform pages, using JS scripts that are injected into an isolated world. +class CreatorDetectionScriptInjector { + public: + CreatorDetectionScriptInjector(); + ~CreatorDetectionScriptInjector(); + + CreatorDetectionScriptInjector(const CreatorDetectionScriptInjector&) = + delete; + CreatorDetectionScriptInjector& operator=( + const CreatorDetectionScriptInjector&) = delete; + + // Injects creator detection scripts (if appropriate) into an isolated world + // associated with the specified render frame host. The scripts are expected + // to set up a JS function that will later be called by `DetectCreator`. + void MaybeInjectScript(content::RenderFrameHost* rfh); + + struct Result { + Result(); + ~Result(); + Result(const Result&); + Result& operator=(const Result&); + + std::string id; + std::string name; + std::string url; + std::string image_url; + }; + + using DetectCreatorCallback = base::OnceCallback)>; + + // Runs the creator detection routine initialized by `MaybeInjectScript` and + // asynchrounously returns the detection result. Return `nullopt` if the + // detection routine was not invoked (e.g. because Rewards is not enabled or + // because there is no script for this page). Returns a `Result` with empty + // fields if there is not creator associated with the current page. Note that + // any of the `Result` fields may be empty if the detection script was unable + // to gather that information from the page. + void DetectCreator(content::RenderFrameHost* rfh, + DetectCreatorCallback callback); + + private: + using ExecuteScriptCallback = base::OnceCallback; + + void ExecuteScript(std::string_view script, ExecuteScriptCallback callback); + + void OnCreatorDetected(DetectCreatorCallback callback, base::Value value); + + mojo::AssociatedRemote injector_; + content::GlobalRenderFrameHostToken injector_host_token_; + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace brave_rewards + +#endif // BRAVE_BROWSER_BRAVE_REWARDS_CREATOR_DETECTION_SCRIPT_INJECTOR_H_ diff --git a/browser/brave_rewards/rewards_service_factory.cc b/browser/brave_rewards/rewards_service_factory.cc index 1bca8a4bc6d9..414063bb3679 100644 --- a/browser/brave_rewards/rewards_service_factory.cc +++ b/browser/brave_rewards/rewards_service_factory.cc @@ -16,7 +16,6 @@ #include "brave/components/brave_rewards/browser/rewards_service.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/rewards_service_observer.h" -#include "brave/components/greaselion/browser/buildflags/buildflags.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/incognito_helpers.h" @@ -31,10 +30,6 @@ #include "extensions/browser/event_router_factory.h" #endif -#if BUILDFLAG(ENABLE_GREASELION) -#include "brave/browser/greaselion/greaselion_service_factory.h" -#endif - namespace brave_rewards { RewardsService* testing_service_ = nullptr; @@ -65,9 +60,6 @@ RewardsServiceFactory::RewardsServiceFactory() BrowserContextDependencyManager::GetInstance()) { #if BUILDFLAG(ENABLE_EXTENSIONS) DependsOn(extensions::EventRouterFactory::GetInstance()); -#endif -#if BUILDFLAG(ENABLE_GREASELION) - DependsOn(greaselion::GreaselionServiceFactory::GetInstance()); #endif DependsOn(brave_wallet::BraveWalletServiceFactory::GetInstance()); } @@ -123,9 +115,6 @@ RewardsServiceFactory::BuildServiceInstanceForBrowserContext( profile, ServiceAccessType::EXPLICIT_ACCESS), request_image_callback, cancel_request_image_callback, profile->GetDefaultStoragePartition(), -#if BUILDFLAG(ENABLE_GREASELION) - greaselion::GreaselionServiceFactory::GetForBrowserContext(context), -#endif brave_wallet::BraveWalletServiceFactory::GetServiceForContext( context)); rewards_service->Init(std::move(extension_observer), diff --git a/browser/brave_rewards/rewards_tab_helper.cc b/browser/brave_rewards/rewards_tab_helper.cc index e21f4acce14d..9556f5ac4367 100644 --- a/browser/brave_rewards/rewards_tab_helper.cc +++ b/browser/brave_rewards/rewards_tab_helper.cc @@ -5,9 +5,11 @@ #include "brave/browser/brave_rewards/rewards_tab_helper.h" +#include + #include "brave/browser/brave_rewards/rewards_service_factory.h" -#include "brave/components/brave_rewards/browser/publisher_utils.h" #include "brave/components/brave_rewards/browser/rewards_service.h" +#include "brave/components/brave_rewards/common/publisher_utils.h" #include "chrome/browser/profiles/profile.h" #include "components/sessions/content/session_tab_helper.h" #include "content/public/browser/navigation_entry.h" @@ -98,19 +100,41 @@ void RewardsTabHelper::DidFinishLoad( rewards_service_->OnLoad(tab_id_, validated_url); } -void RewardsTabHelper::DidFinishNavigation(content::NavigationHandle* handle) { - if (!handle->IsInMainFrame() || !handle->HasCommitted() || - handle->IsDownload()) { +void RewardsTabHelper::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->HasCommitted() || + !navigation_handle->IsInPrimaryMainFrame() || + navigation_handle->IsDownload()) { return; } - auto id = GetPublisherIdFromURL(GetWebContents().GetLastCommittedURL()); - SetPublisherIdForTab(id ? *id : ""); + if (!rewards_service_) { + return; + } - MaybeSavePublisherInfo(); + auto& url = navigation_handle->GetURL(); - if (rewards_service_) { + if (!navigation_handle->IsSameDocument()) { + auto id = GetPublisherIdFromURL(url); + SetPublisherIdForTab(id ? *id : ""); + MaybeSavePublisherInfo(); rewards_service_->OnUnload(tab_id_); + creator_detection_.MaybeInjectScript( + navigation_handle->GetRenderFrameHost()); + } + + // Only invoke creator detection if the URL has changed. + if (url != last_detection_url_) { + last_detection_url_ = url; + + // Store the current navigation ID so that we can determine if the async + // result corresponds to this navigation. + detection_navigation_id_ = navigation_handle->GetNavigationId(); + + creator_detection_.DetectCreator( + navigation_handle->GetRenderFrameHost(), + base::BindOnce(&RewardsTabHelper::OnCreatorDetected, + base::Unretained(this), detection_navigation_id_)); } } @@ -192,13 +216,50 @@ void RewardsTabHelper::MaybeSavePublisherInfo() { } // The Rewards system currently assumes that the |publisher_info| table is - // populated by calling `GetPublisherActivityFromUrl` as the user nativates + // populated by calling `GetPublisherActivityFromUrl` as the user navigates // the web. Previously, this was accomplished within the background script of // the Rewards extension. rewards_service_->GetPublisherActivityFromUrl( tab_id_.id(), GetWebContents().GetLastCommittedURL().spec(), "", ""); } +void RewardsTabHelper::OnCreatorDetected( + int64_t navigation_id, + std::optional result) { + if (!result || navigation_id != detection_navigation_id_) { + return; + } + + SetPublisherIdForTab(result->id); + + if (!result->id.empty()) { + auto visit = mojom::VisitData::New(); + visit->tab_id = static_cast(tab_id_.id()); + visit->domain = result->id; + visit->name = result->name; + visit->path = ""; + visit->url = result->url; + visit->favicon_url = result->image_url; + if (auto platform = GetMediaPlatformFromPublisherId(result->id)) { + visit->provider = *platform; + } + + CHECK(rewards_service_); + + // When a creator has been detected for the current tab, we must send the + // creator data to the utility process so that the "publisher_info" database + // table can be populated. + // TODO(https://github.com/brave/brave-browser/issues/41832): Rename and + // possibly refactor this API. + rewards_service_->GetPublisherActivityFromVisitData(visit->Clone()); + + // Notify the Rewards service that a "page view" has started for this + // creator. + rewards_service_->OnShow(tab_id_); + rewards_service_->OnLoad(std::move(visit)); + } +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(RewardsTabHelper); } // namespace brave_rewards diff --git a/browser/brave_rewards/rewards_tab_helper.h b/browser/brave_rewards/rewards_tab_helper.h index 685d70c1c8aa..8a07ff33dc9f 100644 --- a/browser/brave_rewards/rewards_tab_helper.h +++ b/browser/brave_rewards/rewards_tab_helper.h @@ -7,12 +7,14 @@ #define BRAVE_BROWSER_BRAVE_REWARDS_REWARDS_TAB_HELPER_H_ #include +#include #include #include "base/memory/raw_ptr.h" #include "base/observer_list.h" #include "base/observer_list_types.h" #include "base/scoped_observation.h" +#include "brave/browser/brave_rewards/creator_detection_script_injector.h" #include "brave/components/brave_rewards/browser/rewards_service_observer.h" #include "build/build_config.h" #include "components/sessions/core/session_id.h" @@ -85,6 +87,10 @@ class RewardsTabHelper : public content::WebContentsUserData, void MaybeSavePublisherInfo(); + void OnCreatorDetected( + int64_t navigation_id, + std::optional result); + #if !BUILDFLAG(IS_ANDROID) std::unique_ptr browser_list_observer_; #endif @@ -95,6 +101,9 @@ class RewardsTabHelper : public content::WebContentsUserData, raw_ptr rewards_service_ = nullptr; base::ObserverList observer_list_; std::string publisher_id_; + GURL last_detection_url_; + int64_t detection_navigation_id_ = 0; + CreatorDetectionScriptInjector creator_detection_; WEB_CONTENTS_USER_DATA_KEY_DECL(); }; diff --git a/browser/brave_rewards/test/BUILD.gn b/browser/brave_rewards/test/BUILD.gn index f585b6a5fae9..85858e3fafec 100644 --- a/browser/brave_rewards/test/BUILD.gn +++ b/browser/brave_rewards/test/BUILD.gn @@ -7,36 +7,43 @@ import("//testing/test.gni") source_set("browser_tests") { testonly = true + + sources = [ "creator_detection_browsertest.cc" ] + + deps = [ + "//base/test:test_support", + "//brave/browser/brave_rewards", + "//brave/components/brave_rewards/common", + "//brave/components/brave_rewards/common:features", + "//chrome/browser/profiles:profile", + "//chrome/browser/ui", + "//chrome/test:test_support", + "//chrome/test:test_support_ui", + "//components/prefs", + "//content/test:test_support", + ] + + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + + # TODO(https://github.com/brave/brave-browser/issues/41833): Update these + # tests to run on Android as well. if (!is_android) { - sources = [ + sources += [ "rewards_ofac_browsertest.cc", "rewards_page_browsertest.cc", "rewards_policy_browsertest.cc", ] - deps = [ - "//base/test:test_support", + deps += [ "//brave/app:command_ids", "//brave/browser", "//brave/browser/brave_ads", - "//brave/browser/brave_rewards", "//brave/browser/brave_rewards:util", "//brave/components/brave_rewards/browser", - "//brave/components/brave_rewards/common", - "//brave/components/brave_rewards/common:features", "//brave/components/l10n/common:test_support", - "//chrome/browser/ui", - "//chrome/test:test_support", - "//chrome/test:test_support_ui", "//components/policy/core/browser", "//components/policy/core/common:test_support", - "//components/prefs:prefs", - "//components/user_prefs:user_prefs", - "//content/test:test_support", - "//testing/gtest", - "//url", + "//components/user_prefs", ] - - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] } } # source_set("browser_tests") diff --git a/browser/brave_rewards/test/creator_detection_browsertest.cc b/browser/brave_rewards/test/creator_detection_browsertest.cc new file mode 100644 index 000000000000..dd39c6babf85 --- /dev/null +++ b/browser/brave_rewards/test/creator_detection_browsertest.cc @@ -0,0 +1,445 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include + +#include "base/memory/raw_ref.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" +#include "base/timer/timer.h" +#include "brave/browser/brave_rewards/rewards_service_factory.h" +#include "brave/browser/brave_rewards/rewards_tab_helper.h" +#include "brave/components/brave_rewards/browser/rewards_service.h" +#include "brave/components/brave_rewards/common/features.h" +#include "brave/components/brave_rewards/common/pref_names.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "chrome/test/base/platform_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/prefs/pref_service.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" + +using base::test::TestFuture; +using net::test_server::BasicHttpResponse; +using net::test_server::HttpRequest; +using net::test_server::HttpResponse; + +namespace brave_rewards { + +class CreatorDetectionBrowserTest : public PlatformBrowserTest { + protected: + CreatorDetectionBrowserTest() { + scoped_feature_list_.InitWithFeatures( + {features::kPlatformCreatorDetectionFeature}, {}); + } + + ~CreatorDetectionBrowserTest() override = default; + + void DisableFeature() { + scoped_feature_list_.Reset(); + scoped_feature_list_.InitWithFeatures( + {}, {features::kPlatformCreatorDetectionFeature}); + } + + void SetUpOnMainThread() override { + PlatformBrowserTest::SetUpOnMainThread(); + + host_resolver()->AddRule("*", "127.0.0.1"); + embedded_https_test_server().SetCertHostnames( + {"twitter.com", "github.com", "api.github.com", "reddit.com", + "www.twitch.tv", "vimeo.com", "www.youtube.com", "abc.youtube.com", + "example-creator.com"}); + embedded_https_test_server().RegisterRequestHandler(base::BindRepeating( + &CreatorDetectionBrowserTest::HandleRequest, base::Unretained(this))); + CHECK(embedded_https_test_server().Start()); + } + + void TearDownOnMainThread() override { + EXPECT_TRUE(embedded_https_test_server().ShutdownAndWaitUntilComplete()); + PlatformBrowserTest::TearDownOnMainThread(); + } + + using RequestCallback = + base::RepeatingCallback; + + template + void SetRequestCallback(F callback) { + request_callback_ = base::BindLambdaForTesting(callback); + } + + void SetResponseHTML(std::string_view html) { + std::string content(html); + SetRequestCallback( + [content](std::string_view path, BasicHttpResponse& response) { + response.set_content(content); + }); + } + + bool NavigateTo(std::string_view host, std::string_view path) { + auto url = embedded_https_test_server().GetURL(host, path); + return ui_test_utils::NavigateToURL(browser(), url); + } + + RewardsTabHelper& GetRewardsTabHelper() { + auto* web_contents = chrome_test_utils::GetActiveWebContents(this); + CHECK(web_contents); + auto* tab_helper = RewardsTabHelper::FromWebContents(web_contents); + CHECK(tab_helper); + return *tab_helper; + } + + void WaitForTimeout() { + base::RunLoop run_loop; + base::OneShotTimer timeout; + timeout.Start(FROM_HERE, base::Seconds(2), run_loop.QuitClosure()); + run_loop.Run(); + } + + RewardsService& GetRewardsService() { + auto* rewards_service = + RewardsServiceFactory::GetForProfile(browser()->profile()); + CHECK(rewards_service); + return *rewards_service; + } + + void EnableRewards() { + auto* prefs = browser()->profile()->GetPrefs(); + prefs->SetBoolean(brave_rewards::prefs::kEnabled, true); + + TestFuture future; + GetRewardsService().CreateRewardsWallet("US", future.GetCallback()); + CHECK(future.Wait()); + } + + mojom::PublisherInfoPtr WaitForPublisherInfo(const std::string& id) { + for (;;) { + TestFuture future; + GetRewardsService().GetPublisherInfo(id, future.GetCallback()); + auto info = std::get<1>(future.Take()); + if (info) { + return info; + } + WaitForTimeout(); + } + } + + class TabHelperObserver : public RewardsTabHelper::Observer { + public: + TabHelperObserver(RewardsTabHelper& tab_helper, + base::OnceCallback callback) + : callback_(std::move(callback)) { + tab_helper_observation_.Observe(&tab_helper); + } + + ~TabHelperObserver() override = default; + + void OnPublisherForTabUpdated(const std::string& publisher_id) override { + if (callback_) { + std::move(callback_).Run(publisher_id); + } + } + + private: + base::OnceCallback callback_; + RewardsTabHelper::Observation tab_helper_observation_{this}; + }; + + private: + std::unique_ptr HandleRequest(const HttpRequest& request) { + auto response = std::make_unique(); + response->set_code(net::HTTP_OK); + response->set_content_type("text/html;charset=utf-8"); + if (request_callback_) { + request_callback_.Run(request.relative_url, *response); + } + return response; + } + + base::test::ScopedFeatureList scoped_feature_list_; + RequestCallback request_callback_; + std::string response_html_; +}; + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, NonPlatformSite) { + EnableRewards(); + + SetResponseHTML(R"( + + + Example creator + + )"); + + AddBlankTabAndShow(browser()); + TestFuture id_future; + TabHelperObserver observer(GetRewardsTabHelper(), id_future.GetCallback()); + ASSERT_TRUE(NavigateTo("example-creator.com", "/")); + EXPECT_EQ(id_future.Get(), "example-creator.com"); + EXPECT_TRUE(WaitForPublisherInfo("example-creator.com")); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, GithubDetection) { + EnableRewards(); + + SetRequestCallback([](std::string_view path, BasicHttpResponse& response) { + if (path == "/users/testuser") { + response.AddCustomHeader("Access-Control-Allow-Origin", "*"); + response.set_content_type("application/json"); + response.set_content(R"( + {"id": "1234567", + "avatar_url": "https://github.com/user-avatar"} )"); + return; + } + }); + + AddBlankTabAndShow(browser()); + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("github.com", "/testuser")); + EXPECT_EQ(future.Get(), "github#channel:1234567"); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, RedditDetection) { + EnableRewards(); + + SetRequestCallback([](std::string_view path, BasicHttpResponse& response) { + if (path == "/user/testuser/about.json") { + response.set_content_type("application/json"); + response.set_content(R"( + {"kind": "t2", + "data": { + "id": "987654321", + "icon_img": "https://reddit.com/user-avatar"}} )"); + return; + } + }); + + AddBlankTabAndShow(browser()); + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("reddit.com", "/user/testuser")); + + EXPECT_EQ(future.Get(), "reddit#channel:987654321"); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, TwitchDetection) { + EnableRewards(); + + SetResponseHTML(R"( + + + +

Name

+
+
+ +
+
+ + + )"); + + AddBlankTabAndShow(browser()); + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("www.twitch.tv", "/testuser")); + + EXPECT_EQ(future.Get(), "twitch#author:testuser"); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, TwitterDetection) { + EnableRewards(); + + SetResponseHTML(R"( + + + + + + +
+
+
+ + + )"); + + AddBlankTabAndShow(browser()); + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("twitter.com", "/testuser")); + + EXPECT_EQ(future.Get(), "twitter#channel:987654321"); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, VimeoDetection) { + EnableRewards(); + + SetResponseHTML(R"( + + + + + + + + + )"); + + AddBlankTabAndShow(browser()); + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("vimeo.com", "/testuser")); + + EXPECT_EQ(future.Get(), "vimeo#channel:987654321"); +} + +constexpr std::string_view kYouTubeHTML = R"( + + + + + + + + + + +
+ +
+ + + +)"; + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, YouTubeDetection) { + EnableRewards(); + SetResponseHTML(kYouTubeHTML); + + AddBlankTabAndShow(browser()); + + { + // Initial page load. + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("www.youtube.com", "/@testuser")); + EXPECT_EQ(future.Get(), "youtube#channel:987654321"); + } + + { + // Same-document navigation via `history.pushState`. + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + auto* web_contents = chrome_test_utils::GetActiveWebContents(this); + EXPECT_TRUE(content::ExecJs(web_contents, "triggerSameDocNav()")); + EXPECT_EQ(future.Get(), "youtube#channel:123456789"); + } + + { + // Navigation away from the page. + TestFuture future; + TabHelperObserver observer(GetRewardsTabHelper(), future.GetCallback()); + ASSERT_TRUE(NavigateTo("abc.youtube.com", "/@testuser")); + WaitForTimeout(); + EXPECT_EQ(GetRewardsTabHelper().GetPublisherIdForTab(), ""); + } + + // Ensure that publisher info is stored in the Rewards database appropriately. + auto info = WaitForPublisherInfo("youtube#channel:987654321"); + ASSERT_TRUE(info); + EXPECT_EQ(info->name, "testuser"); + EXPECT_EQ(info->url, embedded_https_test_server().GetURL("www.youtube.com", + "/@testuser")); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, InvalidHost) { + EnableRewards(); + SetResponseHTML(kYouTubeHTML); + AddBlankTabAndShow(browser()); + ASSERT_TRUE(NavigateTo("abc.youtube.com", "/@testuser")); + WaitForTimeout(); + EXPECT_EQ(GetRewardsTabHelper().GetPublisherIdForTab(), ""); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, RewardsDisabled) { + SetResponseHTML(kYouTubeHTML); + AddBlankTabAndShow(browser()); + ASSERT_TRUE(NavigateTo("www.youtube.com", "/@testuser")); + WaitForTimeout(); + EXPECT_EQ(GetRewardsTabHelper().GetPublisherIdForTab(), ""); +} + +IN_PROC_BROWSER_TEST_F(CreatorDetectionBrowserTest, IncognitoProfile) { + EnableRewards(); + SetResponseHTML(kYouTubeHTML); + auto* incognito_browser = CreateIncognitoBrowser(); + AddBlankTabAndShow(incognito_browser); + auto url = + embedded_https_test_server().GetURL("www.youtube.com", "/@testuser"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(incognito_browser, url)); + WaitForTimeout(); + EXPECT_EQ(GetRewardsTabHelper().GetPublisherIdForTab(), ""); +} + +class CreatorDetectionFeatureDisabledBrowserTest + : public CreatorDetectionBrowserTest { + public: + CreatorDetectionFeatureDisabledBrowserTest() { DisableFeature(); } +}; + +IN_PROC_BROWSER_TEST_F(CreatorDetectionFeatureDisabledBrowserTest, + FeatureDisabled) { + EnableRewards(); + SetResponseHTML(kYouTubeHTML); + AddBlankTabAndShow(browser()); + ASSERT_TRUE(NavigateTo("www.youtube.com", "/@testuser")); + WaitForTimeout(); + EXPECT_EQ(GetRewardsTabHelper().GetPublisherIdForTab(), ""); +} + +} // namespace brave_rewards diff --git a/browser/extensions/BUILD.gn b/browser/extensions/BUILD.gn index 526823f77265..bf9062e82730 100644 --- a/browser/extensions/BUILD.gn +++ b/browser/extensions/BUILD.gn @@ -25,11 +25,9 @@ source_set("component_loader") { deps = [ "//base", - "//brave/browser/brave_rewards:util", "//brave/browser/ethereum_remote_client/buildflags", "//brave/components/brave_component_updater/browser", "//brave/components/brave_extension:static_resources", - "//brave/components/brave_rewards/common", "//brave/components/brave_webtorrent:static_resources", "//chrome/browser:browser_process", "//chrome/browser/extensions", diff --git a/browser/extensions/api/brave_rewards_api.cc b/browser/extensions/api/brave_rewards_api.cc index 43ec0f2a8721..b95a4f467674 100644 --- a/browser/extensions/api/brave_rewards_api.cc +++ b/browser/extensions/api/brave_rewards_api.cc @@ -157,29 +157,6 @@ ExtensionFunction::ResponseAction BraveRewardsOpenRewardsPanelFunction::Run() { return RespondNow(NoArguments()); } -BraveRewardsUpdateMediaDurationFunction:: - ~BraveRewardsUpdateMediaDurationFunction() = default; - -ExtensionFunction::ResponseAction -BraveRewardsUpdateMediaDurationFunction::Run() { - std::optional params = - brave_rewards::UpdateMediaDuration::Params::Create(args()); - EXTENSION_FUNCTION_VALIDATE(params); - - Profile* profile = Profile::FromBrowserContext(browser_context()); - RewardsService* rewards_service = - RewardsServiceFactory::GetForProfile(profile); - - if (!rewards_service) { - return RespondNow(NoArguments()); - } - - rewards_service->UpdateMediaDuration(params->window_id, params->publisher_key, - params->duration, params->first_visit); - - return RespondNow(NoArguments()); -} - BraveRewardsGetPublisherInfoFunction::~BraveRewardsGetPublisherInfoFunction() = default; @@ -226,24 +203,6 @@ void BraveRewardsGetPublisherInfoFunction::OnGetPublisherInfo( Respond(WithArguments(static_cast(result), std::move(dict))); } -BraveRewardsSetPublisherIdForTabFunction:: - ~BraveRewardsSetPublisherIdForTabFunction() = default; - -ExtensionFunction::ResponseAction -BraveRewardsSetPublisherIdForTabFunction::Run() { - auto params = brave_rewards::SetPublisherIdForTab::Params::Create(args()); - EXTENSION_FUNCTION_VALIDATE(params); - - auto* tab_helper = - GetRewardsTabHelperForTabId(params->tab_id, browser_context()); - - if (tab_helper) { - tab_helper->SetPublisherIdForTab(params->publisher_id); - } - - return RespondNow(NoArguments()); -} - BraveRewardsGetPublisherInfoForTabFunction:: ~BraveRewardsGetPublisherInfoForTabFunction() = default; @@ -300,90 +259,6 @@ void BraveRewardsGetPublisherInfoForTabFunction::OnGetPublisherPanelInfo( Respond(WithArguments(std::move(dict))); } -BraveRewardsGetPublisherPanelInfoFunction:: - ~BraveRewardsGetPublisherPanelInfoFunction() = default; - -ExtensionFunction::ResponseAction -BraveRewardsGetPublisherPanelInfoFunction::Run() { - std::optional params = - brave_rewards::GetPublisherPanelInfo::Params::Create(args()); - EXTENSION_FUNCTION_VALIDATE(params); - - Profile* profile = Profile::FromBrowserContext(browser_context()); - RewardsService* rewards_service = - RewardsServiceFactory::GetForProfile(profile); - - if (!rewards_service) { - return RespondNow(Error("Rewards service is not available")); - } - - rewards_service->GetPublisherPanelInfo( - params->publisher_key, - base::BindOnce( - &BraveRewardsGetPublisherPanelInfoFunction::OnGetPublisherPanelInfo, - this)); - - return RespondLater(); -} - -void BraveRewardsGetPublisherPanelInfoFunction::OnGetPublisherPanelInfo( - const ::brave_rewards::mojom::Result result, - ::brave_rewards::mojom::PublisherInfoPtr info) { - if (!info) { - Respond(WithArguments(static_cast(result))); - return; - } - - base::Value::Dict dict; - dict.Set("publisherKey", info->id); - dict.Set("name", info->name); - dict.Set("percentage", static_cast(info->percent)); - dict.Set("status", static_cast(info->status)); - dict.Set("excluded", info->excluded == - ::brave_rewards::mojom::PublisherExclude::EXCLUDED); - dict.Set("url", info->url); - dict.Set("provider", info->provider); - dict.Set("favIconUrl", info->favicon_url); - - Respond(WithArguments(static_cast(result), std::move(dict))); -} - -BraveRewardsSavePublisherInfoFunction:: - ~BraveRewardsSavePublisherInfoFunction() = default; - -ExtensionFunction::ResponseAction BraveRewardsSavePublisherInfoFunction::Run() { - std::optional params = - brave_rewards::SavePublisherInfo::Params::Create(args()); - EXTENSION_FUNCTION_VALIDATE(params); - - Profile* profile = Profile::FromBrowserContext(browser_context()); - RewardsService* rewards_service = - RewardsServiceFactory::GetForProfile(profile); - - if (!rewards_service) { - return RespondNow(Error("Rewards service is not available")); - } - - auto publisher_info = ::brave_rewards::mojom::PublisherInfo::New(); - publisher_info->id = params->publisher_key; - publisher_info->name = params->publisher_name; - publisher_info->url = params->url; - publisher_info->provider = params->media_type; - publisher_info->favicon_url = params->fav_icon_url; - - rewards_service->SavePublisherInfo( - params->window_id, std::move(publisher_info), - base::BindOnce( - &BraveRewardsSavePublisherInfoFunction::OnSavePublisherInfo, this)); - - return RespondLater(); -} - -void BraveRewardsSavePublisherInfoFunction::OnSavePublisherInfo( - const ::brave_rewards::mojom::Result result) { - Respond(WithArguments(static_cast(result))); -} - BraveRewardsTipSiteFunction::~BraveRewardsTipSiteFunction() = default; ExtensionFunction::ResponseAction BraveRewardsTipSiteFunction::Run() { @@ -424,22 +299,6 @@ BraveRewardsIncludeInAutoContributionFunction::Run() { return RespondNow(NoArguments()); } -BraveRewardsGetPublisherDataFunction::~BraveRewardsGetPublisherDataFunction() = - default; - -ExtensionFunction::ResponseAction BraveRewardsGetPublisherDataFunction::Run() { - std::optional params = - brave_rewards::GetPublisherData::Params::Create(args()); - Profile* profile = Profile::FromBrowserContext(browser_context()); - auto* rewards_service = RewardsServiceFactory::GetForProfile(profile); - if (rewards_service) { - rewards_service->GetPublisherActivityFromUrl(params->window_id, params->url, - params->favicon_url, - params->publisher_blob); - } - return RespondNow(NoArguments()); -} - BraveRewardsGetRewardsParametersFunction:: ~BraveRewardsGetRewardsParametersFunction() = default; diff --git a/browser/extensions/api/brave_rewards_api.h b/browser/extensions/api/brave_rewards_api.h index 7746acacf92d..512b9f08637a 100644 --- a/browser/extensions/api/brave_rewards_api.h +++ b/browser/extensions/api/brave_rewards_api.h @@ -48,16 +48,6 @@ class BraveRewardsOpenRewardsPanelFunction : public ExtensionFunction { ResponseAction Run() override; }; -class BraveRewardsUpdateMediaDurationFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("braveRewards.updateMediaDuration", UNKNOWN) - - protected: - ~BraveRewardsUpdateMediaDurationFunction() override; - - ResponseAction Run() override; -}; - class BraveRewardsGetPublisherInfoFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveRewards.getPublisherInfo", UNKNOWN) @@ -72,15 +62,6 @@ class BraveRewardsGetPublisherInfoFunction : public ExtensionFunction { brave_rewards::mojom::PublisherInfoPtr info); }; -class BraveRewardsSetPublisherIdForTabFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("braveRewards.setPublisherIdForTab", UNKNOWN) - - protected: - ~BraveRewardsSetPublisherIdForTabFunction() override; - ResponseAction Run() override; -}; - class BraveRewardsGetPublisherInfoForTabFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveRewards.getPublisherInfoForTab", UNKNOWN) @@ -95,33 +76,6 @@ class BraveRewardsGetPublisherInfoForTabFunction : public ExtensionFunction { brave_rewards::mojom::PublisherInfoPtr info); }; -class BraveRewardsGetPublisherPanelInfoFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("braveRewards.getPublisherPanelInfo", UNKNOWN) - - protected: - ~BraveRewardsGetPublisherPanelInfoFunction() override; - - ResponseAction Run() override; - - private: - void OnGetPublisherPanelInfo(const brave_rewards::mojom::Result result, - brave_rewards::mojom::PublisherInfoPtr info); -}; - -class BraveRewardsSavePublisherInfoFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("braveRewards.savePublisherInfo", UNKNOWN) - - protected: - ~BraveRewardsSavePublisherInfoFunction() override; - - ResponseAction Run() override; - - private: - void OnSavePublisherInfo(const brave_rewards::mojom::Result result); -}; - class BraveRewardsTipSiteFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveRewards.tipSite", UNKNOWN) @@ -132,16 +86,6 @@ class BraveRewardsTipSiteFunction : public ExtensionFunction { ResponseAction Run() override; }; -class BraveRewardsGetPublisherDataFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("braveRewards.getPublisherData", UNKNOWN) - - protected: - ~BraveRewardsGetPublisherDataFunction() override; - - ResponseAction Run() override; -}; - class BraveRewardsGetRewardsParametersFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveRewards.getRewardsParameters", UNKNOWN) diff --git a/browser/extensions/brave_component_loader.cc b/browser/extensions/brave_component_loader.cc index c18390e8e878..37db7dbfb8bb 100644 --- a/browser/extensions/brave_component_loader.cc +++ b/browser/extensions/brave_component_loader.cc @@ -11,11 +11,9 @@ #include "base/command_line.h" #include "base/functional/bind.h" #include "base/json/json_reader.h" -#include "brave/browser/brave_rewards/rewards_util.h" #include "brave/components/brave_component_updater/browser/brave_component_installer.h" #include "brave/components/brave_component_updater/browser/brave_on_demand_updater.h" #include "brave/components/brave_extension/grit/brave_extension.h" -#include "brave/components/brave_rewards/common/pref_names.h" #include "brave/components/brave_webtorrent/grit/brave_webtorrent_resources.h" #include "brave/components/constants/brave_switches.h" #include "brave/components/constants/pref_names.h" @@ -53,11 +51,6 @@ BraveComponentLoader::BraveComponentLoader(ExtensionSystem* extension_system, kWebDiscoveryEnabled, base::BindRepeating(&BraveComponentLoader::UpdateBraveExtension, base::Unretained(this))); - - pref_change_registrar_.Add( - brave_rewards::prefs::kEnabled, - base::BindRepeating(&BraveComponentLoader::UpdateBraveExtension, - base::Unretained(this))); } BraveComponentLoader::~BraveComponentLoader() = default; @@ -155,8 +148,7 @@ void BraveComponentLoader::AddWebTorrentExtension() { bool BraveComponentLoader::UseBraveExtensionBackgroundPage() { // Keep sync with `pref_change_registrar_` in the ctor. - return profile_prefs_->GetBoolean(brave_rewards::prefs::kEnabled) || - profile_prefs_->GetBoolean(kWebDiscoveryEnabled); + return profile_prefs_->GetBoolean(kWebDiscoveryEnabled); } void BraveComponentLoader::UpdateBraveExtension() { diff --git a/browser/greaselion/BUILD.gn b/browser/greaselion/BUILD.gn index b3e0e121799b..9876244425ba 100644 --- a/browser/greaselion/BUILD.gn +++ b/browser/greaselion/BUILD.gn @@ -16,7 +16,6 @@ source_set("greaselion") { deps = [ "//base", "//brave/browser:browser_process", - "//brave/components/brave_rewards/common", "//brave/components/greaselion/browser", "//chrome/browser/extensions", "//chrome/browser/profiles", diff --git a/browser/greaselion/greaselion_browsertest.cc b/browser/greaselion/greaselion_browsertest.cc deleted file mode 100644 index a41f10532336..000000000000 --- a/browser/greaselion/greaselion_browsertest.cc +++ /dev/null @@ -1,621 +0,0 @@ -/* Copyright (c) 2019 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "base/containers/flat_map.h" -#include "base/files/file_enumerator.h" -#include "base/memory/raw_ptr.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/scoped_observation.h" -#include "base/task/thread_pool.h" -#include "base/test/bind.h" -#include "base/test/thread_test_helper.h" -#include "brave/browser/brave_browser_process.h" -#include "brave/browser/brave_rewards/rewards_service_factory.h" -#include "brave/browser/extensions/brave_base_local_data_files_browsertest.h" -#include "brave/browser/greaselion/greaselion_service_factory.h" -#include "brave/components/brave_component_updater/browser/local_data_files_service.h" -#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_network_util.h" -#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_response.h" -#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_util.h" -#include "brave/components/brave_rewards/common/pref_names.h" -#include "brave/components/constants/brave_paths.h" -#include "brave/components/greaselion/browser/greaselion_download_service.h" -#include "brave/components/greaselion/browser/greaselion_service.h" -#include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/prefs/pref_service.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "extensions/common/file_util.h" -#include "ui/base/ui_base_switches.h" - -using brave_rewards::RewardsService; -using brave_rewards::RewardsServiceFactory; -using brave_rewards::RewardsServiceImpl; -using brave_rewards::test_util::RewardsBrowserTestResponse; -using extensions::ExtensionBrowserTest; -using greaselion::GreaselionDownloadService; -using greaselion::GreaselionService; -using greaselion::GreaselionServiceFactory; - -constexpr char kTestDataDirectory[] = "greaselion-data"; -constexpr char kEmbeddedTestServerDirectory[] = "greaselion"; - -constexpr char kWaitForTitleChangeScript[] = R"( - new Promise((resolve) => { - if (document.title !== 'OK') { - resolve(document.title) - } else { - new MutationObserver(function(mutations) { - resolve(mutations[0].target.text) - }).observe( - document.querySelector('title'), - { subtree: true, characterData: true, childList: true } - ); - } - }) -)"; - -class GreaselionDownloadServiceWaiter - : public GreaselionDownloadService::Observer { - public: - explicit GreaselionDownloadServiceWaiter( - GreaselionDownloadService* download_service) - : download_service_(download_service) { - scoped_observer_.Observe(download_service_); - } - GreaselionDownloadServiceWaiter(const GreaselionDownloadServiceWaiter&) = - delete; - GreaselionDownloadServiceWaiter& operator=( - const GreaselionDownloadServiceWaiter&) = delete; - ~GreaselionDownloadServiceWaiter() override = default; - - void Wait() { run_loop_.Run(); } - - private: - // GreaselionDownloadService::Observer: - void OnRulesReady(GreaselionDownloadService* download_service) override { - run_loop_.QuitWhenIdle(); - } - - const raw_ptr download_service_; - base::RunLoop run_loop_; - base::ScopedObservation - scoped_observer_{this}; -}; - -class GreaselionServiceWaiter : public GreaselionService::Observer { - public: - explicit GreaselionServiceWaiter(GreaselionService* greaselion_service) - : greaselion_service_(greaselion_service) { - scoped_observer_.Observe(greaselion_service_); - } - GreaselionServiceWaiter(const GreaselionServiceWaiter&) = delete; - GreaselionServiceWaiter& operator=(const GreaselionServiceWaiter&) = delete; - ~GreaselionServiceWaiter() override = default; - - void Wait() { - if (greaselion_service_->update_in_progress()) { - run_loop_.Run(); - } - } - - private: - // GreaselionService::Observer: - void OnExtensionsReady(GreaselionService* greaselion_service, - bool success) override { - ASSERT_TRUE(success); - run_loop_.QuitWhenIdle(); - } - - const raw_ptr greaselion_service_; - base::RunLoop run_loop_; - base::ScopedObservation - scoped_observer_{this}; -}; - -class GreaselionServiceTest : public BaseLocalDataFilesBrowserTest { - public: - GreaselionServiceTest(): https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - response_ = std::make_unique(); - } - - void SetUpOnMainThread() override { - BaseLocalDataFilesBrowserTest::SetUpOnMainThread(); - base::ScopedAllowBlockingForTesting allow_blocking; - response_->LoadMocks(); - profile()->GetPrefs()->SetBoolean(brave_rewards::prefs::kEnabled, true); - } - - // BaseLocalDataFilesBrowserTest overrides - const char* test_data_directory() override { return kTestDataDirectory; } - const char* embedded_test_server_directory() override { - return kEmbeddedTestServerDirectory; - } - LocalDataFilesObserver* service() override { - return g_brave_browser_process->greaselion_download_service(); - } - - void WaitForService() override { - // wait for Greaselion download service to load and parse its - // configuration file - greaselion::GreaselionDownloadService* download_service = - g_brave_browser_process->greaselion_download_service(); - GreaselionDownloadServiceWaiter(download_service).Wait(); - GreaselionService* greaselion_service = - GreaselionServiceFactory::GetForBrowserContext(profile()); - // Give a consistent browser version for testing. - static const base::NoDestructor version("1.2.3.4"); - greaselion_service->SetBrowserVersionForTesting(*version); - // wait for the Greaselion service to install all the extensions it creates - GreaselionServiceWaiter(greaselion_service).Wait(); - } - - int GetRulesSize() { - return g_brave_browser_process->greaselion_download_service() - ->rules() - ->size(); - } - - void ClearRules() { - g_brave_browser_process->greaselion_download_service()->rules()->clear(); - } - - void StartRewards() { - // HTTP resolver - https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); - https_server_.RegisterRequestHandler( - base::BindRepeating(&brave_rewards::test_util::HandleRequest)); - ASSERT_TRUE(https_server_.Start()); - - // Rewards service - rewards_service_ = static_cast( - RewardsServiceFactory::GetForProfile(profile())); - brave_rewards::test_util::StartProcess(rewards_service_); - - // Response mock - rewards_service_->ForTestingSetTestResponseCallback( - base::BindRepeating( - &GreaselionServiceTest::GetTestResponse, - base::Unretained(this))); - rewards_service_->SetEngineEnvForTesting(); - GreaselionService* greaselion_service = - GreaselionServiceFactory::GetForBrowserContext(profile()); - // wait for the Greaselion service to install all the extensions it creates - // after the rewards service is turned off or on - GreaselionServiceWaiter(greaselion_service).Wait(); - } - - void WaitForAutoContributeEnabled() { - auto* prefs = browser()->profile()->GetPrefs(); - if (prefs->GetBoolean(brave_rewards::prefs::kAutoContributeEnabled)) { - return; - } - - base::RunLoop run_loop; - PrefChangeRegistrar pref_change_registrar; - pref_change_registrar.Init(prefs); - pref_change_registrar.Add( - brave_rewards::prefs::kAutoContributeEnabled, - base::BindLambdaForTesting([&run_loop, &prefs] { - if (prefs->GetBoolean(brave_rewards::prefs::kAutoContributeEnabled)) { - run_loop.Quit(); - } - })); - run_loop.Run(); - } - - void GetTestResponse( - const std::string& url, - int32_t method, - int* response_status_code, - std::string* response, - base::flat_map* headers) { - response_->Get( - url, - method, - response_status_code, - response); - } - - std::unique_ptr response_; - net::test_server::EmbeddedTestServer https_server_; - raw_ptr rewards_service_ = nullptr; -}; - -#if !BUILDFLAG(IS_MAC) -class GreaselionServiceLocaleTest : public GreaselionServiceTest { - public: - explicit GreaselionServiceLocaleTest(const std::string& locale) - : locale_(locale) {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitchASCII(switches::kLang, locale_); - } - - private: - std::string locale_; -}; - -class GreaselionServiceLocaleTestEnglish : public GreaselionServiceLocaleTest { - public: - GreaselionServiceLocaleTestEnglish() : GreaselionServiceLocaleTest("en") {} -}; - -class GreaselionServiceLocaleTestGerman : public GreaselionServiceLocaleTest { - public: - GreaselionServiceLocaleTestGerman() : GreaselionServiceLocaleTest("de") {} -}; - -class GreaselionServiceLocaleTestFrench : public GreaselionServiceLocaleTest { - public: - GreaselionServiceLocaleTestFrench() : GreaselionServiceLocaleTest("fr") {} -}; -#endif - -// Ensure the site specific script service properly clears its cache of -// precompiled URLPatterns if initialized twice. (This can happen if -// the parent component is updated while Brave is running.) -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ClearCache) { - ASSERT_TRUE(InstallMockExtension()); - int size = GetRulesSize(); - // clear the cache manually to make sure we're actually - // reinitializing it the second time - ClearRules(); - ASSERT_TRUE(InstallMockExtension()); - EXPECT_EQ(size, GetRulesSize()); - // now reinitialize without manually clearing (simulates an in-place - // component update) - ASSERT_TRUE(InstallMockExtension()); - EXPECT_EQ(size, GetRulesSize()); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ScriptInjection) { - ASSERT_TRUE(InstallMockExtension()); - GURL url = embedded_test_server()->GetURL("www.a.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ScriptInjectionDocumentStart) { - ASSERT_TRUE(InstallMockExtension()); - GURL url = embedded_test_server()->GetURL("runat1.b.com", "/intercept.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - EXPECT_EQ(content::EvalJs(contents, "document.title;"), "SCRIPT_FIRST"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ScriptInjectionDocumentEnd) { - ASSERT_TRUE(InstallMockExtension()); - GURL url = embedded_test_server()->GetURL("runat2.b.com", "/intercept.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - EXPECT_EQ(content::EvalJs(contents, "document.title;"), "PAGE_FIRST"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ScriptInjectionRunAtDefault) { - ASSERT_TRUE(InstallMockExtension()); - GURL url = embedded_test_server()->GetURL("runat3.b.com", "/intercept.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - EXPECT_EQ(content::EvalJs(contents, "document.title;"), "PAGE_FIRST"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - PRE_ScriptInjectionWithPrecondition) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL("pre1.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // should be unaltered because precondition did not match, so no Greaselion - // rules are active - EXPECT_EQ(content::EvalJs(contents, "document.title;"), "OK"); - - StartRewards(); - - auto* prefs = browser()->profile()->GetPrefs(); - EXPECT_FALSE(prefs->GetBoolean(brave_rewards::prefs::kAutoContributeEnabled)); - - // Enable auto-contribute and wait for it - rewards_service_->SetAutoContributeEnabled(true); - WaitForAutoContributeEnabled(); - - ASSERT_TRUE(prefs->GetBoolean(brave_rewards::prefs::kAutoContributeEnabled)); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, ScriptInjectionWithPrecondition) { - ASSERT_TRUE(InstallMockExtension()); - - StartRewards(); - - // Auto-contribute should still be enabled, due to PRE test - auto* prefs = browser()->profile()->GetPrefs(); - ASSERT_TRUE(prefs->GetBoolean(brave_rewards::prefs::kAutoContributeEnabled)); - - GURL url = embedded_test_server()->GetURL("pre1.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // should be altered because rewards precondition matched, so the relevant - // Greaselion rule is active - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, IsGreaselionExtension) { - ASSERT_TRUE(InstallMockExtension()); - - GreaselionService* greaselion_service = - GreaselionServiceFactory::GetForBrowserContext(profile()); - ASSERT_TRUE(greaselion_service); - - auto extension_ids = greaselion_service->GetExtensionIdsForTesting(); - ASSERT_GT(extension_ids.size(), 0UL); - - EXPECT_TRUE(greaselion_service->IsGreaselionExtension(extension_ids[0])); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, IsNotGreaselionExtension) { - ASSERT_TRUE(InstallMockExtension()); - - GreaselionService* greaselion_service = - GreaselionServiceFactory::GetForBrowserContext(profile()); - ASSERT_TRUE(greaselion_service); - - EXPECT_FALSE(greaselion_service->IsGreaselionExtension("INVALID")); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionLowWild) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-low-wild.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is lower than current. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionLowFormat) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-low-format.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is lower than current, even though it - // omits last component. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionMatchWild) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-match-wild.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is wild match. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionMatchExact) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-match-exact.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is exact match. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionHighWild) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-high-wild.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be unaltered because version is too high. - EXPECT_EQ(content::EvalJs(contents, "document.title"), "OK"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionHighExact) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-high-exact.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be unaltered because version is too high. - EXPECT_EQ(content::EvalJs(contents, "document.title"), "OK"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionEmpty) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-empty.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is not good format. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, - ScriptInjectionWithBrowserVersionConditionBadFormat) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL( - "version-bad-format.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - // Should be altered because version is not good format. - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, CleanShutdown) { - ASSERT_TRUE(InstallMockExtension()); - - GURL url = embedded_test_server()->GetURL("www.a.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(url, contents->GetURL()); - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), "Altered"); - - CloseAllBrowsers(); - ui_test_utils::WaitForBrowserToClose(browser()); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceTest, FoldersAreRemovedOnUpdate) { - ASSERT_TRUE(InstallMockExtension()); - - auto io_runner = base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); - - auto count_folders_on_io_runner = [&io_runner] { - base::RunLoop run_loop; - size_t folder_count; - - auto set_folder_count = [&folder_count, &run_loop](size_t count) { - folder_count = count; - run_loop.Quit(); - }; - - auto count_folders = []() { - base::FilePath install_dir = - GreaselionServiceFactory::GetInstallDirectory(); - - base::FilePath extensions_dir = - extensions::file_util::GetInstallTempDir(install_dir); - - base::FileEnumerator enumerator(extensions_dir, false, - base::FileEnumerator::DIRECTORIES); - size_t count = 0; - for (base::FilePath name = enumerator.Next(); !name.empty(); - name = enumerator.Next()) { - ++count; - } - return count; - }; - - io_runner->PostTaskAndReplyWithResult( - FROM_HERE, base::BindOnce(count_folders), - base::BindLambdaForTesting(set_folder_count)); - - run_loop.Run(); - return folder_count; - }; - - size_t start_count = count_folders_on_io_runner(); - EXPECT_GT(start_count, 0ul); - - // Trigger an update to reinstall extension folders and wait for all - // extensions to finish loading. - GreaselionService* greaselion_service = - GreaselionServiceFactory::GetForBrowserContext(profile()); - ASSERT_TRUE(greaselion_service); - greaselion_service->UpdateInstalledExtensions(); - GreaselionServiceWaiter(greaselion_service).Wait(); - - size_t after_update = count_folders_on_io_runner(); - EXPECT_EQ(after_update, start_count); -} - -#if !BUILDFLAG(IS_MAC) -IN_PROC_BROWSER_TEST_F(GreaselionServiceLocaleTestEnglish, - ScriptInjectionWithMessagesDefaultLocale) { - ASSERT_TRUE(InstallMockExtension()); - - const GURL url = - embedded_test_server()->GetURL("messages.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - EXPECT_EQ(url, contents->GetURL()); - - // Ensure that English localization is correct - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), - "Hello, world!"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceLocaleTestGerman, - ScriptInjectionWithMessagesNonDefaultLocale) { - ASSERT_TRUE(InstallMockExtension()); - - const GURL url = - embedded_test_server()->GetURL("messages.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - EXPECT_EQ(url, contents->GetURL()); - - // Ensure that German localization is correct - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), - "Hallo, Welt!"); -} - -IN_PROC_BROWSER_TEST_F(GreaselionServiceLocaleTestFrench, - ScriptInjectionWithMessagesUnsupportedLocale) { - ASSERT_TRUE(InstallMockExtension()); - - const GURL url = - embedded_test_server()->GetURL("messages.example.com", "/simple.html"); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - EXPECT_EQ(url, contents->GetURL()); - - // We don't have a French localization, so ensure that the default - // (English) localization is shown instead - EXPECT_EQ(content::EvalJs(contents, kWaitForTitleChangeScript), - "Hello, world!"); -} -#endif diff --git a/browser/greaselion/greaselion_service_factory.cc b/browser/greaselion/greaselion_service_factory.cc index 491634ebf4da..852a577e4f12 100644 --- a/browser/greaselion/greaselion_service_factory.cc +++ b/browser/greaselion/greaselion_service_factory.cc @@ -12,7 +12,6 @@ #include "base/no_destructor.h" #include "base/path_service.h" #include "brave/browser/brave_browser_process.h" -#include "brave/components/brave_rewards/common/pref_names.h" #include "brave/components/greaselion/browser/greaselion_service.h" #include "brave/components/greaselion/browser/greaselion_service_impl.h" #include "chrome/browser/extensions/extension_service.h" @@ -38,20 +37,9 @@ class GreaselionServiceDelegateImpl content::BrowserContext* browser_context) : browser_context_(browser_context) { DCHECK(browser_context_); - pref_change_registrar_.Init( - Profile::FromBrowserContext(browser_context)->GetPrefs()); - pref_change_registrar_.Add( - brave_rewards::prefs::kEnabled, - base::BindRepeating( - &GreaselionServiceDelegateImpl::UpdateGreaselionExtensions, - base::Unretained(this))); } - bool IsEnabled() const override { - return Profile::FromBrowserContext(browser_context_) - ->GetPrefs() - ->GetBoolean(brave_rewards::prefs::kEnabled); - } + bool IsEnabled() const override { return false; } void AddExtension(extensions::Extension* extension) override { if (auto* extension_service = @@ -80,7 +68,6 @@ class GreaselionServiceDelegateImpl } raw_ptr browser_context_; // Not owned - PrefChangeRegistrar pref_change_registrar_; }; } // namespace diff --git a/browser/notifications/ads_notification_handler.cc b/browser/notifications/ads_notification_handler.cc index 660a2fc5482c..edf57a24c79e 100644 --- a/browser/notifications/ads_notification_handler.cc +++ b/browser/notifications/ads_notification_handler.cc @@ -9,6 +9,7 @@ #include "brave/browser/brave_ads/ads_service_factory.h" #include "brave/components/brave_ads/browser/ads_service.h" +#include "build/build_config.h" #include "url/gurl.h" namespace brave_ads { @@ -28,19 +29,30 @@ void AdsNotificationHandler::OnShow(Profile* profile, const std::string& id) { return; } + did_click_notification_ad_ = false; + ads_service->OnNotificationAdShown(id); } void AdsNotificationHandler::OnClose(Profile* profile, const GURL& origin, const std::string& id, - bool by_user, + const bool by_user, base::OnceClosure completed_closure) { AdsService* ads_service = AdsServiceFactory::GetForProfile(profile); if (!ads_service) { return; } +#if BUILDFLAG(IS_LINUX) + if (did_click_notification_ad_) { + // On Linux, clicking the notification triggers both 'clicked' and 'closed' + // events. To avoid redundant event handling, we suppress the 'closed' event + // if the notification ad was clicked. + return; + } +#endif // BUILDFLAG(IS_LINUX) + ads_service->OnNotificationAdClosed(id, by_user); } @@ -55,6 +67,8 @@ void AdsNotificationHandler::OnClick(Profile* profile, return; } + did_click_notification_ad_ = true; + ads_service->OnNotificationAdClicked(id); } @@ -65,6 +79,8 @@ void AdsNotificationHandler::OpenSettings(Profile* profile, return; } + did_click_notification_ad_ = true; + CHECK(origin.has_query()); const std::string id = origin.query(); diff --git a/browser/notifications/ads_notification_handler.h b/browser/notifications/ads_notification_handler.h index 89408669267a..8559469f51c5 100644 --- a/browser/notifications/ads_notification_handler.h +++ b/browser/notifications/ads_notification_handler.h @@ -21,6 +21,12 @@ namespace brave_ads { class AdsNotificationHandler : public NotificationHandler { public: explicit AdsNotificationHandler(Profile& profile); + + AdsNotificationHandler(const AdsNotificationHandler&) = delete; + AdsNotificationHandler& operator=(const AdsNotificationHandler&) = delete; + AdsNotificationHandler(AdsNotificationHandler&&) = delete; + AdsNotificationHandler& operator=(AdsNotificationHandler&&) = delete; + ~AdsNotificationHandler() override; // NotificationHandler: @@ -41,8 +47,7 @@ class AdsNotificationHandler : public NotificationHandler { private: raw_ref profile_; - AdsNotificationHandler(const AdsNotificationHandler&) = delete; - AdsNotificationHandler& operator=(const AdsNotificationHandler&) = delete; + bool did_click_notification_ad_ = false; }; } // namespace brave_ads diff --git a/browser/resources/settings/brave_leo_assistant_page/model_config_ui.html b/browser/resources/settings/brave_leo_assistant_page/model_config_ui.html index 5d4ec96edfb9..c207c346137e 100644 --- a/browser/resources/settings/brave_leo_assistant_page/model_config_ui.html +++ b/browser/resources/settings/brave_leo_assistant_page/model_config_ui.html @@ -97,7 +97,7 @@ kind="plain-faint" fab > - + diff --git a/browser/tor/test/brave_tor_browsertest.cc b/browser/tor/test/brave_tor_browsertest.cc index 81d4cc67c44b..421d5d26867b 100644 --- a/browser/tor/test/brave_tor_browsertest.cc +++ b/browser/tor/test/brave_tor_browsertest.cc @@ -142,18 +142,18 @@ void NonBlockingDelay(base::TimeDelta delay) { } // namespace -class BraveTorTest : public InProcessBrowserTest { +class BraveTorBrowserTest : public InProcessBrowserTest { public: struct TorInfo { raw_ptr tor_profile = nullptr; int tor_pid = 0; }; - BraveTorTest() { + BraveTorBrowserTest() { BraveSettingsUI::ShouldExposeElementsForTesting() = true; } - ~BraveTorTest() override { + ~BraveTorBrowserTest() override { BraveSettingsUI::ShouldExposeElementsForTesting() = false; } @@ -222,7 +222,7 @@ class BraveTorTest : public InProcessBrowserTest { } }; -IN_PROC_BROWSER_TEST_F(BraveTorTest, OpenCloseDisableTorWindow) { +IN_PROC_BROWSER_TEST_F(BraveTorBrowserTest, OpenCloseDisableTorWindow) { EXPECT_FALSE(TorProfileServiceFactory::IsTorDisabled(browser()->profile())); DownloadTorClient(); @@ -254,7 +254,7 @@ IN_PROC_BROWSER_TEST_F(BraveTorTest, OpenCloseDisableTorWindow) { } } -class BraveTorTestWithCustomProfile : public BraveTorTest { +class BraveTorWithCustomProfileBrowserTest : public BraveTorBrowserTest { private: void SetUpCommandLine(base::CommandLine* command_line) override { InProcessBrowserTest::SetUpCommandLine(command_line); @@ -273,7 +273,7 @@ class BraveTorTestWithCustomProfile : public BraveTorTest { } }; -IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, PRE_SetupBridges) { +IN_PROC_BROWSER_TEST_F(BraveTorWithCustomProfileBrowserTest, PRE_SetupBridges) { EXPECT_FALSE(TorProfileServiceFactory::IsTorDisabled(browser()->profile())); DownloadTorClient(); @@ -331,7 +331,7 @@ IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, PRE_SetupBridges) { g_brave_browser_process->tor_pluggable_transport_updater()); } -IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, SetupBridges) { +IN_PROC_BROWSER_TEST_F(BraveTorWithCustomProfileBrowserTest, SetupBridges) { // Tor is disabled in PRE, check pluggable transports are removed. EXPECT_FALSE(CheckComponentExists(tor::kTorPluggableTransportComponentId)); @@ -345,7 +345,7 @@ IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, SetupBridges) { nullptr)); } -IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, Incognito) { +IN_PROC_BROWSER_TEST_F(BraveTorWithCustomProfileBrowserTest, Incognito) { EXPECT_FALSE(TorProfileServiceFactory::IsTorDisabled(browser()->profile())); EXPECT_FALSE(TorProfileServiceFactory::IsTorManaged(browser()->profile())); @@ -405,7 +405,7 @@ IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, Incognito) { EXPECT_TRUE(is_element_enabled("torSnowflake")); } -IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, Autofill) { +IN_PROC_BROWSER_TEST_F(BraveTorWithCustomProfileBrowserTest, Autofill) { GURL fake_url("http://brave.com/"); // Disable autofill in private windows. browser()->profile()->GetPrefs()->SetBoolean(kBraveAutofillPrivateWindows, @@ -426,7 +426,7 @@ IN_PROC_BROWSER_TEST_F(BraveTorTestWithCustomProfile, Autofill) { TestAutofillInWindow(web_contents, fake_url, true); } -IN_PROC_BROWSER_TEST_F(BraveTorTest, PRE_ResetBridges) { +IN_PROC_BROWSER_TEST_F(BraveTorBrowserTest, PRE_ResetBridges) { EXPECT_FALSE(TorProfileServiceFactory::IsTorDisabled(browser()->profile())); DownloadTorClient(); DownloadTorPluggableTransports(); @@ -451,14 +451,14 @@ IN_PROC_BROWSER_TEST_F(BraveTorTest, PRE_ResetBridges) { WaitProcessExit(tor::kSnowflakeExecutableName); } -IN_PROC_BROWSER_TEST_F(BraveTorTest, ResetBridges) { +IN_PROC_BROWSER_TEST_F(BraveTorBrowserTest, ResetBridges) { // Tor is enabled and bridges are disabled check pluggable transports are // removed. EXPECT_TRUE(CheckComponentExists(tor::kTorClientComponentId)); EXPECT_FALSE(CheckComponentExists(tor::kTorPluggableTransportComponentId)); } -IN_PROC_BROWSER_TEST_F(BraveTorTest, HttpAllowlistIsolation) { +IN_PROC_BROWSER_TEST_F(BraveTorBrowserTest, HttpAllowlistIsolation) { // Normal window Profile* main_profile = browser()->profile(); auto* main_storage_partition = main_profile->GetDefaultStoragePartition(); @@ -511,11 +511,11 @@ IN_PROC_BROWSER_TEST_F(BraveTorTest, HttpAllowlistIsolation) { EXPECT_TRUE(tor_state->IsHttpAllowedForHost(host3, tor_storage_partition)); } -class BraveTorTest_EnableTorHttpsOnlyFlag - : public BraveTorTest, +class BraveTorBrowserTest_EnableTorHttpsOnlyFlag + : public BraveTorBrowserTest, public ::testing::WithParamInterface { public: - BraveTorTest_EnableTorHttpsOnlyFlag() { + BraveTorBrowserTest_EnableTorHttpsOnlyFlag() { if (IsBraveHttpsByDefaultEnabled()) { std::vector enabled_features{ net::features::kBraveTorWindowsHttpsOnly}; @@ -530,7 +530,7 @@ class BraveTorTest_EnableTorHttpsOnlyFlag } } - ~BraveTorTest_EnableTorHttpsOnlyFlag() override = default; + ~BraveTorBrowserTest_EnableTorHttpsOnlyFlag() override = default; bool IsBraveHttpsByDefaultEnabled() { return GetParam(); } @@ -538,7 +538,7 @@ class BraveTorTest_EnableTorHttpsOnlyFlag base::test::ScopedFeatureList scoped_feature_list_; }; -IN_PROC_BROWSER_TEST_P(BraveTorTest_EnableTorHttpsOnlyFlag, +IN_PROC_BROWSER_TEST_P(BraveTorBrowserTest_EnableTorHttpsOnlyFlag, TorWindowHttpsOnly) { EXPECT_FALSE(TorProfileServiceFactory::IsTorDisabled(browser()->profile())); DownloadTorClient(); @@ -549,6 +549,6 @@ IN_PROC_BROWSER_TEST_P(BraveTorTest_EnableTorHttpsOnlyFlag, EXPECT_TRUE(prefs->GetBoolean(prefs::kHttpsOnlyModeEnabled)); } -INSTANTIATE_TEST_SUITE_P(BraveTorTest_EnableTorHttpsOnlyFlag, - BraveTorTest_EnableTorHttpsOnlyFlag, +INSTANTIATE_TEST_SUITE_P(BraveTorBrowserTest_EnableTorHttpsOnlyFlag, + BraveTorBrowserTest_EnableTorHttpsOnlyFlag, ::testing::Bool()); diff --git a/browser/ui/color/brave_color_mixer.cc b/browser/ui/color/brave_color_mixer.cc index 11c9880ff14f..c27d072c2982 100644 --- a/browser/ui/color/brave_color_mixer.cc +++ b/browser/ui/color/brave_color_mixer.cc @@ -208,7 +208,7 @@ void AddChromeLightThemeColorMixer(ui::ColorProvider* provider, mixer[kColorNewTabButtonBackgroundFrameActive] = {ui::kColorFrameActive}; mixer[kColorNewTabButtonBackgroundFrameInactive] = {ui::kColorFrameInactive}; mixer[kColorNewTabPageBackground] = {kBraveNewTabBackgroundLight}; - mixer[kColorTabStrokeFrameActive] = {SkColorSetA(SK_ColorBLACK, 0.07 * 255)}; + mixer[kColorTabStrokeFrameActive] = {ui::kColorRefNeutral80}; mixer[kColorTabStrokeFrameInactive] = {kColorTabStrokeFrameActive}; mixer[kColorToolbarButtonIconInactive] = { ui::SetAlpha(kColorToolbarButtonIcon, kBraveDisabledControlAlpha)}; @@ -248,7 +248,7 @@ void AddChromeDarkThemeColorMixer(ui::ColorProvider* provider, mixer[kColorNewTabButtonBackgroundFrameActive] = {ui::kColorFrameActive}; mixer[kColorNewTabButtonBackgroundFrameInactive] = {ui::kColorFrameInactive}; mixer[kColorNewTabPageBackground] = {kBraveNewTabBackgroundDark}; - mixer[kColorTabStrokeFrameActive] = {kColorToolbar}; + mixer[kColorTabStrokeFrameActive] = {ui::kColorRefNeutral25}; mixer[kColorTabStrokeFrameInactive] = {kColorToolbar}; mixer[kColorToolbarButtonIconInactive] = { ui::SetAlpha(kColorToolbarButtonIcon, kBraveDisabledControlAlpha)}; diff --git a/browser/ui/sidebar/sidebar_browsertest.cc b/browser/ui/sidebar/sidebar_browsertest.cc index 57642f8a456d..598f4f7939ca 100644 --- a/browser/ui/sidebar/sidebar_browsertest.cc +++ b/browser/ui/sidebar/sidebar_browsertest.cc @@ -286,6 +286,18 @@ class SidebarBrowserTest : public InProcessBrowserTest { return std::distance(items.cbegin(), iter); } + bool SidebarContainerObserving(SidePanelEntryId id) { + auto* sidebar_container_view = + static_cast(controller()->sidebar()); + for (const auto& entry : + sidebar_container_view->panel_entry_observations_.sources()) { + if (entry->key().id() == id) { + return true; + } + } + return false; + } + raw_ptr item_added_bubble_anchor_ = nullptr; std::unique_ptr run_loop_; base::WeakPtrFactory weak_factory_{this}; @@ -919,6 +931,10 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, TabSpecificAndGlobalPanelsTest) { WaitUntil(base::BindLambdaForTesting([&]() { return panel_ui->GetCurrentEntryId() == SidePanelEntryId::kBookmarks; })); + // As previous customize panel per-url panel, it's closed by deregistering + // after loading another url. Then, sidebar container should stop observing + // its entry. + EXPECT_FALSE(SidebarContainerObserving(SidePanelEntryId::kCustomizeChrome)); } IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, DisabledItemsTest) { diff --git a/browser/ui/views/frame/brave_browser_view.cc b/browser/ui/views/frame/brave_browser_view.cc index 967be2c34919..90bfd2d96b2d 100644 --- a/browser/ui/views/frame/brave_browser_view.cc +++ b/browser/ui/views/frame/brave_browser_view.cc @@ -778,8 +778,8 @@ WalletButton* BraveBrowserView::GetWalletButton() { return static_cast(toolbar())->wallet_button(); } -void BraveBrowserView::WillShowSidePanel() { - sidebar_container_view_->WillShowSidePanel(); +void BraveBrowserView::WillShowSidePanel(bool show_on_deregistered) { + sidebar_container_view_->WillShowSidePanel(show_on_deregistered); } void BraveBrowserView::NotifyDialogPositionRequiresUpdate() { diff --git a/browser/ui/views/frame/brave_browser_view.h b/browser/ui/views/frame/brave_browser_view.h index 58503984df49..4a72c7105a8f 100644 --- a/browser/ui/views/frame/brave_browser_view.h +++ b/browser/ui/views/frame/brave_browser_view.h @@ -81,7 +81,7 @@ class BraveBrowserView : public BrowserView, void CloseWalletBubble(); WalletButton* GetWalletButton(); views::View* GetWalletButtonAnchorView(); - void WillShowSidePanel(); + void WillShowSidePanel(bool show_on_deregistered); // Triggers layout of web modal dialogs void NotifyDialogPositionRequiresUpdate(); diff --git a/browser/ui/views/side_panel/brave_side_panel_coordinator.cc b/browser/ui/views/side_panel/brave_side_panel_coordinator.cc index a4fc9cade194..4750019371db 100644 --- a/browser/ui/views/side_panel/brave_side_panel_coordinator.cc +++ b/browser/ui/views/side_panel/brave_side_panel_coordinator.cc @@ -151,8 +151,23 @@ void BraveSidePanelCoordinator::PopulateSidePanel( // Notify to give opportunity to observe another panel entries from // global or active tab's contextual registry. auto* brave_browser_view = static_cast(browser_view_); - brave_browser_view->WillShowSidePanel(); - + CHECK(browser_view_->unified_side_panel()->children().size() == 1); + const auto content_wrapper = + browser_view_->unified_side_panel()->children()[0]; + bool show_on_deregistered = false; + // If current entry is not null and its content is already removed from + // wrapper when new panel is about to be shown, new panel is shown by + // deregistering current panel. See the comment of + // SidebarContainerView::WillShowSidePanel() about why |show_on_deregistered| + // is needed. + // Instead, we can override base class' Show(const UniqueKey& entry, ...) + // method as we can know whether it's shown by deregistering with + // |open_trigger| arg. However, need patching to make it virtual as base class + // already have overridden same name methods. + if (current_entry_.get() && content_wrapper->children().empty()) { + show_on_deregistered = true; + } + brave_browser_view->WillShowSidePanel(show_on_deregistered); SidePanelCoordinator::PopulateSidePanel(supress_animations, unique_key, entry, std::move(content_view)); } diff --git a/browser/ui/views/sidebar/sidebar_container_view.cc b/browser/ui/views/sidebar/sidebar_container_view.cc index 686a1c5141a9..78445c941098 100644 --- a/browser/ui/views/sidebar/sidebar_container_view.cc +++ b/browser/ui/views/sidebar/sidebar_container_view.cc @@ -175,7 +175,9 @@ bool SidebarContainerView::IsSidebarVisible() const { return sidebar_control_view_ && sidebar_control_view_->GetVisible(); } -void SidebarContainerView::WillShowSidePanel() { +void SidebarContainerView::WillShowSidePanel(bool show_on_deregistered) { + deregister_when_hidden_ = show_on_deregistered; + // It's good timing to start observing any panel entries // from global and contextual if not yet observed. auto* tab_model = browser_->tab_strip_model(); @@ -769,8 +771,13 @@ void SidebarContainerView::OnEntryShown(SidePanelEntry* entry) { } void SidebarContainerView::OnEntryHidden(SidePanelEntry* entry) { - // Make sure item is deselected DVLOG(1) << "Panel hidden: " << SidePanelEntryIdToString(entry->key().id()); + + if (deregister_when_hidden_) { + StopObservingForEntry(entry); + deregister_when_hidden_ = false; + } + auto* controller = GetBraveBrowser()->sidebar_controller(); // Handling if |entry| is managed one. @@ -811,10 +818,10 @@ void SidebarContainerView::OnEntryWillHide(SidePanelEntry* entry, // re-registered when panel is shown if that entry is still live in tab's // registry. // We only stop observing when |entry|'s panel is hidden by closing. - // If it's hidden by replacing with other panel, we shoudl not stop + // If it's hidden by replacing with other panel, we should not stop // to know the timing that it's shown again. if (reason == SidePanelEntryHideReason::kSidePanelClosed) { - StopObservingForEntry(entry); + deregister_when_hidden_ = true; } } diff --git a/browser/ui/views/sidebar/sidebar_container_view.h b/browser/ui/views/sidebar/sidebar_container_view.h index c14b95343a34..6cd395c95bee 100644 --- a/browser/ui/views/sidebar/sidebar_container_view.h +++ b/browser/ui/views/sidebar/sidebar_container_view.h @@ -78,7 +78,16 @@ class SidebarContainerView BraveSidePanel* side_panel() { return side_panel_; } - void WillShowSidePanel(); + // Need to know this showing comes from deregistering current entry + // or not. We're observing contextual/global panel entries when panel is + // shown. And stop observing when it's hidden by closing. Unfortunately, + // OnEntryWillHide() is not called when current entry is closed by + // deregistering. Only OnEntryHidden() is called. + // By using OnEntryWillHide()'s arg, we can know this hidden is from + // closing or not. Fortunately, we can know when WillShowSidePanel() + // is called whether it's closing from deregistration. + // With |show_on_deregistered|, we can stop observing OnEntryHidden(). + void WillShowSidePanel(bool show_on_deregistered); bool IsFullscreenForCurrentEntry() const; void set_operation_from_active_tab_change(bool tab_change) { @@ -200,6 +209,7 @@ class SidebarContainerView bool initialized_ = false; bool sidebar_on_left_ = true; bool operation_from_active_tab_change_ = false; + bool deregister_when_hidden_ = false; base::OneShotTimer sidebar_hide_timer_; sidebar::SidebarService::ShowSidebarOption show_sidebar_option_ = sidebar::SidebarService::ShowSidebarOption::kShowAlways; diff --git a/browser/ui/webui/new_tab_page/brave_new_tab_message_handler.cc b/browser/ui/webui/new_tab_page/brave_new_tab_message_handler.cc index f44497dd4b20..1e9233eab60f 100644 --- a/browser/ui/webui/new_tab_page/brave_new_tab_message_handler.cc +++ b/browser/ui/webui/new_tab_page/brave_new_tab_message_handler.cc @@ -11,18 +11,14 @@ #include #include "base/functional/bind.h" -#include "base/json/json_writer.h" #include "base/json/values_util.h" #include "base/memory/weak_ptr.h" -#include "base/metrics/histogram_macros.h" #include "base/threading/thread_restrictions.h" -#include "base/time/time.h" #include "base/values.h" #include "brave/browser/brave_ads/ads_service_factory.h" #include "brave/browser/ntp_background/view_counter_service_factory.h" #include "brave/browser/profiles/profile_util.h" #include "brave/browser/search_engines/pref_names.h" -#include "brave/browser/ui/webui/new_tab_page/brave_new_tab_ui.h" #include "brave/components/brave_ads/core/public/ads_util.h" #include "brave/components/brave_news/common/pref_names.h" #include "brave/components/brave_perf_predictor/common/pref_names.h" @@ -32,13 +28,11 @@ #include "brave/components/ntp_background_images/browser/view_counter_service.h" #include "brave/components/ntp_background_images/common/pref_names.h" #include "brave/components/p3a/utils.h" -#include "brave/components/services/bat_ads/public/interfaces/bat_ads.mojom.h" #include "brave/components/time_period_storage/weekly_storage.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/plural_string_handler.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "components/grit/brave_components_strings.h" #include "components/prefs/pref_change_registrar.h" @@ -95,6 +89,9 @@ base::Value::Dict GetPreferencesDictionary(PrefService* prefs) { pref_data.Set( "showSearchBox", prefs->GetBoolean(brave_search_conversion::prefs::kShowNTPSearchBox)); + pref_data.Set("lastUsedNtpSearchEngine", + prefs->GetString( + brave_search_conversion::prefs::kLastUsedNTPSearchEngine)); pref_data.Set("promptEnableSearchSuggestions", prefs->GetBoolean( brave_search_conversion::prefs::kPromptEnableSuggestions)); @@ -292,6 +289,10 @@ void BraveNewTabMessageHandler::OnJavascriptAllowed() { brave_search_conversion::prefs::kShowNTPSearchBox, base::BindRepeating(&BraveNewTabMessageHandler::OnPreferencesChanged, base::Unretained(this))); + pref_change_registrar_.Add( + brave_search_conversion::prefs::kLastUsedNTPSearchEngine, + base::BindRepeating(&BraveNewTabMessageHandler::OnPreferencesChanged, + base::Unretained(this))); pref_change_registrar_.Add( brave_search_conversion::prefs::kPromptEnableSuggestions, base::BindRepeating(&BraveNewTabMessageHandler::OnPreferencesChanged, @@ -393,73 +394,75 @@ void BraveNewTabMessageHandler::HandleSaveNewTabPagePref( } PrefService* prefs = profile_->GetPrefs(); // Collect args - std::string settingsKeyInput = args[0].GetString(); - auto settingsValue = args[1].Clone(); - std::string settingsKey; + std::string settings_key_input = args[0].GetString(); + auto settings_value = args[1].Clone(); + std::string settings_key; // Prevent News onboarding below NTP and sponsored NTP notification // state from triggering the "shown & changed" answer for the // customize dialog metric. - if (settingsKeyInput != "showToday" && - settingsKeyInput != "isBraveNewsOptedIn" && - settingsKeyInput != "isBrandedWallpaperNotificationDismissed") { + if (settings_key_input != "showToday" && + settings_key_input != "isBraveNewsOptedIn" && + settings_key_input != "isBrandedWallpaperNotificationDismissed") { p3a::RecordValueIfGreater( NTPCustomizeUsage::kOpenedAndEdited, kCustomizeUsageHistogramName, kNTPCustomizeUsageStatus, g_browser_process->local_state()); } // Handle string settings - if (settingsValue.is_string()) { - const auto settingsValueString = settingsValue.GetString(); - if (settingsKeyInput == "clockFormat") { - settingsKey = kNewTabPageClockFormat; + if (settings_value.is_string()) { + const auto settings_value_string = settings_value.GetString(); + if (settings_key_input == "clockFormat") { + settings_key = kNewTabPageClockFormat; + } else if (settings_key_input == "lastUsedNtpSearchEngine") { + settings_key = brave_search_conversion::prefs::kLastUsedNTPSearchEngine; } else { LOG(ERROR) << "Invalid setting key"; return; } - prefs->SetString(settingsKey, settingsValueString); + prefs->SetString(settings_key, settings_value_string); return; } // Handle bool settings - if (!settingsValue.is_bool()) { + if (!settings_value.is_bool()) { LOG(ERROR) << "Invalid value type"; return; } - const auto settingsValueBool = settingsValue.GetBool(); - if (settingsKeyInput == "showBackgroundImage") { - settingsKey = kNewTabPageShowBackgroundImage; - } else if (settingsKeyInput == "brandedWallpaperOptIn") { + const auto settings_value_bool = settings_value.GetBool(); + if (settings_key_input == "showBackgroundImage") { + settings_key = kNewTabPageShowBackgroundImage; + } else if (settings_key_input == "brandedWallpaperOptIn") { // TODO(simonhong): I think above |brandedWallpaperOptIn| should be changed // to |sponsoredImagesWallpaperOptIn|. - settingsKey = kNewTabPageShowSponsoredImagesBackgroundImage; - } else if (settingsKeyInput == "showClock") { - settingsKey = kNewTabPageShowClock; - } else if (settingsKeyInput == "showStats") { - settingsKey = kNewTabPageShowStats; - } else if (settingsKeyInput == "showToday") { - settingsKey = brave_news::prefs::kNewTabPageShowToday; - } else if (settingsKeyInput == "isBraveNewsOptedIn") { - settingsKey = brave_news::prefs::kBraveNewsOptedIn; - } else if (settingsKeyInput == "showRewards") { - settingsKey = kNewTabPageShowRewards; - } else if (settingsKeyInput == "isBrandedWallpaperNotificationDismissed") { - settingsKey = kBrandedWallpaperNotificationDismissed; - } else if (settingsKeyInput == "hideAllWidgets") { - settingsKey = kNewTabPageHideAllWidgets; - } else if (settingsKeyInput == "showBraveTalk") { - settingsKey = kNewTabPageShowBraveTalk; - } else if (settingsKeyInput == "showSearchBox") { - settingsKey = brave_search_conversion::prefs::kShowNTPSearchBox; - } else if (settingsKeyInput == "promptEnableSearchSuggestions") { - settingsKey = brave_search_conversion::prefs::kPromptEnableSuggestions; - } else if (settingsKeyInput == "searchSuggestionsEnabled") { - settingsKey = prefs::kSearchSuggestEnabled; + settings_key = kNewTabPageShowSponsoredImagesBackgroundImage; + } else if (settings_key_input == "showClock") { + settings_key = kNewTabPageShowClock; + } else if (settings_key_input == "showStats") { + settings_key = kNewTabPageShowStats; + } else if (settings_key_input == "showToday") { + settings_key = brave_news::prefs::kNewTabPageShowToday; + } else if (settings_key_input == "isBraveNewsOptedIn") { + settings_key = brave_news::prefs::kBraveNewsOptedIn; + } else if (settings_key_input == "showRewards") { + settings_key = kNewTabPageShowRewards; + } else if (settings_key_input == "isBrandedWallpaperNotificationDismissed") { + settings_key = kBrandedWallpaperNotificationDismissed; + } else if (settings_key_input == "hideAllWidgets") { + settings_key = kNewTabPageHideAllWidgets; + } else if (settings_key_input == "showBraveTalk") { + settings_key = kNewTabPageShowBraveTalk; + } else if (settings_key_input == "showSearchBox") { + settings_key = brave_search_conversion::prefs::kShowNTPSearchBox; + } else if (settings_key_input == "promptEnableSearchSuggestions") { + settings_key = brave_search_conversion::prefs::kPromptEnableSuggestions; + } else if (settings_key_input == "searchSuggestionsEnabled") { + settings_key = prefs::kSearchSuggestEnabled; } else { LOG(ERROR) << "Invalid setting key"; return; } - prefs->SetBoolean(settingsKey, settingsValueBool); + prefs->SetBoolean(settings_key, settings_value_bool); } void BraveNewTabMessageHandler::HandleRegisterNewTabPageView( @@ -541,10 +544,10 @@ void BraveNewTabMessageHandler::HandleGetWallpaperData( // Even though we show sponsored image, we should pass "Background wallpaper" // data so that NTP customization menu can know which wallpaper is selected by // users. - auto backgroundWallpaper = service->GetCurrentWallpaper(); + auto background_wallpaper = service->GetCurrentWallpaper(); wallpaper.Set(kBackgroundWallpaperKey, - backgroundWallpaper - ? base::Value(std::move(*backgroundWallpaper)) + background_wallpaper + ? base::Value(std::move(*background_wallpaper)) : base::Value()); const std::string* creative_instance_id = diff --git a/common/extensions/api/brave_rewards.json b/common/extensions/api/brave_rewards.json index 3836f069fa46..37fb9255f0f0 100644 --- a/common/extensions/api/brave_rewards.json +++ b/common/extensions/api/brave_rewards.json @@ -244,29 +244,6 @@ "description": "Opens the Rewards panel in the active window.", "parameters": [] }, - { - "name": "updateMediaDuration", - "type": "function", - "description": "Update the media duration for a given resource", - "parameters": [ - { - "name": "windowId", - "type": "number" - }, - { - "name": "publisherKey", - "type": "string" - }, - { - "name": "duration", - "type": "integer" - }, - { - "name": "firstVisit", - "type": "boolean" - } - ] - }, { "name": "getPublisherInfo", "type": "function", @@ -319,21 +296,6 @@ "does_not_support_promises": "Multi-parameter callback" } }, - { - "name": "setPublisherIdForTab", - "type": "function", - "description": "Sets the current publisher ID for the specified tab", - "parameters": [ - { - "name": "tabId", - "type": "integer" - }, - { - "name": "publisherId", - "type": "string" - } - ] - }, { "name": "getPublisherInfoForTab", "type": "function", @@ -390,107 +352,6 @@ }, "does_not_support_promises": "Requires refactoring" }, - { - "name": "getPublisherPanelInfo", - "type": "function", - "description": "Get the panel info for a particular publisher", - "parameters": [ - { - "name": "publisherKey", - "type": "string" - } - ], - "returns_async": { - "name": "callback", - "parameters": [ - { - "name": "result", - "type": "integer" - }, - { - "name": "publisher", - "type": "object", - "optional": true, - "properties": { - "percentage": { - "type": "integer", - "description": "publisher attention score" - }, - "excluded": { - "type": "boolean", - "description": "is site excluded from auto contribute" - }, - "provider": { - "type": "string", - "description": "provider (if media publisher) for this publisher" - }, - "favIconUrl": { - "type": "string", - "description": "publisher image url" - }, - "publisherKey": { - "type": "string", - "description": "publisher key, unique identifier" - }, - "name": { - "type": "string", - "description": "publisher name" - }, - "url": { - "type": "string", - "description": "url of the current tab" - }, - "status": { - "type": "integer", - "description": "publisher status" - } - } - } - ], - "does_not_support_promises": "Multi-parameter callback" - } - }, - { - "name": "savePublisherInfo", - "type": "function", - "description": "Save the publisher info when visiting a site", - "parameters": [ - { - "name": "windowId", - "type": "number" - }, - { - "name": "mediaType", - "type": "string" - }, - { - "name": "url", - "type": "string" - }, - { - "name": "publisherKey", - "type": "string" - }, - { - "name": "publisherName", - "type": "string" - }, - { - "name": "favIconUrl", - "type": "string" - } - ], - "returns_async": { - "name": "callback", - "parameters": [ - { - "name": "result", - "type": "integer" - } - ] - }, - "does_not_support_promises": "Requires refactoring" - }, { "name": "tipSite", "type": "function", @@ -510,29 +371,6 @@ } ] }, - { - "name": "getPublisherData", - "type": "function", - "description": "Get publisher data", - "parameters": [ - { - "name": "windowId", - "type": "integer" - }, - { - "name": "url", - "type": "string" - }, - { - "name": "faviconUrl", - "type": "string" - }, - { - "name": "publisherBlob", - "type": "string" - } - ] - }, { "name": "getRewardsParameters", "type": "function", diff --git a/components/ai_chat/core/browser/conversation_handler.cc b/components/ai_chat/core/browser/conversation_handler.cc index d2b7b5733d4c..ddc06226fc10 100644 --- a/components/ai_chat/core/browser/conversation_handler.cc +++ b/components/ai_chat/core/browser/conversation_handler.cc @@ -777,8 +777,8 @@ void ConversationHandler::ClearErrorAndGetFailedMessage( DCHECK(!chat_history_.empty()); SetAPIError(mojom::APIError::None); - mojom::ConversationTurnPtr turn = std::move(*chat_history_.end()); - chat_history_.erase(chat_history_.end()); + mojom::ConversationTurnPtr turn = std::move(chat_history_.back()); + chat_history_.pop_back(); OnHistoryUpdate(); diff --git a/components/ai_chat/renderer/ai_chat_resource_sniffer.cc b/components/ai_chat/renderer/ai_chat_resource_sniffer.cc index 191364eca9ab..829c967ea9ad 100644 --- a/components/ai_chat/renderer/ai_chat_resource_sniffer.cc +++ b/components/ai_chat/renderer/ai_chat_resource_sniffer.cc @@ -82,7 +82,7 @@ bool AIChatResourceSniffer::IsTransformer() const { void AIChatResourceSniffer::Transform( std::string body, base::OnceCallback on_complete) { - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void AIChatResourceSniffer::UpdateResponseHead( diff --git a/components/body_sniffer/body_sniffer_url_loader.cc b/components/body_sniffer/body_sniffer_url_loader.cc index 2f0edd4d8fe3..b34e4647c2cc 100644 --- a/components/body_sniffer/body_sniffer_url_loader.cc +++ b/components/body_sniffer/body_sniffer_url_loader.cc @@ -113,7 +113,7 @@ void BodySnifferURLLoader::OnReceiveEarlyHints( network::mojom::EarlyHintsPtr early_hints) { // OnReceiveEarlyHints() shouldn't be called. See the comment in // OnReceiveResponse(). - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void BodySnifferURLLoader::OnReceiveResponse( @@ -123,7 +123,7 @@ void BodySnifferURLLoader::OnReceiveResponse( // OnReceiveResponse() shouldn't be called because BodySnifferURLLoader is // created by WillProcessResponse(), which is equivalent // to OnReceiveResponse(). - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void BodySnifferURLLoader::OnReceiveRedirect( @@ -132,7 +132,7 @@ void BodySnifferURLLoader::OnReceiveRedirect( // OnReceiveRedirect() shouldn't be called because BodySnifferURLLoader is // created by WillProcessResponse(), which is equivalent // to OnReceiveResponse(). - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void BodySnifferURLLoader::OnUploadProgress( @@ -171,10 +171,8 @@ void BodySnifferURLLoader::OnComplete( destination_url_loader_client_->OnComplete(status); return; case State::kAborted: - NOTREACHED_IN_MIGRATION(); - return; + NOTREACHED(); } - NOTREACHED_IN_MIGRATION(); } void BodySnifferURLLoader::FollowRedirect( @@ -184,7 +182,7 @@ void BodySnifferURLLoader::FollowRedirect( const std::optional& new_url) { // BodySnifferURLLoader starts handling the request after // OnReceivedResponse(). A redirect response is not expected. - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void BodySnifferURLLoader::SetPriority(net::RequestPriority priority, @@ -238,8 +236,7 @@ void BodySnifferURLLoader::OnBodyReadable(MojoResult) { body_consumer_watcher_.ArmOrNotify(); return; default: - NOTREACHED_IN_MIGRATION(); - return; + NOTREACHED(); } const bool is_body_complete = result == MOJO_RESULT_FAILED_PRECONDITION; @@ -254,8 +251,7 @@ void BodySnifferURLLoader::OnBodyReadable(MojoResult) { handler->OnBodyUpdated(buffered_body_, is_body_complete); switch (action) { case BodyHandler::Action::kNone: - NOTREACHED_IN_MIGRATION() << "Action shouldn't return kNone"; - break; + NOTREACHED() << "Action shouldn't return kNone"; case BodyHandler::Action::kContinue: if (is_body_complete) { overall_action = BodyHandler::Action::kComplete; @@ -404,8 +400,7 @@ void BodySnifferURLLoader::SendReceivedBodyToClient() { body_producer_watcher_.ArmOrNotify(); return; default: - NOTREACHED_IN_MIGRATION(); - return; + NOTREACHED(); } bytes_remaining_in_buffer_ -= actually_sent_bytes; body_producer_watcher_.ArmOrNotify(); @@ -431,8 +426,7 @@ void BodySnifferURLLoader::ForwardBodyToClient() { CompleteSending(); return; default: - NOTREACHED_IN_MIGRATION(); - return; + NOTREACHED(); } size_t actually_written_bytes = 0; @@ -451,8 +445,7 @@ void BodySnifferURLLoader::ForwardBodyToClient() { body_producer_watcher_.ArmOrNotify(); return; default: - NOTREACHED_IN_MIGRATION(); - return; + NOTREACHED(); } body_consumer_handle_->EndReadData(actually_written_bytes); diff --git a/components/brave_ads/browser/ads_service_impl.cc b/components/brave_ads/browser/ads_service_impl.cc index 22dc0ad93761..6eec71223176 100644 --- a/components/brave_ads/browser/ads_service_impl.cc +++ b/components/brave_ads/browser/ads_service_impl.cc @@ -515,7 +515,7 @@ void AdsServiceImpl::NotifyAdsServiceInitialized() const { } } -void AdsServiceImpl::ShutdownAndClearData() { +void AdsServiceImpl::ShutdownClearDataAndMaybeRestart() { ShutdownAdsService(); VLOG(6) << "Clearing ads data"; @@ -525,11 +525,12 @@ void AdsServiceImpl::ShutdownAndClearData() { file_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&DeletePathOnFileTaskRunner, ads_service_path_), - base::BindOnce(&AdsServiceImpl::ShutdownAndClearDataCallback, + base::BindOnce(&AdsServiceImpl::ShutdownClearDataAndMaybeRestartCallback, weak_ptr_factory_.GetWeakPtr())); } -void AdsServiceImpl::ShutdownAndClearDataCallback(const bool success) { +void AdsServiceImpl::ShutdownClearDataAndMaybeRestartCallback( + const bool success) { if (!success) { VLOG(0) << "Failed to clear ads data"; } else { @@ -1157,7 +1158,7 @@ void AdsServiceImpl::OnNotificationAdClicked(const std::string& placement_id) { void AdsServiceImpl::ClearData() { UMA_HISTOGRAM_BOOLEAN(kClearDataHistogramName, true); - ShutdownAndClearData(); + ShutdownClearDataAndMaybeRestart(); } void AdsServiceImpl::GetDiagnostics(GetDiagnosticsCallback callback) { @@ -1903,14 +1904,14 @@ void AdsServiceImpl::OnRewardsWalletCreated() { } void AdsServiceImpl::OnExternalWalletConnected() { - SetProfilePref(prefs::kShouldMigrateVerifiedRewardsUser, base::Value(true)); - ShowReminder(mojom::ReminderType::kExternalWalletConnected); + + ShutdownClearDataAndMaybeRestart(); } void AdsServiceImpl::OnCompleteReset(const bool success) { if (success) { - ShutdownAndClearData(); + ShutdownClearDataAndMaybeRestart(); } } diff --git a/components/brave_ads/browser/ads_service_impl.h b/components/brave_ads/browser/ads_service_impl.h index e7861cc1ecbb..c98ea93e41e7 100644 --- a/components/brave_ads/browser/ads_service_impl.h +++ b/components/brave_ads/browser/ads_service_impl.h @@ -140,8 +140,10 @@ class AdsServiceImpl final : public AdsService, void NotifyAdsServiceInitialized() const; - void ShutdownAndClearData(); - void ShutdownAndClearDataCallback(bool success); + void ShutdownClearDataAndMaybeRestart(); + void ShutdownClearDataAndMaybeRestartCallback(bool success); + + void OnExternalWalletConnectedCallback(bool success); void SetSysInfo(); void SetBuildChannel(); diff --git a/components/brave_ads/core/internal/BUILD.gn b/components/brave_ads/core/internal/BUILD.gn index 32a962023cc0..29fd853de9a4 100644 --- a/components/brave_ads/core/internal/BUILD.gn +++ b/components/brave_ads/core/internal/BUILD.gn @@ -189,7 +189,6 @@ static_library("internal") { "account/user_data/user_data_info.h", "account/user_rewards/user_rewards.cc", "account/user_rewards/user_rewards.h", - "account/user_rewards/user_rewards_delegate.h", "account/user_rewards/user_rewards_util.cc", "account/user_rewards/user_rewards_util.h", "account/utility/redeem_confirmation/non_reward/redeem_non_reward_confirmation.cc", diff --git a/components/brave_ads/core/internal/account/account.cc b/components/brave_ads/core/internal/account/account.cc index a5c94a6b8d96..0ef457cc5d26 100644 --- a/components/brave_ads/core/internal/account/account.cc +++ b/components/brave_ads/core/internal/account/account.cc @@ -227,7 +227,6 @@ void Account::MaybeInitializeUserRewards() { // destroyed. user_rewards_ = std::make_unique(*wallet_); - user_rewards_->SetDelegate(this); user_rewards_->FetchIssuers(); @@ -295,8 +294,4 @@ void Account::OnFailedToConfirm(const ConfirmationInfo& /*confirmation*/) { MaybeRefillConfirmationTokens(); } -void Account::OnDidMigrateVerifiedRewardsUser() { - InitializeConfirmations(); -} - } // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/account.h b/components/brave_ads/core/internal/account/account.h index 7a1c32ee5b3b..5525d29ebbfa 100644 --- a/components/brave_ads/core/internal/account/account.h +++ b/components/brave_ads/core/internal/account/account.h @@ -16,7 +16,6 @@ #include "brave/components/brave_ads/core/internal/account/account_observer.h" #include "brave/components/brave_ads/core/internal/account/confirmations/confirmations_delegate.h" #include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards.h" -#include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h" #include "brave/components/brave_ads/core/internal/account/wallet/wallet_info.h" #include "brave/components/brave_ads/core/mojom/brave_ads.mojom-forward.h" #include "brave/components/brave_ads/core/public/ads_callback.h" @@ -28,8 +27,7 @@ class Confirmations; struct TransactionInfo; class Account final : public AdsClientNotifierObserver, - public ConfirmationDelegate, - public UserRewardsDelegate { + public ConfirmationDelegate { public: Account(); @@ -118,9 +116,6 @@ class Account final : public AdsClientNotifierObserver, void OnDidConfirm(const ConfirmationInfo& confirmation) override; void OnFailedToConfirm(const ConfirmationInfo& confirmation) override; - // UserRewardsDelegate: - void OnDidMigrateVerifiedRewardsUser() override; - base::ObserverList observers_; std::unique_ptr confirmations_; diff --git a/components/brave_ads/core/internal/account/confirmations/confirmations_util.cc b/components/brave_ads/core/internal/account/confirmations/confirmations_util.cc index 89dae3f3aca8..47e471b00ce1 100644 --- a/components/brave_ads/core/internal/account/confirmations/confirmations_util.cc +++ b/components/brave_ads/core/internal/account/confirmations/confirmations_util.cc @@ -9,14 +9,10 @@ #include #include "base/base64url.h" -#include "base/functional/callback_helpers.h" #include "base/json/json_reader.h" #include "brave/components/brave_ads/core/internal/account/confirmations/confirmation_info.h" #include "brave/components/brave_ads/core/internal/account/confirmations/payload/confirmation_payload_json_writer.h" -#include "brave/components/brave_ads/core/internal/account/confirmations/queue/confirmation_queue_database_table.h" #include "brave/components/brave_ads/core/internal/account/confirmations/reward/reward_info.h" -#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_util.h" -#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_util.h" #include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/unblinded_token.h" #include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/verification_key.h" #include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/verification_signature.h" @@ -87,13 +83,4 @@ bool IsValid(const ConfirmationInfo& confirmation) { return Verify(confirmation); } -void ResetTokens() { - database::table::ConfirmationQueue database_table; - database_table.DeleteAll(/*intentional*/ base::DoNothing()); - - RemoveAllConfirmationTokens(); - - RemoveAllPaymentTokens(); -} - } // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/confirmations/confirmations_util.h b/components/brave_ads/core/internal/account/confirmations/confirmations_util.h index 1a9d84a1cb3b..d8e77c829574 100644 --- a/components/brave_ads/core/internal/account/confirmations/confirmations_util.h +++ b/components/brave_ads/core/internal/account/confirmations/confirmations_util.h @@ -12,8 +12,6 @@ struct ConfirmationInfo; [[nodiscard]] bool IsValid(const ConfirmationInfo& confirmation); -void ResetTokens(); - } // namespace brave_ads #endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_CONFIRMATIONS_CONFIRMATIONS_UTIL_H_ diff --git a/components/brave_ads/core/internal/account/confirmations/confirmations_util_unittest.cc b/components/brave_ads/core/internal/account/confirmations/confirmations_util_unittest.cc index a11c92b4c772..f668479d5380 100644 --- a/components/brave_ads/core/internal/account/confirmations/confirmations_util_unittest.cc +++ b/components/brave_ads/core/internal/account/confirmations/confirmations_util_unittest.cc @@ -7,7 +7,6 @@ #include -#include "base/test/mock_callback.h" #include "brave/components/brave_ads/core/internal/account/confirmations/confirmation_info.h" #include "brave/components/brave_ads/core/internal/account/confirmations/non_reward/non_reward_confirmation_test_util.h" #include "brave/components/brave_ads/core/internal/account/confirmations/queue/confirmation_queue_database_table.h" @@ -15,8 +14,6 @@ #include "brave/components/brave_ads/core/internal/account/confirmations/reward/reward_confirmation_test_util.h" #include "brave/components/brave_ads/core/internal/account/confirmations/reward/reward_confirmation_util.h" #include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_test_util.h" -#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_util.h" -#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_util.h" #include "brave/components/brave_ads/core/internal/account/tokens/token_generator_test_util.h" #include "brave/components/brave_ads/core/internal/common/test/test_base.h" #include "brave/components/brave_ads/core/internal/settings/settings_test_util.h" @@ -63,43 +60,4 @@ TEST_F(BraveAdsConfirmationsUtilTest, IsConfirmationNotValid) { EXPECT_FALSE(IsValid(confirmation)); } -TEST_F(BraveAdsConfirmationsUtilTest, ResetTokens) { - // Arrange - test::MockTokenGenerator(/*count=*/1); - test::RefillConfirmationTokens(/*count=*/1); - - const std::optional confirmation = - test::BuildRewardConfirmation(/*should_generate_random_uuids=*/false); - ASSERT_TRUE(confirmation); - test::BuildAndSaveConfirmationQueueItems(*confirmation, /*count=*/1); - - // Act - ResetTokens(); - - // Assert - base::MockCallback callback; - EXPECT_CALL(callback, Run(/*success=*/true, - /*confirmation_queue_items=*/::testing::IsEmpty())); - confirmation_queue_database_table_.GetAll(callback.Get()); - - EXPECT_TRUE(ConfirmationTokensIsEmpty()); - - EXPECT_TRUE(PaymentTokensIsEmpty()); -} - -TEST_F(BraveAdsConfirmationsUtilTest, ResetIfNoTokens) { - // Act - ResetTokens(); - - // Assert - base::MockCallback callback; - EXPECT_CALL(callback, Run(/*success=*/true, - /*confirmation_queue_items=*/::testing::IsEmpty())); - confirmation_queue_database_table_.GetAll(callback.Get()); - - EXPECT_TRUE(ConfirmationTokensIsEmpty()); - - EXPECT_TRUE(PaymentTokensIsEmpty()); -} - } // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/issuers/issuers_util.cc b/components/brave_ads/core/internal/account/issuers/issuers_util.cc index ffbcf87ccc91..8192ff506d7b 100644 --- a/components/brave_ads/core/internal/account/issuers/issuers_util.cc +++ b/components/brave_ads/core/internal/account/issuers/issuers_util.cc @@ -46,11 +46,6 @@ std::optional GetIssuers() { return issuers; } -void ResetIssuers() { - ClearProfilePref(prefs::kIssuerPing); - ClearProfilePref(prefs::kIssuers); -} - bool IsIssuersValid(const IssuersInfo& issuers) { return IsConfirmationTokenIssuerValid(issuers) && IsPaymentTokenIssuerValid(issuers); diff --git a/components/brave_ads/core/internal/account/issuers/issuers_util.h b/components/brave_ads/core/internal/account/issuers/issuers_util.h index 25649e386fda..078da6ef3160 100644 --- a/components/brave_ads/core/internal/account/issuers/issuers_util.h +++ b/components/brave_ads/core/internal/account/issuers/issuers_util.h @@ -14,7 +14,6 @@ struct IssuersInfo; void SetIssuers(const IssuersInfo& issuers); std::optional GetIssuers(); -void ResetIssuers(); bool IsIssuersValid(const IssuersInfo& issuers); diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards.cc b/components/brave_ads/core/internal/account/user_rewards/user_rewards.cc index 30b11dfe0524..94e3cc99ae12 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards.cc +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards.cc @@ -9,7 +9,6 @@ #include "base/debug/dump_without_crashing.h" #include "base/functional/bind.h" -#include "brave/components/brave_ads/core/internal/account/confirmations/confirmations_util.h" #include "brave/components/brave_ads/core/internal/account/issuers/issuers_info.h" #include "brave/components/brave_ads/core/internal/account/issuers/issuers_util.h" #include "brave/components/brave_ads/core/internal/account/issuers/url_request/issuers_url_request.h" @@ -19,9 +18,7 @@ #include "brave/components/brave_ads/core/internal/ads_client/ads_client_util.h" #include "brave/components/brave_ads/core/internal/common/logging_util.h" #include "brave/components/brave_ads/core/internal/common/time/time_formatting_util.h" -#include "brave/components/brave_ads/core/internal/prefs/pref_util.h" #include "brave/components/brave_ads/core/public/ads_client/ads_client.h" -#include "brave/components/brave_ads/core/public/prefs/pref_names.h" namespace brave_ads { @@ -37,8 +34,6 @@ UserRewards::UserRewards(WalletInfo wallet) : wallet_(std::move(wallet)) { UserRewards::~UserRewards() { GetAdsClient()->RemoveObserver(this); - - delegate_ = nullptr; } void UserRewards::FetchIssuers() { @@ -55,39 +50,10 @@ void UserRewards::MaybeRedeemPaymentTokens() { /////////////////////////////////////////////////////////////////////////////// -void UserRewards::MaybeMigrateVerifiedRewardsUser() { - if (!ShouldMigrateVerifiedRewardsUser()) { - return; - } - - BLOG(1, "Migrate verified rewards user"); - - ResetTokens(); - - ResetIssuers(); - FetchIssuers(); - - SetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser, false); - - NotifyDidMigrateVerifiedRewardsUser(); -} - -void UserRewards::NotifyDidMigrateVerifiedRewardsUser() const { - if (delegate_) { - delegate_->OnDidMigrateVerifiedRewardsUser(); - } -} - void UserRewards::OnNotifyDidSolveAdaptiveCaptcha() { MaybeRefillConfirmationTokens(); } -void UserRewards::OnNotifyPrefDidChange(const std::string& path) { - if (path == prefs::kShouldMigrateVerifiedRewardsUser) { - MaybeMigrateVerifiedRewardsUser(); - } -} - void UserRewards::OnDidFetchIssuers(const IssuersInfo& issuers) { if (!IsIssuersValid(issuers)) { return BLOG(0, "Invalid issuers"); diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards.h b/components/brave_ads/core/internal/account/user_rewards/user_rewards.h index 210ff1493ac8..d092a16ba586 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards.h +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards.h @@ -8,12 +8,10 @@ #include -#include "base/memory/raw_ptr.h" #include "brave/components/brave_ads/core/internal/account/issuers/url_request/issuers_url_request.h" #include "brave/components/brave_ads/core/internal/account/issuers/url_request/issuers_url_request_delegate.h" #include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_info.h" #include "brave/components/brave_ads/core/internal/account/transactions/transactions_database_table.h" -#include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h" #include "brave/components/brave_ads/core/internal/account/utility/redeem_payment_tokens/redeem_payment_tokens.h" #include "brave/components/brave_ads/core/internal/account/utility/redeem_payment_tokens/redeem_payment_tokens_delegate.h" #include "brave/components/brave_ads/core/internal/account/utility/refill_confirmation_tokens/refill_confirmation_tokens.h" @@ -40,11 +38,6 @@ class UserRewards final : public AdsClientNotifierObserver, ~UserRewards() override; - void SetDelegate(UserRewardsDelegate* delegate) { - CHECK_EQ(delegate_, nullptr); - delegate_ = delegate; - } - void FetchIssuers(); void MaybeRefillConfirmationTokens(); @@ -52,13 +45,8 @@ class UserRewards final : public AdsClientNotifierObserver, void MaybeRedeemPaymentTokens(); private: - void MaybeMigrateVerifiedRewardsUser(); - - void NotifyDidMigrateVerifiedRewardsUser() const; - // AdsClientNotifierObserver: void OnNotifyDidSolveAdaptiveCaptcha() override; - void OnNotifyPrefDidChange(const std::string& path) override; // IssuersUrlRequestDelegate: void OnDidFetchIssuers(const IssuersInfo& issuers) override; @@ -76,8 +64,6 @@ class UserRewards final : public AdsClientNotifierObserver, void OnCaptchaRequiredToRefillConfirmationTokens( const std::string& captcha_id) override; - raw_ptr delegate_ = nullptr; - IssuersUrlRequest issuers_url_request_; RefillConfirmationTokens refill_confirmation_tokens_; RedeemPaymentTokens redeem_payment_tokens_; diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h b/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h deleted file mode 100644 index 6013f11881ad..000000000000 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2023 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_H_ - -namespace brave_ads { - -class UserRewardsDelegate { - public: - // Invoked to tell the delegate that migration of the verified rewards user - // was successful. - virtual void OnDidMigrateVerifiedRewardsUser() {} - - protected: - virtual ~UserRewardsDelegate() = default; -}; - -} // namespace brave_ads - -#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_H_ diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.cc b/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.cc deleted file mode 100644 index 468d3ac2e52d..000000000000 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.cc +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (c) 2023 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h" - -namespace brave_ads { - -UserRewardsDelegateMock::UserRewardsDelegateMock() = default; - -UserRewardsDelegateMock::~UserRewardsDelegateMock() = default; - -} // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h b/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h deleted file mode 100644 index c56573845421..000000000000 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2023 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_MOCK_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_MOCK_H_ - -#include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace brave_ads { - -class UserRewardsDelegateMock : public UserRewardsDelegate { - public: - UserRewardsDelegateMock(); - - UserRewardsDelegateMock(const UserRewardsDelegateMock&) = delete; - UserRewardsDelegateMock& operator=(const UserRewardsDelegateMock&) = delete; - - UserRewardsDelegateMock(UserRewardsDelegateMock&&) noexcept = delete; - UserRewardsDelegateMock& operator=(UserRewardsDelegateMock&&) noexcept = - delete; - - ~UserRewardsDelegateMock() override; - - MOCK_METHOD(void, OnDidMigrateVerifiedRewardsUser, ()); -}; - -} // namespace brave_ads - -#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_USER_REWARDS_USER_REWARDS_DELEGATE_MOCK_H_ diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_unittest.cc b/components/brave_ads/core/internal/account/user_rewards/user_rewards_unittest.cc index 5a117a4d146b..1eedfc438893 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_unittest.cc +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards_unittest.cc @@ -15,7 +15,6 @@ #include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_util.h" #include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_test_util.h" #include "brave/components/brave_ads/core/internal/account/tokens/token_generator_test_util.h" -#include "brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h" #include "brave/components/brave_ads/core/internal/account/utility/redeem_payment_tokens/redeem_payment_tokens_test_util.h" #include "brave/components/brave_ads/core/internal/account/utility/redeem_payment_tokens/url_request_builders/redeem_payment_tokens_url_request_builder_util.h" #include "brave/components/brave_ads/core/internal/account/utility/refill_confirmation_tokens/refill_confirmation_tokens_test_util.h" @@ -29,8 +28,6 @@ #include "brave/components/brave_ads/core/internal/common/test/profile_pref_value_test_util.h" #include "brave/components/brave_ads/core/internal/common/test/test_base.h" #include "brave/components/brave_ads/core/internal/common/test/time_test_util.h" -#include "brave/components/brave_ads/core/internal/prefs/pref_util.h" -#include "brave/components/brave_ads/core/internal/settings/settings_test_util.h" #include "brave/components/brave_ads/core/public/prefs/pref_names.h" #include "net/http/http_status_code.h" @@ -44,11 +41,9 @@ class BraveAdsUserRewardsTest : public AdsClientMock, public test::TestBase { test::TestBase::SetUp(); user_rewards_ = std::make_unique(test::Wallet()); - user_rewards_->SetDelegate(&delegate_mock_); } std::unique_ptr user_rewards_; - UserRewardsDelegateMock delegate_mock_; }; TEST_F(BraveAdsUserRewardsTest, FetchIssuers) { @@ -218,44 +213,6 @@ TEST_F(BraveAdsUserRewardsTest, RedeemPaymentTokens) { EXPECT_TRUE(PaymentTokensIsEmpty()); } -TEST_F(BraveAdsUserRewardsTest, MigrateVerifiedRewardsUser) { - // Arrange - test::BuildAndSetIssuers(); - - test::MockTokenGenerator(/*count=*/50); - - const test::URLResponseMap url_responses = { - {BuildIssuersUrlPath(), - {{net::HTTP_OK, test::BuildIssuersUrlResponseBody()}}}}; - test::MockUrlResponses(ads_client_mock_, url_responses); - - test::SetPaymentTokens(/*count=*/1); - - EXPECT_CALL(delegate_mock_, OnDidMigrateVerifiedRewardsUser); - - // Act - SetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser, true); - - // Assert - EXPECT_EQ(0U, ConfirmationTokenCount()); - EXPECT_EQ(0U, PaymentTokenCount()); - EXPECT_FALSE(GetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser)); - EXPECT_TRUE(HasIssuers()); -} - -TEST_F(BraveAdsUserRewardsTest, DoNotMigrateVerifiedRewardsUser) { - // Arrange - test::DisableBraveRewards(); - - EXPECT_CALL(delegate_mock_, OnDidMigrateVerifiedRewardsUser).Times(0); - - // Act - SetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser, false); - - // Assert - EXPECT_FALSE(GetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser)); -} - TEST_F(BraveAdsUserRewardsTest, RequireCaptchaToRefillConfirmationTokensIfCaptchaIdExists) { // Arrange diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.cc b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.cc index 253de64f4d6b..2bb0e4119c54 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.cc +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.cc @@ -8,17 +8,9 @@ #include "brave/components/brave_ads/core/internal/account/issuers/issuers_info.h" #include "brave/components/brave_ads/core/internal/account/issuers/issuers_util.h" #include "brave/components/brave_ads/core/internal/common/logging_util.h" -#include "brave/components/brave_ads/core/internal/prefs/pref_util.h" -#include "brave/components/brave_ads/core/internal/settings/settings.h" -#include "brave/components/brave_ads/core/public/prefs/pref_names.h" namespace brave_ads { -bool ShouldMigrateVerifiedRewardsUser() { - return UserHasJoinedBraveRewards() && - GetProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser); -} - void UpdateIssuers(const IssuersInfo& issuers) { if (!HasIssuersChanged(issuers)) { return BLOG(1, "Issuers already up to date"); diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.h b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.h index cd39673b8bad..d4f96267aff6 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.h +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util.h @@ -10,8 +10,6 @@ namespace brave_ads { struct IssuersInfo; -bool ShouldMigrateVerifiedRewardsUser(); - void UpdateIssuers(const IssuersInfo& issuers); } // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util_unittest.cc b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util_unittest.cc index 752a2865795a..02bb0d3a39ab 100644 --- a/components/brave_ads/core/internal/account/user_rewards/user_rewards_util_unittest.cc +++ b/components/brave_ads/core/internal/account/user_rewards/user_rewards_util_unittest.cc @@ -10,9 +10,7 @@ #include "brave/components/brave_ads/core/internal/account/issuers/issuers_util.h" #include "brave/components/brave_ads/core/internal/ads_client/ads_client_notifier_observer_mock.h" #include "brave/components/brave_ads/core/internal/ads_client/ads_client_util.h" -#include "brave/components/brave_ads/core/internal/common/test/profile_pref_value_test_util.h" #include "brave/components/brave_ads/core/internal/common/test/test_base.h" -#include "brave/components/brave_ads/core/internal/settings/settings_test_util.h" #include "brave/components/brave_ads/core/public/prefs/pref_names.h" // npm run test -- brave_unit_tests --filter=BraveAds @@ -37,27 +35,6 @@ class BraveAdsUserRewardsUtilTest : public AdsClientNotifierObserverMock, AdsClientNotifierObserverMock ads_client_notifier_observer_mock_; }; -TEST_F(BraveAdsUserRewardsUtilTest, ShouldMigrateVerifiedRewardsUser) { - // Arrange - test::SetProfileBooleanPrefValue(prefs::kShouldMigrateVerifiedRewardsUser, - true); - - // Act & Assert - EXPECT_TRUE(ShouldMigrateVerifiedRewardsUser()); -} - -TEST_F(BraveAdsUserRewardsUtilTest, - ShouldNotMigrateVerifiedRewardsUserIfBraveRewardsIsDisabled) { - // Arrange - test::DisableBraveRewards(); - - test::SetProfileBooleanPrefValue(prefs::kShouldMigrateVerifiedRewardsUser, - false); - - // Act & Assert - EXPECT_FALSE(ShouldMigrateVerifiedRewardsUser()); -} - TEST_F(BraveAdsUserRewardsUtilTest, UpdateIssuers) { // Arrange EXPECT_CALL(ads_client_notifier_observer_mock_, diff --git a/components/brave_ads/core/internal/common/test/pref_registry_test_util.cc b/components/brave_ads/core/internal/common/test/pref_registry_test_util.cc index 63b01fba7d7d..658deec1624a 100644 --- a/components/brave_ads/core/internal/common/test/pref_registry_test_util.cc +++ b/components/brave_ads/core/internal/common/test/pref_registry_test_util.cc @@ -59,7 +59,6 @@ void RegisterProfilePrefs() { RegisterProfileBooleanPref(prefs::kHasMigratedClientState, true); RegisterProfileBooleanPref(prefs::kHasMigratedConfirmationState, true); - RegisterProfileBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser, false); RegisterProfileStringPref(prefs::kBrowserVersionNumber, ""); diff --git a/components/brave_ads/core/internal/prefs/obsolete_pref_util.cc b/components/brave_ads/core/internal/prefs/obsolete_pref_util.cc index 27fb5624ff97..8c12a5889a1e 100644 --- a/components/brave_ads/core/internal/prefs/obsolete_pref_util.cc +++ b/components/brave_ads/core/internal/prefs/obsolete_pref_util.cc @@ -29,6 +29,9 @@ constexpr char kHasMigratedNotificationState[] = constexpr char kHasMigratedRewardsState[] = "brave.brave_ads.migrated.rewards_state"; +constexpr char kShouldMigrateVerifiedRewardsUser[] = + "brave.brave_ads.rewards.verified_user.should_migrate"; + } // namespace void RegisterProfilePrefsForMigration(PrefRegistrySimple* const registry) { @@ -46,6 +49,9 @@ void RegisterProfilePrefsForMigration(PrefRegistrySimple* const registry) { registry->RegisterBooleanPref(kHasMigratedConversionState, false); registry->RegisterBooleanPref(kHasMigratedNotificationState, false); registry->RegisterBooleanPref(kHasMigratedRewardsState, false); + + // Added 10/2024. + registry->RegisterBooleanPref(kShouldMigrateVerifiedRewardsUser, false); } void MigrateObsoleteProfilePrefs(PrefService* const prefs) { @@ -61,6 +67,9 @@ void MigrateObsoleteProfilePrefs(PrefService* const prefs) { prefs->ClearPref(kHasMigratedConversionState); prefs->ClearPref(kHasMigratedNotificationState); prefs->ClearPref(kHasMigratedRewardsState); + + // Added 10/2024. + prefs->ClearPref(kShouldMigrateVerifiedRewardsUser); } } // namespace brave_ads diff --git a/components/brave_ads/core/internal/prefs/pref_registry.cc b/components/brave_ads/core/internal/prefs/pref_registry.cc index 1baeaf91a7a6..32d08ed5195f 100644 --- a/components/brave_ads/core/internal/prefs/pref_registry.cc +++ b/components/brave_ads/core/internal/prefs/pref_registry.cc @@ -50,8 +50,6 @@ void RegisterProfilePrefs(PrefRegistrySimple* const registry) { registry->RegisterBooleanPref(prefs::kHasMigratedClientState, false); registry->RegisterBooleanPref(prefs::kHasMigratedConfirmationState, false); - registry->RegisterBooleanPref(prefs::kShouldMigrateVerifiedRewardsUser, - false); registry->RegisterStringPref(prefs::kBrowserVersionNumber, ""); diff --git a/components/brave_ads/core/public/prefs/pref_names.h b/components/brave_ads/core/public/prefs/pref_names.h index e878b5f8a07b..79dbcb530cf0 100644 --- a/components/brave_ads/core/public/prefs/pref_names.h +++ b/components/brave_ads/core/public/prefs/pref_names.h @@ -51,8 +51,6 @@ inline constexpr char kHasMigratedClientState[] = "brave.brave_ads.state.has_migrated.client.v7"; inline constexpr char kHasMigratedConfirmationState[] = "brave.brave_ads.state.has_migrated.confirmations.v8"; -inline constexpr char kShouldMigrateVerifiedRewardsUser[] = - "brave.brave_ads.rewards.verified_user.should_migrate"; inline constexpr char kBrowserVersionNumber[] = "brave.brave_ads.browser_version_number"; diff --git a/components/brave_ads/core/test/BUILD.gn b/components/brave_ads/core/test/BUILD.gn index a988fb885f8c..76ba2bbe7bda 100644 --- a/components/brave_ads/core/test/BUILD.gn +++ b/components/brave_ads/core/test/BUILD.gn @@ -106,8 +106,6 @@ source_set("brave_ads_unit_tests") { "//brave/components/brave_ads/core/internal/account/user_data/fixed/summary_user_data_unittest.cc", "//brave/components/brave_ads/core/internal/account/user_data/fixed/summary_user_data_util_unittest.cc", "//brave/components/brave_ads/core/internal/account/user_data/fixed/version_number_user_data_unittest.cc", - "//brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.cc", - "//brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_delegate_mock.h", "//brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_unittest.cc", "//brave/components/brave_ads/core/internal/account/user_rewards/user_rewards_util_unittest.cc", "//brave/components/brave_ads/core/internal/account/utility/redeem_confirmation/non_reward/redeem_non_reward_confirmation_test_util.cc", diff --git a/components/brave_extension/extension/brave_extension/background.ts b/components/brave_extension/extension/brave_extension/background.ts index 5410bfb7b71a..3d2fa7a9e03d 100644 --- a/components/brave_extension/extension/brave_extension/background.ts +++ b/components/brave_extension/extension/brave_extension/background.ts @@ -3,7 +3,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -import './background/greaselion' import './background/webDiscoveryProject' if (chrome.test) { diff --git a/components/brave_extension/extension/brave_extension/background/greaselion.ts b/components/brave_extension/extension/brave_extension/background/greaselion.ts deleted file mode 100644 index 3ebe3f030c8e..000000000000 --- a/components/brave_extension/extension/brave_extension/background/greaselion.ts +++ /dev/null @@ -1,452 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -interface GreaselionError { - errorMessage: string -} - -interface OnAPIRequest { - name: string - url: string - init: {} -} - -interface MediaDurationMetadata { - mediaKey: string - duration: number - firstVisit: boolean -} - -interface RegisterOnCompletedWebRequest { - urlPatterns: string[] -} - -interface RegisterOnSendHeadersWebRequest { - urlPatterns: string[] - extra?: string[] -} - -interface SavePublisherVisit { - url: string - publisherKey: string - publisherName: string - mediaKey?: string - favIconUrl?: string -} - -interface ConnectionState { - port: chrome.runtime.Port - onCompletedWebRequestListener?: ( - details: chrome.webRequest.WebResponseCacheDetails - ) => void - onSendHeadersWebRequestListener?: ( - details: chrome.webRequest.WebRequestHeadersDetails - ) => void - onUpdatedTabListener?: ( - tabId: number, - changeInfo: chrome.tabs.TabChangeInfo, - tab: chrome.tabs.Tab - ) => void -} - -// Maps Greaselion connection state by tabId:senderId -const connectionsByTabIdSenderId = new Map() - -// Maps publisher keys by media key -const publisherKeysByMediaKey = new Map() - -// Maps publisher keys by tabId -const publisherKeysByTabId = new Map() - -const braveRewardsExtensionId = 'jidkidbbcafjabdphckchenhfomhnfma' - -const buildTabIdSenderIdKey = (tabId: number, senderId: string) => { - if (!tabId || !senderId) { - return '' - } - - return `${tabId}:${senderId}` -} - -const handleGreaselionError = (tabId: number, mediaType: string, data: GreaselionError) => { - console.error(`Greaselion error: ${data.errorMessage}`) -} - -const handleOnAPIRequest = (data: OnAPIRequest, onSuccess: (response: any) => void, onFailure: (error: any) => void) => { - if (!data || !data.url || !data.init || !onSuccess || !onFailure) { - return - } - - fetch(data.url, data.init) - .then(response => { - if (!response.ok) { - throw new Error(`API request failed: ${response.statusText} (${response.status})`) - } - - return response.json() - }) - .then(responseData => onSuccess(responseData)) - .catch(error => onFailure(error)) -} - -const handleMediaDurationMetadata = (tabId: number, mediaType: string, data: MediaDurationMetadata) => { - const publisherKey = publisherKeysByMediaKey.get(data.mediaKey) - if (!publisherKey) { - console.error(`Failed to handle media duration metadata: missing publisher key for media key ${data.mediaKey}`) - return - } - - chrome.braveRewards.updateMediaDuration(tabId, publisherKey, data.duration, data.firstVisit) -} - -const onCompletedWebRequest = ( - registrationKey: string, - mediaType: string, - details: chrome.webRequest.WebResponseCacheDetails -) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || !connectionState.port) { - return - } - connectionState.port.postMessage({ - type: 'OnCompletedWebRequest', - mediaType, - details - }) -} - -const handleRegisterOnCompletedWebRequest = ( - registrationKey: string, - mediaType: string, - data: RegisterOnCompletedWebRequest -) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || connectionState.onCompletedWebRequestListener) { - return - } - - // Create and install the listener - const listener = onCompletedWebRequest.bind(null, registrationKey, mediaType) - chrome.webRequest.onCompleted.addListener( - // Listener - listener, - // Filters - { - types: [ - 'image', - 'media', - 'script', - 'xmlhttprequest' - ], - urls: data.urlPatterns - }) - - connectionState.onCompletedWebRequestListener = listener -} - -const onSendHeadersWebRequest = ( - registrationKey: string, - mediaType: string, - details: chrome.webRequest.WebRequestHeadersDetails -) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || !connectionState.port) { - return - } - connectionState.port.postMessage({ - type: 'OnSendHeadersWebRequest', - mediaType, - data: { - details - } - }) -} - -const handleRegisterOnSendHeadersWebRequest = (registrationKey: string, mediaType: string, data: RegisterOnSendHeadersWebRequest) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || connectionState.onSendHeadersWebRequestListener) { - return - } - - // Create and install the listener - const listener = - onSendHeadersWebRequest.bind(null, registrationKey, mediaType) - chrome.webRequest.onSendHeaders.addListener( - // Listener - listener, - // Filters - { - urls: data.urlPatterns - }, - // Extra - data.extra - ) - - connectionState.onSendHeadersWebRequestListener = listener -} - -const onUpdatedTab = ( - registrationKey: string, - mediaType: string, - tabId: number, - changeInfo: chrome.tabs.TabChangeInfo, - tab: chrome.tabs.Tab -) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || !connectionState.port) { - return - } - connectionState.port.postMessage({ - type: 'OnUpdatedTab', - mediaType, - data: { - tabId, - changeInfo, - tab - } - }) -} - -const handleRegisterOnUpdatedTab = (registrationKey: string, mediaType: string) => { - const connectionState = connectionsByTabIdSenderId.get(registrationKey) - if (!connectionState || connectionState.onUpdatedTabListener) { - return - } - - // Create and install the listener - const listener = onUpdatedTab.bind(null, registrationKey, mediaType) - chrome.tabs.onUpdated.addListener(listener) - - connectionState.onUpdatedTabListener = listener -} - -const getPublisherPanelInfo = (tabId: number, publisherKey: string) => { - chrome.braveRewards.getPublisherPanelInfo( - publisherKey, (result: RewardsExtension.Result, info?: RewardsExtension.Publisher) => { - if (result === 0 && info) { - chrome.runtime.sendMessage( - braveRewardsExtensionId, - { - type: 'OnPublisherData', - tabId, - info - }) - } - }) -} - -const getPublisherPanelInfoByTabId = (tabId: number) => { - if (!tabId) { - return - } - - const publisherKey = publisherKeysByTabId.get(tabId) - if (!publisherKey) { - return - } - - getPublisherPanelInfo(tabId, publisherKey) -} - -const savePublisherInfo = (tabId: number, mediaType: string, url: string, publisherKey: string, publisherName: string, favIconUrl: string) => { - chrome.braveRewards.savePublisherInfo( - tabId, - mediaType, - url, - publisherKey, - publisherName, - favIconUrl, - (result: RewardsExtension.Result) => { - if (result !== 0) { - console.error(`Failed to save publisher info for ${publisherKey}, result is ${result}`) - } - }) -} - -const handleSavePublisherVisit = (tabId: number, mediaType: string, data: SavePublisherVisit) => { - if (!data.publisherKey || !data.publisherName) { - console.error('Invalid parameter') - return - } - - publisherKeysByTabId.set(tabId, data.publisherKey) - - chrome.braveRewards.setPublisherIdForTab(tabId, data.publisherKey) - - if (data.mediaKey && !publisherKeysByMediaKey.has(data.mediaKey)) { - publisherKeysByMediaKey.set(data.mediaKey, data.publisherKey) - } - - chrome.braveRewards.getPublisherInfo( - data.publisherKey, (result: RewardsExtension.Result, info?: RewardsExtension.Publisher) => { - let shouldUpdate = false - if (result === 0 && info) { - shouldUpdate = (info.name !== data.publisherName || info.url !== data.url) - if (!shouldUpdate) { - getPublisherPanelInfo(tabId, data.publisherKey) - return - } - } - - // Failed to find the publisher info corresponding to this key or the - // publisher info needs to be updated, so save the info now - if (result === 9 || shouldUpdate) { - savePublisherInfo( - tabId, - mediaType, - data.url, - data.publisherKey, - data.publisherName, - data.favIconUrl || '') - } - }) -} - -const onMessageListener = (msg: any, port: chrome.runtime.Port) => { - if (!port || !port.sender || !port.sender.id || !port.sender.tab || !msg) { - return - } - - const tabId = port.sender.tab.id - if (!tabId) { - return - } - - const senderId = port.sender.id - if (!senderId) { - return - } - - const key = buildTabIdSenderIdKey(tabId, senderId) - if (!connectionsByTabIdSenderId.has(key)) { - const connectionState = { - port - } - connectionsByTabIdSenderId.set(key, connectionState) - } - - chrome.greaselion.isGreaselionExtension(port.sender.id, (valid: boolean) => { - if (!valid) { - return - } - switch (msg.type) { - case 'GreaselionError': { - const data = msg.data as GreaselionError - handleGreaselionError(tabId, msg.mediaType, data) - break - } - case 'MediaDurationMetadata': { - const data = msg.data as MediaDurationMetadata - handleMediaDurationMetadata(tabId, msg.mediaType, data) - break - } - case 'OnAPIRequest': { - const data = msg.data as OnAPIRequest - handleOnAPIRequest( - data, - (response: any) => { - if (connectionsByTabIdSenderId.has(key)) { - port.postMessage({ - type: 'OnAPIResponse', - mediaType: msg.mediaType, - data: { - name: data.name, - response - } - }) - } - }, - (error: any) => { - if (connectionsByTabIdSenderId.has(key)) { - port.postMessage({ - type: 'OnAPIResponse', - mediaType: msg.mediaType, - data: { - name: data.name, - error - } - }) - } - }) - break - } - case 'RegisterOnCompletedWebRequest': { - const data = msg.data as RegisterOnCompletedWebRequest - handleRegisterOnCompletedWebRequest(key, msg.mediaType, data) - break - } - case 'RegisterOnSendHeadersWebRequest': { - const data = msg.data as RegisterOnSendHeadersWebRequest - handleRegisterOnSendHeadersWebRequest(key, msg.mediaType, data) - break - } - case 'RegisterOnUpdatedTab': { - handleRegisterOnUpdatedTab(key, msg.mediaType) - break - } - case 'SavePublisherVisit': { - const data = msg.data as SavePublisherVisit - handleSavePublisherVisit(tabId, msg.mediaType, data) - break - } - } - }) -} - -chrome.runtime.onConnectExternal.addListener((port: chrome.runtime.Port) => { - if (!port || port.name !== 'Greaselion') { - return - } - - port.onMessage.addListener(onMessageListener) - - port.onDisconnect.addListener((port: chrome.runtime.Port) => { - if (chrome.runtime.lastError) { - console.error(`Greaselion port disconnected due to error: ${chrome.runtime.lastError}`) - } - if (port.sender && port.sender.id && port.sender.tab && port.sender.tab.id) { - const key = buildTabIdSenderIdKey(port.sender.tab.id, port.sender.id) - const connectionState = connectionsByTabIdSenderId.get(key) - if (connectionState) { - if (connectionState.onCompletedWebRequestListener) { - chrome.webRequest.onCompleted.removeListener( - connectionState.onCompletedWebRequestListener) - } - if (connectionState.onSendHeadersWebRequestListener) { - chrome.webRequest.onSendHeaders.removeListener( - connectionState.onSendHeadersWebRequestListener) - } - if (connectionState.onUpdatedTabListener) { - chrome.tabs.onUpdated.removeListener( - connectionState.onUpdatedTabListener) - } - } - - connectionsByTabIdSenderId.delete(key) - publisherKeysByTabId.delete(port.sender.tab.id) - - port.onMessage.removeListener(onMessageListener) - } - }) -}) - -chrome.runtime.onMessageExternal.addListener( - function (msg: any, sender: chrome.runtime.MessageSender, sendResponse: any) { - if (!msg || !msg.type || !sender || !sender.id) { - return - } - chrome.greaselion.isGreaselionExtension(sender.id, (valid: boolean) => { - if (!valid && sender.id !== braveRewardsExtensionId) { - return - } - switch (msg.type) { - case 'GetPublisherPanelInfo': - getPublisherPanelInfoByTabId(msg.tabId) - break - case 'SupportsGreaselion': - sendResponse({ supported: true }) - break - } - }) - }) diff --git a/components/brave_new_tab_ui/components/search/EngineContext.tsx b/components/brave_new_tab_ui/components/search/EngineContext.tsx new file mode 100644 index 000000000000..aa8c1a98fc60 --- /dev/null +++ b/components/brave_new_tab_ui/components/search/EngineContext.tsx @@ -0,0 +1,85 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. +import { SearchEngineInfo } from '../../api/background' +import { useNewTabPref } from '../../hooks/usePref' +import * as React from 'react'; +import { ENABLED_SEARCH_ENGINES_KEY, LAST_SEARCH_ENGINE_KEY, braveSearchHost } from './config'; + +interface Engine { + setLastSearchEngine: (engine: SearchEngineInfo) => void + lastSearchEngine: string, + engineConfig: Record, + setEngineConfig: (engine: string, enabled: boolean) => void, +} + +const EngineContext = React.createContext({ + setLastSearchEngine: () => { }, + lastSearchEngine: '', + engineConfig: {}, + setEngineConfig: () => { }, +}) + +const searchEngineConfig = () => { + const localStorageValue = localStorage.getItem(ENABLED_SEARCH_ENGINES_KEY); + if (localStorageValue) { + return JSON.parse(localStorageValue); + } + return { + // Default to enabling Brave Search + [braveSearchHost]: true + }; +} + +export function EngineContextProvider(props: React.PropsWithChildren<{}>) { + const [lastUsed, setLastUsed] = useNewTabPref('lastUsedNtpSearchEngine') + const lastLocalStorage = localStorage.getItem(LAST_SEARCH_ENGINE_KEY) + const [config, setConfig] = React.useState>(searchEngineConfig); + + const setLastNtpSearchEngine = React.useCallback((engine: SearchEngineInfo) => { + setLastUsed(engine.host); + }, [setLastUsed]) + + const lastNtpSearchEngine = React.useMemo(() => { + let last = lastUsed; + + // Migrates the existing local storage value to the new pref value, letting the local storage value take precedence. + if (lastLocalStorage && config[lastLocalStorage] && lastUsed !== lastLocalStorage) { + setLastUsed(lastLocalStorage); + last = lastLocalStorage; + localStorage.removeItem(LAST_SEARCH_ENGINE_KEY) + } + + // If the last search engine we used has been disabled or doesn't exist in the config, return the first enabled + // one, or Brave Search. + if (!last || !config[last]) { + return Object.keys(config).find(key => config[key]) ?? braveSearchHost + } + + return last + }, [lastUsed, lastLocalStorage, config]); + + const setEngineEnabled = React.useCallback(((engine: string, enabled: boolean) => { + setConfig(prevConfig => { + const newState = { ...prevConfig, [engine]: enabled }; + localStorage.setItem(ENABLED_SEARCH_ENGINES_KEY, JSON.stringify(newState)); + return newState; + }); + }), []) + + return ( + + {props.children} + + ) +} + +export function useEngineContext() { + return React.useContext(EngineContext) +} diff --git a/components/brave_new_tab_ui/components/search/SearchContext.tsx b/components/brave_new_tab_ui/components/search/SearchContext.tsx index 8d06ffc66d41..eea2fe963c80 100644 --- a/components/brave_new_tab_ui/components/search/SearchContext.tsx +++ b/components/brave_new_tab_ui/components/search/SearchContext.tsx @@ -8,7 +8,7 @@ import { AutocompleteResult, OmniboxPopupSelection, PageHandler, PageHandlerRemo import { stringToMojoString16 } from 'chrome://resources/js/mojo_type_util.js'; import * as React from 'react'; import getNTPBrowserAPI, { SearchEngineInfo } from '../../api/background'; -import { getDefaultSearchEngine, isSearchEngineEnabled, setDefaultSearchEngine } from './config'; +import { useEngineContext } from './EngineContext'; interface Context { open: boolean, @@ -23,7 +23,7 @@ interface Context { const Context = React.createContext({ open: false, - setOpen: () => {}, + setOpen: () => { }, query: '', setQuery: () => { }, searchEngine: undefined, @@ -73,18 +73,19 @@ class SearchPage implements PageInterface { for (const listener of this.selectionListeners) listener(selection) } - setInputText(inputText: string) {} - setThumbnail(thumbnailUrl: string) {} + setInputText(inputText: string) { } + setThumbnail(thumbnailUrl: string) { } } export const search = new SearchPage() export function SearchContext(props: React.PropsWithChildren<{}>) { + const { engineConfig, lastSearchEngine, setLastSearchEngine } = useEngineContext() const [open, setOpen] = React.useState(false) const [searchEngine, setSearchEngineInternal] = React.useState() const [query, setQuery] = React.useState('') const { result: searchEngines = [] } = usePromise(() => searchEnginesPromise, []) - const filteredSearchEngines = searchEngines.filter(isSearchEngineEnabled) + const filteredSearchEngines = searchEngines.filter(s => engineConfig[s.host]) const setSearchEngine = React.useCallback((engine: SearchEngineInfo | string) => { if (typeof engine === 'string') { @@ -93,7 +94,7 @@ export function SearchContext(props: React.PropsWithChildren<{}>) { if (!engine) return - setDefaultSearchEngine(engine) + setLastSearchEngine(engine) getNTPBrowserAPI().newTabMetrics.reportNTPSearchDefaultEngine(engine.prepopulateId) setSearchEngineInternal(engine) }, [searchEngines]); @@ -102,7 +103,7 @@ export function SearchContext(props: React.PropsWithChildren<{}>) { React.useEffect(() => { if (!searchEngines.length) return - const match = filteredSearchEngines.find(s => s.host === getDefaultSearchEngine()) + const match = filteredSearchEngines.find(s => s.host === lastSearchEngine) ?? searchEngines[0] getNTPBrowserAPI().newTabMetrics.reportNTPSearchDefaultEngine(match.prepopulateId) setSearchEngine(match) diff --git a/components/brave_new_tab_ui/components/search/SearchEngineIcon.tsx b/components/brave_new_tab_ui/components/search/SearchEngineIcon.tsx index f05d7d52ccaa..4abf0efa784b 100644 --- a/components/brave_new_tab_ui/components/search/SearchEngineIcon.tsx +++ b/components/brave_new_tab_ui/components/search/SearchEngineIcon.tsx @@ -41,7 +41,7 @@ function MaybeImage(props: React.DetailedHTMLProps diff --git a/components/brave_new_tab_ui/components/search/config.ts b/components/brave_new_tab_ui/components/search/config.ts index 3361ce478300..ea578b9879f7 100644 --- a/components/brave_new_tab_ui/components/search/config.ts +++ b/components/brave_new_tab_ui/components/search/config.ts @@ -2,62 +2,10 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -import { radius } from "@brave/leo/tokens/css/variables"; -import { SearchEngineInfo } from "../../api/background"; - -// At some point we might want to store this in prefs, but -// at this point its only used on Desktop, and only on the NTP -// so this seems fine. -const ENABLED_SEARCH_ENGINES_KEY = 'search-engines' -const LAST_SEARCH_ENGINE_KEY = 'last-search-engine' +import { radius } from "@brave/leo/tokens/css/variables" +// You can obtain one at https://mozilla.org/MPL/2.0/. +export const ENABLED_SEARCH_ENGINES_KEY = 'search-engines' +export const LAST_SEARCH_ENGINE_KEY = 'last-search-engine' export const braveSearchHost = 'search.brave.com' -export const searchBoxRadius = radius.xl; - -let cache: Record | undefined - -const getConfig = () => { - if (!cache) { - cache = JSON.parse(localStorage.getItem(ENABLED_SEARCH_ENGINES_KEY)!) ?? { - // Default to enabling Brave Search - [braveSearchHost]: true - } - } - return cache! -} - -// Determines whether any search engines are enabled -export const hasEnabledEngine = () => Object.values(getConfig()).find(c => c) - -export const maybeEnableDefaultEngine = () => { - // If no engines are enabled, enable the default one. - if (!hasEnabledEngine()) { - setEngineEnabled({ host: braveSearchHost }, true) - } -} - -export const setEngineEnabled = (engine: { host: string }, enabled: boolean) => { - const config = getConfig() - config[engine.host] = enabled - - localStorage.setItem(ENABLED_SEARCH_ENGINES_KEY, JSON.stringify(config)) -} - -export const isSearchEngineEnabled = (engine: SearchEngineInfo) => getConfig()[engine.host] - -export const getDefaultSearchEngine = () => { - const config = getConfig() - const last = localStorage.getItem(LAST_SEARCH_ENGINE_KEY) - - // If the last search engine we used has been disabled, return the first enabled - // one, or Brave Search. - if (!config[last!]) { - return Object.entries(config).find(([key, value]) => value)?.[0] - ?? braveSearchHost - } - return last -} - -export const setDefaultSearchEngine = (engine: SearchEngineInfo) => { - localStorage.setItem(LAST_SEARCH_ENGINE_KEY, engine.host) -} +export const searchBoxRadius = radius.xl diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index c6deb0a24204..f4e4f3002ae3 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -44,6 +44,7 @@ import Icon from '@brave/leo/react/icon' import * as style from './style' import { defaultState } from '../../storage/new_tab_storage' +import { EngineContextProvider } from '../../components/search/EngineContext' const BraveNewsPeek = React.lazy(() => import('../../../brave_news/browser/resources/Peek')) const SearchPlaceholder = React.lazy(() => import('../../components/search/SearchPlaceholder')) @@ -273,7 +274,7 @@ class NewTabPage extends React.Component { if (activeSettingsTabRaw) { const allSettingsTabTypes = [...Object.keys(SettingsTabType)] if (allSettingsTabTypes.includes(activeSettingsTabRaw)) { - activeSettingsTab = SettingsTabType[activeSettingsTabRaw] + activeSettingsTab = SettingsTabType[activeSettingsTabRaw as keyof typeof SettingsTabType] } } this.setState({ showSettingsMenu: true, activeSettingsTab }) @@ -403,7 +404,7 @@ class NewTabPage extends React.Component { showRewards, showBraveTalk } = this.props.newTabData - const lookup = { + const lookup: { [p: string]: { display: boolean, render: any } } = { 'rewards': { display: braveRewardsSupported && showRewards, render: this.renderRewardsWidget.bind(this) @@ -621,6 +622,7 @@ class NewTabPage extends React.Component { data-show-news-prompt={((this.state.backgroundHasLoaded || colorForBackground) && this.state.isPromptingBraveNews && !defaultState.featureFlagBraveNewsFeedV2Enabled) ? true : undefined}> + { /> : null } + ) diff --git a/components/brave_new_tab_ui/containers/newTab/settings/search.tsx b/components/brave_new_tab_ui/containers/newTab/settings/search.tsx index a52a8db1879d..e5cf9e608eda 100644 --- a/components/brave_new_tab_ui/containers/newTab/settings/search.tsx +++ b/components/brave_new_tab_ui/containers/newTab/settings/search.tsx @@ -20,9 +20,10 @@ import { } from '../../../components/default' import { searchEnginesPromise } from '../../../components/search/SearchContext' import { MediumSearchEngineIcon } from '../../../components/search/SearchEngineIcon' -import { hasEnabledEngine, isSearchEngineEnabled, maybeEnableDefaultEngine, setEngineEnabled } from '../../../components/search/config' import { useNewTabPref } from '../../../hooks/usePref' import { getLocale } from '../../../../common/locale' +import { braveSearchHost } from '../../../components/search/config' +import { useEngineContext } from '../../../components/search/EngineContext' const EnginesContainer = styled(Flex)` font: ${font.default.regular}; @@ -66,10 +67,18 @@ const Hr = styled.hr` ` const CheckboxText = styled.span`flex: 1`; +const hasEnabledEngine = (config: Record) => Object.keys(config).some(key => config[key]) export default function SearchSettings() { const { result: engines = [] } = usePromise(() => searchEnginesPromise, []) const [showSearchBox, setShowSearchBox] = useNewTabPref('showSearchBox') + const { setEngineConfig, engineConfig } = useEngineContext() + + React.useEffect(() => { + if (!hasEnabledEngine(engineConfig)) { + setShowSearchBox(false) + } + }, [engineConfig]) return @@ -79,8 +88,8 @@ export default function SearchSettings() { // If we've just enabled the searchbox, make sure at least one engine // is enabled. - if (e.checked) { - maybeEnableDefaultEngine() + if (e.checked && !hasEnabledEngine(engineConfig)) { + setEngineConfig(braveSearchHost, true) } }} /> @@ -90,11 +99,8 @@ export default function SearchSettings() {
{getLocale('searchEnableSearchEnginesTitle')}
{engines.map(engine => - { - setEngineEnabled(engine, e.checked) - if (!hasEnabledEngine()) { - setShowSearchBox(false) - } + { + setEngineConfig(engine.host, e.checked) }}> {engine.name} diff --git a/components/brave_new_tab_ui/storage/new_tab_storage.ts b/components/brave_new_tab_ui/storage/new_tab_storage.ts index fe253ba06f92..c16b8a8d3b70 100644 --- a/components/brave_new_tab_ui/storage/new_tab_storage.ts +++ b/components/brave_new_tab_ui/storage/new_tab_storage.ts @@ -6,6 +6,7 @@ // Utils import { debounce } from '../../common/debounce' import { loadTimeData } from '../../common/loadTimeData' +import { braveSearchHost } from '../components/search/config' export const keyName = 'new-tab-data' @@ -28,6 +29,7 @@ export const defaultState: NewTab.State = { showRewards: false, showBraveTalk: false, showSearchBox: true, + lastUsedNtpSearchEngine: braveSearchHost, promptEnableSearchSuggestions: true, searchSuggestionsEnabled: false, showBitcoinDotCom: false, @@ -115,7 +117,7 @@ export const replaceStackWidgets = (state: NewTab.State) => { braveRewardsSupported, braveTalkSupported } = state - const displayLookup = { + const displayLookup: { [p: string]: { display: boolean } } = { 'rewards': { display: braveRewardsSupported && showRewards }, diff --git a/components/brave_rewards/browser/BUILD.gn b/components/brave_rewards/browser/BUILD.gn index 7de87871a8d1..4185ed4eb8af 100644 --- a/components/brave_rewards/browser/BUILD.gn +++ b/components/brave_rewards/browser/BUILD.gn @@ -4,7 +4,6 @@ # You can obtain one at https://mozilla.org/MPL/2.0/. import("//brave/components/brave_rewards/core/config.gni") -import("//brave/components/greaselion/browser/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") static_library("browser") { @@ -14,8 +13,6 @@ static_library("browser") { "diagnostic_log.cc", "diagnostic_log.h", "logging.h", - "publisher_utils.cc", - "publisher_utils.h", "rewards_notification_service.cc", "rewards_notification_service.h", "rewards_notification_service_impl.cc", @@ -44,7 +41,6 @@ static_library("browser") { "//brave/components/brave_wallet/browser", "//brave/components/brave_wallet/common", "//brave/components/brave_wallet/common:mojom", - "//brave/components/greaselion/browser/buildflags", "//brave/components/ntp_background_images/common", "//brave/components/p3a_utils", "//brave/components/resources", @@ -73,10 +69,6 @@ static_library("browser") { if (is_android) { deps += [ "//brave/components/safetynet:android" ] } - - if (enable_greaselion) { - deps += [ "//brave/components/greaselion/browser" ] - } } source_set("testutil") { diff --git a/components/brave_rewards/browser/publisher_utils_unittest.cc b/components/brave_rewards/browser/publisher_utils_unittest.cc deleted file mode 100644 index db329b670fc9..000000000000 --- a/components/brave_rewards/browser/publisher_utils_unittest.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "brave/components/brave_rewards/browser/publisher_utils.h" - -#include -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace brave_rewards { - -class RewardsPublisherUtilsTest : public testing::Test { - protected: - std::optional GetPublisherId(const std::string& url) { - return GetPublisherIdFromURL(GURL(url)); - } -}; - -TEST_F(RewardsPublisherUtilsTest, GetPublisherIdFromURL) { - EXPECT_EQ(GetPublisherId("https://brave.com"), "brave.com"); - EXPECT_EQ(GetPublisherId("http://brave.com"), "brave.com"); - EXPECT_EQ(GetPublisherId("https://search.brave.com"), "brave.com"); - EXPECT_EQ(GetPublisherId("http://search.brave.com"), "brave.com"); - - EXPECT_EQ(GetPublisherId("https://brave.co.uk"), "brave.co.uk"); - EXPECT_EQ(GetPublisherId("https://www.brave.co.uk"), "brave.co.uk"); - - EXPECT_EQ(GetPublisherId("file:///a/b/c/"), std::nullopt); - EXPECT_EQ(GetPublisherId("invalid-url"), std::nullopt); - - EXPECT_EQ(GetPublisherId("https://twitter.com/foo"), std::nullopt); - EXPECT_EQ(GetPublisherId("https://github.com/foo"), std::nullopt); - EXPECT_EQ(GetPublisherId("https://reddit.com/foo"), std::nullopt); - EXPECT_EQ(GetPublisherId("https://youtube.com/foo"), std::nullopt); - EXPECT_EQ(GetPublisherId("https://vimeo.com/foo"), std::nullopt); - EXPECT_EQ(GetPublisherId("https://twitch.tv/foo"), std::nullopt); -} - -} // namespace brave_rewards diff --git a/components/brave_rewards/browser/rewards_service.h b/components/brave_rewards/browser/rewards_service.h index 0c64c46a874b..2f15ae8e5aeb 100644 --- a/components/brave_rewards/browser/rewards_service.h +++ b/components/brave_rewards/browser/rewards_service.h @@ -144,6 +144,7 @@ class RewardsService : public KeyedService { virtual void GetExcludedList(GetPublisherInfoListCallback callback) = 0; virtual void RestorePublishers() = 0; + virtual void OnLoad(mojom::VisitDataPtr visit_data) = 0; virtual void OnLoad(SessionID tab_id, const GURL& gurl) = 0; virtual void OnUnload(SessionID tab_id) = 0; virtual void OnShow(SessionID tab_id) = 0; @@ -171,8 +172,10 @@ class RewardsService : public KeyedService { const uint32_t month, const uint32_t year, GetBalanceReportCallback callback) = 0; + virtual void GetPublisherActivityFromVisitData( + mojom::VisitDataPtr visit_data) = 0; virtual void GetPublisherActivityFromUrl( - uint64_t windowId, + uint64_t tab_id, const std::string& url, const std::string& favicon_url, const std::string& publisher_blob) = 0; @@ -223,12 +226,6 @@ class RewardsService : public KeyedService { virtual const RewardsNotificationService::RewardsNotificationsMap& GetAllNotifications() = 0; - virtual void UpdateMediaDuration( - const uint64_t window_id, - const std::string& publisher_key, - const uint64_t duration, - const bool firstVisit) = 0; - virtual void IsPublisherRegistered( const std::string& publisher_id, base::OnceCallback callback) = 0; diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 3ed81f9c1856..c64e387c193d 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -36,7 +36,6 @@ #include "brave/components/brave_rewards/browser/android_util.h" #include "brave/components/brave_rewards/browser/diagnostic_log.h" #include "brave/components/brave_rewards/browser/logging.h" -#include "brave/components/brave_rewards/browser/publisher_utils.h" #include "brave/components/brave_rewards/browser/rewards_notification_service.h" #include "brave/components/brave_rewards/browser/rewards_notification_service_impl.h" #include "brave/components/brave_rewards/browser/rewards_p3a.h" @@ -45,6 +44,7 @@ #include "brave/components/brave_rewards/common/buildflags/buildflags.h" #include "brave/components/brave_rewards/common/features.h" #include "brave/components/brave_rewards/common/pref_names.h" +#include "brave/components/brave_rewards/common/publisher_utils.h" #include "brave/components/brave_rewards/common/rewards_util.h" #include "brave/components/brave_rewards/core/global_constants.h" #include "brave/components/brave_rewards/core/parameters/rewards_parameters_provider.h" @@ -256,18 +256,12 @@ RewardsServiceImpl::RewardsServiceImpl( RequestImageCallback request_image_callback, CancelImageRequestCallback cancel_image_request_callback, content::StoragePartition* storage_partition, -#if BUILDFLAG(ENABLE_GREASELION) - greaselion::GreaselionService* greaselion_service, -#endif brave_wallet::BraveWalletService* brave_wallet_service) : prefs_(prefs), favicon_service_(favicon_service), request_image_callback_(request_image_callback), cancel_image_request_callback_(cancel_image_request_callback), storage_partition_(storage_partition), -#if BUILDFLAG(ENABLE_GREASELION) - greaselion_service_(greaselion_service), -#endif brave_wallet_service_(brave_wallet_service), receiver_(this), file_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( @@ -290,28 +284,11 @@ RewardsServiceImpl::RewardsServiceImpl( persist_log_level_ = kDiagnosticLogMaxVerboseLevel; } -#if BUILDFLAG(ENABLE_GREASELION) - if (greaselion_service_) { - // Greaselion's rules may be ready before we register our observer, so check - // for that here - if (!greaselion_enabled_ && greaselion_service_->rules_ready()) { - OnRulesReady(greaselion_service_); - } - greaselion_service_->AddObserver(this); - } -#endif - p3a::RecordAdTypesEnabled(prefs_); } RewardsServiceImpl::~RewardsServiceImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - -#if BUILDFLAG(ENABLE_GREASELION) - if (greaselion_service_) { - greaselion_service_->RemoveObserver(this); - } -#endif } void RewardsServiceImpl::ConnectionClosed() { @@ -388,16 +365,6 @@ void RewardsServiceImpl::OnPreferenceChanged(const std::string& key) { base::BindOnce(&RewardsServiceImpl::OnRecordBackendP3AExternalWallet, AsWeakPtr(), false, true)); } - -#if BUILDFLAG(ENABLE_GREASELION) - if (key == brave_ads::prefs::kOptedInToNotificationAds) { - if (greaselion_service_) { - greaselion_service_->SetFeatureEnabled( - greaselion::ADS, - prefs_->GetBoolean(brave_ads::prefs::kOptedInToNotificationAds)); - } - } -#endif } void RewardsServiceImpl::CheckPreferences() { @@ -684,12 +651,15 @@ void RewardsServiceImpl::OnGetPublisherInfoList( std::move(callback).Run(std::move(list)); } -void RewardsServiceImpl::OnLoad(SessionID tab_id, const GURL& url) { +void RewardsServiceImpl::OnLoad(mojom::VisitDataPtr visit_data) { if (!Connected()) { return; } + engine_->OnLoad(std::move(visit_data), GetCurrentTimestamp()); +} - if (IsAutoContributeHandledByContentScript(url)) { +void RewardsServiceImpl::OnLoad(SessionID tab_id, const GURL& url) { + if (!Connected()) { return; } @@ -755,8 +725,12 @@ void RewardsServiceImpl::OnXHRLoad(SessionID tab_id, return; } - if (IsAutoContributeHandledByContentScript(url) || - !GetPublisherDomainFromURL(url)) { + if (base::FeatureList::IsEnabled( + features::kPlatformCreatorDetectionFeature)) { + return; + } + + if (!GetPublisherDomainFromURL(url)) { return; } @@ -1187,29 +1161,6 @@ void RewardsServiceImpl::GetReconcileStamp(GetReconcileStampCallback callback) { engine_->GetReconcileStamp(std::move(callback)); } -#if BUILDFLAG(ENABLE_GREASELION) -void RewardsServiceImpl::EnableGreaselion() { - if (!greaselion_service_) { - return; - } - - greaselion_service_->SetFeatureEnabled(greaselion::REWARDS, true); - greaselion_service_->SetFeatureEnabled( - greaselion::AUTO_CONTRIBUTION, - prefs_->GetBoolean(prefs::kAutoContributeEnabled)); - greaselion_service_->SetFeatureEnabled( - greaselion::ADS, - prefs_->GetBoolean(brave_ads::prefs::kOptedInToNotificationAds)); - - greaselion_enabled_ = true; -} - -void RewardsServiceImpl::OnRulesReady( - greaselion::GreaselionService* greaselion_service) { - EnableGreaselion(); -} -#endif - void RewardsServiceImpl::StopEngine(StopEngineCallback callback) { BLOG(1, "Shutting down rewards process"); if (!Connected()) { @@ -1476,21 +1427,36 @@ void RewardsServiceImpl::GetBalanceReport( std::move(callback))); } +void RewardsServiceImpl::GetPublisherActivityFromVisitData( + mojom::VisitDataPtr visit_data) { + if (!Connected()) { + return; + } + uint32_t tab_id = visit_data->tab_id; + engine_->GetPublisherActivityFromUrl(tab_id, std::move(visit_data), ""); +} + void RewardsServiceImpl::GetPublisherActivityFromUrl( - uint64_t windowId, + uint64_t tab_id, const std::string& url, const std::string& favicon_url, const std::string& publisher_blob) { GURL parsed_url(url); - if (!parsed_url.is_valid() || - IsAutoContributeHandledByContentScript(parsed_url)) { + if (!parsed_url.is_valid()) { return; } + if (base::FeatureList::IsEnabled( + features::kPlatformCreatorDetectionFeature)) { + if (IsMediaPlatformURL(parsed_url)) { + return; + } + } + auto publisher_domain = GetPublisherDomainFromURL(parsed_url); if (!publisher_domain) { mojom::PublisherInfoPtr info; - OnPanelPublisherInfo(mojom::Result::NOT_FOUND, std::move(info), windowId); + OnPanelPublisherInfo(mojom::Result::NOT_FOUND, std::move(info), tab_id); return; } @@ -1505,19 +1471,19 @@ void RewardsServiceImpl::GetPublisherActivityFromUrl( visit_data->url = parsed_url.scheme() + "://" + *publisher_domain + "/"; visit_data->favicon_url = favicon_url; - engine_->GetPublisherActivityFromUrl(windowId, std::move(visit_data), + engine_->GetPublisherActivityFromUrl(tab_id, std::move(visit_data), publisher_blob); } void RewardsServiceImpl::OnPanelPublisherInfo(mojom::Result result, mojom::PublisherInfoPtr info, - uint64_t windowId) { + uint64_t tab_id) { if (result != mojom::Result::OK && result != mojom::Result::NOT_FOUND) { return; } for (auto& observer : observers_) { - observer.OnPanelPublisherInfo(this, result, info.get(), windowId); + observer.OnPanelPublisherInfo(this, result, info.get(), tab_id); } } @@ -1664,18 +1630,6 @@ void RewardsServiceImpl::OnContributionSent( std::move(callback).Run(success); } -void RewardsServiceImpl::UpdateMediaDuration( - const uint64_t window_id, - const std::string& publisher_key, - const uint64_t duration, - const bool first_visit) { - if (!Connected()) { - return; - } - - engine_->UpdateMediaDuration(window_id, publisher_key, duration, first_visit); -} - void RewardsServiceImpl::IsPublisherRegistered( const std::string& publisher_id, base::OnceCallback callback) { diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index bb9001e04413..b93cd20e240f 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -30,7 +30,6 @@ #include "brave/components/brave_rewards/common/rewards_flags.h" #include "brave/components/brave_wallet/browser/brave_wallet_service.h" #include "brave/components/brave_wallet/common/brave_wallet.mojom.h" -#include "brave/components/greaselion/browser/buildflags/buildflags.h" #include "brave/components/services/bat_rewards/public/interfaces/rewards_engine_factory.mojom.h" #include "build/build_config.h" #include "components/prefs/pref_change_registrar.h" @@ -44,10 +43,6 @@ #include "brave/components/safetynet/safetynet_check.h" #endif -#if BUILDFLAG(ENABLE_GREASELION) -#include "brave/components/greaselion/browser/greaselion_service.h" -#endif - namespace base { class OneShotTimer; class SequencedTaskRunner; @@ -92,9 +87,6 @@ using RequestImageCallback = base::RepeatingCallback; using CancelImageRequestCallback = base::RepeatingCallback; class RewardsServiceImpl final : public RewardsService, -#if BUILDFLAG(ENABLE_GREASELION) - public greaselion::GreaselionService::Observer, -#endif public mojom::RewardsEngineClient { public: RewardsServiceImpl(PrefService* prefs, @@ -103,9 +95,6 @@ class RewardsServiceImpl final : public RewardsService, RequestImageCallback request_image_callback, CancelImageRequestCallback cancel_image_request_callback, content::StoragePartition* storage_partition, -#if BUILDFLAG(ENABLE_GREASELION) - greaselion::GreaselionService* greaselion_service, -#endif brave_wallet::BraveWalletService* brave_wallet_service); RewardsServiceImpl(const RewardsServiceImpl&) = delete; @@ -151,6 +140,7 @@ class RewardsServiceImpl final : public RewardsService, void OnGetPublisherInfoList(GetPublisherInfoListCallback callback, std::vector list); + void OnLoad(mojom::VisitDataPtr visit_data) override; void OnLoad(SessionID tab_id, const GURL& url) override; void OnUnload(SessionID tab_id) override; void OnShow(SessionID tab_id) override; @@ -172,11 +162,12 @@ class RewardsServiceImpl final : public RewardsService, const uint32_t month, const uint32_t year, GetBalanceReportCallback callback) override; - void GetPublisherActivityFromUrl( - uint64_t window_id, - const std::string& url, - const std::string& favicon_url, - const std::string& publisher_blob) override; + void GetPublisherActivityFromVisitData( + mojom::VisitDataPtr visit_data) override; + void GetPublisherActivityFromUrl(uint64_t tab_id, + const std::string& url, + const std::string& favicon_url, + const std::string& publisher_blob) override; void GetAutoContributionAmount( GetAutoContributionAmountCallback callback) override; void GetPublisherBanner(const std::string& publisher_id, @@ -225,12 +216,6 @@ class RewardsServiceImpl final : public RewardsService, void SetAutoContributionAmount(const double amount) const override; - void UpdateMediaDuration( - const uint64_t window_id, - const std::string& publisher_key, - const uint64_t duration, - const bool first_visit) override; - void IsPublisherRegistered(const std::string& publisher_id, base::OnceCallback callback) override; @@ -312,13 +297,6 @@ class RewardsServiceImpl final : public RewardsService, using SimpleURLLoaderList = std::list>; -#if BUILDFLAG(ENABLE_GREASELION) - void EnableGreaselion(); - - // GreaselionService::Observer: - void OnRulesReady(greaselion::GreaselionService* greaselion_service) override; -#endif - void InitPrefChangeRegistrar(); void OnPreferenceChanged(const std::string& key); @@ -389,7 +367,7 @@ class RewardsServiceImpl final : public RewardsService, void SetPublisherMinVisits(int visits) const override; void OnPanelPublisherInfo(mojom::Result result, mojom::PublisherInfoPtr info, - uint64_t window_id) override; + uint64_t tab_id) override; void FetchFavIcon(const std::string& url, const std::string& favicon_key, FetchFavIconCallback callback) override; @@ -554,11 +532,6 @@ class RewardsServiceImpl final : public RewardsService, const RequestImageCallback request_image_callback_; const CancelImageRequestCallback cancel_image_request_callback_; raw_ptr storage_partition_; // NOT OWNED -#if BUILDFLAG(ENABLE_GREASELION) - raw_ptr greaselion_service_ = - nullptr; // NOT OWNED - bool greaselion_enabled_ = false; -#endif raw_ptr brave_wallet_service_ = nullptr; mojo::AssociatedReceiver receiver_; mojo::AssociatedRemote engine_; diff --git a/components/brave_rewards/browser/rewards_service_impl_jp_unittest.cc b/components/brave_rewards/browser/rewards_service_impl_jp_unittest.cc index e4ed2bea1c2a..5d4b823ca9a7 100644 --- a/components/brave_rewards/browser/rewards_service_impl_jp_unittest.cc +++ b/components/brave_rewards/browser/rewards_service_impl_jp_unittest.cc @@ -10,7 +10,6 @@ #include "brave/components/brave_rewards/common/features.h" #include "brave/components/brave_rewards/common/pref_names.h" #include "brave/components/brave_rewards/core/global_constants.h" -#include "brave/components/greaselion/browser/buildflags/buildflags.h" #include "brave/components/l10n/common/test/scoped_default_locale.h" #include "chrome/browser/profiles/profile.h" #include "chrome/test/base/testing_browser_process.h" @@ -45,9 +44,6 @@ class RewardsServiceJPTest : public testing::Test { const net::NetworkTrafficAnnotationTag& traffic_annotation)>(), base::RepeatingCallback(), profile()->GetDefaultStoragePartition(), -#if BUILDFLAG(ENABLE_GREASELION) - nullptr, -#endif nullptr); ASSERT_TRUE(rewards_service()); diff --git a/components/brave_rewards/browser/rewards_service_impl_unittest.cc b/components/brave_rewards/browser/rewards_service_impl_unittest.cc index 6c6f45426962..9cf26617b9c9 100644 --- a/components/brave_rewards/browser/rewards_service_impl_unittest.cc +++ b/components/brave_rewards/browser/rewards_service_impl_unittest.cc @@ -15,7 +15,6 @@ #include "brave/components/brave_rewards/common/mojom/rewards.mojom.h" #include "brave/components/brave_rewards/common/pref_names.h" #include "brave/components/brave_rewards/core/global_constants.h" -#include "brave/components/greaselion/browser/buildflags/buildflags.h" #include "brave/components/l10n/common/test/scoped_default_locale.h" #include "chrome/browser/profiles/profile.h" #include "chrome/test/base/testing_browser_process.h" @@ -72,9 +71,6 @@ class RewardsServiceTest : public testing::Test { const net::NetworkTrafficAnnotationTag& traffic_annotation)>(), base::RepeatingCallback(), profile()->GetDefaultStoragePartition(), -#if BUILDFLAG(ENABLE_GREASELION) - nullptr, -#endif nullptr); ASSERT_TRUE(rewards_service()); observer_ = std::make_unique(); diff --git a/components/brave_rewards/browser/test/rewards_state_browsertest.cc b/components/brave_rewards/browser/test/rewards_state_browsertest.cc index 3b74b2a40097..b298edcab149 100644 --- a/components/brave_rewards/browser/test/rewards_state_browsertest.cc +++ b/components/brave_rewards/browser/test/rewards_state_browsertest.cc @@ -20,7 +20,6 @@ #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "brave/browser/brave_rewards/rewards_service_factory.h" -#include "brave/components/brave_ads/core/public/prefs/pref_names.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_network_util.h" #include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_response.h" @@ -996,18 +995,6 @@ IN_PROC_BROWSER_TEST_P_(V13, Paths) { ASSERT_TRUE(encrypted_wallet); profile_->GetPrefs()->SetString( "brave.rewards.wallets." + std::get<0>(GetParam()), *encrypted_wallet); - - test_util::StartProcess(rewards_service_); - - if (wallet_status == mojom::WalletStatus::kConnected) { - ASSERT_TRUE(profile_->GetPrefs()->HasPrefPath( - brave_ads::prefs::kShouldMigrateVerifiedRewardsUser)); - ASSERT_TRUE(profile_->GetPrefs()->GetBoolean( - brave_ads::prefs::kShouldMigrateVerifiedRewardsUser)); - } else { - ASSERT_FALSE(profile_->GetPrefs()->HasPrefPath( - brave_ads::prefs::kShouldMigrateVerifiedRewardsUser)); - } } IN_PROC_BROWSER_TEST_F(RewardsStateBrowserTest, V14EmptyWalletType) { diff --git a/components/brave_rewards/common/BUILD.gn b/components/brave_rewards/common/BUILD.gn index 79c45b364c60..9c45c3c0cd08 100644 --- a/components/brave_rewards/common/BUILD.gn +++ b/components/brave_rewards/common/BUILD.gn @@ -20,6 +20,8 @@ static_library("common") { "pref_names.h", "pref_registry.cc", "pref_registry.h", + "publisher_utils.cc", + "publisher_utils.h", "rewards_flags.cc", "rewards_flags.h", "rewards_util.cc", @@ -31,6 +33,7 @@ static_library("common") { "//base", "//brave/components/l10n/common", "//components/prefs", - "//third_party/abseil-cpp:absl", + "//net", + "//url", ] } diff --git a/components/brave_rewards/common/features.cc b/components/brave_rewards/common/features.cc index d9acd9a13be8..1b3b0c87a9c3 100644 --- a/components/brave_rewards/common/features.cc +++ b/components/brave_rewards/common/features.cc @@ -41,4 +41,13 @@ BASE_FEATURE(kAnimatedBackgroundFeature, "BraveRewardsAnimatedBackground", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPlatformCreatorDetectionFeature, + "BraveRewardsPlatformCreatorDetection", +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + base::FEATURE_DISABLED_BY_DEFAULT +#else + base::FEATURE_ENABLED_BY_DEFAULT +#endif +); + } // namespace brave_rewards::features diff --git a/components/brave_rewards/common/features.h b/components/brave_rewards/common/features.h index bc386f6888f2..27bc8059b40a 100644 --- a/components/brave_rewards/common/features.h +++ b/components/brave_rewards/common/features.h @@ -30,6 +30,8 @@ BASE_DECLARE_FEATURE(kNewRewardsUIFeature); BASE_DECLARE_FEATURE(kAnimatedBackgroundFeature); +BASE_DECLARE_FEATURE(kPlatformCreatorDetectionFeature); + } // namespace brave_rewards::features #endif // BRAVE_COMPONENTS_BRAVE_REWARDS_COMMON_FEATURES_H_ diff --git a/components/brave_rewards/common/mojom/rewards_engine.mojom b/components/brave_rewards/common/mojom/rewards_engine.mojom index fcb072b888cf..641be2307337 100644 --- a/components/brave_rewards/common/mojom/rewards_engine.mojom +++ b/components/brave_rewards/common/mojom/rewards_engine.mojom @@ -110,11 +110,6 @@ interface RewardsEngine { StartContributionsForTesting(); - UpdateMediaDuration(uint64 window_id, - string publisher_key, - uint64 duration, - bool first_visit); - IsPublisherRegistered(string publisher_id) => (bool registered); GetPublisherInfo(string publisher_key) diff --git a/components/brave_rewards/browser/publisher_utils.cc b/components/brave_rewards/common/publisher_utils.cc similarity index 58% rename from components/brave_rewards/browser/publisher_utils.cc rename to components/brave_rewards/common/publisher_utils.cc index 3e6b0ebdc4b9..1643572e6da1 100644 --- a/components/brave_rewards/browser/publisher_utils.cc +++ b/components/brave_rewards/common/publisher_utils.cc @@ -1,33 +1,51 @@ /* Copyright (c) 2022 The Brave Authors. All rights reserved. * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ -#include "brave/components/brave_rewards/browser/publisher_utils.h" +#include "brave/components/brave_rewards/common/publisher_utils.h" #include #include #include "base/ranges/algorithm.h" +#include "base/strings/string_util.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" namespace brave_rewards { namespace { -const std::array kMediaPlatformDomains = {"twitter.com", "github.com", - "reddit.com", "twitch.tv", - "vimeo.com", "youtube.com"}; +constexpr auto kMediaPlatformDomains = std::to_array( + {"github.com", "reddit.com", "twitch.tv", "twitter.com", "vimeo.com", + "x.com", "youtube.com"}); + +constexpr auto kMediaPlatformPrefixes = std::to_array( + {"github#", "reddit#", "twitch#", "twitter#", "vimeo#", "youtube#"}); + +} // namespace bool IsMediaPlatformURL(const GURL& url) { - return base::ranges::any_of(kMediaPlatformDomains, [&url](auto* domain) { + if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) { + return false; + } + return base::ranges::any_of(kMediaPlatformDomains, [&url](auto domain) { return net::registry_controlled_domains::SameDomainOrHost( url, GURL("https://" + std::string(domain)), net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); }); } -} // namespace +std::optional GetMediaPlatformFromPublisherId( + std::string_view publisher_id) { + for (auto prefix : kMediaPlatformPrefixes) { + CHECK(prefix.length() > 1); + if (publisher_id.starts_with(prefix)) { + return std::string(publisher_id.substr(0, prefix.length() - 1)); + } + } + return std::nullopt; +} std::optional GetPublisherIdFromURL(const GURL& url) { if (IsMediaPlatformURL(url)) { @@ -50,12 +68,4 @@ std::optional GetPublisherDomainFromURL(const GURL& url) { return domain; } -bool IsAutoContributeHandledByContentScript(const GURL& url) { -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) - return false; -#else - return IsMediaPlatformURL(url); -#endif -} - } // namespace brave_rewards diff --git a/components/brave_rewards/browser/publisher_utils.h b/components/brave_rewards/common/publisher_utils.h similarity index 58% rename from components/brave_rewards/browser/publisher_utils.h rename to components/brave_rewards/common/publisher_utils.h index f248fe77f4bf..f55b6d8e6a70 100644 --- a/components/brave_rewards/browser/publisher_utils.h +++ b/components/brave_rewards/common/publisher_utils.h @@ -1,18 +1,27 @@ /* Copyright (c) 2022 The Brave Authors. All rights reserved. * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ -#ifndef BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_PUBLISHER_UTILS_H_ -#define BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_PUBLISHER_UTILS_H_ +#ifndef BRAVE_COMPONENTS_BRAVE_REWARDS_COMMON_PUBLISHER_UTILS_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_COMMON_PUBLISHER_UTILS_H_ #include #include +#include #include "url/gurl.h" namespace brave_rewards { +// Returns a value indicating whether the specified URL is a social media +// platform that can host Rewards publisher content. +bool IsMediaPlatformURL(const GURL& url); + +// Returns the media platform associated with the specified publisher ID. +std::optional GetMediaPlatformFromPublisherId( + std::string_view publisher_id); + // Returns the publisher ID associated with the specified URL, or `nullopt` if // the publisher ID cannot be statically determined from the URL. For example, // a `nullopt` will be returned if the URL points to a configured social media @@ -23,9 +32,6 @@ std::optional GetPublisherIdFromURL(const GURL& url); // platforms, the site domain will be returned (e.g "twitter.com"). std::optional GetPublisherDomainFromURL(const GURL& url); -// Returns a value indicating whether content scripting is used to measure AC. -bool IsAutoContributeHandledByContentScript(const GURL& url); - } // namespace brave_rewards -#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_PUBLISHER_UTILS_H_ +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_COMMON_PUBLISHER_UTILS_H_ diff --git a/components/brave_rewards/common/publisher_utils_unittest.cc b/components/brave_rewards/common/publisher_utils_unittest.cc new file mode 100644 index 000000000000..ec60f2c92a46 --- /dev/null +++ b/components/brave_rewards/common/publisher_utils_unittest.cc @@ -0,0 +1,85 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/brave_rewards/common/publisher_utils.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace brave_rewards { + +namespace { + +std::optional GetPublisherId(const std::string& url) { + return GetPublisherIdFromURL(GURL(url)); +} + +} // namespace + +class RewardsPublisherUtilsTest : public testing::Test {}; + +TEST(RewardsPublisherUtilsTest, IsMediaPlatformURL) { + EXPECT_FALSE(IsMediaPlatformURL(GURL("https://brave.com"))); + EXPECT_FALSE(IsMediaPlatformURL(GURL("http://brave.com"))); + EXPECT_FALSE(IsMediaPlatformURL(GURL("https://search.brave.com"))); + + EXPECT_FALSE(IsMediaPlatformURL(GURL("https://brave.co.uk"))); + EXPECT_FALSE(IsMediaPlatformURL(GURL("https://www.brave.co.uk"))); + + EXPECT_FALSE(IsMediaPlatformURL(GURL("file:///a/b/c/"))); + EXPECT_FALSE(IsMediaPlatformURL(GURL("invalid-url"))); + EXPECT_FALSE(IsMediaPlatformURL(GURL("abc://twitter.com/foo"))); + + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://twitter.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://www.twitter.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://x.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://www.x.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://github.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://reddit.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://youtube.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://vimeo.com/foo"))); + EXPECT_TRUE(IsMediaPlatformURL(GURL("https://twitch.tv/foo"))); +} + +TEST(RewardsPublisherUtilsTest, GetMediaPlatformFromPublisherId) { + EXPECT_EQ(GetMediaPlatformFromPublisherId("youtube#channel:123").value(), + "youtube"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("reddit#channel:123").value(), + "reddit"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("github#channel:123").value(), + "github"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("twitch#author:123").value(), + "twitch"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("vimeo#channel:123").value(), + "vimeo"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("twitter#channel:123").value(), + "twitter"); + EXPECT_EQ(GetMediaPlatformFromPublisherId("example.com"), std::nullopt); +} + +TEST(RewardsPublisherUtilsTest, GetPublisherIdFromURL) { + EXPECT_EQ(GetPublisherId("https://brave.com"), "brave.com"); + EXPECT_EQ(GetPublisherId("http://brave.com"), "brave.com"); + EXPECT_EQ(GetPublisherId("https://search.brave.com"), "brave.com"); + EXPECT_EQ(GetPublisherId("http://search.brave.com"), "brave.com"); + + EXPECT_EQ(GetPublisherId("https://brave.co.uk"), "brave.co.uk"); + EXPECT_EQ(GetPublisherId("https://www.brave.co.uk"), "brave.co.uk"); + + EXPECT_EQ(GetPublisherId("file:///a/b/c/"), std::nullopt); + EXPECT_EQ(GetPublisherId("invalid-url"), std::nullopt); + + EXPECT_EQ(GetPublisherId("https://twitter.com/foo"), std::nullopt); + EXPECT_EQ(GetPublisherId("https://github.com/foo"), std::nullopt); + EXPECT_EQ(GetPublisherId("https://reddit.com/foo"), std::nullopt); + EXPECT_EQ(GetPublisherId("https://youtube.com/foo"), std::nullopt); + EXPECT_EQ(GetPublisherId("https://vimeo.com/foo"), std::nullopt); + EXPECT_EQ(GetPublisherId("https://twitch.tv/foo"), std::nullopt); +} + +} // namespace brave_rewards diff --git a/components/brave_rewards/core/publisher/media/media.cc b/components/brave_rewards/core/publisher/media/media.cc index f22904f13fe7..c20745ac0217 100644 --- a/components/brave_rewards/core/publisher/media/media.cc +++ b/components/brave_rewards/core/publisher/media/media.cc @@ -3,10 +3,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "brave/components/brave_rewards/core/publisher/media/media.h" + #include #include "base/containers/flat_map.h" -#include "brave/components/brave_rewards/core/publisher/media/media.h" +#include "base/feature_list.h" +#include "brave/components/brave_rewards/common/features.h" #include "brave/components/brave_rewards/core/legacy/static_values.h" #include "brave/components/brave_rewards/core/publisher/publisher.h" #include "brave/components/brave_rewards/core/rewards_engine.h" @@ -23,6 +26,11 @@ Media::~Media() = default; std::string Media::GetLinkType(const std::string& url, const std::string& first_party_url, const std::string& referrer) { + if (base::FeatureList::IsEnabled( + features::kPlatformCreatorDetectionFeature)) { + return ""; + } + std::string type = YouTube::GetLinkType(url); if (type.empty()) { diff --git a/components/brave_rewards/core/publisher/publisher.cc b/components/brave_rewards/core/publisher/publisher.cc index 906c5d401d02..2cb7bc001873 100644 --- a/components/brave_rewards/core/publisher/publisher.cc +++ b/components/brave_rewards/core/publisher/publisher.cc @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "brave/components/brave_rewards/core/publisher/publisher.h" + #include #include #include @@ -11,8 +13,10 @@ #include #include +#include "base/feature_list.h" #include "base/strings/stringprintf.h" #include "base/uuid.h" +#include "brave/components/brave_rewards/common/features.h" #include "brave/components/brave_rewards/core/constants.h" #include "brave/components/brave_rewards/core/contribution/contribution.h" #include "brave/components/brave_rewards/core/database/database.h" @@ -20,7 +24,6 @@ #include "brave/components/brave_rewards/core/legacy/static_values.h" #include "brave/components/brave_rewards/core/publisher/media/media.h" #include "brave/components/brave_rewards/core/publisher/prefix_util.h" -#include "brave/components/brave_rewards/core/publisher/publisher.h" #include "brave/components/brave_rewards/core/publisher/publisher_prefix_list_updater.h" #include "brave/components/brave_rewards/core/publisher/server_publisher_fetcher.h" #include "brave/components/brave_rewards/core/rewards_engine.h" @@ -550,8 +553,10 @@ void Publisher::GetPublisherActivityFromUrl(uint64_t windowId, return; } - const bool is_media = visit_data->domain == YOUTUBE_DOMAIN || - visit_data->domain == GITHUB_DOMAIN; + const bool is_media = !base::FeatureList::IsEnabled( + features::kPlatformCreatorDetectionFeature) && + (visit_data->domain == YOUTUBE_DOMAIN || + visit_data->domain == GITHUB_DOMAIN); if (is_media && visit_data->path != "" && visit_data->path != "/") { std::string type = YOUTUBE_MEDIA_TYPE; @@ -724,39 +729,6 @@ void Publisher::OnSearchPrefixListForGetServerPublisherInfo( } } -void Publisher::UpdateMediaDuration(const uint64_t window_id, - const std::string& publisher_key, - const uint64_t duration, - const bool first_visit) { - engine_->Log(FROM_HERE) << "Media duration: " << duration; - engine_->database()->GetPublisherInfo( - publisher_key, - base::BindOnce(&Publisher::OnGetPublisherInfoForUpdateMediaDuration, - weak_factory_.GetWeakPtr(), window_id, duration, - first_visit)); -} - -void Publisher::OnGetPublisherInfoForUpdateMediaDuration( - const uint64_t window_id, - const uint64_t duration, - const bool first_visit, - mojom::Result result, - mojom::PublisherInfoPtr info) { - if (result != mojom::Result::OK) { - engine_->LogError(FROM_HERE) - << "Failed to retrieve publisher info while updating media duration"; - return; - } - - mojom::VisitData visit_data; - visit_data.name = info->name; - visit_data.url = info->url; - visit_data.provider = info->provider; - visit_data.favicon_url = info->favicon_url; - - SaveVisit(info->id, visit_data, duration, first_visit, 0, base::DoNothing()); -} - void Publisher::GetPublisherPanelInfo(const std::string& publisher_key, GetPublisherPanelInfoCallback callback) { auto filter = CreateActivityFilter( diff --git a/components/brave_rewards/core/publisher/publisher.h b/components/brave_rewards/core/publisher/publisher.h index c57f04a70382..0eb8954dc195 100644 --- a/components/brave_rewards/core/publisher/publisher.h +++ b/components/brave_rewards/core/publisher/publisher.h @@ -85,11 +85,6 @@ class Publisher { bool use_prefix_list, GetServerPublisherInfoCallback callback); - void UpdateMediaDuration(const uint64_t window_id, - const std::string& publisher_key, - const uint64_t duration, - const bool first_visit); - void GetPublisherPanelInfo(const std::string& publisher_key, GetPublisherPanelInfoCallback callback); @@ -112,12 +107,6 @@ class Publisher { GetServerPublisherInfoCallback callback, bool publisher_exists); - void OnGetPublisherInfoForUpdateMediaDuration(const uint64_t window_id, - const uint64_t duration, - const bool first_visit, - mojom::Result result, - mojom::PublisherInfoPtr info); - void OnGetPanelPublisherInfo(GetPublisherPanelInfoCallback callback, const mojom::Result result, mojom::PublisherInfoPtr info); diff --git a/components/brave_rewards/core/rewards_engine.cc b/components/brave_rewards/core/rewards_engine.cc index b2b5c11b573b..f6de5f5c7efc 100644 --- a/components/brave_rewards/core/rewards_engine.cc +++ b/components/brave_rewards/core/rewards_engine.cc @@ -456,16 +456,6 @@ void RewardsEngine::StartContributionsForTesting() { }); } -void RewardsEngine::UpdateMediaDuration(uint64_t window_id, - const std::string& publisher_key, - uint64_t duration, - bool first_visit) { - WhenReady([this, window_id, publisher_key, duration, first_visit] { - publisher()->UpdateMediaDuration(window_id, publisher_key, duration, - first_visit); - }); -} - void RewardsEngine::IsPublisherRegistered( const std::string& publisher_id, IsPublisherRegisteredCallback callback) { diff --git a/components/brave_rewards/core/rewards_engine.h b/components/brave_rewards/core/rewards_engine.h index 6be3c41106ec..a4f24767f607 100644 --- a/components/brave_rewards/core/rewards_engine.h +++ b/components/brave_rewards/core/rewards_engine.h @@ -190,11 +190,6 @@ class RewardsEngine : public mojom::RewardsEngine, void StartContributionsForTesting() override; - void UpdateMediaDuration(uint64_t window_id, - const std::string& publisher_key, - uint64_t duration, - bool first_visit) override; - void IsPublisherRegistered(const std::string& publisher_id, IsPublisherRegisteredCallback callback) override; diff --git a/components/brave_rewards/resources/BUILD.gn b/components/brave_rewards/resources/BUILD.gn index 7ff8e7b65693..370bcc3a5e69 100644 --- a/components/brave_rewards/resources/BUILD.gn +++ b/components/brave_rewards/resources/BUILD.gn @@ -37,6 +37,7 @@ repack("resources") { ":internals_generated_resources", ":page_generated_resources", ":static_resources", + "creator_detection:creator_detection_generated", "rewards_page:rewards_page_generated", ] @@ -44,6 +45,7 @@ repack("resources") { "$root_gen_dir/brave/components/brave_rewards/resources/brave_rewards_internals_generated.pak", "$root_gen_dir/brave/components/brave_rewards/resources/brave_rewards_page_generated.pak", "$root_gen_dir/brave/components/brave_rewards/resources/brave_rewards_static.pak", + "$root_gen_dir/brave/components/brave_rewards/resources/creator_detection_generated.pak", "$root_gen_dir/brave/components/brave_rewards/resources/rewards_page_generated.pak", ] diff --git a/components/brave_rewards/resources/creator_detection/BUILD.gn b/components/brave_rewards/resources/creator_detection/BUILD.gn new file mode 100644 index 000000000000..e4bc58e57b46 --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//brave/components/common/typescript.gni") + +transpile_web_ui("creator_detection") { + entry_points = [ + [ + "github", + rebase_path("github.ts"), + ], + [ + "reddit", + rebase_path("reddit.ts"), + ], + [ + "twitch", + rebase_path("twitch.ts"), + ], + [ + "twitter", + rebase_path("twitter.ts"), + ], + [ + "vimeo", + rebase_path("vimeo.ts"), + ], + [ + "youtube", + rebase_path("youtube.ts"), + ], + ] + resource_name = "creator_detection" +} + +pack_web_resources("creator_detection_generated") { + resource_name = "creator_detection" + output_dir = "$root_gen_dir/brave/components/brave_rewards/resources" + deps = [ ":creator_detection" ] +} diff --git a/components/brave_rewards/resources/creator_detection/creator_detection.ts b/components/brave_rewards/resources/creator_detection/creator_detection.ts new file mode 100644 index 000000000000..e1d21eb834f6 --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/creator_detection.ts @@ -0,0 +1,54 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { log, throttle } from './helpers' + +export interface CreatorInfo { + id: string + name: string + url: string + imageURL: string +} + +type DetectionHandler = () => Promise + +function setPageDetectionHandler(detectCreator: DetectionHandler) { + let { braveRewards } = self as any + if (!braveRewards) { + braveRewards = {} + Object.assign(self, { braveRewards }) + } + Object.assign(braveRewards, { detectCreator }) +} + +export function initializeDetector(initializer: () => DetectionHandler) { + const detectCreator = throttle(initializer()) + let currentURL = '' + + setPageDetectionHandler(async () => { + if (location.href === currentURL) { + return null + } + + currentURL = location.href + + let creator: CreatorInfo | null = null + try { + creator = await detectCreator() + } catch (err) { + log.error('Error detecting creator', err) + } + + if (creator) { + log.info('Found creator:', creator) + } else { + log.info('No creator found for current URL') + } + + return creator + }) +} + + diff --git a/components/brave_rewards/resources/creator_detection/github.ts b/components/brave_rewards/resources/creator_detection/github.ts new file mode 100644 index 000000000000..3e25c2935942 --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/github.ts @@ -0,0 +1,112 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { CreatorInfo, initializeDetector } from './creator_detection' +import { log, getPathComponents } from './helpers' + +initializeDetector(() => { + + const nonUserPaths = new Set([ + 'about', + 'enterprise', + 'events', + 'explore', + 'home', + 'issues', + 'login', + 'logout', + 'marketplace', + 'nonprofit', + 'notifications', + 'orgs', + 'pricing', + 'pulls', + 'search', + 'settings', + 'team', + 'tos' + ]) + + function getScreenNameFromPath(path: string) { + const parts = getPathComponents(path) + if (parts.length === 0) { + return '' + } + + const screenName = parts[0] + if (screenName === 'orgs' && parts.length > 1) { + return parts[1] + } + + if (nonUserPaths.has(screenName)) { + return '' + } + + return screenName + } + + function getCreatorFromResponse(screenName: string, response: any): any { + if (!response) { + log.info('Empty response') + return null + } + if (!response.id) { + log.info('Missing "id" property') + return null + } + return { + id: `github#channel:${response.id}`, + name: screenName, + url: `https://github.com/${screenName}/`, + imageURL: String(response.avatar_url || '') + } + } + + let currentCreator: CreatorInfo | null = null + + async function fetchUserData(screenName: string) { + if (!screenName) { + return null + } + + if (currentCreator && currentCreator.name === screenName) { + return currentCreator + } + + const hostname = 'api.' + location.hostname.split('.').slice(-2).join('.') + const origin = location.origin.replace(location.hostname, hostname) + const response = await fetch(`${origin}/users/${screenName}`) + + if (!response.ok) { + log.error('Unable to fetch profile data') + return null + } + + let responseJSON: any + try { + responseJSON = await response.json() + } catch (err) { + log.error('Error parsing profile data', err) + return null + } + + currentCreator = getCreatorFromResponse(screenName, responseJSON) + if (!currentCreator) { + log.info('Profile data response', responseJSON) + } + + return currentCreator + } + + return async () => { + const screenName = getScreenNameFromPath(location.pathname) + if (!screenName) { + log.info('No screen name for the current path') + return null + } + return await fetchUserData(screenName) + } + +}) diff --git a/components/brave_rewards/resources/creator_detection/helpers.ts b/components/brave_rewards/resources/creator_detection/helpers.ts new file mode 100644 index 000000000000..90ba6ab21d5b --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/helpers.ts @@ -0,0 +1,70 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +export const log = new class { + info(...args: any[]) { + console.debug('[Rewards]', ...args) + } + + error(...args: any[]) { + console.error('[Rewards]', ...args) + } +} + +interface PollOptions { + name: string + timeout: number + interval: number +} + +export async function pollFor(fn: () => T | Promise, opts: PollOptions) { + const startTime = Date.now() + while (Date.now() - startTime < opts.timeout) { + const result = await fn() + if (result) { + return result + } + await new Promise((resolve) => setTimeout(resolve, opts.interval)) + } + log.info(`Timed out waiting for ${opts.name}`) + return null +} + +export function throttle(fn: () => Promise | T) { + let current: Promise | null = null + let next: Promise | null = null + + let start = () => { + current = Promise.resolve(fn()).finally(() => { current = null }) + return current + } + + return () => { + if (!current) { + return start() + } + if (!next) { + next = current.finally(() => { next = null }).then(start) + } + return next + } +} + +export function urlPath(url: string) { + try { return new URL(url, location.href).pathname } + catch { return '' } +} + +export function absoluteURL(url: string) { + try { return new URL(url, location.href).toString() } + catch { return '' } +} + +export function getPathComponents(path: string) { + return path + .split('/') + .filter((part) => part) + .map((part) => part.toLocaleLowerCase()) +} diff --git a/components/brave_rewards/resources/creator_detection/reddit.ts b/components/brave_rewards/resources/creator_detection/reddit.ts new file mode 100644 index 000000000000..8ee4343237f4 --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/reddit.ts @@ -0,0 +1,81 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { CreatorInfo, initializeDetector } from './creator_detection' +import { log } from './helpers' + +initializeDetector(() => { + + function getCreatorFromResponse(screenName: string, response: any): any { + if (!response || response.kind !== 't2') { + log.info('Unexpected "kind" value') + return null + } + const { data } = response + if (!data) { + log.info('Missing "data" property') + return null + } + if (!data.id || typeof data.id !== 'string') { + log.info('Missing "id" property') + return null + } + return { + id: `reddit#channel:${data.id}`, + name: screenName, + url: `https://reddit.com/user/${screenName}/`, + imageURL: String(data.icon_img || '') + } + } + + let currentCreator: CreatorInfo | null = null + + async function fetchUserData(screenName: string) { + if (!screenName) { + return null + } + + if (currentCreator && currentCreator.name === screenName) { + return currentCreator + } + + log.info('Fetching profile data for', screenName) + const response = await fetch(`/user/${screenName}/about.json`) + if (!response.ok) { + log.error('Unable to fetch profile data') + return null + } + + let responseJSON: any + try { + responseJSON = await response.json() + } catch (err) { + log.error('Error parsing profile data', err) + return null + } + + currentCreator = getCreatorFromResponse(screenName, responseJSON) + if (!currentCreator) { + log.info('Profile data response', responseJSON) + } + + return currentCreator + } + + function getScreenNameFromPath(path: string) { + const match = path.match(/^\/user\/([^\/]+)/i) + return match ? match[1] : '' + } + + return async () => { + const screenName = getScreenNameFromPath(location.pathname) + if (!screenName) { + log.info('No screen name for the current path') + return null + } + return await fetchUserData(screenName) + } + +}) diff --git a/components/brave_rewards/resources/creator_detection/twitch.ts b/components/brave_rewards/resources/creator_detection/twitch.ts new file mode 100644 index 000000000000..523ffd3455e4 --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/twitch.ts @@ -0,0 +1,125 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { CreatorInfo, initializeDetector } from './creator_detection' +import { log, getPathComponents, pollFor } from './helpers' + +initializeDetector(() => { + + function scrapeIcon() { + const elem = + document.querySelector('.channel-info-content .tw-avatar [src]') + return (elem && elem.getAttribute('src')) || '' + } + + function getChannelTitleElement() { + return document.querySelector('h1.tw-title') + } + + function scrapeChannelName() { + const elem = getChannelTitleElement() + return elem && elem.textContent || '' + } + + function firstPathComponent(path: string) { + return getPathComponents(path)[0] || '' + } + + function isVideoPath() { + return firstPathComponent(location.pathname) === 'videos' + } + + const excludedPaths = new Set([ + 'directory', + 'downloads', + 'jobs', + 'p', + 'search', + 'turbo' + ]) + + function scrapeChannelID() { + if (isVideoPath()) { + const elem = getChannelTitleElement() + if (!elem || !elem.parentElement) { + log.info('Unable to find parent of channel title element') + return '' + } + const href = elem.parentElement.getAttribute('href') + if (!href) { + log.info('Missing "href" attribute in title element') + return '' + } + let id = firstPathComponent(href) + if (!id) { + log.info('Unable to find channel ID in channel title "href":', href) + return '' + } + log.info('Found channel ID in channel title element:', id) + return id + } + + const pathPart = firstPathComponent(location.pathname) + if (!pathPart || excludedPaths.has(pathPart)) { + log.info('Path does not support creator detection') + return '' + } + + log.info('Found channel ID in path:', pathPart) + return pathPart + } + + function scrapeUser() { + const id = scrapeChannelID() + if (!id) { + return null + } + return { + id: `twitch#author:${id}`, + name: scrapeChannelName(), + url: `${location.origin}/${id}`, + imageURL: scrapeIcon() + } + } + + let currentUser: CreatorInfo | null = null + + function isPageLoadComplete() { + const user = scrapeUser() + if (!user) { + return !isVideoPath() + } + if (!user.name || !user.imageURL) { + return false + } + if (!currentUser) { + return true + } + if (user.id === currentUser.id) { + return true + } + return ( + user.name !== currentUser.name && + user.imageURL !== currentUser.imageURL + ) + } + + function getUser() { + if (!isPageLoadComplete()) { + return null + } + currentUser = scrapeUser() + return currentUser + } + + return async () => { + return await pollFor(getUser, { + name: 'creator', + interval: 500, + timeout: 6000 + }) + } + +}) diff --git a/components/brave_rewards/resources/creator_detection/twitter.ts b/components/brave_rewards/resources/creator_detection/twitter.ts new file mode 100644 index 000000000000..8222a4a0548a --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/twitter.ts @@ -0,0 +1,148 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { CreatorInfo, initializeDetector } from './creator_detection' +import { log, pollFor } from './helpers' + +function getUserFromAppState(eventName: string, screenName: string) { + interface StateStore { + getState: () => any + } + + let messages: any[] = [] + + function getElementStore(elem: object | null) { + if (!elem) { + return null + } + for (const name of Object.getOwnPropertyNames(elem)) { + if (name.startsWith('__reactProps$')) { + let store: any = null + try { store = (elem as any)[name].children.props.store } + catch {} + if (store && typeof store.getState === 'function') { + return store as StateStore + } + } + } + return null + } + + function findStore(elem: Element | null, depth = 0): StateStore | null { + if (!elem) { + return null + } + let store = getElementStore(elem) + if (store) { + return store + } + if (depth === 4) { + return null + } + for (let child of elem.children) { + store = findStore(child, depth + 1) + if (store) { + return store + } + } + return null + } + + function screenNamesMatch(name1: any, name2: any) { + if (typeof name1 === 'string' && typeof name2 === 'string') { + return name1.toLocaleLowerCase() === name2.toLocaleLowerCase() + } + return false + } + + function getUserFromState(state: any, screenName: string) { + const userEntities = state.entities.users.entities + for (let [key, value] of Object.entries(userEntities) as any) { + if (screenNamesMatch(value.screen_name, screenName)) { + return { + id: `twitter#channel:${key}`, + name: screenName, + url: `${location.origin}/${screenName}`, + imageURL: String(value.profile_image_url_https || '') + } + } + } + messages = ['Screen name not found in state'] + return null + } + + function getUserByScreenName() { + const store = findStore(document.getElementById('react-root')) + if (!store) { + messages = ['State store could not be found'] + return null + } + const state = store.getState() + try { + return getUserFromState(state, screenName) + } catch (e) { + console.error(e) + messages = ['Error attempting to get user state', state] + } + return null + } + + document.dispatchEvent(new CustomEvent(eventName, { + detail: { user: getUserByScreenName(), messages } + })) +} + +initializeDetector(() => { + async function getUserFromState(screenName: string) { + return new Promise((resolve) => { + const eventName = 'brave-rewards-user-data' + const listener = (event: CustomEvent) => { + document.removeEventListener(eventName, listener) + const { user, messages } = event.detail || {} + resolve(user || null) + if (Array.isArray(messages) && messages.length > 0) { + log.info(...messages) + } + } + document.addEventListener(eventName, listener) + const script = document.createElement('script') + script.textContent = `(${getUserFromAppState})( + ${JSON.stringify(eventName)}, + ${JSON.stringify(screenName)})` + document.head.appendChild(script) + document.head.removeChild(script) + }) + } + + function getScreenNameFromPath(path: string) { + let match = path.match(/^\/([^\/]+)(\/|\/status\/[\s\S]+)?$/) + if (match) { + log.info('Found screen name in path:', match[1]) + return match[1] + } + log.info('Screen name not found in path') + return null + } + + async function getUserFromPath(path: string) { + const screenName = getScreenNameFromPath(path) + if (screenName) { + const user = await getUserFromState(screenName) + if (user) { + return user + } + } + return null + } + + return async () => { + return await pollFor(() => getUserFromPath(location.pathname), { + name: 'creator', + interval: 1000, + timeout: 6000 + }) + } + +}) diff --git a/components/brave_rewards/resources/creator_detection/vimeo.ts b/components/brave_rewards/resources/creator_detection/vimeo.ts new file mode 100644 index 000000000000..358f9462b14b --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/vimeo.ts @@ -0,0 +1,120 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { initializeDetector } from './creator_detection' +import { log, pollFor, absoluteURL } from './helpers' + +initializeDetector(() => { + + function getIdFromPerson(person: any) { + if (!person) { + return '' + } + if (person.identifier) { + return String(person.identifier) + } + const { potentialAction } = person + if (!potentialAction) { + log.error('Missing "potentialAction" in Person') + return '' + } + const { target } = potentialAction + if (!target || typeof target !== 'string') { + log.error('Missing "potentialAction.target" in Person') + return '' + } + const match = target.match(/\/users\/([^\/]+)/i) + if (!match) { + log.error('Unable to read ID from Person') + return '' + } + return match[1] + } + + function getUserFromPerson(person: any) { + const id = getIdFromPerson(person) + if (!id) { + return null + } + return { + id: `vimeo#channel:${id}`, + name: String(person.name || ''), + url: absoluteURL(person.url || location.href), + imageURL: String(person.image || '') + } + } + + function getUserFromVideoData(video: any) { + if (!video) { + return null + } + const { author } = video + if (!author) { + log.error('Missing "author" in VideoObject') + return null + } + return getUserFromPerson(author) + } + + function getUserFromMetadata(json: string) { + let data: any + try { + data = JSON.parse(json) + } catch (err) { + log.error('Invalid JSON in metadata script') + return null + } + if (!Array.isArray(data)) { + log.error('Invalid metadata object: expected an array') + return null + } + for (const item of data) { + switch (item['@type']) { + case 'Person': { + const user = getUserFromPerson(item) + if (user) { + return user + } + } + case 'VideoObject': { + const user = getUserFromVideoData(item) + if (user) { + return user + } + } + } + } + log.info('Unable to find user in metadata scripts') + return null + } + + const metadataScriptSelector = 'script[type="application/ld+json"]' + + function parseMetadataScript() { + const elems = document.querySelectorAll(metadataScriptSelector) + for (const elem of elems) { + const user = getUserFromMetadata(elem.innerText) + if (user) { + return user + } + } + return null + } + + function hasMetadataScript() { + return Boolean(document.querySelector(metadataScriptSelector)) + } + + return async () => { + await pollFor(hasMetadataScript, { + name: 'metadata', + interval: 500, + timeout: 6000 + }) + + return parseMetadataScript() + } + +}) diff --git a/components/brave_rewards/resources/creator_detection/youtube.ts b/components/brave_rewards/resources/creator_detection/youtube.ts new file mode 100644 index 000000000000..a8f97894dd7a --- /dev/null +++ b/components/brave_rewards/resources/creator_detection/youtube.ts @@ -0,0 +1,238 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +import { initializeDetector } from './creator_detection' +import { log, pollFor, urlPath, absoluteURL } from './helpers' + +initializeDetector(() => { + + function getChannelFromURL(url: string) { + let pathname = urlPath(url) + let match = pathname.match(/^\/channel\/([^\/]+)/i) + if (match) { + return match[1] + } + return '' + } + + function getVideoIdFromURL(url: string) { + if (!urlPath(url).match(/^\/watch(\/|$)/i)) { + return '' + } + let params = null + try { + params = new URL(url).searchParams + } catch { + return '' + } + return params.get('v') || '' + } + + function getChannelNameFromURL(url: string) { + let pathname = urlPath(url) + let match = pathname.match(/^\/@([^\/]+)/) + if (match) { + return match[1] + } + return '' + } + + type PathType = 'channel' | 'channel-name' | 'video' | '' + + function getPathType(): PathType { + if (getChannelFromURL(location.href)) { + return 'channel' + } + if (getChannelNameFromURL(location.href)) { + return 'channel-name' + } + if (getVideoIdFromURL(location.href)) { + return 'video' + } + return '' + } + + let firstChannelScrape = true + let currentPathType: PathType = '' + + // Attempts to find the channel identifier by inspecting the URL and various + // DOM elements. + function scrapeChannel() { + let firstScrape = firstChannelScrape + firstChannelScrape = false + + let channel = getChannelFromURL(location.href) + if (channel) { + return channel + } + + let elem = document.querySelector('a[aria-label=About]') + if (elem) { + channel = getChannelFromURL(elem.href) + if (channel) { + return channel + } + } + + elem = document.querySelector('a.ytp-ce-channel-title') + if (elem) { + channel = getChannelFromURL(elem.href) + if (channel) { + return channel + } + } + + // On initial page load, a "canonical" link element that contains the + // channel identifier may be present on channel pages. On subsequent + // same-document navigations, this element will still exist but will no + // longer be valid. Only look for this element the first time we attempt to + // find the channel ID on the page (i.e. the initial page load). + if (firstScrape) { + let elem = document.querySelector('link[rel=canonical]') + if (elem) { + channel = getChannelFromURL(elem.href) + if (channel) { + return channel + } + } + } + + return '' + } + + function scrapeChannelName() { + let name = getChannelNameFromURL(location.href) + if (name) { + return name + } + + let elems = document.querySelectorAll([ + 'ytd-video-owner-renderer a', + 'ytm-slim-owner-renderer a' + ].join(',')) + + for (let elem of elems) { + name = getChannelNameFromURL(elem.href) + if (name) { + return name + } + } + + return '' + } + + function scrapeImage() { + let elems = document.querySelectorAll([ + '#avatar img', + 'yt-page-header-renderer yt-avatar-shape img', + 'ytm-slim-owner-renderer a img' + ].join(',')) + + for (let elem of elems) { + if (elem.src) { + return elem.src + } + } + + return '' + } + + function scrapeChannelURL() { + let name = scrapeChannelName() + if (name) { + return `${location.origin}/@${name}` + } + if (currentPathType === 'channel') { + return location.href + } + return '' + } + + async function getChannel() { + let channel = scrapeChannel() + if (channel) { + return channel + } + let name = scrapeChannelName() + if (name) { + let channelURL = `/@${name}` + log.info(`Fetching "${channelURL}" for channel ID detection`) + let response = await fetch(channelURL) + let responseText = response.ok ? await response.text() : '' + let match = responseText.match(/( + 'a.ytp-ce-channel-title' + ) + if (elem) { + return absoluteURL(elem.href) === location.href + } + return Boolean(document.querySelector('#page-header')) + } + + if (currentPathType === 'channel-name') { + let elem = document.querySelector( + 'ytd-video-owner-renderer a' + ) + if (elem && absoluteURL(elem.href) === location.href) { + return true + } + let form = document.querySelector('#form') + let name = getChannelNameFromURL(location.href) + return Boolean(form && urlPath(form.action).startsWith(`/@${name}`)) + } + + if (currentPathType === 'video') { + let id = getVideoIdFromURL(location.href) + let elem = document.querySelector('ytd-watch-metadata') + return Boolean(elem && elem.getAttribute('video-id') === id) + } + + return true + } + + return async () => { + currentPathType = getPathType() + log.info(`Current path type: ${currentPathType} (${location.pathname})`) + + await pollFor(isPageLoadComplete, { + name: 'load complete', + interval: 500, + timeout: 6000 + }) + + return await getUser() + } + +}) diff --git a/components/brave_rewards/test/BUILD.gn b/components/brave_rewards/test/BUILD.gn index 9c342cbf4fdb..6d06bf992c20 100644 --- a/components/brave_rewards/test/BUILD.gn +++ b/components/brave_rewards/test/BUILD.gn @@ -11,10 +11,10 @@ source_set("brave_rewards_unit_tests") { testonly = true sources = [ - "//brave/components/brave_rewards/browser/publisher_utils_unittest.cc", "//brave/components/brave_rewards/browser/rewards_protocol_navigation_throttle_unittest.cc", "//brave/components/brave_rewards/browser/rewards_service_impl_jp_unittest.cc", "//brave/components/brave_rewards/browser/rewards_service_impl_unittest.cc", + "//brave/components/brave_rewards/common/publisher_utils_unittest.cc", ] deps = [ @@ -28,7 +28,6 @@ source_set("brave_rewards_unit_tests") { "//brave/components/brave_rewards/core:publishers_proto", "//brave/components/brave_rewards/resources:static_resources_grit", "//brave/components/challenge_bypass_ristretto", - "//brave/components/greaselion/browser/buildflags:buildflags", "//brave/components/l10n/common:test_support", "//brave/third_party/rapidjson", "//chrome/browser:browser", diff --git a/components/brave_search_conversion/pref_names.h b/components/brave_search_conversion/pref_names.h index d1db191df841..64a750005943 100644 --- a/components/brave_search_conversion/pref_names.h +++ b/components/brave_search_conversion/pref_names.h @@ -27,6 +27,9 @@ inline constexpr char kLatestDDGBannerTypeFirstShownTime[] = inline constexpr char kShowNTPSearchBox[] = "brave.brave_search.show-ntp-search"; +inline constexpr char kLastUsedNTPSearchEngine[] = + "brave.brave_search.last-used-ntp-search-engine"; + // Determines whether the search box on the NTP prompts the user to enable // search suggestions. inline constexpr char kPromptEnableSuggestions[] = diff --git a/components/brave_search_conversion/utils.cc b/components/brave_search_conversion/utils.cc index 6bc42ab5fa18..59f285ba7cbc 100644 --- a/components/brave_search_conversion/utils.cc +++ b/components/brave_search_conversion/utils.cc @@ -171,6 +171,8 @@ ConversionType GetConversionType(PrefService* prefs, void RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref(prefs::kDismissed, false); registry->RegisterBooleanPref(prefs::kShowNTPSearchBox, true); + registry->RegisterStringPref(prefs::kLastUsedNTPSearchEngine, + "search.brave.com"); registry->RegisterBooleanPref(prefs::kPromptEnableSuggestions, true); registry->RegisterTimePref(prefs::kMaybeLaterClickedTime, base::Time()); registry->RegisterIntegerPref(prefs::kDDGBannerTypeIndex, 0); diff --git a/components/de_amp/browser/de_amp_body_handler.cc b/components/de_amp/browser/de_amp_body_handler.cc index 470f360c9b7d..b531ac10c4b2 100644 --- a/components/de_amp/browser/de_amp_body_handler.cc +++ b/components/de_amp/browser/de_amp_body_handler.cc @@ -156,7 +156,7 @@ bool DeAmpBodyHandler::IsTransformer() const { void DeAmpBodyHandler::DeAmpBodyHandler::Transform( std::string body, base::OnceCallback on_complete) { - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void DeAmpBodyHandler::UpdateResponseHead( diff --git a/components/definitions/chromel.d.ts b/components/definitions/chromel.d.ts index 2c57f6d4302b..9b388089b011 100644 --- a/components/definitions/chromel.d.ts +++ b/components/definitions/chromel.d.ts @@ -88,16 +88,11 @@ declare namespace chrome.braveRewards { const getUserType: (callback: (userType: string) => void) => void const getPublishersVisitedCount: (callback: (count: number) => void) => void const getRewardsParameters: (callback: (properties: RewardsExtension.RewardsParameters) => void) => {} - const updateMediaDuration: (tabId: number, publisherKey: string, duration: number, firstVisit: boolean) => {} const getPublisherInfo: (publisherKey: string, callback: (result: RewardsExtension.Result, properties: RewardsExtension.PublisherInfo) => void) => {} - const getPublisherPanelInfo: (publisherKey: string, callback: (result: RewardsExtension.Result, properties: RewardsExtension.PublisherInfo) => void) => {} - const setPublisherIdForTab: (tabId: number, publisherId: string) => void const getPublisherInfoForTab: (tabId: number, callback: (publisher?: RewardsExtension.PublisherInfo) => void) => void - const savePublisherInfo: (windowId: number, mediaType: string, url: string, publisherKey: string, publisherName: string, favIconUrl: string, callback: (result: RewardsExtension.Result) => void) => {} const tipSite: (tabId: number, publisherKey: string, entryPoint: RewardsExtension.TipDialogEntryPoint) => {} - const getPublisherData: (windowId: number, url: string, faviconUrl: string, publisherBlob: string | undefined) => {} const getBalanceReport: (month: number, year: number, callback: (properties: RewardsExtension.BalanceReport) => void) => {} const onPublisherData: { addListener: (callback: (windowId: number, publisher: RewardsExtension.Publisher) => void) => void diff --git a/components/definitions/newTab.d.ts b/components/definitions/newTab.d.ts index d68a6ab62f30..85a51e26196a 100644 --- a/components/definitions/newTab.d.ts +++ b/components/definitions/newTab.d.ts @@ -122,6 +122,7 @@ declare namespace NewTab { showRewards: boolean showBraveTalk: boolean showSearchBox: boolean + lastUsedNtpSearchEngine: string promptEnableSearchSuggestions: boolean searchSuggestionsEnabled: boolean hideAllWidgets: boolean diff --git a/components/ntp_background_images/browser/ntp_background_images_service.h b/components/ntp_background_images/browser/ntp_background_images_service.h index 6d1381aedaab..1eb0e1d22ec0 100644 --- a/components/ntp_background_images/browser/ntp_background_images_service.h +++ b/components/ntp_background_images/browser/ntp_background_images_service.h @@ -80,6 +80,8 @@ class NTPBackgroundImagesService { FRIEND_TEST_ALL_PREFIXES(NTPBackgroundImagesServiceTest, InternalDataTest); FRIEND_TEST_ALL_PREFIXES(NTPBackgroundImagesServiceTest, MultipleCampaignsTest); + FRIEND_TEST_ALL_PREFIXES(NTPBackgroundImagesServiceTest, + SponsoredImageWithMissingImageUrlTest); FRIEND_TEST_ALL_PREFIXES(NTPBackgroundImagesServiceTest, WithDefaultReferralCodeTest1); FRIEND_TEST_ALL_PREFIXES(NTPBackgroundImagesServiceTest, diff --git a/components/ntp_background_images/browser/ntp_background_images_service_unittest.cc b/components/ntp_background_images/browser/ntp_background_images_service_unittest.cc index 6a5c6049c87f..f8d54f9529f4 100644 --- a/components/ntp_background_images/browser/ntp_background_images_service_unittest.cc +++ b/components/ntp_background_images/browser/ntp_background_images_service_unittest.cc @@ -121,6 +121,34 @@ constexpr char kTestSponsoredImagesWithMultipleCampaigns[] = R"( ] })"; +constexpr char kTestSponsoredImagesWithMissingImageUrl[] = R"( + { + "schemaVersion": 1, + "campaignId": "fb7ee174-5430-4fb9-8e97-29bf14e8d828", + "logo": { + "imageUrl": "logo.png", + "alt": "Technikke: For music lovers", + "destinationUrl": "https://www.brave.com/", + "companyName": "Technikke" + }, + "wallpapers": [ + { + "missing_imageUrl": "background-1.jpg", + "focalPoint": { "x": 696, "y": 691 } + }, + { + "missing_imageUrl": "background-2.jpg", + "creativeInstanceId": "c0d61af3-3b85-4af4-a3cc-cf1b3dd40e70", + "logo": { + "imageUrl": "logo-2.png", + "alt": "logo2", + "companyName": "BAT", + "destinationUrl": "https://www.bat.com/" + } + } + ] + })"; + constexpr char kTestBackgroundImages[] = R"( { "schemaVersion": 1, @@ -460,6 +488,29 @@ TEST_F(NTPBackgroundImagesServiceTest, MultipleCampaignsTest) { service_->RemoveObserver(&observer); } +TEST_F(NTPBackgroundImagesServiceTest, SponsoredImageWithMissingImageUrlTest) { + Init(); + TestObserver observer; + service_->AddObserver(&observer); + + pref_service_.SetBoolean(kReferralCheckedForPromoCodeFile, true); + pref_service_.SetBoolean(kReferralInitialization, true); + + observer.si_data_ = nullptr; + service_->si_images_data_.reset(); + observer.on_si_updated_ = false; + service_->OnGetSponsoredComponentJsonData( + false, kTestSponsoredImagesWithMissingImageUrl); + // Mark this is not SR to get SI data. + service_->MarkThisInstallIsNotSuperReferralForever(); + + auto* si_data = service_->GetBrandedImagesData(false); + EXPECT_FALSE(si_data); + EXPECT_TRUE(observer.on_si_updated_); + EXPECT_TRUE(observer.si_data_->campaigns.empty()); + EXPECT_TRUE(service_->si_images_data_->campaigns.empty()); +} + #if BUILDFLAG(IS_LINUX) // Linux doesn't support referral service now. diff --git a/components/ntp_background_images/browser/ntp_sponsored_images_data.cc b/components/ntp_background_images/browser/ntp_sponsored_images_data.cc index e38b0b453b11..7e5d61912dbe 100644 --- a/components/ntp_background_images/browser/ntp_sponsored_images_data.cc +++ b/components/ntp_background_images/browser/ntp_sponsored_images_data.cc @@ -228,9 +228,13 @@ Campaign NTPSponsoredImagesData::GetCampaignFromValue( if (auto* wallpapers = value.FindList(kWallpapersKey)) { for (const auto& entry : *wallpapers) { const auto& wallpaper = entry.GetDict(); + const std::string* image_url = wallpaper.FindString(kImageURLKey); + if (!image_url) { + continue; + } + SponsoredBackground background; - background.image_file = - installed_dir.AppendASCII(*wallpaper.FindString(kImageURLKey)); + background.image_file = installed_dir.AppendASCII(*image_url); if (auto* focal_point = wallpaper.FindDict(kWallpaperFocalPointKey)) { background.focal_point = {focal_point->FindInt(kXKey).value_or(0), diff --git a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java index d341dcd24213..25827ee0e5c4 100644 --- a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java +++ b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java @@ -11,8 +11,8 @@ import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.safetynet.SafeBrowsingThreat; import com.google.android.gms.safetynet.SafetyNet; -import com.google.android.gms.safetynet.SafetyNetApi.SafeBrowsingResponse; import com.google.android.gms.safetynet.SafetyNetStatusCodes; import org.chromium.base.ContextUtils; @@ -21,6 +21,9 @@ import org.chromium.components.safe_browsing.BraveSafeBrowsingUtils.SafeBrowsingJavaThreatType; import org.chromium.components.safe_browsing.SafeBrowsingApiHandler.LookupResult; +import java.util.List; +import java.util.stream.Collectors; + /** * Brave implementation of SafeBrowsingApiHandler for Safe Browsing Under the bonnet it still uses * SafetyNet. @@ -120,18 +123,18 @@ public void startUriLookup(long callbackId, String uri, int[] threatTypes, int p DEFAULT_CHECK_DELTA); return; } else { - warnWhenMoreThanOneThreat(sbResponse); + List threats = + sbResponse.getDetectedThreats().stream() + .map(SafeBrowsingThreat::getThreatType) + .collect(Collectors.toList()); - // Response only with the first code mObserver.onUrlCheckDone( callbackId, LookupResult.SUCCESS, BraveSafeBrowsingUtils .safetyNetToSafeBrowsingJavaThreatType( - sbResponse - .getDetectedThreats() - .get(0) - .getThreatType()), + BraveSafeBrowsingUtils + .getHighestPriorityThreat(threats)), THREAT_ATTRIBUTES_STUB, SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, DEFAULT_CHECK_DELTA); @@ -201,18 +204,6 @@ public void startUriLookup(long callbackId, String uri, int[] threatTypes, int p }); } - private void warnWhenMoreThanOneThreat(SafeBrowsingResponse sbResponse) { - if (sbResponse.getDetectedThreats().size() != 1) { - Log.d(TAG, "Unexpected threats count: " + sbResponse.getDetectedThreats().size()); - String threats = ""; - for (int i = 0; i < sbResponse.getDetectedThreats().size(); i++) { - threats += sbResponse.getDetectedThreats().get(i).getThreatType(); - threats += " "; - } - Log.d(TAG, "Threats: [" + threats + "]"); - } - } - public void initSafeBrowsing() { SafetyNet.getClient(ContextUtils.getApplicationContext()).initSafeBrowsing(); mInitialized = true; diff --git a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java index e33357d54182..3327365f302a 100644 --- a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java +++ b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java @@ -6,6 +6,7 @@ package org.chromium.components.safe_browsing; import androidx.annotation.IntDef; +import androidx.annotation.VisibleForTesting; import org.chromium.base.Log; @@ -139,4 +140,35 @@ public static int safetyNetToSafeBrowsingJavaThreatType(int safetyNetThreatType) return SafeBrowsingJavaThreatType.NO_THREAT; } } + + // Priorities from most high to low + private static final int SAFETY_NET_THREAT_PRIORITIES[] = { + SafetyNetJavaThreatType.SOCIAL_ENGINEERING, + SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION, + SafetyNetJavaThreatType.BILLING, + SafetyNetJavaThreatType.UNWANTED_SOFTWARE, + SafetyNetJavaThreatType.SUBRESOURCE_FILTER, + SafetyNetJavaThreatType.CSD_ALLOWLIST, + SafetyNetJavaThreatType.MAX_VALUE + }; + + @VisibleForTesting + public static int getHighestPriorityThreat(List threats) { + if (threats.size() == 0) { + return SafetyNetJavaThreatType.MAX_VALUE; + } + + if (threats.size() == 1) { + return threats.get(0); + } + + for (int i = 0; i < SAFETY_NET_THREAT_PRIORITIES.length; ++i) { + if (threats.contains(SAFETY_NET_THREAT_PRIORITIES[i])) { + return SAFETY_NET_THREAT_PRIORITIES[i]; + } + } + + assert false : "Unexpected threat"; + return SafetyNetJavaThreatType.MAX_VALUE; + } } diff --git a/components/services/tor/BUILD.gn b/components/services/tor/BUILD.gn index b64456eb2e21..eccbb6863924 100644 --- a/components/services/tor/BUILD.gn +++ b/components/services/tor/BUILD.gn @@ -13,6 +13,7 @@ static_library("tor") { "public/interfaces", "//base", "//brave/components/child_process_monitor", + "//brave/components/tor:constants", "//mojo/public/cpp/bindings", ] } diff --git a/components/services/tor/public/interfaces/tor.mojom b/components/services/tor/public/interfaces/tor.mojom index 9c39afc66557..1c495f7a8a8a 100644 --- a/components/services/tor/public/interfaces/tor.mojom +++ b/components/services/tor/public/interfaces/tor.mojom @@ -3,14 +3,17 @@ // You can obtain one at http://mozilla.org/MPL/2.0/. module tor.mojom; -import "mojo/public/mojom/base/file_path.mojom"; +import "mojo/public/mojom/base/safe_base_name.mojom"; import "sandbox/policy/mojom/sandbox.mojom"; struct TorConfig { - mojo_base.mojom.FilePath binary_path; - mojo_base.mojom.FilePath torrc_path; - mojo_base.mojom.FilePath tor_data_path; - mojo_base.mojom.FilePath tor_watch_path; + // The install directory provided by the component updater for the Tor + // client. + mojo_base.mojom.SafeBaseName install_dir; + + // The filename for the tor executable. The executable is expected to be in + // the install directory. + mojo_base.mojom.SafeBaseName executable; }; [ServiceSandbox=sandbox.mojom.Sandbox.kNoSandbox] diff --git a/components/services/tor/tor_launcher_impl.cc b/components/services/tor/tor_launcher_impl.cc index c0a26ff50c6c..7b948a9561e1 100644 --- a/components/services/tor/tor_launcher_impl.cc +++ b/components/services/tor/tor_launcher_impl.cc @@ -11,10 +11,24 @@ #include "base/files/file_util.h" #include "base/process/launch.h" #include "base/strings/string_number_conversions.h" +#include "brave/components/tor/constants.h" #include "build/build_config.h" namespace tor { +namespace { + +// A utiltiy function to create the missing directories that are used by the +// launcher. +base::FilePath CreateIfNotExists(const base::FilePath& path) { + if (!base::DirectoryExists(path)) { + CHECK(base::CreateDirectory(path)); + } + return path; +} + +} // namespace + TorLauncherImpl::TorLauncherImpl( mojo::PendingReceiver receiver) : child_monitor_(std::make_unique()), @@ -53,32 +67,27 @@ void TorLauncherImpl::Launch(mojom::TorConfigPtr config, std::move(callback).Run(false, -1); return; } - base::CommandLine args(config->binary_path); + base::CommandLine args( + GetClientExecutablePath(config->install_dir, config->executable)); args.AppendArg("--ignore-missing-torrc"); + + auto torrc_path = GetTorRcPath(config->install_dir); args.AppendArg("-f"); - args.AppendArgPath(config->torrc_path); + args.AppendArgPath(torrc_path); args.AppendArg("--defaults-torrc"); - args.AppendArgPath(config->torrc_path); - base::FilePath tor_data_path = config->tor_data_path; - if (!tor_data_path.empty()) { - if (!base::DirectoryExists(tor_data_path)) - base::CreateDirectory(tor_data_path); - args.AppendArg("--DataDirectory"); - args.AppendArgPath(tor_data_path); - } + args.AppendArgPath(torrc_path); + + args.AppendArg("--DataDirectory"); + args.AppendArgPath(CreateIfNotExists(GetTorDataPath())); args.AppendArg("--__OwningControllerProcess"); args.AppendArg(base::NumberToString(base::Process::Current().Pid())); - tor_watch_path_ = config->tor_watch_path; - if (!tor_watch_path_.empty()) { - if (!base::DirectoryExists(tor_watch_path_)) - base::CreateDirectory(tor_watch_path_); - args.AppendArg("--pidfile"); - args.AppendArgPath(tor_watch_path_.AppendASCII("tor.pid")); - args.AppendArg("--controlportwritetofile"); - args.AppendArgPath(tor_watch_path_.AppendASCII("controlport")); - args.AppendArg("--cookieauthfile"); - args.AppendArgPath(tor_watch_path_.AppendASCII("control_auth_cookie")); - } + tor_watch_path_ = CreateIfNotExists(GetTorWatchPath()); + args.AppendArg("--pidfile"); + args.AppendArgPath(tor_watch_path_.AppendASCII("tor.pid")); + args.AppendArg("--controlportwritetofile"); + args.AppendArgPath(tor_watch_path_.AppendASCII("controlport")); + args.AppendArg("--cookieauthfile"); + args.AppendArgPath(tor_watch_path_.AppendASCII("control_auth_cookie")); base::LaunchOptions launchopts; #if BUILDFLAG(IS_LINUX) @@ -87,13 +96,14 @@ void TorLauncherImpl::Launch(mojom::TorConfigPtr config, #if BUILDFLAG(IS_WIN) launchopts.start_hidden = true; #endif - launchopts.current_directory = config->binary_path.DirName(); + // This line is necessary as the paths for tor_snowflake and tor_obfs4 are set + // up relative to this binary. + launchopts.current_directory = args.GetProgram().DirName(); base::Process tor_process = base::LaunchProcess(args, launchopts); - bool result = tor_process.IsValid(); - - if (callback) - std::move(callback).Run(result, tor_process.Pid()); + if (callback) { + std::move(callback).Run(tor_process.IsValid(), tor_process.Pid()); + } child_monitor_->Start(std::move(tor_process), base::BindOnce(&TorLauncherImpl::OnChildCrash, diff --git a/components/test/testData.ts b/components/test/testData.ts index 256ffa361fca..5e5dda32037e 100644 --- a/components/test/testData.ts +++ b/components/test/testData.ts @@ -59,9 +59,6 @@ export const getMockChrome = () => { let mock = { send: (methodName: string, ...args: any[]) => undefined, getVariableValue: () => undefined, - braveRewards: { - getPublisherData: (id: number, url: string, favicon: string) => undefined - }, runtime: { onMessage: new ChromeEvent(), onConnect: new ChromeEvent(), diff --git a/components/tor/BUILD.gn b/components/tor/BUILD.gn index 5738d8233e1c..e440b1f2f5bb 100644 --- a/components/tor/BUILD.gn +++ b/components/tor/BUILD.gn @@ -3,6 +3,18 @@ import("//chrome/common/features.gni") assert(enable_tor) +source_set("constants") { + sources = [ + "constants.cc", + "constants.h", + ] + + deps = [ + "//base", + "//components/component_updater:component_updater_paths", + ] +} + static_library("tor") { public_deps = [ ":common", @@ -45,6 +57,7 @@ static_library("tor") { ] deps += [ + ":constants", "//brave/components/brave_component_updater/browser", "//brave/components/resources:strings", "//brave/components/services/tor/public/interfaces", diff --git a/components/tor/brave_tor_client_updater.cc b/components/tor/brave_tor_client_updater.cc index f43bd6875495..11ec2e62e668 100644 --- a/components/tor/brave_tor_client_updater.cc +++ b/components/tor/brave_tor_client_updater.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/task/task_runner.h" #include "base/task/thread_pool.h" +#include "brave/components/tor/constants.h" #include "brave/components/tor/pref_names.h" #include "brave/components/tor/tor_switches.h" #include "build/build_config.h" @@ -28,10 +29,8 @@ namespace tor { namespace { -std::pair InitTorPath( - const base::FilePath& install_dir) { +base::FilePath InitTorPath(const base::FilePath& install_dir) { base::FilePath executable_path; - base::FilePath torrc_path; base::FileEnumerator traversal(install_dir, false, base::FileEnumerator::FILES, FILE_PATH_LITERAL("tor-*")); @@ -42,18 +41,17 @@ std::pair InitTorPath( file_info.GetName().MaybeAsASCII(), "tor-\\d+\\.\\d+\\.\\d+\\.\\d+-\\w+(-\\w+)?-brave-\\d+")) { executable_path = current; - } else if (file_info.GetName().MaybeAsASCII() == "tor-torrc") { - torrc_path = current; } - if (!executable_path.empty() && !torrc_path.empty()) + if (!executable_path.empty()) { break; + } } - if (executable_path.empty() || torrc_path.empty()) { - LOG(ERROR) << "Failed to locate Tor client executable or torrc in " + if (executable_path.empty()) { + LOG(ERROR) << "Failed to locate the Tor client executable in " << install_dir.value().c_str(); - return std::make_pair(base::FilePath(), base::FilePath()); + return {}; } #if BUILDFLAG(IS_POSIX) @@ -63,62 +61,15 @@ std::pair InitTorPath( if (!base::SetPosixFilePermissions(executable_path, 0755)) { LOG(ERROR) << "Failed to set executable permission on " << executable_path.value().c_str(); - return std::make_pair(base::FilePath(), base::FilePath()); + return {}; } #endif // BUILDFLAG(IS_POSIX) - return std::make_pair(executable_path, torrc_path); + return executable_path; } } // namespace -#if BUILDFLAG(IS_WIN) -constexpr char kTorClientComponentName[] = "Brave Tor Client Updater (Windows)"; -constexpr char kTorClientComponentId[] = "cpoalefficncklhjfpglfiplenlpccdb"; -constexpr char kTorClientComponentBase64PublicKey[] = - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1AYAsmR/VoRwkZCsjRpD" - "58xjrgngW5y17H6BqQ7/CeNSpmXlcMXy6bJs2D/yeS96rhZSrQSHTzS9h/ieo/NZ" - "F5PIwcv07YsG5sRd6zF5a6m92aWCQa1OkbL6jpcpL2Tbc4mCqNxhKMErT7EtIIWL" - "9cW+mtFUjUjvV3rJLQ3Vy9u6fEi77Y8b25kGnTJoVt3uETAIHBnyNpL7ac2f8Iq+" - "4Qa6VFmuoBhup54tTZvMv+ikoKKaQkHzkkjTa4hV5AzdnFDKO8C9qJb3T/Ef0+MO" - "IuZjyySVzGNcOfASeHkhxhlwMQSQuhCN5mdFW5YBnVZ/5QWx8WzbhqBny/ZynS4e" - "rQIDAQAB"; -#elif BUILDFLAG(IS_MAC) -constexpr char kTorClientComponentName[] = "Brave Tor Client Updater (Mac)"; -constexpr char kTorClientComponentId[] = "cldoidikboihgcjfkhdeidbpclkineef"; -constexpr char kTorClientComponentBase64PublicKey[] = - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2QUXSbVuRxYpItYApZ8" - "Ly/fGeUD3A+vb3J7Ot62CF32wTfWweANWyyB+EBGfbtNDAuRlAbNk0QYeCQEttuf" - "jLh3Kd5KR5fSyyNNd2cAzAckQ8p7JdiFYjvqZLGC5vlnHgqq4O8xACX5EPwHLNFD" - "iSpsthNmz3GCUrHrzPHjHVfy+IuucQXygnRv2fwIaAIxJmTbYm4fqsGKpfolWdMe" - "jKVAy1hc9mApZSyt4oGvUu4SJZnxlYMrY4Ze+OWbDesi2JGy+6dA1ddL9IdnwCb3" - "9CBOMNjaHeCVz0MKxdCWGPieQM0R7S1KvDCVqAkss6NAbLB6AVM0JulqxC9b+hr/" - "xwIDAQAB"; -#elif BUILDFLAG(IS_LINUX) -constexpr char kTorClientComponentName[] = "Brave Tor Client Updater (Linux)"; -#if defined(ARCH_CPU_ARM64) -constexpr char kTorClientComponentId[] = "monolafkoghdlanndjfeebmdfkbklejg"; -constexpr char kTorClientComponentBase64PublicKey[] = - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzqb14fggDpbjZtv3HKmR" - "UTnvfDTcqVbVZo0DdCHQi6SwxDlRweGwsvsHuy9U37VBr41ha/neemQGf+5qkWgY" - "y+mzzAkb5ZtrHkBSOOsZdyO9WEj7GwXuAx9FvcxG2zPpA/CvagnC14VhMyUFLL8v" - "XdfHYPmQOtIVdW3eR0G/4JP/mTbnAEkipQfxrDMtDVpX+FDB+Zy5yEMGKWHRLcdH" - "bHUgb/VhB9ppt0LKRjM44KSpyPDlYquXNcn3WFmxHoVm7PZ3LTAn3eSNZrT4ptmo" - "KveT4LgWtObrHoZtrg+/LnHAi1GYf8PHrRc+o/FptobOWoUN5lt8NvhLjv85ERBt" - "rQIDAQAB"; -#else -constexpr char kTorClientComponentId[] = "biahpgbdmdkfgndcmfiipgcebobojjkp"; -constexpr char kTorClientComponentBase64PublicKey[] = - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseuq8dXKawkZC7RSE7xb" - "lRwh6DD+oPEGEjZWKh596/42IrWNQw60gRIR6s7x0YHh5geFnBRkx9bisEXOrFkq" - "oArVY7eD0gMkjpor9CneD5CnCxc9/2uIPajtXfAmmLAHtN6Wk7yW30SkRf/WvLWX" - "/H+PqskQBN7I5MO7sveYxSrRMSj7prrFHEiFmXTgG/DwjpzrA7KV6vmzz/ReD51o" - "+UuLHE7cxPhnsNd/52uY3Lod3GhxvDoXKYx9kWlzBjxB53A2eLBCDIwwCpqS4/Ib" - "RSJhvF33KQT8YM+7V1MitwB49klP4aEWPXwOlFHmn9Dkmlx2RbO7S0tRcH9UH4LK" - "2QIDAQAB"; -#endif -#endif - BraveTorClientUpdater::BraveTorClientUpdater( BraveComponent::Delegate* component_delegate, PrefService* local_state, @@ -173,40 +124,19 @@ void BraveTorClientUpdater::RemoveObsoleteFiles() { task_runner_->PostTask(FROM_HERE, base::GetDeleteFileCallback(tor_log)); } -void BraveTorClientUpdater::SetTorPath( - const std::pair& paths) { - executable_path_ = paths.first; - torrc_path_ = paths.second; +void BraveTorClientUpdater::OnExecutablePathFound(base::FilePath path) { + executable_ = std::move(path); for (Observer& observer : observers_) - observer.OnExecutableReady(paths.second); -} - -base::FilePath BraveTorClientUpdater::GetExecutablePath() const { - return executable_path_; -} - -base::FilePath BraveTorClientUpdater::GetTorrcPath() const { - return torrc_path_; -} - -base::FilePath BraveTorClientUpdater::GetTorDataPath() const { - DCHECK(!user_data_dir_.empty()); - return user_data_dir_.Append(FILE_PATH_LITERAL("tor")) - .Append(FILE_PATH_LITERAL("data")); -} - -base::FilePath BraveTorClientUpdater::GetTorWatchPath() const { - DCHECK(!user_data_dir_.empty()); - return user_data_dir_.Append(FILE_PATH_LITERAL("tor")) - .Append(FILE_PATH_LITERAL("watch")); + observer.OnExecutableReady(executable_); } void BraveTorClientUpdater::OnComponentReady(const std::string& component_id, const base::FilePath& install_dir, const std::string& manifest) { + install_dir_ = install_dir; GetTaskRunner()->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&InitTorPath, install_dir), - base::BindOnce(&BraveTorClientUpdater::SetTorPath, + base::BindOnce(&BraveTorClientUpdater::OnExecutablePathFound, weak_ptr_factory_.GetWeakPtr())); } diff --git a/components/tor/brave_tor_client_updater.h b/components/tor/brave_tor_client_updater.h index 0d5f6c120d7d..58333b82950f 100644 --- a/components/tor/brave_tor_client_updater.h +++ b/components/tor/brave_tor_client_updater.h @@ -8,7 +8,6 @@ #include #include -#include #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" @@ -47,14 +46,13 @@ class BraveTorClientUpdater : public BraveComponent { void Register(); void Unregister(); void Cleanup(); - base::FilePath GetExecutablePath() const; - base::FilePath GetTorrcPath() const; - base::FilePath GetTorDataPath() const; - base::FilePath GetTorWatchPath() const; scoped_refptr GetTaskRunner() { return task_runner_; } + const base::FilePath& install_dir() const { return install_dir_; } + const base::FilePath& executable() const { return executable_; } + void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -67,13 +65,18 @@ class BraveTorClientUpdater : public BraveComponent { private: void RemoveObsoleteFiles(); - // - void SetTorPath(const std::pair&); + // Called with a response for the search for the executable path. + void OnExecutablePathFound(base::FilePath path); scoped_refptr task_runner_; bool registered_; - base::FilePath executable_path_; - base::FilePath torrc_path_; + + // The path where the binary has been ultimately installed. + base::FilePath install_dir_; + + // The path for the tor executable. + base::FilePath executable_; + base::ObserverList observers_; raw_ptr local_state_ = nullptr; base::FilePath user_data_dir_; diff --git a/components/tor/constants.cc b/components/tor/constants.cc new file mode 100644 index 000000000000..697078215bda --- /dev/null +++ b/components/tor/constants.cc @@ -0,0 +1,72 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/tor/constants.h" + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "build/build_config.h" +#include "components/component_updater/component_updater_paths.h" + +#if BUILDFLAG(IS_WIN) +#include "base/command_line.h" +#endif // BUILDFLAG(IS_WIN) + +namespace tor { + +namespace { + +// The filename for the tor client config file. +constexpr base::FilePath::StringPieceType kTorRcFilename = + FILE_PATH_LITERAL("tor-torrc"); + +base::FilePath GetUserDataDir() { +#if BUILDFLAG(IS_WIN) + // The switch used to set a custom user data dir. + constexpr char kUserDataDir[] = "user-data-dir"; + // It is not very clear why, but only on windows `PathService` user dir wasn't + // getting overridden when passing `kUserDataDir`, so we only check for the + // switch on Windows where the problem occurs. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + base::FilePath user_data_dir = command_line->GetSwitchValuePath(kUserDataDir); + if (!user_data_dir.empty()) { + return user_data_dir; + } +#endif // BUILDFLAG(IS_WIN) + return base::PathService::CheckedGet(component_updater::DIR_COMPONENT_USER); +} + +} // namespace + +base::FilePath GetTorClientDirectory() { + return GetUserDataDir().AppendASCII(kTorClientComponentId); +} + +base::FilePath GetClientExecutablePath(const base::SafeBaseName& install_dir, + const base::SafeBaseName& executable) { + return GetTorClientDirectory() + .Append(install_dir.path()) + .Append(executable.path()); +} + +base::FilePath GetTorRcPath(const base::SafeBaseName& install_dir) { + return GetTorClientDirectory() + .Append(install_dir.path()) + .Append(kTorRcFilename); +} + +base::FilePath GetTorDataPath() { + return GetUserDataDir() + .Append(FILE_PATH_LITERAL("tor")) + .Append(FILE_PATH_LITERAL("data")); +} + +base::FilePath GetTorWatchPath() { + return GetUserDataDir() + .Append(FILE_PATH_LITERAL("tor")) + .Append(FILE_PATH_LITERAL("watch")); +} + +} // namespace tor diff --git a/components/tor/constants.h b/components/tor/constants.h new file mode 100644 index 000000000000..43fc4d48046a --- /dev/null +++ b/components/tor/constants.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_TOR_CONSTANTS_H_ +#define BRAVE_COMPONENTS_TOR_CONSTANTS_H_ + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/files/safe_base_name.h" +#include "build/build_config.h" + +namespace tor { + +#if BUILDFLAG(IS_WIN) +inline constexpr char kTorClientComponentName[] = + "Brave Tor Client Updater (Windows)"; +inline constexpr char kTorClientComponentId[] = + "cpoalefficncklhjfpglfiplenlpccdb"; +inline constexpr char kTorClientComponentBase64PublicKey[] = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1AYAsmR/VoRwkZCsjRpD" + "58xjrgngW5y17H6BqQ7/CeNSpmXlcMXy6bJs2D/yeS96rhZSrQSHTzS9h/ieo/NZ" + "F5PIwcv07YsG5sRd6zF5a6m92aWCQa1OkbL6jpcpL2Tbc4mCqNxhKMErT7EtIIWL" + "9cW+mtFUjUjvV3rJLQ3Vy9u6fEi77Y8b25kGnTJoVt3uETAIHBnyNpL7ac2f8Iq+" + "4Qa6VFmuoBhup54tTZvMv+ikoKKaQkHzkkjTa4hV5AzdnFDKO8C9qJb3T/Ef0+MO" + "IuZjyySVzGNcOfASeHkhxhlwMQSQuhCN5mdFW5YBnVZ/5QWx8WzbhqBny/ZynS4e" + "rQIDAQAB"; +#elif BUILDFLAG(IS_MAC) +inline constexpr char kTorClientComponentName[] = + "Brave Tor Client Updater (Mac)"; +inline constexpr char kTorClientComponentId[] = + "cldoidikboihgcjfkhdeidbpclkineef"; +inline constexpr char kTorClientComponentBase64PublicKey[] = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2QUXSbVuRxYpItYApZ8" + "Ly/fGeUD3A+vb3J7Ot62CF32wTfWweANWyyB+EBGfbtNDAuRlAbNk0QYeCQEttuf" + "jLh3Kd5KR5fSyyNNd2cAzAckQ8p7JdiFYjvqZLGC5vlnHgqq4O8xACX5EPwHLNFD" + "iSpsthNmz3GCUrHrzPHjHVfy+IuucQXygnRv2fwIaAIxJmTbYm4fqsGKpfolWdMe" + "jKVAy1hc9mApZSyt4oGvUu4SJZnxlYMrY4Ze+OWbDesi2JGy+6dA1ddL9IdnwCb3" + "9CBOMNjaHeCVz0MKxdCWGPieQM0R7S1KvDCVqAkss6NAbLB6AVM0JulqxC9b+hr/" + "xwIDAQAB"; +#elif BUILDFLAG(IS_LINUX) +inline constexpr char kTorClientComponentName[] = + "Brave Tor Client Updater (Linux)"; +#if defined(ARCH_CPU_ARM64) +inline constexpr char kTorClientComponentId[] = + "monolafkoghdlanndjfeebmdfkbklejg"; +inline constexpr char kTorClientComponentBase64PublicKey[] = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzqb14fggDpbjZtv3HKmR" + "UTnvfDTcqVbVZo0DdCHQi6SwxDlRweGwsvsHuy9U37VBr41ha/neemQGf+5qkWgY" + "y+mzzAkb5ZtrHkBSOOsZdyO9WEj7GwXuAx9FvcxG2zPpA/CvagnC14VhMyUFLL8v" + "XdfHYPmQOtIVdW3eR0G/4JP/mTbnAEkipQfxrDMtDVpX+FDB+Zy5yEMGKWHRLcdH" + "bHUgb/VhB9ppt0LKRjM44KSpyPDlYquXNcn3WFmxHoVm7PZ3LTAn3eSNZrT4ptmo" + "KveT4LgWtObrHoZtrg+/LnHAi1GYf8PHrRc+o/FptobOWoUN5lt8NvhLjv85ERBt" + "rQIDAQAB"; +#else // #if defined(ARCH_CPU_ARM64) +inline constexpr char kTorClientComponentId[] = + "biahpgbdmdkfgndcmfiipgcebobojjkp"; +inline constexpr char kTorClientComponentBase64PublicKey[] = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseuq8dXKawkZC7RSE7xb" + "lRwh6DD+oPEGEjZWKh596/42IrWNQw60gRIR6s7x0YHh5geFnBRkx9bisEXOrFkq" + "oArVY7eD0gMkjpor9CneD5CnCxc9/2uIPajtXfAmmLAHtN6Wk7yW30SkRf/WvLWX" + "/H+PqskQBN7I5MO7sveYxSrRMSj7prrFHEiFmXTgG/DwjpzrA7KV6vmzz/ReD51o" + "+UuLHE7cxPhnsNd/52uY3Lod3GhxvDoXKYx9kWlzBjxB53A2eLBCDIwwCpqS4/Ib" + "RSJhvF33KQT8YM+7V1MitwB49klP4aEWPXwOlFHmn9Dkmlx2RbO7S0tRcH9UH4LK" + "2QIDAQAB"; +#endif +#endif + +// Returns the path for for where the Tor client binary is installed. +base::FilePath GetTorClientDirectory(); + +// Returns the path client execution path, based on the installation path for +// components, the `install_dir` provided, and the `filename`. +base::FilePath GetClientExecutablePath(const base::SafeBaseName& install_dir, + const base::SafeBaseName& executable); + +// Returns the path for the torrc file, based on the installation path for +// components, and the `install_dir` provided. +base::FilePath GetTorRcPath(const base::SafeBaseName& install_dir); + +// Returns the path for the client's `--DataDirectory` argument. +base::FilePath GetTorDataPath(); + +// Return the directory path for the watcher arguments passed to the client. +base::FilePath GetTorWatchPath(); + +} // namespace tor + +#endif // BRAVE_COMPONENTS_TOR_CONSTANTS_H_ diff --git a/components/tor/tor_launcher_factory.cc b/components/tor/tor_launcher_factory.cc index 2ddb71248c8f..e225c36fce47 100644 --- a/components/tor/tor_launcher_factory.cc +++ b/components/tor/tor_launcher_factory.cc @@ -13,6 +13,7 @@ #include "base/no_destructor.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" +#include "brave/components/tor/constants.h" #include "brave/components/tor/tor_file_watcher.h" #include "brave/components/tor/tor_launcher_observer.h" #include "brave/components/tor/tor_utils.h" @@ -66,6 +67,7 @@ TorLauncherFactory::TorLauncherFactory() : is_starting_(false), is_connected_(false), tor_pid_(-1), + tor_watch_path_(tor::GetTorWatchPath()), control_(nullptr, base::OnTaskRunnerDeleter(content::GetIOThreadTaskRunner({}))) { control_.reset(new tor::TorControl(this->AsWeakPtr(), @@ -108,10 +110,8 @@ void TorLauncherFactory::LaunchTorProcess(const tor::mojom::TorConfig& config) { return; } - DCHECK(!config.binary_path.empty()); - DCHECK(!config.torrc_path.empty()); - DCHECK(!config.tor_data_path.empty()); - DCHECK(!config.tor_watch_path.empty()); + DCHECK(!config.executable.path().empty()); + DCHECK(!config.install_dir.path().empty()); config_ = config; // Tor launcher could be null if we created Tor process and killed it @@ -252,7 +252,7 @@ void TorLauncherFactory::OnTorLaunched(bool result, int64_t pid) { } tor::TorFileWatcher* tor_file_watcher = - new tor::TorFileWatcher(config_.tor_watch_path); + new tor::TorFileWatcher(tor_watch_path_); tor_file_watcher->StartWatching(base::BindPostTask( base::SequencedTaskRunner::GetCurrentDefault(), base::BindOnce(&TorLauncherFactory::OnTorControlPrerequisitesReady, @@ -349,7 +349,7 @@ void TorLauncherFactory::OnTorControlClosed(bool was_running) { // closed unexpectedly and Tor process is still running if (was_running && tor_launcher_.is_bound()) { tor::TorFileWatcher* tor_file_watcher = - new tor::TorFileWatcher(config_.tor_watch_path); + new tor::TorFileWatcher(tor_watch_path_); tor_file_watcher->StartWatching(base::BindPostTask( base::SequencedTaskRunner::GetCurrentDefault(), base::BindOnce(&TorLauncherFactory::OnTorControlPrerequisitesReady, @@ -371,7 +371,7 @@ void TorLauncherFactory::OnTorControlPrerequisitesReady( control_->Start(std::move(cookie), port); } else { tor::TorFileWatcher* tor_file_watcher = - new tor::TorFileWatcher(config_.tor_watch_path); + new tor::TorFileWatcher(tor_watch_path_); tor_file_watcher->StartWatching(base::BindPostTask( base::SequencedTaskRunner::GetCurrentDefault(), base::BindOnce(&TorLauncherFactory::OnTorControlPrerequisitesReady, diff --git a/components/tor/tor_launcher_factory.h b/components/tor/tor_launcher_factory.h index f81b056e2014..debab566d0fa 100644 --- a/components/tor/tor_launcher_factory.h +++ b/components/tor/tor_launcher_factory.h @@ -107,6 +107,8 @@ class TorLauncherFactory : public tor::TorControl::Delegate { int64_t tor_pid_; tor::mojom::TorConfig config_; + // The watch path from the tor client. This value is static for the user. + const base::FilePath tor_watch_path_; base::ObserverList observers_; diff --git a/components/tor/tor_profile_service_impl.cc b/components/tor/tor_profile_service_impl.cc index c0f7c46e747f..a5472bb38a14 100644 --- a/components/tor/tor_profile_service_impl.cc +++ b/components/tor/tor_profile_service_impl.cc @@ -285,7 +285,7 @@ void TorProfileServiceImpl::OnPluggableTransportReady(bool success) { DCHECK(base::PathExists(tor_path.Append(snowflake_path))); DCHECK(base::PathExists(tor_path.Append(obfs4_path))); }, - GetTorExecutablePath(), snowflake_path, obfs4_path)); + tor_client_updater_->executable(), snowflake_path, obfs4_path)); #endif OnBridgesConfigChanged(); @@ -331,29 +331,16 @@ void TorProfileServiceImpl::OnBuiltinBridgesResponse( } void TorProfileServiceImpl::LaunchTor() { - tor::mojom::TorConfig config(GetTorExecutablePath(), GetTorrcPath(), - GetTorDataPath(), GetTorWatchPath()); - tor_launcher_factory_->LaunchTorProcess(config); -} - -base::FilePath TorProfileServiceImpl::GetTorExecutablePath() const { - return tor_client_updater_ ? tor_client_updater_->GetExecutablePath() - : base::FilePath(); -} + auto install_dir = + base::SafeBaseName::Create(tor_client_updater_->install_dir()); + CHECK(install_dir) << tor_client_updater_->install_dir(); -base::FilePath TorProfileServiceImpl::GetTorrcPath() const { - return tor_client_updater_ ? tor_client_updater_->GetTorrcPath() - : base::FilePath(); -} - -base::FilePath TorProfileServiceImpl::GetTorDataPath() const { - return tor_client_updater_ ? tor_client_updater_->GetTorDataPath() - : base::FilePath(); -} + auto executable = + base::SafeBaseName::Create(tor_client_updater_->executable()); + CHECK(executable) << tor_client_updater_->executable(); -base::FilePath TorProfileServiceImpl::GetTorWatchPath() const { - return tor_client_updater_ ? tor_client_updater_->GetTorWatchPath() - : base::FilePath(); + tor_launcher_factory_->LaunchTorProcess(tor::mojom::TorConfig( + std::move(install_dir).value(), std::move(executable).value())); } void TorProfileServiceImpl::RegisterTorClientUpdater() { diff --git a/components/tor/tor_profile_service_impl.h b/components/tor/tor_profile_service_impl.h index 7bdf308f5b30..4112b98c4296 100644 --- a/components/tor/tor_profile_service_impl.h +++ b/components/tor/tor_profile_service_impl.h @@ -66,11 +66,6 @@ class TorProfileServiceImpl private: void LaunchTor(); - base::FilePath GetTorExecutablePath() const; - base::FilePath GetTorrcPath() const; - base::FilePath GetTorDataPath() const; - base::FilePath GetTorWatchPath() const; - // BraveTorClientUpdater::Observer void OnExecutableReady(const base::FilePath& path) override; diff --git a/ios/brave-ios/Sources/AIChat/Components/Settings/AIChatMenuView.swift b/ios/brave-ios/Sources/AIChat/Components/Settings/AIChatMenuView.swift index cec2fab12c3f..fb82404b85d3 100644 --- a/ios/brave-ios/Sources/AIChat/Components/Settings/AIChatMenuView.swift +++ b/ios/brave-ios/Sources/AIChat/Components/Settings/AIChatMenuView.swift @@ -123,7 +123,7 @@ struct AIChatMenuView: View { } var body: some View { - LazyVStack(spacing: 0.0) { + VStack(spacing: 0.0) { Text(Strings.AIChat.defaultModelLanguageSectionTitle) .font(.caption2.weight(.semibold)) .foregroundStyle(Color(braveSystemName: .textPrimary)) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Menu.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Menu.swift index 3cb6dc61aae6..ca34d21abfc4 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Menu.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Menu.swift @@ -4,6 +4,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. import BraveCore +import BraveShared import BraveUI import BraveVPN import BraveWallet @@ -410,8 +411,9 @@ extension BrowserViewController { .lineLimit(1) .foregroundColor(Color(.braveLabel)) } - Text( - verbatim: URLFormatter.formatURLOrigin( + + URLElidedText( + text: URLFormatter.formatURLOrigin( forDisplayOmitSchemePathAndTrivialSubdomains: url.absoluteString ) ) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageFlowLayout.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageFlowLayout.swift index d6d0cdcdbfbe..50c1434dede7 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageFlowLayout.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageFlowLayout.swift @@ -64,6 +64,9 @@ class NewTabPageFlowLayout: UICollectionViewFlowLayout { lastSizedElementMinY = nil lastSizedElementPreferredHeight = nil + } else { + gapLength = 0 + extraHeight = 0 } } diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageViewController.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageViewController.swift index 43ec986d3439..d89a05943a0b 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageViewController.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/New Tab Page/NewTabPageViewController.swift @@ -772,26 +772,9 @@ class NewTabPageViewController: UIViewController { collectionView.deleteItems(at: [IndexPath(item: 0, section: section)]) } - // We check if first item exists before scrolling up to it. - // This should never happen since first item is our shields stats view. - // However we saw it crashing in XCode logs, see #4202. - let firstItemIndexPath = IndexPath(item: 0, section: 0) - if let itemCount = collectionView.dataSource?.collectionView( - collectionView, - numberOfItemsInSection: 0 - ), - itemCount > 0, // Only scroll if the section has items, otherwise it will crash. - collectionView.dataSource? - .collectionView(collectionView, cellForItemAt: firstItemIndexPath) != nil - { - collectionView.scrollToItem(at: firstItemIndexPath, at: .top, animated: true) - } else { - // Cannot scorll to deleted item index. - // Collection-View datasource never changes or updates - // Therefore we need to scroll to offset 0. - // See: #4575. - collectionView.setContentOffset(.zero, animated: true) - } + // scroll to offset .zero to preserve padding above section + collectionView.setContentOffset(.zero, animated: true) + backgroundButtonsView.setNeedsLayout() collectionView.verticalScrollIndicatorInsets = .zero UIView.animate(withDuration: 0.25) { self.feedOverlayView.headerView.alpha = 0.0 diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/TabManager.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/TabManager.swift index 61eed9dc868f..335491210a96 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/TabManager.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/TabManager.swift @@ -1665,15 +1665,32 @@ extension WKWebsiteDataStore { @MainActor fileprivate func deleteDataRecords(forDomains domains: Set) async { let records = await dataRecords( - ofTypes: WKWebsiteDataStore.allWebsiteDataTypes() + ofTypes: WKWebsiteDataStore.allWebsiteDataTypesIncludingPrivate() ) let websiteRecords = records.filter { record in domains.contains(record.displayName) } await removeData( - ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), + ofTypes: WKWebsiteDataStore.allWebsiteDataTypesIncludingPrivate(), for: websiteRecords ) } + + /// This includes all public types from `WKWebsiteDataStore.allWebsiteDataTypes` as well as private data types. + public static func allWebsiteDataTypesIncludingPrivate() -> Set { + // https://github.com/WebKit/WebKit/blob/b66e4895df40202b14bb20fb47444c3e0a3c164e/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h + var types = WKWebsiteDataStore.allWebsiteDataTypes() + types.insert("_WKWebsiteDataTypeHSTSCache") + types.insert("_WKWebsiteDataTypeResourceLoadStatistics") + types.insert("_WKWebsiteDataTypeCredentials") + types.insert("_WKWebsiteDataTypeAdClickAttributions") + types.insert("_WKWebsiteDataTypePrivateClickMeasurements") + types.insert("_WKWebsiteDataTypeAlternativeServices") + if #unavailable(iOS 17) { + types.insert("_WKWebsiteDataTypeMediaKeys") + types.insert("_WKWebsiteDataTypeSearchFieldRecentSearches") + } + return types + } } diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarkDetailsView.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarkDetailsView.swift index 1cf579f5ef86..4a20205afe4d 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarkDetailsView.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarkDetailsView.swift @@ -21,6 +21,7 @@ private class URLTextField: UITextField { defaultTextAttributes[.paragraphStyle, default: NSParagraphStyle()] as! NSParagraphStyle let style = oldStyle.mutableCopy() as! NSMutableParagraphStyle style.lineBreakMode = .byTruncatingHead + style.baseWritingDirection = .leftToRight defaultTextAttributes[.paragraphStyle] = style self.addTarget(self, action: #selector(didBeginEditing), for: .editingDidBegin) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/History/HistoryView.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/History/HistoryView.swift index 0a4b1e909a9d..9b002b718173 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/History/HistoryView.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/History/HistoryView.swift @@ -4,10 +4,12 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. import BraveCore +import BraveShared import BraveStrings import DesignSystem import Favicon import Preferences +import Shared import SwiftUI struct HistoryItemView: View { @@ -37,15 +39,18 @@ struct HistoryItemView: View { .foregroundStyle(Color(braveSystemName: .textPrimary)) } - Text( - URLFormatter.formatURLOrigin( + URLElidedText( + text: URLFormatter.formatURLOrigin( forDisplayOmitSchemePathAndTrivialSubdomains: url.absoluteString ) ) + .truncationMode(.tail) .font(.footnote) .frame(maxWidth: .infinity, alignment: .leading) .fixedSize(horizontal: false, vertical: true) .foregroundStyle(Color(braveSystemName: .textSecondary)) + .environment(\.layoutDirection, .leftToRight) + .flipsForRightToLeftLayoutDirection(false) } } } diff --git a/ios/brave-ios/Sources/Brave/Frontend/Shields/ShieldsPanelView.swift b/ios/brave-ios/Sources/Brave/Frontend/Shields/ShieldsPanelView.swift index 0cdf3ca85553..83faf1088c20 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Shields/ShieldsPanelView.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Shields/ShieldsPanelView.swift @@ -4,6 +4,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. import BraveCore +import BraveShared import BraveShields import BraveUI import Data @@ -35,9 +36,8 @@ struct ShieldsPanelView: View { self.url = url self.viewModel = ShieldsSettingsViewModel(tab: tab, domain: domain) self.actionCallback = callback - self.displayHost = URLFormatter.formatURLOrigin( - forDisplayOmitSchemePathAndTrivialSubdomains: url.absoluteString - ) + self.displayHost = + "\u{200E}\(URLFormatter.formatURLOrigin(forDisplayOmitSchemePathAndTrivialSubdomains: url.absoluteString))" } private var shieldsEnabledAccessibiltyLabel: String { @@ -82,7 +82,7 @@ struct ShieldsPanelView: View { url: url.absoluteString, isPrivateBrowsing: viewModel.isPrivateBrowsing ) - Text(displayHost) + URLElidedText(text: displayHost) .font(.title2) .foregroundStyle(Color(.bravePrimary)) } @@ -187,7 +187,9 @@ struct ShieldsPanelView: View { } @ViewBuilder private var shieldSettingsSectionView: some View { - ShieldSettingSectionHeader(title: displayHost) + ShieldSettingSectionHeader( + title: displayHost + ) ShieldSettingRow { HStack { Text(Strings.Shields.trackersAndAdsBlocking) @@ -309,7 +311,7 @@ private struct ShieldSettingSectionHeader: View { var body: some View { VStack(alignment: .leading, spacing: 8) { - Text(title) + URLElidedText(text: title) .font(.footnote) .foregroundStyle(Color(.secondaryBraveLabel)) .textCase(.uppercase) diff --git a/ios/brave-ios/Sources/BraveShared/URLElidedTextView.swift b/ios/brave-ios/Sources/BraveShared/URLElidedTextView.swift new file mode 100644 index 000000000000..e84f543012cb --- /dev/null +++ b/ios/brave-ios/Sources/BraveShared/URLElidedTextView.swift @@ -0,0 +1,41 @@ +// Copyright 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import BraveCore +import SwiftUI +import UIKit + +public struct URLElidedText: View { + public var text: String + + @Environment(\.font) + private var font: Font? + + @Environment(\.truncationMode) + private var truncationMode: Text.TruncationMode + + private var paragraphStyle: NSParagraphStyle { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineBreakMode = + truncationMode == .head + ? .byTruncatingHead : truncationMode == .middle ? .byTruncatingMiddle : .byTruncatingTail + paragraphStyle.baseWritingDirection = .leftToRight + return paragraphStyle + } + + public init(text: String) { + self.text = text + } + + public var body: some View { + // LRM character prevents Text elements from rendering RTL special characters + Text( + AttributedString( + "\u{200E}\(text)", + attributes: .init([.font: font ?? .body, .paragraphStyle: paragraphStyle]) + ) + ) + } +} diff --git a/ios/browser/api/bookmarks/bookmark_model_listener_ios.mm b/ios/browser/api/bookmarks/bookmark_model_listener_ios.mm index 5ac9b38edd8e..78441174ab0c 100644 --- a/ios/browser/api/bookmarks/bookmark_model_listener_ios.mm +++ b/ios/browser/api/bookmarks/bookmark_model_listener_ios.mm @@ -49,7 +49,7 @@ - (instancetype)initWithNode:(const bookmarks::BookmarkNode*)node void BookmarkModelListener::BookmarkModelBeingDeleted() { // This is an inconsistent state in the application lifecycle. The bookmark // model shouldn't disappear. - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } void BookmarkModelListener::BookmarkNodeMoved( diff --git a/ios/browser/api/bookmarks/exporter/bookmark_html_writer.cc b/ios/browser/api/bookmarks/exporter/bookmark_html_writer.cc index 171ddf768b93..3b39fdd02a38 100644 --- a/ios/browser/api/bookmarks/exporter/bookmark_html_writer.cc +++ b/ios/browser/api/bookmarks/exporter/bookmark_html_writer.cc @@ -302,7 +302,7 @@ class Writer : public base::RefCountedThreadSafe { break; default: - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } return Write(utf8_string); @@ -327,20 +327,14 @@ class Writer : public base::RefCountedThreadSafe { const std::string* date_added_string = value.FindString(BookmarkCodec::kDateAddedKey); const std::string* type_string = value.FindString(BookmarkCodec::kTypeKey); - if (!title_ptr || !date_added_string || !type_string || - (*type_string != BookmarkCodec::kTypeURL && - *type_string != BookmarkCodec::kTypeFolder)) { - NOTREACHED_IN_MIGRATION(); - return false; - } + CHECK(title_ptr && date_added_string && type_string && + (*type_string == BookmarkCodec::kTypeURL || + *type_string == BookmarkCodec::kTypeFolder)); std::string title = *title_ptr; if (*type_string == BookmarkCodec::kTypeURL) { const std::string* url_string = value.FindString(BookmarkCodec::kURLKey); - if (!url_string) { - NOTREACHED_IN_MIGRATION(); - return false; - } + CHECK(url_string); std::string favicon_string; auto itr = favicons_map_->find(*url_string); @@ -368,10 +362,7 @@ class Writer : public base::RefCountedThreadSafe { value.FindString(BookmarkCodec::kDateModifiedKey); const base::Value::List* child_values = value.FindList(BookmarkCodec::kChildrenKey); - if (!last_modified_date || !child_values) { - NOTREACHED_IN_MIGRATION(); - return false; - } + CHECK(last_modified_date && child_values); if (folder_type != BookmarkNode::OTHER_NODE && folder_type != BookmarkNode::MOBILE) { // The other/mobile folder name are not written out. This gives the effect @@ -398,10 +389,7 @@ class Writer : public base::RefCountedThreadSafe { // Write the children. for (const base::Value& child_value : *child_values) { - if (!child_value.is_dict()) { - NOTREACHED_IN_MIGRATION(); - return false; - } + CHECK(child_value.is_dict()); if (!WriteNode(child_value.GetDict(), BookmarkNode::FOLDER)) { return false; } diff --git a/ios/browser/api/bookmarks/exporter/brave_bookmarks_exporter.mm b/ios/browser/api/bookmarks/exporter/brave_bookmarks_exporter.mm index a9df300bffdf..2a58ff6b72da 100644 --- a/ios/browser/api/bookmarks/exporter/brave_bookmarks_exporter.mm +++ b/ios/browser/api/bookmarks/exporter/brave_bookmarks_exporter.mm @@ -56,15 +56,20 @@ void BraveBookmarksExportObserver::OnExportFinished(Result result) { switch (result) { case Result::kSuccess: - return _on_export_finished(BraveBookmarksExporterStateCompleted); + _on_export_finished(BraveBookmarksExporterStateCompleted); + break; case Result::kCouldNotCreateFile: - return _on_export_finished(BraveBookmarksExporterStateErrorCreatingFile); + _on_export_finished(BraveBookmarksExporterStateErrorCreatingFile); + break; case Result::kCouldNotWriteHeader: - return _on_export_finished(BraveBookmarksExporterStateErrorWritingHeader); + _on_export_finished(BraveBookmarksExporterStateErrorWritingHeader); + break; case Result::kCouldNotWriteNodes: - return _on_export_finished(BraveBookmarksExporterStateErrorWritingNodes); + _on_export_finished(BraveBookmarksExporterStateErrorWritingNodes); + break; default: - NOTREACHED_IN_MIGRATION(); + delete this; + NOTREACHED(); } delete this; } diff --git a/ios/browser/api/bookmarks/importer/bookmark_html_reader.cc b/ios/browser/api/bookmarks/importer/bookmark_html_reader.cc index 846e921ce752..3a21aaef77a2 100644 --- a/ios/browser/api/bookmarks/importer/bookmark_html_reader.cc +++ b/ios/browser/api/bookmarks/importer/bookmark_html_reader.cc @@ -187,10 +187,8 @@ void ImportBookmarksFile( if (is_bookmark && post_data.empty() && (valid_url_callback.is_null() || valid_url_callback.Run(url))) { - if (toolbar_folder_index > path.size() && !path.empty()) { - NOTREACHED_IN_MIGRATION(); // error in parsing. - break; - } + CHECK(toolbar_folder_index <= path.size() || + path.empty()); // error in parsing. ImportedBookmarkEntry entry; entry.creation_time = add_date; diff --git a/ios/browser/api/bookmarks/importer/bookmarks_importer.mm b/ios/browser/api/bookmarks/importer/bookmarks_importer.mm index 485a4149fd71..9f7a528d3f7a 100644 --- a/ios/browser/api/bookmarks/importer/bookmarks_importer.mm +++ b/ios/browser/api/bookmarks/importer/bookmarks_importer.mm @@ -49,19 +49,20 @@ } // If the given name is unique, use it. - if (existing_folder_names.find(folder_name) == existing_folder_names.end()) + if (existing_folder_names.find(folder_name) == existing_folder_names.end()) { return folder_name; + } // Otherwise iterate until we find a unique name. for (size_t i = 1; i <= existing_folder_names.size(); ++i) { std::u16string name = folder_name + u" (" + base::NumberToString16(i) + u")"; - if (existing_folder_names.find(name) == existing_folder_names.end()) + if (existing_folder_names.find(name) == existing_folder_names.end()) { return name; + } } - NOTREACHED_IN_MIGRATION(); - return folder_name; + NOTREACHED(); } // Shows the bookmarks toolbar. diff --git a/ios/browser/api/web/ui/chrome_webview.mm b/ios/browser/api/web/ui/chrome_webview.mm index 4c984aae35e3..7853fdd50ea3 100644 --- a/ios/browser/api/web/ui/chrome_webview.mm +++ b/ios/browser/api/web/ui/chrome_webview.mm @@ -266,7 +266,7 @@ - (void)webStateDestroyed:(web::WebState*)webState { // The WebState is owned by the current instance, and the observer bridge // is unregistered before the WebState is destroyed, so this event should // never happen. - NOTREACHED_IN_MIGRATION(); + NOTREACHED(); } // MARK: - CRWWebStateDelegate implementation diff --git a/ios/browser/favicon/brave_ios_web_favicon_driver.mm b/ios/browser/favicon/brave_ios_web_favicon_driver.mm index 9be4fed6f6ff..22078a33711c 100644 --- a/ios/browser/favicon/brave_ios_web_favicon_driver.mm +++ b/ios/browser/favicon/brave_ios_web_favicon_driver.mm @@ -61,7 +61,8 @@ void BraveIOSWebFaviconDriver::DownloadManifest( const GURL& url, ManifestDownloadCallback callback) { - NOTREACHED_IN_MIGRATION(); + // We don't support downloading manifests + NOTREACHED(); } bool BraveIOSWebFaviconDriver::IsOffTheRecord() { diff --git a/package-lock.json b/package-lock.json index 31716de1c0f7..67d016526cb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "brave-core", - "version": "1.73.46", + "version": "1.73.50", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "brave-core", - "version": "1.73.46", + "version": "1.73.50", "license": "MPL-2.0", "dependencies": { "@brave/brave-ui": "0.40.6", diff --git a/package.json b/package.json index d6c3e64290e0..5d7bb9d51707 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "brave-core", - "version": "1.73.46", + "version": "1.73.50", "description": "Brave Core is a set of changes, APIs and scripts used for customizing Chromium to make Brave.", "main": "index.js", "scripts": { @@ -227,4 +227,4 @@ "elliptic": "6.5.7", "send": "0.19.0" } -} \ No newline at end of file +} diff --git a/resources/resource_ids.spec b/resources/resource_ids.spec index 05eef4c1d235..cb319d1c0278 100644 --- a/resources/resource_ids.spec +++ b/resources/resource_ids.spec @@ -221,4 +221,8 @@ "META": {"sizes": {"includes": [50]}}, "includes": [64650], }, + "<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-creator_detection/creator_detection.grd": { + "META": {"sizes": {"includes": [10]}}, + "includes": [64700], + }, } diff --git a/snapcraft.yaml b/snapcraft.yaml index 3677b7a7120e..2b871720ee73 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -1,5 +1,5 @@ name: brave -version: 1.73.46 +version: 1.73.50 grade: stable architectures: - build-on: amd64 diff --git a/test/BUILD.gn b/test/BUILD.gn index 91f98cd195e6..ed2c6071ae5c 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -11,7 +11,6 @@ import("//brave/components/ai_chat/core/common/buildflags/buildflags.gni") import("//brave/components/brave_vpn/common/buildflags/buildflags.gni") import("//brave/components/brave_wayback_machine/buildflags/buildflags.gni") import("//brave/components/brave_webtorrent/browser/buildflags/buildflags.gni") -import("//brave/components/greaselion/browser/buildflags/buildflags.gni") import("//brave/components/ntp_background_images/buildflags/buildflags.gni") import("//brave/components/playlist/common/buildflags/buildflags.gni") import("//brave/components/request_otr/common/buildflags/buildflags.gni") @@ -1043,17 +1042,6 @@ test("brave_browser_tests") { sources += [ "//brave/browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc" ] } - if (enable_greaselion) { - sources += [ "//brave/browser/greaselion/greaselion_browsertest.cc" ] - - deps += [ - "//brave/browser/brave_rewards", - "//brave/browser/greaselion", - "//brave/components/greaselion/browser", - "//chrome/browser", - ] - } - if (ethereum_remote_client_enabled) { sources += [ "//brave/browser/extensions/brave_wallet_apitest.cc" ] @@ -1264,6 +1252,7 @@ if (is_android) { } sources = [ + "//brave/android/javatests/org/chromium/chrome/browser/BraveSafetyNetThreatsPrioritiesTest.java", "//brave/android/javatests/org/chromium/chrome/browser/BraveSwipeRefreshHandlerTest.java", "//brave/android/javatests/org/chromium/chrome/browser/BytecodeTest.java", "//brave/android/javatests/org/chromium/chrome/browser/brave_wallet/BraveWalletUtilsTest.java", @@ -1279,6 +1268,7 @@ if (is_android) { "//base:base_java_test_support", "//base:base_shared_preferences_java", "//brave/components/brave_wallet/common:mojom_java", + "//brave/components/safe_browsing/android:brave_safe_browsing_java", "//cc:cc_java", "//chrome/android/features/keyboard_accessory/public:public_java", "//chrome/browser/android/browserservices/intents:java", diff --git a/test/data/tor/components/linux/biahpgbdmdkfgndcmfiipgcebobojjkp/1.0.0/tor-0.3.3.8-linux-brave-5 b/test/data/tor/components/linux/biahpgbdmdkfgndcmfiipgcebobojjkp/1.0.0/tor-0.3.3.8-linux-brave-5 old mode 100644 new mode 100755 diff --git a/tools/perf/profiles/brave-typical-android.zip.sha1 b/tools/perf/profiles/brave-typical-android.zip.sha1 index a679fbebd779..1123380db892 100644 --- a/tools/perf/profiles/brave-typical-android.zip.sha1 +++ b/tools/perf/profiles/brave-typical-android.zip.sha1 @@ -1 +1 @@ -9be0b2a1d71c85eb606ed9a4934a48124b3d9f7b +44a53ab9e86463346fe464b0eafa5428a1834e8e diff --git a/tools/perf/profiles/brave-typical-android.zip.sizes b/tools/perf/profiles/brave-typical-android.zip.sizes index ed0787746c38..614a14f31457 100644 --- a/tools/perf/profiles/brave-typical-android.zip.sizes +++ b/tools/perf/profiles/brave-typical-android.zip.sizes @@ -1,11 +1,11 @@ -Total size 95771K +Total size 97769K -GROUP Adblock [8472K total] - 133K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.231 [adcocjohghhfpidemphmcmlmhnfgikei] - 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9081 [bfpgedeaaibpoidldhjcknekahbikncb] - 1398K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10005 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] +GROUP Adblock [8488K total] + 134K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.233 [adcocjohghhfpidemphmcmlmhnfgikei] + 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9233 [bfpgedeaaibpoidldhjcknekahbikncb] + 1401K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10155 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] 145K Brave Ad Block Updater (Regional Catalog) 1.0.67 [gkboaolpopklhgplhaaiboijnklogmbc] - 5693K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8488 [iodkpdagapdfkphljnddpjlldadblomo] + 5704K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8611 [iodkpdagapdfkphljnddpjlldadblomo] 6K Brave Ad Block Updater (Brave Experimental Adblock Rules (plaintext)) 1.0.40 [jcfckfokjmopfomnoebdkdhbhcgjfnbi] 1041K Brave Ad Block Updater (Resources) 1.0.100 [mfddibmblmbccpadfndgakiopmmhebop] @@ -13,23 +13,23 @@ GROUP Ads [22973K total] 70K Brave Ads Resources 1.0.104 [iblokdlgekdjophgeonmanpnjihcjkjj] 22903K Brave Ads Resources 1.0.67 [ocilmpijebaopmdifcomolmpigakocmo] -GROUP Ntp [12649K total] +GROUP Ntp [14584K total] 12360K Brave NTP background images 1.0.15 [aoojcmojmmcbpfgoecoadbdpnagfchel] - 289K Brave NTP sponsored images 1.0.1102 [pciohbjgmbejokmghgjkobeionibheai] + 2224K Brave NTP sponsored images 1.0.1111 [pciohbjgmbejokmghgjkobeionibheai] -GROUP Other [166K total] - 166K Brave Local Data Files Updater 1.0.936 [afalakplffnnnlkncjhbmahjfjhmlkal] +GROUP Other [167K total] + 167K Brave Local Data Files Updater 1.0.942 [afalakplffnnnlkncjhbmahjfjhmlkal] -GROUP chromium [1116K total] - 532K crl-set-5864472947170489117.data 9225 [CertificateRevocation] +GROUP chromium [1177K total] + 592K crl-set-7068604811368670265.data 9246 [CertificateRevocation] 31K chromeCommerceHeuristics 2023.3.30.1305 [CommerceHeuristics] 103K Crowd Deny 2023.11.29.1201 [Crowd Deny] 9K fileTypePolicies 67 [FileTypePolicies] - 205K pkiMetadata 1103 [PKIMetadata] + 205K pkiMetadata 1113 [PKIMetadata] 32K real_time_url_checks_allowlist 9 [RealTimeUrlChecksAllowlist] 4K sslErrorAssistant 7 [SSLErrorAssistant] - 160K safetyTips 3045 [SafetyTips] - 34K Third-Party Cookie Deprecation Metadata 2024.10.19.1 [TpcdMetadata] + 162K safetyTips 3047 [SafetyTips] + 34K Third-Party Cookie Deprecation Metadata 2024.10.26.1 [TpcdMetadata] GROUP large_files [44256K total] 44256K Default/publisher_info_db diff --git a/tools/perf/profiles/brave-typical-mac.zip.sha1 b/tools/perf/profiles/brave-typical-mac.zip.sha1 index 4a2df21e2971..1b60674891cf 100644 --- a/tools/perf/profiles/brave-typical-mac.zip.sha1 +++ b/tools/perf/profiles/brave-typical-mac.zip.sha1 @@ -1 +1 @@ -c0a922be4e75ad4da9d7219bf1490882a166a020 +1845d163c51e123c5c606985adb9daa1b907c325 diff --git a/tools/perf/profiles/brave-typical-mac.zip.sizes b/tools/perf/profiles/brave-typical-mac.zip.sizes index 63ad5d38e243..4d89a7a12bac 100644 --- a/tools/perf/profiles/brave-typical-mac.zip.sizes +++ b/tools/perf/profiles/brave-typical-mac.zip.sizes @@ -1,11 +1,11 @@ -Total size 130942K +Total size 132898K -GROUP Adblock [8472K total] - 133K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.231 [adcocjohghhfpidemphmcmlmhnfgikei] - 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9081 [bfpgedeaaibpoidldhjcknekahbikncb] - 1398K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10005 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] +GROUP Adblock [8488K total] + 134K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.233 [adcocjohghhfpidemphmcmlmhnfgikei] + 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9233 [bfpgedeaaibpoidldhjcknekahbikncb] + 1401K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10155 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] 145K Brave Ad Block Updater (Regional Catalog) 1.0.67 [gkboaolpopklhgplhaaiboijnklogmbc] - 5693K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8488 [iodkpdagapdfkphljnddpjlldadblomo] + 5704K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8611 [iodkpdagapdfkphljnddpjlldadblomo] 6K Brave Ad Block Updater (Brave Experimental Adblock Rules (plaintext)) 1.0.40 [jcfckfokjmopfomnoebdkdhbhcgjfnbi] 1041K Brave Ad Block Updater (Resources) 1.0.100 [mfddibmblmbccpadfndgakiopmmhebop] @@ -13,12 +13,12 @@ GROUP Ads [22973K total] 70K Brave Ads Resources 1.0.104 [iblokdlgekdjophgeonmanpnjihcjkjj] 22903K Brave Ads Resources 1.0.67 [ocilmpijebaopmdifcomolmpigakocmo] -GROUP Ntp [12649K total] +GROUP Ntp [14584K total] 12360K Brave NTP background images 1.0.15 [aoojcmojmmcbpfgoecoadbdpnagfchel] - 289K Brave NTP sponsored images 1.0.1759 [gccbbckogglekeggclmmekihdgdpdgoe] + 2224K Brave NTP sponsored images 1.0.1768 [gccbbckogglekeggclmmekihdgdpdgoe] -GROUP Other [166K total] - 166K Brave Local Data Files Updater 1.0.936 [afalakplffnnnlkncjhbmahjfjhmlkal] +GROUP Other [167K total] + 167K Brave Local Data Files Updater 1.0.942 [afalakplffnnnlkncjhbmahjfjhmlkal] GROUP large_files [76312K total] 3262K Default/Local Extension Settings/mnojpmjdmbbfmejpflffifhffcmidifd/000003.log diff --git a/tools/perf/profiles/brave-typical-win.zip.sha1 b/tools/perf/profiles/brave-typical-win.zip.sha1 index e1d59fa65324..797256c71262 100644 --- a/tools/perf/profiles/brave-typical-win.zip.sha1 +++ b/tools/perf/profiles/brave-typical-win.zip.sha1 @@ -1 +1 @@ -f2bd889f597fe7ad8eb5ceb56a390517d9122538 +f5bb11d6dac7c0a6858d90d4c779c36af751a171 diff --git a/tools/perf/profiles/brave-typical-win.zip.sizes b/tools/perf/profiles/brave-typical-win.zip.sizes index 798fbe0cf52a..e382f9308acf 100644 --- a/tools/perf/profiles/brave-typical-win.zip.sizes +++ b/tools/perf/profiles/brave-typical-win.zip.sizes @@ -1,11 +1,11 @@ -Total size 134905K +Total size 136866K -GROUP Adblock [8472K total] - 133K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.231 [adcocjohghhfpidemphmcmlmhnfgikei] - 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9081 [bfpgedeaaibpoidldhjcknekahbikncb] - 1398K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10005 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] +GROUP Adblock [8488K total] + 134K Brave Ad Block Updater (Brave Ad Block First Party Filters (plaintext)) 1.0.233 [adcocjohghhfpidemphmcmlmhnfgikei] + 54K Brave Ad Block Updater (Fanboy's Mobile Notifications (plaintext)) 1.0.9233 [bfpgedeaaibpoidldhjcknekahbikncb] + 1401K Brave Ad Block Updater (EasyList Cookie (plaintext)) 1.0.10155 [cdbbhgbmjhfnhnmgeddbliobbofkgdhe] 145K Brave Ad Block Updater (Regional Catalog) 1.0.67 [gkboaolpopklhgplhaaiboijnklogmbc] - 5693K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8488 [iodkpdagapdfkphljnddpjlldadblomo] + 5704K Brave Ad Block Updater (Brave Ad Block Updater (plaintext)) 1.0.8611 [iodkpdagapdfkphljnddpjlldadblomo] 6K Brave Ad Block Updater (Brave Experimental Adblock Rules (plaintext)) 1.0.40 [jcfckfokjmopfomnoebdkdhbhcgjfnbi] 1041K Brave Ad Block Updater (Resources) 1.0.100 [mfddibmblmbccpadfndgakiopmmhebop] @@ -13,12 +13,12 @@ GROUP Ads [22973K total] 70K Brave Ads Resources 1.0.104 [iblokdlgekdjophgeonmanpnjihcjkjj] 22903K Brave Ads Resources 1.0.67 [ocilmpijebaopmdifcomolmpigakocmo] -GROUP Ntp [12649K total] +GROUP Ntp [14584K total] 12360K Brave NTP background images 1.0.15 [aoojcmojmmcbpfgoecoadbdpnagfchel] - 289K Brave NTP sponsored images 1.0.1759 [gccbbckogglekeggclmmekihdgdpdgoe] + 2224K Brave NTP sponsored images 1.0.1768 [gccbbckogglekeggclmmekihdgdpdgoe] -GROUP Other [166K total] - 166K Brave Local Data Files Updater 1.0.936 [afalakplffnnnlkncjhbmahjfjhmlkal] +GROUP Other [167K total] + 167K Brave Local Data Files Updater 1.0.942 [afalakplffnnnlkncjhbmahjfjhmlkal] GROUP large_files [80333K total] 3262K Default\Local Extension Settings\mnojpmjdmbbfmejpflffifhffcmidifd\000003.log diff --git a/tools/perf/profiles/chrome-typical-android.zip.sha1 b/tools/perf/profiles/chrome-typical-android.zip.sha1 index 8dc58b20471e..4694da124470 100644 --- a/tools/perf/profiles/chrome-typical-android.zip.sha1 +++ b/tools/perf/profiles/chrome-typical-android.zip.sha1 @@ -1 +1 @@ -6dee138a35a550fa5d14230bc5f7962ebdfd0b71 +528d8b44d7b309d84144e663bcccf231bc6e7719 diff --git a/tools/perf/profiles/chrome-typical-android.zip.sizes b/tools/perf/profiles/chrome-typical-android.zip.sizes index ff90b93f277b..36a3ccd0d2ee 100644 --- a/tools/perf/profiles/chrome-typical-android.zip.sizes +++ b/tools/perf/profiles/chrome-typical-android.zip.sizes @@ -1,20 +1,20 @@ -Total size 15244K +Total size 15304K -GROUP chromium [9396K total] +GROUP chromium [9468K total] 217K chromeAutofillStatesData 2024.7.12.235938 [AutofillStates] - 532K crl-set-5864472947170489117.data 9225 [CertificateRevocation] + 592K crl-set-7068604811368670265.data 9246 [CertificateRevocation] 31K chromeCommerceHeuristics 2023.3.30.1305 [CommerceHeuristics] 103K Crowd Deny 2023.11.29.1201 [Crowd Deny] 9K fileTypePolicies 67 [FileTypePolicies] 13K First Party Sets 2024.8.10.0 [FirstPartySetsPreloaded] - 7751K OnDeviceHeadSuggestENUS500000 20240929.685292949.14 [OnDeviceHeadSuggestModel] - 54K Optimization Hints 470 [OptimizationHints] + 7760K OnDeviceHeadSuggestENUS500000 20241014.687946955.14 [OnDeviceHeadSuggestModel] + 54K Optimization Hints 472 [OptimizationHints] 1K Origin Trials Updates 1.0.0.17 [OriginTrials] - 205K pkiMetadata 1103 [PKIMetadata] - 9K Privacy Sandbox Attestations 2024.10.14.0 [PrivacySandboxAttestationsPreloaded] + 205K pkiMetadata 1113 [PKIMetadata] + 9K Privacy Sandbox Attestations 2024.10.23.0 [PrivacySandboxAttestationsPreloaded] 32K real_time_url_checks_allowlist 9 [RealTimeUrlChecksAllowlist] 4K sslErrorAssistant 7 [SSLErrorAssistant] - 160K safetyTips 3045 [SafetyTips] - 223K Subresource Filtering Rules 9.51.0 [Subresource Filter] - 34K Third-Party Cookie Deprecation Metadata 2024.10.19.1 [TpcdMetadata] + 162K safetyTips 3047 [SafetyTips] + 224K Subresource Filtering Rules 9.52.0 [Subresource Filter] + 34K Third-Party Cookie Deprecation Metadata 2024.10.26.1 [TpcdMetadata] 10K trustToken 2024.10.11.1 [TrustTokenKeyCommitments] diff --git a/tools/perf/profiles/chrome-typical-mac.zip.sha1 b/tools/perf/profiles/chrome-typical-mac.zip.sha1 index da99be497b42..93daf0068975 100644 --- a/tools/perf/profiles/chrome-typical-mac.zip.sha1 +++ b/tools/perf/profiles/chrome-typical-mac.zip.sha1 @@ -1 +1 @@ -2873c2a02c9ff67b775bf4d2d1006a94efb7df02 +b56c7df1047182aa1fbec78a46a8692aaaa84466 diff --git a/tools/perf/profiles/chrome-typical-mac.zip.sizes b/tools/perf/profiles/chrome-typical-mac.zip.sizes index a678d0c6a924..3eeda6184e0b 100644 --- a/tools/perf/profiles/chrome-typical-mac.zip.sizes +++ b/tools/perf/profiles/chrome-typical-mac.zip.sizes @@ -1,4 +1,4 @@ -Total size 41479K +Total size 41511K GROUP large_files [31272K total] 1791K Safe Browsing/ChromeExtMalware.store.32_13357756173012233 diff --git a/tools/perf/profiles/chrome-typical-win.zip.sha1 b/tools/perf/profiles/chrome-typical-win.zip.sha1 index a1a77725a8b3..3e1ccc9a9276 100644 --- a/tools/perf/profiles/chrome-typical-win.zip.sha1 +++ b/tools/perf/profiles/chrome-typical-win.zip.sha1 @@ -1 +1 @@ -ee2bcfa7527b3bbbfe68d2c9d4366d14b814ee83 +05bcea07a0afc8c393af3a1f1e47980f39f302c5 diff --git a/tools/perf/profiles/chrome-typical-win.zip.sizes b/tools/perf/profiles/chrome-typical-win.zip.sizes index f0489951ec27..0d6f08b750f1 100644 --- a/tools/perf/profiles/chrome-typical-win.zip.sizes +++ b/tools/perf/profiles/chrome-typical-win.zip.sizes @@ -1,4 +1,4 @@ -Total size 41496K +Total size 41509K GROUP large_files [31272K total] 1791K Safe Browsing\ChromeExtMalware.store.32_13357751453489368