1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/firebug", 6 "firebug/lib/domplate", 7 "firebug/lib/locale", 8 "firebug/lib/xpcom", 9 "firebug/lib/css", 10 "firebug/lib/http", 11 "firebug/net/netUtils" 12 ], 13 function(Obj, Firebug, Domplate, Locale, Xpcom, Css, Http, NetUtils) { 14 15 // ********************************************************************************************* // 16 // Constants 17 18 // List of XML related content types. 19 var xmlContentTypes = 20 [ 21 "text/xml", 22 "application/xml", 23 "application/xhtml+xml", 24 "application/rss+xml", 25 "application/atom+xml",, 26 "application/vnd.mozilla.maybe.feed", 27 "application/mathml+xml", 28 "application/rdf+xml", 29 "application/vnd.mozilla.xul+xml" 30 ]; 31 32 // ********************************************************************************************* // 33 // Model implementation 34 35 /** 36 * @module Implements viewer for XML based network responses. In order to create a new 37 * tab wihin network request detail, a listener is registered into 38 * <code>Firebug.NetMonitor.NetInfoBody</code> object. 39 */ 40 Firebug.XMLViewerModel = Obj.extend(Firebug.Module, 41 /** lends Firebug.XMLViewerModel */ 42 { 43 dispatchName: "xmlViewer", 44 45 initialize: function() 46 { 47 Firebug.ActivableModule.initialize.apply(this, arguments); 48 Firebug.NetMonitor.NetInfoBody.addListener(this); 49 }, 50 51 shutdown: function() 52 { 53 Firebug.ActivableModule.shutdown.apply(this, arguments); 54 Firebug.NetMonitor.NetInfoBody.removeListener(this); 55 }, 56 57 /** 58 * Check response's content-type and if it's a Xml, create a new tab with XML preview. 59 */ 60 initTabBody: function(infoBox, file) 61 { 62 if (FBTrace.DBG_XMLVIEWER) 63 FBTrace.sysout("xmlviewer.initTabBody", infoBox); 64 65 // If the response is XML let's display a pretty preview. 66 if (this.isXML(Http.safeGetContentType(file.request))) 67 { 68 Firebug.NetMonitor.NetInfoBody.appendTab(infoBox, "XML", 69 Locale.$STR("xmlviewer.tab.XML")); 70 71 if (FBTrace.DBG_XMLVIEWER) 72 FBTrace.sysout("xmlviewer.initTabBody; XML response available"); 73 } 74 }, 75 76 isXML: function(contentType) 77 { 78 if (!contentType) 79 return false; 80 81 return NetUtils.matchesContentType(contentType, xmlContentTypes); 82 }, 83 84 /** 85 * Parse XML response and render pretty printed preview. 86 */ 87 updateTabBody: function(infoBox, file, context) 88 { 89 var tab = infoBox.selectedTab; 90 var tabBody = infoBox.getElementsByClassName("netInfoXMLText").item(0); 91 if (!Css.hasClass(tab, "netInfoXMLTab") || tabBody.updated) 92 return; 93 94 tabBody.updated = true; 95 96 this.insertXML(tabBody, NetUtils.getResponseText(file, context)); 97 }, 98 99 insertXML: function(parentNode, text) 100 { 101 var parser = Xpcom.CCIN("@mozilla.org/xmlextras/domparser;1", "nsIDOMParser"); 102 var doc = parser.parseFromString(text, "text/xml"); 103 var root = doc.documentElement; 104 105 // Error handling 106 var nsURI = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; 107 if (root.namespaceURI == nsURI && root.nodeName == "parsererror") 108 { 109 this.ParseError.tag.replace({error: { 110 message: root.firstChild.nodeValue, 111 source: root.lastChild.textContent 112 }}, parentNode); 113 return; 114 } 115 116 if (FBTrace.DBG_XMLVIEWER) 117 FBTrace.sysout("xmlviewer.updateTabBody; XML response parsed", doc); 118 119 // Override getHidden in these templates. The parsed XML documen is 120 // hidden, but we want to display it using 'visible' styling. 121 var templates = [ 122 Firebug.HTMLPanel.CompleteElement, 123 Firebug.HTMLPanel.Element, 124 Firebug.HTMLPanel.TextElement, 125 Firebug.HTMLPanel.EmptyElement, 126 Firebug.HTMLPanel.XEmptyElement, 127 ]; 128 129 var originals = []; 130 for (var i=0; i<templates.length; i++) 131 { 132 originals[i] = templates[i].getHidden; 133 templates[i].getHidden = function() { 134 return ""; 135 } 136 } 137 138 // Generate XML preview. 139 Firebug.HTMLPanel.CompleteElement.tag.replace({object: doc.documentElement}, parentNode); 140 141 for (var i=0; i<originals.length; i++) 142 templates[i].getHidden = originals[i]; 143 } 144 }); 145 146 // ********************************************************************************************* // 147 // Domplate 148 149 /** 150 * @domplate Represents a template for displaying XML parser errors. Used by 151 * <code>Firebug.XMLViewerModel</code>. 152 */ 153 with (Domplate) { 154 Firebug.XMLViewerModel.ParseError = domplate(Firebug.Rep, 155 { 156 tag: 157 DIV({"class": "xmlInfoError"}, 158 DIV({"class": "xmlInfoErrorMsg"}, "$error.message"), 159 PRE({"class": "xmlInfoErrorSource"}, "$error|getSource") 160 ), 161 162 getSource: function(error) 163 { 164 var parts = error.source.split("\n"); 165 if (parts.length != 2) 166 return error.source; 167 168 var limit = 50; 169 var column = parts[1].length; 170 if (column >= limit) { 171 parts[0] = "..." + parts[0].substr(column - limit); 172 parts[1] = "..." + parts[1].substr(column - limit); 173 } 174 175 if (parts[0].length > 80) 176 parts[0] = parts[0].substr(0, 80) + "..."; 177 178 return parts.join("\n"); 179 } 180 })}; 181 182 // ********************************************************************************************* // 183 // Registration 184 185 Firebug.registerModule(Firebug.XMLViewerModel); 186 187 return Firebug.XMLViewerModel; 188 189 // ********************************************************************************************* // 190 }); 191