Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement unified adblock catalog #19946

Merged
merged 22 commits into from
Sep 19, 2023
Merged

Implement unified adblock catalog #19946

merged 22 commits into from
Sep 19, 2023

Conversation

antonok-edm
Copy link
Collaborator

Resolves brave/brave-browser#32482

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run lint, npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

This change makes the default adblock component available slightly later on first startup after install, as it requires an additional network round-trip for a component installation. It'd be good to test the following:

With a completely fresh install, open Brave and as quickly as humanly possible navigate to a page that is likely to have ads and/or cookie banners if Shields are down (i.e. definitely YouTube, maybe some others as well). Shields should still be working correctly. This should be the case on a wide range of internet connnections (slow/fast, high/low latency).

If there are any issues with this, it's possible to preload the default adblock component's ID and public key like we had before in a followup.

@antonok-edm antonok-edm requested a review from a team as a code owner August 30, 2023 18:29
@antonok-edm antonok-edm self-assigned this Aug 30, 2023
if (i > UINT8_MAX) {
return false;
}
*field = (uint8_t)i;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reported by reviewdog 🐶
[semgrep] Semgrep found a cast from int (signed) to uint8_t. For arithmetic use base::CheckAdd(value1, value2).AssignIfValid(&result)

Source: https://github.com/brave/security-action/blob/main/assets/semgrep_rules/c/cast-signed-to-unsigned.yaml


Cc @fmarier @thypon

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the check above to the following, although it doesn't appear in the preview here for some reason:

if (i < 0 || i > UINT8_MAX) {
  return false;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bridiver should we use some native helper here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's base::IsValueInRangeForNumericType<uint8_t>(i) but presumedly that won't help with the cast warning either. Closest I found for a one-liner was base::checked_cast<uint8_t>(value->GetInt()) but that CHECKs on out-of-range values instead of returning.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we definitely should not be doing a c-style cast anywhere, but base::checked_cast is probably what you want here. If you want to fail without a CHECK then call IsValueInRangeForNumericType first

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 19 to 22
@property(nonatomic, copy) bool hidden;
@property(nonatomic, copy) bool default_enabled;
@property(nonatomic, copy) bool first_party_protections;
@property(nonatomic, copy) uint8_t permission_mask;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. copy doesn't apply to primative types, it can be removed entirely and just be @property(nonatomic)
  2. You didn't expose any of these properties in the header file so they aren't accessible on the iOS side

Copy link
Collaborator

@kylehickinson kylehickinson Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Camel-case for Obj-C property names and prefixed with is for bools (i.e. isHidden, isEnabledByDefault, isFirstPartyProtection, etc)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, exactly what I needed to know 🙏

updated

@antonok-edm antonok-edm force-pushed the unified-adblock-catalog branch 3 times, most recently from aa4acaf to 6c79625 Compare August 30, 2023 21:32
@antonok-edm antonok-edm force-pushed the unified-adblock-catalog branch 2 times, most recently from b26d9be to 705f6de Compare August 30, 2023 22:13
Copy link
Collaborator

@kylehickinson kylehickinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS++

cc @cuba just to notify about upcoming non-breaking changes

base::BindOnce(&AdBlockFiltersProviderManager::FinishCombinating,
weak_factory_.GetWeakPtr(), std::move(cb)));
const auto collect_and_merge = base::BarrierClosure(
filters_providers.size(), base::BindOnce(std::move(cb)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you adding another BindOnce to the callback here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, fixed

.add_filter_list(
std::str::from_utf8(rules.as_slice())?,
ParseOptions {
permissions: PermissionMask::from_bits(permission_mask),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

permissions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've documented it in a few places including here and here; let me know if there's somewhere else you'd prefer to see more information.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like you have an enum on one end, but not sure about the cpp end and definitely needs some docs, preferably in the code in the other place I commented

g_brave_browser_process->ad_block_service()->regional_service_manager();
if (!regional_service_manager ||
!regional_service_manager->IsFilterListAvailable(
auto* component_service_manager =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

component is already so overloaded, is there a better name we can use here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅 It is at least managing all the filter lists fetched via the component updater now. Previously it managed a weird subset of them, and the original "regional" naming was never 100% accurate for as long as I can remember.

Would CRXServiceManager be better?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see DM, I think maybe it's better to not expose this in the public api at all. I don't think callers of these methods need to care that there is a ComponentServiceManager that handles certain providers and a subscription manager that handles others, they just want to check IsFilterListAvailable or whatever the case may be

const std::string& resources_json) {
auto result = adblock::engine_from_filter_set(std::move(filter_set));
if (result.result_kind != adblock::ResultKind::Success) {
LOG(ERROR) << "AdBlockEngine::OnFilterSetLoaded failed: "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other one, logging like this generally isn't useful so we would normally restrict this to a VLOG. We shouldn't just be logging errors into the main chrome log and actually I think even that is disabled by default maybe

}
},
adblock_engine_->AsWeakPtr(), deserialize_, std::move(dat_buf_),
resources_json);
adblock_engine_->AsWeakPtr(), *std::move(filter_set_), resources_json);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might have something a bit weird here with *std::move(filter_set_). You want to move the underlying rust::Box<adblock::FilterSet>, not the absl::optional so I think it should be std::move(*filter_set_)

dat_buf_ = std::move(dat_buf);
void AdBlockService::SourceProviderObserver::OnFilterSetLoaded(
rust::Box<adblock::FilterSet>* filter_set) {
filter_set_ = absl::make_optional(std::move(*filter_set));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems very odd and confusing. Taking ownership from a pointer is not the behavior you would expect. When using base::Owned the callback should not know or need to know that base::Owned was used and in this case it definitely would need to know that. I think you want auto* filter_set to be a unique_ptr, get a raw pointer reference using .get() before you create on_loaded_cb (and call std::move) and then pass that as base::Unretained to LoadFilterSetForEngine

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would also be simpler if you used unique_ptr instead of absl::optional which makes things a bit confusing here and also https://github.com/brave/brave-core/pull/19946/files#r1329348390

@@ -70,6 +71,20 @@ bool GetStringVector(const base::Value* value,
}
}

bool GetUint8(const base::Value* value, uint8_t* field) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have any tests that cover this indirectly?

Copy link
Collaborator

@bridiver bridiver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good for merge to fix the bug and we'll follow-up with other changes

@antonok-edm antonok-edm merged commit 2e17608 into master Sep 19, 2023
6 checks passed
@antonok-edm antonok-edm deleted the unified-adblock-catalog branch September 19, 2023 21:47
@sangwoo108 sangwoo108 mentioned this pull request Sep 20, 2023
25 tasks
sangwoo108 added a commit that referenced this pull request Sep 20, 2023
* The file was renamed from #19946
@kjozwiak kjozwiak added this to the 1.60.x - Nightly milestone Sep 25, 2023
atuchin-m added a commit that referenced this pull request Oct 7, 2023
@atuchin-m atuchin-m mentioned this pull request Oct 7, 2023
25 tasks
@antonok-edm antonok-edm mentioned this pull request Jan 31, 2024
24 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement unified adblock list catalog
7 participants