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

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: Fix Windows compile error. Created 8 years, 8 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..207979e88605cfd3238f85721bf7e6794b8c0dd6
--- /dev/null
+++ b/tools/page_cycler/webpagereplay/extension/background.js
@@ -0,0 +1,328 @@
+// 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);
+ }
+}
+
+function Result() {
+ var me_ = this;
+ this.url = "";
+ this.firstPaintTime = 0;
+ this.readBytesKB = 0;
+ this.writeBytesKB = 0;
+ this.numRequests = 0;
+ this.numConnects = 0;
+ this.timing = {}; // window.performance.timing
+ this.getTotalTime = function() {
+ var totalTime = 0
+ if (me_.timing.navigationStart && me_.timing.loadEventEnd) {
+ totalTime = me_.timing.loadEventEnd - me_.timing.navigationStart;
+ }
+ CHECK(totalTime >= 0);
+ return totalTime;
+ }
+}
+
+// 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() {
+ return results_.map(function (t) { return t.getTotalTime(); });
+ }
+}
+
+// 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_.clearConnections_;
+ };
+
+ this.clearAll_ = function(callback) {
+ chrome.tabs.getSelected(null, function(tab) {
+ chrome.tabs.update(tab.id, {"url": kWaitUrl}, function() {
+ chrome.benchmarking.clearHostResolverCache();
+ chrome.benchmarking.clearPredictorCache();
+ chrome.benchmarking.closeConnections();
+ var dataToRemove = {
+ "appcache": true,
+ "cache": true,
+ "cookies": true,
+ "downloads": true,
+ "fileSystems": true,
+ "formData": true,
+ "history": true,
+ "indexedDB": true,
+ "localStorage": true,
+ "passwords": true,
+ "pluginData": true,
+ "webSQL": true
+ };
+ // Add any items new to the API.
+ for (var prop in chrome.browsingData) {
+ var dataName = prop.replace("remove", "");
+ if (dataName && dataName != prop) {
+ dataName = dataName.charAt(0).toLowerCase() +
+ dataName.substr(1);
+ if (!dataToRemove.hasOwnProperty(dataName)) {
+ console.log("New browsingData API item: " + dataName);
+ dataToRemove[dataName] = true;
+ }
+ }
+ }
+ chrome.browsingData.remove({}, dataToRemove, callback);
+ });
+ });
+ };
+
+ 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) {
+ if (!isFinished_) {
+ isFinished_ = true;
+ clearTimeout(timeoutId_);
+ chrome.extension.onRequest.removeListener(me_.finishLoad_);
+ me_.saveResult_(msg.loadTimes, msg.timing);
+ }
+ };
+
+ this.saveResult_ = function(loadTimes, timing) {
+ result_ = new Result()
+ result_.url = url_;
+ if (!loadTimes || !timing) {
+ console.log("LOAD INCOMPLETE: " + url_);
+ } else {
+ console.log("LOAD complete: " + url_);
+ result_.timing = timing;
+ var baseTime = timing.navigationStart;
+ CHECK(baseTime);
+ result_.firstPaintTime = Math.max(0,
+ Math.round((1000.0 * loadTimes.firstPaintTime) - baseTime));
+ }
+ result_.readBytesKB = (chrome.benchmarking.counter(kTcpReadBytes) -
+ initialReadBytes_) / 1024;
+ result_.writeBytesKB = (chrome.benchmarking.counter(kTcpWriteBytes) -
+ initialWriteBytes_) / 1024;
+ result_.numRequests = (chrome.benchmarking.counter(kRequestCount) -
+ initialRequestCount_);
+ result_.numConnects = (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.getTotalTime();
+ 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_ + ": " + totalTime);
+ loaderIndex_++;
+ if (loaderIndex_ >= pageLoaders_.length) {
+ iterationIndex_++;
+ if (iterationIndex_ < iterations_) {
+ loaderIndex_ = 0;
+ } else {
+ resultsReadyCallback_(me_);
+ 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()
+ }
+ });
+});
« no previous file with comments | « tools/page_cycler/webpagereplay/extension/background.html ('k') | tools/page_cycler/webpagereplay/extension/content.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698