summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/app.js
blob: a41ae2156c5bbb40119b43a4f510bc172c0a78f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {
  createFactory,
} = require("resource://devtools/client/shared/vendor/react.js");
const {
  render,
  unmountComponentAtNode,
} = require("resource://devtools/client/shared/vendor/react-dom.js");
const Provider = createFactory(
  require("resource://devtools/client/shared/vendor/react-redux.js").Provider
);
const App = createFactory(
  require("resource://devtools/client/netmonitor/src/components/App.js")
);
const {
  EVENTS,
} = require("resource://devtools/client/netmonitor/src/constants.js");

const {
  getDisplayedRequestById,
} = require("resource://devtools/client/netmonitor/src/selectors/index.js");

const SearchDispatcher = require("resource://devtools/client/netmonitor/src/workers/search/index.js");

/**
 * Global App object for Network panel. This object depends
 * on the UI and can't be created independently.
 *
 * This object can be consumed by other panels (e.g. Console
 * is using inspectRequest), by the Launchpad (bootstrap), etc.
 *
 * @param {Object} api An existing API object to be reused.
 */
function NetMonitorApp(api) {
  this.api = api;
}

NetMonitorApp.prototype = {
  async bootstrap({ toolbox, document }) {
    // Get the root element for mounting.
    this.mount = document.querySelector("#mount");

    const openLink = link => {
      const parentDoc = toolbox.doc;
      const iframe = parentDoc.getElementById(
        "toolbox-panel-iframe-netmonitor"
      );
      const { top } = iframe.ownerDocument.defaultView;
      top.openWebLinkIn(link, "tab");
    };

    const openSplitConsole = err => {
      toolbox.openSplitConsole().then(() => {
        toolbox.target.logErrorInPage(err, "har");
      });
    };

    const { actions, connector, store } = this.api;

    const sourceMapURLService = toolbox.sourceMapURLService;
    const app = App({
      actions,
      connector,
      openLink,
      openSplitConsole,
      sourceMapURLService,
      toolboxDoc: toolbox.doc,
    });

    // Render the root Application component.
    render(Provider({ store }, app), this.mount);
  },

  /**
   * Clean up (unmount from DOM, remove listeners, disconnect).
   */
  destroy() {
    unmountComponentAtNode(this.mount);

    SearchDispatcher.stop();

    // Make sure to destroy the API object. It's usually destroyed
    // in the Toolbox destroy method, but we need it here for case
    // where the Network panel is initialized without the toolbox
    // and running in a tab (see initialize.js for details).
    this.api.destroy();
  },

  /**
   * Selects the specified request in the waterfall and opens the details view.
   * This is a firefox toolbox specific API, which providing an ability to inspect
   * a network request directly from other internal toolbox panel.
   *
   * @param {string} requestId The actor ID of the request to inspect.
   * @return {object} A promise resolved once the task finishes.
   */
  async inspectRequest(requestId) {
    const { actions, store } = this.api;

    // Look for the request in the existing ones or wait for it to appear,
    // if the network monitor is still loading.
    return new Promise(resolve => {
      let request = null;
      const inspector = () => {
        request = getDisplayedRequestById(store.getState(), requestId);
        if (!request) {
          // Reset filters so that the request is visible.
          actions.toggleRequestFilterType("all");
          request = getDisplayedRequestById(store.getState(), requestId);
        }

        // If the request was found, select it. Otherwise this function will be
        // called again once new requests arrive.
        if (request) {
          this.api.off(EVENTS.REQUEST_ADDED, inspector);
          actions.selectRequest(request.id);
          resolve();
        }
      };

      inspector();

      if (!request) {
        this.api.on(EVENTS.REQUEST_ADDED, inspector);
      }
    });
  },
};

exports.NetMonitorApp = NetMonitorApp;