317 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			317 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| // Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| var cycle_tabs = {};
 | |
| var cycles = {};
 | |
| var time_ratio = 3600 * 1000 / test_time_ms; // default test time is 1 hour
 | |
| var preexisting_windows = [];
 | |
| var log_lines = [];
 | |
| var error_codes = {}; //for each active tabId
 | |
| var page_timestamps = [];
 | |
| var page_timestamps_recorder = {};
 | |
| var keys_values = [];
 | |
| 
 | |
| function setupTest() {
 | |
|   //adding these listeners to track request failure codes
 | |
|   chrome.webRequest.onCompleted.addListener(capture_completed_status,
 | |
|                                             {urls: ["<all_urls>"]});
 | |
|   task_monitor.bind();
 | |
| 
 | |
|   chrome.windows.getAll(null, function(windows) {
 | |
|     preexisting_windows = windows;
 | |
|     for (var i = 0; i < tasks.length; i++) {
 | |
|       setTimeout(launch_task, tasks[i].start / time_ratio, tasks[i]);
 | |
|     }
 | |
|     var end = 3600 * 1000 / time_ratio;
 | |
|     log_lines = [];
 | |
|     page_timestamps = [];
 | |
|     page_timestamps_recorder = {};
 | |
|     keys_values = [];
 | |
|     record_log_entry(dateToString(new Date()) + " Loop started");
 | |
|     setTimeout(send_summary, end);
 | |
|   });
 | |
| }
 | |
| 
 | |
| function close_preexisting_windows() {
 | |
|   for (var i = 0; i < preexisting_windows.length; i++) {
 | |
|     chrome.windows.remove(preexisting_windows[i].id);
 | |
|   }
 | |
|   preexisting_windows.length = 0;
 | |
| }
 | |
| 
 | |
| function get_active_url(cycle) {
 | |
|   active_idx = cycle.idx == 0 ? cycle.urls.length - 1 : cycle.idx - 1;
 | |
|   return cycle.urls[active_idx];
 | |
| }
 | |
| 
 | |
| function testListener(request, sender, sendResponse) {
 | |
|   end = Date.now()
 | |
|   page = page_timestamps_recorder[sender.tab.id];
 | |
|   page['end_load_time'] = end;
 | |
|   console.log("page_timestamps_recorder:");
 | |
|   console.log(JSON.stringify(page_timestamps_recorder));
 | |
|   if (sender.tab.id in cycle_tabs) {
 | |
|     cycle = cycle_tabs[sender.tab.id];
 | |
|     cycle.successful_loads++;
 | |
|     url = get_active_url(cycle);
 | |
|     record_log_entry(dateToString(new Date()) + " [load success] " + url);
 | |
|     if (request.action == "should_scroll" && cycle.focus) {
 | |
|       sendResponse({"should_scroll": should_scroll,
 | |
|                     "should_scroll_up": should_scroll_up,
 | |
|                     "scroll_loop": scroll_loop,
 | |
|                     "scroll_interval": scroll_interval_ms,
 | |
|                     "scroll_by": scroll_by_pixels});
 | |
|     }
 | |
|     delete cycle_tabs[sender.tab.id];
 | |
|   }
 | |
| }
 | |
| 
 | |
| function report_page_nav_to_test() {
 | |
|   //Sends message to PLT informing that user is navigating to new page.
 | |
|   var ping_url = 'http://localhost:8001/pagenav';
 | |
|   var req = new XMLHttpRequest();
 | |
|   req.open('GET', ping_url, true);
 | |
|   req.send("");
 | |
| }
 | |
| 
 | |
| function capture_completed_status(details) {
 | |
|   var tabId = details.tabId;
 | |
|   if (!(details.tabId in error_codes)) {
 | |
|     error_codes[tabId] = [];
 | |
|   }
 | |
|   var report = {
 | |
|     'url':details.url,
 | |
|     'code': details.statusCode,
 | |
|     'status': details.statusLine,
 | |
|     'time': new Date(details.timeStamp)
 | |
|   }
 | |
|   error_codes[tabId].push(report);
 | |
| }
 | |
| 
 | |
| 
 | |
