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

Side by Side Diff: Tools/Scripts/webkitpy/thirdparty/webpagereplay/perftracker/extension/background.html

Issue 18418010: Check in the thirdparty libs needed for webkitpy. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 <script type="text/javascript" src="server.js"></script>
2
3 <script>
4 // TODO(mbelshe): Remove all these console.log statements
5
6 var LoadType = { "cold": 0, "hot": 1, "warm": 2 };
7 var LoadTypeNames = [ "cold", "hot", "warm" ];
8
9 // Configuration and results are stored globally.
10 window.iterations = 10;
11 window.interval = 300;
12 window.loadCheck = 0;
13 window.timeout = 15000; // Max ms before killing page.
14 window.maxLoadChecks = Math.round(window.timeout / window.interval);
15 window.enableSpdy = false;
16 window.windowId = 0;
17 window.submitter;
18
19 // TODO(simonjam): This must be in the same order as LoadType is defined.
20 // TODO(simonjam): Figure out how to skip cold and/or hot if desired.
21 window.kTestsToRun = [ LoadType.cold, LoadType.hot, LoadType.warm ];
22
23 // Map the WebTiming property to the name we use to log it.
24 window.loggedTimings = {
25 fetchStart: 'start_load_time',
26 domainLookupEnd: 'dns_time',
27 connectEnd: 'connect_time',
28 responseStart: 'first_byte_time',
29 responseEnd: 'last_byte_time',
30 domInteractive: 'doc_load_time',
31 domContentLoadedEventEnd: 'dcl_time',
32 loadEventEnd: 'total_time',
33 };
34
35 // This is to be provided by the benchmark starter
36 window.benchmarkConfiguration = {};
37
38 // Constant StatCounter Names
39 var kTCPReadBytes = "tcp.read_bytes";
40 var kTCPWriteBytes = "tcp.write_bytes";
41 var kRequestCount = "HttpNetworkTransaction.Count";
42 var kConnectCount = "tcp.connect";
43 var kSpdySessionCount = "spdy.sessions";
44
45 var globalTestSetResults = [];
46
47 function CHECK(expr, comment) {
48 if (!expr) {
49 console.log(comment);
50 alert(comment);
51 }
52 }
53
54 // Returns the max value in the array.
55 Array.max = function(array) {
56 return Math.max.apply(Math, array);
57 };
58
59 // Returns the min value in the array.
60 Array.min = function(array) {
61 return Math.min.apply(Math, array);
62 };
63
64 // Returns the sum of all values in the array.
65 Array.sum = function(array) {
66 var sum = 0;
67 for (var i = array.length - 1; i >= 0; i--) {
68 sum += array[i];
69 }
70 return sum;
71 };
72
73 // Returns the mean of the array.
74 Array.mean = function(array) {
75 var count = array.length;
76 if (count == 0) { return 0; }
77 var sum = Array.sum(array);
78 return sum / count;
79 }
80
81 // Returns the standard deviation of the array
82 Array.stddev = function(array) {
83 var count = array.length;
84 if (count < 2) { return 0; }
85
86 var mean = Array.mean(array);
87 var variance = 0;
88 for (var i = 0; i < count; i++) {
89 var deviation = mean - array[i];
90 variance += deviation * deviation;
91 }
92 variance /= (count - 1);
93 return Math.sqrt(variance);
94 }
95
96 function Result() {
97 this.url = "";
98 this.set_id = 0;
99 this.load_type = "";
100 this.paint_time = 0;
101 this.read_bytes_kb = 0;
102 this.write_bytes_kb = 0;
103 this.num_requests = 0;
104 this.num_connects = 0;
105 this.num_sessions = 0;
106 }
107
108 function ResultCollection() {
109 var results_ = [];
110
111 this.addResult = function(result) {
112 results_.push(result);
113 }
114
115 this.numResults = function() {
116 return results_.length;
117 }
118
119 this.summarize = function() {
120 CHECK(results_.length, "there are no results");
121
122 var unique_urls = {};
123 var total_time_array = []
124 var num = results_.length;
125 var max_iterations = 0;
126
127 var summary = new Result();
128
129 summary.set_id = results_[0].set_id;
130 summary.load_type = results_[0].load_type;
131 summary.iterations = 0;
132
133 for (var i in results_) {
134 var result = results_[i];
135
136 CHECK(summary.set_id == result.set_id, "set_id doesn't match");
137 CHECK(summary.load_type == result.load_type, "load_type doesn't match");
138
139 for (var prop in loggedTimings) {
140 if (loggedTimings[prop] in result) {
141 if (!(loggedTimings[prop] in summary)) {
142 summary[loggedTimings[prop]] = 0;
143 }
144 summary[loggedTimings[prop]] += result[loggedTimings[prop]] / num;
145 }
146 }
147 summary.paint_time += result.paint_time / num;
148 summary.read_bytes_kb += result.read_bytes_kb / num;
149 summary.write_bytes_kb += result.write_bytes_kb / num;
150 summary.num_requests += result.num_requests / num;
151 summary.num_connects += result.num_connects / num;
152 summary.num_sessions += result.num_sessions / num;
153 summary.url = result.url;
154 unique_urls[result.url] = 1;
155 total_time_array.push(result.total_time);
156 max_iterations = Math.max(max_iterations,
157 result.iterations ? result.iterations : 0);
158 }
159
160 var num_unique_urls = 0;
161 for (var url in unique_urls) {
162 num_unique_urls++;
163 }
164 if (num_unique_urls > 1) {
165 summary.iterations = max_iterations;
166 summary.url = "<multiple>";
167 } else {
168 summary.iterations = results_.length;
169 }
170 summary.url_count = num_unique_urls;
171 summary.total_time_stddev = Array.stddev(total_time_array);
172
173 return summary;
174 }
175 }
176
177 function BenchmarkLoad(url, loadType, setId) {
178 var me_ = this;
179 var url_ = url;
180 var loadType_ = loadType;
181 var setId_ = setId;
182 var callbackWhenFinished_;
183
184 var tab_;
185 var result_;
186 var processId_;
187
188 var hasBeenRun_ = false;
189 var checkForLoadId_;
190 var loadCheck_ = 0;
191 var finished_ = false;
192
193 var initialReadBytes_;
194 var initialWriteBytes_;
195 var initialRequestCount_;
196 var initialConnectCount_;
197 var initialSpdySessionCount_;
198 var startTime_;
199
200 this.tab = function() { return tab_; }
201 this.loadType = function() { return loadType_; }
202 this.result = function() { return result_; }
203 this.processId = function() { return processId_; }
204
205 this.run = function(tabToReuse, callbackWhenFinished) {
206 console.log("Running " + url_ + " on tab " +
207 (tabToReuse ? tabToReuse.id : 'new'));
208
209 CHECK(!hasBeenRun_, "This BenchmarkLoad has already run");
210 hasBeenRun_ = true;
211
212 callbackWhenFinished_ = callbackWhenFinished;
213
214 initialReadBytes_ = chrome.benchmarking.counter(kTCPReadBytes);
215 initialWriteBytes_ = chrome.benchmarking.counter(kTCPWriteBytes);
216 initialRequestCount_ = chrome.benchmarking.counter(kRequestCount);
217 initialConnectCount_ = chrome.benchmarking.counter(kConnectCount);
218 initialSpdySessionCount_ = chrome.benchmarking.counter(kSpdySessionCount);
219 startTime_ = new Date();
220
221 var navigationProperties = {
222 "url": url_,
223 "selected": true
224 };
225
226 if (tabToReuse == 0) {
227 // We don't trust the tab creation to succeed, so start a timer
228 // that is cleared when the tab is created.
229 var hangTimer = setTimeout(function() {
230 // It is unlikely but possible for this to get enqueued after
231 // create tabs completes. In this case, loadCheck will have
232 // been cleared, but checkForLoad will not have fired yet.
233 // So, bail out if loadCheck is zero.
234 if (!window.loadCheck) return;
235
236 console.log("chrome.tabs.create failed for " + url_);
237 finished_ = true;
238 callbackWhenFinished_(me_);
239 }, window.timeout);
240
241 chrome.tabs.create(navigationProperties, function(tab) {
242 clearTimeout(hangTimer);
243 me_.startMonitoringLoad(tab);
244 });
245 } else {
246 chrome.tabs.executeScript(
247 tabToReuse.id,
248 { 'code': 'window.history.back();' },
249 function() { me_.startMonitoringLoad(tabToReuse); });
250 }
251 }
252
253 this.startMonitoringLoad = function(tab) {
254 console.log("Assigned " + url_ + " to tab " + tab.id);
255 tab_ = tab;
256 checkForLoadId_ = setInterval(function() {
257 me_.checkForLoad(tab);
258 }, window.interval);
259 }
260
261 this.checkForLoad = function(tab) {
262 loadCheck_++;
263 if (loadCheck_ > window.maxLoadChecks) {
264 console.log("load failed");
265 finished_ = true;
266 clearInterval(checkForLoadId_);
267 me_.finishBenchmarkLoad();
268 return;
269 }
270
271 chrome.tabs.sendRequest(tab.id, {}, me_.handlePossiblePageLoad);
272 }
273
274 this.handlePossiblePageLoad = function(response) {
275 if (finished_) {
276 return;
277 }
278
279 if (response.timing.loadEventEnd && response.loadTimes.finishLoadTime) {
280 finished_ = true;
281 clearInterval(checkForLoadId_);
282
283 // If it record mode, wait here another 10 seconds to be absolutely
284 // sure that any lazy loaded resources are recorded.
285 if (benchmarkConfiguration.record) {
286 setTimeout(function() { me_.handlePageLoaded(response); }, 10000);
287 } else {
288 me_.handlePageLoaded(response);
289 }
290 }
291 }
292
293 this.handlePageLoaded = function(response) {
294 console.log("Page loaded: " + url_ + " on tab " + tab_.id);
295
296 var load_times = response.loadTimes;
297 var timing = response.timing;
298
299 // Make sure the content was fetched via spdy if it is enabled.
300 if (window.enableSpdy && !load_times.wasFetchedViaSpdy) {
301 alert("Did not fetch current url via spdy.\n" +
302 "Ending current test.");
303 me_.finishBenchmarkLoad();
304 return;
305 }
306
307 // Record the individual result
308 var result = new Result()
309 var baseTime = timing.navigationStart;
310 CHECK(baseTime);
311 for (var prop in loggedTimings) {
312 if (prop in timing) {
313 result[loggedTimings[prop]] = timing[prop] - baseTime;
314 }
315 }
316 result.paint_time =
317 load_times.firstPaintTime ?
318 Math.round((1000.0 * load_times.firstPaintTime) - baseTime) : 0;
319 result.set_id = setId_;
320 result.url = url_;
321 result.load_type = LoadTypeNames[loadType_];
322 result.using_spdy = load_times.wasFetchedViaSpdy;
323 var bytesRead = chrome.benchmarking.counter(kTCPReadBytes) -
324 initialReadBytes_;
325 var bytesWrite = chrome.benchmarking.counter(kTCPWriteBytes) -
326 initialWriteBytes_;
327 result.read_bytes_kb = bytesRead / 1024;
328 result.write_bytes_kb = bytesWrite / 1024;
329 result.num_requests = chrome.benchmarking.counter(kRequestCount) -
330 initialRequestCount_;
331 result.num_connects = chrome.benchmarking.counter(kConnectCount) -
332 initialConnectCount_;
333 result.num_sessions = chrome.benchmarking.counter(kSpdySessionCount) -
334 initialSpdySessionCount_;
335
336 result_ = result;
337 window.submitter.PostResult(result, me_.finishBenchmarkLoad);
338 }
339
340 this.finishBenchmarkLoad = function() {
341 chrome.experimental.processes.getProcessIdForTab(tab_.id,
342 me_.handleProcessId);
343 }
344
345 this.handleProcessId = function(processId) {
346 processId_ = processId;
347 if (benchmarkConfiguration.screenshot_dir) {
348 var params = { 'format': 'png' };
349 chrome.tabs.captureVisibleTab(tab_.windowId, params, me_.handleSnapshot);
350 } else {
351 me_.allDone();
352 }
353 }
354
355 this.handleSnapshot = function(dataUri) {
356 postUrl = getWebPageReplayUrl(url_,
357 'post-image-' + LoadTypeNames[loadType_]);
358 XHRPost(postUrl, dataUri, me_.allDone);
359 }
360
361 this.allDone = function() {
362 callbackWhenFinished_(me_);
363 }
364 }
365
366 function Benchmark(url, setIds, callbackWhenFinished) {
367 var me_ = this;
368 var url_ = url;
369 var setIds_ = setIds;
370 var runCount_ = window.iterations;
371 var resultsByLoadType_ = [];
372 var numSummariesInFlight_ = 0;
373 var callbackWhenFinished_ = callbackWhenFinished;
374 var state_;
375 var stateActions_ = [];
376 var initialized_ = false;
377 var processIds_ = {};
378
379 this.runOneIteration = function() {
380 if (!initialized_) {
381 me_.initialize();
382 initialized_ = true;
383 }
384 state_ = LoadType.cold;
385 me_.advanceStateMachine(0);
386 }
387
388 this.initialize = function() {
389 for (var i in kTestsToRun) {
390 resultsByLoadType_[i] = new ResultCollection();
391 }
392 me_.buildStateMachine();
393 }
394
395 this.buildStateMachine = function() {
396 // TODO(simonjam): Support skipping cold and/or hot.
397 stateActions_[LoadType.cold] = me_.runCold;
398 stateActions_[LoadType.hot] = me_.runHot;
399 stateActions_[LoadType.warm] = me_.runWarm;
400 stateActions_[kTestsToRun.length] = me_.handleIterationFinished;
401 }
402
403 this.advanceStateMachine = function(tab) {
404 stateActions_[state_++](tab);
405 }
406
407 this.runCold = function(unusedTab) {
408 console.log("starting cold");
409 var coldLoad = new BenchmarkLoad(url_, LoadType.cold,
410 setIds_[LoadType.cold]);
411
412 chrome.benchmarking.clearCache();
413 chrome.benchmarking.clearHostResolverCache();
414 chrome.benchmarking.clearPredictorCache();
415 chrome.benchmarking.closeConnections();
416 me_.asyncClearCookies();
417
418 // Go back to the browser so that tasks can run.
419 setTimeout(function() { coldLoad.run(0, me_.handleLoadFinished); },
420 window.interval);
421 }
422
423 this.runHot = function(tab) {
424 console.log("starting hot on tab " + tab.id);
425 var hotLoad = new BenchmarkLoad(url_, LoadType.hot,
426 setIds_[LoadType.hot]);
427
428 chrome.tabs.update(
429 tab.id,
430 // We need to navigate away to perform this test, but we still want to
431 // keep the same renderer. Navigating to a bogus url on the same domain
432 // seems to have the desired effect.
433 { "url": getWebPageReplayUrl(url_, 'generate-404'), "selected": true },
434 function(tab) {
435 setTimeout(function() { hotLoad.run(tab, me_.handleLoadFinished); },
436 window.interval);
437 });
438 }
439
440 this.runWarm = function(tab) {
441 console.log("starting warm and closing tab " + tab.id);
442 var warmLoad = new BenchmarkLoad(url_, LoadType.warm,
443 setIds_[LoadType.warm]);
444
445 chrome.benchmarking.closeConnections();
446
447 chrome.tabs.remove(
448 tab.id,
449 function() {
450 setTimeout(function() { warmLoad.run(0, me_.handleLoadFinished); },
451 window.interval)
452 });
453 }
454
455 this.handleLoadFinished = function(benchmarkLoad) {
456 var loadType = benchmarkLoad.loadType();
457 console.log("Posted result for " + url_ + " " + loadType + " from tab " +
458 benchmarkLoad.tab().id);
459 var result = benchmarkLoad.result();
460 if (result != null) {
461 resultsByLoadType_[loadType].addResult(result);
462 }
463 processIds_[loadType] = benchmarkLoad.processId();
464
465 me_.advanceStateMachine(benchmarkLoad.tab());
466 }
467
468 this.handleIterationFinished = function(tab) {
469 runCount_--;
470 if (LoadType.cold in processIds_ && LoadType.hot in processIds_) {
471 CHECK(processIds_[LoadType.cold] == processIds_[LoadType.hot],
472 "Hot load occurred in different process than cold: " +
473 processIds_[LoadType.cold] + " != " + processIds_[LoadType.hot]);
474 }
475 console.log("all load types complete, closing " + tab.id);
476 chrome.tabs.remove(tab.id);
477 if (me_.hasMoreIterations()) {
478 callbackWhenFinished_();
479 } else {
480 me_.handleBenchmarkComplete();
481 }
482 }
483
484 this.hasMoreIterations = function() {
485 if (runCount_ <= 0) { return false; }
486
487 // Dynamically look at the current results and see if the variance is low
488 // enough to warrant no longer testing this page. To do this, we're
489 // using a normal approximate to the distribution of the sample variance.
490 // You can read more about this here:
491 // http://en.wikipedia.org/wiki/Normal_distribution#Estimation_of_parameters
492 // Basically this means we're using a metric similar to the stderr, but
493 // which requires twice the samples:
494 // error = stddev / sqrt(n/2)
495 var kMinIterationsBeforeStop = 5;
496 var kMinErrorBeforeStop = .02; // 2%
497
498 var num_iterations = resultsByLoadType_[LoadType.cold].numResults();
499 if (num_iterations >= kMinIterationsBeforeStop) {
500 var results = resultsByLoadType_[LoadType.cold].summarize();
501 var mean = results.total_time;
502 var stddev = results.total_time_stddev;
503 var error = stddev / Math.sqrt(num_iterations / 2);
504 var ratio = error / mean;
505
506 console.log(url + ": CHECKED EARLY BAIL: " + num_iterations +
507 " iterations, stddev=" + stddev + ", error=" + error);
508
509 if (ratio <= kMinErrorBeforeStop) {
510 console.log("Variance is good enough for url: " + url_ +
511 ", iterations: " + num_iterations +
512 ", stddev: " + stddev +
513 ", error: " + error +
514 ", ratio: " + ratio);
515 runCount_ = 0;
516 return false;
517 }
518 }
519
520 return true;
521 }
522
523 this.handleBenchmarkComplete = function() {
524 console.log("Posting summaries");
525 numSummariesInFlight_ = 0;
526 for (var i in kTestsToRun) {
527 if (resultsByLoadType_[i].numResults()) {
528 numSummariesInFlight_++;
529 var summary = resultsByLoadType_[i].summarize();
530 globalTestSetResults[i].addResult(summary);
531 window.submitter.PostSummary(summary, me_.handleSummaryPosted);
532 }
533 }
534 if (numSummariesInFlight_ == 0) {
535 me_.handleSummaryPosted();
536 }
537 }
538
539 this.handleSummaryPosted = function(response) {
540 console.log("Posted summary: " + response);
541 numSummariesInFlight_--;
542 if (numSummariesInFlight_ <= 0) {
543 callbackWhenFinished_();
544 }
545 }
546
547 this.asyncClearCookies = function() {
548 chrome.cookies.getAll({}, function(cookies) {
549 for (var i = cookies.length - 1; i >= 0; i--) {
550 var cookie = cookies[i];
551
552 if (!cookie || !cookie.domain) continue;
553 var cookie_domain = 'http' + (cookie.secure ? 's' : '') + '://' + cookie .domain;
554
555 // Do not clear the cookie which allows us to login to the results serve r also.
556 if (!benchmarkConfiguration.server_url) {
557 console.log("WARNING: Not clearing any cookies because unable to " +
558 "determine results server URL.");
559 continue;
560 }
561 if (benchmarkConfiguration.server_url.indexOf(cookie_domain) == 0) {
562 continue;
563 }
564
565 chrome.cookies.remove({
566 url: cookie_domain + cookie.path,
567 name: cookie.name,
568 storeId: cookie.storeId,
569 });
570 }
571 });
572 }
573 }
574
575 function BenchmarkManager() {
576 var me_ = this;
577 var setIds_ = [];
578 var benchmarks_ = [];
579 var currentBenchmarkIndex_ = 0;
580 var numSummariesInFlight_ = 0;
581 var numTestsToCreate_;
582
583 this.run = function() {
584 me_.createTests();
585 }
586
587 this.createTests = function() {
588 numTestsToCreate_ = kTestsToRun.length;
589 CHECK(numTestsToCreate_, "There are no tests to run");
590 for (var i in kTestsToRun) {
591 globalTestSetResults[i] = new ResultCollection();
592 window.submitter.CreateTest(LoadTypeNames[kTestsToRun[i]],
593 me_.handleTestCreated);
594 }
595 }
596
597 this.handleTestCreated = function(loadType, setId) {
598 numTestsToCreate_--;
599 setIds_[LoadType[loadType]] = setId;
600 if (numTestsToCreate_ <= 0) {
601 me_.createBenchmarks();
602 me_.runNextBenchmark();
603 }
604 }
605
606 this.createBenchmarks = function() {
607 var urls = benchmarkConfiguration.urls;
608 for (var i = 0; i < urls.length; i++) {
609 // Remove extra space at the beginning or end of a url.
610 urls[i] = removeSpace(urls[i]);
611
612 // Alert about and ignore blank page which does not get loaded.
613 if (urls[i] == "about:blank") {
614 alert("blank page loaded!");
615 } else if (!checkScheme(urls[i])) {
616 // Alert about url that is not in scheme http:// or https://.
617 alert(urls[i] + " does not start with http:// or https://.");
618 } else {
619 var benchmark = new Benchmark(urls[i], setIds_,
620 me_.handleBenchmarkIterationFinished);
621 benchmarks_.push(benchmark);
622 }
623 }
624 }
625
626 this.runNextBenchmark = function() {
627 var benchmark = benchmarks_[currentBenchmarkIndex_];
628 setTimeout(function() {
629 benchmark.runOneIteration();
630 }, window.interval);
631 }
632
633 this.handleBenchmarkIterationFinished = function() {
634 numSummariesInFlight_ = 0;
635 for (var i in kTestsToRun) {
636 if (globalTestSetResults[i].numResults()) {
637 numSummariesInFlight_++;
638 window.submitter.UpdateSetSummary(
639 globalTestSetResults[i].summarize(),
640 me_.handleSummaryPosted);
641 }
642 }
643 if (numSummariesInFlight_ == 0) {
644 me_.handleSummaryPosted();
645 }
646 }
647
648 this.handleSummaryPosted = function(response) {
649 console.log("Posted set summary: " + response);
650 numSummariesInFlight_--;
651 if (numSummariesInFlight_ <= 0) {
652 if (benchmarks_[currentBenchmarkIndex_].hasMoreIterations()) {
653 currentBenchmarkIndex_++;
654 } else {
655 benchmarks_.splice(currentBenchmarkIndex_, 1);
656 if (benchmarks_.length == 0) {
657 me_.asyncExitBrowser();
658 return;
659 }
660 }
661 if (currentBenchmarkIndex_ >= benchmarks_.length) {
662 currentBenchmarkIndex_ = 0;
663 }
664 me_.runNextBenchmark();
665 }
666 }
667
668 this.asyncExitBrowser = function() {
669 chrome.tabs.getAllInWindow(null, function(tabs) {
670 tabs.forEach(function(tab) {
671 chrome.tabs.remove(tab.id);
672 });
673 });
674 // FIXME: This doesn't actually exit on mac.
675 }
676 }
677
678 chrome.extension.onConnect.addListener(function(port) {
679 port.onMessage.addListener(function(data) {
680 if (data.message == "start") {
681 window.benchmarkConfiguration = data.benchmark;
682 window.submitter = new TestResultSubmitter(benchmarkConfiguration);
683 run();
684 }
685 });
686 });
687
688 function run() {
689 window.iterations = benchmarkConfiguration.iterations;
690 window.enableSpdy = benchmarkConfiguration.protocol == "spdy" ||
691 benchmarkConfiguration.protocol == "spdy-nossl";
692
693 if (window.clearCache) {
694 // Show a warning if we will try to clear the cache between runs
695 // but will also be reusing the same WebKit instance (i.e. Chrome
696 // is in single-process mode) because the WebKit cache might not get
697 // completely cleared between runs.
698 if (chrome.benchmarking.isSingleProcess()) {
699 alert("Warning: the WebKit cache may not be cleared correctly " +
700 "between runs because Chrome is running in single-process mode.");
701 }
702 }
703
704 var benchmarkManager = new BenchmarkManager();
705 benchmarkManager.run();
706 }
707
708 // Remove extra whitespace in the beginning or end of a url string.
709 function removeSpace(url) {
710 var tempUrl = url;
711 while (tempUrl.charAt(tempUrl.length-1) == " ") {
712 tempUrl = tempUrl.substring(0, tempUrl.length-1);
713 };
714 while (tempUrl.charAt(0) == " ") {
715 tempUrl = tempUrl.substring(1, tempUrl.length);
716 };
717 return tempUrl;
718 }
719
720 // Check whether a Url starts with http:// or https://.
721 function checkScheme(url) {
722 var httpStr = "http://";
723 var httpsStr = "https://";
724 var urlSubStr1 = url.substring(0, httpStr.length);
725 var urlSubStr2 = url.substring(0, httpsStr.length);
726
727 if ( (urlSubStr1 == httpStr) || (urlSubStr2 == httpsStr) ) {
728 return true;
729 }
730 return false;
731 }
732
733 function getWebPageReplayUrl(url, suffix) {
734 var startOfHost = url.indexOf('//') + 2;
735 var startOfPath = url.indexOf('/', startOfHost);
736 var baseUrl = url.substr(0, startOfPath);
737 var customUrl = baseUrl + '/web-page-replay-' + suffix;
738 return customUrl;
739 }
740
741 // Run at startup
742 chrome.windows.getCurrent(function(currentWindow) {
743 window.windowId = currentWindow.id;
744 });
745 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698