browser.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. const { windows, isBrowser, isInteractive, isDocumentLoaded,
  6. getOuterId } = require("../window/utils");
  7. const { InputPort } = require("./system");
  8. const { lift, merges, foldp, keepIf, start, Input } = require("../event/utils");
  9. const { patch } = require("diffpatcher/index");
  10. const { Sequence, seq, filter, object, pairs } = require("../util/sequence");
  11. // Create lazy iterators from the regular arrays, although
  12. // once https://github.com/mozilla/addon-sdk/pull/1314 lands
  13. // `windows` will be transforme to lazy iterators.
  14. // When iterated over belowe sequences items will represent
  15. // state of windows at the time of iteration.
  16. const opened = seq(function*() {
  17. const items = windows("navigator:browser", {includePrivates: true});
  18. for (let item of items) {
  19. yield [getOuterId(item), item];
  20. }
  21. });
  22. const interactive = filter(([_, window]) => isInteractive(window), opened);
  23. const loaded = filter(([_, window]) => isDocumentLoaded(window), opened);
  24. // Helper function that converts given argument to a delta.
  25. const Update = window => window && object([getOuterId(window), window]);
  26. const Delete = window => window && object([getOuterId(window), null]);
  27. // Signal represents delta for last top level window close.
  28. const LastClosed = lift(Delete,
  29. keepIf(isBrowser, null,
  30. new InputPort({topic: "domwindowclosed"})));
  31. exports.LastClosed = LastClosed;
  32. const windowFor = document => document && document.defaultView;
  33. // Signal represent delta for last top level window document becoming interactive.
  34. const InteractiveDoc = new InputPort({topic: "chrome-document-interactive"});
  35. const InteractiveWin = lift(windowFor, InteractiveDoc);
  36. const LastInteractive = lift(Update, keepIf(isBrowser, null, InteractiveWin));
  37. exports.LastInteractive = LastInteractive;
  38. // Signal represent delta for last top level window loaded.
  39. const LoadedDoc = new InputPort({topic: "chrome-document-loaded"});
  40. const LoadedWin = lift(windowFor, LoadedDoc);
  41. const LastLoaded = lift(Update, keepIf(isBrowser, null, LoadedWin));
  42. exports.LastLoaded = LastLoaded;
  43. const initialize = input => {
  44. if (!input.initialized) {
  45. input.value = object(...input.value);
  46. Input.start(input);
  47. input.initialized = true;
  48. }
  49. };
  50. // Signal represents set of top level interactive windows, updated any
  51. // time new window becomes interactive or one get's closed.
  52. const Interactive = foldp(patch, interactive, merges([LastInteractive,
  53. LastClosed]));
  54. Interactive[start] = initialize;
  55. exports.Interactive = Interactive;
  56. // Signal represents set of top level loaded window, updated any time
  57. // new window becomes interactive or one get's closed.
  58. const Loaded = foldp(patch, loaded, merges([LastLoaded, LastClosed]));
  59. Loaded[start] = initialize;
  60. exports.Loaded = Loaded;