diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-11-07 16:01:04 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-11-08 14:15:20 +0000 |
| commit | 9c60c31484778260e7eb20d563c33554cf39e8fd (patch) | |
| tree | ccf4d8082a8d543bb1d3c884245dad72b66447a3 /pkg | |
| parent | 63bef6c39574466284f629bde4aedc7649179c26 (diff) | |
pkg/manager: add common HTML page header
Add common HTML page header to every page.
The header contains common tabs, and expert mode switch.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/html/pages/style.css | 15 | ||||
| -rw-r--r-- | pkg/manager/http.go | 134 |
2 files changed, 113 insertions, 36 deletions
diff --git a/pkg/html/pages/style.css b/pkg/html/pages/style.css index b0afa3126..5da7359e6 100644 --- a/pkg/html/pages/style.css +++ b/pkg/html/pages/style.css @@ -84,6 +84,21 @@ table td, table th { padding-left: 20px; } +.action_button, .action_button_selected { + border: 1px solid black; + align: left; + vertical-align: center; + text-align: center; + width: 30px; + height: 30px; + padding: 4px; + margin: 5px; +} + +.action_button_selected { + border: 3px solid black; +} + .position_table .search { text-align: right; } diff --git a/pkg/manager/http.go b/pkg/manager/http.go index f057c9795..06fa9ca2b 100644 --- a/pkg/manager/http.go +++ b/pkg/manager/http.go @@ -72,8 +72,8 @@ func (serv *HTTPServer) Serve() { http.Handle(pattern, handlers.CompressHandler(http.HandlerFunc(handler))) } handle("/", serv.httpSummary) + handle("/action", serv.httpAction) handle("/config", serv.httpConfig) - handle("/expert_mode", serv.httpExpertMode) handle("/stats", serv.httpStats) handle("/vms", serv.httpVMs) handle("/vm", serv.httpVM) @@ -109,6 +109,14 @@ func (serv *HTTPServer) Serve() { } } +func (serv *HTTPServer) httpAction(w http.ResponseWriter, r *http.Request) { + switch r.FormValue("action") { + case "toggle-expert": + serv.expertMode = !serv.expertMode + } + http.Redirect(w, r, r.FormValue("url"), http.StatusFound) +} + func (serv *HTTPServer) httpSummary(w http.ResponseWriter, r *http.Request) { data := &UISummaryData{ UIPageHeader: serv.pageHeader(r, "syzkaller"), @@ -141,18 +149,29 @@ func (serv *HTTPServer) httpSummary(w http.ResponseWriter, r *http.Request) { } func (serv *HTTPServer) httpConfig(w http.ResponseWriter, r *http.Request) { - data, err := json.MarshalIndent(serv.Cfg, "", "\t") + serv.jsonPage(w, r, "config", serv.Cfg) +} + +func (serv *HTTPServer) jsonPage(w http.ResponseWriter, r *http.Request, title string, data any) { + text, err := json.MarshalIndent(data, "", "\t") if err != nil { - http.Error(w, fmt.Sprintf("failed to encode json: %v", err), - http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("failed to encode json: %v", err), http.StatusInternalServerError) return } - w.Write(data) + serv.textPage(w, r, title, text) } -func (serv *HTTPServer) httpExpertMode(w http.ResponseWriter, r *http.Request) { - serv.expertMode = !serv.expertMode - http.Redirect(w, r, "/", http.StatusFound) +func (serv *HTTPServer) textPage(w http.ResponseWriter, r *http.Request, title string, text []byte) { + if r.FormValue("raw") != "" { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Write(text) + return + } + data := &UITextPage{ + UIPageHeader: serv.pageHeader(r, title), + Text: text, + } + executeTemplate(w, textTemplate, data) } func (serv *HTTPServer) httpSyscalls(w http.ResponseWriter, r *http.Request) { @@ -592,15 +611,12 @@ func (serv *HTTPServer) httpFile(w http.ResponseWriter, r *http.Request) { http.Error(w, "oh, oh, oh!", http.StatusInternalServerError) return } - file = filepath.Join(serv.Cfg.Workdir, file) - f, err := os.Open(file) + data, err := os.ReadFile(filepath.Join(serv.Cfg.Workdir, file)) if err != nil { - http.Error(w, "failed to open the file", http.StatusInternalServerError) + http.Error(w, "failed to read the file", http.StatusInternalServerError) return } - defer f.Close() - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - io.Copy(w, f) + serv.textPage(w, r, "file", data) } func (serv *HTTPServer) httpInput(w http.ResponseWriter, r *http.Request) { @@ -666,20 +682,12 @@ func (serv *HTTPServer) httpDebugInput(w http.ResponseWriter, r *http.Request) { } func (serv *HTTPServer) modulesInfo(w http.ResponseWriter, r *http.Request) { - var modules []*vminfo.KernelModule - if obj := serv.Cover.Load(); obj != nil { - modules = obj.Modules - } else { + cover := serv.Cover.Load() + if cover == nil { http.Error(w, "info is not ready, please try again later after fuzzer started", http.StatusInternalServerError) return } - jsonModules, err := json.MarshalIndent(modules, "", "\t") - if err != nil { - fmt.Fprintf(w, "unable to create JSON modules info: %v", err) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(jsonModules) + serv.jsonPage(w, r, "modules", cover.Modules) } var alphaNumRegExp = regexp.MustCompile(`^[a-zA-Z0-9]*$`) @@ -943,8 +951,12 @@ type UIInput struct { } type UIPageHeader struct { - PageTitle string - InstanceName string + PageTitle string + // Relative page URL w/o GET parameters (e.g. "/stats"). + URLPath string + // Relative page URL with GET parameters/fragment/etc (e.g. "/stats?foo=1#bar"). + CurrentURL string + // syzkaller build git revision and link. GitRevision string GitRevisionLink string ExpertMode bool @@ -956,9 +968,14 @@ func (serv *HTTPServer) pageHeader(r *http.Request, title string) UIPageHeader { revisionLink = vcs.LogLink(vcs.SyzkallerRepo, revision) revision = revision[:8] } + url := r.URL + url.Scheme = "" + url.Host = "" + url.User = nil return UIPageHeader{ PageTitle: title, - InstanceName: serv.Cfg.Name, + URLPath: r.URL.Path, + CurrentURL: url.String(), GitRevision: revision, GitRevisionLink: revisionLink, ExpertMode: serv.expertMode, @@ -974,7 +991,50 @@ func createPage(data any, body string) *template.Template { {{HEAD}} </head> <body> -%v + <header id="topbar"> + <table class="position_table"> + <tr> + <td> + <h1><a href="/">syzkaller</a></h1> + </td> + <td> + <form action="/action" method="post"> + <input type="hidden" name="url" value="{{.CurrentURL}}" /> + <button type="submit" name="action" value="toggle-expert" class="action_button{{if .ExpertMode}}_selected{{end}}" title="Toggle expert mode"> + π§ + </input> + </form> + </td> + <td class="search"> + <a href="https://github.com/google/syzkaller/blob/master/docs/" target="_blank">docs</a> | + <a href="https://groups.google.com/forum/#!forum/syzkaller" target="_blank">mailing list</a> | + <a href="{{.GitRevisionLink}}" target="_blank">source {{.GitRevision}}</a> + </td> + </tr> + </table> + <div class="navigation"> + <div class="navigation_tab{{if eq .URLPath "/stats"}}_selected{{end}}"> + <a href='/stats'>π stats</a> + </div> + <div class="navigation_tab{{if eq .URLPath "/cover"}}_selected{{end}}"> + <a href='/cover'>π coverage</a> + </div> + <div class="navigation_tab{{if eq .URLPath "/syscalls"}}_selected{{end}}"> + <a href='/syscalls'>π€ syscalls</a> + </div> + <div class="navigation_tab{{if eq .URLPath "/corpus"}}_selected{{end}}"> + <a href='/corpus'>π corpus</a> + </div> + <div class="navigation_tab{{if eq .URLPath "/vms"}}_selected{{end}}"> + <a href='/vms'>π» VMs</a> + </div> + <div class="navigation_tab{{if eq .URLPath "/config"}}_selected{{end}}"> + <a href='/config'>π§ config</a> + </div> + </div> + </header> + <br> + %v </body></html> `, body)) templTypes = append(templTypes, templType{ @@ -992,14 +1052,7 @@ type templType struct { var templTypes []templType var summaryTemplate = createPage(UISummaryData{}, ` -<b>{{.InstanceName }} syzkaller</b> -<a href='/config'>[config]</a> -<a href='{{.GitRevisionLink}}'>{{.GitRevision}}</a> -<a class="navigation_tab" href='expert_mode'>{{if .ExpertMode}}disable{{else}}enable{{end}} expert mode</a> -<br> - <table class="list_table"> - <caption><a href='/stats'>Stats π</a></caption> {{range $s := $.Stats}} <tr> <td class="stat_name" title="{{$s.Hint}}">{{$s.Name}}</td> @@ -1319,3 +1372,12 @@ var jobListTemplate = createPage(UIJobList{}, ` {{end}} </table> `) + +type UITextPage struct { + UIPageHeader + Text []byte +} + +var textTemplate = createPage(UITextPage{}, ` +<pre>{{printf "%s" .Text}}</pre> +`) |
