netmonitor-controller.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* globals window, document, NetMonitorView, gStore, Actions */
  6. /* exported loader */
  7. "use strict";
  8. var { utils: Cu } = Components;
  9. // Descriptions for what this frontend is currently doing.
  10. const ACTIVITY_TYPE = {
  11. // Standing by and handling requests normally.
  12. NONE: 0,
  13. // Forcing the target to reload with cache enabled or disabled.
  14. RELOAD: {
  15. WITH_CACHE_ENABLED: 1,
  16. WITH_CACHE_DISABLED: 2,
  17. WITH_CACHE_DEFAULT: 3
  18. },
  19. // Enabling or disabling the cache without triggering a reload.
  20. ENABLE_CACHE: 3,
  21. DISABLE_CACHE: 4
  22. };
  23. var BrowserLoaderModule = {};
  24. Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
  25. var { loader, require } = BrowserLoaderModule.BrowserLoader({
  26. baseURI: "resource://devtools/client/netmonitor/",
  27. window
  28. });
  29. const promise = require("promise");
  30. const Services = require("Services");
  31. /* eslint-disable mozilla/reject-some-requires */
  32. const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
  33. const EventEmitter = require("devtools/shared/event-emitter");
  34. const Editor = require("devtools/client/sourceeditor/editor");
  35. const {TimelineFront} = require("devtools/shared/fronts/timeline");
  36. const {Task} = require("devtools/shared/task");
  37. const {Prefs} = require("./prefs");
  38. const {EVENTS} = require("./events");
  39. const Actions = require("./actions/index");
  40. XPCOMUtils.defineConstant(this, "EVENTS", EVENTS);
  41. XPCOMUtils.defineConstant(this, "ACTIVITY_TYPE", ACTIVITY_TYPE);
  42. XPCOMUtils.defineConstant(this, "Editor", Editor);
  43. XPCOMUtils.defineConstant(this, "Prefs", Prefs);
  44. XPCOMUtils.defineLazyModuleGetter(this, "Chart",
  45. "resource://devtools/client/shared/widgets/Chart.jsm");
  46. XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
  47. "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
  48. Object.defineProperty(this, "NetworkHelper", {
  49. get: function () {
  50. return require("devtools/shared/webconsole/network-helper");
  51. },
  52. configurable: true,
  53. enumerable: true
  54. });
  55. /**
  56. * Object defining the network monitor controller components.
  57. */
  58. var NetMonitorController = {
  59. /**
  60. * Initializes the view and connects the monitor client.
  61. *
  62. * @return object
  63. * A promise that is resolved when the monitor finishes startup.
  64. */
  65. startupNetMonitor: Task.async(function* () {
  66. if (this._startup) {
  67. return this._startup.promise;
  68. }
  69. this._startup = promise.defer();
  70. {
  71. NetMonitorView.initialize();
  72. yield this.connect();
  73. }
  74. this._startup.resolve();
  75. return undefined;
  76. }),
  77. /**
  78. * Destroys the view and disconnects the monitor client from the server.
  79. *
  80. * @return object
  81. * A promise that is resolved when the monitor finishes shutdown.
  82. */
  83. shutdownNetMonitor: Task.async(function* () {
  84. if (this._shutdown) {
  85. return this._shutdown.promise;
  86. }
  87. this._shutdown = promise.defer();
  88. {
  89. NetMonitorView.destroy();
  90. this.TargetEventsHandler.disconnect();
  91. this.NetworkEventsHandler.disconnect();
  92. yield this.disconnect();
  93. }
  94. this._shutdown.resolve();
  95. return undefined;
  96. }),
  97. /**
  98. * Initiates remote or chrome network monitoring based on the current target,
  99. * wiring event handlers as necessary. Since the TabTarget will have already
  100. * started listening to network requests by now, this is largely
  101. * netmonitor-specific initialization.
  102. *
  103. * @return object
  104. * A promise that is resolved when the monitor finishes connecting.
  105. */
  106. connect: Task.async(function* () {
  107. if (this._connection) {
  108. return this._connection.promise;
  109. }
  110. this._connection = promise.defer();
  111. // Some actors like AddonActor or RootActor for chrome debugging
  112. // aren't actual tabs.
  113. if (this._target.isTabActor) {
  114. this.tabClient = this._target.activeTab;
  115. }
  116. let connectTimeline = () => {
  117. // Don't start up waiting for timeline markers if the server isn't
  118. // recent enough to emit the markers we're interested in.
  119. if (this._target.getTrait("documentLoadingMarkers")) {
  120. this.timelineFront = new TimelineFront(this._target.client,
  121. this._target.form);
  122. return this.timelineFront.start({ withDocLoadingEvents: true });
  123. }
  124. return undefined;
  125. };
  126. this.webConsoleClient = this._target.activeConsole;
  127. yield connectTimeline();
  128. this.TargetEventsHandler.connect();
  129. this.NetworkEventsHandler.connect();
  130. window.emit(EVENTS.CONNECTED);
  131. this._connection.resolve();
  132. this._connected = true;
  133. return undefined;
  134. }),
  135. /**
  136. * Disconnects the debugger client and removes event handlers as necessary.
  137. */
  138. disconnect: Task.async(function* () {
  139. if (this._disconnection) {
  140. return this._disconnection.promise;
  141. }
  142. this._disconnection = promise.defer();
  143. // Wait for the connection to finish first.
  144. if (!this.isConnected()) {
  145. yield this._connection.promise;
  146. }
  147. // When debugging local or a remote instance, the connection is closed by
  148. // the RemoteTarget. The webconsole actor is stopped on disconnect.
  149. this.tabClient = null;
  150. this.webConsoleClient = null;
  151. // The timeline front wasn't initialized and started if the server wasn't
  152. // recent enough to emit the markers we were interested in.
  153. if (this._target.getTrait("documentLoadingMarkers")) {
  154. yield this.timelineFront.destroy();
  155. this.timelineFront = null;
  156. }
  157. this._disconnection.resolve();
  158. this._connected = false;
  159. return undefined;
  160. }),
  161. /**
  162. * Checks whether the netmonitor connection is active.
  163. * @return boolean
  164. */
  165. isConnected: function () {
  166. return !!this._connected;
  167. },
  168. /**
  169. * Gets the activity currently performed by the frontend.
  170. * @return number
  171. */
  172. getCurrentActivity: function () {
  173. return this._currentActivity || ACTIVITY_TYPE.NONE;
  174. },
  175. /**
  176. * Triggers a specific "activity" to be performed by the frontend.
  177. * This can be, for example, triggering reloads or enabling/disabling cache.
  178. *
  179. * @param number type
  180. * The activity type. See the ACTIVITY_TYPE const.
  181. * @return object
  182. * A promise resolved once the activity finishes and the frontend
  183. * is back into "standby" mode.
  184. */
  185. triggerActivity: function (type) {
  186. // Puts the frontend into "standby" (when there's no particular activity).
  187. let standBy = () => {
  188. this._currentActivity = ACTIVITY_TYPE.NONE;
  189. };
  190. // Waits for a series of "navigation start" and "navigation stop" events.
  191. let waitForNavigation = () => {
  192. let deferred = promise.defer();
  193. this._target.once("will-navigate", () => {
  194. this._target.once("navigate", () => {
  195. deferred.resolve();
  196. });
  197. });
  198. return deferred.promise;
  199. };
  200. // Reconfigures the tab, optionally triggering a reload.
  201. let reconfigureTab = options => {
  202. let deferred = promise.defer();
  203. this._target.activeTab.reconfigure(options, deferred.resolve);
  204. return deferred.promise;
  205. };
  206. // Reconfigures the tab and waits for the target to finish navigating.
  207. let reconfigureTabAndWaitForNavigation = options => {
  208. options.performReload = true;
  209. let navigationFinished = waitForNavigation();
  210. return reconfigureTab(options).then(() => navigationFinished);
  211. };
  212. if (type == ACTIVITY_TYPE.RELOAD.WITH_CACHE_DEFAULT) {
  213. return reconfigureTabAndWaitForNavigation({}).then(standBy);
  214. }
  215. if (type == ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED) {
  216. this._currentActivity = ACTIVITY_TYPE.ENABLE_CACHE;
  217. this._target.once("will-navigate", () => {
  218. this._currentActivity = type;
  219. });
  220. return reconfigureTabAndWaitForNavigation({
  221. cacheDisabled: false,
  222. performReload: true
  223. }).then(standBy);
  224. }
  225. if (type == ACTIVITY_TYPE.RELOAD.WITH_CACHE_DISABLED) {
  226. this._currentActivity = ACTIVITY_TYPE.DISABLE_CACHE;
  227. this._target.once("will-navigate", () => {
  228. this._currentActivity = type;
  229. });
  230. return reconfigureTabAndWaitForNavigation({
  231. cacheDisabled: true,
  232. performReload: true
  233. }).then(standBy);
  234. }
  235. if (type == ACTIVITY_TYPE.ENABLE_CACHE) {
  236. this._currentActivity = type;
  237. return reconfigureTab({
  238. cacheDisabled: false,
  239. performReload: false
  240. }).then(standBy);
  241. }
  242. if (type == ACTIVITY_TYPE.DISABLE_CACHE) {
  243. this._currentActivity = type;
  244. return reconfigureTab({
  245. cacheDisabled: true,
  246. performReload: false
  247. }).then(standBy);
  248. }
  249. this._currentActivity = ACTIVITY_TYPE.NONE;
  250. return promise.reject(new Error("Invalid activity type"));
  251. },
  252. /**
  253. * Selects the specified request in the waterfall and opens the details view.
  254. *
  255. * @param string requestId
  256. * The actor ID of the request to inspect.
  257. * @return object
  258. * A promise resolved once the task finishes.
  259. */
  260. inspectRequest: function (requestId) {
  261. // Look for the request in the existing ones or wait for it to appear, if
  262. // the network monitor is still loading.
  263. let deferred = promise.defer();
  264. let request = null;
  265. let inspector = function () {
  266. let predicate = i => i.value === requestId;
  267. request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
  268. if (!request) {
  269. // Reset filters so that the request is visible.
  270. gStore.dispatch(Actions.toggleFilterType("all"));
  271. request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
  272. }
  273. // If the request was found, select it. Otherwise this function will be
  274. // called again once new requests arrive.
  275. if (request) {
  276. window.off(EVENTS.REQUEST_ADDED, inspector);
  277. NetMonitorView.RequestsMenu.selectedItem = request;
  278. deferred.resolve();
  279. }
  280. };
  281. inspector();
  282. if (!request) {
  283. window.on(EVENTS.REQUEST_ADDED, inspector);
  284. }
  285. return deferred.promise;
  286. },
  287. /**
  288. * Getter that tells if the server supports sending custom network requests.
  289. * @type boolean
  290. */
  291. get supportsCustomRequest() {
  292. return this.webConsoleClient &&
  293. (this.webConsoleClient.traits.customNetworkRequest ||
  294. !this._target.isApp);
  295. },
  296. /**
  297. * Getter that tells if the server includes the transferred (compressed /
  298. * encoded) response size.
  299. * @type boolean
  300. */
  301. get supportsTransferredResponseSize() {
  302. return this.webConsoleClient &&
  303. this.webConsoleClient.traits.transferredResponseSize;
  304. },
  305. /**
  306. * Getter that tells if the server can do network performance statistics.
  307. * @type boolean
  308. */
  309. get supportsPerfStats() {
  310. return this.tabClient &&
  311. (this.tabClient.traits.reconfigure || !this._target.isApp);
  312. },
  313. /**
  314. * Open a given source in Debugger
  315. */
  316. viewSourceInDebugger(sourceURL, sourceLine) {
  317. return this._toolbox.viewSourceInDebugger(sourceURL, sourceLine);
  318. }
  319. };
  320. /**
  321. * Functions handling target-related lifetime events.
  322. */
  323. function TargetEventsHandler() {
  324. this._onTabNavigated = this._onTabNavigated.bind(this);
  325. this._onTabDetached = this._onTabDetached.bind(this);
  326. }
  327. TargetEventsHandler.prototype = {
  328. get target() {
  329. return NetMonitorController._target;
  330. },
  331. /**
  332. * Listen for events emitted by the current tab target.
  333. */
  334. connect: function () {
  335. dumpn("TargetEventsHandler is connecting...");
  336. this.target.on("close", this._onTabDetached);
  337. this.target.on("navigate", this._onTabNavigated);
  338. this.target.on("will-navigate", this._onTabNavigated);
  339. },
  340. /**
  341. * Remove events emitted by the current tab target.
  342. */
  343. disconnect: function () {
  344. if (!this.target) {
  345. return;
  346. }
  347. dumpn("TargetEventsHandler is disconnecting...");
  348. this.target.off("close", this._onTabDetached);
  349. this.target.off("navigate", this._onTabNavigated);
  350. this.target.off("will-navigate", this._onTabNavigated);
  351. },
  352. /**
  353. * Called for each location change in the monitored tab.
  354. *
  355. * @param string type
  356. * Packet type.
  357. * @param object packet
  358. * Packet received from the server.
  359. */
  360. _onTabNavigated: function (type, packet) {
  361. switch (type) {
  362. case "will-navigate": {
  363. // Reset UI.
  364. if (!Services.prefs.getBoolPref("devtools.webconsole.persistlog")) {
  365. NetMonitorView.RequestsMenu.reset();
  366. NetMonitorView.Sidebar.toggle(false);
  367. } else {
  368. // If the log is persistent, just clear some informations.
  369. NetMonitorView.RequestsMenu.resetNotPersistent();
  370. }
  371. // Switch to the default network traffic inspector view.
  372. if (NetMonitorController.getCurrentActivity() == ACTIVITY_TYPE.NONE) {
  373. NetMonitorView.showNetworkInspectorView();
  374. }
  375. // Clear any accumulated markers.
  376. NetMonitorController.NetworkEventsHandler.clearMarkers();
  377. gStore.dispatch(Actions.clearTimingMarkers());
  378. window.emit(EVENTS.TARGET_WILL_NAVIGATE);
  379. break;
  380. }
  381. case "navigate": {
  382. window.emit(EVENTS.TARGET_DID_NAVIGATE);
  383. break;
  384. }
  385. }
  386. },
  387. /**
  388. * Called when the monitored tab is closed.
  389. */
  390. _onTabDetached: function () {
  391. NetMonitorController.shutdownNetMonitor();
  392. }
  393. };
  394. /**
  395. * Functions handling target network events.
  396. */
  397. function NetworkEventsHandler() {
  398. this._markers = [];
  399. this._onNetworkEvent = this._onNetworkEvent.bind(this);
  400. this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
  401. this._onDocLoadingMarker = this._onDocLoadingMarker.bind(this);
  402. this._onRequestHeaders = this._onRequestHeaders.bind(this);
  403. this._onRequestCookies = this._onRequestCookies.bind(this);
  404. this._onRequestPostData = this._onRequestPostData.bind(this);
  405. this._onResponseHeaders = this._onResponseHeaders.bind(this);
  406. this._onResponseCookies = this._onResponseCookies.bind(this);
  407. this._onResponseContent = this._onResponseContent.bind(this);
  408. this._onEventTimings = this._onEventTimings.bind(this);
  409. }
  410. NetworkEventsHandler.prototype = {
  411. get client() {
  412. return NetMonitorController._target.client;
  413. },
  414. get webConsoleClient() {
  415. return NetMonitorController.webConsoleClient;
  416. },
  417. get timelineFront() {
  418. return NetMonitorController.timelineFront;
  419. },
  420. get firstDocumentDOMContentLoadedTimestamp() {
  421. let marker = this._markers.filter(e => {
  422. return e.name == "document::DOMContentLoaded";
  423. })[0];
  424. return marker ? marker.unixTime / 1000 : -1;
  425. },
  426. get firstDocumentLoadTimestamp() {
  427. let marker = this._markers.filter(e => e.name == "document::Load")[0];
  428. return marker ? marker.unixTime / 1000 : -1;
  429. },
  430. /**
  431. * Connect to the current target client.
  432. */
  433. connect: function () {
  434. dumpn("NetworkEventsHandler is connecting...");
  435. this.webConsoleClient.on("networkEvent", this._onNetworkEvent);
  436. this.webConsoleClient.on("networkEventUpdate", this._onNetworkEventUpdate);
  437. if (this.timelineFront) {
  438. this.timelineFront.on("doc-loading", this._onDocLoadingMarker);
  439. }
  440. this._displayCachedEvents();
  441. },
  442. /**
  443. * Disconnect from the client.
  444. */
  445. disconnect: function () {
  446. if (!this.client) {
  447. return;
  448. }
  449. dumpn("NetworkEventsHandler is disconnecting...");
  450. this.webConsoleClient.off("networkEvent", this._onNetworkEvent);
  451. this.webConsoleClient.off("networkEventUpdate", this._onNetworkEventUpdate);
  452. if (this.timelineFront) {
  453. this.timelineFront.off("doc-loading", this._onDocLoadingMarker);
  454. }
  455. },
  456. /**
  457. * Display any network events already in the cache.
  458. */
  459. _displayCachedEvents: function () {
  460. for (let cachedEvent of this.webConsoleClient.getNetworkEvents()) {
  461. // First add the request to the timeline.
  462. this._onNetworkEvent("networkEvent", cachedEvent);
  463. // Then replay any updates already received.
  464. for (let update of cachedEvent.updates) {
  465. this._onNetworkEventUpdate("networkEventUpdate", {
  466. packet: {
  467. updateType: update
  468. },
  469. networkInfo: cachedEvent
  470. });
  471. }
  472. }
  473. },
  474. /**
  475. * The "DOMContentLoaded" and "Load" events sent by the timeline actor.
  476. * @param object marker
  477. */
  478. _onDocLoadingMarker: function (marker) {
  479. window.emit(EVENTS.TIMELINE_EVENT, marker);
  480. this._markers.push(marker);
  481. gStore.dispatch(Actions.addTimingMarker(marker));
  482. },
  483. /**
  484. * The "networkEvent" message type handler.
  485. *
  486. * @param string type
  487. * Message type.
  488. * @param object networkInfo
  489. * The network request information.
  490. */
  491. _onNetworkEvent: function (type, networkInfo) {
  492. let { actor,
  493. startedDateTime,
  494. request: { method, url },
  495. isXHR,
  496. cause,
  497. fromCache,
  498. fromServiceWorker
  499. } = networkInfo;
  500. NetMonitorView.RequestsMenu.addRequest(
  501. actor, startedDateTime, method, url, isXHR, cause, fromCache,
  502. fromServiceWorker
  503. );
  504. window.emit(EVENTS.NETWORK_EVENT, actor);
  505. },
  506. /**
  507. * The "networkEventUpdate" message type handler.
  508. *
  509. * @param string type
  510. * Message type.
  511. * @param object packet
  512. * The message received from the server.
  513. * @param object networkInfo
  514. * The network request information.
  515. */
  516. _onNetworkEventUpdate: function (type, { packet, networkInfo }) {
  517. let { actor } = networkInfo;
  518. switch (packet.updateType) {
  519. case "requestHeaders":
  520. this.webConsoleClient.getRequestHeaders(actor, this._onRequestHeaders);
  521. window.emit(EVENTS.UPDATING_REQUEST_HEADERS, actor);
  522. break;
  523. case "requestCookies":
  524. this.webConsoleClient.getRequestCookies(actor, this._onRequestCookies);
  525. window.emit(EVENTS.UPDATING_REQUEST_COOKIES, actor);
  526. break;
  527. case "requestPostData":
  528. this.webConsoleClient.getRequestPostData(actor,
  529. this._onRequestPostData);
  530. window.emit(EVENTS.UPDATING_REQUEST_POST_DATA, actor);
  531. break;
  532. case "securityInfo":
  533. NetMonitorView.RequestsMenu.updateRequest(actor, {
  534. securityState: networkInfo.securityInfo,
  535. });
  536. this.webConsoleClient.getSecurityInfo(actor, this._onSecurityInfo);
  537. window.emit(EVENTS.UPDATING_SECURITY_INFO, actor);
  538. break;
  539. case "responseHeaders":
  540. this.webConsoleClient.getResponseHeaders(actor,
  541. this._onResponseHeaders);
  542. window.emit(EVENTS.UPDATING_RESPONSE_HEADERS, actor);
  543. break;
  544. case "responseCookies":
  545. this.webConsoleClient.getResponseCookies(actor,
  546. this._onResponseCookies);
  547. window.emit(EVENTS.UPDATING_RESPONSE_COOKIES, actor);
  548. break;
  549. case "responseStart":
  550. NetMonitorView.RequestsMenu.updateRequest(actor, {
  551. httpVersion: networkInfo.response.httpVersion,
  552. remoteAddress: networkInfo.response.remoteAddress,
  553. remotePort: networkInfo.response.remotePort,
  554. status: networkInfo.response.status,
  555. statusText: networkInfo.response.statusText,
  556. headersSize: networkInfo.response.headersSize
  557. });
  558. window.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
  559. break;
  560. case "responseContent":
  561. NetMonitorView.RequestsMenu.updateRequest(actor, {
  562. contentSize: networkInfo.response.bodySize,
  563. transferredSize: networkInfo.response.transferredSize,
  564. mimeType: networkInfo.response.content.mimeType
  565. });
  566. this.webConsoleClient.getResponseContent(actor,
  567. this._onResponseContent);
  568. window.emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
  569. break;
  570. case "eventTimings":
  571. NetMonitorView.RequestsMenu.updateRequest(actor, {
  572. totalTime: networkInfo.totalTime
  573. });
  574. this.webConsoleClient.getEventTimings(actor, this._onEventTimings);
  575. window.emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
  576. break;
  577. }
  578. },
  579. /**
  580. * Handles additional information received for a "requestHeaders" packet.
  581. *
  582. * @param object response
  583. * The message received from the server.
  584. */
  585. _onRequestHeaders: function (response) {
  586. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  587. requestHeaders: response
  588. }, () => {
  589. window.emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
  590. });
  591. },
  592. /**
  593. * Handles additional information received for a "requestCookies" packet.
  594. *
  595. * @param object response
  596. * The message received from the server.
  597. */
  598. _onRequestCookies: function (response) {
  599. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  600. requestCookies: response
  601. }, () => {
  602. window.emit(EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
  603. });
  604. },
  605. /**
  606. * Handles additional information received for a "requestPostData" packet.
  607. *
  608. * @param object response
  609. * The message received from the server.
  610. */
  611. _onRequestPostData: function (response) {
  612. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  613. requestPostData: response
  614. }, () => {
  615. window.emit(EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
  616. });
  617. },
  618. /**
  619. * Handles additional information received for a "securityInfo" packet.
  620. *
  621. * @param object response
  622. * The message received from the server.
  623. */
  624. _onSecurityInfo: function (response) {
  625. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  626. securityInfo: response.securityInfo
  627. }, () => {
  628. window.emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
  629. });
  630. },
  631. /**
  632. * Handles additional information received for a "responseHeaders" packet.
  633. *
  634. * @param object response
  635. * The message received from the server.
  636. */
  637. _onResponseHeaders: function (response) {
  638. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  639. responseHeaders: response
  640. }, () => {
  641. window.emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
  642. });
  643. },
  644. /**
  645. * Handles additional information received for a "responseCookies" packet.
  646. *
  647. * @param object response
  648. * The message received from the server.
  649. */
  650. _onResponseCookies: function (response) {
  651. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  652. responseCookies: response
  653. }, () => {
  654. window.emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
  655. });
  656. },
  657. /**
  658. * Handles additional information received for a "responseContent" packet.
  659. *
  660. * @param object response
  661. * The message received from the server.
  662. */
  663. _onResponseContent: function (response) {
  664. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  665. responseContent: response
  666. }, () => {
  667. window.emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
  668. });
  669. },
  670. /**
  671. * Handles additional information received for a "eventTimings" packet.
  672. *
  673. * @param object response
  674. * The message received from the server.
  675. */
  676. _onEventTimings: function (response) {
  677. NetMonitorView.RequestsMenu.updateRequest(response.from, {
  678. eventTimings: response
  679. }, () => {
  680. window.emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
  681. });
  682. },
  683. /**
  684. * Clears all accumulated markers.
  685. */
  686. clearMarkers: function () {
  687. this._markers.length = 0;
  688. },
  689. /**
  690. * Fetches the full text of a LongString.
  691. *
  692. * @param object | string stringGrip
  693. * The long string grip containing the corresponding actor.
  694. * If you pass in a plain string (by accident or because you're lazy),
  695. * then a promise of the same string is simply returned.
  696. * @return object Promise
  697. * A promise that is resolved when the full string contents
  698. * are available, or rejected if something goes wrong.
  699. */
  700. getString: function (stringGrip) {
  701. return this.webConsoleClient.getString(stringGrip);
  702. }
  703. };
  704. /**
  705. * Returns true if this is document is in RTL mode.
  706. * @return boolean
  707. */
  708. XPCOMUtils.defineLazyGetter(window, "isRTL", function () {
  709. return window.getComputedStyle(document.documentElement, null)
  710. .direction == "rtl";
  711. });
  712. /**
  713. * Convenient way of emitting events from the panel window.
  714. */
  715. EventEmitter.decorate(this);
  716. /**
  717. * Preliminary setup for the NetMonitorController object.
  718. */
  719. NetMonitorController.TargetEventsHandler = new TargetEventsHandler();
  720. NetMonitorController.NetworkEventsHandler = new NetworkEventsHandler();
  721. /**
  722. * Export some properties to the global scope for easier access.
  723. */
  724. Object.defineProperties(window, {
  725. "gNetwork": {
  726. get: function () {
  727. return NetMonitorController.NetworkEventsHandler;
  728. },
  729. configurable: true
  730. }
  731. });
  732. /**
  733. * Helper method for debugging.
  734. * @param string
  735. */
  736. function dumpn(str) {
  737. if (wantLogging) {
  738. dump("NET-FRONTEND: " + str + "\n");
  739. }
  740. }
  741. var wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");