• 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_load_times = [];
12var page_load_time_counter = {};
13var unique_url_salt = 1;
14
15function setupTest() {
16  //adding these listeners to track request failure codes
17  chrome.webRequest.onCompleted.addListener(capture_completed_status, {urls: ["<all_urls>"]});
18  chrome.windows.getAll(null, function(windows) {
19    preexisting_windows = windows;
20    for (var i = 0; i < tasks.length; i++) {
21      setTimeout(launch_task, tasks[i].start / time_ratio, tasks[i]);
22    }
23    var end = 3600 * 1000 / time_ratio;
24    log_lines = [];
25    page_load_times = [];
26    page_load_time_counter = {};
27    record_log_entry(dateToString(new Date()) + " Loop started");
28    setTimeout(send_summary, end);
29  });
30}
31
32function close_preexisting_windows() {
33  for (var i = 0; i < preexisting_windows.length; i++) {
34    chrome.windows.remove(preexisting_windows[i].id);
35  }
36  preexisting_windows.length = 0;
37}
38
39function get_active_url(cycle) {
40  active_idx = cycle.idx == 0 ? cycle.urls.length - 1 : cycle.idx - 1;
41  return cycle.urls[active_idx];
42}
43
44function testListener(request, sender, sendResponse) {
45  end = Date.now()
46  if (sender.tab.id in cycle_tabs) {
47    cycle = cycle_tabs[sender.tab.id];
48    cycle.successful_loads++;
49    url = get_active_url(cycle);
50   var page_load_time = end - page_load_time_counter[cycle.id]
51   page_load_times.push({'url': (unique_url_salt++) + url, 'time': page_load_time});
52   console.log(JSON.stringify(page_load_times));
53    record_log_entry(dateToString(new Date()) + " [load success] " + url);
54    if (request.action == "should_scroll" && cycle.focus) {
55      sendResponse({"should_scroll": should_scroll,
56                    "should_scroll_up": should_scroll_up,
57                    "scroll_loop": scroll_loop,
58                    "scroll_interval": scroll_interval_ms,
59                    "scroll_by": scroll_by_pixels});
60    }
61    delete cycle_tabs[sender.tab.id];
62  }
63}
64
65function capture_completed_status(details) {
66  var tabId = details.tabId;
67  if (!(details.tabId in error_codes)) {
68    error_codes[tabId] = [];
69  }
70  var report = {
71    'url':details.url,
72    'code': details.statusCode,
73    'status': details.statusLine,
74    'time': new Date(details.timeStamp)
75  }
76  error_codes[tabId].push(report);
77}
78
79
80function cycle_navigate(cycle) {
81  cycle_tabs[cycle.id] = cycle;
82  var url = cycle.urls[cycle.idx];
83  // Resetting the error codes.
84  // TODO(coconutruben) Verify if reseeting here might give us
85  // garbage data since some requests/responses might still come
86  // in before we update the tab, but we'll register them as
87  // information about the subsequent url
88  error_codes[cycle.id] = [];
89  record_log_entry(dateToString(new Date()) + " [load start] " + url)
90  var start = Date.now();
91  page_load_time_counter[cycle.id] = start;
92  chrome.tabs.update(cycle.id, {'url': url, 'selected': true});
93  cycle.idx = (cycle.idx + 1) % cycle.urls.length;
94  if (cycle.timeout < cycle.delay / time_ratio && cycle.timeout > 0) {
95    cycle.timer = setTimeout(cycle_check_timeout, cycle.timeout, cycle);
96  } else {
97    cycle.timer = setTimeout(cycle_navigate, cycle.delay / time_ratio, cycle);
98  }
99}
100
101function record_error_codes(cycle) {
102  var error_report = dateToString(new Date()) + " [load failure details] " + get_active_url(cycle) + "\n";
103  var reports = error_codes[cycle.id];
104  for (var i = 0; i < reports.length; i++) {
105    report = reports[i];
106    error_report = error_report + "\t\t" +
107    dateToString(report.time) + " | " +
108    "[response code] " + report.code + " | " +
109    "[url] " + report.url + " | " +
110    "[status line] " + report.status + "\n";
111  }
112  log_lines.push(error_report);
113  console.log(error_report);
114}
115
116function cycle_check_timeout(cycle) {
117  if (cycle.id in cycle_tabs) {
118    cycle.failed_loads++;
119    record_error_codes(cycle);
120    record_log_entry(dateToString(new Date()) + " [load failure] " + get_active_url(cycle));
121    cycle_navigate(cycle);
122  } else {
123    cycle.timer = setTimeout(cycle_navigate,
124                             cycle.delay / time_ratio - cycle.timeout,
125                             cycle);
126  }
127}
128
129function launch_task(task) {
130  if (task.type == 'window' && task.tabs) {
131    chrome.windows.create({'url': 'about:blank'}, function (win) {
132      close_preexisting_windows();
133      chrome.tabs.getSelected(win.id, function(tab) {
134        chrome.tabs.update(tab.id, {'url': task.tabs[0], 'selected': true});
135        for (var i = 1; i < task.tabs.length; i++) {
136          chrome.tabs.create({'windowId':win.id, url: task.tabs[i]});
137        }
138        setTimeout(chrome.windows.remove, task.duration / time_ratio, win.id);
139      });
140    });
141  } else if (task.type == 'cycle' && task.urls) {
142    chrome.windows.create({'url': 'about:blank'}, function (win) {
143      close_preexisting_windows();
144      chrome.tabs.getSelected(win.id, function(tab) {
145        var cycle = {
146           'timeout': task.timeout,
147           'name': task.name,
148           'delay': task.delay,
149           'urls': task.urls,
150           'id': tab.id,
151           'idx': 0,
152           'timer': null,
153           'focus': !!task.focus,
154           'successful_loads': 0,
155           'failed_loads': 0
156        };
157        cycles[task.name] = cycle;
158        cycle_navigate(cycle);
159        setTimeout(function(cycle, win_id) {
160          clearTimeout(cycle.timer);
161          chrome.windows.remove(win_id);
162        }, task.duration / time_ratio, cycle, win.id);
163      });
164    });
165  }
166}
167
168function record_log_entry(entry) {
169  log_lines.push(entry);
170}
171
172function send_log_entries() {
173  var post = [];
174  log_lines.forEach(function (item, index, array) {
175    var entry = encodeURIComponent(item);
176    post.push('url'+ index + '=' + entry);
177  });
178
179  var log_url = 'http://localhost:8001/log';
180  //  TODO(coconutruben): code-snippet below is shared
181  //  across record_log_entry and send_keyvals. Consider
182  //  pull into helper if we use more urls.
183  var req = new XMLHttpRequest();
184  req.open('POST', log_url, true);
185  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
186  req.send(post.join("&"));
187  console.log(post.join("&"));
188}
189
190function send_keyvals() {
191  var post = ["status=good"];
192
193  for (var name in cycles) {
194    var cycle = cycles[name];
195    post.push(name + "_successful_loads=" + cycle.successful_loads);
196    post.push(name + "_failed_loads=" + cycle.failed_loads);
197  }
198
199  chrome.runtime.onMessage.removeListener(testListener);
200
201  var status_url = 'http://localhost:8001/status';
202  var req = new XMLHttpRequest();
203  req.open('POST', status_url, true);
204  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
205  req.send(post.join("&"));
206  console.log(post.join("&"));
207}
208
209function send_raw_page_load_time_info() {
210  var post = [];
211  page_load_times.forEach(function (item, index, array) {
212    var key = encodeURIComponent(item.url);
213    post.push(key + "=" + item.time);
214  })
215
216  var pagelt_info_url = 'http://localhost:8001/pagelt'
217  var req = new XMLHttpRequest();
218  req.open('POST', pagelt_info_url, true);
219  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
220  req.send(post.join("&"));
221  console.log(post.join("&"));
222}
223
224function send_summary() {
225  send_log_entries();
226  send_raw_page_load_time_info();
227  send_keyvals();
228}
229
230function startTest() {
231  time_ratio = 3600 * 1000 / test_time_ms; // default test time is 1 hour
232  chrome.runtime.onMessage.addListener(testListener);
233  setTimeout(setupTest, 1000);
234}
235
236function initialize() {
237  // Called when the user clicks on the browser action.
238  chrome.browserAction.onClicked.addListener(function(tab) {
239    // Start the test with default settings.
240    chrome.runtime.onMessage.addListener(testListener);
241    setTimeout(setupTest, 1000);
242  });
243}
244
245window.addEventListener("load", initialize);
246