You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have modified the performance bookmarklet so that it runs within an iframe with it's own security sandbox (so that the code is only loaded as needed, and so I don't need to audit your code much!). The performance data is passed from the "host" document to the "guest" iframe using sendMessage.
I have attached the code here to give an idea of the changes, although it would need a few hours work for anyone to use.
The function to show the performance metrics (e.g. connected to a button), run from the "host" document is:
function showTiming() {
function objectify(object) {
return JSON.parse(JSON.stringify(object));
}
var performance = window.performance;
if (!performance || !performance.getEntriesByType) return;
var perf = {
resources: objectify(performance.getEntriesByType('resource')),
marks: objectify(performance.getEntriesByType('mark')),
measures: objectify(performance.getEntriesByType('measure')),
timing: objectify(performance.timing),
navigation: objectify(performance.navigation)
};
var html = '<script src="https://some.domain.here/performance-bookmarklet.js"></script>';
var secondBody = document.createElement('body');
secondBody.innerHTML = '<iframe class=nobox frameborder=0 src="about:blank"></iframe>';
var iframe = secondBody.firstChild;
if ('srcdoc' in iframe) {
iframe.setAttribute('sandbox', 'allow-scripts');
iframe.setAttribute('referrerpolicy', 'no-referrer');
iframe.srcdoc = html;
} else { // srcdoc not IE but will be introduced in Edge 18
setTimeout(function() { // IE needs iframe to be in document so use postpone
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(html);
iframeDoc.close();
}, 0);
}
iframe.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;z-index:10000;';
iframe.onload = function() {
iframe.contentWindow.postMessage(perf, '*');
iframe.onload = null;
};
var closeButton = document.createElement('button');
closeButton.textContent = 'close';
closeButton.style.cssText = 'position:fixed;top:20px;left:20px;z-index:10001;background-color:#BBF;';
closeButton.onclick = function() {
document.body.style.overflow = '';
document.documentElement.removeChild(secondBody);
}
secondBody.appendChild(closeButton);
document.body.style.overflow = 'hidden';
document.documentElement.appendChild(secondBody); // looks odd, but html spec does allow multiple body elements
}
I edited the compiled performance-bookmarklet.js (Yes this is a very dirty technique. Done because I didn't want to edit source code as then I would need to run your build process which would have taken me more time and I needed the code to work with our custom build process).
We put the following code around the performance-bookmarklet.js code (dirty: monkey patches window.performance to read the local data)
(function () {
function go(perf) {
window.performance = {
timing: perf.timing,
navigation: perf.navigation,
getEntriesByType: function(type){
if (type == "resource") {
return perf.resources;
} else if (type == 'mark') {
return perf.marks;
} else if (type == "measure") {
return perf.measures;
}
}
};
execBookmarklet(withinIframe);
window.performance = null;
}
if (window.doubleLoad) {
return;
}
window.doubleLoad = 1;
var withinIframe = window.top !== window.self;
if (withinIframe) {
window.onmessage = function(event) {
var perf = event.data;
if (perf.resources) {
go(perf);
}
};
} else { // Called by 'Timing Graph Debug'
var objectify = function(object) {
return JSON.parse(JSON.stringify(object));
}
go({
resources: objectify(window.performance.getEntriesByType("resource")), // JSON.parse(JSON.stringify(window.performance.getEntriesByType("resource")))
marks: objectify(window.performance.getEntriesByType("mark")),
measures: objectify(window.performance.getEntriesByType("measure")),
timing: objectify(window.performance.timing),
navigation: objectify(window.performance.navigation)
});
}
// put copyright into a string stored on an object so that the copyright isn't removed during compression
execBookmarklet.copyright = 'Copyright 2014 Michael Mrowetz. MIT License: https://github.com/micmro/performance-bookmarklet/blob/d3e037620270419521eab20bf479c51c8ea72d96/LICENSE';
function execBookmarklet(withinIframe) {
// INSERT BOOKMARKLET CODE HERE
}
})();
The BOOKMARKLET CODE itself also has a few modifications.
Don't read localStorage (causes exception):
if (!withinIframe)
var persistanceEnabled = !!JSON.parse(localStorage.getItem(storageKey));
Change the IFrameHolder code:
iFrameHolder.getOutputIFrame = function () {
return outputIFrame;
};
module.exports = iFrameHolder;
if (withinIframe) {
module.exports = {
setup: function (onIFrameReady) {
function addComponent(domEl) {
document.body.appendChild(domEl);
}
var styleTag = dom.newTag("style", {
type: "text/css",
text: style
});
document.head.appendChild(styleTag);
var outputHolder = dom.newTag("div", { id: "perfbook-holder" });
var outputContent = dom.newTag("div", { id: "perfbook-content" });
outputHolder.appendChild(outputContent);
document.body.appendChild(outputHolder);
onIFrameReady(addComponent);
},
getOutputIFrame: function(){
return document;
}
};
}
Add connection details (very important for HTTP2 connection versus HTTP1.1 connection):
var connection = navigator.connection;
if (connection) {
createAppendixDefValue(appendix, dom.newTag("abbr", { title: "Connection", text: "navigator.connection.*" }), "");
for (var key in connection) {
var value = connection[key];
if (value && typeof value != "function") {
createAppendixDefValue(appendix, dom.newTextNode("\xa0\xa0" + key + ":"), value);
}
}
}
tilesHolder.appendChild(appendix);
return tilesHolder;
Dont check for about: protocol:
if (withinIframe) {
if (!data.isValid()) {
return;
}
} else {
if (location.protocol === "about:" || !data.isValid()) {
return;
}
}
Commented out dead code:
// window.outputContent;
The final change was to remove the negative right margins (replaced -18px and -72px with 0 in the css style).
I have written this issue so that if anyone else wants to use your code others can branch and build on these snippets. Hopefully it is useful to someone so maybe just leave the issue open?!
I really really appreciate your code - it still works beautifully (2019).
The text was updated successfully, but these errors were encountered:
Hi @MorrisJohns
thanks a lot for your work.
I will give it a proper review and update the code accordingly, but because I am moving countries in the moment I will unfortunately need another few weeks before I will get the time for this.
I have modified the performance bookmarklet so that it runs within an iframe with it's own security sandbox (so that the code is only loaded as needed, and so I don't need to audit your code much!). The performance data is passed from the "host" document to the "guest" iframe using sendMessage.
I have attached the code here to give an idea of the changes, although it would need a few hours work for anyone to use.
The function to show the performance metrics (e.g. connected to a button), run from the "host" document is:
I edited the compiled performance-bookmarklet.js (Yes this is a very dirty technique. Done because I didn't want to edit source code as then I would need to run your build process which would have taken me more time and I needed the code to work with our custom build process).
We put the following code around the performance-bookmarklet.js code (dirty: monkey patches window.performance to read the local data)
The BOOKMARKLET CODE itself also has a few modifications.
Don't read localStorage (causes exception):
Change the IFrameHolder code:
Add connection details (very important for HTTP2 connection versus HTTP1.1 connection):
Dont check for
about:
protocol:Commented out dead code:
The final change was to remove the negative right margins (replaced
-18px
and-72px
with 0 in the css style).I have written this issue so that if anyone else wants to use your code others can branch and build on these snippets. Hopefully it is useful to someone so maybe just leave the issue open?!
I really really appreciate your code - it still works beautifully (2019).
The text was updated successfully, but these errors were encountered: