1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.webkit; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.app.ActivityThread; 23 import android.app.Application; 24 import android.app.ResourcesManager; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.content.Context; 27 import android.content.pm.ApplicationInfo; 28 import android.content.res.Resources; 29 import android.graphics.Canvas; 30 import android.graphics.RecordingCanvas; 31 import android.os.RemoteException; 32 import android.os.SystemProperties; 33 import android.os.Trace; 34 import android.util.SparseArray; 35 import android.view.View; 36 import android.view.ViewRootImpl; 37 38 import com.android.internal.util.ArrayUtils; 39 40 /** 41 * Delegate used by the WebView provider implementation to access 42 * the required framework functionality needed to implement a {@link WebView}. 43 * 44 * @hide 45 */ 46 @SystemApi 47 public final class WebViewDelegate { 48 49 @UnsupportedAppUsage WebViewDelegate()50 /* package */ WebViewDelegate() { } 51 52 /** 53 * Listener that gets notified whenever tracing has been enabled/disabled. 54 */ 55 public interface OnTraceEnabledChangeListener { onTraceEnabledChange(boolean enabled)56 void onTraceEnabledChange(boolean enabled); 57 } 58 59 /** 60 * Register a callback to be invoked when tracing for the WebView component has been 61 * enabled/disabled. 62 */ setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener)63 public void setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener) { 64 SystemProperties.addChangeCallback(new Runnable() { 65 @Override 66 public void run() { 67 listener.onTraceEnabledChange(isTraceTagEnabled()); 68 } 69 }); 70 } 71 72 /** 73 * Returns {@code true} if the WebView trace tag is enabled and {@code false} otherwise. 74 */ isTraceTagEnabled()75 public boolean isTraceTagEnabled() { 76 return Trace.isTagEnabled(Trace.TRACE_TAG_WEBVIEW); 77 } 78 79 /** 80 * Throws {@link UnsupportedOperationException} 81 * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)} 82 */ 83 @Deprecated canInvokeDrawGlFunctor(View containerView)84 public boolean canInvokeDrawGlFunctor(View containerView) { 85 throw new UnsupportedOperationException(); 86 } 87 88 /** 89 * Throws {@link UnsupportedOperationException} 90 * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)} 91 */ 92 @Deprecated invokeDrawGlFunctor(View containerView, long nativeDrawGLFunctor, boolean waitForCompletion)93 public void invokeDrawGlFunctor(View containerView, long nativeDrawGLFunctor, 94 boolean waitForCompletion) { 95 throw new UnsupportedOperationException(); 96 } 97 98 /** 99 * Throws {@link UnsupportedOperationException} 100 * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)} 101 */ 102 @Deprecated callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor)103 public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) { 104 throw new UnsupportedOperationException(); 105 } 106 107 /** 108 * Throws {@link UnsupportedOperationException} 109 * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)} 110 */ 111 @Deprecated callDrawGlFunction(@onNull Canvas canvas, long nativeDrawGLFunctor, @Nullable Runnable releasedRunnable)112 public void callDrawGlFunction(@NonNull Canvas canvas, long nativeDrawGLFunctor, 113 @Nullable Runnable releasedRunnable) { 114 throw new UnsupportedOperationException(); 115 } 116 117 /** 118 * Call webview draw functor. See API in draw_fn.h. 119 * @param canvas a {@link RecordingCanvas}. 120 * @param functor created by AwDrawFn_CreateFunctor in draw_fn.h. 121 */ drawWebViewFunctor(@onNull Canvas canvas, int functor)122 public void drawWebViewFunctor(@NonNull Canvas canvas, int functor) { 123 if (!(canvas instanceof RecordingCanvas)) { 124 // Canvas#isHardwareAccelerated() is only true for subclasses of RecordingCanvas. 125 throw new IllegalArgumentException(canvas.getClass().getName() 126 + " is not a RecordingCanvas canvas"); 127 } 128 ((RecordingCanvas) canvas).drawWebViewFunctor(functor); 129 } 130 131 /** 132 * Detaches the draw GL functor. 133 * 134 * @param nativeDrawGLFunctor the pointer to the native functor that implements 135 * system/core/include/utils/Functor.h 136 * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)} 137 */ 138 @Deprecated detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor)139 public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) { 140 ViewRootImpl viewRootImpl = containerView.getViewRootImpl(); 141 if (nativeDrawGLFunctor != 0 && viewRootImpl != null) { 142 viewRootImpl.detachFunctor(nativeDrawGLFunctor); 143 } 144 } 145 146 /** 147 * Returns the package id of the given {@code packageName}. 148 */ getPackageId(Resources resources, String packageName)149 public int getPackageId(Resources resources, String packageName) { 150 SparseArray<String> packageIdentifiers = 151 resources.getAssets().getAssignedPackageIdentifiers(); 152 for (int i = 0; i < packageIdentifiers.size(); i++) { 153 final String name = packageIdentifiers.valueAt(i); 154 155 if (packageName.equals(name)) { 156 return packageIdentifiers.keyAt(i); 157 } 158 } 159 throw new RuntimeException("Package not found: " + packageName); 160 } 161 162 /** 163 * Returns the application which is embedding the WebView. 164 */ getApplication()165 public Application getApplication() { 166 return ActivityThread.currentApplication(); 167 } 168 169 /** 170 * Returns the error string for the given {@code errorCode}. 171 */ getErrorString(Context context, int errorCode)172 public String getErrorString(Context context, int errorCode) { 173 return LegacyErrorStrings.getString(errorCode, context); 174 } 175 176 /** 177 * Adds the WebView asset path to {@link android.content.res.AssetManager}. 178 * If {@link android.content.res.Flags#FLAG_REGISTER_RESOURCE_PATHS} is enabled, this function 179 * will be a no-op because the asset paths appending work will only be handled by 180 * {@link android.content.res.Resources#registerResourcePaths(String, ApplicationInfo)}, 181 * otherwise it behaves the old way. 182 */ addWebViewAssetPath(Context context)183 public void addWebViewAssetPath(Context context) { 184 if (android.content.res.Flags.registerResourcePaths()) { 185 return; 186 } 187 188 final String[] newAssetPaths = 189 WebViewFactory.getLoadedPackageInfo().applicationInfo.getAllApkPaths(); 190 final ApplicationInfo appInfo = context.getApplicationInfo(); 191 192 // Build the new library asset path list. 193 String[] newLibAssets = appInfo.sharedLibraryFiles; 194 for (String newAssetPath : newAssetPaths) { 195 newLibAssets = ArrayUtils.appendElement(String.class, newLibAssets, newAssetPath); 196 } 197 198 if (newLibAssets != appInfo.sharedLibraryFiles) { 199 // Update the ApplicationInfo object with the new list. 200 // We know this will persist and future Resources created via ResourcesManager 201 // will include the shared library because this ApplicationInfo comes from the 202 // underlying LoadedApk in ContextImpl, which does not change during the life of the 203 // application. 204 appInfo.sharedLibraryFiles = newLibAssets; 205 206 // Update existing Resources with the WebView library. 207 ResourcesManager.getInstance().appendLibAssetsForMainAssetPath( 208 appInfo.getBaseResourcePath(), newAssetPaths); 209 } 210 } 211 212 /** 213 * Returns whether WebView should run in multiprocess mode. 214 */ isMultiProcessEnabled()215 public boolean isMultiProcessEnabled() { 216 if (Flags.updateServiceV2()) { 217 return true; 218 } else if (Flags.updateServiceIpcWrapper()) { 219 // We don't want to support this method in the new wrapper because updateServiceV2 is 220 // intended to ship in the same release (or sooner). It's only possible to disable it 221 // with an obscure adb command, so just return true here too. 222 return true; 223 } 224 try { 225 return WebViewFactory.getUpdateService().isMultiProcessEnabled(); 226 } catch (RemoteException e) { 227 throw e.rethrowFromSystemServer(); 228 } 229 } 230 231 /** 232 * Returns the data directory suffix to use, or null for none. 233 */ getDataDirectorySuffix()234 public String getDataDirectorySuffix() { 235 return WebViewFactory.getDataDirectorySuffix(); 236 } 237 238 /** 239 * Get the timestamps at which various WebView startup events occurred in this process. 240 * This method must be called on the same thread where the 241 * WebViewChromiumFactoryProvider#create method was invoked. 242 */ 243 @NonNull getStartupTimestamps()244 public WebViewFactory.StartupTimestamps getStartupTimestamps() { 245 return WebViewFactory.getStartupTimestamps(); 246 } 247 } 248