@@ -166,7 +166,7 @@ function setAttributes(el, attrs) {
166166 attrs = attrs || { }
167167 for ( var attr in attrs ) {
168168 if ( attr !== 'src' )
169- el . setAttribute ( attr , attrs [ attr ] ) ;
169+ el . setAttribute ( attr . toLowerCase ( ) , attrs [ attr ] ) ;
170170 }
171171 // Workaround for Chromium: set <img>'s src attribute after all other
172172 // attributes to ensure the policy is applied.
@@ -826,6 +826,54 @@ function requestViaWebSocket(url) {
826826 } ) ;
827827}
828828
829+ /**
830+ * Creates a svg anchor element and the corresponding svg setup, appends the
831+ * setup to {@code document.body} and performs the navigation.
832+ * @param {string } url The URL to navigate to.
833+ * @return {Promise } The promise for success/error events.
834+ */
835+ function requestViaSVGAnchor ( url , additionalAttributes ) {
836+ const name = guid ( ) ;
837+
838+ const iframe =
839+ createElement ( "iframe" , { "name" : name , "id" : name } , document . body , false ) ;
840+
841+ // Create SVG container
842+ const svg = document . createElementNS ( "http://www.w3.org/2000/svg" , "svg" ) ;
843+
844+ // Create SVG anchor element
845+ const svgAnchor = document . createElementNS ( "http://www.w3.org/2000/svg" , "a" ) ;
846+ const link_attributes = Object . assign ( { "href" : url , "target" : name } , additionalAttributes ) ;
847+ setAttributes ( svgAnchor , link_attributes ) ;
848+
849+ // Add some text content for the anchor
850+ const text = document . createElementNS ( "http://www.w3.org/2000/svg" , "text" ) ;
851+ text . setAttribute ( "y" , "50" ) ;
852+ text . textContent = "SVG Link to resource" ;
853+
854+ svgAnchor . appendChild ( text ) ;
855+ svg . appendChild ( svgAnchor ) ;
856+ document . body . appendChild ( svg ) ;
857+
858+ const promise =
859+ bindEvents2 ( window , "message" , iframe , "error" , window , "error" )
860+ . then ( event => {
861+ if ( event . source !== iframe . contentWindow )
862+ return Promise . reject ( new Error ( 'Unexpected event.source' ) ) ;
863+ return event . data ;
864+ } ) ;
865+
866+ // Simulate a click event on the SVG anchor
867+ const event = new MouseEvent ( 'click' , {
868+ view : window ,
869+ bubbles : true ,
870+ cancelable : true
871+ } ) ;
872+ svgAnchor . dispatchEvent ( event ) ;
873+
874+ return promise ;
875+ }
876+
829877/**
830878 @typedef SubresourceType
831879 @type {string }
@@ -892,6 +940,10 @@ const subresourceMap = {
892940 path : "/common/security-features/subresource/script.py" ,
893941 invoker : requestViaDynamicImport ,
894942 } ,
943+ "svg-a-tag" : {
944+ path : "/common/security-features/subresource/document.py" ,
945+ invoker : requestViaSVGAnchor ,
946+ } ,
895947 "video-tag" : {
896948 path : "/common/security-features/subresource/video.py" ,
897949 invoker : requestViaVideo ,
0 commit comments