| OLD | NEW |
| 1 package main | 1 package main |
| 2 | 2 |
| 3 /* | 3 /* |
| 4 Runs the frontend portion of the fuzzer. This primarily is the webserver (see D
ESIGN.md) | 4 Runs the frontend portion of the fuzzer. This primarily is the webserver (see D
ESIGN.md) |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "encoding/base64" | 9 "encoding/base64" |
| 10 "encoding/json" | 10 "encoding/json" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 ) | 40 ) |
| 41 | 41 |
| 42 const ( | 42 const ( |
| 43 // OAUTH2_CALLBACK_PATH is callback endpoint used for the Oauth2 flow. | 43 // OAUTH2_CALLBACK_PATH is callback endpoint used for the Oauth2 flow. |
| 44 OAUTH2_CALLBACK_PATH = "/oauth2callback/" | 44 OAUTH2_CALLBACK_PATH = "/oauth2callback/" |
| 45 ) | 45 ) |
| 46 | 46 |
| 47 var ( | 47 var ( |
| 48 // indexTemplate is the main index.html page we serve. | 48 // indexTemplate is the main index.html page we serve. |
| 49 indexTemplate *template.Template = nil | 49 indexTemplate *template.Template = nil |
| 50 » // detailsTemplate is used for /category/foo, which displays the number
of | 50 » // detailsTemplate is used for /category, which displays the count of fu
zzes in various files |
| 51 » // fuzzes by file/function/line | 51 » // as well as the stacktraces. |
| 52 » overviewTemplate *template.Template = nil | |
| 53 » // detailsTemplate is used for /details, which displays the information
from | |
| 54 » // overview as well as the stacktraces and fuzzes. | |
| 55 detailsTemplate *template.Template = nil | 52 detailsTemplate *template.Template = nil |
| 56 | 53 |
| 57 storageClient *storage.Client = nil | 54 storageClient *storage.Client = nil |
| 58 | 55 |
| 59 versionWatcher *fcommon.VersionWatcher = nil | 56 versionWatcher *fcommon.VersionWatcher = nil |
| 60 | 57 |
| 61 fuzzSyncer *syncer.FuzzSyncer = nil | 58 fuzzSyncer *syncer.FuzzSyncer = nil |
| 62 ) | 59 ) |
| 63 | 60 |
| 64 var ( | 61 var ( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 91 | 88 |
| 92 func Init() { | 89 func Init() { |
| 93 reloadTemplates() | 90 reloadTemplates() |
| 94 } | 91 } |
| 95 | 92 |
| 96 func reloadTemplates() { | 93 func reloadTemplates() { |
| 97 indexTemplate = template.Must(template.ParseFiles( | 94 indexTemplate = template.Must(template.ParseFiles( |
| 98 filepath.Join(*resourcesDir, "templates/index.html"), | 95 filepath.Join(*resourcesDir, "templates/index.html"), |
| 99 filepath.Join(*resourcesDir, "templates/header.html"), | 96 filepath.Join(*resourcesDir, "templates/header.html"), |
| 100 )) | 97 )) |
| 101 overviewTemplate = template.Must(template.ParseFiles( | |
| 102 filepath.Join(*resourcesDir, "templates/overview.html"), | |
| 103 filepath.Join(*resourcesDir, "templates/header.html"), | |
| 104 )) | |
| 105 detailsTemplate = template.New("details.html") | 98 detailsTemplate = template.New("details.html") |
| 106 // Allows this template to have Polymer binding in it and go template ma
rkup. The go templates | 99 // Allows this template to have Polymer binding in it and go template ma
rkup. The go templates |
| 107 // have been changed to be {%.Thing%} instead of {{.Thing}} | 100 // have been changed to be {%.Thing%} instead of {{.Thing}} |
| 108 detailsTemplate.Delims("{%", "%}") | 101 detailsTemplate.Delims("{%", "%}") |
| 109 detailsTemplate = template.Must(detailsTemplate.ParseFiles( | 102 detailsTemplate = template.Must(detailsTemplate.ParseFiles( |
| 110 filepath.Join(*resourcesDir, "templates/details.html"), | 103 filepath.Join(*resourcesDir, "templates/details.html"), |
| 111 filepath.Join(*resourcesDir, "templates/header.html"), | 104 filepath.Join(*resourcesDir, "templates/header.html"), |
| 112 )) | 105 )) |
| 113 } | 106 } |
| 114 | 107 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 r.HandleFunc("/category/{category:[a-z_]+}/file/{file}/func/{function}",
detailsPageHandler) | 213 r.HandleFunc("/category/{category:[a-z_]+}/file/{file}/func/{function}",
detailsPageHandler) |
| 221 r.HandleFunc(`/category/{category:[a-z_]+}/file/{file}/func/{function}/l
ine/{line}`, detailsPageHandler) | 214 r.HandleFunc(`/category/{category:[a-z_]+}/file/{file}/func/{function}/l
ine/{line}`, detailsPageHandler) |
| 222 r.HandleFunc("/loginstatus/", login.StatusHandler) | 215 r.HandleFunc("/loginstatus/", login.StatusHandler) |
| 223 r.HandleFunc("/logout/", login.LogoutHandler) | 216 r.HandleFunc("/logout/", login.LogoutHandler) |
| 224 r.HandleFunc("/json/version", skiaversion.JsonHandler) | 217 r.HandleFunc("/json/version", skiaversion.JsonHandler) |
| 225 r.HandleFunc("/json/fuzz-summary", summaryJSONHandler) | 218 r.HandleFunc("/json/fuzz-summary", summaryJSONHandler) |
| 226 r.HandleFunc("/json/details", detailsJSONHandler) | 219 r.HandleFunc("/json/details", detailsJSONHandler) |
| 227 r.HandleFunc("/json/status", statusJSONHandler) | 220 r.HandleFunc("/json/status", statusJSONHandler) |
| 228 r.HandleFunc(`/fuzz/{category:[a-z_]+}/{name:[0-9a-f]+}`, fuzzHandler) | 221 r.HandleFunc(`/fuzz/{category:[a-z_]+}/{name:[0-9a-f]+}`, fuzzHandler) |
| 229 r.HandleFunc(`/metadata/{category:[a-z_]+}/{name:[0-9a-f]+_(debug|releas
e)\.(err|dump|asan)}`, metadataHandler) | 222 r.HandleFunc(`/metadata/{category:[a-z_]+}/{name:[0-9a-f]+_(debug|releas
e)\.(err|dump|asan)}`, metadataHandler) |
| 230 r.HandleFunc("/fuzz_count", fuzzCountHandler) | |
| 231 r.HandleFunc("/newBug", newBugHandler) | 223 r.HandleFunc("/newBug", newBugHandler) |
| 232 | 224 |
| 233 rootHandler := login.ForceAuth(util.LoggingGzipRequestResponse(r), OAUTH
2_CALLBACK_PATH) | 225 rootHandler := login.ForceAuth(util.LoggingGzipRequestResponse(r), OAUTH
2_CALLBACK_PATH) |
| 234 | 226 |
| 235 http.Handle("/", rootHandler) | 227 http.Handle("/", rootHandler) |
| 236 glog.Infof("Ready to serve on %s", serverURL) | 228 glog.Infof("Ready to serve on %s", serverURL) |
| 237 glog.Fatal(http.ListenAndServe(*port, nil)) | 229 glog.Fatal(http.ListenAndServe(*port, nil)) |
| 238 } | 230 } |
| 239 | 231 |
| 240 func indexHandler(w http.ResponseWriter, r *http.Request) { | 232 func indexHandler(w http.ResponseWriter, r *http.Request) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 258 Category string | 250 Category string |
| 259 }{ | 251 }{ |
| 260 Category: mux.Vars(r)["category"], | 252 Category: mux.Vars(r)["category"], |
| 261 } | 253 } |
| 262 | 254 |
| 263 if err := detailsTemplate.Execute(w, cat); err != nil { | 255 if err := detailsTemplate.Execute(w, cat); err != nil { |
| 264 glog.Errorf("Failed to expand template: %v", err) | 256 glog.Errorf("Failed to expand template: %v", err) |
| 265 } | 257 } |
| 266 } | 258 } |
| 267 | 259 |
| 268 func summaryPageHandler(w http.ResponseWriter, r *http.Request) { | |
| 269 if *local { | |
| 270 reloadTemplates() | |
| 271 } | |
| 272 w.Header().Set("Content-Type", "text/html") | |
| 273 | |
| 274 var cat = struct { | |
| 275 Category string | |
| 276 }{ | |
| 277 Category: mux.Vars(r)["category"], | |
| 278 } | |
| 279 | |
| 280 if err := overviewTemplate.Execute(w, cat); err != nil { | |
| 281 glog.Errorf("Failed to expand template: %v", err) | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 type countSummary struct { | 260 type countSummary struct { |
| 286 Category string `json:"category"` | 261 Category string `json:"category"` |
| 287 CategoryDisplay string `json:"categoryDisplay"` | 262 CategoryDisplay string `json:"categoryDisplay"` |
| 288 TotalBad int `json:"totalBadCount"` | 263 TotalBad int `json:"totalBadCount"` |
| 289 TotalGrey int `json:"totalGreyCount"` | 264 TotalGrey int `json:"totalGreyCount"` |
| 290 // "This" means "newly introduced/fixed in this revision" | 265 // "This" means "newly introduced/fixed in this revision" |
| 291 ThisBad int `json:"thisBadCount"` | 266 ThisBad int `json:"thisBadCount"` |
| 292 ThisGrey int `json:"thisGreyCount"` | 267 ThisGrey int `json:"thisGreyCount"` |
| 293 } | 268 } |
| 294 | 269 |
| 295 func summaryJSONHandler(w http.ResponseWriter, r *http.Request) { | 270 func summaryJSONHandler(w http.ResponseWriter, r *http.Request) { |
| 296 » var overview interface{} | 271 » summary := getSummary() |
| 297 » if cat := r.FormValue("category"); cat != "" { | |
| 298 » » overview = data.CategoryOverview(cat) | |
| 299 » } else { | |
| 300 » » overview = getOverview() | |
| 301 » } | |
| 302 | 272 |
| 303 » if err := json.NewEncoder(w).Encode(overview); err != nil { | 273 » if err := json.NewEncoder(w).Encode(summary); err != nil { |
| 304 glog.Errorf("Failed to write or encode output: %v", err) | 274 glog.Errorf("Failed to write or encode output: %v", err) |
| 305 return | 275 return |
| 306 } | 276 } |
| 307 } | 277 } |
| 308 | 278 |
| 309 func getOverview() []countSummary { | 279 func getSummary() []countSummary { |
| 310 » overviews := make([]countSummary, 0, len(fcommon.FUZZ_CATEGORIES)) | 280 » counts := make([]countSummary, 0, len(fcommon.FUZZ_CATEGORIES)) |
| 311 for _, cat := range fcommon.FUZZ_CATEGORIES { | 281 for _, cat := range fcommon.FUZZ_CATEGORIES { |
| 312 o := countSummary{ | 282 o := countSummary{ |
| 313 CategoryDisplay: fcommon.PrettifyCategory(cat), | 283 CategoryDisplay: fcommon.PrettifyCategory(cat), |
| 314 Category: cat, | 284 Category: cat, |
| 315 } | 285 } |
| 316 c := syncer.FuzzCount{ | 286 c := syncer.FuzzCount{ |
| 317 TotalBad: -1, | 287 TotalBad: -1, |
| 318 TotalGrey: -1, | 288 TotalGrey: -1, |
| 319 ThisBad: -1, | 289 ThisBad: -1, |
| 320 ThisGrey: -1, | 290 ThisGrey: -1, |
| 321 } | 291 } |
| 322 if fuzzSyncer != nil { | 292 if fuzzSyncer != nil { |
| 323 c = fuzzSyncer.LastCount(cat) | 293 c = fuzzSyncer.LastCount(cat) |
| 324 } | 294 } |
| 325 o.TotalBad = c.TotalBad | 295 o.TotalBad = c.TotalBad |
| 326 o.ThisBad = c.ThisBad | 296 o.ThisBad = c.ThisBad |
| 327 o.TotalGrey = c.TotalGrey | 297 o.TotalGrey = c.TotalGrey |
| 328 o.ThisGrey = c.ThisGrey | 298 o.ThisGrey = c.ThisGrey |
| 329 » » overviews = append(overviews, o) | 299 » » counts = append(counts, o) |
| 330 } | 300 } |
| 331 » return overviews | 301 » return counts |
| 332 } | 302 } |
| 333 | 303 |
| 334 func detailsJSONHandler(w http.ResponseWriter, r *http.Request) { | 304 func detailsJSONHandler(w http.ResponseWriter, r *http.Request) { |
| 335 w.Header().Set("Content-Type", "application/json") | 305 w.Header().Set("Content-Type", "application/json") |
| 336 | 306 |
| 337 category := r.FormValue("category") | 307 category := r.FormValue("category") |
| 338 name := r.FormValue("name") | 308 name := r.FormValue("name") |
| 339 // The file names have "/" in them and the functions can have "(*&" in t
hem. | 309 // The file names have "/" in them and the functions can have "(*&" in t
hem. |
| 340 // We base64 encode them to prevent problems. | 310 // We base64 encode them to prevent problems. |
| 341 file, err := decodeBase64(r.FormValue("file")) | 311 file, err := decodeBase64(r.FormValue("file")) |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 } | 437 } |
| 468 } | 438 } |
| 469 } | 439 } |
| 470 | 440 |
| 471 if err := json.NewEncoder(w).Encode(s); err != nil { | 441 if err := json.NewEncoder(w).Encode(s); err != nil { |
| 472 glog.Errorf("Failed to write or encode output: %s", err) | 442 glog.Errorf("Failed to write or encode output: %s", err) |
| 473 return | 443 return |
| 474 } | 444 } |
| 475 } | 445 } |
| 476 | 446 |
| 477 func fuzzCountHandler(w http.ResponseWriter, r *http.Request) { | |
| 478 c := syncer.FuzzCount{ | |
| 479 TotalBad: -1, | |
| 480 TotalGrey: -1, | |
| 481 ThisBad: -1, | |
| 482 ThisGrey: -1, | |
| 483 } | |
| 484 if fuzzSyncer != nil { | |
| 485 c = fuzzSyncer.LastCount(r.FormValue("category")) | |
| 486 } | |
| 487 if err := json.NewEncoder(w).Encode(c); err != nil { | |
| 488 glog.Errorf("Failed to write or encode output: %s", err) | |
| 489 return | |
| 490 } | |
| 491 } | |
| 492 | |
| 493 type newBug struct { | 447 type newBug struct { |
| 494 Category string | 448 Category string |
| 495 PrettyCategory string | 449 PrettyCategory string |
| 496 Name string | 450 Name string |
| 497 Revision string | 451 Revision string |
| 498 } | 452 } |
| 499 | 453 |
| 500 var newBugTemplate = template.Must(template.New("new_bug").Parse(`# Your bug des
cription here about fuzz found in {{.PrettyCategory}} | 454 var newBugTemplate = template.Must(template.New("new_bug").Parse(`# Your bug des
cription here about fuzz found in {{.PrettyCategory}} |
| 501 | 455 |
| 502 # tracking metadata below: | 456 # tracking metadata below: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 522 } | 476 } |
| 523 var t bytes.Buffer | 477 var t bytes.Buffer |
| 524 if err := newBugTemplate.Execute(&t, b); err != nil { | 478 if err := newBugTemplate.Execute(&t, b); err != nil { |
| 525 util.ReportError(w, r, err, fmt.Sprintf("Could not create templa
te with %#v", b)) | 479 util.ReportError(w, r, err, fmt.Sprintf("Could not create templa
te with %#v", b)) |
| 526 return | 480 return |
| 527 } | 481 } |
| 528 q.Add("comment", t.String()) | 482 q.Add("comment", t.String()) |
| 529 // 303 means "make a GET request to this url" | 483 // 303 means "make a GET request to this url" |
| 530 http.Redirect(w, r, "https://bugs.chromium.org/p/skia/issues/entry?"+q.E
ncode(), 303) | 484 http.Redirect(w, r, "https://bugs.chromium.org/p/skia/issues/entry?"+q.E
ncode(), 303) |
| 531 } | 485 } |
| OLD | NEW |