| function cycle_navigate(cycle) {
 | |
|   cycle_tabs[cycle.id] = cycle;
 | |
|   var url = cycle.urls[cycle.idx];
 | |
|   // Resetting the error codes.
 | |
|   // TODO(coconutruben) Verify if reseting here might give us
 | |
|   // garbage data since some requests/responses might still come
 | |
|   // in before we update the tab, but we'll register them as
 | |
|   // information about the subsequent url
 | |
|   error_codes[cycle.id] = [];
 | |
|   record_log_entry(dateToString(new Date()) + " [load start] " + url)
 | |
|   var start = Date.now();
 | |
|   // start_time of next page is end_browse_time of previous page
 | |
|   if (cycle.id in page_timestamps_recorder) {
 | |
|     page = page_timestamps_recorder[cycle.id];
 | |
|     page['end_browse_time'] = start;
 | |
|     page_timestamps.push(page);
 | |
|     console.log(JSON.stringify(page_timestamps));
 | |
|   }
 | |
|   page_timestamps_new_record(cycle.id, url, start);
 | |
|   chrome.tabs.update(cycle.id, {'url': url, 'selected': true});
 | |
|   report_page_nav_to_test()
 | |
|   cycle.idx = (cycle.idx + 1) % cycle.urls.length;
 | |
|   if (cycle.timeout < cycle.delay / time_ratio && cycle.timeout > 0) {
 | |
|     cycle.timer = setTimeout(cycle_check_timeout, cycle.timeout, cycle);
 | |
|   } else {
 | |
|     cycle.timer = setTimeout(cycle_navigate, cycle.delay / time_ratio, cycle);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function record_error_codes(cycle) {
 | |
|   var error_report = dateToString(new Date()) + " [load failure details] "
 | |
|                      + get_active_url(cycle) + "\n";
 | |
|   var reports = error_codes[cycle.id];
 | |
|   for (var i = 0; i < reports.length; i++) {
 | |
|     report = reports[i];
 | |
|     error_report = error_report + "\t\t" +
 | |
|     dateToString(report.time) + " | " +
 | |
|     "[response code] " + report.code + " | " +
 | |
|     "[url] " + report.url + " | " +
 | |
|     "[status line] " + report.status + "\n";
 | |
|   }
 | |
|   log_lines.push(error_report);
 | |
|   console.log(error_report);
 | |
| }
 | |
| 
 | |
| function cycle_check_timeout(cycle) {
 | |
|   if (cycle.id in cycle_tabs) {
 | |
|     cycle.failed_loads++;
 | |
|     record_error_codes(cycle);
 | |
|     record_log_entry(dateToString(new Date()) + " [load failure] " +
 | |
|                                   get_active_url(cycle));
 | |
|     cycle_navigate(cycle);
 | |
|   } else {
 | |
|     cycle.timer = setTimeout(cycle_navigate,
 | |
|                              cycle.delay / time_ratio - cycle.timeout,
 | |
|                              cycle);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function launch_task(task) {
 | |
|   if (task.type == 'window' && task.tabs) {
 | |
|     chrome.windows.create({'url': '/focus.html'}, function (win) {
 | |
|       close_preexisting_windows();
 | |
|       chrome.tabs.getSelected(win.id, function(tab) {
 | |
|         for (var i = 1; i < task.tabs.length; i++) {
 | |
|           chrome.tabs.create({'windowId':win.id, 'url': '/focus.html'});
 | |
|         }
 | |
|         chrome.tabs.getAllInWindow(win.id, function(tabs) {
 | |
|           for (var i = 0; i < tabs.length; i++) {
 | |
|             tab = tabs[i];
 | |
|             url = task.tabs[i];
 | |
|             start = Date.now();
 | |
|             page_timestamps_new_record(tab.id, url, start);
 | |
|             chrome.tabs.update(tab.id, {'url': url, 'selected': true});
 | |
|           }
 | |
|           console.log(JSON.stringify(page_timestamps_recorder));
 | |
|         });
 | |
|         setTimeout(function(win_id) {
 | |
|           record_end_browse_time_for_window(win_id);
 | |
|           chrome.windows.remove(win_id);
 | |
|         }, (task.duration / time_ratio), win.id);
 | |
|       });
 | |
|     });
 | |
|   } else if (task.type == 'cycle' && task.urls) {
 | |
|     chrome.windows.create({'url': '/focus.html'}, function (win) {
 | |
|       close_preexisting_windows();
 | |
|       chrome.tabs.getSelected(win.id, function(tab) {
 | |
|         var cycle = {
 | |
|            'timeout': task.timeout,
 | |
|            'name': task.name,
 | |
|            'delay': task.delay,
 | |
|            'urls': task.urls,
 | |
|            'id': tab.id,
 | |
|            'idx': 0,
 | |
|            'timer': null,
 | |
|            'focus': !!task.focus,
 | |
|            'successful_loads': 0,
 | |
|            'failed_loads': 0
 | |
|         };
 | |
|         cycles[task.name] = cycle;
 | |
|         cycle_navigate(cycle);
 | |
|         setTimeout(function(cycle, win_id) {
 | |
|           clearTimeout(cycle.timer);
 | |
|           record_end_browse_time_for_window(win_id);
 | |
|           chrome.windows.remove(win_id);
 | |
|         }, task.duration / time_ratio, cycle, win.id);
 | |
|       });
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| function page_timestamps_new_record(tab_id, url, start) {
 | |
|   // sanitize url, make http(s)://www.abc.com/d/e/f into www.abc.com
 | |
|   sanitized_url = url.replace(/https?:\/\//, '').split('/')[0];
 | |
|   page_timestamps_recorder[tab_id] = {
 | |
|     'url': sanitized_url,
 | |
|     'start_time': start,
 | |
|     'end_load_time': null,
 | |
|     'end_browse_time': null
 | |
|   }
 | |
| }
 | |
| 
 | |
| function record_end_browse_time_for_window(win_id) {
 | |
|   chrome.tabs.getAllInWindow(win_id, function(tabs) {
 | |
|     end = Date.now();
 | |
|     console.log("page_timestamps_recorder:");
 | |
|     console.log(JSON.stringify(page_timestamps_recorder));
 | |
|     tabs.forEach(function (tab) {
 | |
|       if (tab.id in page_timestamps_recorder) {
 | |
|         page = page_timestamps_recorder[tab.id];
 | |
|         page['end_browse_time'] = end;
 | |
|         page_timestamps.push(page);
 | |
|       }
 | |
|     });
 | |
|     console.log(JSON.stringify("page_timestamps:"));
 | |
|     console.log(JSON.stringify(page_timestamps));
 | |
|   });
 | |
| }
 | |
| 
 | |
| function record_log_entry(entry) {
 | |
|   log_lines.push(entry);
 | |
| }
 | |
| 
 | |
| function record_key_values(dictionary) {
 | |
|   keys_values.push(dictionary);
 | |
| }
 | |
| 
 | |
| function send_log_entries() {
 | |
|   var post = [];
 | |
|   log_lines.forEach(function (item, index) {
 | |
|     var entry = encodeURIComponent(item);
 | |
|     post.push('log'+ index + '=' + entry);
 | |
|   });
 | |
| 
 | |
|   var log_url = 'http://localhost:8001/log';
 | |
|   send_post_data(post, log_url)
 | |
| }
 | |
| 
 | |
| function send_status() {
 | |
|   var post = ["status=good"];
 | |
| 
 | |
|   for (var name in cycles) {
 | |
|     var cycle = cycles[name];
 | |
|     post.push(name + "_successful_loads=" + cycle.successful_loads);
 | |
|     post.push(name + "_failed_loads=" + cycle.failed_loads);
 | |
|   }
 | |
| 
 | |
|   chrome.runtime.onMessage.removeListener(testListener);
 | |
| 
 | |
|   var status_url = 'http://localhost:8001/status';
 | |
|   send_post_data(post, status_url)
 | |
| }
 | |
| 
 | |
| function send_raw_page_time_info() {
 | |
|   var post = [];
 | |
|   page_timestamps.forEach(function (item, index) {
 | |
|     post.push('page_time_data'+ index + "=" + JSON.stringify(item));
 | |
|   })
 | |
| 
 | |
|   var pagetime_info_url = 'http://localhost:8001/pagetime';
 | |
|   send_post_data(post, pagetime_info_url)
 | |
| }
 | |
| 
 | |
| function send_key_values() {
 | |
|   var post = [];
 | |
|   keys_values.forEach(function (item, index) {
 | |
|     post.push("keyval" + index + "=" + JSON.stringify(item));
 | |
|   })
 | |
|   var key_values_info_url = 'http://localhost:8001/keyvalues';
 | |
|   send_post_data(post, key_values_info_url)
 | |
| }
 | |
| 
 | |
| function send_post_data(post, url) {
 | |
|   var req = new XMLHttpRequest();
 | |
|   req.open('POST', url, true);
 | |
|   req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 | |
|   req.send(post.join("&"));
 | |
|   console.log(post.join("&"));
 | |
| }
 | |
| 
 | |
| function send_summary() {
 | |
|   send_raw_page_time_info();
 | |
|   task_monitor.unbind();
 | |
|   send_key_values();
 | |
|   send_status();
 | |
|   send_log_entries();
 | |
| }
 | |
| 
 | |
| function startTest() {
 | |
|   time_ratio = 3600 * 1000 / test_time_ms; // default test time is 1 hour
 | |
|   chrome.runtime.onMessage.addListener(testListener);
 | |
|   setTimeout(setupTest, 1000);
 | |
| }
 | |
| 
 | |
| function initialize() {
 | |
|   // Called when the user clicks on the browser action.
 | |
|   chrome.browserAction.onClicked.addListener(function(tab) {
 | |
|     // Start the test with default settings.
 | |
|     chrome.runtime.onMessage.addListener(testListener);
 | |
|     setTimeout(setupTest, 1000);
 | |
|   });
 | |
| }
 | |
| 
 | |
| window.addEventListener("load", initialize);
 |