13c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski/*
23c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * Copyright (C) 2010 The Android Open Source Project
33c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski *
43c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * Licensed under the Apache License, Version 2.0 (the "License");
53c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * you may not use this file except in compliance with the License.
63c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * You may obtain a copy of the License at
73c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski *
83c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski *      http://www.apache.org/licenses/LICENSE-2.0
93c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski *
103c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * Unless required by applicable law or agreed to in writing, software
113c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * distributed under the License is distributed on an "AS IS" BASIS,
123c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * See the License for the specific language governing permissions and
143c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * limitations under the License.
153c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski */
163c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
173c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowskipackage com.android.dumprendertree2;
183c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
19394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowskiimport android.content.Context;
202e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport android.content.res.AssetManager;
212e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport android.content.res.Configuration;
222e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport android.content.res.Resources;
23394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowskiimport android.database.Cursor;
242e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport android.os.Build;
259893d96d1231235f3d984e9dc751f08409a5f873Maksymilian Osowskiimport android.os.Message;
262e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport android.util.DisplayMetrics;
27603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowskiimport android.util.Log;
28603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski
29603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowskiimport com.android.dumprendertree2.forwarder.ForwarderManager;
302e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski
313c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowskiimport java.io.File;
32603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowskiimport java.net.MalformedURLException;
331b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowskiimport java.net.URI;
34603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowskiimport java.net.URL;
356d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowskiimport java.text.SimpleDateFormat;
366d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowskiimport java.util.ArrayList;
376d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowskiimport java.util.Date;
386d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowskiimport java.util.List;
392e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport java.util.regex.Matcher;
402e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowskiimport java.util.regex.Pattern;
413c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
423c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski/**
433c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * A class that collects information about tests that ran and can create HTML
443c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski * files with summaries and easy navigation.
453c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski */
463c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowskipublic class Summarizer {
473c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
483c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    private static final String LOG_TAG = "Summarizer";
493c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
503c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    private static final String CSS =
516d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "<style type=\"text/css\">" +
524ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "* {" +
534ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       font-family: Verdana;" +
544ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border: 0;" +
554ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       margin: 0;" +
564ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       padding: 0;}" +
574ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "body {" +
584ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       margin: 10px;}" +
594ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "h1 {" +
606d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-size: 24px;" +
614ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       margin: 4px 0 4px 0;}" +
624ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "h2 {" +
636d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-size:18px;" +
646d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       text-transform: uppercase;" +
654ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       margin: 20px 0 3px 0;}" +
666d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "h3, h3 a {" +
676d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-size: 14px;" +
686d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: black;" +
696d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       text-decoration: none;" +
7001c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       margin-top: 4px;" +
7101c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       margin-bottom: 2px;}" +
726d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "h3 a span.path {" +
736d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       text-decoration: underline;}" +
746d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "h3 span.tri {" +
754a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       text-decoration: none;" +
764a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       float: left;" +
774a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       width: 20px;}" +
784a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "h3 span.sqr {" +
794a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       text-decoration: none;" +
804a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       float: left;" +
814a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       width: 20px;}" +
828a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "h3 span.sqr_pass {" +
838a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "       color: #8ee100;}" +
848a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "h3 span.sqr_fail {" +
858a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "       color: #c30000;}" +
8601c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "span.source {" +
8701c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       display: block;" +
8801c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       font-size: 10px;" +
8901c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       color: #888;" +
9001c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       margin-left: 20px;" +
9101c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       margin-bottom: 1px;}" +
9201c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "span.source a {" +
9301c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       font-size: 10px;" +
9401c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            "       color: #888;}" +
956d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "h3 img {" +
966d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       width: 8px;" +
976d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       margin-right: 4px;}" +
986d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "div.diff {" +
996d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       margin-bottom: 25px;}" +
1006d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "div.diff a {" +
1016d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-size: 12px;" +
1026d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: #888;}" +
1034ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff {" +
1044ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-bottom: 0px solid;" +
1054ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-collapse: collapse;" +
1064ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       width: 100%;" +
1076d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       margin-bottom: 2px;}" +
1084ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr.headers td {" +
1094ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-bottom: 1px solid;" +
1104ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-top: 0;" +
1114ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       padding-bottom: 3px;}" +
1124ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr.results td {" +
1134ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-top: 1px dashed;" +
1144ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-right: 1px solid;" +
1154ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       font-size: 15px;" +
1164ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       vertical-align: top;}" +
1174ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr.results td.line_count {" +
1184ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       background-color:#aaa;" +
1194ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       min-width:20px;" +
1204ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       text-align: right;" +
1214ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-right: 1px solid;" +
1224ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-left: 1px solid;" +
1234ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       padding: 2px 1px 2px 0px;}" +
1244ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr.results td.line {" +
1254ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       padding: 2px 0px 2px 4px;" +
1264ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-right: 1px solid;" +
1274ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       width: 49.8%;}" +
1284ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr.footers td {" +
1294ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-top: 1px solid;" +
1304ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border-bottom: 0;}" +
1314ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "table.visual_diff tr td.space {" +
1324ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       border: 0;" +
1334ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       width: 0.4%}" +
1344ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "div.space {" +
1356d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       margin-top:4px;}" +
1364ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "span.eql {" +
1374ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       background-color: #f3f3f3;}" +
1384ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "span.del {" +
1394ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       background-color: #ff8888; }" +
1404ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "span.ins {" +
1414ee7f4b19489f4dc9b87e90d1e5c7742cfa7ebe0Maksymilian Osowski            "       background-color: #88ff88; }" +
1426d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "table.summary {" +
1436d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       border: 1px solid black;" +
1446d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       margin-top: 20px;}" +
1456d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "table.summary td {" +
1466d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       padding: 3px;}" +
1476d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "span.listItem {" +
1486d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-size: 11px;" +
1496d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       font-weight: normal;" +
1506d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       text-transform: uppercase;" +
1516d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       padding: 3px;" +
1526d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       -webkit-border-radius: 4px;}" +
1538a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "span." + AbstractResult.ResultCode.RESULTS_DIFFER.name() + "{" +
1546d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       background-color: #ccc;" +
1556d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: black;}" +
1568a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "span." + AbstractResult.ResultCode.NO_EXPECTED_RESULT.name() + "{" +
1576d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       background-color: #a700e4;" +
1586d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: #fff;}" +
1598a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "span.timed_out {" +
1606d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       background-color: #f3cb00;" +
1616d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: black;}" +
1628a6def02473ee4fbffcd1b34173daf751d316202Steve Block            "span.crashed {" +
1636d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       background-color: #c30000;" +
1646d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "       color: #fff;}" +
1654a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "span.noLtc {" +
1664a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski            "       background-color: #944000;" +
1677e2a39b5985a1449588a397195c178bfef9421dbMaksymilian Osowski            "       color: #fff;}" +
1687e2a39b5985a1449588a397195c178bfef9421dbMaksymilian Osowski            "span.noEventSender {" +
1697e2a39b5985a1449588a397195c178bfef9421dbMaksymilian Osowski            "       background-color: #815600;" +
1707e2a39b5985a1449588a397195c178bfef9421dbMaksymilian Osowski            "       color: #fff;}" +
1716d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "</style>";
1723c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
1736d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    private static final String SCRIPT =
1746d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "<script type=\"text/javascript\">" +
1756d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "    function toggleDisplay(id) {" +
1766d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "        element = document.getElementById(id);" +
1776d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "        triangle = document.getElementById('tri.' + id);" +
1786d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "        if (element.style.display == 'none') {" +
1796d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "            element.style.display = 'inline';" +
1806d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "            triangle.innerHTML = '&#x25bc; ';" +
1816d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "        } else {" +
1826d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "            element.style.display = 'none';" +
1836d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "            triangle.innerHTML = '&#x25b6; ';" +
1846d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "        }" +
1856d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "    }" +
1866d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            "</script>";
1873c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
1886d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    /** TODO: Make it a setting */
1895fb9ff420d378c5c83e116efadefb669791098d5Maksymilian Osowski    private static final String HTML_DETAILS_RELATIVE_PATH = "details.html";
1903df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski    private static final String TXT_SUMMARY_RELATIVE_PATH = "summary.txt";
1913c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
192fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski    private static final int RESULTS_PER_DUMP = 500;
193394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private static final int RESULTS_PER_DB_ACCESS = 50;
194fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski
1956d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    private int mCrashedTestsCount = 0;
1966ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski    private List<AbstractResult> mUnexpectedFailures = new ArrayList<AbstractResult>();
1976ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski    private List<AbstractResult> mExpectedFailures = new ArrayList<AbstractResult>();
19801c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski    private List<AbstractResult> mExpectedPasses = new ArrayList<AbstractResult>();
19901c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski    private List<AbstractResult> mUnexpectedPasses = new ArrayList<AbstractResult>();
2003c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
201394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private Cursor mUnexpectedFailuresCursor;
202394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private Cursor mExpectedFailuresCursor;
203394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private Cursor mUnexpectedPassesCursor;
204394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private Cursor mExpectedPassesCursor;
205394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
2063c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    private FileFilter mFileFilter;
2073c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    private String mResultsRootDirPath;
2082e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    private String mTestsRelativePath;
2092e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    private Date mDate;
2103df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
211fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski    private int mResultsSinceLastHtmlDump = 0;
212394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private int mResultsSinceLastDbAccess = 0;
213394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
214394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private SummarizerDBHelper mDbHelper;
215fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski
216cda9448206494b67c0812b9591cc066ca070a7a6Steve Block    public Summarizer(String resultsRootDirPath, Context context) {
217cda9448206494b67c0812b9591cc066ca070a7a6Steve Block        mFileFilter = new FileFilter();
2183c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski        mResultsRootDirPath = resultsRootDirPath;
219394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
220394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        /**
221394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski         * We don't run the database I/O in a separate thread to avoid consumer/producer problem
222394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski         * and to simplify code.
223394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski         */
224394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mDbHelper = new SummarizerDBHelper(context);
225394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mDbHelper.open();
2263c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
2273c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
2281b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowski    public static URI getDetailsUri() {
2291b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowski        return new File(ManagerService.RESULTS_ROOT_DIR_PATH + File.separator +
2301b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowski                HTML_DETAILS_RELATIVE_PATH).toURI();
2311b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowski    }
2321b034781f4c45608e4d57e46cd46dfab9fc64746Maksymilian Osowski
2336d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    public void appendTest(AbstractResult result) {
2346d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        String relativePath = result.getRelativePath();
2356d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
2368a6def02473ee4fbffcd1b34173daf751d316202Steve Block        if (result.didCrash()) {
2376d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            mCrashedTestsCount++;
2386d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        }
2396d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
2408a6def02473ee4fbffcd1b34173daf751d316202Steve Block        if (result.didPass()) {
241394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            result.clearResults();
2426ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            if (mFileFilter.isFail(relativePath)) {
24301c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski                mUnexpectedPasses.add(result);
2446ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            } else {
24501c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski                mExpectedPasses.add(result);
2466ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            }
2476d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        } else {
2486ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            if (mFileFilter.isFail(relativePath)) {
2496ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski                mExpectedFailures.add(result);
2506ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            } else {
2516ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski                mUnexpectedFailures.add(result);
2526ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            }
2536d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        }
254394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
255394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        if (++mResultsSinceLastDbAccess == RESULTS_PER_DB_ACCESS) {
256394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            persistLists();
257394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            clearLists();
258394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        }
259394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    }
260394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
261394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private void clearLists() {
262394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedFailures.clear();
263394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedFailures.clear();
264394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedPasses.clear();
265394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedPasses.clear();
266394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    }
267394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
268394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private void persistLists() {
269394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        persistListToTable(mUnexpectedFailures, SummarizerDBHelper.UNEXPECTED_FAILURES_TABLE);
270394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        persistListToTable(mExpectedFailures, SummarizerDBHelper.EXPECTED_FAILURES_TABLE);
271394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        persistListToTable(mUnexpectedPasses, SummarizerDBHelper.UNEXPECTED_PASSES_TABLE);
272394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        persistListToTable(mExpectedPasses, SummarizerDBHelper.EXPECTED_PASSES_TABLE);
273394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mResultsSinceLastDbAccess = 0;
274394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    }
275394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
276394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski    private void persistListToTable(List<AbstractResult> results, String table) {
277394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        for (AbstractResult abstractResult : results) {
278394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            mDbHelper.insertAbstractResult(abstractResult, table);
279394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        }
2803c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
2813c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
2822e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    public void setTestsRelativePath(String testsRelativePath) {
2832e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        mTestsRelativePath = testsRelativePath;
2842e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    }
2852e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski
2869893d96d1231235f3d984e9dc751f08409a5f873Maksymilian Osowski    public void summarize(Message onFinishMessage) {
287394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        persistLists();
288394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        clearLists();
289394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
290394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedFailuresCursor =
291394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            mDbHelper.getAbstractResults(SummarizerDBHelper.UNEXPECTED_FAILURES_TABLE);
292394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedPassesCursor =
293394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            mDbHelper.getAbstractResults(SummarizerDBHelper.UNEXPECTED_PASSES_TABLE);
294394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedFailuresCursor =
295394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            mDbHelper.getAbstractResults(SummarizerDBHelper.EXPECTED_FAILURES_TABLE);
296394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedPassesCursor =
297394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            mDbHelper.getAbstractResults(SummarizerDBHelper.EXPECTED_PASSES_TABLE);
298394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
299ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        String webKitRevision = getWebKitRevision();
300ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        createHtmlDetails(webKitRevision);
301ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        createTxtSummary(webKitRevision);
302394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
303394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        clearLists();
304394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedFailuresCursor.close();
305394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mUnexpectedPassesCursor.close();
306394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedFailuresCursor.close();
307394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mExpectedPassesCursor.close();
308394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
3099893d96d1231235f3d984e9dc751f08409a5f873Maksymilian Osowski        onFinishMessage.sendToTarget();
3103df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski    }
3113df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
312ea46f2595a8718d4478e016fd40b2d57658289cfMaksymilian Osowski    public void reset() {
313ea46f2595a8718d4478e016fd40b2d57658289cfMaksymilian Osowski        mCrashedTestsCount = 0;
314394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        clearLists();
315394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        mDbHelper.reset();
3162e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        mDate = new Date();
317ea46f2595a8718d4478e016fd40b2d57658289cfMaksymilian Osowski    }
318ea46f2595a8718d4478e016fd40b2d57658289cfMaksymilian Osowski
319fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski    private void dumpHtmlToFile(StringBuilder html, boolean append) {
320fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DETAILS_RELATIVE_PATH),
321fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski                html.toString().getBytes(), append);
322fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski        html.setLength(0);
323fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski        mResultsSinceLastHtmlDump = 0;
324fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski    }
325fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski
326ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block    private void createTxtSummary(String webKitRevision) {
3273df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski        StringBuilder txt = new StringBuilder();
3283df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
3292e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
33075aa0d382844dbee2d7931f21245112c27dd3d64Maksymilian Osowski        txt.append("Path: " + mTestsRelativePath + "\n");
3312e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        txt.append("Date: " + dateFormat.format(mDate) + "\n");
3322e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        txt.append("Build fingerprint: " + Build.FINGERPRINT + "\n");
3332e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        txt.append("WebKit version: " + getWebKitVersionFromUserAgentString() + "\n");
334ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        txt.append("WebKit revision: " + webKitRevision + "\n");
3352e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski
3367438b53487cb21f261eac4396aba0dbaa16ee015Steve Block        txt.append("TOTAL:                     " + getTotalTestCount() + "\n");
3377438b53487cb21f261eac4396aba0dbaa16ee015Steve Block        txt.append("CRASHED (among all tests): " + mCrashedTestsCount + "\n");
338394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        txt.append("UNEXPECTED FAILURES:       " + mUnexpectedFailuresCursor.getCount() + "\n");
339394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        txt.append("UNEXPECTED PASSES:         " + mUnexpectedPassesCursor.getCount() + "\n");
340394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        txt.append("EXPECTED FAILURES:         " + mExpectedFailuresCursor.getCount() + "\n");
341394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        txt.append("EXPECTED PASSES:           " + mExpectedPassesCursor.getCount() + "\n");
3423df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
3433df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, TXT_SUMMARY_RELATIVE_PATH),
3443df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski                txt.toString().getBytes(), false);
3453df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski    }
3463df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
347ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block    private void createHtmlDetails(String webKitRevision) {
3483c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski        StringBuilder html = new StringBuilder();
3493c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
3506d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("<html><head>");
3516d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append(CSS);
3526d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append(SCRIPT);
3536d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("</head><body>");
3546d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
355ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        createTopSummaryTable(webKitRevision, html);
356fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski        dumpHtmlToFile(html, false);
3576d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
358394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createResultsList(html, "Unexpected failures", mUnexpectedFailuresCursor);
359394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createResultsList(html, "Unexpected passes", mUnexpectedPassesCursor);
360394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createResultsList(html, "Expected failures", mExpectedFailuresCursor);
361394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createResultsList(html, "Expected passes", mExpectedPassesCursor);
3626d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
3636d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("</body></html>");
364fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski        dumpHtmlToFile(html, true);
3653c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
3663c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
3672e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    private int getTotalTestCount() {
368394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        return mUnexpectedFailuresCursor.getCount() +
369394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski                mUnexpectedPassesCursor.getCount() +
370394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski                mExpectedPassesCursor.getCount() +
371394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski                mExpectedFailuresCursor.getCount();
3722e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    }
3733df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
3742e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski    private String getWebKitVersionFromUserAgentString() {
3752e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        Resources resources = new Resources(new AssetManager(), new DisplayMetrics(),
3762e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski                new Configuration());
3772e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        String userAgent =
3782e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski                resources.getString(com.android.internal.R.string.web_user_agent);
3792e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski
3802e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        Matcher matcher = Pattern.compile("AppleWebKit/([0-9]+?\\.[0-9])").matcher(userAgent);
3812e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        if (matcher.find()) {
3822e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski            return matcher.group(1);
3832e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        }
3842e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        return "unknown";
3853df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski    }
3863df4eab3de243d3e9a68d2554eeaed3b1bb4d69dMaksymilian Osowski
3872ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski    private String getWebKitRevision() {
3882ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        URL url = null;
3892ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        try {
3900e2bae14b408d001fea84c0cbdb7348c3ec611a3Steve Block            url = new URL(ForwarderManager.getHostSchemePort(false) + "ThirdPartyProject.prop");
3912ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        } catch (MalformedURLException e) {
3922ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski            assert false;
3932ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        }
3942ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski
3950e2bae14b408d001fea84c0cbdb7348c3ec611a3Steve Block        String thirdPartyProjectContents = new String(FsUtils.readDataFromUrl(url));
3960e2bae14b408d001fea84c0cbdb7348c3ec611a3Steve Block        Matcher matcher = Pattern.compile("^version=([0-9]+)", Pattern.MULTILINE).matcher(
3970e2bae14b408d001fea84c0cbdb7348c3ec611a3Steve Block                thirdPartyProjectContents);
3982ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        if (matcher.find()) {
3992ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski            return matcher.group(1);
4002ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        }
4012ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        return "unknown";
4022ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski    }
4032ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski
404ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block    private void createTopSummaryTable(String webKitRevision, StringBuilder html) {
4052e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
40675aa0d382844dbee2d7931f21245112c27dd3d64Maksymilian Osowski        html.append("<h1>" + "Layout tests' results for: " +
40775aa0d382844dbee2d7931f21245112c27dd3d64Maksymilian Osowski                (mTestsRelativePath.equals("") ? "all tests" : mTestsRelativePath) + "</h1>");
4082e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        html.append("<h3>" + "Date: " + dateFormat.format(new Date()) + "</h3>");
4092e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        html.append("<h3>" + "Build fingerprint: " + Build.FINGERPRINT + "</h3>");
4102e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        html.append("<h3>" + "WebKit version: " + getWebKitVersionFromUserAgentString() + "</h3>");
4113c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4122ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        html.append("<h3>" + "WebKit revision: ");
413ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block        html.append("<a href=\"http://trac.webkit.org/browser/trunk?rev=" + webKitRevision +
414ab87db4ad8e16e36f99303933db5267946e7bb34Steve Block                "\" target=\"_blank\"><span class=\"path\">" + webKitRevision + "</span></a>");
4152ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski        html.append("</h3>");
4162ca8acdb5622b03a4ef56159477087adcf87db62Maksymilian Osowski
4176d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("<table class=\"summary\">");
4182e64bb7afdd97c954491877306ccb8318f8ec3ceMaksymilian Osowski        createSummaryTableRow(html, "TOTAL", getTotalTestCount());
4197438b53487cb21f261eac4396aba0dbaa16ee015Steve Block        createSummaryTableRow(html, "CRASHED (among all tests)", mCrashedTestsCount);
420394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createSummaryTableRow(html, "UNEXPECTED FAILURES", mUnexpectedFailuresCursor.getCount());
421394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createSummaryTableRow(html, "UNEXPECTED PASSES", mUnexpectedPassesCursor.getCount());
422394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createSummaryTableRow(html, "EXPECTED FAILURES", mExpectedFailuresCursor.getCount());
423394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        createSummaryTableRow(html, "EXPECTED PASSES", mExpectedPassesCursor.getCount());
4246d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("</table>");
4253c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
4263c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4276d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    private void createSummaryTableRow(StringBuilder html, String caption, int size) {
4286d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("<tr>");
4296d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("    <td>" + caption + "</td>");
4306d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("    <td>" + size + "</td>");
4316d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        html.append("</tr>");
4326d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski    }
4333c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4348a6def02473ee4fbffcd1b34173daf751d316202Steve Block    private void createResultsList(
435394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            StringBuilder html, String title, Cursor cursor) {
4366d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        String relativePath;
4376d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        String id = "";
4386d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski        AbstractResult.ResultCode resultCode;
4393c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
440394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        html.append("<h2>" + title + " [" + cursor.getCount() + "]</h2>");
441394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
442394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        if (!cursor.moveToFirst()) {
443394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            return;
444394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        }
445394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
446394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        AbstractResult result;
447394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        do {
448394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            result = SummarizerDBHelper.getAbstractResult(cursor);
449394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
4506d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            relativePath = result.getRelativePath();
4516d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            resultCode = result.getResultCode();
4523c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4536d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            html.append("<h3>");
4546d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski
4556ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            /**
4566ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski             * Technically, two different paths could end up being the same, because
4576ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski             * ':' is a valid  character in a path. However, it is probably not going
4586ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski             * to cause any problems in this case
4596ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski             */
4606ae5ce4b409759d36f2350e96ff2242e1385b147Maksymilian Osowski            id = relativePath.replace(File.separator, ":");
4618a6def02473ee4fbffcd1b34173daf751d316202Steve Block
4628a6def02473ee4fbffcd1b34173daf751d316202Steve Block            /** Write the test name */
4638a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (resultCode == AbstractResult.ResultCode.RESULTS_DIFFER) {
4648a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<a href=\"#\" onClick=\"toggleDisplay('" + id + "');");
4658a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("return false;\">");
4668a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<span class=\"tri\" id=\"tri." + id + "\">&#x25b6; </span>");
4678a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<span class=\"path\">" + relativePath + "</span>");
4688a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("</a>");
4698a6def02473ee4fbffcd1b34173daf751d316202Steve Block            } else {
4708a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<a href=\"" + getViewSourceUrl(result.getRelativePath()).toString() + "\"");
4718a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" target=\"_blank\">");
4728a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<span class=\"sqr sqr_" + (result.didPass() ? "pass" : "fail"));
4738a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("\">&#x25a0; </span>");
4748a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<span class=\"path\">" + result.getRelativePath() + "</span>");
4758a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("</a>");
4768a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
4778a6def02473ee4fbffcd1b34173daf751d316202Steve Block
4788a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (!result.didPass()) {
4798a6def02473ee4fbffcd1b34173daf751d316202Steve Block                appendTags(html, result);
4807e2a39b5985a1449588a397195c178bfef9421dbMaksymilian Osowski            }
4814a9e3a6dc3bfbc885730cfec7b2f1c147d179cc1Maksymilian Osowski
4826d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            html.append("</h3>");
48301c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            appendExpectedResultsSources(result, html);
4843c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4858a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (resultCode == AbstractResult.ResultCode.RESULTS_DIFFER) {
4868a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<div class=\"diff\" style=\"display: none;\" id=\"" + id + "\">");
4878a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(result.getDiffAsHtml());
4888a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<a href=\"#\" onClick=\"toggleDisplay('" + id + "');");
4898a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("return false;\">Hide</a>");
4908a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" | ");
4918a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("<a href=\"" + getViewSourceUrl(relativePath).toString() + "\"");
4928a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" target=\"_blank\">Show source</a>");
4938a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("</div>");
4948a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
4953c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
4966d0dae6a6534a01ee4c58d4f4ee1bf115c82319cMaksymilian Osowski            html.append("<div class=\"space\"></div>");
497fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski
498fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski            if (++mResultsSinceLastHtmlDump == RESULTS_PER_DUMP) {
499fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski                dumpHtmlToFile(html, true);
500fadb0de33d3d4b0da765e2d3f60b895016b89c4fMaksymilian Osowski            }
501394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski
502394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski            cursor.moveToNext();
503394e0fb84996f5f5ee9e33c9e2f0e11066e6f943Maksymilian Osowski        } while (!cursor.isAfterLast());
5043c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
5053c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski
5068a6def02473ee4fbffcd1b34173daf751d316202Steve Block    private void appendTags(StringBuilder html, AbstractResult result) {
5078a6def02473ee4fbffcd1b34173daf751d316202Steve Block        /** Tag tests which crash, time out or where results don't match */
5088a6def02473ee4fbffcd1b34173daf751d316202Steve Block        if (result.didCrash()) {
5098a6def02473ee4fbffcd1b34173daf751d316202Steve Block            html.append(" <span class=\"listItem crashed\">Crashed</span>");
5108a6def02473ee4fbffcd1b34173daf751d316202Steve Block        } else {
5118a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (result.didTimeOut()) {
5128a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" <span class=\"listItem timed_out\">Timed out</span>");
5138a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
5148a6def02473ee4fbffcd1b34173daf751d316202Steve Block            AbstractResult.ResultCode resultCode = result.getResultCode();
5158a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (resultCode != AbstractResult.ResultCode.RESULTS_MATCH) {
5168a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" <span class=\"listItem " + resultCode.name() + "\">");
5178a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(resultCode.toString());
5188a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("</span>");
5198a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
5208a6def02473ee4fbffcd1b34173daf751d316202Steve Block        }
5218a6def02473ee4fbffcd1b34173daf751d316202Steve Block
5228a6def02473ee4fbffcd1b34173daf751d316202Steve Block        /** Detect missing LTC function */
5238a6def02473ee4fbffcd1b34173daf751d316202Steve Block        String additionalTextOutputString = result.getAdditionalTextOutputString();
5248a6def02473ee4fbffcd1b34173daf751d316202Steve Block        if (additionalTextOutputString != null &&
5258a6def02473ee4fbffcd1b34173daf751d316202Steve Block                additionalTextOutputString.contains("com.android.dumprendertree") &&
5268a6def02473ee4fbffcd1b34173daf751d316202Steve Block                additionalTextOutputString.contains("has no method")) {
5278a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (additionalTextOutputString.contains("LayoutTestController")) {
5288a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" <span class=\"listItem noLtc\">LTC function missing</span>");
5298a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
5308a6def02473ee4fbffcd1b34173daf751d316202Steve Block            if (additionalTextOutputString.contains("EventSender")) {
5318a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append(" <span class=\"listItem noEventSender\">");
5328a6def02473ee4fbffcd1b34173daf751d316202Steve Block                html.append("ES function missing</span>");
5338a6def02473ee4fbffcd1b34173daf751d316202Steve Block            }
5343c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski        }
5353c8ccb384513dd9bae0f98ac516ea36fbaa3173bMaksymilian Osowski    }
536603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski
53701c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski    private static final void appendExpectedResultsSources(AbstractResult result,
53801c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            StringBuilder html) {
53901c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski        String textSource = result.getExpectedTextResultPath();
54001c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski        String imageSource = result.getExpectedImageResultPath();
54101c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski
54224652bc958997dc32d5c8275f2f2ce38daf6e106Steve Block        if (result.didCrash()) {
54324652bc958997dc32d5c8275f2f2ce38daf6e106Steve Block            html.append("<span class=\"source\">Did not look for expected results</span>");
54424652bc958997dc32d5c8275f2f2ce38daf6e106Steve Block            return;
54524652bc958997dc32d5c8275f2f2ce38daf6e106Steve Block        }
54624652bc958997dc32d5c8275f2f2ce38daf6e106Steve Block
547f460dd42190ada4a2c147db5127a9d7870fe0101Steve Block        if (textSource == null) {
548f460dd42190ada4a2c147db5127a9d7870fe0101Steve Block            // Show if a text result is missing. We may want to revisit this decision when we add
549f460dd42190ada4a2c147db5127a9d7870fe0101Steve Block            // support for image results.
550f460dd42190ada4a2c147db5127a9d7870fe0101Steve Block            html.append("<span class=\"source\">Expected textual result missing</span>");
551f460dd42190ada4a2c147db5127a9d7870fe0101Steve Block        } else {
55201c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append("<span class=\"source\">Expected textual result from: ");
55301c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append("<a href=\"" + ForwarderManager.getHostSchemePort(false) + "LayoutTests/" +
55401c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski                    textSource + "\"");
55501c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append(" target=\"_blank\">");
55601c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append(textSource + "</a></span>");
55701c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski        }
55801c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski        if (imageSource != null) {
55901c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append("<span class=\"source\">Expected image result from: ");
56001c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append("<a href=\"" + ForwarderManager.getHostSchemePort(false) + "LayoutTests/" +
56101c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski                    imageSource + "\"");
56201c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append(" target=\"_blank\">");
56301c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski            html.append(imageSource + "</a></span>");
56401c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski        }
56501c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski    }
56601c1f9d9e9e7ab3a40a9bf27195a434eb0c9bb9bMaksymilian Osowski
567603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski    private static final URL getViewSourceUrl(String relativePath) {
568603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski        URL url = null;
569603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski        try {
570603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski            url = new URL("http", "localhost", ForwarderManager.HTTP_PORT,
571183c3c9ca20f55703f31e3610bca72682f6355dbSteve Block                    "/Tools/DumpRenderTree/android/view_source.php?src=" +
572603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski                    relativePath);
573603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski        } catch (MalformedURLException e) {
574603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski            assert false : "relativePath=" + relativePath;
575603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski        }
576603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski        return url;
577603b70dd8b1ef8acabf71c52089c6cd5396fe931Maksymilian Osowski    }
5780e2bae14b408d001fea84c0cbdb7348c3ec611a3Steve Block}
579