1# Copyright 2023 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import java_types 6 7 8def Generate(jni_obj, *, gen_jni_class, script_name): 9 proxy_class = java_types.JavaClass( 10 f'{jni_obj.java_class.full_name_with_slashes}Jni') 11 visibility = 'public ' if jni_obj.proxy_visibility == 'public' else '' 12 interface_name = jni_obj.proxy_interface.name_with_dots 13 gen_jni = gen_jni_class.name 14 type_resolver = java_types.TypeResolver(proxy_class) 15 type_resolver.imports = list(jni_obj.type_resolver.imports) 16 17 sb = [] 18 sb.append(f"""\ 19// 20// This file was generated by {script_name} 21// 22package {jni_obj.java_class.class_without_prefix.package_with_dots}; 23 24import org.jni_zero.CheckDiscard; 25import org.jni_zero.JniStaticTestMocker; 26import org.jni_zero.NativeLibraryLoadedStatus; 27import {gen_jni_class.full_name_with_dots}; 28""") 29 30 # Copy over all imports (some will be unused, but oh well). 31 for c in type_resolver.imports: 32 sb.append(f'import {c.full_name_with_dots};\n') 33 34 sb.append(f""" 35@CheckDiscard("crbug.com/993421") 36{visibility}class {proxy_class.name} implements {interface_name} {{ 37 private static {interface_name} testInstance; 38 39 public static final JniStaticTestMocker<{interface_name}> TEST_HOOKS = 40 new JniStaticTestMocker<{interface_name}>() {{ 41 @Override 42 public void setInstanceForTesting({interface_name} instance) {{ 43 if (!{gen_jni}.TESTING_ENABLED) {{ 44 throw new RuntimeException( 45 "Tried to set a JNI mock when mocks aren't enabled!"); 46 }} 47 testInstance = instance; 48 }} 49 }}; 50""") 51 52 for native in jni_obj.proxy_natives: 53 call_params = native.params.to_call_str() 54 sig_params = native.params.to_java_declaration(type_resolver) 55 return_type_str = native.return_type.to_java(type_resolver) 56 return_prefix = '' 57 if not native.return_type.is_void(): 58 return_prefix = f'return ({return_type_str}) ' 59 60 sb.append(f""" 61 @Override 62 public {return_type_str} {native.name}({sig_params}) {{ 63 {return_prefix}{gen_jni}.{native.proxy_name}({call_params}); 64 }} 65""") 66 67 sb.append(f""" 68 public static {interface_name} get() {{ 69 if ({gen_jni}.TESTING_ENABLED) {{ 70 if (testInstance != null) {{ 71 return testInstance; 72 }} 73 if ({gen_jni}.REQUIRE_MOCK) {{ 74 throw new UnsupportedOperationException( 75 "No mock found for the native implementation of {interface_name}. " 76 + "The current configuration requires implementations be mocked."); 77 }} 78 }} 79 NativeLibraryLoadedStatus.checkLoaded(); 80 return new {proxy_class.name}(); 81 }} 82}} 83""") 84 return ''.join(sb) 85