-
-
Save riccardobl/18603f9de508b1ab6c9e to your computer and use it in GitHub Desktop.
/** | |
* @author Riccardo Balbo | |
* @description This patch aims to make the WebView capable to correctly render transparent pages. | |
* @license | |
* Copyright (c) 2015 Riccardo Balbo < riccardo @ forkforge . net > | |
* | |
* This software is provided 'as-is', without any express or implied | |
* warranty. In no event will the authors be held liable for any | |
* damages arising from the use of this software. | |
* | |
* Permission is granted to anyone to use this software for any | |
* purpose, including commercial applications, and to alter it and | |
* redistribute it freely, subject to the following restrictions: | |
* | |
* 1. The origin of this software must not be misrepresented; you must | |
* not claim that you wrote the original software. If you use this | |
* software in a product, an acknowledgment in the product | |
* documentation would be appreciated but is not required. | |
* | |
* 2. Altered source versions must be plainly marked as such, and must | |
* not be misrepresented as being the original software. | |
* | |
* 3. This notice may not be removed or altered from any source | |
* distribution. | |
*/ | |
import java.io.ByteArrayInputStream; | |
import java.lang.instrument.ClassFileTransformer; | |
import java.lang.instrument.IllegalClassFormatException; | |
import java.security.ProtectionDomain; | |
import java.lang.instrument.Instrumentation; | |
import javassist.ClassPool; | |
import javassist.CtClass; | |
import javassist.CtMethod; | |
public class TransparentWebViewPatch implements ClassFileTransformer{ | |
private final ClassPool _CLASS_POOL=ClassPool.getDefault(); | |
public static void premain(String agentArguments,Instrumentation instrumentation){ | |
instrumentation.addTransformer(new TransparentWebViewPatch()); | |
} | |
// This patch aims to make the WebView capable to correctly render | |
// transparent pages. | |
@Override | |
public byte[] transform(ClassLoader loader, String class_name, Class<?> class_being_redefined, ProtectionDomain protection_domain, byte[] byte_code) throws IllegalClassFormatException { | |
if(class_name.equals("com/sun/webkit/WebPage")){ | |
System.out.println("> Patching "+class_name+" ..."); | |
try{ | |
CtClass ct_class=_CLASS_POOL.makeClass(new ByteArrayInputStream(byte_code)); | |
// First thing to do is edit the fireLoadEvent in order to force | |
// the page to set its own | |
// background to transparent black (0x00000000 argb) each time | |
// it changes | |
CtMethod fireLoadEvent_method=ct_class.getDeclaredMethod("fireLoadEvent"); | |
fireLoadEvent_method.insertBefore("{\n"+" " | |
+ "setBackgroundColor(0);\n" | |
+"}"); | |
// DEPRECATED CODE: NOT WORKING FROM JAVA 1.8.0_66 | |
// Then, we edit the the paint2GC method in order to call | |
// clearRect every time right before it | |
// start to draw a clip (clips are parts of the rendered frame). | |
// We need this because when the webpage is rendered with the | |
// backbuffer enabled, | |
// every clip is just drawn over the old rendered frame without | |
// care about the alpha channel. | |
// NOTE: there is a system property | |
// com.sun.webkit.pagebackbuffer that could do the trick without | |
// this entire patch, but i didn't succeed in getting anything | |
// useful out of it... | |
// CtMethod | |
// paint2GC_method=ct_class.getDeclaredMethod("paint2GC"); | |
// paint2GC_method.insertAt(696, | |
// "{\n" + | |
// " com.sun.webkit.graphics.WCRectangle clip=$1.getClip(); \n" | |
// + | |
// " | |
// $1.clearRect(clip.getX(),clip.getY(),clip.getWidth(),clip.getHeight());\n" | |
// + | |
// "}" | |
// ); | |
// END OF DEPRECATED CODE | |
// Then we replace the scroll method body in order to force the | |
// repaint of the entire frame | |
// when the page is scrolled | |
CtMethod scroll_method=ct_class.getDeclaredMethod("scroll"); | |
scroll_method.setBody( | |
"{\n"+" " | |
+ "addDirtyRect(new com.sun.webkit.graphics.WCRectangle(0f,0f,(float)width,(float)height));\n" | |
+"}" | |
); | |
byte_code=ct_class.toBytecode(); | |
ct_class.detach(); | |
}catch(Exception e){ | |
System.out.println("/!\\ "+class_name+" patching failed :("); | |
e.printStackTrace(); | |
return byte_code; | |
} | |
System.out.println("> "+class_name+" patching succeeded!"); | |
}else if(class_name.equals("com/sun/javafx/webkit/prism/WCGraphicsPrismContext")){ | |
System.out.println("> Patching "+class_name+" ..."); | |
try{ | |
CtClass ct_class=_CLASS_POOL.makeClass(new ByteArrayInputStream(byte_code)); | |
// Then, we edit the the WCGraphicsPrismContext.setClip method | |
// in order to call clearRect over the area of the clip. | |
CtClass signature[]=new CtClass[]{_CLASS_POOL.get("com.sun.webkit.graphics.WCRectangle")}; | |
CtMethod setClip_method=ct_class.getDeclaredMethod("setClip",signature); | |
setClip_method.insertBefore( | |
"{"+" " | |
+ " $0.clearRect($1.getX(),$1.getY(),$1.getWidth(),$1.getHeight());" | |
+"}"); | |
byte_code=ct_class.toBytecode(); | |
ct_class.detach(); | |
}catch(Exception e){ | |
System.out.println("/!\\ "+class_name+" patching failed :("); | |
e.printStackTrace(); | |
return byte_code; | |
} | |
System.out.println("> "+class_name+" patching succeeded!"); | |
} | |
return byte_code; | |
} | |
} |
origin_dir=$PWD | |
rm -R build | |
mkdir build | |
rm -R /tmp/buildTransparentWebViewPatch | |
mkdir /tmp/buildTransparentWebViewPatch | |
cp TransparentWebViewPatch.java /tmp/buildTransparentWebViewPatch | |
cd /tmp/buildTransparentWebViewPatch | |
echo "Downloading jboss javassist..." | |
wget https://github.com/jboss-javassist/javassist/releases/download/rel_3_20_0_ga/javassist.jar > /dev/null 2>&1 | |
echo "Compiling..." | |
javac -cp javassist.jar TransparentWebViewPatch.java | |
echo "Building jar..." | |
sed -n '/\/\*\*/,/\*\//p' TransparentWebViewPatch.java > INFO.txt | |
echo "Premain-Class: TransparentWebViewPatch" > manifest.txt | |
jar -cvfm TransparentWebViewPatch.jar manifest.txt INFO.txt TransparentWebViewPatch.class TransparentWebViewPatch.java | |
cp TransparentWebViewPatch.jar $origin_dir/build/ | |
cp javassist.jar $origin_dir/build/ | |
rm -R /tmp/buildTransparentWebViewPatch | |
echo "Done!" |
Hi, i'm sorry for the two months delay but i've lost or never received (still not sure how this gist thing works) the notification.
In case you still need it and for for posterity, this is what you need to do:
- Compile this class and pack it in a jar file
- Add this line to the manifest.mf
Premain-Class: path.of.the.Patch
- Run your app with
-javaagent:path/of/the/jar/that/contains/the/patch.jar
Thank you very much! This really solved a big issue for me :-)
I also had to:
- Replace
Patcher._CLASS_POOL
withClasPool.getDefault()
- Add a method:
public static void premain(String agentArguments, Instrumentation instrumentation) {
instrumentation.addTransformer(new TransparentWebViewPatch());
}
True! I extrapolated this class from a project of mine, as you may have already guessed from the header, and i forgot to add the Patcher class that does what you said.
EDIT: Added the missing code and a build script
Time to update this to Java 10 - have you already done it? :)
Breaks when I update to java fx 14
Caused by: java.lang.ClassFormatError: Nest member class_info_index 63 has bad constant type in class file com/sun/webkit/WebPage
Well I removed patching the "scroll" method now it runs and works as well. No idea what I did but seems working :D
Ok in the end that was not the solution instead:
scroll_method.insertBefore(
"{\n" + " "
+ "addDirtyRect(new com.sun.webkit.graphics.WCRectangle(0f,0f,(float)width,(float)height));\n"
+ "return;"
+ "}"
);
works, setBody(...) somehow does not work.
I have problem with javafx 14.
javassist.CannotCompileException: [source error] no such class: com.sun.webkit.graphics.WCRectangle
javassist.NotFoundException: com.sun.webkit.graphics.WCRectangle
Can you give me some advice? Thanks you.
I have fixed above problem
Console show msg
Patching com/sun/webkit/WebPage ...
com/sun/webkit/WebPage patching succeeded!
Patching com/sun/javafx/webkit/prism/WCGraphicsPrismContext ...
com/sun/javafx/webkit/prism/WCGraphicsPrismContext patching succeeded!
But the webview background still not transparent
Worked for me when I used java fx 14 https://github.com/FAForever/downlords-faf-client/blob/develop/webview-patch/src/main/java/com/faforever/client/webviewpatcher/TransparentWebViewPatch.java I went back on java fx 11 tho for other reasons.
Hi axel1200.
I have used your version.
Console show msg.
Patching com/sun/webkit/WebPage ...
com/sun/webkit/WebPage patching succeeded!
Patching com/sun/javafx/webkit/prism/WCGraphicsPrismContext ...
com/sun/javafx/webkit/prism/WCGraphicsPrismContext patching succeeded!
But the webview background still not transparent
I use JDK 14, javaassist 3.27.0-GA, and Java Fx 14.
Can you tell me what u are using? Thank a lot.
I used jdk 11 :D not sure if that creates an issue. As javafx 14 says it needs jdk 11+. Not sure about the rest but you should find it in the repo
javassist.version=3.23.1-GA
And these vm parameters of which many should not be related -DnativeDir=build/resources/native -Dprism.dirtyopts=false -Xms128m -Xmx712m -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=33 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseStringDeduplication -javaagent:webview-patch/build/libs/webview-patch.jar -Djava.net.preferIPv4Stack=true -XX:TieredStopAtLevel=1 -noverify
How to apply this patch?