|
1 |
|
2 let Cu = Components.utils; |
|
3 let Cc = Components.classes; |
|
4 let Ci = Components.interfaces; |
|
5 |
|
6 const URL1 = MAIN_DOMAIN + "navigate-first.html"; |
|
7 const URL2 = MAIN_DOMAIN + "navigate-second.html"; |
|
8 |
|
9 let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {}); |
|
10 let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {}); |
|
11 |
|
12 let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; |
|
13 let events = devtools.require("sdk/event/core"); |
|
14 |
|
15 let client; |
|
16 |
|
17 // State machine to check events order |
|
18 let i = 0; |
|
19 function assertEvent(event, data) { |
|
20 let x = 0; |
|
21 switch(i++) { |
|
22 case x++: |
|
23 is(event, "request", "Get first page load"); |
|
24 is(data, URL1); |
|
25 break; |
|
26 case x++: |
|
27 is(event, "load-new-document", "Ask to load the second page"); |
|
28 break; |
|
29 case x++: |
|
30 is(event, "unload-dialog", "We get the dialog on first page unload"); |
|
31 break; |
|
32 case x++: |
|
33 is(event, "will-navigate", "The very first event is will-navigate on server side"); |
|
34 is(data.newURI, URL2, "newURI property is correct"); |
|
35 break; |
|
36 case x++: |
|
37 is(event, "tabNavigated", "Right after will-navigate, the client receive tabNavigated"); |
|
38 is(data.state, "start", "state is start"); |
|
39 is(data.url, URL2, "url property is correct"); |
|
40 break; |
|
41 case x++: |
|
42 is(event, "request", "Given that locally, the Debugger protocol is sync, the request happens after tabNavigated"); |
|
43 is(data, URL2); |
|
44 break; |
|
45 case x++: |
|
46 is(event, "DOMContentLoaded"); |
|
47 is(content.document.readyState, "interactive"); |
|
48 break; |
|
49 case x++: |
|
50 is(event, "load"); |
|
51 is(content.document.readyState, "complete"); |
|
52 break; |
|
53 case x++: |
|
54 is(event, "navigate", "Then once the second doc is loaded, we get the navigate event"); |
|
55 is(content.document.readyState, "complete", "navigate is emitted only once the document is fully loaded"); |
|
56 break; |
|
57 case x++: |
|
58 is(event, "tabNavigated", "Finally, the receive the client event"); |
|
59 is(data.state, "stop", "state is stop"); |
|
60 is(data.url, URL2, "url property is correct"); |
|
61 |
|
62 // End of test! |
|
63 cleanup(); |
|
64 break; |
|
65 } |
|
66 } |
|
67 |
|
68 function waitForOnBeforeUnloadDialog(browser, callback) { |
|
69 browser.addEventListener("DOMWillOpenModalDialog", function onModalDialog() { |
|
70 browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true); |
|
71 |
|
72 executeSoon(() => { |
|
73 let stack = browser.parentNode; |
|
74 let dialogs = stack.getElementsByTagName("tabmodalprompt"); |
|
75 let {button0, button1} = dialogs[0].ui; |
|
76 callback(button0, button1); |
|
77 }); |
|
78 }, true); |
|
79 } |
|
80 |
|
81 let httpObserver = function (subject, topic, state) { |
|
82 let channel = subject.QueryInterface(Ci.nsIHttpChannel); |
|
83 let url = channel.URI.spec; |
|
84 // Only listen for our document request, as many other requests can happen |
|
85 if (url == URL1 || url == URL2) { |
|
86 assertEvent("request", url); |
|
87 } |
|
88 }; |
|
89 Services.obs.addObserver(httpObserver, "http-on-modify-request", false); |
|
90 |
|
91 function onDOMContentLoaded() { |
|
92 assertEvent("DOMContentLoaded"); |
|
93 } |
|
94 function onLoad() { |
|
95 assertEvent("load"); |
|
96 } |
|
97 |
|
98 function getServerTabActor(callback) { |
|
99 // Ensure having a minimal server |
|
100 if (!DebuggerServer.initialized) { |
|
101 DebuggerServer.init(function () { return true; }); |
|
102 DebuggerServer.addBrowserActors(); |
|
103 } |
|
104 |
|
105 // Connect to this tab |
|
106 let transport = DebuggerServer.connectPipe(); |
|
107 client = new DebuggerClient(transport); |
|
108 client.connect(function onConnect() { |
|
109 client.listTabs(function onListTabs(aResponse) { |
|
110 // Fetch the BrowserTabActor for this tab |
|
111 let actorID = aResponse.tabs[aResponse.selected].actor; |
|
112 client.attachTab(actorID, function(aResponse, aTabClient) { |
|
113 // !Hack! Retrieve a server side object, the BrowserTabActor instance |
|
114 let conn = transport._serverConnection; |
|
115 let tabActor = conn.getActor(actorID); |
|
116 callback(tabActor); |
|
117 }); |
|
118 }); |
|
119 }); |
|
120 |
|
121 client.addListener("tabNavigated", function (aEvent, aPacket) { |
|
122 assertEvent("tabNavigated", aPacket); |
|
123 }); |
|
124 } |
|
125 |
|
126 function test() { |
|
127 waitForExplicitFinish(); |
|
128 |
|
129 // Open a test tab |
|
130 addTab(URL1, function(doc) { |
|
131 getServerTabActor(function (tabActor) { |
|
132 // In order to listen to internal will-navigate/navigate events |
|
133 events.on(tabActor, "will-navigate", function (data) { |
|
134 assertEvent("will-navigate", data); |
|
135 }); |
|
136 events.on(tabActor, "navigate", function (data) { |
|
137 assertEvent("navigate", data); |
|
138 }); |
|
139 |
|
140 // Start listening for page load events |
|
141 let browser = gBrowser.selectedTab.linkedBrowser; |
|
142 browser.addEventListener("DOMContentLoaded", onDOMContentLoaded, true); |
|
143 browser.addEventListener("load", onLoad, true); |
|
144 |
|
145 // Listen for alert() call being made in navigate-first during unload |
|
146 waitForOnBeforeUnloadDialog(browser, function (btnLeave, btnStay) { |
|
147 assertEvent("unload-dialog"); |
|
148 // accept to quit this page to another |
|
149 btnLeave.click(); |
|
150 }); |
|
151 |
|
152 // Load another document in this doc to dispatch these events |
|
153 assertEvent("load-new-document"); |
|
154 content.location = URL2; |
|
155 }); |
|
156 |
|
157 }); |
|
158 } |
|
159 |
|
160 function cleanup() { |
|
161 let browser = gBrowser.selectedTab.linkedBrowser; |
|
162 browser.removeEventListener("DOMContentLoaded", onDOMContentLoaded); |
|
163 browser.removeEventListener("load", onLoad); |
|
164 client.close(function () { |
|
165 Services.obs.addObserver(httpObserver, "http-on-modify-request", false); |
|
166 DebuggerServer.destroy(); |
|
167 finish(); |
|
168 }); |
|
169 } |