• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2014 The Chromium OS 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
5var cycle_tabs = {};
6var cycles = {};
7var time_ratio = 3600 * 1000 / test_time_ms; // default test time is 1 hour
8var preexisting_windows = [];
9var log_lines = [];
10var error_codes = {}; //for each active tabId
11var page_timestamps = [];
12var page_timestamps_recorder = {};
13var keys_values = [];
14
15function setupTest() {
16  //adding these listeners to track request failure codes
17  chrome.webRequest.onCompleted.addListener(capture_completed_status,
18                                            {urls: ["<all_urls>"]});
19  task_monitor.bind();
20
21  chrome.windows.getAll(null, function(windows) {
22    preexisting_windows = windows;
23    for (var i = 0; i < tasks.length; i++) {
24      setTimeout(launch_task, tasks[i].start / time_ratio, tasks[i]);
25    }
26    var end = 3600 * 1000 / time_ratio;
27    log_lines = [];
28    page_timestamps = [];
29    page_timestamps_recorder = {};
30    keys_values = [];
31    record_log_entry(dateToString(new Date()) + " Loop started");
32    setTimeout(send_summary, end);
33  });
34}
35
36function close_preexisting_windows() {
37  for (var i = 0; i < preexisting_windows.length; i++) {
38    chrome.windows.remove(preexisting_windows[i].id);
39  }
40  preexisting_windows.length = 0;
41}
42
43function get_active_url(cycle) {
44  active_idx = cycle.idx == 0 ? cycle.urls.length - 1 : cycle.idx - 1;
45  return cycle.urls[active_idx];
46}
47
48function testListener(request, sender, sendResponse) {
49  end = Date.now()
50  page = page_timestamps_recorder[sender.tab.id];
51  page['end_load_time'] = end;
52  console.log("page_timestamps_recorder:");
53  console.log(JSON.stringify(page_timestamps_recorder));
54  if (sender.tab.id in cycle_tabs) {
55    cycle = cycle_tabs[sender.tab.id];
56    cycle.successful_loads++;
57    url = get_active_url(cycle);
58    record_log_entry(dateToString(new Date()) + " [load success] " + url);
59    if (request.action == "should_scroll" && cycle.focus) {
60      sendResponse({"should_scroll": should_scroll,
61                    "should_scroll_up": should_scroll_up,
62                    "scroll_loop": scroll_loop,
63                    "scroll_interval": scroll_interval_ms,
64                    "scroll_by": scroll_by_pixels});
65    }
66    delete cycle_tabs[sender.tab.id];
67  }
68}
69
70function report_page_nav_to_test() {
71  //Sends message to PLT informing that user is navigating to new page.
72  var ping_url = 'http://localhost:8001/pagenav';
73  var req = new XMLHttpRequest();
74  req.open('GET', ping_url, true);
75  req.send("");
76}
77
78function capture_completed_status(details) {
79  var tabId = details.tabId;
80  if (!(details.tabId in error_codes)) {
81    error_codes[tabId] = [];
82  }
83  var report = {
84    'url':details.url,
85    'code': details.statusCode,
86    'status': details.statusLine,
87    'time': new Date(details.timeStamp)
88  }
89  error_codes[tabId].push(report);
90}
91
92
93function cycle_navigate(cycle) {
94  cycle_tabs[cycle.id] = cycle;
95  var url = cycle.urls[cycle.idx];
96  // Resetting the error codes.
97  // TODO(coconutruben) Verify if reseting here might give us
98  // garbage data since some requests/responses might still come
99  // in before we update the tab, but we'll register them as
100  // information about the subsequent url
101  error_codes[cycle.id] = [];
102  record_log_entry(dateToString(new Date()) + " [load start] " + url)
103  var start = Date.now();
104  // start_time of next page is end_browse_time of previous page
105  if (cycle.id in page_timestamps_recorder) {
106    page = page_timestamps_recorder[cycle.id];
107    page['end_browse_time'] = start;
108    page_timestamps.push(page);
109    console.log(JSON.stringify(page_timestamps));
110  }
111  page_timestamps_new_record(cycle.id, url, start);
112  chrome.tabs.update(cycle.id, {'url': url, 'selected': true});
113  report_page_nav_to_test()
114  cycle.idx = (cycle.idx + 1) % cycle.urls.length;
115  if (cycle.timeout < cycle.delay / time_ratio && cycle.timeout > 0) {
116    cycle.timer = setTimeout(cycle_check_timeout, cycle.timeout, cycle);
117  } else {
118    cycle.timer = setTimeout(cycle_navigate, cycle.delay / time_ratio, cycle);
119  }
120}
121
122function record_error_codes(cycle) {
123  var error_report = dateToString(new Date()) + " [load failure details] "
124                     + get_active_url(cycle) + "\n";
125  var reports = error_codes[cycle.id];
126  for (var i = 0; i < reports.length; i++) {
127    report = reports[i];
128    error_report = error_report + "\t\t" +
129    dateToString(report.time) + " | " +
130    "[response code] " + report.code + " | " +
131    "[url] " + report.url + " | " +
132    "[status line] " + report.status + "\n";
133  }
134  log_lines.push(error_report);
135  console.log(error_report);
136}
137
138function cycle_check_timeout(cycle) {
139  if (cycle.id in cycle_tabs) {
140    cycle.failed_loads++;
141    record_error_codes(cycle);
142    record_log_entry(dateToString(new Date()) + " [load failure] " +
143                                  get_active_url(cycle));
144    cycle_navigate(cycle);
145  } else {
146    cycle.timer = setTimeout(cycle_navigate,
147                             cycle.delay / time_ratio - cycle.timeout,
148                             cycle);
149  }
150}
151
152function launch_task(task) {
153  if (task.type == 'window' && task.tabs) {
154    chrome.windows.create({'url': '/focus.html'}, function (win) {
155      close_preexisting_windows();
156      chrome.tabs.getSelected(win.id, function(tab) {
157        for (var i = 1; i < task.tabs.length; i++) {
158          chrome.tabs.create({'windowId':win.id, 'url': '/focus.html'});
159        }
160        chrome.tabs.getAllInWindow(win.id, function(tabs) {
161          for (var i = 0; i < tabs.length; i++) {
162            tab = tabs[i];
163            url = task.tabs[i];
164            start = Date.now();
165            page_timestamps_new_record(tab.id, url, start);
166            chrome.tabs.update(tab.id, {'url': url, 'selected': true});
167          }
168          console.log(JSON.stringify(page_timestamps_recorder));
169        });
170        setTimeout(function(win_id) {
171          record_end_browse_time_for_window(win_id);
172          chrome.windows.remove(win_id);
173        }, (task.duration / time_ratio), win.id);
174      });
175    });
176  } else if (task.type == 'cycle' && task.urls) {
177    chrome.windows.create({'url': '/focus.html'}, function (win) {
178      close_preexisting_windows();
179      chrome.tabs.getSelected(win.id, function(tab) {
180        var cycle = {
181           'timeout': task.timeout,
182           'name': task.name,
183           'delay': task.delay,
184           'urls': task.urls,
185           'id': tab.id,
186           'idx': 0,
187           'timer': null,
188           'focus': !!task.focus,
189           'successful_loads': 0,
190           'failed_loads': 0
191        };
192        cycles[task.name] = cycle;
193        cycle_navigate(cycle);
194        setTimeout(function(cycle, win_id) {
195          clearTimeout(cycle.timer);
196          record_end_browse_time_for_window(win_id);
197          chrome.windows.remove(win_id);
198        }, task.duration / time_ratio, cycle, win.id);
199      });
200    });
201  }
202}
203
204function page_timestamps_new_record(tab_id, url, start) {
205  // sanitize url, make http(s)://www.abc.com/d/e/f into www.abc.com
206  sanitized_url = url.replace(/https?:\/\//, '').split('/')[0];
207  page_timestamps_recorder[tab_id] = {
208    'url': sanitized_url,
209    'start_time': start,
210    'end_load_time': null,
211    'end_browse_time': null
212  }
213}
214
215function record_end_browse_time_for_window(win_id) {
216  chrome.tabs.getAllInWindow(win_id, function(tabs) {
217    end = Date.now();
218    console.log("page_timestamps_recorder:");
219    console.log(JSON.stringify(page_timestamps_recorder));
220    tabs.forEach(function (tab) {
221      if (tab.id in page_timestamps_recorder) {
222        page = page_timestamps_recorder[tab.id];
223        page['end_browse_time'] = end;
224        page_timestamps.push(page);
225      }
226    });
227    console.log(JSON.stringify("page_timestamps:"));
228    console.log(JSON.stringify(page_timestamps));
229  });
230}
231
232function record_log_entry(entry) {
233  log_lines.push(entry);
234}
235
236function record_key_values(dictionary) {
237  keys_values.push(dictionary);
238}
239
240function send_log_entries() {
241  var post = [];
242  log_lines.forEach(function (item, index) {
243    var entry = encodeURIComponent(item);
244    post.push('log'+ index + '=' + entry);
245  });
246
247  var log_url = 'http://localhost:8001/log';
248  send_post_data(post, log_url)
249}
250
251function send_status() {
252  var post = ["status=good"];
253
254  for (var name in cycles) {
255    var cycle = cycles[name];
256    post.push(name + "_successful_loads=" + cycle.successful_loads);
257    post.push(name + "_failed_loads=" + cycle.failed_loads);
258  }
259
260  chrome.runtime.onMessage.removeListener(testListener);
261
262  var status_url = 'http://localhost:8001/status';
263  send_post_data(post, status_url)
264}
265
266function send_raw_page_time_info() {
267  var post = [];
268  page_timestamps.forEach(function (item, index) {
269    post.push('page_time_data'+ index + "=" + JSON.stringify(item));
270  })
271
272  var pagetime_info_url = 'http://localhost:8001/pagetime';
273  send_post_data(post, pagetime_info_url)
274}
275
276function send_key_values() {
277  var post = [];
278  keys_values.forEach(function (item, index) {
279    post.push("keyval" + index + "=" + JSON.stringify(item));
280  })
281  var key_values_info_url = 'http://localhost:8001/keyvalues';
282  send_post_data(post, key_values_info_url)
283}
284
285function send_post_data(post, url) {
286  var req = new XMLHttpRequest();
287  req.open('POST', url, true);
288  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
289  req.send(post.join("&"));
290  console.log(post.join("&"));
291}
292
293function send_summary() {
294  send_raw_page_time_info();
295  task_monitor.unbind();
296  send_key_values();
297  send_status();
298  send_log_entries();
299}
300
301function startTest() {
302  time_ratio = 3600 * 1000 / test_time_ms; // default test time is 1 hour
303  chrome.runtime.onMessage.addListener(testListener);
304  setTimeout(setupTest, 1000);
305}
306
307function initialize() {
308  // Called when the user clicks on the browser action.
309  chrome.browserAction.onClicked.addListener(function(tab) {
310    // Start the test with default settings.
311    chrome.runtime.onMessage.addListener(testListener);
312    setTimeout(setupTest, 1000);
313  });
314}
315
316window.addEventListener("load", initialize);
317