Attachment #8758151: Part 2: Show network request cause and stacktrace in netmonitor UI for bug #1134073

View | Details | Raw Unified | Return to bug 1134073
Collapse All | Expand All

(-)a/devtools/client/locales/en-US/netmonitor.dtd (+4 lines)
Line     Link Here 
 Lines 34-49    Link Here 
34
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.file): This is the label displayed
34
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.file): This is the label displayed
35
  -  in the network table toolbar, above the "file" column. -->
35
  -  in the network table toolbar, above the "file" column. -->
36
<!ENTITY netmonitorUI.toolbar.file        "File">
36
<!ENTITY netmonitorUI.toolbar.file        "File">
37
37
38
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.domain): This is the label displayed
38
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.domain): This is the label displayed
39
  -  in the network table toolbar, above the "domain" column. -->
39
  -  in the network table toolbar, above the "domain" column. -->
40
<!ENTITY netmonitorUI.toolbar.domain      "Domain">
40
<!ENTITY netmonitorUI.toolbar.domain      "Domain">
41
41
42
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.cause): This is the label displayed
43
  -  in the network table toolbar, above the "cause" column. -->
44
<!ENTITY netmonitorUI.toolbar.cause        "Cause">
45
42
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.type): This is the label displayed
46
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.type): This is the label displayed
43
  -  in the network table toolbar, above the "type" column. -->
47
  -  in the network table toolbar, above the "type" column. -->
44
<!ENTITY netmonitorUI.toolbar.type        "Type">
48
<!ENTITY netmonitorUI.toolbar.type        "Type">
45
49
46
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.transferred): This is the label displayed
50
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.transferred): This is the label displayed
47
  -  in the network table toolbar, above the "transferred" column, which is the
51
  -  in the network table toolbar, above the "transferred" column, which is the
48
  -  compressed / encoded size. -->
52
  -  compressed / encoded size. -->
49
<!ENTITY netmonitorUI.toolbar.transferred "Transferred">
53
<!ENTITY netmonitorUI.toolbar.transferred "Transferred">
(-)a/devtools/client/netmonitor/netmonitor-controller.js (-1 / +10 lines)
Line     Link Here 
 Lines 428-443   var NetMonitorController = { Link Here 
428
428
429
  /**
429
  /**
430
   * Getter that tells if the server can do network performance statistics.
430
   * Getter that tells if the server can do network performance statistics.
431
   * @type boolean
431
   * @type boolean
432
   */
432
   */
433
  get supportsPerfStats() {
433
  get supportsPerfStats() {
434
    return this.tabClient &&
434
    return this.tabClient &&
435
           (this.tabClient.traits.reconfigure || !this._target.isApp);
435
           (this.tabClient.traits.reconfigure || !this._target.isApp);
436
  },
437
438
  /**
439
   * Open a given source in Debugger
440
   */
441
  viewSourceInDebugger(sourceURL, sourceLine) {
442
    return this._toolbox.viewSourceInDebugger(sourceURL, sourceLine);
436
  }
443
  }
437
};
444
};
438
445
439
/**
446
/**
440
 * Functions handling target-related lifetime events.
447
 * Functions handling target-related lifetime events.
441
 */
448
 */
