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

Include component versions in webcompat reports #25688

Merged
merged 33 commits into from
Oct 21, 2024

Conversation

vadimstruts
Copy link
Collaborator

@vadimstruts vadimstruts commented Sep 22, 2024

Resolves brave/brave-browser#35674

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 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:

Make sure that Webcompat Report contains the component versions information.
Steps:

  1. Open Brave Shields pop up dialog
  2. Switch off Brave Shields if It is ON
  3. Click "Report broken site", then click "Submit"
  4. Go to the webcompat reporter dashboard and see the component versions information.

@vadimstruts vadimstruts force-pushed the 35674-include-component-versions-webcompat-reports branch 3 times, most recently from 9a6a930 to dc56223 Compare October 2, 2024 11:54
@vadimstruts vadimstruts marked this pull request as ready for review October 3, 2024 11:49
@vadimstruts vadimstruts requested review from a team as code owners October 3, 2024 11:49
@vadimstruts vadimstruts marked this pull request as draft October 3, 2024 20:11
@vadimstruts vadimstruts force-pushed the 35674-include-component-versions-webcompat-reports branch from ea63de7 to b54f416 Compare October 10, 2024 12:55
@vadimstruts vadimstruts marked this pull request as ready for review October 11, 2024 13:38
@vadimstruts vadimstruts requested a review from a team as a code owner October 11, 2024 13:38
@StephenHeaps StephenHeaps self-requested a review October 11, 2024 14:03
@@ -50,12 +52,14 @@ namespace {
constexpr char kUISourceHistogramName[] = "Brave.Webcompat.UISource";
constexpr int kMaxScreenshotPixelCount = 1280 * 720;

const std::string BoolToString(bool value) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const std::string BoolToString(bool value) {
std::string BoolToString(bool value) {

content::BrowserContext*
WebcompatReporterServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
Copy link
Member

Choose a reason for hiding this comment

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

pls use ProfileKeyedServiceFactory configured for incognito appropriately.

Copy link
Member

Choose a reason for hiding this comment

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

now that you have ProfileKeyedServiceFactory, you need to remove GetBrowserContextToUse override.

@@ -63,7 +63,8 @@ class WebcompatReporterDOMHandler : public content::WebUIMessageHandler {

raw_ptr<content::RenderWidgetHostView> render_widget_host_view_;
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
std::unique_ptr<webcompat_reporter::WebcompatReportUploader> uploader_;
std::unique_ptr<webcompat_reporter::WebcompatReporterService>
reporter_service_;
Copy link
Member

Choose a reason for hiding this comment

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

is this variable used somehow or is it a leftover? It looks wrong, because you should never own a KeyedService.

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 was leftover


private:
raw_ptr<component_updater::ComponentUpdateService> component_update_service_;
raw_ptr<brave_shields::AdBlockService> adblock_service_;
Copy link
Member

Choose a reason for hiding this comment

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

const raw_ptr<...> both members.


// static
mojo::PendingRemote<mojom::WebcompatReporterHandler>
WebcompatReporterServiceFactory::GetForContext(
Copy link
Member

Choose a reason for hiding this comment

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

GetMojoReportHandlerForContext

format: "%@ (%@)",
AppInfo.appVersion,
AppInfo.buildNumber
),
Copy link
Member

Choose a reason for hiding this comment

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

channel is missing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no, channel has separate property: "channel": "developer"
mentioned code helps to combine version value. ex: "version": "1.73 (0)"

Copy link
Member

Choose a reason for hiding this comment

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

ah, I see it's filled later in WebcompatReporter.swift. Not sure why those are separated.. maybe everything can be filled in one place?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, I removed WebcompatReporter.swift, so now all things are in the same place

]

deps = [
":webcompat_reporter_mojom_wrappers",
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this be a public_deps instead?

std::optional<std::vector<ComponentInfo>> GetComponentInfos() const override;

private:
raw_ptr<component_updater::ComponentUpdateService> component_update_service_;
Copy link
Member

Choose a reason for hiding this comment

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

const

return std::nullopt;
}

return result;
Copy link
Member

Choose a reason for hiding this comment

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

seems like this exact code is duplicated. Pls create a base delegate impl that will be shared on iOS and desktop/android.

public WebcompatReporterHandler getWebcompatReporterHandler(
ConnectionErrorHandler connectionErrorHandler) {
Profile profile = Utils.getProfile(false); // Always use regular profile
if (profile == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Utils.getProfile is marked as @NonNull and it tries to get the profile in several different ways, so I would not use the null check

Copy link
Contributor

@AlexeyBarabash AlexeyBarabash left a comment

Choose a reason for hiding this comment

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

Android Java code lgtm.

These imports look strange:

import org.chromium.chrome.browser.crypto_wallet.util.Utils;
at src/brave/android/java/org/chromium/chrome/browser/webcompat_reporter/WebcompatReporterServiceFactory.java

and

import org.chromium.chrome.browser.BraveRewardsHelper;
import org.chromium.chrome.browser.BraveRewardsNativeWorker;

at src/brave/android/java/org/chromium/chrome/browser/shields/BraveShieldsHandler.java

And this is an issue beyond the current PR, crypto_wallet.util.Utils and BraveRewardsHelper are widely used beyond rewards/wallet.

Follow-up issues:
brave/brave-browser#41689
brave/brave-browser#41690

auto service =
webcompat_reporter::WebcompatReporterServiceFactory::GetForBrowserState(
browserState);
if (!service) {
Copy link
Member

Choose a reason for hiding this comment

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

this is a mojo interface, not a keyed service.

I think the variable and the method name GetForBrowserState should be renamed accordingly to not confuse people.

content::BrowserContext*
WebcompatReporterServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
Copy link
Member

Choose a reason for hiding this comment

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

now that you have ProfileKeyedServiceFactory, you need to remove GetBrowserContextToUse override.

if (!is_ios) {
deps += [
"//brave/components/brave_shields/content/browser",
"//chrome/test:test_support",
Copy link
Member

Choose a reason for hiding this comment

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

what is it for? you shouldn't have //chrome in components.

std::optional<std::string> brave_vpn_connected;
std::optional<std::string> details;
std::optional<std::string> contact;
std::optional<base::Value> ad_block_components;
Copy link
Member

Choose a reason for hiding this comment

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

you added a mojo structure that's just similar to this one. Do we really need to have both? Why not just use mojo structure everywhere from now on? Seems like the right thing to do.

ConvertCompsToValue(report_info->ad_block_components_version.value());
if (components) {
report_details_dict.Set(kAdBlockComponentsVersionField,
components->Clone());
Copy link
Member

Choose a reason for hiding this comment

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

you can let ConvertCompsToValue always return a value and simplify things here a bit:

if (report_info->ad_block_components_version && !report_info->ad_block_components_version->empty()) {
  report_details_dict.Set(kAdBlockComponentsVersionField,
                          ConvertCompsToValue(report_info->ad_block_components_version.value()));
}

std::unique_ptr<WebcompatReportUploader> webcompat_report_uploader_;
network::TestURLLoaderFactory url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
base::test::TaskEnvironment task_environment_{
Copy link
Member

Choose a reason for hiding this comment

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

task environment should go first, otherwise you might hit uaf on test destruction.

std::move(delegate), nullptr);

webcompat_reporter_service_->SetReportUploaderForTest(
std::unique_ptr<WebcompatReportUploader>(
Copy link
Member

Choose a reason for hiding this comment

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

why not pass this directly into constructor and remove SetReportUploaderForTest?

also std::make_unique<>.

+ (nullable id)serviceForBrowserState:(ChromeBrowserState*)browserState {
auto service = webcompat_reporter::WebcompatReporterServiceFactory::
GetMojoReportHandlerForContext(browserState);
if (!service) {
Copy link
Member

Choose a reason for hiding this comment

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

handler

#include "ios/chrome/browser/shared/model/profile/profile_ios.h"

@implementation WebcompatReporterServiceFactory
+ (nullable id)serviceForBrowserState:(ChromeBrowserState*)browserState {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this be handlerForBrowserState?

Logger.module.error(
"Failed to setup webcompat request payload: \(error.localizedDescription)"
public static func send(
braveVersion: String?,
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why this function should list all these parameters? Can it just receive the mojo struct type?

namespace webcompat_reporter {

bool NeedsToGetComponentInfo(const std::string& component_id) {
static const base::NoDestructor<base::flat_set<std::string>> kComponentIds({
Copy link
Member

Choose a reason for hiding this comment

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

can it just be base::MakeFixedFlatSet<std::string_view>{...}? everything here should be constexpr.

the function can also receive std::string_view instead of std::string.


// static
mojo::PendingRemote<mojom::WebcompatReporterHandler>
WebcompatReporterServiceFactory::GetMojoReportHandlerForContext(
Copy link
Member

Choose a reason for hiding this comment

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

hm.. let's actually call it GetHandlerForContext.

format: "%@ (%@)",
AppInfo.appVersion,
AppInfo.buildNumber
),
Copy link
Member

Choose a reason for hiding this comment

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

ah, I see it's filled later in WebcompatReporter.swift. Not sure why those are separated.. maybe everything can be filled in one place?

private static var currentLanguageCode: String? {
return Locale.current.language.languageCode?.identifier
}
public class WebcompatReporterUploader {
Copy link
Member

Choose a reason for hiding this comment

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

do we need this class at all? can't we just call

      privateMode: false
    )!
    webcompatReporterAPI.submitWebcompatReport

in the frontend?

Copy link
Collaborator

@StephenHeaps StephenHeaps left a comment

Choose a reason for hiding this comment

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

iOS just needs a format for presubmit check, but lgtm 👍.

Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
…d to add unittests

Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
vadimstruts and others added 20 commits October 21, 2024 11:44
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: vadym <vadym@vadyms-iMac-Pro.local>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
Signed-off-by: Vadym Struts <vstruts@brave.com>
@vadimstruts vadimstruts force-pushed the 35674-include-component-versions-webcompat-reports branch from 45ae0dd to 396c47c Compare October 21, 2024 09:45
Copy link
Contributor

[puLL-Merge] - brave/brave-core@25688

Description

This pull request implements a new WebcompatReporterService for reporting web compatibility issues in Brave browser. It adds functionality to submit reports about website issues, including details about the browser's configuration and any user-provided information. The implementation spans across Android, iOS, and desktop platforms.

Changes

Changes

  1. android/brave_java_sources.gni:

    • Added a new Java source file for WebcompatReporterServiceFactory.
  2. android/java/org/chromium/chrome/browser/shields/BraveShieldsHandler.java:

    • Integrated the new WebcompatReporterHandler for submitting reports.
    • Removed AsyncTask usage and replaced it with the new service.
  3. android/java/org/chromium/chrome/browser/webcompat_reporter/WebcompatReporterServiceFactory.java:

    • Added a new file to create and manage WebcompatReporterHandler instances.
  4. browser/browser_context_keyed_service_factories.cc:

    • Added WebcompatReporterServiceFactory to the list of service factories.
  5. browser/sources.gni:

    • Included new webcompat reporter sources and dependencies.
  6. browser/ui/BUILD.gn:

    • Added dependency on the new webcompat reporter mojom.
  7. browser/ui/webui/webcompat_reporter/webcompat_reporter_ui.cc:

    • Updated to use the new WebcompatReporterService for report submission.
  8. browser/webcompat_reporter/:

    • Added new files for the WebcompatReporterService implementation, including service delegate and factory.
  9. components/webcompat_reporter/browser/:

    • Updated and added files for the core implementation of the WebcompatReporterService.
  10. components/webcompat_reporter/common/:

    • Added new mojom file defining the WebcompatReporterHandler interface.
  11. ios/:

    • Added implementations specific to iOS for the WebcompatReporterService.
  12. test/BUILD.gn:

    • Added unit tests for the new webcompat reporter component.

Possible Issues

  1. The removal of NTPBackgroundImagesBridge in the Android implementation might affect functionality related to New Tab Page background images.
  2. The change from AsyncTask to the new service in Android might introduce threading issues if not properly managed.

Security Hotspots

  1. The handling of user-provided data in report submissions should be carefully reviewed to ensure proper sanitization and to prevent potential injection attacks.
  2. The use of API keys and sensitive browser information in reports should be audited to ensure no unnecessary data exposure.

This PR significantly refactors the web compatibility reporting system in Brave, centralizing the functionality and making it more consistent across platforms. It also introduces a more modular and maintainable architecture for handling these reports.

Signed-off-by: Vadym Struts <vstruts@brave.com>
@vadimstruts vadimstruts merged commit e7bec70 into master Oct 21, 2024
17 checks passed
@vadimstruts vadimstruts deleted the 35674-include-component-versions-webcompat-reports branch October 21, 2024 15:33
@github-actions github-actions bot added this to the 1.73.x - Nightly milestone Oct 21, 2024
@brave-builds
Copy link
Collaborator

Released in v1.73.31

Comment on lines +52 to +66
KeyedService* WebcompatReporterServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
auto* default_storage_partition = context->GetDefaultStoragePartition();
if (!default_storage_partition) {
return nullptr;
}

auto report_uploader = std::make_unique<WebcompatReportUploader>(
default_storage_partition->GetURLLoaderFactoryForBrowserProcess());
return new WebcompatReporterService(
std::make_unique<WebcompatReporterServiceDelegateImpl>(
g_browser_process->component_updater(),
g_brave_browser_process->ad_block_service()),
std::move(report_uploader));
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

BuildServiceInstanceFor has been deprecated for a while now, and all instances of it in brave have been removed in the past. This PR has introduced a new case though. Leaving a comment to as a PSA.

[1] https://issues.chromium.org/issues/40249337
[2] #25833

@bsclifton bsclifton modified the milestones: 1.73.x - Nightly, 1.74.x - Nightly Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Include component versions in webcompat reports
7 participants