- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / examples / extensions / buildbot / popup.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 (function(){
6
7 var lkgrURL = 'http://chromium-status.appspot.com/lkgr';
8
9 // Interval at which to reload the non-CL bot status.
10 var botStatusRefreshIntervalInMs = 60 * 1000;
11 // Interval at which to check for LKGR updates.
12 var lkgrRefreshIntervalInMs = 60 * 1000;
13
14 function getClassForTryJobResult(result) {
15   // Some win bots seem to report a null result while building.
16   if (result === null)
17     result = buildbot.RUNNING;
18
19   switch (parseInt(result)) {
20   case buildbot.RUNNING:
21     return "running";
22
23   case buildbot.SUCCESS:
24     return "success";
25
26   case buildbot.WARNINGS:
27     return "warnings";
28
29   case buildbot.FAILURE:
30     return "failure";
31
32   case buildbot.SKIPPED:
33     return "skipped";
34
35   case buildbot.EXCEPTION:
36     return "exception";
37
38   case buildbot.RETRY:
39     return "retry";
40
41   case buildbot.NOT_STARTED:
42   default:
43     return "never";
44   }
45 }
46
47 // Remove try jobs that have been supplanted by newer runs.
48 function filterOldTryJobs(tryJobs) {
49   var latest = {};
50   tryJobs.forEach(function(tryJob) {
51     if (!latest[tryJob.builder] ||
52         latest[tryJob.builder].buildnumber < tryJob.buildnumber)
53       latest[tryJob.builder] = tryJob;
54   });
55
56   var result = [];
57   tryJobs.forEach(function(tryJob) {
58     if (tryJob.buildnumber == latest[tryJob.builder].buildnumber)
59       result.push(tryJob);
60   });
61
62   return result;
63 }
64
65 function createTryJobAnchorTitle(tryJob, fullTryJob) {
66   var title = tryJob.builder;
67
68   if (!fullTryJob)
69     return title;
70
71   var stepText = [];
72   if (fullTryJob.currentStep)
73     stepText.push("running " + fullTryJob.currentStep.name);
74
75   if (fullTryJob.results == buildbot.FAILURE && fullTryJob.text) {
76     stepText.push(fullTryJob.text.join(" "));
77   } else {
78     // Sometimes a step can fail without setting the try job text.  Look
79     // through all the steps to identify if this is the case.
80     var text = [];
81     fullTryJob.steps.forEach(function(step) {
82       if (step.results[0] == buildbot.FAILURE)
83         text.push(step.results[1][0]);
84     });
85
86     if (text.length > 0) {
87       text.unshift("failure");
88       stepText.push(text.join(" "));
89     }
90   }
91
92   if (stepText.length > 0)
93     title += ": " + stepText.join("; ");
94
95   return title;
96 }
97
98 function createPatchsetStatusElement(patchset) {
99   var table = document.createElement("div");
100   table.className = "issue-status";
101
102   var tryJobs = filterOldTryJobs(patchset.try_job_results);
103   tryJobs.forEach(function(tryJob) {
104     var key = tryJob.builder + "-" + tryJob.buildnumber;
105     var fullTryJob = patchset.full_try_job_results &&
106         patchset.full_try_job_results[key];
107
108     var tryJobAnchor = document.createElement("a");
109     tryJobAnchor.textContent = "  ";
110     tryJobAnchor.title = createTryJobAnchorTitle(tryJob, fullTryJob);
111     tryJobAnchor.className = "issue-status-build " +
112       getClassForTryJobResult(tryJob.result);
113     tryJobAnchor.target = "_blank";
114     tryJobAnchor.href = tryJob.url;
115     table.appendChild(tryJobAnchor);
116   });
117
118   return table;
119 }
120
121 function getLastFullPatchsetWithTryJobs(issue) {
122   var index = issue.patchsets.length - 1;
123   var fullPatchsets = issue.full_patchsets;
124   while (index >= 0 &&
125          (!fullPatchsets ||
126           !fullPatchsets[issue.patchsets[index]] ||
127           !fullPatchsets[issue.patchsets[index]].try_job_results ||
128           fullPatchsets[issue.patchsets[index]].try_job_results.length == 0)) {
129     index--;
130   }
131
132   return index >= 0 ? fullPatchsets[issue.patchsets[index]] : null;
133 }
134
135 function createTryStatusRow(issue) {
136   var table = document.getElementById("status-table");
137
138   // Order by decreasing issue number.
139   var position =
140       document.getElementsByClassName("trunk-status-row")[0].rowIndex;
141   while (position > 0 &&
142          parseInt(issue.issue) >
143              parseInt(table.rows[position - 1].getAttribute("data-issue"))) {
144     position--;
145   }
146
147   var row = table.insertRow(position);
148   row.setAttribute("data-issue", issue.issue);
149
150   return row;
151 }
152
153 function updateIssueDisplay(issue) {
154   var codereviewBaseURL = "https://codereview.chromium.org";
155
156   var lastFullPatchset = getLastFullPatchsetWithTryJobs(issue);
157
158   var row = document.querySelector("*[data-issue='" + issue.issue + "']");
159   if (!lastFullPatchset) {
160     if (row)
161       row.parentNode.removeChild(row);
162     return;
163   }
164
165   if (!row)
166     row = createTryStatusRow(issue);
167
168   var label = row.childNodes[0] || row.insertCell(-1);
169   var status = row.childNodes[1] || row.insertCell(-1);
170
171   label.className = "status-label";
172   var clAnchor = label.childNodes[0] ||
173     label.appendChild(document.createElement("a"));
174   clAnchor.textContent = "CL " + issue.issue;
175   clAnchor.href = codereviewBaseURL + "/" + issue.issue;
176   clAnchor.title = issue.subject;
177   if (lastFullPatchset && lastFullPatchset.message)
178     clAnchor.title += " | " + lastFullPatchset.message;
179   clAnchor.target = "_blank";
180
181   var statusElement = createPatchsetStatusElement(lastFullPatchset);
182   if (status.childElementCount < 1)
183     status.appendChild(statusElement);
184   else
185     status.replaceChild(statusElement, status.firstChild);
186 }
187
188 function removeIssueDisplay(issueNumber) {
189   var row = document.querySelector("*[data-issue='" + issueNumber + "']");
190   row.parentNode.removeChild(row);
191 }
192
193 function addTryStatusRows() {
194   buildbot.getActiveIssues().forEach(updateIssueDisplay);
195 }
196
197 function updateLKGR(lkgr) {
198   var link = document.getElementById('link_lkgr');
199   link.textContent = 'LKGR (' + lkgr + ')';
200 }
201
202 function addBotStatusRow(bot, className) {
203   var table = document.getElementById("status-table");
204
205   var baseURL = "http://build.chromium.org/p/chromium" +
206     (bot.id != "" ? "." + bot.id : "");
207   var consoleURL = baseURL + "/console";
208   var statusURL = baseURL + "/horizontal_one_box_per_builder";
209
210   var row = table.insertRow(-1);
211   row.className = "trunk-status-row " + className;
212   var label = row.insertCell(-1);
213   label.className = "status-label";
214   var labelAnchor = document.createElement("a");
215   labelAnchor.href = consoleURL;
216   labelAnchor.target = "_blank";
217   labelAnchor.id = "link_" + bot.id;
218   labelAnchor.textContent = bot.label;
219   label.appendChild(labelAnchor);
220
221   var status = row.insertCell(-1);
222   status.className = "trunk-status-cell";
223   var statusIframe = document.createElement("iframe");
224   statusIframe.scrolling = "no";
225   statusIframe.src = statusURL;
226   status.appendChild(statusIframe);
227 }
228
229 function addBotStatusRows() {
230   var closerBots = [
231     {id: "", label: "Chromium"},
232     {id: "win", label: "Win"},
233     {id: "mac", label: "Mac"},
234     {id: "linux", label: "Linux"},
235     {id: "chromiumos", label: "ChromiumOS"},
236     {id: "chrome", label: "Official"},
237     {id: "memory", label: "Memory"}
238   ];
239
240   var otherBots = [
241     {id: "lkgr", label: "LKGR"},
242     {id: "perf", label: "Perf"},
243     {id: "memory.fyi", label: "Memory FYI"},
244     {id: "gpu", label: "GPU"},
245     {id: "gpu.fyi", label: "GPU FYI"}
246   ];
247
248   closerBots.forEach(function(bot) {
249     addBotStatusRow(bot, "closer-status-row");
250   });
251
252   otherBots.forEach(function(bot) {
253     addBotStatusRow(bot, "other-status-row");
254   });
255 }
256
257 function fillStatusTable() {
258   addBotStatusRows();
259   addTryStatusRows();
260 }
261
262 function main() {
263   buildbot.requestURL(lkgrURL, "text", updateLKGR);
264   fillStatusTable();
265
266   buildbot.getActiveIssues().setEventCallback(function(request) {
267     // NOTE(wittman): It doesn't appear that we can reliably detect closing of
268     // the popup and remove the event callback, so ensure the popup window is
269     // displayed before processing the event.
270     if (!chrome.extension.getViews({type: "popup"}))
271       return;
272
273     switch (request.event) {
274     case "issueUpdated":
275     case "issueAdded":
276       updateIssueDisplay(buildbot.getActiveIssues().getIssue(request.issue));
277       break;
278
279     case "issueRemoved":
280       removeIssueDisplay(request.issue);
281       break;
282     }
283   });
284
285   setInterval(function() {
286     buildbot.requestURL(lkgrURL, "text", updateLKGR);
287   }, lkgrRefreshIntervalInMs);
288
289   setInterval(function() {
290     var botStatusElements =
291         document.getElementsByClassName("trunk-status-iframe");
292     for (var i = 0; i < botStatusElements.length; i++)
293       // Force a reload of the iframe in a way that doesn't cause cross-domain
294       // policy violations.
295       botStatusElements.item(i).src = botStatusElements.item(i).src;
296   }, botStatusRefreshIntervalInMs);
297 }
298
299 main();
300
301 })();