events.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. // This module provides temporary shim until Bug 843901 is shipped.
  6. // It basically registers tab event listeners on all windows that get
  7. // opened and forwards them through observer notifications.
  8. module.metadata = {
  9. "stability": "experimental"
  10. };
  11. const { Ci } = require("chrome");
  12. const { windows, isInteractive } = require("../window/utils");
  13. const { events } = require("../browser/events");
  14. const { open } = require("../event/dom");
  15. const { filter, map, merge, expand } = require("../event/utils");
  16. const isFennec = require("sdk/system/xul-app").is("Fennec");
  17. // Module provides event stream (in nodejs style) that emits data events
  18. // for all the tab events that happen in running firefox. At the moment
  19. // it does it by registering listeners on all browser windows and then
  20. // forwarding events when they occur to a stream. This will become obsolete
  21. // once Bug 843901 is fixed, and we'll just leverage observer notifications.
  22. // Set of tab events that this module going to aggregate and expose.
  23. const TYPES = ["TabOpen","TabClose","TabSelect","TabMove","TabPinned",
  24. "TabUnpinned"];
  25. // Utility function that given a browser `window` returns stream of above
  26. // defined tab events for all tabs on the given window.
  27. function tabEventsFor(window) {
  28. // Map supported event types to a streams of those events on the given
  29. // `window` and than merge these streams into single form stream off
  30. // all events.
  31. let channels = TYPES.map(function(type) open(window, type));
  32. return merge(channels);
  33. }
  34. // Filter DOMContentLoaded events from all the browser events.
  35. let readyEvents = filter(events, function(e) e.type === "DOMContentLoaded");
  36. // Map DOMContentLoaded events to it's target browser windows.
  37. let futureWindows = map(readyEvents, function(e) e.target);
  38. // Expand all browsers that will become interactive to supported tab events
  39. // on these windows. Result will be a tab events from all tabs of all windows
  40. // that will become interactive.
  41. let eventsFromFuture = expand(futureWindows, tabEventsFor);
  42. // Above covers only windows that will become interactive in a future, but some
  43. // windows may already be interactive so we pick those and expand to supported
  44. // tab events for them too.
  45. let interactiveWindows = windows("navigator:browser", { includePrivate: true }).
  46. filter(isInteractive);
  47. let eventsFromInteractive = merge(interactiveWindows.map(tabEventsFor));
  48. // Finally merge stream of tab events from future windows and current windows
  49. // to cover all tab events on all windows that will open.
  50. let allEvents = merge([eventsFromInteractive, eventsFromFuture]);
  51. // Map events to Fennec format if necessary
  52. exports.events = map(allEvents, function (event) {
  53. return !isFennec ? event : {
  54. type: event.type,
  55. target: event.target.ownerDocument.defaultView.BrowserApp
  56. .getTabForBrowser(event.target)
  57. };
  58. });