diff --git a/lib/harAnalyzer.js b/lib/harAnalyzer.js index 9cdff66..7074f09 100644 --- a/lib/harAnalyzer.js +++ b/lib/harAnalyzer.js @@ -149,18 +149,51 @@ export class HarAnalyzer { // HAR -> simplified data // --------------------------------------------------------------------------- - transform2SimplifiedData(harData, navUrl) { - const data = { url: navUrl, primary: null, htmls: [] }; - + getFirstPageEntries(navUrl, harData) { let log = harData; if (log && 'log' in log) { log = log.log; } if (!log || !Array.isArray(log.entries)) { - return data; + return []; + } + const entries = log.entries; + + // A HAR can contain more than one page, for example when a concurrent + // browsertime run ends up in the same browser session (crossed DevTools + // port) and navigates to another website mid-recording. Requests made + // by other pages must not be attributed to the tested website, and if + // the recording doesn't even start with the navigated url's host nothing + // in it can be trusted. + if (navUrl && entries.length > 0) { + const firstUrl = entries[0].request && entries[0].request.url; + if (firstUrl) { + try { + if (new URL(firstUrl).hostname !== new URL(navUrl).hostname) { + return []; + } + } catch { + // Unparsable URLs are handled by the entry loops as before + } + } } - for (const entry of log.entries) { + const pages = log.pages; + if (!Array.isArray(pages) || pages.length === 0) { + return entries; + } + const firstPageId = pages[0].id; + if (firstPageId === undefined) { + return entries; + } + return entries.filter(entry => + entry.pageref === undefined || entry.pageref === firstPageId); + } + + transform2SimplifiedData(harData, navUrl) { + const data = { url: navUrl, primary: null, htmls: [] }; + + for (const entry of this.getFirstPageEntries(navUrl, harData)) { const req = entry.request || {}; const res = entry.response || {}; const content = res.content || {};