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 17package android.webkit; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.annotation.SystemApi; 22import android.app.ActivityThread; 23import android.app.Application; 24import android.app.ResourcesManager; 25import android.content.Context; 26import android.content.pm.ApplicationInfo; 27import android.content.res.Resources; 28import android.graphics.Canvas; 29import android.os.RemoteException; 30import android.os.SystemProperties; 31import android.os.Trace; 32import android.util.SparseArray; 33import android.view.DisplayListCanvas; 34import android.view.View; 35import android.view.ViewRootImpl; 36 37import com.android.internal.util.ArrayUtils; 38 39/** 40 * Delegate used by the WebView provider implementation to access 41 * the required framework functionality needed to implement a {@link WebView}. 42 * 43 * @hide 44 */ 45@SystemApi 46public final class WebViewDelegate { 47 48 /* package */ WebViewDelegate() { } 49 50 /** 51 * Listener that gets notified whenever tracing has been enabled/disabled. 52 */ 53 public interface OnTraceEnabledChangeListener { 54 void onTraceEnabledChange(boolean enabled); 55 } 56 57 /** 58 * Register a callback to be invoked when tracing for the WebView component has been 59 * enabled/disabled. 60 */ 61 public void setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener) { 62 SystemProperties.addChangeCallback(new Runnable() { 63 @Override 64 public void run() { 65 listener.onTraceEnabledChange(isTraceTagEnabled()); 66 } 67 }); 68 } 69 70 /** 71 * Returns {@code true} if the WebView trace tag is enabled and {@code false} otherwise. 72 */ 73 public boolean isTraceTagEnabled() { 74 return Trace.isTagEnabled(Trace.TRACE_TAG_WEBVIEW); 75 } 76 77 /** 78 * Returns {@code true} if the draw GL functor can be invoked (see {@link #invokeDrawGlFunctor}) 79 * and {@code false} otherwise. 80 */ 81 public boolean canInvokeDrawGlFunctor(View containerView) { 82 return true; 83 } 84 85 /** 86 * Invokes the draw GL functor. If waitForCompletion is {@code false} the functor 87 * may be invoked asynchronously. 88 * 89 * @param nativeDrawGLFunctor the pointer to the native functor that implements 90 * system/core/include/utils/Functor.h 91 */ 92 public void invokeDrawGlFunctor(View containerView, long nativeDrawGLFunctor, 93 boolean waitForCompletion) { 94 ViewRootImpl.invokeFunctor(nativeDrawGLFunctor, waitForCompletion); 95 } 96 97 /** 98 * Calls the function specified with the nativeDrawGLFunctor functor pointer. This 99 * functionality is used by the WebView for calling into their renderer from the 100 * framework display lists. 101 * 102 * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}) 103 * @param nativeDrawGLFunctor the pointer to the native functor that implements 104 * system/core/include/utils/Functor.h 105 * @throws IllegalArgumentException if the canvas is not hardware accelerated 106 */ 107 public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) { 108 if (!(canvas instanceof DisplayListCanvas)) { 109 // Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas. 110 throw new IllegalArgumentException(canvas.getClass().getName() 111 + " is not a DisplayList canvas"); 112 } 113 ((DisplayListCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, null); 114 } 115 116 /** 117 * Calls the function specified with the nativeDrawGLFunctor functor pointer. This 118 * functionality is used by the WebView for calling into their renderer from the 119 * framework display lists. 120 * 121 * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}) 122 * @param nativeDrawGLFunctor the pointer to the native functor that implements 123 * system/core/include/utils/Functor.h 124 * @param releasedRunnable Called when this nativeDrawGLFunctor is no longer referenced by this 125 * canvas, so is safe to be destroyed. 126 * @throws IllegalArgumentException if the canvas is not hardware accelerated 127 */ 128 public void callDrawGlFunction(@NonNull Canvas canvas, long nativeDrawGLFunctor, 129 @Nullable Runnable releasedRunnable) { 130 if (!(canvas instanceof DisplayListCanvas)) { 131 // Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas. 132 throw new IllegalArgumentException(canvas.getClass().getName() 133 + " is not a DisplayList canvas"); 134 } 135 ((DisplayListCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, releasedRunnable); 136 } 137 138 /** 139 * Detaches the draw GL functor. 140 * 141 * @param nativeDrawGLFunctor the pointer to the native functor that implements 142 * system/core/include/utils/Functor.h 143 */ 144 public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) { 145 ViewRootImpl viewRootImpl = containerView.getViewRootImpl(); 146 if (nativeDrawGLFunctor != 0 && viewRootImpl != null) { 147 viewRootImpl.detachFunctor(nativeDrawGLFunctor); 148 } 149 } 150 151 /** 152 * Returns the package id of the given {@code packageName}. 153 */ 154 public int getPackageId(Resources resources, String packageName) { 155 SparseArray<String> packageIdentifiers = 156 resources.getAssets().getAssignedPackageIdentifiers(); 157 for (int i = 0; i < packageIdentifiers.size(); i++) { 158 final String name = packageIdentifiers.valueAt(i); 159 160 if (packageName.equals(name)) { 161 return packageIdentifiers.keyAt(i); 162 } 163 } 164 throw new RuntimeException("Package not found: " + packageName); 165 } 166 167 /** 168 * Returns the application which is embedding the WebView. 169 */ 170 public Application getApplication() { 171 return ActivityThread.currentApplication(); 172 } 173 174 /** 175 * Returns the error string for the given {@code errorCode}. 176 */ 177 public String getErrorString(Context context, int errorCode) { 178 return LegacyErrorStrings.getString(errorCode, context); 179 } 180 181 /** 182 * Adds the WebView asset path to {@link android.content.res.AssetManager}. 183 */ 184 public void addWebViewAssetPath(Context context) { 185 final String newAssetPath = WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir; 186 187 final ApplicationInfo appInfo = context.getApplicationInfo(); 188 final String[] libs = appInfo.sharedLibraryFiles; 189 if (!ArrayUtils.contains(libs, newAssetPath)) { 190 // Build the new library asset path list. 191 final int newLibAssetsCount = 1 + (libs != null ? libs.length : 0); 192 final String[] newLibAssets = new String[newLibAssetsCount]; 193 if (libs != null) { 194 System.arraycopy(libs, 0, newLibAssets, 0, libs.length); 195 } 196 newLibAssets[newLibAssetsCount - 1] = newAssetPath; 197 198 // Update the ApplicationInfo object with the new list. 199 // We know this will persist and future Resources created via ResourcesManager 200 // will include the shared library because this ApplicationInfo comes from the 201 // underlying LoadedApk in ContextImpl, which does not change during the life of the 202 // application. 203 appInfo.sharedLibraryFiles = newLibAssets; 204 205 // Update existing Resources with the WebView library. 206 ResourcesManager.getInstance().appendLibAssetForMainAssetPath( 207 appInfo.getBaseResourcePath(), newAssetPath); 208 } 209 } 210 211 /** 212 * Returns whether WebView should run in multiprocess mode. 213 */ 214 public boolean isMultiProcessEnabled() { 215 try { 216 return WebViewFactory.getUpdateService().isMultiProcessEnabled(); 217 } catch (RemoteException e) { 218 throw e.rethrowFromSystemServer(); 219 } 220 } 221 222 /** 223 * Returns the data directory suffix to use, or null for none. 224 */ 225 public String getDataDirectorySuffix() { 226 return WebViewFactory.getDataDirectorySuffix(); 227 } 228} 229