Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Unified Diff: tools/page_cycler/webpagereplay/extension/background.js

Issue 9956045: Add Web Page Replay test to page cycler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Ready for review. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/page_cycler/webpagereplay/extension/background.js
diff --git a/tools/page_cycler/webpagereplay/extension/background.js b/tools/page_cycler/webpagereplay/extension/background.js
new file mode 100644
index 0000000000000000000000000000000000000000..d9d0c86a4c3d1bd4869bc7d478d597fd98ab65b9
--- /dev/null
+++ b/tools/page_cycler/webpagereplay/extension/background.js
@@ -0,0 +1,340 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// start.js sends a "start" message to set this.
+window.benchmarkConfiguration = {};
+
+// The callback (e.g. report writer) is set via AddBenchmarckCallback.
+window.benchmarkCallback;
+
+// Url to load before loading target page.
+var kWaitUrl = "http://wprwprwpr/web-page-replay-generate-200";
+
+// Constant StatCounter Names
+var kTcpReadBytes = "tcp.read_bytes";
+var kTcpWriteBytes = "tcp.write_bytes";
+var kRequestCount = "HttpNetworkTransaction.Count";
+var kConnectCount = "tcp.connect";
+
+function CHECK(expr, comment) {
+ if (!expr) {
+ console.log(comment);
+ alert(comment);
+ }
+}
+
+// Return a list of values for an attribute (e.g. [x.attr for x in array]).
+Array.attrValues = function(array, attr, default_value) {
+ var values = [];
+ for (var i = 0, len = array.length; i < len; i++) {
+ if (attr in array[i]) {
+ values.push(array[i][attr]);
+ } else {
+ values.push(default_value);
+ }
+ }
+ return values;
+};
+
+// Returns the sum of all values in the array.
+Array.sum = function(array) {
+ var sum = 0;
+ for (var i = array.length - 1; i >= 0; i--) {
+ sum += array[i];
+ }
+ return sum;
+};
+
+// Map WebTiming properties to Result attribute names.
+window.loggedTimings = {
+ fetchStart: 'start_load_time',
+ domainLookupEnd: 'dns_time',
+ connectEnd: 'connect_time',
+ responseStart: 'first_byte_time',
+ responseEnd: 'last_byte_time',
+ domInteractive: 'doc_load_time',
+ domContentLoadedEventEnd: 'dcl_time',
+ loadEventEnd: 'total_time',
+};
+
+function Result() {
+ this.url = "";
+ this.paint_time = 0;
+ this.read_bytes_kb = 0;
+ this.write_bytes_kb = 0;
+ this.num_requests = 0;
+ this.num_connects = 0;
+ this.num_sessions = 0;
+ // The values of window.loggedTimings are also added as attributes.
+}
+
+// Collect all the results for a session (i.e. different pages).
+function ResultsCollection() {
+ var results_ = [];
+ var pages_ = [];
+ var pageResults_ = {};
+
+ this.addResult = function(result) {
+ results_.push(result);
+ var url = result.url;
+ if (!(url in pageResults_)) {
+ pages_.push(url);
+ pageResults_[url] = [];
+ }
+ pageResults_[url].push(result);
+ }
+
+ this.getPages = function() {
+ return pages_;
+ }
+
+ this.getResults = function() {
+ return results_;
+ }
+
+ this.getTotalTimes = function() {
+ var default_time = 0;
+ return Array.attrValues(results_, "total_time", default_time);
+ }
+}
+
+// Load a url in the default tab and record the time.
+function PageLoader(url, resultReadyCallback) {
+ var me_ = this;
+ var url_ = url;
+ var resultReadyCallback_ = resultReadyCallback;
+
+ // If it record mode, wait a little longer for lazy loaded resources.
+ var postLoadGraceMs_ = window.isRecordMode ? 5000 : 0;
+ var loadInterval_ = window.loadInterval;
+ var checkInterval_ = window.checkInterval;
+ var timeout_ = window.timeout;
+ var maxLoadChecks_ = window.maxLoadChecks;
+
+ var preloadFunc_;
+ var timeoutId_;
+ var isFinished_;
+ var result_;
+
+ var initialReadBytes_;
+ var initialWriteBytes_;
+ var initialRequestCount_;
+ var initialConnectCount_;
+
+ this.result = function() { return result_; };
+
+ this.run = function() {
+ timeoutId_ = null;
+ isFinished_ = false;
+ result_ = null;
+ initialReadBytes_ = chrome.benchmarking.counter(kTcpReadBytes);
+ initialWriteBytes_ = chrome.benchmarking.counter(kTcpWriteBytes);
+ initialRequestCount_ = chrome.benchmarking.counter(kRequestCount);
+ initialConnectCount_ = chrome.benchmarking.counter(kConnectCount);
+
+ if (me_.preloadFunc_) {
+ me_.preloadFunc_(me_.load_);
+ } else {
+ me_.load_();
+ }
+ };
+
+ this.setClearAll = function() {
+ me_.preloadFunc_ = me_.clearAll;
+ };
+
+ this.setClearConnections = function() {
+ me_.preloadFunc_ = me_.clearClearConnections;
+ };
+
+ this.clearAll = function(callback) {
James Simonsen 2012/04/05 00:07:22 These two clear* methods should be marked private.
+ chrome.tabs.getSelected(null, function(tab) {
+ chrome.tabs.update(tab.id, {"url": kWaitUrl});
+ });
+ var isDone = false;
+ chrome.browsingData.remove({}, {
+ "appcache": true,
+ "cache": true,
+ "cookies": true,
+ "localStorage": true,
+ "pluginData": true,
+ "webSQL": true
+ }, callback);
+ chrome.benchmarking.clearHostResolverCache();
+ chrome.benchmarking.clearPredictorCache();
+ chrome.benchmarking.closeConnections();
+ };
+
+ this.clearConnections = function(callback) {
+ chrome.benchmarking.closeConnections();
+ callback();
+ };
+
+ this.load_ = function() {
+ console.log("LOAD started: " + url_);
+ setTimeout(function() {
+ chrome.extension.onRequest.addListener(me_.finishLoad);
+ timeoutId_ = setTimeout(function() {
+ me_.finishLoad({"loadTimes": null, "timing": null});
+ }, timeout_);
+ chrome.tabs.getSelected(null, function(tab) {
+ chrome.tabs.update(tab.id, {"url": url_});
+ });
+ }, loadInterval_);
+ };
+
+ this.finishLoad = function(msg) {
James Simonsen 2012/04/05 00:07:22 Should be marked private.
+ if (!isFinished_) {
+ isFinished_ = true;
+ clearTimeout(timeoutId_);
+ chrome.extension.onRequest.removeListener(me_.finishLoad);
+ me_.saveResult(msg.loadTimes, msg.timing);
+ }
+ };
+
+ this.saveResult = function(loadTimes, timing) {
James Simonsen 2012/04/05 00:07:22 private
+ result_ = new Result()
+ result_.url = url_;
+ if (!loadTimes || !timing) {
+ console.log("LOAD INCOMPLETE: " + url_);
+ } else {
+ console.log("LOAD complete: " + url_);
+ var baseTime = timing.navigationStart;
+ CHECK(baseTime);
+ for (var prop in loggedTimings) {
+ if (prop in timing) {
+ result_[loggedTimings[prop]] = Math.max(0, timing[prop] - baseTime);
+ }
+ }
+ result_.paint_time = Math.max(0,
+ Math.round((1000.0 * loadTimes.firstPaintTime) - baseTime));
+ }
+ result_.read_bytes_kb = (chrome.benchmarking.counter(kTcpReadBytes) -
+ initialReadBytes_) / 1024;
+ result_.write_bytes_kb = (chrome.benchmarking.counter(kTcpWriteBytes) -
+ initialWriteBytes_) / 1024;
+ result_.num_requests = (chrome.benchmarking.counter(kRequestCount) -
+ initialRequestCount_);
+ result_.num_connects = (chrome.benchmarking.counter(kConnectCount) -
+ initialConnectCount_);
+ setTimeout(function() { resultReadyCallback_(me_); }, postLoadGraceMs_);
+ };
+}
+
+// Load page sets and prepare performance results.
+function SessionLoader(resultsReadyCallback) {
+ var me_ = this;
+ var resultsReadyCallback_ = resultsReadyCallback;
+ var pageSets_ = benchmarkConfiguration.pageSets;
+ var iterations_ = window.iterations;
+ var retries_ = window.retries;
+
+ var pageLoaders_ = [];
+ var resultsCollection_ = new ResultsCollection();
+ var loaderIndex_ = 0;
+ var retryIndex_ = 0;
+ var iterationIndex_ = 0;
+
+ this.run = function() {
+ me_.createLoaders();
+ me_.loadPage();
+ }
+
+ this.getResultsCollection = function() {
+ return resultsCollection_;
+ }
+
+ this.createLoaders = function() {
+ // Each url becomes one benchmark.
+ for (var i = 0; i < pageSets_.length; i++) {
+ for (var j = 0; j < pageSets_[i].length; j++) {
+ // Remove extra space at the beginning or end of a url.
+ var url = pageSets_[i][j].trim();
+ // Alert about and ignore blank page which does not get loaded.
+ if (url == "about:blank") {
+ alert("blank page loaded!");
+ } else if (!url.match(/https?:\/\//)) {
+ // Alert about url that is not in scheme http:// or https://.
+ alert("Skipping url without http:// or https://: " + url);
+ } else {
+ var loader = new PageLoader(url, me_.handleResult)
+ if (j == 0) {
+ // Clear all browser data for the first page in a sub list.
+ loader.setClearAll();
+ } else {
+ // Otherwise, only clear the connections.
+ loader.setClearConnections();
+ }
+ pageLoaders_.push(loader);
+ }
+ }
+ }
+ }
+
+ this.loadPage = function() {
+ console.log("LOAD url " + (loaderIndex_ + 1) + " of " +
+ pageLoaders_.length +
+ ", iteration " + (iterationIndex_ + 1) + " of " +
+ iterations_);
+ pageLoaders_[loaderIndex_].run();
+ }
+
+ this.handleResult = function(loader) {
+ var result = loader.result();
+ resultsCollection_.addResult(result);
+ var totalTime = result["total_time"] || 0;
+ if (!totalTime && retryIndex_ < retries_) {
+ retryIndex_++;
+ console.log("LOAD retry, " + retryIndex_);
+ } else {
+ retryIndex_ = 0;
+ console.log("RESULTS url " + (loaderIndex_ + 1) + " of " +
+ pageLoaders_.length +
+ ", iteration " + (iterationIndex_ + 1) + " of " +
+ iterations_ + ": " + result["total_time"]);
+ loaderIndex_++;
+ if (loaderIndex_ >= pageLoaders_.length) {
+ iterationIndex_++;
+ if (iterationIndex_ < iterations_) {
+ loaderIndex_ = 0;
+ } else {
+ resultsReadyCallback(me_);
James Simonsen 2012/04/05 00:07:22 Needs _.
+ return;
+ }
+ }
+ }
+ me_.loadPage();
+ }
+}
+
+function AddBenchmarkCallback(callback) {
+ window.benchmarkCallback = callback;
+}
+
+function Run() {
+ window.checkInterval = 500;
+ window.loadInterval = 1000;
+ window.timeout = 20000; // max ms before killing page.
+ window.retries = 0;
+ window.isRecordMode = benchmarkConfiguration.isRecordMode;
+ if (window.isRecordMode) {
+ window.iterations = 1;
+ window.timeout = 40000;
+ window.retries = 2;
+ } else {
+ window.iterations = benchmarkConfiguration["iterations"] || 3;
+ }
+ var sessionLoader = new SessionLoader(benchmarkCallback);
+ console.log("pageSets: " + JSON.stringify(benchmarkConfiguration.pageSets));
+ sessionLoader.run();
+}
+
+chrome.extension.onConnect.addListener(function(port) {
+ port.onMessage.addListener(function(data) {
+ if (data.message == "start") {
+ window.benchmarkConfiguration = data.benchmark;
+ Run()
+ }
+ });
+});

Powered by Google App Engine
This is Rietveld 408576698