9a83298f18860ef6d05232bf7e10f2df3c1c2b1d
braney
  Sat Aug 22 10:26:22 2026 -0700
hgc: route inline javascript through the standard helpers

Three places in hgc wrote script markup by hand instead of using the
helpers the rest of the tree uses.

printIframe now emits its script block the way hgIntegrator does. The
wiki track create-item form builds its function with jsInlineF, so the
function lands in the same block as the handler that calls it.
showSomePartialDnaAlignment sets the body frame's start position through
the frame URL, which is how the sibling index links already address that
frame, and matches showSomeAlignment just above it.

No change to what any of the three pages contain.

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index 07969fcd50e..9ac00223254 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -950,40 +950,44 @@
 char *iframeOptions = trackDbSettingOrDefault(tdb, "iframeOptions", "width='100%%' height='1024'");
 // Resizing requires the hgcDetails pages to include a bit of javascript.
 //
 // Explanation how this works and why the javascript is needed:
 // http://stackoverflow.com/questions/153152/resizing-an-iframe-based-on-content
 // In short:
 // - iframes have a fixed size in html, resizing can only be done in javascript
 // - the iframed page cannot call the resize() function in the hgc html directly, as they have
 //   been loaded from different webservers
 // - one way around it is that the iframed page includes a helper page on our server and 
 //   send their size to the helper page (pages can call functions of included pages)
 // - the helper page then sends the size back to hgc (pages on the same server can
 //   call each others' functions)
 //   width='%s' height='%s' src='%s' seamless scrolling='%s' frameborder='%s'
 
+// The nonce is required: our CSP puts a nonce in script-src, which makes
+// browsers ignore 'unsafe-inline', so an un-nonced inline script never runs.
+// The script stays here, ahead of the iframe, so resizeIframe is defined
+// before the iframed page loads and calls it.
 printf(" \
-<script> \
+<script nonce='%s'> \
 function resizeIframe(height) \
 { \
      document.getElementById('hgcIframe').height = parseInt(height)+10; \
 } \
 </script> \
  \
 <iframe id='hgcIframe' src='%s' %s></iframe> \
-<p>", eUrl, iframeOptions);
+<p>", getNonce(), eUrl, iframeOptions);
 }
 
 void printCustomUrlWithLabel(struct trackDb *tdb, char *itemName, char *itemLabel, 
                                 char *urlSetting, boolean encode, struct slPair *fields)
 /* Print custom URL specified in trackDb settings. */
 {
 char urlLabelSetting[32];
 
 // replace the $$ and other wildchards with the url given in tdb 
 char *url = getUrlSetting(tdb, urlSetting);
 //char* eUrl = constructUrl(tdb, url, itemName, encode);
 if (url==NULL || isEmpty(url))
     return;
 
 char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, 
@@ -8476,37 +8480,38 @@
 fprintf(index, "<A HREF=\"../%s#cDNA\" TARGET=\"body\">%s</A><BR>\n", bodyTn.forCgi, qName);
 if (partPsl != wholePsl)
     fprintf(index, "<A HREF=\"../%s#cDNAStart\" TARGET=\"body\">%s in browser window</A><BR>\n", bodyTn.forCgi, qName);
 fprintf(index, "<A HREF=\"../%s#genomic\" TARGET=\"body\">%s.%s</A><BR>\n", bodyTn.forCgi, hOrganism(database), partPsl->tName);
 for (i=1; i<=blockCount; ++i)
     {
     fprintf(index, "<A HREF=\"../%s#%d\" TARGET=\"body\">block%d</A><BR>\n",
 	    bodyTn.forCgi, i, i);
     }
 fprintf(index, "<A HREF=\"../%s#ali\" TARGET=\"body\">together</A><BR>\n", bodyTn.forCgi);
 htmEnd(index);
 fclose(index);
 chmod(indexTn.forCgi, 0666);
 
 /* Write (to stdout) the main html page containing just the frame info. */
-if (partPsl != wholePsl)
-    printf("<FRAMESET COLS = \"13%%,87%% \" "
-	   "ONLOAD=\"body.location.href = '%s#cDNAStart';\">\n",
-	   bodyTn.forCgi);
-else
 puts("<FRAMESET COLS = \"13%,87% \" >");
 printf("  <FRAME SRC=\"%s\" NAME=\"index\">\n", indexTn.forCgi);
+// Start the body frame at the #cDNAStart anchor.  This used to be an ONLOAD
+// attribute on the FRAMESET, but our CSP puts a nonce in script-src, so
+// browsers ignore 'unsafe-inline' and never run an inline event handler.
+if (partPsl != wholePsl)
+    printf("  <FRAME SRC=\"%s#cDNAStart\" NAME=\"body\">\n", bodyTn.forCgi);
+else
     printf("  <FRAME SRC=\"%s\" NAME=\"body\">\n", bodyTn.forCgi);
 puts("<NOFRAMES><BODY></BODY></NOFRAMES>");
 puts("</FRAMESET>");
 puts("</HTML>\n");
 exit(0);	/* Avoid cartHtmlEnd. */
 }
 
 static void getCdsStartAndStop(struct sqlConnection *conn, char *acc, char *trackTable,
 			       uint *retCdsStart, uint *retCdsEnd)
 /* Get cds start and stop, if available */
 {
 struct trackDb *tdb = hashFindVal(trackHash, trackTable);
 // Note: this variable was previously named cdsTable but unfortunately the
 // hg/(inc|lib)/genbank.[hc] code uses the global var cdsTable!
 char *tdbCdsTable = tdb ? trackDbSetting(tdb, "cdsTable") : NULL;