UNPKG

chrome-devtools-frontend

Version:
114 lines (97 loc) 4.81 kB
// Copyright 2024 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../core/i18n/i18n.js'; import * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js'; import * as Extras from '../extras/extras.js'; import * as Handlers from '../handlers/handlers.js'; import * as Helpers from '../helpers/helpers.js'; import type * as Types from '../types/types.js'; import { InsightCategory, type InsightModel, type InsightSetContext, type PartialInsightModel, type RequiredData } from './types.js'; export const UIStrings = { /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as "third-party code"). */ title: 'Third parties', /** * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control. * This is displayed after a user expands the section to see more. No character length limits. */ description: 'Third party code can significantly impact load performance. ' + '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\'s content.', /** Label for a table column that displays the name of a third-party provider. */ columnThirdParty: 'Third party', /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */ columnTransferSize: 'Transfer size', /** Label for a table column that displays how much time each row spent running on the main thread, entries will be the number of milliseconds spent. */ columnMainThreadTime: 'Main thread time', /** * @description Text block indicating that no third party content was detected on the page */ noThirdParties: 'No third parties found', }; const str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings); export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] { return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting']; } export type ThirdPartiesInsightModel = InsightModel<typeof UIStrings, { eventsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.Event[]>, summaryByEntity: Map<Extras.ThirdParties.Entity, Extras.ThirdParties.Summary>, summaryByUrl: Map<string, Extras.ThirdParties.Summary>, urlsByEntity: Map<Extras.ThirdParties.Entity, Set<string>>, /** The entity for this navigation's URL. Any other entity is from a third party. */ firstPartyEntity?: Extras.ThirdParties.Entity, }>; function getRelatedEvents( summaries: Extras.ThirdParties.ThirdPartySummary, firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] { const relatedEvents = []; for (const [entity, events] of summaries.eventsByEntity.entries()) { if (entity !== firstPartyEntity) { relatedEvents.push(...events); } } return relatedEvents; } function finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>): ThirdPartiesInsightModel { return { strings: UIStrings, title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), category: InsightCategory.ALL, state: [...partialModel.summaryByEntity.entries()].find(kv => kv[0] !== partialModel.firstPartyEntity) ? 'informative' : 'pass', ...partialModel, }; } export function generateInsight( parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartiesInsightModel { const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => { if (!context.navigation) { return false; } if (event.args.data.frame !== context.frameId) { return false; } return Helpers.Timing.eventIsInBounds(event, context.bounds); }); const thirdPartySummary = Extras.ThirdParties.summarizeThirdParties( parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests); const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL; const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || Handlers.Helpers.makeUpEntity(thirdPartySummary.madeUpEntityCache, firstPartyUrl); return finalize({ relatedEvents: getRelatedEvents(thirdPartySummary, firstPartyEntity), eventsByEntity: thirdPartySummary.eventsByEntity, summaryByEntity: thirdPartySummary.byEntity, summaryByUrl: thirdPartySummary.byUrl, urlsByEntity: thirdPartySummary.urlsByEntity, firstPartyEntity, }); }