static async compute_(data, context) {
    const {trace, devtoolsLog} = data;
    const networkRecords = await NetworkRecords.request(devtoolsLog, context);
    const processedNavigation = await ProcessedNavigation.request(trace, context);
    if (processedNavigation.timings.largestContentfulPaint === undefined) {
      throw new LighthouseError(LighthouseError.errors.NO_LCP);
    }

    // Use main-frame-only LCP to match the metric value.
    const lcpEvent = processedNavigation.largestContentfulPaintEvt;
    if (!lcpEvent) return;

    const lcpImagePaintEvent = trace.traceEvents.filter(e => {
      return e.name === 'LargestImagePaint::Candidate' &&
          e.args.frame === lcpEvent.args.frame &&
          e.args.data?.DOMNodeId === lcpEvent.args.data?.nodeId &&
          e.args.data?.size === lcpEvent.args.data?.size;
    // Get last candidate, in case there was more than one.
    }).sort((a, b) => b.ts - a.ts)[0];

    const lcpUrl = lcpImagePaintEvent?.args.data?.imageUrl;
    if (!lcpUrl) return;

    const candidates = networkRecords.filter(record => {
      return record.url === lcpUrl &&
          record.finished &&
          // Same frame as LCP trace event.
          record.frameId === lcpImagePaintEvent.args.frame &&
          record.networkRequestTime < (processedNavigation.timestamps.largestContentfulPaint || 0);
    }).map(record => {
      // Follow any redirects to find the real image request.
      while (record.redirectDestination) {
        record = record.redirectDestination;
      }
      return record;
    }).filter(record => {
      // Don't select if also loaded by some other means (xhr, etc). `resourceType`
      // isn't set on redirect _sources_, so have to check after following redirects.
      return record.resourceType === 'Image';
    });

    // If there are still multiple candidates, at this point it appears the page
    // simply made multiple requests for the image. The first loaded is the best
    // guess of the request that made the image available for use.
    return candidates.sort((a, b) => a.networkEndTime - b.networkEndTime)[0];
  }
@param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog}} data
@param {LH.Artifacts.ComputedContext} context
@return {Promise<LH.Artifacts.NetworkRequest|undefined>}