Skip to content

Commit

Permalink
misc(treemap): support passing data in url (#12509)
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark authored May 19, 2021
1 parent 545176a commit 5f358c4
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
56 changes: 49 additions & 7 deletions lighthouse-core/report/html/renderer/report-ui-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ class ReportUIFeatures {

const showTreemapApp =
this.json.audits['script-treemap-data'] && this.json.audits['script-treemap-data'].details;
// TODO: need window.opener to work in DevTools.
if (showTreemapApp && !this._dom.isDevTools()) {
if (showTreemapApp) {
this.addButton({
text: Util.i18n.strings.viewTreemapLabel,
icon: 'treemap',
onClick: () => ReportUIFeatures.openTreemap(this.json),
onClick: () => ReportUIFeatures.openTreemap(
this.json, this._dom.isDevTools() ? 'url' : 'postMessage'),
});
}

Expand Down Expand Up @@ -548,20 +548,36 @@ class ReportUIFeatures {
/**
* Opens a new tab to the treemap app and sends the JSON results using postMessage.
* @param {LH.Result} json
* @param {'postMessage'|'url'} method
* @protected
*/
static openTreemap(json) {
static openTreemap(json, method = 'postMessage') {
const treemapData = json.audits['script-treemap-data'].details;
if (!treemapData) {
throw new Error('no script treemap data found');
}

const windowName = `treemap-${json.requestedUrl}`;
/** @type {LH.Treemap.Options} */
const treemapOptions = {
lhr: json,
lhr: {
requestedUrl: json.requestedUrl,
finalUrl: json.finalUrl,
audits: {
'script-treemap-data': json.audits['script-treemap-data'],
},
configSettings: {
locale: json.configSettings.locale,
},
},
};
const url = getAppsOrigin() + '/treemap/';
ReportUIFeatures.openTabAndSendData(treemapOptions, url, windowName);
const windowName = `treemap-${json.requestedUrl}`;

if (method === 'postMessage') {
ReportUIFeatures.openTabAndSendData(treemapOptions, url, windowName);
} else {
ReportUIFeatures.openTabWithUrlData(treemapOptions, url, windowName);
}
}

/**
Expand Down Expand Up @@ -591,6 +607,32 @@ class ReportUIFeatures {
const popup = window.open(url, windowName);
}

/**
* Opens a new tab to an external page and sends data via base64 encoded url params.
* @param {{lhr: LH.Result} | LH.Treemap.Options} data
* @param {string} url_
* @param {string} windowName
* @protected
*/
static openTabWithUrlData(data, url_, windowName) {
const url = new URL(url_);
url.hash = toBinary(JSON.stringify(data));

// The popup's window.name is keyed by version+url+fetchTime, so we reuse/select tabs correctly
window.open(url.toString(), windowName);

/**
* @param {string} string
*/
function toBinary(string) {
const codeUnits = new Uint16Array(string.length);
for (let i = 0; i < codeUnits.length; i++) {
codeUnits[i] = string.charCodeAt(i);
}
return btoa(String.fromCharCode(...new Uint8Array(codeUnits.buffer)));
}
}

/**
* Expands all audit `<details>`.
* Ideally, a print stylesheet could take care of this, but CSS has no way to
Expand Down
30 changes: 29 additions & 1 deletion lighthouse-treemap/app/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -734,13 +734,41 @@ function showError(message) {
document.body.textContent = message;
}

/**
* @param {string} encoded
*/
function fromBinary(encoded) {
const binary = atob(encoded);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return String.fromCharCode(...new Uint16Array(bytes.buffer));
}

async function main() {
/** @type {Record<string, any>} */
let params = {};
if (Object.fromEntries) {
const queryParams = new URLSearchParams(window.location.search);
const hashParams = location.hash ? JSON.parse(fromBinary(location.hash.substr(1))) : {};
params = {
...Object.fromEntries(queryParams.entries()),
...hashParams,
};
}

if (window.__treemapOptions) {
// Prefer the hardcoded options from a saved HTML file above all.
init(window.__treemapOptions);
} else if (new URLSearchParams(window.location.search).has('debug')) {
} else if ('debug' in params) {
const response = await fetch('debug.json');
init(await response.json());
} else if (params.lhr) {
const options = {
lhr: params.lhr,
};
init(options);
} else {
window.addEventListener('message', e => {
if (e.source !== self.opener) return;
Expand Down
11 changes: 10 additions & 1 deletion types/treemap.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@
declare global {
module LH.Treemap {
interface Options {
lhr: LH.Result;
lhr: {
requestedUrl: string;
finalUrl: string;
audits: {
'script-treemap-data': LH.Audit.Result;
};
configSettings: {
locale: LH.Locale;
}
}
}

type NodePath = string[];
Expand Down

0 comments on commit 5f358c4

Please sign in to comment.