1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.android_webview; 6 7 import android.content.Context; 8 import android.net.Uri; 9 10 import org.chromium.android_webview.common.Flag; 11 import org.chromium.android_webview.common.FlagOverrideHelper; 12 import org.chromium.android_webview.common.PlatformServiceBridge; 13 import org.chromium.android_webview.common.ProductionSupportedFlagList; 14 import org.chromium.base.Callback; 15 import org.chromium.base.ThreadUtils; 16 import org.chromium.base.annotations.CalledByNative; 17 import org.chromium.base.annotations.JNINamespace; 18 import org.chromium.base.annotations.NativeMethods; 19 import org.chromium.base.task.PostTask; 20 import org.chromium.base.task.TaskTraits; 21 import org.chromium.content_public.browser.UiThreadTaskTraits; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.Map; 26 27 /** 28 * Implementations of various static methods, and also a home for static 29 * data structures that are meant to be shared between all webviews. 30 */ 31 @JNINamespace("android_webview") 32 public class AwContentsStatics { 33 34 private static ClientCertLookupTable sClientCertLookupTable; 35 36 private static String sUnreachableWebDataUrl; 37 38 private static boolean sRecordFullDocument; 39 40 private static final String sSafeBrowsingWarmUpHelper = 41 "com.android.webview.chromium.SafeBrowsingWarmUpHelper"; 42 43 /** 44 * Return the client certificate lookup table. 45 */ getClientCertLookupTable()46 public static ClientCertLookupTable getClientCertLookupTable() { 47 ThreadUtils.assertOnUiThread(); 48 if (sClientCertLookupTable == null) { 49 sClientCertLookupTable = new ClientCertLookupTable(); 50 } 51 return sClientCertLookupTable; 52 } 53 54 /** 55 * Clear client cert lookup table. Should only be called from UI thread. 56 */ clearClientCertPreferences(Runnable callback)57 public static void clearClientCertPreferences(Runnable callback) { 58 ThreadUtils.assertOnUiThread(); 59 getClientCertLookupTable().clear(); 60 AwContentsStaticsJni.get().clearClientCertPreferences(callback); 61 } 62 63 @CalledByNative clientCertificatesCleared(Runnable callback)64 private static void clientCertificatesCleared(Runnable callback) { 65 if (callback == null) return; 66 callback.run(); 67 } 68 getUnreachableWebDataUrl()69 public static String getUnreachableWebDataUrl() { 70 // Note that this method may be called from both IO and UI threads, 71 // but as it only retrieves a value of a constant from native, even if 72 // two calls will be running at the same time, this should not cause 73 // any harm. 74 if (sUnreachableWebDataUrl == null) { 75 sUnreachableWebDataUrl = AwContentsStaticsJni.get().getUnreachableWebDataUrl(); 76 } 77 return sUnreachableWebDataUrl; 78 } 79 setRecordFullDocument(boolean recordFullDocument)80 public static void setRecordFullDocument(boolean recordFullDocument) { 81 sRecordFullDocument = recordFullDocument; 82 } 83 getRecordFullDocument()84 /* package */ static boolean getRecordFullDocument() { 85 return sRecordFullDocument; 86 } 87 getProductVersion()88 public static String getProductVersion() { 89 return AwContentsStaticsJni.get().getProductVersion(); 90 } 91 setServiceWorkerIoThreadClient( AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext)92 public static void setServiceWorkerIoThreadClient( 93 AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext) { 94 AwContentsStaticsJni.get().setServiceWorkerIoThreadClient(ioThreadClient, browserContext); 95 } 96 97 @CalledByNative safeBrowsingAllowlistAssigned(Callback<Boolean> callback, boolean success)98 private static void safeBrowsingAllowlistAssigned(Callback<Boolean> callback, boolean success) { 99 if (callback == null) return; 100 callback.onResult(success); 101 } 102 setSafeBrowsingAllowlist(List<String> urls, Callback<Boolean> callback)103 public static void setSafeBrowsingAllowlist(List<String> urls, Callback<Boolean> callback) { 104 String[] urlArray = urls.toArray(new String[urls.size()]); 105 if (callback == null) { 106 callback = b -> { 107 }; 108 } 109 AwContentsStaticsJni.get().setSafeBrowsingAllowlist(urlArray, callback); 110 } 111 112 @SuppressWarnings("NoContextGetApplicationContext") initSafeBrowsing(Context context, final Callback<Boolean> callback)113 public static void initSafeBrowsing(Context context, final Callback<Boolean> callback) { 114 // Wrap the callback to make sure we always invoke it on the UI thread, as guaranteed by the 115 // API. 116 Callback<Boolean> wrapperCallback = b -> { 117 if (callback != null) { 118 PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, callback.bind(b)); 119 } 120 }; 121 122 PlatformServiceBridge.getInstance().warmUpSafeBrowsing( 123 context.getApplicationContext(), wrapperCallback); 124 } 125 getSafeBrowsingPrivacyPolicyUrl()126 public static Uri getSafeBrowsingPrivacyPolicyUrl() { 127 return Uri.parse(AwContentsStaticsJni.get().getSafeBrowsingPrivacyPolicyUrl()); 128 } 129 setCheckClearTextPermitted(boolean permitted)130 public static void setCheckClearTextPermitted(boolean permitted) { 131 AwContentsStaticsJni.get().setCheckClearTextPermitted(permitted); 132 } 133 logCommandLineForDebugging()134 public static void logCommandLineForDebugging() { 135 AwContentsStaticsJni.get().logCommandLineForDebugging(); 136 } 137 logFlagOverridesWithNative(Map<String, Boolean> flagOverrides)138 public static void logFlagOverridesWithNative(Map<String, Boolean> flagOverrides) { 139 // Do work asynchronously to avoid blocking startup. 140 PostTask.postTask(TaskTraits.THREAD_POOL_BEST_EFFORT, () -> { 141 FlagOverrideHelper helper = 142 new FlagOverrideHelper(ProductionSupportedFlagList.sFlagList); 143 ArrayList<String> switches = new ArrayList<>(); 144 ArrayList<String> features = new ArrayList<>(); 145 for (Map.Entry<String, Boolean> entry : flagOverrides.entrySet()) { 146 Flag flag = helper.getFlagForName(entry.getKey()); 147 boolean enabled = entry.getValue(); 148 if (flag.isBaseFeature()) { 149 features.add(flag.getName() + (enabled ? ":enabled" : ":disabled")); 150 } else if (enabled) { 151 switches.add("--" + flag.getName()); 152 } 153 // Only insert enabled switches; ignore explicitly disabled switches since this is 154 // usually a NOOP. 155 } 156 AwContentsStaticsJni.get().logFlagMetrics( 157 switches.toArray(new String[0]), features.toArray(new String[0])); 158 }); 159 } 160 161 /** 162 * Return the first substring consisting of the address of a physical location. 163 * @see {@link android.webkit.WebView#findAddress(String)} 164 * 165 * @param addr The string to search for addresses. 166 * @return the address, or if no address is found, return null. 167 */ findAddress(String addr)168 public static String findAddress(String addr) { 169 if (addr == null) { 170 throw new NullPointerException("addr is null"); 171 } 172 return FindAddress.findAddress(addr); 173 } 174 175 /** 176 * Returns true if WebView is running in multi process mode. 177 */ isMultiProcessEnabled()178 public static boolean isMultiProcessEnabled() { 179 return AwContentsStaticsJni.get().isMultiProcessEnabled(); 180 } 181 182 @NativeMethods 183 interface Natives { logCommandLineForDebugging()184 void logCommandLineForDebugging(); logFlagMetrics(String[] switches, String[] features)185 void logFlagMetrics(String[] switches, String[] features); 186 getSafeBrowsingPrivacyPolicyUrl()187 String getSafeBrowsingPrivacyPolicyUrl(); clearClientCertPreferences(Runnable callback)188 void clearClientCertPreferences(Runnable callback); getUnreachableWebDataUrl()189 String getUnreachableWebDataUrl(); getProductVersion()190 String getProductVersion(); setServiceWorkerIoThreadClient( AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext)191 void setServiceWorkerIoThreadClient( 192 AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext); setSafeBrowsingAllowlist(String[] urls, Callback<Boolean> callback)193 void setSafeBrowsingAllowlist(String[] urls, Callback<Boolean> callback); setCheckClearTextPermitted(boolean permitted)194 void setCheckClearTextPermitted(boolean permitted); isMultiProcessEnabled()195 boolean isMultiProcessEnabled(); 196 } 197 } 198