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