- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / webnavigation / framework.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var deepEq = chrome.test.checkDeepEq;
6 var expectedEventData;
7 var expectedEventOrder;
8 var capturedEventData;
9 var nextFrameId;
10 var frameIds;
11 var nextTabId;
12 var tabIds;
13 var nextProcessId;
14 var processIds;
15 var initialized = false;
16
17 var debug = false;
18
19 function deepCopy(obj) {
20   if (obj === null)
21     return null;
22   if (typeof(obj) != 'object')
23     return obj;
24   if (Array.isArray(obj)) {
25     var tmp_array = new Array;
26     for (var i = 0; i < obj.length; i++) {
27       tmp_array.push(deepCopy(obj[i]));
28     }
29     return tmp_array;
30   }
31
32   var tmp_object = {}
33   for (var p in obj) {
34     tmp_object[p] = deepCopy(obj[p]);
35   }
36   return tmp_object;
37 }
38
39 // data: array of expected events, each one is a dictionary:
40 //     { label: "<unique identifier>",
41 //       event: "<webnavigation event type>",
42 //       details: { <expected details of the event> }
43 //     }
44 // order: an array of sequences, e.g. [ ["a", "b", "c"], ["d", "e"] ] means that
45 //     event with label "a" needs to occur before event with label "b". The
46 //     relative order of "a" and "d" does not matter.
47 function expect(data, order) {
48   expectedEventData = data;
49   capturedEventData = [];
50   expectedEventOrder = order;
51   nextFrameId = 1;
52   frameIds = {};
53   nextTabId = 0;
54   tabIds = {};
55   nextProcessId = 0;
56   processIds = {}
57   initListeners();
58 }
59
60 function checkExpectations() {
61   if (capturedEventData.length < expectedEventData.length) {
62     return;
63   }
64   if (capturedEventData.length > expectedEventData.length) {
65     chrome.test.fail("Recorded too many events. " +
66         JSON.stringify(capturedEventData));
67   }
68   // We have ensured that capturedEventData contains exactly the same elements
69   // as expectedEventData. Now we need to verify the ordering.
70   // Step 1: build positions such that
71   //     position[<event-label>]=<position of this event in capturedEventData>
72   var curPos = 0;
73   var positions = {};
74   capturedEventData.forEach(function (event) {
75     chrome.test.assertTrue(event.hasOwnProperty("label"));
76     positions[event.label] = curPos;
77     curPos++;
78   });
79   // Step 2: check that elements arrived in correct order
80   expectedEventOrder.forEach(function (order) {
81     var previousLabel = undefined;
82     order.forEach(function (label) {
83       if (previousLabel === undefined) {
84         previousLabel = label;
85         return;
86       }
87       chrome.test.assertTrue(positions[previousLabel] < positions[label],
88           "Event " + previousLabel + " is supposed to arrive before " +
89           label + ".");
90       previousLabel = label;
91     });
92   });
93   chrome.test.succeed();
94 }
95
96 function captureEvent(name, details) {
97   if ('url' in details) {
98     // Skip about:blank navigations
99     if (details.url == 'about:blank') {
100       return;
101     }
102     // Strip query parameter as it is hard to predict.
103     details.url = details.url.replace(new RegExp('\\?[^#]*'), '');
104   }
105   // normalize details.
106   if ('timeStamp' in details) {
107     details.timeStamp = 0;
108   }
109   if (('frameId' in details) && (details.frameId != 0)) {
110     if (frameIds[details.frameId] === undefined) {
111       frameIds[details.frameId] = nextFrameId++;
112     }
113     details.frameId = frameIds[details.frameId];
114   }
115   if (('parentFrameId' in details) && (details.parentFrameId > 0)) {
116     if (frameIds[details.parentFrameId] === undefined) {
117       frameIds[details.parentFrameId] = nextFrameId++;
118     }
119     details.parentFrameId = frameIds[details.parentFrameId];
120   }
121   if (('sourceFrameId' in details) && (details.sourceFrameId != 0)) {
122     if (frameIds[details.sourceFrameId] === undefined) {
123       frameIds[details.sourceFrameId] = nextFrameId++;
124     }
125     details.sourceFrameId = frameIds[details.sourceFrameId];
126   }
127   if ('tabId' in details) {
128     if (tabIds[details.tabId] === undefined) {
129       tabIds[details.tabId] = nextTabId++;
130     }
131     details.tabId = tabIds[details.tabId];
132   }
133   if ('sourceTabId' in details) {
134     if (tabIds[details.sourceTabId] === undefined) {
135       tabIds[details.sourceTabId] = nextTabId++;
136     }
137     details.sourceTabId = tabIds[details.sourceTabId];
138   }
139   if ('replacedTabId' in details) {
140     if (tabIds[details.replacedTabId] === undefined) {
141       tabIds[details.replacedTabId] = nextTabId++;
142     }
143     details.replacedTabId = tabIds[details.replacedTabId];
144   }
145   if ('processId' in details) {
146     if (processIds[details.processId] === undefined) {
147       processIds[details.processId] = nextProcessId++;
148     }
149     details.processId = processIds[details.processId];
150   }
151   if ('sourceProcessId' in details) {
152     if (processIds[details.sourceProcessId] === undefined) {
153       processIds[details.sourceProcessId] = nextProcessId++;
154     }
155     details.sourceProcessId = processIds[details.sourceProcessId];
156   }
157
158   if (debug)
159     console.log("Received event '" + name + "':" + JSON.stringify(details));
160
161   // find |details| in expectedEventData
162   var found = false;
163   var label = undefined;
164   expectedEventData.forEach(function (exp) {
165     if (exp.event == name) {
166       var exp_details;
167       var alt_details;
168       if ('transitionQualifiers' in exp.details) {
169         var idx = exp.details['transitionQualifiers'].indexOf(
170             'maybe_client_redirect');
171         if (idx >= 0) {
172           exp_details = deepCopy(exp.details);
173           exp_details['transitionQualifiers'].splice(idx, 1);
174           alt_details = deepCopy(exp_details);
175           alt_details['transitionQualifiers'].push('client_redirect');
176         } else {
177           exp_details = exp.details;
178           alt_details = exp.details;
179         }
180       } else {
181         exp_details = exp.details;
182         alt_details = exp.details;
183       }
184       if (deepEq(exp_details, details) || deepEq(alt_details, details)) {
185         if (!found) {
186           found = true;
187           label = exp.label;
188           exp.event = undefined;
189         }
190       }
191     }
192   });
193   if (!found) {
194     chrome.test.fail("Received unexpected event '" + name + "':" +
195         JSON.stringify(details));
196   }
197   capturedEventData.push({label: label, event: name, details: details});
198   checkExpectations();
199 }
200
201 function initListeners() {
202   if (initialized)
203     return;
204   initialized = true;
205   chrome.webNavigation.onBeforeNavigate.addListener(
206       function(details) {
207     captureEvent("onBeforeNavigate", details);
208   });
209   chrome.webNavigation.onCommitted.addListener(
210       function(details) {
211     captureEvent("onCommitted", details);
212   });
213   chrome.webNavigation.onDOMContentLoaded.addListener(
214       function(details) {
215     captureEvent("onDOMContentLoaded", details);
216   });
217   chrome.webNavigation.onCompleted.addListener(
218       function(details) {
219     captureEvent("onCompleted", details);
220   });
221   chrome.webNavigation.onCreatedNavigationTarget.addListener(
222       function(details) {
223     captureEvent("onCreatedNavigationTarget", details);
224   });
225   chrome.webNavigation.onReferenceFragmentUpdated.addListener(
226       function(details) {
227     captureEvent("onReferenceFragmentUpdated", details);
228   });
229   chrome.webNavigation.onErrorOccurred.addListener(
230       function(details) {
231     captureEvent("onErrorOccurred", details);
232   });
233   chrome.webNavigation.onTabReplaced.addListener(
234       function(details) {
235     captureEvent("onTabReplaced", details);
236   });
237   chrome.webNavigation.onHistoryStateUpdated.addListener(
238       function(details) {
239     captureEvent("onHistoryStateUpdated", details);
240   });
241 }
242
243 // Returns the usual order of navigation events.
244 function navigationOrder(prefix) {
245   return [ prefix + "onBeforeNavigate",
246            prefix + "onCommitted",
247            prefix + "onDOMContentLoaded",
248            prefix + "onCompleted" ];
249 }
250
251 // Returns the constraints expressing that a frame is an iframe of another
252 // frame.
253 function isIFrameOf(iframe, main_frame) {
254   return [ main_frame + "onCommitted",
255            iframe + "onBeforeNavigate",
256            iframe + "onCompleted",
257            main_frame + "onCompleted" ];
258 }
259
260 // Returns the constraint expressing that a frame was loaded by another.
261 function isLoadedBy(target, source) {
262   return [ source + "onDOMContentLoaded", target + "onBeforeNavigate"];
263 }