Conversation
b419aea to
142ce48
Compare
1de933d to
418ecff
Compare
|
@iefremov This should be all set for review |
| std::shared_ptr<BraveRequestInfo> ctx, | ||
| const base::Optional<std::string> cname) { | ||
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | ||
| scoped_refptr<base::SequencedTaskRunner> task_runner = |
There was a problem hiding this comment.
This isn't safe because AdblockCnameResolveHostClient is not owned by anything and so it could outlive anything including the ad_block_service
There was a problem hiding this comment.
you could pass the task runner itself into the AdblockCnameResolveHostClient constructor since it's ref counted
| ctx)); | ||
| auto* rph = content::RenderProcessHost::FromID(ctx->render_process_id); | ||
| if (!rph) { | ||
| // This case occurs for the top-level request. It's okay to ignore the |
There was a problem hiding this comment.
top-level requests don't have a render process host? That doesn't sound right and also if top-level requests can't be blocked, why are we calling ShouldBlockAdOnTaskRunner?
There was a problem hiding this comment.
ctx->render_process_id comes up as -1 for top level requests from my testing, which causes the RenderProcessHost to be a nullptr.
There was a problem hiding this comment.
resolved by getting required fields through GetWebContents
| ctx, base::Optional<std::string>()), | ||
| base::BindOnce(&OnShouldBlockAdResult, next_callback, ctx)); | ||
| } else { | ||
| new AdblockCnameResolveHostClient(next_callback, ctx); |
There was a problem hiding this comment.
rather than passing the next_callback, I would pass https://github.com/brave/brave-core/pull/6640/files#diff-5a17ec06c6e281e744cfa03e9d7561a6R164 so you don't have to duplicate it here https://github.com/brave/brave-core/pull/6640/files#diff-5a17ec06c6e281e744cfa03e9d7561a6R77
There was a problem hiding this comment.
I would also partially bind https://github.com/brave/brave-core/pull/6640/files#diff-5a17ec06c6e281e744cfa03e9d7561a6R162 base::BindOnce(&ShouldBlockAdOnTaskRunner, ctx) and pass that as well so AdblockCnameResolveHostClient doesn't have to stay in sync with any changes here
There was a problem hiding this comment.
We ended up keeping the logic only in OnGetCnameResult, renaming that to ShouldBlockAdWithOptionalCname, and calling it directly with the empty Optional if there's no render process host.
| @@ -56,16 +60,88 @@ void OnShouldBlockAdResult(const ResponseCallback& next_callback, | |||
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |||
There was a problem hiding this comment.
we should really be checking g_brave_browser_process->IsShuttingDown() here. This isn't new with your changes, but I think it's safer for the existing code. wdyt @iefremov ? I think next_callback.run could potentially crash here otherwise?
There was a problem hiding this comment.
I think we are fine, until we hold any potentially dangling references - TaskRunners clean up their task queues on destruction. next_callback holds weak pointer to `BraveRequestHandler, so this is also safe.
50e7911 to
eec6dc1
Compare
| base::BindOnce(&ShouldBlockAdWithOptionalCname, task_runner, | ||
| next_callback, ctx); | ||
|
|
||
| new AdblockCnameResolveHostClient(std::move(cname_callback), ctx); |
There was a problem hiding this comment.
do you have any ideas or measurements about performance implications of this?
There was a problem hiding this comment.
Not really, I don't had a good sense of how that can be done in this instance. I did look into writing some browsertests, but I couldn't see how to mock the DNS responses.
Happy to hear suggestions on this if you have any - but from manual testing, I couldn't notice any slowdown at all.
There was a problem hiding this comment.
We can start with measuring the delay manually (check the time before ResolveHost and then in OnResult) and reporting it to UMA_HISTOGRAM_TIMES. Then after some browsing this value can be checked on brave://histograms. Would be nice to test an android apk.
as for browser tests, I see some examples using FakeHostResolver - did you check that?
There was a problem hiding this comment.
hmm, I might need some more detailed instructions, this is all new to me.
Should histogram measurement code be left in and merged? Or just temporarily added for manual testing? Any good examples of where we've done this in the past?
As for browser tests, I'm not sure of the best way to force shields to use the fake resolver. It looks like chrome/browser/net/dns_probe_browsertest.cc uses this to set up a DnsProbeService with a fake resolver, and I can't tell what the equivalent approach would look like for this PR.
void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) {
delaying_dns_probe_service_ = static_cast<DelayingDnsProbeService*>(
DnsProbeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
browser->profile(),
base::BindRepeating(
&DelayingDnsProbeService::Create,
base::BindRepeating(&DnsProbeBrowserTest::GetNetworkContext,
base::Unretained(this)),
base::BindRepeating(
&DnsProbeBrowserTest::GetDnsConfigChangeManager,
base::Unretained(this)))));
// If currently watching a NetErrorTabHelper, stop doing so before start
// watching another.
if (monitored_tab_helper_) {
monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
NetErrorTabHelper::DnsProbeStatusSnoopCallback());
}
active_browser_ = browser;
monitored_tab_helper_ = NetErrorTabHelper::FromWebContents(
active_browser_->tab_strip_model()->GetActiveWebContents());
monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
BindRepeating(&DnsProbeBrowserTest::OnDnsProbeStatusSent,
Unretained(this)));
}There was a problem hiding this comment.
Should histogram measurement code be left in and merged?
yes, it can be useful in the future. Basically the whole Chromium codebase is full of histograms.
I've added some related ones like Brave.ProxyingURLLoader.TotalRequestTime or Brave.OnBeforeURLRequest_Handler
|
|
||
| // Should not be called | ||
| void OnTextResults(const std::vector<std::string>& text_results) override { | ||
| DCHECK(false); |
| std::move(cb_).Run( | ||
| base::Optional<std::string>(resolved_addresses->canonical_name())); | ||
| } else { | ||
| std::move(cb_).Run(base::Optional<std::string>()); |
There was a problem hiding this comment.
base::nullopt or maybe just {} ?
There was a problem hiding this comment.
cool, didn't know about these
| return nullptr; | ||
| } | ||
| web_contents = | ||
| content::WebContents::FromRenderFrameHost(rfh); |
There was a problem hiding this comment.
can fit to the previous line?
| ctx->request_url.host() != *canonical_name && *canonical_name != "") { | ||
| GURL::Replacements replacements = GURL::Replacements(); | ||
| replacements.SetHost(canonical_name->c_str(), | ||
| url::Component(0, static_cast<int>(canonical_name->length()))); |
| auto* web_contents = GetWebContents(ctx->render_process_id, | ||
| ctx->render_frame_id, | ||
| ctx->frame_tree_node_id); | ||
| DCHECK(web_contents); |
There was a problem hiding this comment.
not sure this will work for service workers
There was a problem hiding this comment.
you're correct, I noticed that Twitch has this case occasionally. Should be fixed now.
| DCHECK(web_contents); | ||
|
|
||
| content::BrowserContext* context = web_contents->GetBrowserContext(); | ||
| DCHECK(context); |
| const ResponseCallback& next_callback, | ||
| std::shared_ptr<BraveRequestInfo> ctx) { | ||
| base::OnceCallback<void(base::Optional<std::string>)> cname_callback = | ||
| base::BindOnce(&ShouldBlockAdWithOptionalCname, task_runner, |
There was a problem hiding this comment.
I don't understand why do we need this callback. Can we just call ShouldBlockAdWithOptionalCname in OnComplete?
task_runner will be alive given that it is owned by ad_block_service which in turn is owned by g_browser_process.
Or we can bind an anonymous lambda here that would take get task_runner and post
There was a problem hiding this comment.
Good call, we needed this previously in the (now removed) failure case when we couldn't create the resolver
There was a problem hiding this comment.
I moved it into the AdblockCnameResolveHostClient constructor since you discovered we need to bind the ResponseCallback anyways.
4fe6756 to
0d4219c
Compare
| #include "ui/base/resource/resource_bundle.h" | ||
| #include "url/url_canon.h" | ||
|
|
||
| namespace { |
There was a problem hiding this comment.
typically anonymous namespace should be placed inside main namespace (i.e. brave)
| const base::Optional<net::AddressList>& resolved_addresses) override { | ||
| if (result == net::OK && resolved_addresses) { | ||
| DCHECK(resolved_addresses.has_value() && !resolved_addresses->empty()); | ||
| std::move(cb_).Run( |
There was a problem hiding this comment.
I think we can replace this with a direct call
task_runner->PostTaskAndReply(
FROM_HERE, base::BindOnce(&ShouldBlockAdOnTaskRunner, ctx, cname),
base::BindOnce(&OnShouldBlockAdResult, next_callback, ctx));
This way, you don't need to bind and store cb_, and ShouldBlockAdWithOptionalCname can also be eliminated. task_runner() can also be obtained right here. So you would need to only save next_callback in constructor
There was a problem hiding this comment.
@bridiver said he wanted the task runner passed in, perhaps the two of you should discuss?
0d4219c to
51d38eb
Compare
|
@iefremov I did some browsing for ~30 minutes with the latest changes, compiled in |
51d38eb to
c65adfb
Compare
|
Took some histogram measurements of With CNAME adblockingWithout CNAME adblockingSample size here is ~36x larger. ThoughtsWith CNAME adblocking, the distribution is definitely skewed downwards and also noticeably bi-modal. Completion under 5 milliseconds(?) regresses from 22.1% to 13% of requests, but completion under 40 milliseconds(?) is roughly equal on both. Given the previous measurements for Probably not related to this PR, but I am intrigued by the narrow peak at exactly |
|
At @pes10k's suggestion, I've redone the performance measurements here using Puppeteer for a more fair comparison. These are both across the top 920 Alexa domains. I used https://github.com/brave/format-chromium-histogram to generate these histograms using raw data from the Chrome DevTools Protocol. With CNAME adblockingWithout CNAME adblocking |
|
@iefremov just some background; after seeing the initial numbers above, I thought it might be a sampling issue, and that in a heavily cached based system like DNS, the more queries you have, the more you drive the mean down to the min. Anywhoo, just wanted to check in. Does it look like this is clear to merge then? :) |
|
yeah, well, then we are probably safe to merge. Though this looks like a good candidate for a/b test (which we don't do yet :)) |
c65adfb to
89a4f48
Compare
Resolves brave/brave-browser#11712
Submitter Checklist:
npm run lint)git rebase master(if needed).git rebase -ito squash commits (if needed).Test Plan:
The actual test plan
When visiting https://mathon.fr, there should be a request to a URL of a similar format[1] to
https://xxxx.mathon.fr/xxxxxxxxxxx.jsthat is blocked and displayed under the Shields panel advanced view when expanding the "Ads and trackers blocked" dropdown counter. Further, there should not be a request tohttps://static.criteo.net/js/ld/ld.jsin the list (or listed anywhere in the Dev Tools network tab).x's are used to symbolize arbitrary alphanumeric charactersSome optional background reading :)
The website
https://mathon.frpulls a CNAME-cloaked script that triggers a few extra network requests. The subdomain and path may change arbitrarily, but during my testing, a script was requested fromhttps://16ao.mathon.fr/frWWWMA6548.js. Using thedigcommandline tool, we can find the full DNS records for16ao.mathon.fr:The canonical name for
16ao.mathon.friset5.eulerian.net, which is blocked by uBlock Origin's default lists. This prevents several other network requests from starting. As a result, the Shields panel actually shows fewer blocked requests (4 instead of 7 in my configuration).Reviewer Checklist:
After-merge Checklist:
changes has landed on.