OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * Copyright (C) 2012 Intel Inc. All rights reserved. | 3 * Copyright (C) 2012 Intel Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 | 738 |
739 /** | 739 /** |
740 * @return {boolean} | 740 * @return {boolean} |
741 */ | 741 */ |
742 containsTime: function(time) | 742 containsTime: function(time) |
743 { | 743 { |
744 return this.startTime <= time && time <= this.endTime; | 744 return this.startTime <= time && time <= this.endTime; |
745 }, | 745 }, |
746 | 746 |
747 /** | 747 /** |
748 * @param {!WebInspector.TimelinePresentationModel.Record} record | |
749 * @param {!WebInspector.Linkifier} linkifier | |
750 * @param {function(!DocumentFragment)} callback | |
751 */ | |
752 generatePopupContent: function(record, linkifier, callback) | |
753 { | |
754 var imageElement = /** @type {?Element} */ (record.getUserObject("Timeli
nePresentationModel::preview-element") || null); | |
755 var relatedNode = /** @type {?WebInspector.DOMNode} */ (record.getUserOb
ject("TimelinePresentationModel::related-node") || null); | |
756 | |
757 var barrier = new CallbackBarrier(); | |
758 if (!imageElement && WebInspector.TimelineUIUtils.needsPreviewElement(re
cord.type)) | |
759 WebInspector.DOMPresentationUtils.buildImagePreviewContents(record.u
rl, false, barrier.createCallback(saveImage)); | |
760 if (!relatedNode && record.relatedBackendNodeId()) | |
761 WebInspector.domAgent.pushNodeByBackendIdToFrontend(record.relatedBa
ckendNodeId(), barrier.createCallback(saveNode)); | |
762 barrier.callWhenDone(callbackWrapper.bind(this)); | |
763 | |
764 /** | |
765 * @param {!Element=} element | |
766 */ | |
767 function saveImage(element) | |
768 { | |
769 imageElement = element || null; | |
770 record.setUserObject("TimelinePresentationModel::preview-element", e
lement); | |
771 } | |
772 | |
773 /** | |
774 * @param {?DOMAgent.NodeId} nodeId | |
775 */ | |
776 function saveNode(nodeId) | |
777 { | |
778 if (nodeId !== null) { | |
779 relatedNode = WebInspector.domAgent.nodeForId(nodeId); | |
780 record.setUserObject("TimelinePresentationModel::related-node",
relatedNode); | |
781 } | |
782 } | |
783 | |
784 /** | |
785 * @this {WebInspector.TimelinePresentationModel.Record} | |
786 */ | |
787 function callbackWrapper() | |
788 { | |
789 callback(this._generatePopupContentSynchronously(record, linkifier,
imageElement, relatedNode)); | |
790 } | |
791 }, | |
792 | |
793 /** | |
794 * @param {string} key | 748 * @param {string} key |
795 * @return {?Object} | 749 * @return {?Object} |
796 */ | 750 */ |
797 getUserObject: function(key) | 751 getUserObject: function(key) |
798 { | 752 { |
799 if (!this._userObjects) | 753 if (!this._userObjects) |
800 return null; | 754 return null; |
801 return this._userObjects.get(key); | 755 return this._userObjects.get(key); |
802 }, | 756 }, |
803 | 757 |
804 /** | 758 /** |
805 * @param {string} key | 759 * @param {string} key |
806 * @param {?Object|undefined} value | 760 * @param {?Object|undefined} value |
807 */ | 761 */ |
808 setUserObject: function(key, value) | 762 setUserObject: function(key, value) |
809 { | 763 { |
810 if (!this._userObjects) | 764 if (!this._userObjects) |
811 this._userObjects = new StringMap(); | 765 this._userObjects = new StringMap(); |
812 this._userObjects.put(key, value); | 766 this._userObjects.put(key, value); |
813 }, | 767 }, |
814 | 768 |
815 /** | 769 /** |
816 * @return {number} nodeId | 770 * @return {number} nodeId |
817 */ | 771 */ |
818 relatedBackendNodeId: function() | 772 relatedBackendNodeId: function() |
819 { | 773 { |
820 return this._relatedBackendNodeId; | 774 return this._relatedBackendNodeId; |
821 }, | 775 }, |
822 | 776 |
823 /** | |
824 * @param {!WebInspector.TimelinePresentationModel.Record} record | |
825 * @param {!WebInspector.Linkifier} linkifier | |
826 * @param {?Element} imagePreviewElement | |
827 * @param {?WebInspector.DOMNode} relatedNode | |
828 * @return {!DocumentFragment} | |
829 */ | |
830 _generatePopupContentSynchronously: function(record, linkifier, imagePreview
Element, relatedNode) | |
831 { | |
832 var fragment = document.createDocumentFragment(); | |
833 if (!record.coalesced && record.children.length) | |
834 fragment.appendChild(WebInspector.TimelineUIUtils.generatePieChart(r
ecord.aggregatedStats, record.category, record.selfTime)); | |
835 else | |
836 fragment.appendChild(WebInspector.TimelineUIUtils.generatePieChart(r
ecord.aggregatedStats)); | |
837 | |
838 if (record.coalesced) | |
839 return fragment; | |
840 | |
841 const recordTypes = WebInspector.TimelineModel.RecordType; | |
842 | |
843 // The messages may vary per record type; | |
844 var callSiteStackTraceLabel; | |
845 var callStackLabel; | |
846 var relatedNodeLabel; | |
847 | |
848 var contentHelper = new WebInspector.TimelineDetailsContentHelper(linkif
ier, true); | |
849 contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.m
illisToString(record.selfTime, true)); | |
850 contentHelper.appendTextRow(WebInspector.UIString("Start Time"), Number.
millisToString(record.startTimeOffset)); | |
851 | |
852 switch (record.type) { | |
853 case recordTypes.GCEvent: | |
854 contentHelper.appendTextRow(WebInspector.UIString("Collected"),
Number.bytesToString(record.data["usedHeapSizeDelta"])); | |
855 break; | |
856 case recordTypes.TimerFire: | |
857 callSiteStackTraceLabel = WebInspector.UIString("Timer installed
"); | |
858 // Fall-through intended. | |
859 | |
860 case recordTypes.TimerInstall: | |
861 case recordTypes.TimerRemove: | |
862 contentHelper.appendTextRow(WebInspector.UIString("Timer ID"), r
ecord.data["timerId"]); | |
863 if (typeof record.timeout === "number") { | |
864 contentHelper.appendTextRow(WebInspector.UIString("Timeout")
, Number.millisToString(record.timeout)); | |
865 contentHelper.appendTextRow(WebInspector.UIString("Repeats")
, !record.singleShot); | |
866 } | |
867 break; | |
868 case recordTypes.FireAnimationFrame: | |
869 callSiteStackTraceLabel = WebInspector.UIString("Animation frame
requested"); | |
870 contentHelper.appendTextRow(WebInspector.UIString("Callback ID")
, record.data["id"]); | |
871 break; | |
872 case recordTypes.FunctionCall: | |
873 if (record.scriptName) | |
874 contentHelper.appendLocationRow(WebInspector.UIString("Locat
ion"), record.scriptName, record.scriptLine); | |
875 break; | |
876 case recordTypes.ScheduleResourceRequest: | |
877 case recordTypes.ResourceSendRequest: | |
878 case recordTypes.ResourceReceiveResponse: | |
879 case recordTypes.ResourceReceivedData: | |
880 case recordTypes.ResourceFinish: | |
881 contentHelper.appendElementRow(WebInspector.UIString("Resource")
, WebInspector.linkifyResourceAsNode(record.url)); | |
882 if (imagePreviewElement) | |
883 contentHelper.appendElementRow(WebInspector.UIString("Previe
w"), imagePreviewElement); | |
884 if (record.data["requestMethod"]) | |
885 contentHelper.appendTextRow(WebInspector.UIString("Request M
ethod"), record.data["requestMethod"]); | |
886 if (typeof record.data["statusCode"] === "number") | |
887 contentHelper.appendTextRow(WebInspector.UIString("Status Co
de"), record.data["statusCode"]); | |
888 if (record.data["mimeType"]) | |
889 contentHelper.appendTextRow(WebInspector.UIString("MIME Type
"), record.data["mimeType"]); | |
890 if (record.data["encodedDataLength"]) | |
891 contentHelper.appendTextRow(WebInspector.UIString("Encoded D
ata Length"), WebInspector.UIString("%d Bytes", record.data["encodedDataLength"]
)); | |
892 break; | |
893 case recordTypes.EvaluateScript: | |
894 if (record.data && record.url) | |
895 contentHelper.appendLocationRow(WebInspector.UIString("Scrip
t"), record.url, record.data["lineNumber"]); | |
896 break; | |
897 case recordTypes.Paint: | |
898 var clip = record.data["clip"]; | |
899 if (clip) { | |
900 contentHelper.appendTextRow(WebInspector.UIString("Location"
), WebInspector.UIString("(%d, %d)", clip[0], clip[1])); | |
901 var clipWidth = WebInspector.TimelinePresentationModel.quadW
idth(clip); | |
902 var clipHeight = WebInspector.TimelinePresentationModel.quad
Height(clip); | |
903 contentHelper.appendTextRow(WebInspector.UIString("Dimension
s"), WebInspector.UIString("%d × %d", clipWidth, clipHeight)); | |
904 } else { | |
905 // Backward compatibility: older version used x, y, width, h
eight fields directly in data. | |
906 if (typeof record.data["x"] !== "undefined" && typeof record
.data["y"] !== "undefined") | |
907 contentHelper.appendTextRow(WebInspector.UIString("Locat
ion"), WebInspector.UIString("(%d, %d)", record.data["x"], record.data["y"])); | |
908 if (typeof record.data["width"] !== "undefined" && typeof re
cord.data["height"] !== "undefined") | |
909 contentHelper.appendTextRow(WebInspector.UIString("Dimen
sions"), WebInspector.UIString("%d\u2009\u00d7\u2009%d", record.data["width"], r
ecord.data["height"])); | |
910 } | |
911 // Fall-through intended. | |
912 | |
913 case recordTypes.PaintSetup: | |
914 case recordTypes.Rasterize: | |
915 case recordTypes.ScrollLayer: | |
916 relatedNodeLabel = WebInspector.UIString("Layer root"); | |
917 break; | |
918 case recordTypes.AutosizeText: | |
919 relatedNodeLabel = WebInspector.UIString("Root node"); | |
920 break; | |
921 case recordTypes.DecodeImage: | |
922 case recordTypes.ResizeImage: | |
923 relatedNodeLabel = WebInspector.UIString("Image element"); | |
924 if (record.url) | |
925 contentHelper.appendElementRow(WebInspector.UIString("Image
URL"), WebInspector.linkifyResourceAsNode(record.url)); | |
926 break; | |
927 case recordTypes.RecalculateStyles: // We don't want to see default
details. | |
928 if (record.data["elementCount"]) | |
929 contentHelper.appendTextRow(WebInspector.UIString("Elements
affected"), record.data["elementCount"]); | |
930 callStackLabel = WebInspector.UIString("Styles recalculation for
ced"); | |
931 break; | |
932 case recordTypes.Layout: | |
933 if (record.data["dirtyObjects"]) | |
934 contentHelper.appendTextRow(WebInspector.UIString("Nodes tha
t need layout"), record.data["dirtyObjects"]); | |
935 if (record.data["totalObjects"]) | |
936 contentHelper.appendTextRow(WebInspector.UIString("Layout tr
ee size"), record.data["totalObjects"]); | |
937 if (typeof record.data["partialLayout"] === "boolean") { | |
938 contentHelper.appendTextRow(WebInspector.UIString("Layout sc
ope"), | |
939 record.data["partialLayout"] ? WebInspector.UIString("Par
tial") : WebInspector.UIString("Whole document")); | |
940 } | |
941 callSiteStackTraceLabel = WebInspector.UIString("Layout invalida
ted"); | |
942 callStackLabel = WebInspector.UIString("Layout forced"); | |
943 relatedNodeLabel = WebInspector.UIString("Layout root"); | |
944 break; | |
945 case recordTypes.ConsoleTime: | |
946 contentHelper.appendTextRow(WebInspector.UIString("Message"), re
cord.data["message"]); | |
947 break; | |
948 case recordTypes.WebSocketCreate: | |
949 case recordTypes.WebSocketSendHandshakeRequest: | |
950 case recordTypes.WebSocketReceiveHandshakeResponse: | |
951 case recordTypes.WebSocketDestroy: | |
952 if (typeof record.webSocketURL !== "undefined") | |
953 contentHelper.appendTextRow(WebInspector.UIString("URL"), re
cord.webSocketURL); | |
954 if (typeof record.webSocketProtocol !== "undefined") | |
955 contentHelper.appendTextRow(WebInspector.UIString("WebSocket
Protocol"), record.webSocketProtocol); | |
956 if (typeof record.data["message"] !== "undefined") | |
957 contentHelper.appendTextRow(WebInspector.UIString("Message")
, record.data["message"]); | |
958 break; | |
959 case recordTypes.EmbedderCallback: | |
960 contentHelper.appendTextRow(WebInspector.UIString("Callback Func
tion"), record.embedderCallbackName); | |
961 break; | |
962 default: | |
963 var detailsNode = record.buildDetailsNode(record, linkifier); | |
964 if (detailsNode) | |
965 contentHelper.appendElementRow(WebInspector.UIString("Detail
s"), detailsNode); | |
966 break; | |
967 } | |
968 | |
969 /** | |
970 * @param {!WebInspector.DOMNode} node | |
971 */ | |
972 function createNodeAnchor(node) | |
973 { | |
974 var span = document.createElement("span"); | |
975 span.classList.add("node-link"); | |
976 span.addEventListener("click", WebInspector.Revealer.reveal.bind(Web
Inspector.Revealer, node, undefined), false); | |
977 WebInspector.DOMPresentationUtils.decorateNodeLabel(node, span); | |
978 return span; | |
979 } | |
980 | |
981 if (relatedNode) | |
982 contentHelper.appendElementRow(relatedNodeLabel || WebInspector.UISt
ring("Related node"), createNodeAnchor(relatedNode)); | |
983 | |
984 if (record.scriptName && record.type !== recordTypes.FunctionCall) | |
985 contentHelper.appendLocationRow(WebInspector.UIString("Function Call
"), record.scriptName, record.scriptLine); | |
986 | |
987 if (record.jsHeapSizeUsed) { | |
988 if (record.usedHeapSizeDelta) { | |
989 var sign = record.usedHeapSizeDelta > 0 ? "+" : "-"; | |
990 contentHelper.appendTextRow(WebInspector.UIString("Used JavaScri
pt Heap Size"), | |
991 WebInspector.UIString("%s (%s%s)", Number.bytesToString(reco
rd.jsHeapSizeUsed), sign, Number.bytesToString(Math.abs(record.usedHeapSizeDelta
)))); | |
992 } else if (record.category === WebInspector.TimelineUIUtils.categori
es().scripting) | |
993 contentHelper.appendTextRow(WebInspector.UIString("Used JavaScri
pt Heap Size"), Number.bytesToString(record.jsHeapSizeUsed)); | |
994 } | |
995 | |
996 if (record.callSiteStackTrace) | |
997 contentHelper.appendStackTrace(callSiteStackTraceLabel || WebInspect
or.UIString("Call Site stack"), record.callSiteStackTrace); | |
998 | |
999 if (record.stackTrace) | |
1000 contentHelper.appendStackTrace(callStackLabel || WebInspector.UIStri
ng("Call Stack"), record.stackTrace); | |
1001 | |
1002 if (record.warnings) { | |
1003 var ul = document.createElement("ul"); | |
1004 for (var i = 0; i < record.warnings.length; ++i) | |
1005 ul.createChild("li").textContent = record.warnings[i]; | |
1006 contentHelper.appendElementRow(WebInspector.UIString("Warning"), ul)
; | |
1007 } | |
1008 fragment.appendChild(contentHelper.element); | |
1009 return fragment; | |
1010 }, | |
1011 | |
1012 /** | |
1013 * @param {!WebInspector.TimelinePresentationModel.Record} record | |
1014 * @param {!WebInspector.Linkifier} linkifier | |
1015 * @return {?Node} | |
1016 */ | |
1017 buildDetailsNode: function(record, linkifier) | |
1018 { | |
1019 var details; | |
1020 var detailsText; | |
1021 if (record.coalesced) { | |
1022 var node = document.createElement("span"); | |
1023 node.textContent = WebInspector.UIString("× %d", record.children.len
gth); | |
1024 return node; | |
1025 } | |
1026 | |
1027 switch (record.type) { | |
1028 case WebInspector.TimelineModel.RecordType.GCEvent: | |
1029 detailsText = WebInspector.UIString("%s collected", Number.bytesToSt
ring(record.data["usedHeapSizeDelta"])); | |
1030 break; | |
1031 case WebInspector.TimelineModel.RecordType.TimerFire: | |
1032 details = linkifyScriptLocation(); | |
1033 detailsText = record.data["timerId"]; | |
1034 break; | |
1035 case WebInspector.TimelineModel.RecordType.FunctionCall: | |
1036 if (record.scriptName) | |
1037 details = linkifyLocation(record.scriptName, record.scriptLine,
0); | |
1038 break; | |
1039 case WebInspector.TimelineModel.RecordType.FireAnimationFrame: | |
1040 details = linkifyScriptLocation(); | |
1041 detailsText = record.data["id"]; | |
1042 break; | |
1043 case WebInspector.TimelineModel.RecordType.EventDispatch: | |
1044 detailsText = record.data ? record.data["type"] : null; | |
1045 break; | |
1046 case WebInspector.TimelineModel.RecordType.Paint: | |
1047 var width = record.data.clip ? WebInspector.TimelinePresentationMode
l.quadWidth(record.data.clip) : record.data.width; | |
1048 var height = record.data.clip ? WebInspector.TimelinePresentationMod
el.quadHeight(record.data.clip) : record.data.height; | |
1049 if (width && height) | |
1050 detailsText = WebInspector.UIString("%d\u2009\u00d7\u2009%d", wi
dth, height); | |
1051 break; | |
1052 case WebInspector.TimelineModel.RecordType.TimerInstall: | |
1053 case WebInspector.TimelineModel.RecordType.TimerRemove: | |
1054 details = linkifyTopCallFrame(); | |
1055 detailsText = record.data["timerId"]; | |
1056 break; | |
1057 case WebInspector.TimelineModel.RecordType.RequestAnimationFrame: | |
1058 case WebInspector.TimelineModel.RecordType.CancelAnimationFrame: | |
1059 details = linkifyTopCallFrame(); | |
1060 detailsText = record.data["id"]; | |
1061 break; | |
1062 case WebInspector.TimelineModel.RecordType.ParseHTML: | |
1063 case WebInspector.TimelineModel.RecordType.RecalculateStyles: | |
1064 details = linkifyTopCallFrame(); | |
1065 break; | |
1066 case WebInspector.TimelineModel.RecordType.EvaluateScript: | |
1067 details = record.url ? linkifyLocation(record.url, record.data["line
Number"], 0) : null; | |
1068 break; | |
1069 case WebInspector.TimelineModel.RecordType.XHRReadyStateChange: | |
1070 case WebInspector.TimelineModel.RecordType.XHRLoad: | |
1071 case WebInspector.TimelineModel.RecordType.ScheduleResourceRequest: | |
1072 case WebInspector.TimelineModel.RecordType.ResourceSendRequest: | |
1073 case WebInspector.TimelineModel.RecordType.ResourceReceivedData: | |
1074 case WebInspector.TimelineModel.RecordType.ResourceReceiveResponse: | |
1075 case WebInspector.TimelineModel.RecordType.ResourceFinish: | |
1076 case WebInspector.TimelineModel.RecordType.DecodeImage: | |
1077 case WebInspector.TimelineModel.RecordType.ResizeImage: | |
1078 detailsText = WebInspector.displayNameForURL(record.url); | |
1079 break; | |
1080 case WebInspector.TimelineModel.RecordType.ConsoleTime: | |
1081 detailsText = record.data["message"]; | |
1082 break; | |
1083 case WebInspector.TimelineModel.RecordType.EmbedderCallback: | |
1084 detailsText = record.data["callbackName"]; | |
1085 break; | |
1086 default: | |
1087 details = record.scriptName ? linkifyLocation(record.scriptName, rec
ord.scriptLine, 0) : linkifyTopCallFrame(); | |
1088 break; | |
1089 } | |
1090 | |
1091 if (!details && detailsText) | |
1092 details = document.createTextNode(detailsText); | |
1093 return details; | |
1094 | |
1095 /** | |
1096 * @param {string} url | |
1097 * @param {number} lineNumber | |
1098 * @param {number=} columnNumber | |
1099 */ | |
1100 function linkifyLocation(url, lineNumber, columnNumber) | |
1101 { | |
1102 // FIXME(62725): stack trace line/column numbers are one-based. | |
1103 columnNumber = columnNumber ? columnNumber - 1 : 0; | |
1104 return linkifier.linkifyLocation(url, lineNumber - 1, columnNumber,
"timeline-details"); | |
1105 } | |
1106 | |
1107 /** | |
1108 * @param {!ConsoleAgent.CallFrame} callFrame | |
1109 */ | |
1110 function linkifyCallFrame(callFrame) | |
1111 { | |
1112 return linkifyLocation(callFrame.url, callFrame.lineNumber, callFram
e.columnNumber); | |
1113 } | |
1114 | |
1115 /** | |
1116 * @return {?Element} | |
1117 */ | |
1118 function linkifyTopCallFrame() | |
1119 { | |
1120 if (record.stackTrace) | |
1121 return linkifyCallFrame(record.stackTrace[0]); | |
1122 if (record.callSiteStackTrace) | |
1123 return linkifyCallFrame(record.callSiteStackTrace[0]); | |
1124 return null; | |
1125 } | |
1126 | |
1127 /** | |
1128 * @return {?Element} | |
1129 */ | |
1130 function linkifyScriptLocation() | |
1131 { | |
1132 return record.scriptName ? linkifyLocation(record.scriptName, record
.scriptLine, 0) : null; | |
1133 } | |
1134 }, | |
1135 | |
1136 calculateAggregatedStats: function() | 777 calculateAggregatedStats: function() |
1137 { | 778 { |
1138 this._aggregatedStats = {}; | 779 this._aggregatedStats = {}; |
1139 this._cpuTime = this._selfTime; | 780 this._cpuTime = this._selfTime; |
1140 | 781 |
1141 for (var index = this._children.length; index; --index) { | 782 for (var index = this._children.length; index; --index) { |
1142 var child = this._children[index - 1]; | 783 var child = this._children[index - 1]; |
1143 for (var category in child._aggregatedStats) | 784 for (var category in child._aggregatedStats) |
1144 this._aggregatedStats[category] = (this._aggregatedStats[categor
y] || 0) + child._aggregatedStats[category]; | 785 this._aggregatedStats[category] = (this._aggregatedStats[categor
y] || 0) + child._aggregatedStats[category]; |
1145 } | 786 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1242 { | 883 { |
1243 } | 884 } |
1244 | 885 |
1245 WebInspector.TimelinePresentationModel.Filter.prototype = { | 886 WebInspector.TimelinePresentationModel.Filter.prototype = { |
1246 /** | 887 /** |
1247 * @param {!WebInspector.TimelinePresentationModel.Record} record | 888 * @param {!WebInspector.TimelinePresentationModel.Record} record |
1248 * @return {boolean} | 889 * @return {boolean} |
1249 */ | 890 */ |
1250 accept: function(record) { return false; } | 891 accept: function(record) { return false; } |
1251 } | 892 } |
OLD | NEW |