1 // Copyright 2018 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 com.android.webview.chromium; 6 7 import android.webkit.WebChromeClient; 8 import android.webkit.WebViewClient; 9 10 import org.chromium.android_webview.AwContents; 11 import org.chromium.android_webview.AwRenderProcess; 12 import org.chromium.android_webview.ScriptReference; 13 import org.chromium.android_webview.WebMessageListener; 14 import org.chromium.android_webview.WebViewChromiumRunQueue; 15 import org.chromium.base.ThreadUtils; 16 import org.chromium.content_public.browser.MessagePort; 17 18 import java.util.concurrent.Callable; 19 20 /** 21 * This class contains the parts of WebViewChromium that should be shared between the webkit-glue 22 * layer and the support library glue layer. 23 */ 24 public class SharedWebViewChromium { 25 private final WebViewChromiumRunQueue mRunQueue; 26 private final WebViewChromiumAwInit mAwInit; 27 // The WebView wrapper for WebContents and required browser components. 28 private AwContents mAwContents; 29 30 private SharedWebViewContentsClientAdapter mContentsClientAdapter; 31 32 // Default WebViewClient used to avoid null checks. 33 static final WebViewClient sNullWebViewClient = new WebViewClient(); 34 // The WebViewClient instance that was passed to WebView.setWebViewClient(). 35 private WebViewClient mWebViewClient = sNullWebViewClient; 36 private WebChromeClient mWebChromeClient; 37 SharedWebViewChromium(WebViewChromiumRunQueue runQueue, WebViewChromiumAwInit awInit)38 public SharedWebViewChromium(WebViewChromiumRunQueue runQueue, WebViewChromiumAwInit awInit) { 39 mRunQueue = runQueue; 40 mAwInit = awInit; 41 } 42 setWebViewClient(WebViewClient client)43 void setWebViewClient(WebViewClient client) { 44 mWebViewClient = client != null ? client : sNullWebViewClient; 45 } 46 getWebViewClient()47 public WebViewClient getWebViewClient() { 48 return mWebViewClient; 49 } 50 setWebChromeClient(WebChromeClient client)51 void setWebChromeClient(WebChromeClient client) { 52 mWebChromeClient = client; 53 } 54 getWebChromeClient()55 public WebChromeClient getWebChromeClient() { 56 return mWebChromeClient; 57 } 58 getRenderProcess()59 public AwRenderProcess getRenderProcess() { 60 mAwInit.startYourEngines(true); 61 if (checkNeedsPost()) { 62 return mRunQueue.runOnUiThreadBlocking(() -> getRenderProcess()); 63 } 64 return mAwContents.getRenderProcess(); 65 } 66 init(SharedWebViewContentsClientAdapter contentsClientAdapter)67 public void init(SharedWebViewContentsClientAdapter contentsClientAdapter) { 68 mContentsClientAdapter = contentsClientAdapter; 69 } 70 initForReal(AwContents awContents)71 public void initForReal(AwContents awContents) { 72 assert ThreadUtils.runningOnUiThread(); 73 74 if (mAwContents != null) { 75 throw new RuntimeException( 76 "Cannot create multiple AwContents for the same SharedWebViewChromium"); 77 } 78 mAwContents = awContents; 79 } 80 insertVisualStateCallback(long requestId, AwContents.VisualStateCallback callback)81 public void insertVisualStateCallback(long requestId, AwContents.VisualStateCallback callback) { 82 if (checkNeedsPost()) { 83 mRunQueue.addTask(new Runnable() { 84 @Override 85 public void run() { 86 insertVisualStateCallback(requestId, callback); 87 } 88 }); 89 return; 90 } 91 mAwContents.insertVisualStateCallback(requestId, callback); 92 } 93 createWebMessageChannel()94 public MessagePort[] createWebMessageChannel() { 95 mAwInit.startYourEngines(true); 96 if (checkNeedsPost()) { 97 MessagePort[] ret = mRunQueue.runOnUiThreadBlocking(new Callable<MessagePort[]>() { 98 @Override 99 public MessagePort[] call() { 100 return createWebMessageChannel(); 101 } 102 }); 103 return ret; 104 } 105 return mAwContents.createMessageChannel(); 106 } 107 postMessageToMainFrame( final String message, final String targetOrigin, final MessagePort[] sentPorts)108 public void postMessageToMainFrame( 109 final String message, final String targetOrigin, final MessagePort[] sentPorts) { 110 if (checkNeedsPost()) { 111 mRunQueue.addTask(new Runnable() { 112 @Override 113 public void run() { 114 postMessageToMainFrame(message, targetOrigin, sentPorts); 115 } 116 }); 117 return; 118 } 119 mAwContents.postMessageToMainFrame(message, targetOrigin, sentPorts); 120 } 121 addWebMessageListener(final String jsObjectName, final String[] allowedOriginRules, final WebMessageListener listener)122 public void addWebMessageListener(final String jsObjectName, final String[] allowedOriginRules, 123 final WebMessageListener listener) { 124 if (checkNeedsPost()) { 125 mRunQueue.addTask( 126 () -> addWebMessageListener(jsObjectName, allowedOriginRules, listener)); 127 return; 128 } 129 mAwContents.addWebMessageListener(jsObjectName, allowedOriginRules, listener); 130 } 131 removeWebMessageListener(final String jsObjectName)132 public void removeWebMessageListener(final String jsObjectName) { 133 if (checkNeedsPost()) { 134 mRunQueue.addTask(() -> removeWebMessageListener(jsObjectName)); 135 return; 136 } 137 mAwContents.removeWebMessageListener(jsObjectName); 138 } 139 addDocumentStartJavaScript( final String script, final String[] allowedOriginRules)140 public ScriptReference addDocumentStartJavaScript( 141 final String script, final String[] allowedOriginRules) { 142 if (checkNeedsPost()) { 143 return mRunQueue.runOnUiThreadBlocking( 144 () -> addDocumentStartJavaScript(script, allowedOriginRules)); 145 } 146 return mAwContents.addDocumentStartJavaScript(script, allowedOriginRules); 147 } 148 setWebViewRendererClientAdapter( SharedWebViewRendererClientAdapter webViewRendererClientAdapter)149 public void setWebViewRendererClientAdapter( 150 SharedWebViewRendererClientAdapter webViewRendererClientAdapter) { 151 if (checkNeedsPost()) { 152 mRunQueue.addTask(new Runnable() { 153 @Override 154 public void run() { 155 setWebViewRendererClientAdapter(webViewRendererClientAdapter); 156 } 157 }); 158 return; 159 } 160 mContentsClientAdapter.setWebViewRendererClientAdapter(webViewRendererClientAdapter); 161 } 162 getWebViewRendererClientAdapter()163 public SharedWebViewRendererClientAdapter getWebViewRendererClientAdapter() { 164 mAwInit.startYourEngines(true); 165 if (checkNeedsPost()) { 166 return mRunQueue.runOnUiThreadBlocking( 167 new Callable<SharedWebViewRendererClientAdapter>() { 168 @Override 169 public SharedWebViewRendererClientAdapter call() { 170 return getWebViewRendererClientAdapter(); 171 } 172 }); 173 } 174 return mContentsClientAdapter.getWebViewRendererClientAdapter(); 175 } 176 177 protected boolean checkNeedsPost() { 178 boolean needsPost = !mRunQueue.chromiumHasStarted() || !ThreadUtils.runningOnUiThread(); 179 if (!needsPost && mAwContents == null) { 180 throw new IllegalStateException("AwContents must be created if we are not posting!"); 181 } 182 return needsPost; 183 } 184 185 public AwContents getAwContents() { 186 return mAwContents; 187 } 188 } 189