-
Notifications
You must be signed in to change notification settings - Fork 868
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove Greaselion dependency from Rewards service
- Loading branch information
1 parent
571021b
commit 442ee26
Showing
55 changed files
with
1,892 additions
and
1,802 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
186 changes: 186 additions & 0 deletions
186
browser/brave_rewards/creator_detection_script_injector.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
// 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 <utility> | ||
|
||
#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<std::string_view, int>( | ||
{{"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<std::string> 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_ = rfh; | ||
last_url_ = GURL(); | ||
|
||
auto script_source = GetDetectionScript(injector_host_); | ||
if (!script_source) { | ||
return; | ||
} | ||
|
||
injector_host_->GetRemoteAssociatedInterfaces()->GetInterface(&injector_); | ||
|
||
bool verbose_logging = | ||
base::FeatureList::IsEnabled(features::kVerboseLoggingFeature); | ||
|
||
// Add a `braveRewards` global variable to the isolated world. | ||
std::string initializer = | ||
base::StrCat({"self.braveRewards = { verboseLogging: ", | ||
verbose_logging ? "true" : "false", " }"}); | ||
ExecuteScript(initializer, base::DoNothing()); | ||
|
||
// 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 != injector_host_.get() || !injector_.is_bound()) { | ||
std::move(callback).Run(std::nullopt); | ||
return; | ||
} | ||
|
||
// Do not call the detection routine if it has already been run for this URL. | ||
auto& url = injector_host_->GetLastCommittedURL(); | ||
if (url == last_url_) { | ||
std::move(callback).Run(std::nullopt); | ||
return; | ||
} | ||
|
||
last_url_ = url; | ||
|
||
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <optional> | ||
#include <string> | ||
#include <string_view> | ||
|
||
#include "base/functional/callback.h" | ||
#include "base/memory/raw_ref.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "base/values.h" | ||
#include "brave/components/script_injector/common/mojom/script_injector.mojom.h" | ||
#include "mojo/public/cpp/bindings/associated_remote.h" | ||
#include "url/gurl.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<void(std::optional<Result>)>; | ||
|
||
// 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. | ||
void DetectCreator(content::RenderFrameHost* rfh, | ||
DetectCreatorCallback callback); | ||
|
||
private: | ||
using ExecuteScriptCallback = base::OnceCallback<void(base::Value)>; | ||
|
||
void ExecuteScript(std::string_view script, ExecuteScriptCallback callback); | ||
|
||
void OnCreatorDetected(DetectCreatorCallback callback, base::Value value); | ||
|
||
mojo::AssociatedRemote<script_injector::mojom::ScriptInjector> injector_; | ||
raw_ptr<content::RenderFrameHost> injector_host_ = nullptr; | ||
GURL last_url_; | ||
base::WeakPtrFactory<CreatorDetectionScriptInjector> weak_factory_{this}; | ||
}; | ||
|
||
} // namespace brave_rewards | ||
|
||
#endif // BRAVE_BROWSER_BRAVE_REWARDS_CREATOR_DETECTION_SCRIPT_INJECTOR_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.