442
function TargetEventsHandler() {
449
function TargetEventsHandler() {
443
  this._onTabNavigated = this._onTabNavigated.bind(this);
450
  this._onTabNavigated = this._onTabNavigated.bind(this);
 Lines 624-645   NetworkEventsHandler.prototype = { Link Here 
624
   * @param object networkInfo
631
   * @param object networkInfo
625
   *        The network request information.
632
   *        The network request information.
626
   */
633
   */
627
  _onNetworkEvent: function (type, networkInfo) {
634
  _onNetworkEvent: function (type, networkInfo) {
628
    let { actor,
635
    let { actor,
629
      startedDateTime,
636
      startedDateTime,
630
      request: { method, url },
637
      request: { method, url },
631
      isXHR,
638
      isXHR,
639
      cause,
632
      fromCache,
640
      fromCache,
633
      fromServiceWorker
641
      fromServiceWorker
634
    } = networkInfo;
642
    } = networkInfo;
635
643
636
    NetMonitorView.RequestsMenu.addRequest(
644
    NetMonitorView.RequestsMenu.addRequest(
637
      actor, startedDateTime, method, url, isXHR, fromCache, fromServiceWorker
645
      actor, startedDateTime, method, url, isXHR, cause, fromCache,
646
        fromServiceWorker
638
    );
647
    );
639
    window.emit(EVENTS.NETWORK_EVENT, actor);
648
    window.emit(EVENTS.NETWORK_EVENT, actor);
640
  },
649
  },
641
650
642
  /**
651
  /**
643
   * The "networkEventUpdate" message type handler.
652
   * The "networkEventUpdate" message type handler.
644
   *
653
   *
645
   * @param string type
654
   * @param string type
(-)a/devtools/client/netmonitor/netmonitor-view.js (-54 / +116 lines)
Line     Link Here 
 Lines 56-71   const HTML_NS = "http://www.w3.org/1999/xhtml"; Link Here 
56
const EPSILON = 0.001;
56
const EPSILON = 0.001;
57
// 100 KB in bytes
57
// 100 KB in bytes
58
const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 102400;
58
const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 102400;
59
// ms
59
// ms
60
const RESIZE_REFRESH_RATE = 50;
60
const RESIZE_REFRESH_RATE = 50;
61
// ms
61
// ms
62
const REQUESTS_REFRESH_RATE = 50;
62
const REQUESTS_REFRESH_RATE = 50;
63
const REQUESTS_TOOLTIP_POSITION = "topcenter bottomleft";
63
const REQUESTS_TOOLTIP_POSITION = "topcenter bottomleft";
64
// tooltip show/hide delay in ms
65
const REQUESTS_TOOLTIP_TOGGLE_DELAY = 500;
64
// px
66
// px
65
const REQUESTS_TOOLTIP_IMAGE_MAX_DIM = 400;
67
const REQUESTS_TOOLTIP_IMAGE_MAX_DIM = 400;
66
// px
68
// px
67
const REQUESTS_WATERFALL_SAFE_BOUNDS = 90;
69
const REQUESTS_WATERFALL_SAFE_BOUNDS = 90;
68
// ms
70
// ms
69
const REQUESTS_WATERFALL_HEADER_TICKS_MULTIPLE = 5;
71
const REQUESTS_WATERFALL_HEADER_TICKS_MULTIPLE = 5;
70
// px
72
// px
71
const REQUESTS_WATERFALL_HEADER_TICKS_SPACING_MIN = 60;
73
const REQUESTS_WATERFALL_HEADER_TICKS_SPACING_MIN = 60;
 Lines 97-112   const CONTENT_MIME_TYPE_MAPPINGS = { Link Here 
97
  "/xml": Editor.modes.html,
99
  "/xml": Editor.modes.html,
98
  "/atom": Editor.modes.html,
100
  "/atom": Editor.modes.html,
99
  "/soap": Editor.modes.html,
101
  "/soap": Editor.modes.html,
100
  "/vnd.mpeg.dash.mpd": Editor.modes.html,
102
  "/vnd.mpeg.dash.mpd": Editor.modes.html,
101
  "/rdf": Editor.modes.css,
103
  "/rdf": Editor.modes.css,
102
  "/rss": Editor.modes.css,
104
  "/rss": Editor.modes.css,
103
  "/css": Editor.modes.css
105
  "/css": Editor.modes.css
104
};
106
};
107
const LOAD_CAUSE_STRINGS = {
108
  [Ci.nsIContentPolicy.TYPE_INVALID]: "invalid",
109
  [Ci.nsIContentPolicy.TYPE_OTHER]: "other",
110
  [Ci.nsIContentPolicy.TYPE_SCRIPT]: "script",
111
  [Ci.nsIContentPolicy.TYPE_IMAGE]: "img",
112
  [Ci.nsIContentPolicy.TYPE_STYLESHEET]: "stylesheet",
113
  [Ci.nsIContentPolicy.TYPE_OBJECT]: "object",
114
  [Ci.nsIContentPolicy.TYPE_DOCUMENT]: "document",
115
  [Ci.nsIContentPolicy.TYPE_SUBDOCUMENT]: "subdocument",
116
  [Ci.nsIContentPolicy.TYPE_REFRESH]: "refresh",
117
  [Ci.nsIContentPolicy.TYPE_XBL]: "xbl",
118
  [Ci.nsIContentPolicy.TYPE_PING]: "ping",
119
  [Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST]: "xhr",
120
  [Ci.nsIContentPolicy.TYPE_OBJECT_SUBREQUEST]: "objectSubdoc",
121
  [Ci.nsIContentPolicy.TYPE_DTD]: "dtd",
122
  [Ci.nsIContentPolicy.TYPE_FONT]: "font",
123
  [Ci.nsIContentPolicy.TYPE_MEDIA]: "media",
124
  [Ci.nsIContentPolicy.TYPE_WEBSOCKET]: "websocket",
125
  [Ci.nsIContentPolicy.TYPE_CSP_REPORT]: "csp",
126
  [Ci.nsIContentPolicy.TYPE_XSLT]: "xslt",
127
  [Ci.nsIContentPolicy.TYPE_BEACON]: "beacon",
128
  [Ci.nsIContentPolicy.TYPE_FETCH]: "fetch",
129
  [Ci.nsIContentPolicy.TYPE_IMAGESET]: "imageset",
130
  [Ci.nsIContentPolicy.TYPE_WEB_MANIFEST]: "webManifest"
131
};
105
const DEFAULT_EDITOR_CONFIG = {
132
const DEFAULT_EDITOR_CONFIG = {
106
  mode: Editor.modes.text,
133
  mode: Editor.modes.text,
107
  readOnly: true,
134
  readOnly: true,
108
  lineNumbers: true
135
  lineNumbers: true
109
};
136
};
110
const GENERIC_VARIABLES_VIEW_SETTINGS = {
137
const GENERIC_VARIABLES_VIEW_SETTINGS = {
111
  lazyEmpty: true,
138
  lazyEmpty: true,
112
  // ms
139
  // ms
 Lines 426-441   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
426
453
427
    this.widget = new SideMenuWidget($("#requests-menu-contents"));
454
    this.widget = new SideMenuWidget($("#requests-menu-contents"));
428
    this._splitter = $("#network-inspector-view-splitter");
455
    this._splitter = $("#network-inspector-view-splitter");
429
    this._summary = $("#requests-menu-network-summary-button");
456
    this._summary = $("#requests-menu-network-summary-button");
430
    this._summary.setAttribute("label", L10N.getStr("networkMenu.empty"));
457
    this._summary.setAttribute("label", L10N.getStr("networkMenu.empty"));
431
    this.userInputTimer = Cc["@mozilla.org/timer;1"]
458
    this.userInputTimer = Cc["@mozilla.org/timer;1"]
432
      .createInstance(Ci.nsITimer);
459
      .createInstance(Ci.nsITimer);
433
460
461
    // Create a tooltip for the newly appended network request item.
462
    this.tooltip = new Tooltip(document, {
463
      closeOnEvents: [{
464
        emitter: $("#requests-menu-contents"),
465
        event: "scroll",
466
        useCapture: true
467
      }]
468
    });
469
    this.tooltip.startTogglingOnHover(this.widget, this._onHover, {
470
      toggleDelay: REQUESTS_TOOLTIP_TOGGLE_DELAY,
471
      interactive: true
472
    });
473
    this.tooltip.defaultPosition = REQUESTS_TOOLTIP_POSITION;
474
434
    Prefs.filters.forEach(type => this.filterOn(type));
475
    Prefs.filters.forEach(type => this.filterOn(type));
435
    this.sortContents(this._byTiming);
476
    this.sortContents(this._byTiming);
436
477
437
    this.allowFocusOnRightClick = true;
478
    this.allowFocusOnRightClick = true;
438
    this.maintainSelectionVisible = true;
479
    this.maintainSelectionVisible = true;
439
480
440
    this.widget.addEventListener("select", this._onSelect, false);
481
    this.widget.addEventListener("select", this._onSelect, false);
441
    this.widget.addEventListener("swap", this._onSwap, false);
482
    this.widget.addEventListener("swap", this._onSwap, false);
 Lines 632-656   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
632
   *        A string representation of when the request was started, which
673
   *        A string representation of when the request was started, which
633
   *        can be parsed by Date (for example "2012-09-17T19:50:03.699Z").
674
   *        can be parsed by Date (for example "2012-09-17T19:50:03.699Z").
634
   * @param string method
675
   * @param string method
635
   *        Specifies the request method (e.g. "GET", "POST", etc.)
676
   *        Specifies the request method (e.g. "GET", "POST", etc.)
636
   * @param string url
677
   * @param string url
637
   *        Specifies the request's url.
678
   *        Specifies the request's url.
638
   * @param boolean isXHR
679
   * @param boolean isXHR
639
   *        True if this request was initiated via XHR.
680
   *        True if this request was initiated via XHR.
681
   * @param object cause
682
   *        Specifies the request's cause. Has the following properties:
683
   *        - type: nsContentPolicyType constant
684
   *        - loadingDocumentUri: URI of the request origin
685
   *        - stacktrace: JS stacktrace of the request
640
   * @param boolean fromCache
686
   * @param boolean fromCache
641
   *        Indicates if the result came from the browser cache
687
   *        Indicates if the result came from the browser cache
642
   * @param boolean fromServiceWorker
688
   * @param boolean fromServiceWorker
643
   *        Indicates if the request has been intercepted by a Service Worker
689
   *        Indicates if the request has been intercepted by a Service Worker
644
   */
690
   */
645
  addRequest: function (id, startedDateTime, method, url, isXHR, fromCache,
691
  addRequest: function (id, startedDateTime, method, url, isXHR, cause,
646
    fromServiceWorker) {
692
    fromCache, fromServiceWorker) {
647
    this._addQueue.push([id, startedDateTime, method, url, isXHR, fromCache,
693
    this._addQueue.push([id, startedDateTime, method, url, isXHR, cause,
648
      fromServiceWorker]);
694
      fromCache, fromServiceWorker]);
649
695
650
    // Lazy updating is disabled in some tests.
696
    // Lazy updating is disabled in some tests.
651
    if (!this.lazyUpdate) {
697
    if (!this.lazyUpdate) {
652
      return void this._flushRequests();
698
      return void this._flushRequests();
653
    }
699
    }
654
700
655
    this._flushRequestsTask.arm();
701
    this._flushRequestsTask.arm();
656
    return undefined;
702
    return undefined;
 Lines 880-896   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
880
  /**
926
  /**
881
   * Create a new custom request form populated with the data from
927
   * Create a new custom request form populated with the data from
882
   * the currently selected request.
928
   * the currently selected request.
883
   */
929
   */
884
  cloneSelectedRequest: function () {
930
  cloneSelectedRequest: function () {
885
    let selected = this.selectedItem.attachment;
931
    let selected = this.selectedItem.attachment;
886
932
887
    // Create the element node for the network request item.
933
    // Create the element node for the network request item.
888
    let menuView = this._createMenuView(selected.method, selected.url);
934
    let menuView = this._createMenuView(selected.method, selected.url,
935
      selected.cause);
889
936
890
    // Append a network request item to this container.
937
    // Append a network request item to this container.
891
    let newItem = this.push([menuView], {
938
    let newItem = this.push([menuView], {
892
      attachment: Object.create(selected, {
939
      attachment: Object.create(selected, {
893
        isCustom: { value: true }
940
        isCustom: { value: true }
894
      })
941
      })
895
    });
942
    });
896
943
 Lines 1447-1475   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
1447
      } else {
1494
      } else {
1448
        requestTarget.setAttribute("odd", "");
1495
        requestTarget.setAttribute("odd", "");
1449
        requestTarget.removeAttribute("even");
1496
        requestTarget.removeAttribute("even");
1450
      }
1497
      }
1451
    }
1498
    }
1452
  },
1499
  },
1453
1500
1454
  /**
1501
  /**
1455
   * Refreshes the toggling anchor for the specified item's tooltip.
1456
   *
1457
   * @param object item
1458
   *        The network request item in this container.
1459
   */
1460
  refreshTooltip: function (item) {
1461
    let tooltip = item.attachment.tooltip;
1462
    tooltip.hide();
1463
    tooltip.startTogglingOnHover(item.target, this._onHover);
1464
    tooltip.defaultPosition = REQUESTS_TOOLTIP_POSITION;
1465
  },
1466
1467
  /**
1468
   * Attaches security icon click listener for the given request menu item.
1502
   * Attaches security icon click listener for the given request menu item.
1469
   *
1503
   *
1470
   * @param object item
1504
   * @param object item
1471
   *        The network request item to attach the listener to.
1505
   *        The network request item to attach the listener to.
1472
   */
1506
   */
1473
  attachSecurityIconClickListener: function ({ target }) {
1507
  attachSecurityIconClickListener: function ({ target }) {
1474
    let icon = $(".requests-security-state-icon", target);
1508
    let icon = $(".requests-security-state-icon", target);
1475
    icon.addEventListener("click", this._onSecurityIconClick);
1509
    icon.addEventListener("click", this._onSecurityIconClick);
 Lines 1505-1556   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
1505
    // Prevent displaying any updates received after the target closed.
1539
    // Prevent displaying any updates received after the target closed.
1506
    if (NetMonitorView._isDestroyed) {
1540
    if (NetMonitorView._isDestroyed) {
1507
      return;
1541
      return;
1508
    }
1542
    }
1509
1543
1510
    let widget = NetMonitorView.RequestsMenu.widget;
1544
    let widget = NetMonitorView.RequestsMenu.widget;
1511
    let isScrolledToBottom = widget.isScrolledToBottom();
1545
    let isScrolledToBottom = widget.isScrolledToBottom();
1512
1546
1513
    for (let [id, startedDateTime, method, url, isXHR, fromCache,
1547
    for (let [id, startedDateTime, method, url, isXHR, cause, fromCache,
1514
      fromServiceWorker] of this._addQueue) {
1548
      fromServiceWorker] of this._addQueue) {
1515
      // Convert the received date/time string to a unix timestamp.
1549
      // Convert the received date/time string to a unix timestamp.
1516
      let unixTime = Date.parse(startedDateTime);
1550
      let unixTime = Date.parse(startedDateTime);
1517
1551
1518
      // Create the element node for the network request item.
1552
      // Create the element node for the network request item.
1519
      let menuView = this._createMenuView(method, url);
1553
      let menuView = this._createMenuView(method, url, cause);
1520
1554
1521
      // Remember the first and last event boundaries.
1555
      // Remember the first and last event boundaries.
1522
      this._registerFirstRequestStart(unixTime);
1556
      this._registerFirstRequestStart(unixTime);
1523
      this._registerLastRequestEnd(unixTime);
1557
      this._registerLastRequestEnd(unixTime);
1524
1558
1525
      // Append a network request item to this container.
1559
      // Append a network request item to this container.
1526
      let requestItem = this.push([menuView, id], {
1560
      let requestItem = this.push([menuView, id], {
1527
        attachment: {
1561
        attachment: {
1528
          startedDeltaMillis: unixTime - this._firstRequestStartedMillis,
1562
          startedDeltaMillis: unixTime - this._firstRequestStartedMillis,
1529
          startedMillis: unixTime,
1563
          startedMillis: unixTime,
1530
          method: method,
1564
          method: method,
1531
          url: url,
1565
          url: url,
1532
          isXHR: isXHR,
1566
          isXHR: isXHR,
1567
          cause: cause,
1533
          fromCache: fromCache,
1568
          fromCache: fromCache,
1534
          fromServiceWorker: fromServiceWorker
1569
          fromServiceWorker: fromServiceWorker
1535
        }
1570
        }
1536
      });
1571
      });
1537
1572
1538
      // Create a tooltip for the newly appended network request item.
1539
      requestItem.attachment.tooltip = new Tooltip(document, {
1540
        closeOnEvents: [{
1541
          emitter: $("#requests-menu-contents"),
1542
          event: "scroll",
1543
          useCapture: true
1544
        }]
1545
      });
1546
1547
      this.refreshTooltip(requestItem);
1548
1549
      if (id == this._preferredItemId) {
1573
      if (id == this._preferredItemId) {
1550
        this.selectedItem = requestItem;
1574
        this.selectedItem = requestItem;
1551
      }
1575
      }
1552
1576
1553
      window.emit(EVENTS.REQUEST_ADDED, id);
1577
      window.emit(EVENTS.REQUEST_ADDED, id);
1554
    }
1578
    }
1555
1579
1556
    if (isScrolledToBottom && this._addQueue.length) {
1580
    if (isScrolledToBottom && this._addQueue.length) {
 Lines 1749-1779   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
1749
1773
1750
  /**
1774
  /**
1751
   * Customization function for creating an item's UI.
1775
   * Customization function for creating an item's UI.
1752
   *
1776
   *
1753
   * @param string method
1777
   * @param string method
1754
   *        Specifies the request method (e.g. "GET", "POST", etc.)
1778
   *        Specifies the request method (e.g. "GET", "POST", etc.)
1755
   * @param string url
1779
   * @param string url
1756
   *        Specifies the request's url.
1780
   *        Specifies the request's url.
1781
   * @param object cause
1782
   *        Specifies the request's cause. Has two properties:
1783
   *        - type: nsContentPolicyType constant
1784
   *        - uri: URI of the request origin
1757
   * @return nsIDOMNode
1785
   * @return nsIDOMNode
1758
   *         The network request view.
1786
   *         The network request view.
1759
   */
1787
   */
1760
  _createMenuView: function (method, url) {
1788
  _createMenuView: function (method, url, cause) {
1761
    let template = $("#requests-menu-item-template");
1789
    let template = $("#requests-menu-item-template");
1762
    let fragment = document.createDocumentFragment();
1790
    let fragment = document.createDocumentFragment();
1763
1791
1764
    this.updateMenuView(template, "method", method);
1765
    this.updateMenuView(template, "url", url);
1766
1767
    // Flatten the DOM by removing one redundant box (the template container).
1792
    // Flatten the DOM by removing one redundant box (the template container).
1768
    for (let node of template.childNodes) {
1793
    for (let node of template.childNodes) {
1769
      fragment.appendChild(node.cloneNode(true));
1794
      fragment.appendChild(node.cloneNode(true));
1770
    }
1795
    }
1771
1796
1797
    this.updateMenuView(fragment, "method", method);
1798
    this.updateMenuView(fragment, "url", url);
1799
    this.updateMenuView(fragment, "cause", cause);
1800
1772
    return fragment;
1801
    return fragment;
1773
  },
1802
  },
1774
1803
1775
  /**
1804
  /**
1776
   * Get a human-readable string from a number of bytes, with the B, KB, MB, or
1805
   * Get a human-readable string from a number of bytes, with the B, KB, MB, or
1777
   * GB value. Note that the transition between abbreviations is by 1000 rather
1806
   * GB value. Note that the transition between abbreviations is by 1000 rather
1778
   * than 1024 in order to keep the displayed digits smaller as "1016 KB" is
1807
   * than 1024 in order to keep the displayed digits smaller as "1016 KB" is
1779
   * more awkward than 0.99 MB"
1808
   * more awkward than 0.99 MB"
 Lines 1895-1910   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
1895
        codeNode.setAttribute("value", value.status);
1924
        codeNode.setAttribute("value", value.status);
1896
        break;
1925
        break;
1897
      }
1926
      }
1898
      case "statusText": {
1927
      case "statusText": {
1899
        let node = $(".requests-menu-status", target);
1928
        let node = $(".requests-menu-status", target);
1900
        node.setAttribute("tooltiptext", value);
1929
        node.setAttribute("tooltiptext", value);
1901
        break;
1930
        break;
1902
      }
1931
      }
1932
      case "cause": {
1933
        let node = $(".requests-menu-cause", target);
1934
        let text = LOAD_CAUSE_STRINGS[value.type] || "unknown";
1935
        node.setAttribute("value", text);
1936
        if (value.loadingDocumentUri) {
1937
          node.setAttribute("tooltiptext", value.loadingDocumentUri);
1938
        }
1939
        break;
1940
      }
1903
      case "contentSize": {
1941
      case "contentSize": {
1904
        let node = $(".requests-menu-size", target);
1942
        let node = $(".requests-menu-size", target);
1905
1943
1906
        let text = this.getFormattedSize(value);
1944
        let text = this.getFormattedSize(value);
1907
1945
1908
        node.setAttribute("value", text);
1946
        node.setAttribute("value", text);
1909
        node.setAttribute("tooltiptext", text);
1947
        node.setAttribute("tooltiptext", text);
1910
        break;
1948
        break;
 Lines 2225-2245   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
2225
    }
2263
    }
2226
  },
2264
  },
2227
2265
2228
  /**
2266
  /**
2229
   * The swap listener for this container.
2267
   * The swap listener for this container.
2230
   * Called when two items switch places, when the contents are sorted.
2268
   * Called when two items switch places, when the contents are sorted.
2231
   */
2269
   */
2232
  _onSwap: function ({ detail: [firstItem, secondItem] }) {
2270
  _onSwap: function ({ detail: [firstItem, secondItem] }) {
2233
    // Sorting will create new anchor nodes for all the swapped request items
2234
    // in this container, so it's necessary to refresh the Tooltip instances.
2235
    this.refreshTooltip(firstItem);
2236
    this.refreshTooltip(secondItem);
2237
2238
    // Reattach click listener to the security icons
2271
    // Reattach click listener to the security icons
2239
    this.attachSecurityIconClickListener(firstItem);
2272
    this.attachSecurityIconClickListener(firstItem);
2240
    this.attachSecurityIconClickListener(secondItem);
2273
    this.attachSecurityIconClickListener(secondItem);
2241
  },
2274
  },
2242
2275
2243
  /**
2276
  /**
2244
   * The predicate used when deciding whether a popup should be shown
2277
   * The predicate used when deciding whether a popup should be shown
2245
   * over a request item or not.
2278
   * over a request item or not.
 Lines 2247-2281   RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { Link Here 
2247
   * @param nsIDOMNode target
2280
   * @param nsIDOMNode target
2248
   *        The element node currently being hovered.
2281
   *        The element node currently being hovered.
2249
   * @param object tooltip
2282
   * @param object tooltip
2250
   *        The current tooltip instance.
2283
   *        The current tooltip instance.
2251
   * @return {Promise}
2284
   * @return {Promise}
2252
   */
2285
   */
2253
  _onHover: Task.async(function* (target, tooltip) {
2286
  _onHover: Task.async(function* (target, tooltip) {
2254
    let requestItem = this.getItemForElement(target);
2287
    let requestItem = this.getItemForElement(target);
2255
    if (!requestItem || !requestItem.attachment.responseContent) {
2288
    if (!requestItem) {
2256
      return false;
2289
      return false;
2257
    }
2290
    }
2258
2291
2259
    let hovered = requestItem.attachment;
2292
    let hovered = requestItem.attachment;
2260
    let { mimeType, text, encoding } = hovered.responseContent.content;
2293
    if (hovered.responseContent &&
2261
2294
        target.closest(".requests-menu-icon-and-file", requestItem.target)) {
2262
    if (mimeType && mimeType.includes("image/") && (
2295
      let { mimeType, text, encoding } = hovered.responseContent.content;
2263
      target.classList.contains("requests-menu-icon") ||
2296
2264
      target.classList.contains("requests-menu-file"))) {
2297
      if (mimeType && mimeType.includes("image/")) {
2265
      let string = yield gNetwork.getString(text);
2298
        let string = yield gNetwork.getString(text);
2266
      let anchor = $(".requests-menu-icon", requestItem.target);
2299
        let anchor = $(".requests-menu-icon", requestItem.target);
2267
      let src = formDataURI(mimeType, encoding, string);
2300
        let src = formDataURI(mimeType, encoding, string);
2268
2301
2269
      tooltip.setImageContent(src, {
2302
        tooltip.setImageContent(src, {
2270
        maxDim: REQUESTS_TOOLTIP_IMAGE_MAX_DIM
2303
          maxDim: REQUESTS_TOOLTIP_IMAGE_MAX_DIM
2271
      });
2304
        });
2272
      return anchor;
2305
2306
        return anchor;
2307
      }
2308
    } else if (hovered.cause &&
2309
               target.closest(".requests-menu-cause", requestItem.target)) {
2310
      let stack = hovered.cause.stacktrace;
2311
      if (stack && stack.length > 0) {
2312
        let doc = tooltip.doc;
2313
        let el = doc.createElement("vbox");
2314
2315
        for (let s of stack) {
2316
          let { functionName, filename, lineNumber, columnNumber } = s;
2317
          functionName = functionName || "anonymous";
2318
2319
          let sel = doc.createElement("label");
2320
          sel.className = "devtools-monospace";
2321
          sel.setAttribute("value",
2322
            `${functionName} @ ${filename}:${lineNumber}:${columnNumber}`);
2323
          sel.addEventListener("click", () => {
2324
            NetMonitorController.viewSourceInDebugger(filename, lineNumber);
2325
          }, false);
2326
2327
          el.appendChild(sel);
2328
        }
2329
2330
        tooltip.content = el;
2331
2332
        return true;
2333
      }
2273
    }
2334
    }
2335
2274
    return false;
2336
    return false;
2275
  }),
2337
  }),
2276
2338
2277
  /**
2339
  /**
2278
   * A handler that opens the security tab in the details view if secure or
2340
   * A handler that opens the security tab in the details view if secure or
2279
   * broken security indicator is clicked.
2341
   * broken security indicator is clicked.
2280
   */
2342
   */
2281
  _onSecurityIconClick: function (e) {
2343
  _onSecurityIconClick: function (e) {
(-)a/devtools/client/netmonitor/netmonitor.xul (+13 lines)
Line     Link Here 
 Lines 216-231    Link Here 
216
                <button id="requests-menu-domain-button"
216
                <button id="requests-menu-domain-button"
217
                        class="requests-menu-header-button requests-menu-security-and-domain"
217
                        class="requests-menu-header-button requests-menu-security-and-domain"
218
                        data-key="domain"
218
                        data-key="domain"
219
                        label="&netmonitorUI.toolbar.domain;"
219
                        label="&netmonitorUI.toolbar.domain;"
220
                        crop="end"
220
                        crop="end"
221
                        flex="1">
221
                        flex="1">
222
                </button>
222
                </button>
223
              </hbox>
223
              </hbox>
224
              <hbox id="requests-menu-cause-header-box"
225
                    class="requests-menu-header requests-menu-cause"
226
                    align="center">
227
                <button id="requests-menu-cause-button"
228
                        class="requests-menu-header-button requests-menu-cause"
229
                        data-key="cause"
230
                        label="&netmonitorUI.toolbar.cause;"
231
                        crop="end"
232
                        flex="1">
233
                </button>
234
              </hbox>
224
              <hbox id="requests-menu-type-header-box"
235
              <hbox id="requests-menu-type-header-box"
225
                    class="requests-menu-header requests-menu-type"
236
                    class="requests-menu-header requests-menu-type"
226
                    align="center">
237
                    align="center">
227
                <button id="requests-menu-type-button"
238
                <button id="requests-menu-type-button"
228
                        class="requests-menu-header-button requests-menu-type"
239
                        class="requests-menu-header-button requests-menu-type"
229
                        data-key="type"
240
                        data-key="type"
230
                        label="&netmonitorUI.toolbar.type;"
241
                        label="&netmonitorUI.toolbar.type;"
231
                        crop="end"
242
                        crop="end"
 Lines 318-333    Link Here 
318
              </hbox>
329
              </hbox>
319
              <hbox class="requests-menu-subitem requests-menu-security-and-domain"
330
              <hbox class="requests-menu-subitem requests-menu-security-and-domain"
320
                    align="center">
331
                    align="center">
321
                <image class="requests-security-state-icon" />
332
                <image class="requests-security-state-icon" />
322
                <label class="plain requests-menu-domain"
333
                <label class="plain requests-menu-domain"
323
                       crop="end"
334
                       crop="end"
324
                       flex="1"/>
335
                       flex="1"/>
325
              </hbox>
336
              </hbox>
337
              <label class="plain requests-menu-subitem requests-menu-cause"
338
                     crop="end"/>
326
              <label class="plain requests-menu-subitem requests-menu-type"
339
              <label class="plain requests-menu-subitem requests-menu-type"
327
                     crop="end"/>
340
                     crop="end"/>
328
              <label class="plain requests-menu-subitem requests-menu-transferred"
341
              <label class="plain requests-menu-subitem requests-menu-transferred"
329
                     crop="end"/>
342
                     crop="end"/>
330
              <label class="plain requests-menu-subitem requests-menu-size"
343
              <label class="plain requests-menu-subitem requests-menu-size"
331
                     crop="end"/>
344
                     crop="end"/>
332
              <hbox class="requests-menu-subitem requests-menu-waterfall"
345
              <hbox class="requests-menu-subitem requests-menu-waterfall"
333
                    align="center"
346
                    align="center"
(-)a/devtools/client/netmonitor/panel.js (+1 lines)
Line     Link Here 
 Lines 11-26   const { Task } = require("devtools/shared/task"); Link Here 
11
11
12
function NetMonitorPanel(iframeWindow, toolbox) {
12
function NetMonitorPanel(iframeWindow, toolbox) {
13
  this.panelWin = iframeWindow;
13
  this.panelWin = iframeWindow;
14
  this._toolbox = toolbox;
14
  this._toolbox = toolbox;
15
15
16
  this._view = this.panelWin.NetMonitorView;
16
  this._view = this.panelWin.NetMonitorView;
17
  this._controller = this.panelWin.NetMonitorController;
17
  this._controller = this.panelWin.NetMonitorController;
18
  this._controller._target = this.target;
18
  this._controller._target = this.target;
19
  this._controller._toolbox = this._toolbox;
19
20
20
  EventEmitter.decorate(this);
21
  EventEmitter.decorate(this);
21
}
22
}
22
23
23
exports.NetMonitorPanel = NetMonitorPanel;
24
exports.NetMonitorPanel = NetMonitorPanel;
24
25
25
NetMonitorPanel.prototype = {
26
NetMonitorPanel.prototype = {
26
  /**
27
  /**
(-)a/devtools/client/themes/netmonitor.css (+1 lines)
Line     Link Here 
 Lines 234-249    Link Here 
234
.security-state-broken {
234
.security-state-broken {
235
  list-style-image: url(chrome://devtools/skin/images/security-state-broken.svg);
235
  list-style-image: url(chrome://devtools/skin/images/security-state-broken.svg);
236
}
236
}
237
237
238
.security-state-local {
238
.security-state-local {
239
  list-style-image: url(chrome://devtools/skin/images/security-state-local.svg);
239
  list-style-image: url(chrome://devtools/skin/images/security-state-local.svg);
240
}
240
}
241
241
242
.requests-menu-cause,
242
.requests-menu-type,
243
.requests-menu-type,
243
.requests-menu-size {
244
.requests-menu-size {
244
  max-width: 6em;
245
  max-width: 6em;
245
  text-align: center;
246
  text-align: center;
246
  width: 8vw;
247
  width: 8vw;
247
}
248
}
248
249
249
.requests-menu-transferred {
250
.requests-menu-transferred {

Return to bug 1134073