Repository: servo/servo
File: components/script/security_manager.rs (Rust)

Code before:
                // Step 3.4.2.2. If endpoint is not a valid URL, skip the remaining substeps.
                continue;
            };
            // Step 3.4.2.3. Let request be a new request, initialized as follows:
            let mut headers = HeaderMap::with_capacity(1);
            headers.typed_insert(ContentType::from(
                "application/csp-report".parse::<mime::Mime>().unwrap(),
            ));
            println!("Reporting to {}", endpoint.to_string());
            let request = create_a_potential_cors_request(
                None,
                endpoint.clone(),
                csp::Destination::Report,
                None,
                None,
                global.get_referrer(),
                global.insecure_requests_policy(),
                global.has_trustworthy_ancestor_or_current_origin(),
                global.policy_container(),
            )
            .method(http::Method::POST)
            .origin(global.origin().immutable().clone())
            .credentials_mode(CredentialsMode::CredentialsSameOrigin)
            .headers(headers);
            // TODO: Set body to the result of https://www.w3.org/TR/CSP/#deprecated-serialize-violation
            // using serialize_jsval_to_json_utf8
            // Step 3.4.2.4. Fetch request. The result will be ignored.
            global.fetch(
                request,
                Arc::new(Mutex::new(CSPReportUriFetchListener {
                    endpoint,
                    global: Trusted::new(global),
                    resource_timing: ResourceFetchTiming::new(ResourceTimingType::None),
                })),
                global.task_manager().networking_task_source().into(),
            );
        }
    }
}

/// Corresponds to the operation in 5.5 Report Violation
/// <https://w3c.github.io/webappsec-csp/#report-violation>
/// > Queue a task to run the following steps:
impl TaskOnce for CSPViolationReportTask {
    fn run_once(self) {
        let global = &self.global.root();
        let violation_policy = &self.violation_policy.clone();
        // > If target implements EventTarget, fire an event named securitypolicyviolation
        // > that uses the SecurityPolicyViolationEvent interface
        // > at target with its attributes initialized as follows:
        self.fire_violation_event(CanGc::note());

Review comment (suggestion):
@jdm Can you help me out here? I need to construct a map here (that represent a JSON Object), populate with a couple of fields and then I need to call `JSON.stringify` on it. I see that `serialize_jsval_to_json_utf8` does most of the heavy lifting, but it takes a `HandleValue`. Therefore, I think I need to construct a `HandleObject` myself and set the fields using JS Rust API's.

These API's are still a bit magic to me, so I am struggling to peace these together. Can you provide me a code snippet to get things going on how I can construct such a map? Thanks!

Code after:
        };
        // Step 4. Return the result of serialize an infra value to JSON bytes given «[ "csp-report" → body ]».
        Some(create_request_body_with_content(
            &serde_json::to_string(&report_body).unwrap_or("".to_owned()),
        ))
    }

    /// Step 3.4 of <https://www.w3.org/TR/CSP/#report-violation>
    fn post_csp_violation_to_report_uri(&self, report_uri_directive: &csp::Directive) {
        let global = self.global.root();
        // Step 3.4.1. If violation’s policy’s directive set contains a directive named
        // "report-to", skip the remaining substeps.
        if self
            .violation_policy
            .contains_a_directive_whose_name_is("report-to")
        {
            return;
        }
        // Step 3.4.2. For each token of directive’s value:
        for token in &report_uri_directive.value {
            // Step 3.4.2.1. Let endpoint be the result of executing the URL parser with token as the input,
            // and violation’s url as the base URL.
            let Ok(endpoint) = ServoUrl::parse_with_base(Some(&global.get_url()), token) else {
                // Step 3.4.2.2. If endpoint is not a valid URL, skip the remaining substeps.
                continue;
            };
            // Step 3.4.2.3. Let request be a new request, initialized as follows:
            let mut headers = HeaderMap::with_capacity(1);
            headers.typed_insert(ContentType::from(
                "application/csp-report".parse::<mime::Mime>().unwrap(),
            ));
            let request_body = self.serialize_violation();
            let request = create_a_potential_cors_request(
                None,
                endpoint.clone(),
                csp::Destination::Report,
                None,
                None,
                global.get_referrer(),
                global.insecure_requests_policy(),
                global.has_trustworthy_ancestor_or_current_origin(),
                global.policy_container(),
            )
            .method(http::Method::POST)
            .body(request_body)
            .origin(global.origin().immutable().clone())
            .credentials_mode(CredentialsMode::CredentialsSameOrigin)
            .headers(headers);
            // Step 3.4.2.4. Fetch request. The result will be ignored.
            global.fetch(
                request,