home *** CD-ROM | disk | FTP | other *** search
/ Computer Active Guide 2009 July / CAG7.ISO / Internetas / SafariSetup.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_ResourceView.js < prev    next >
Encoding:
Text File  |  2010-06-03  |  14.9 KB  |  376 lines

  1. /*
  2.  * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
  3.  * Copyright (C) IBM Corp. 2009  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1.  Redistributions of source code must retain the above copyright
  10.  *     notice, this list of conditions and the following disclaimer. 
  11.  * 2.  Redistributions in binary form must reproduce the above copyright
  12.  *     notice, this list of conditions and the following disclaimer in the
  13.  *     documentation and/or other materials provided with the distribution. 
  14.  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  15.  *     its contributors may be used to endorse or promote products derived
  16.  *     from this software without specific prior written permission. 
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  19.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21.  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  22.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. WebInspector.ResourceView = function(resource)
  31. {
  32.     WebInspector.View.call(this);
  33.  
  34.     this.element.addStyleClass("resource-view");
  35.  
  36.     this.resource = resource;
  37.  
  38.     this.tabsElement = document.createElement("div");
  39.     this.tabsElement.className = "scope-bar";
  40.     this.element.appendChild(this.tabsElement);
  41.  
  42.     this.headersTabElement = document.createElement("li");
  43.     this.headersTabElement.textContent = WebInspector.UIString("Headers");
  44.     this.contentTabElement = document.createElement("li");
  45.     this.contentTabElement.textContent = WebInspector.UIString("Content");
  46.  
  47.     this.tabsElement.appendChild(this.headersTabElement);
  48.     this.tabsElement.appendChild(this.contentTabElement);
  49.  
  50.     this.headersTabElement.addEventListener("click", this._selectHeadersTab.bind(this, true), false);
  51.     this.contentTabElement.addEventListener("click", this.selectContentTab.bind(this, true), false);
  52.  
  53.     this.headersElement = document.createElement("div");
  54.     this.headersElement.className = "resource-view-headers";
  55.     this.element.appendChild(this.headersElement);
  56.  
  57.     this.contentElement = document.createElement("div");
  58.     this.contentElement.className = "resource-view-content";
  59.     this.element.appendChild(this.contentElement);
  60.  
  61.     this.headersListElement = document.createElement("ol");
  62.     this.headersListElement.className = "outline-disclosure";
  63.     this.headersElement.appendChild(this.headersListElement);
  64.  
  65.     this.headersTreeOutline = new TreeOutline(this.headersListElement);
  66.     this.headersTreeOutline.expandTreeElementsWhenArrowing = true;
  67.  
  68.     this.urlTreeElement = new TreeElement("", null, false);
  69.     this.urlTreeElement.selectable = false;
  70.     this.headersTreeOutline.appendChild(this.urlTreeElement);
  71.  
  72.     this.requestMethodTreeElement = new TreeElement("", null, false);
  73.     this.requestMethodTreeElement.selectable = false;
  74.     this.headersTreeOutline.appendChild(this.requestMethodTreeElement);
  75.  
  76.     this.statusCodeTreeElement = new TreeElement("", null, false);
  77.     this.statusCodeTreeElement.selectable = false;
  78.     this.headersTreeOutline.appendChild(this.statusCodeTreeElement);
  79.      
  80.     this.requestHeadersTreeElement = new TreeElement("", null, true);
  81.     this.requestHeadersTreeElement.expanded = true;
  82.     this.requestHeadersTreeElement.selectable = false;
  83.     this.headersTreeOutline.appendChild(this.requestHeadersTreeElement);
  84.  
  85.     this._decodeHover = WebInspector.UIString("Double-Click to toggle between URL encoded and decoded formats");
  86.     this._decodeRequestParameters = true;
  87.  
  88.     this.queryStringTreeElement = new TreeElement("", null, true);
  89.     this.queryStringTreeElement.expanded = true;
  90.     this.queryStringTreeElement.selectable = false;
  91.     this.queryStringTreeElement.hidden = true;
  92.     this.headersTreeOutline.appendChild(this.queryStringTreeElement);
  93.  
  94.     this.formDataTreeElement = new TreeElement("", null, true);
  95.     this.formDataTreeElement.expanded = true;
  96.     this.formDataTreeElement.selectable = false;
  97.     this.formDataTreeElement.hidden = true;
  98.     this.headersTreeOutline.appendChild(this.formDataTreeElement);
  99.  
  100.     this.requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true);
  101.     this.requestPayloadTreeElement.expanded = true;
  102.     this.requestPayloadTreeElement.selectable = false;
  103.     this.requestPayloadTreeElement.hidden = true;
  104.     this.headersTreeOutline.appendChild(this.requestPayloadTreeElement);
  105.  
  106.     this.responseHeadersTreeElement = new TreeElement("", null, true);
  107.     this.responseHeadersTreeElement.expanded = true;
  108.     this.responseHeadersTreeElement.selectable = false;
  109.     this.headersTreeOutline.appendChild(this.responseHeadersTreeElement);
  110.  
  111.     this.headersVisible = true;
  112.  
  113.     resource.addEventListener("url changed", this._refreshURL, this);
  114.     resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
  115.     resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
  116.     resource.addEventListener("finished", this._refreshHTTPInformation, this);
  117.  
  118.     this._refreshURL();
  119.     this._refreshRequestHeaders();
  120.     this._refreshResponseHeaders();
  121.     this._refreshHTTPInformation();
  122.     if (!this.hasContentTab())
  123.         this.contentTabElement.addStyleClass("hidden");
  124.     this._selectTab();
  125. }
  126.  
  127. WebInspector.ResourceView.prototype = {
  128.     attach: function()
  129.     {
  130.         if (!this.element.parentNode) {
  131.             var parentElement = (document.getElementById("resource-views") || document.getElementById("script-resource-views"));
  132.             if (parentElement)
  133.                 parentElement.appendChild(this.element);
  134.         }
  135.     },
  136.  
  137.     show: function(parentElement)
  138.     {
  139.         WebInspector.View.prototype.show.call(this, parentElement);
  140.         this._selectTab();
  141.     },
  142.  
  143.     set headersVisible(x)
  144.     {
  145.         if (x === this._headersVisible)
  146.             return;
  147.         this._headersVisible = x;
  148.         if (x)
  149.             this.element.addStyleClass("headers-visible"); 
  150.         else
  151.             this.element.removeStyleClass("headers-visible"); 
  152.         this._selectTab();
  153.     },
  154.  
  155.     _selectTab: function()
  156.     {
  157.         if (this._headersVisible) {
  158.             if (!this.hasContentTab() || WebInspector.settings.resourceViewTab === "headers")
  159.                 this._selectHeadersTab();
  160.             else
  161.                 this.selectContentTab();
  162.         } else
  163.             this._innerSelectContentTab();
  164.     },
  165.  
  166.     _selectHeadersTab: function(updatePrefs)
  167.     {
  168.         if (updatePrefs)
  169.             WebInspector.settings.resourceViewTab = "headers";
  170.         this.headersTabElement.addStyleClass("selected");
  171.         this.contentTabElement.removeStyleClass("selected");
  172.         this.headersElement.removeStyleClass("hidden");
  173.         this.contentElement.addStyleClass("hidden");
  174.     },
  175.  
  176.     selectContentTab: function(updatePrefs)
  177.     {
  178.         if (updatePrefs)
  179.             WebInspector.settings.resourceViewTab = "content";
  180.         this._innerSelectContentTab();
  181.     },
  182.  
  183.     hasContentTab: function()
  184.     {
  185.         // Derived classes should override this method and define this.contentTabSelected for content rendering.
  186.         return false;
  187.     },
  188.  
  189.     _innerSelectContentTab: function()
  190.     {
  191.         this.contentTabElement.addStyleClass("selected");
  192.         this.headersTabElement.removeStyleClass("selected");
  193.         this.contentElement.removeStyleClass("hidden");
  194.         this.headersElement.addStyleClass("hidden");
  195.         if ("resize" in this)
  196.             this.resize();
  197.         this.contentTabSelected();
  198.     },
  199.  
  200.     _refreshURL: function()
  201.     {
  202.         this.urlTreeElement.title = "<div class=\"header-name\">" + WebInspector.UIString("Request URL") + ":</div>" +
  203.             "<div class=\"header-value source-code\">" + this.resource.url.escapeHTML() + "</div>";
  204.     },
  205.  
  206.     _refreshQueryString: function()
  207.     {
  208.         var url = this.resource.url;
  209.         var hasQueryString = url.indexOf("?") >= 0;
  210.  
  211.         if (!hasQueryString) {
  212.             this.queryStringTreeElement.hidden = true;
  213.             return;
  214.         }
  215.  
  216.         this.queryStringTreeElement.hidden = false;
  217.         var parmString = url.split("?", 2)[1];
  218.         this._refreshParms(WebInspector.UIString("Query String Parameters"), parmString, this.queryStringTreeElement);
  219.     },
  220.  
  221.     _refreshFormData: function()
  222.     {
  223.         this.formDataTreeElement.hidden = true;
  224.         this.requestPayloadTreeElement.hidden = true;
  225.  
  226.         var isFormData = this.resource.requestFormData;
  227.         if (!isFormData)
  228.             return;
  229.  
  230.         var isFormEncoded = false;
  231.         var requestContentType = this._getHeaderValue(this.resource.requestHeaders, "Content-Type");
  232.         if (requestContentType && requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
  233.             isFormEncoded = true;
  234.  
  235.         if (isFormEncoded) {
  236.             this.formDataTreeElement.hidden = false;
  237.             this._refreshParms(WebInspector.UIString("Form Data"), this.resource.requestFormData, this.formDataTreeElement);
  238.         } else {
  239.             this.requestPayloadTreeElement.hidden = false;
  240.             this._refreshRequestPayload(this.resource.requestFormData);
  241.         }
  242.     },
  243.  
  244.     _refreshRequestPayload: function(formData)
  245.     {
  246.         this.requestPayloadTreeElement.removeChildren();
  247.  
  248.         var title = "<div class=\"header-name\"> </div>";
  249.         title += "<div class=\"raw-form-data header-value source-code\">" + formData.escapeHTML() + "</div>";
  250.         var parmTreeElement = new TreeElement(title, null, false);
  251.         parmTreeElement.selectable = false;
  252.         this.requestPayloadTreeElement.appendChild(parmTreeElement);
  253.     },
  254.  
  255.     _refreshParms: function(title, parmString, parmsTreeElement)
  256.     {
  257.         var parms = parmString.split("&");
  258.         for (var i = 0; i < parms.length; ++i) {
  259.             var parm = parms[i];
  260.             parm = parm.split("=", 2);
  261.             if (parm.length == 1)
  262.                 parm.push("");
  263.             parms[i] = parm;
  264.         }
  265.  
  266.         parmsTreeElement.removeChildren();
  267.  
  268.         parmsTreeElement.title = title + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", parms.length) + "</span>";
  269.  
  270.         for (var i = 0; i < parms.length; ++i) {
  271.             var key = parms[i][0];
  272.             var value = parms[i][1];
  273.  
  274.             var errorDecoding = false;
  275.             if (this._decodeRequestParameters) {
  276.                 if (value.indexOf("%") >= 0) {
  277.                     try {
  278.                         value = decodeURIComponent(value);
  279.                     } catch(e) {
  280.                         errorDecoding = true;
  281.                     }
  282.                 }
  283.                     
  284.                 value = value.replace(/\+/g, " ");
  285.             }
  286.  
  287.             valueEscaped = value.escapeHTML();
  288.             if (errorDecoding)
  289.                 valueEscaped += " <span class=\"error-message\">" + WebInspector.UIString("(unable to decode value)").escapeHTML() + "</span>";
  290.  
  291.             var title = "<div class=\"header-name\">" + key.escapeHTML() + ":</div>";
  292.             title += "<div class=\"header-value source-code\">" + valueEscaped + "</div>";
  293.  
  294.             var parmTreeElement = new TreeElement(title, null, false);
  295.             parmTreeElement.selectable = false;
  296.             parmTreeElement.tooltip = this._decodeHover;
  297.             parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this);
  298.             parmsTreeElement.appendChild(parmTreeElement);
  299.         }
  300.     },
  301.  
  302.     _toggleURLdecoding: function(event)
  303.     {
  304.         this._decodeRequestParameters = !this._decodeRequestParameters;
  305.         this._refreshQueryString();
  306.         this._refreshFormData();
  307.     },
  308.  
  309.     _getHeaderValue: function(headers, key)
  310.     {
  311.         var lowerKey = key.toLowerCase();
  312.         for (var testKey in headers) {
  313.             if (testKey.toLowerCase() === lowerKey)
  314.                 return headers[testKey];
  315.         }
  316.     },
  317.  
  318.     _refreshRequestHeaders: function()
  319.     {
  320.         this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
  321.         this._refreshFormData();
  322.     },
  323.  
  324.     _refreshResponseHeaders: function()
  325.     {
  326.         this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
  327.     },
  328.  
  329.     _refreshHTTPInformation: function()
  330.     {
  331.         var requestMethodElement = this.requestMethodTreeElement;
  332.         requestMethodElement.hidden = !this.resource.statusCode;
  333.         var statusCodeElement = this.statusCodeTreeElement;
  334.         statusCodeElement.hidden = !this.resource.statusCode;
  335.         var statusCodeImage = "";
  336.  
  337.         if (this.resource.statusCode) {
  338.             var statusImageSource = "";
  339.             if (this.resource.statusCode < 300)
  340.                 statusImageSource = "Images/successGreenDot.png";
  341.             else if (this.resource.statusCode < 400)
  342.                 statusImageSource = "Images/warningOrangeDot.png";
  343.             else
  344.                 statusImageSource = "Images/errorRedDot.png";
  345.             statusCodeImage = "<img class=\"resource-status-image\" src=\"" + statusImageSource + "\" title=\"" + WebInspector.Resource.StatusTextForCode(this.resource.statusCode) + "\">";
  346.     
  347.             requestMethodElement.title = "<div class=\"header-name\">" + WebInspector.UIString("Request Method") + ":</div>" +
  348.                 "<div class=\"header-value source-code\">" + this.resource.requestMethod + "</div>";
  349.  
  350.             statusCodeElement.title = "<div class=\"header-name\">" + WebInspector.UIString("Status Code") + ":</div>" +
  351.                 statusCodeImage + "<div class=\"header-value source-code\">" + WebInspector.Resource.StatusTextForCode(this.resource.statusCode) + "</div>";
  352.         }
  353.     },
  354.     
  355.     _refreshHeaders: function(title, headers, headersTreeElement)
  356.     {
  357.         headersTreeElement.removeChildren();
  358.  
  359.         var length = headers.length;
  360.         headersTreeElement.title = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>";
  361.         headersTreeElement.hidden = !length;
  362.  
  363.         var length = headers.length;
  364.         for (var i = 0; i < length; ++i) {
  365.             var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
  366.             title += "<div class=\"header-value source-code\">" + headers[i].value.escapeHTML() + "</div>"
  367.  
  368.             var headerTreeElement = new TreeElement(title, null, false);
  369.             headerTreeElement.selectable = false;
  370.             headersTreeElement.appendChild(headerTreeElement);
  371.         }
  372.     }
  373. }
  374.  
  375. WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype;
  376.