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