1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// found in the LICENSE file.
4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/** Information about a particular waterfall. */
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfunction WaterfallInfo(waterfallData) {
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var waterfallName = waterfallData[0];
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var waterfallUrl = waterfallData[1];
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var waterfallShowsAllBots = waterfallData[2];
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
11a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create a table cell that acts as a header for its bot section.
12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var linkElement = document.createElement('a');
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  linkElement.href = waterfallUrl;
14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  linkElement.innerHTML = waterfallName;
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var thElement = document.createElement('th');
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  thElement.colSpan = 15;
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  thElement.className = 'section-header';
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  thElement.appendChild(linkElement);
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.botInfo = {};
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.inFlight = 0;
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.name = waterfallName;
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.showsAllBots = waterfallShowsAllBots;
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.thElement = thElement;
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.timeLastRequested = 0;
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.rootJsonUrl = waterfallUrl + 'json/';
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.url = waterfallUrl;
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/** Send an asynchronous request to get the main waterfall's JSON. */
31a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochWaterfallInfo.prototype.requestJson = function() {
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (this.inFlight) {
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var elapsed = new Date().getTime() - this.timeLastRequested;
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (elapsed < MAX_MILLISECONDS_TO_WAIT) return;
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // A response was not received in a reasonable timeframe. Try again.
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    this.inFlight--;
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gNumRequestsInFlight--;
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gNumRequestsRetried++;
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.inFlight++;
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.timeLastRequested = new Date().getTime();
44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gNumRequestsInFlight++;
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create the request and send it off.
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var waterfallInfo = this;
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var url = this.url + 'json/builders/';
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var request = new XMLHttpRequest();
50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  request.open('GET', url, true);
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  request.onreadystatechange = function() {
52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (request.readyState == 4 && request.status == 200) {
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      waterfallInfo.parseJSON(JSON.parse(request.responseText));
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  };
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  request.send(null);
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/** Parse out the data received about the waterfall. */
60a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochWaterfallInfo.prototype.parseJSON = function(buildersJson) {
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  this.inFlight--;
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gNumRequestsInFlight--;
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Go through each builder on the waterfall and get the latest status.
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var builderNames = Object.keys(buildersJson);
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (var i = 0; i < builderNames.length; ++i) {
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var builderName = builderNames[i];
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!this.showsAllBots && !this.shouldShowBot(builderName)) continue;
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Prepare the bot info.
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var builderJson = buildersJson[builderName];
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!this.botInfo[builderName]) {
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      this.botInfo[builderName] = new BotInfo(builderName,
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                              builderJson.category);
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    this.botInfo[builderName].update(this.rootJsonUrl, builderJson);
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gWaterfallDataIsDirty = true;
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/** Override this function to filter out particular bots. */
83a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochWaterfallInfo.prototype.shouldShowBot = function(builderName) {
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return true;
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/** Updates the HTML. */
88a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochWaterfallInfo.prototype.updateWaterfallStatusHTML = function() {
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var table = document.getElementById('build-info');
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Point at the waterfall.
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var headerCell = this.thElement;
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  headerCell.className =
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      'section-header' + (this.inFlight > 0 ? ' in-flight' : '');
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var headerRow = table.insertRow(-1);
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  headerRow.appendChild(headerCell);
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Print out useful bits about the bots.
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  var botNames = sortBotNamesByCategory(this.botInfo);
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (var i = 0; i < botNames.length; ++i) {
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var botName = botNames[i];
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var botInfo = this.botInfo[botName];
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var waterfallBaseUrl = this.url + 'builders/';
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var botRowElement = botInfo.createHtml(waterfallBaseUrl);
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Determine whether we should apply keyword filter.
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var filter = document.getElementById('text-filter').value.trim();
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (filter.length > 0) {
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      var keywords = filter.split(' ');
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      var buildNumbers = Object.keys(botInfo.builds);
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      var matchesFilter = false;
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      for (var x = 0; x < buildNumbers.length && !matchesFilter; ++x) {
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        var buildStatus = botInfo.builds[buildNumbers[x]].statusText;
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for (var y = 0; y < keywords.length && !matchesFilter; ++y) {
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          if (buildStatus.indexOf(keywords[y]) >= 0)
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            matchesFilter = true;
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        }
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      }
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      if (!matchesFilter)
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        continue;
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // If the user doesn't want to see completely green bots, hide it.
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    var shouldHideStable =
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        document.getElementById('checkbox-hide-stable').checked;
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (shouldHideStable && botInfo.isSteadyGreen)
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      continue;
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    table.appendChild(botRowElement);
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
135