|
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 module.metadata = { |
|
8 "stability": "experimental" |
|
9 }; |
|
10 |
|
11 const { Ci } = require("chrome"); |
|
12 const { open } = require("../event/dom"); |
|
13 const { observe } = require("../event/chrome"); |
|
14 const { filter, merge, map, expand } = require("../event/utils"); |
|
15 const { windows } = require("../window/utils"); |
|
16 const { events: windowEvents } = require("sdk/window/events"); |
|
17 |
|
18 // Note: Please note that even though pagehide event is included |
|
19 // it's not observable reliably since it's not always triggered |
|
20 // when closing tabs. Implementation can be imrpoved once that |
|
21 // event will be necessary. |
|
22 let TYPES = ["DOMContentLoaded", "load", "pageshow", "pagehide"]; |
|
23 |
|
24 let insert = observe("document-element-inserted"); |
|
25 let windowCreate = merge([ |
|
26 observe("content-document-global-created"), |
|
27 observe("chrome-document-global-created") |
|
28 ]); |
|
29 let create = map(windowCreate, function({target, data, type}) { |
|
30 return { target: target.document, type: type, data: data } |
|
31 }); |
|
32 |
|
33 function streamEventsFrom({document}) { |
|
34 // Map supported event types to a streams of those events on the given |
|
35 // `window` for the inserted document and than merge these streams into |
|
36 // single form stream off all window state change events. |
|
37 let stateChanges = TYPES.map(function(type) { |
|
38 return open(document, type, { capture: true }); |
|
39 }); |
|
40 |
|
41 // Since load events on document occur for every loded resource |
|
42 return filter(merge(stateChanges), function({target}) { |
|
43 return target instanceof Ci.nsIDOMDocument |
|
44 }) |
|
45 } |
|
46 exports.streamEventsFrom = streamEventsFrom; |
|
47 |
|
48 let opened = windows(null, { includePrivate: true }); |
|
49 let state = merge(opened.map(streamEventsFrom)); |
|
50 |
|
51 |
|
52 let futureReady = filter(windowEvents, function({type}) |
|
53 type === "DOMContentLoaded"); |
|
54 let futureWindows = map(futureReady, function({target}) target); |
|
55 let futureState = expand(futureWindows, streamEventsFrom); |
|
56 |
|
57 exports.events = merge([insert, create, state, futureState]); |