diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 562b96e37b8e..33c981d657f5 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -24,7 +24,6 @@ package hudson.model; -import static hudson.util.QuotedStringTokenizer.quote; import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -1306,7 +1305,7 @@ public String getFormField() { @Override public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { if (FormApply.isApply(req)) { - FormApply.applyResponse("notificationBar.show(" + quote(getMessage()) + ",notificationBar.ERROR)") + FormApply.showNotification(getMessage(), FormApply.NotificationType.ERROR) .generateResponse(req, rsp, node); } else { // for now, we can't really use the field name that caused the problem. diff --git a/core/src/main/java/hudson/util/FormApply.java b/core/src/main/java/hudson/util/FormApply.java index 280a3051286a..9fc5f578f05d 100644 --- a/core/src/main/java/hudson/util/FormApply.java +++ b/core/src/main/java/hudson/util/FormApply.java @@ -24,8 +24,10 @@ package hudson.util; +import hudson.Functions; import jakarta.servlet.ServletException; import java.io.IOException; +import jenkins.model.Jenkins; import org.kohsuke.stapler.HttpResponses.HttpResponseException; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerRequest2; @@ -51,7 +53,7 @@ public static HttpResponseException success(final String destination) { public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { if (isApply(req)) { // if the submission is via 'apply', show a response in the notification bar - applyResponse("notificationBar.show('" + Messages.HttpResponses_Saved() + "',notificationBar.SUCCESS)") + showNotification(Messages.HttpResponses_Saved(), NotificationType.SUCCESS) .generateResponse(req, rsp, node); } else { rsp.sendRedirect(destination); @@ -69,6 +71,7 @@ public static boolean isApply(StaplerRequest2 req) { return Boolean.parseBoolean(req.getParameter("core:apply")); } + /** * @deprecated use {@link #isApply(StaplerRequest2)} */ @@ -82,7 +85,10 @@ public static boolean isApply(StaplerRequest req) { *
* When the response HTML includes a JavaScript function in a pre-determined name, that function gets executed. * This method generates such a response from JavaScript text. + * + * @deprecated use {@link #showNotification(String, NotificationType)} instead, which is CSP compatible version */ + @Deprecated public static HttpResponseException applyResponse(final String script) { return new HttpResponseException() { @Override @@ -98,4 +104,36 @@ public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object n } }; } + + /** + * Generates the response for the asynchronous background form submission (AKA the Apply button), + * that will show a notification of certain type and with provided message. + * + * @param message a message to display in the popup. Only plain text is supported. + * @param notificationType type of notification. See {@link NotificationType} for supported types. Defines the notification + * color and the icon that will be shown. + * + * @since TODO + */ + public static HttpResponseException showNotification(final String message, final NotificationType notificationType) { + return new HttpResponseException() { + @Override + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException { + rsp.setContentType("text/html;charset=UTF-8"); + rsp.getWriter().println(""); + } + }; + } + + + /** + * Corresponds to types declared in index.js + */ + public enum NotificationType { + SUCCESS, + WARNING, + ERROR + } } diff --git a/war/src/main/webapp/scripts/apply.js b/war/src/main/webapp/scripts/apply.js new file mode 100644 index 000000000000..b82153250bf6 --- /dev/null +++ b/war/src/main/webapp/scripts/apply.js @@ -0,0 +1,8 @@ +window.applyCompletionHandler = function (w) { + let scriptTagData = document.getElementById("form-apply-data-holder").dataset; + + w.notificationBar.show( + scriptTagData.message, + w.notificationBar[scriptTagData.notificationType], + ); +};