├── .gitignore ├── platforms └── android │ ├── libs │ ├── armeabi │ │ └── liblbs.so │ └── tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar │ └── src │ └── org │ └── apache │ └── cordova │ └── x5engine │ ├── X5CordovaHttpAuthHandler.java │ ├── X5CordovaClientCertRequest.java │ ├── X5ExposedJsApi.java │ ├── X5CookieManager.java │ ├── X5WebView.java │ ├── X5WebChromeClient.java │ ├── X5WebViewEngine.java │ └── X5WebViewClient.java ├── README.md ├── package.json ├── plugin.xml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore project config 2 | 3 | /.vscode 4 | /.history 5 | 6 | -------------------------------------------------------------------------------- /platforms/android/libs/armeabi/liblbs.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runner525/x5webview-cordova-plugin/HEAD/platforms/android/libs/armeabi/liblbs.so -------------------------------------------------------------------------------- /platforms/android/libs/tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runner525/x5webview-cordova-plugin/HEAD/platforms/android/libs/tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # x5webview-cordova-plugin 2 | x5webview-cordova-plugin 是腾讯浏览服务(TBS)为cordova框架提供的用于android平台的cordova插件,旨在为android平台提供更好的webview浏览体验. 3 | 4 | 一.接入步骤: 5 | 1.向cordiva工程中添加x5webview插件,有如下两种方式: 6 | ``` 7 | (1)cordova plugin add x5webview-cordova-plugin 8 | (2)cordova plugin add https://github.com/runner525/x5webview-cordova-plugin.git 9 | 10 | ``` 11 | 12 | 二.熟悉android开发的同学可以参考x5官网来灵活使用x5内核.常用链接如下: 13 | 14 | 官网(https://x5.tencent.com/tbs/) 15 | 16 | 常见问题(https://x5.tencent.com/tbs/faq.html) 17 | 18 | 论坛(http://bbs.mb.qq.com/forum-112-1.html) 19 | 20 | 内核加载问题检测工具(http://bbs.mb.qq.com/thread-1944983-1-1.html) 21 | 22 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5CordovaHttpAuthHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.cordova.x5engine; 2 | 3 | import com.tencent.smtt.export.external.interfaces.HttpAuthHandler; 4 | 5 | import org.apache.cordova.ICordovaHttpAuthHandler; 6 | 7 | public class X5CordovaHttpAuthHandler implements ICordovaHttpAuthHandler { 8 | 9 | private final HttpAuthHandler handler; 10 | 11 | public X5CordovaHttpAuthHandler(HttpAuthHandler handler) { 12 | this.handler = handler; 13 | } 14 | 15 | /** 16 | * Instructs the XWalkView to cancel the authentication request. 17 | */ 18 | public void cancel() { 19 | handler.cancel(); 20 | } 21 | 22 | /** 23 | * Instructs the XWalkView to proceed with the authentication with the given credentials. 24 | * 25 | * @param username 26 | * @param password 27 | */ 28 | public void proceed(String username, String password) { 29 | handler.proceed(username, password); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x5webview-cordova-plugin", 3 | "version": "1.1.1", 4 | "description": "Changes the default WebView to x5engine", 5 | "cordova": { 6 | "id": "x5webview-cordova-plugin", 7 | "platforms": [ 8 | "android" 9 | ] 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/runner525/x5webview-cordova-plugin.git" 14 | }, 15 | "keywords": [ 16 | "cordova", 17 | "chromium", 18 | "x5engine", 19 | "webview", 20 | "ecosystem:cordova", 21 | "cordova-android" 22 | ], 23 | "engines": [ 24 | { 25 | "name": "cordova-android", 26 | "version": ">=4" 27 | }, 28 | { 29 | "name": "cordova-plugman", 30 | "version": ">=5.2.0" 31 | } 32 | ], 33 | "author": "lz", 34 | "license": "Apache 2.0", 35 | "bugs": { 36 | "url": "https://github.com/runner525/x5webview-cordova-plugin/issues" 37 | }, 38 | "homepage": "https://github.com/runner525/x5webview-cordova-plugin#readme" 39 | } 40 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5CordovaClientCertRequest.java: -------------------------------------------------------------------------------- 1 | package org.apache.cordova.x5engine; 2 | 3 | 4 | import com.tencent.smtt.export.external.interfaces.ClientCertRequest; 5 | 6 | import org.apache.cordova.ICordovaClientCertRequest; 7 | 8 | import java.security.Principal; 9 | import java.security.PrivateKey; 10 | import java.security.cert.X509Certificate; 11 | 12 | 13 | public class X5CordovaClientCertRequest implements ICordovaClientCertRequest { 14 | 15 | private final ClientCertRequest request; 16 | 17 | public X5CordovaClientCertRequest(ClientCertRequest request) { 18 | this.request = request; 19 | } 20 | 21 | /** 22 | * Cancel this request 23 | */ 24 | public void cancel() 25 | { 26 | request.cancel(); 27 | } 28 | 29 | /* 30 | * Returns the host name of the server requesting the certificate. 31 | */ 32 | public String getHost() 33 | { 34 | return request.getHost(); 35 | } 36 | 37 | /* 38 | * Returns the acceptable types of asymmetric keys (can be null). 39 | */ 40 | public String[] getKeyTypes() 41 | { 42 | return request.getKeyTypes(); 43 | } 44 | 45 | /* 46 | * Returns the port number of the server requesting the certificate. 47 | */ 48 | public int getPort() 49 | { 50 | return request.getPort(); 51 | } 52 | 53 | /* 54 | * Returns the acceptable certificate issuers for the certificate matching the private key (can be null). 55 | */ 56 | public Principal[] getPrincipals() 57 | { 58 | return request.getPrincipals(); 59 | } 60 | 61 | /* 62 | * Ignore the request for now. Do not remember user's choice. 63 | */ 64 | public void ignore() 65 | { 66 | request.ignore(); 67 | } 68 | 69 | /* 70 | * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests. 71 | * 72 | * @param privateKey The privateKey 73 | * @param chain The certificate chain 74 | */ 75 | public void proceed(PrivateKey privateKey, X509Certificate[] chain) 76 | { 77 | request.proceed(privateKey, chain); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5ExposedJsApi.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.x5engine; 20 | 21 | import android.webkit.JavascriptInterface; 22 | 23 | import org.apache.cordova.CordovaBridge; 24 | import org.apache.cordova.ExposedJsApi; 25 | import org.json.JSONException; 26 | 27 | /** 28 | * Contains APIs that the JS can call. All functions in here should also have 29 | * an equivalent entry in CordovaChromeClient.java, and be added to 30 | * cordova-js/lib/android/plugin/android/promptbasednativeapi.js 31 | */ 32 | class X5ExposedJsApi implements ExposedJsApi { 33 | private final CordovaBridge bridge; 34 | 35 | X5ExposedJsApi(CordovaBridge bridge) { 36 | this.bridge = bridge; 37 | } 38 | 39 | @JavascriptInterface 40 | public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException { 41 | return bridge.jsExec(bridgeSecret, service, action, callbackId, arguments); 42 | } 43 | 44 | @JavascriptInterface 45 | public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException { 46 | bridge.jsSetNativeToJsBridgeMode(bridgeSecret, value); 47 | } 48 | 49 | @JavascriptInterface 50 | public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException { 51 | return bridge.jsRetrieveJsMessages(bridgeSecret, fromOnlineEvent); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5CookieManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.x5engine; 21 | 22 | import android.annotation.TargetApi; 23 | import android.os.Build; 24 | import com.tencent.smtt.sdk.CookieManager; 25 | import com.tencent.smtt.sdk.WebView; 26 | 27 | import org.apache.cordova.ICordovaCookieManager; 28 | 29 | class X5CookieManager implements ICordovaCookieManager { 30 | 31 | protected final WebView webView; 32 | private final CookieManager cookieManager; 33 | 34 | //Added because lint can't see the conditional RIGHT ABOVE this 35 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 36 | public X5CookieManager(WebView webview) { 37 | webView = webview; 38 | cookieManager = CookieManager.getInstance(); 39 | 40 | //REALLY? Nobody has seen this UNTIL NOW? 41 | // cookieManager.setAcceptFileSchemeCookies(true); 42 | cookieManager.setAcceptCookie(true); 43 | 44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 45 | cookieManager.setAcceptThirdPartyCookies(webView, true); 46 | } 47 | } 48 | 49 | public void setCookiesEnabled(boolean accept) { 50 | cookieManager.setAcceptCookie(accept); 51 | } 52 | 53 | public void setCookie(final String url, final String value) { 54 | cookieManager.setCookie(url, value); 55 | } 56 | 57 | public String getCookie(final String url) { 58 | return cookieManager.getCookie(url); 59 | } 60 | 61 | public void clearCookies() { 62 | cookieManager.removeAllCookie(); 63 | } 64 | 65 | public void flush() { 66 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 67 | cookieManager.flush(); 68 | } 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | x5engine WebView Engine 9 | use x5webview for cordova to get a better webview browsing experience 10 | Apache 2.0 11 | x5webview,webview,chromium,cordova 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5WebView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.x5engine; 21 | 22 | import android.content.Context; 23 | import android.util.AttributeSet; 24 | import android.view.KeyEvent; 25 | import com.tencent.smtt.sdk.WebChromeClient; 26 | import com.tencent.smtt.sdk.WebView; 27 | import com.tencent.smtt.sdk.WebViewClient; 28 | 29 | import org.apache.cordova.CordovaInterface; 30 | import org.apache.cordova.CordovaWebView; 31 | import org.apache.cordova.CordovaWebViewEngine; 32 | 33 | 34 | public class X5WebView extends WebView implements CordovaWebViewEngine.EngineView { 35 | private X5WebViewClient viewClient; 36 | X5WebChromeClient chromeClient; 37 | private X5WebViewEngine parentEngine; 38 | private CordovaInterface cordova; 39 | 40 | public X5WebView(Context context) { 41 | this(context, null); 42 | } 43 | 44 | public X5WebView(Context context, AttributeSet attrs) { 45 | super(context, attrs); 46 | } 47 | 48 | // Package visibility to enforce that only X5WebViewEngine should call this method. 49 | void init(X5WebViewEngine parentEngine, CordovaInterface cordova) { 50 | this.cordova = cordova; 51 | this.parentEngine = parentEngine; 52 | if (this.viewClient == null) { 53 | setWebViewClient(new X5WebViewClient(parentEngine)); 54 | } 55 | 56 | if (this.chromeClient == null) { 57 | setWebChromeClient(new X5WebChromeClient(parentEngine)); 58 | } 59 | } 60 | 61 | @Override 62 | public CordovaWebView getCordovaWebView() { 63 | return parentEngine != null ? parentEngine.getCordovaWebView() : null; 64 | } 65 | 66 | @Override 67 | public void setWebViewClient(WebViewClient client) { 68 | viewClient = (X5WebViewClient)client; 69 | super.setWebViewClient(client); 70 | } 71 | 72 | @Override 73 | public void setWebChromeClient(WebChromeClient client) { 74 | chromeClient = (X5WebChromeClient)client; 75 | super.setWebChromeClient(client); 76 | } 77 | 78 | @Override 79 | public boolean dispatchKeyEvent(KeyEvent event) { 80 | Boolean ret = parentEngine.client.onDispatchKeyEvent(event); 81 | if (ret != null) { 82 | return ret.booleanValue(); 83 | } 84 | return super.dispatchKeyEvent(event); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /platforms/android/src/org/apache/cordova/x5engine/X5WebChromeClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.x5engine; 20 | 21 | import java.util.Arrays; 22 | import android.annotation.TargetApi; 23 | import android.app.Activity; 24 | import android.content.Context; 25 | import android.content.ActivityNotFoundException; 26 | import android.content.Intent; 27 | import android.net.Uri; 28 | import android.os.Build; 29 | import android.util.Log; 30 | import android.view.Gravity; 31 | import android.view.View; 32 | import android.view.ViewGroup.LayoutParams; 33 | import com.tencent.smtt.export.external.interfaces.ConsoleMessage; 34 | import com.tencent.smtt.export.external.interfaces.GeolocationPermissionsCallback; 35 | import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient; 36 | import com.tencent.smtt.export.external.interfaces.JsPromptResult; 37 | import com.tencent.smtt.export.external.interfaces.JsResult; 38 | import com.tencent.smtt.sdk.ValueCallback; 39 | import com.tencent.smtt.sdk.WebChromeClient; 40 | import com.tencent.smtt.sdk.WebStorage; 41 | import com.tencent.smtt.sdk.WebView; 42 | 43 | import android.webkit.PermissionRequest; 44 | import android.widget.LinearLayout; 45 | import android.widget.ProgressBar; 46 | import android.widget.RelativeLayout; 47 | 48 | import org.apache.cordova.CordovaDialogsHelper; 49 | import org.apache.cordova.CordovaPlugin; 50 | import org.apache.cordova.LOG; 51 | 52 | /** 53 | * This class is the WebChromeClient that implements callbacks for our web view. 54 | * The kind of callbacks that happen here are on the chrome outside the document, 55 | * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related 56 | * to but different than CordovaWebViewClient. 57 | */ 58 | public class X5WebChromeClient extends WebChromeClient { 59 | 60 | private static final int FILECHOOSER_RESULTCODE = 5173; 61 | private static final String LOG_TAG = "X5WebChromeClient"; 62 | private long MAX_QUOTA = 100 * 1024 * 1024; 63 | protected final X5WebViewEngine parentEngine; 64 | 65 | // the video progress view 66 | private View mVideoProgressView; 67 | 68 | private CordovaDialogsHelper dialogsHelper; 69 | private Context appContext; 70 | 71 | private IX5WebChromeClient.CustomViewCallback mCustomViewCallback; 72 | private View mCustomView; 73 | 74 | public X5WebChromeClient(X5WebViewEngine parentEngine) { 75 | this.parentEngine = parentEngine; 76 | appContext = parentEngine.webView.getContext(); 77 | dialogsHelper = new CordovaDialogsHelper(appContext); 78 | } 79 | 80 | /** 81 | * Tell the client to display a javascript alert dialog. 82 | */ 83 | @Override 84 | public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { 85 | dialogsHelper.showAlert(message, new CordovaDialogsHelper.Result() { 86 | @Override public void gotResult(boolean success, String value) { 87 | if (success) { 88 | result.confirm(); 89 | } else { 90 | result.cancel(); 91 | } 92 | } 93 | }); 94 | return true; 95 | } 96 | 97 | /** 98 | * Tell the client to display a confirm dialog to the user. 99 | */ 100 | @Override 101 | public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { 102 | dialogsHelper.showConfirm(message, new CordovaDialogsHelper.Result() { 103 | @Override 104 | public void gotResult(boolean success, String value) { 105 | if (success) { 106 | result.confirm(); 107 | } else { 108 | result.cancel(); 109 | } 110 | } 111 | }); 112 | return true; 113 | } 114 | 115 | /** 116 | * Tell the client to display a prompt dialog to the user. 117 | * If the client returns true, WebView will assume that the client will 118 | * handle the prompt dialog and call the appropriate JsPromptResult method. 119 | * 120 | * Since we are hacking prompts for our own purposes, we should not be using them for 121 | * this purpose, perhaps we should hack console.log to do this instead! 122 | */ 123 | @Override 124 | public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) { 125 | // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread. 126 | String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue); 127 | if (handledRet != null) { 128 | result.confirm(handledRet); 129 | } else { 130 | dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() { 131 | @Override 132 | public void gotResult(boolean success, String value) { 133 | if (success) { 134 | result.confirm(value); 135 | } else { 136 | result.cancel(); 137 | } 138 | } 139 | }); 140 | } 141 | return true; 142 | } 143 | 144 | /** 145 | * Handle database quota exceeded notification. 146 | */ 147 | @Override 148 | public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, 149 | long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) 150 | { 151 | LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota); 152 | quotaUpdater.updateQuota(MAX_QUOTA); 153 | } 154 | 155 | @TargetApi(8) 156 | @Override 157 | public boolean onConsoleMessage(ConsoleMessage consoleMessage) 158 | { 159 | if (consoleMessage.message() != null) 160 | LOG.d(LOG_TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message()); 161 | return super.onConsoleMessage(consoleMessage); 162 | } 163 | 164 | @Override 165 | /** 166 | * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin. 167 | * 168 | * This also checks for the Geolocation Plugin and requests permission from the application to use Geolocation. 169 | * 170 | * @param origin 171 | * @param callback 172 | */ 173 | public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissionsCallback callback) { 174 | super.onGeolocationPermissionsShowPrompt(origin, callback); 175 | callback.invoke(origin, true, false); 176 | //Get the plugin, it should be loaded 177 | CordovaPlugin geolocation = parentEngine.pluginManager.getPlugin("Geolocation"); 178 | if(geolocation != null && !geolocation.hasPermisssion()) 179 | { 180 | geolocation.requestPermissions(0); 181 | } 182 | 183 | } 184 | 185 | //TODO API level 7 is required for this, see if we could lower this using something else 186 | // @Override 187 | // public void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback callback) { 188 | // parentEngine.getCordovaWebView().showCustomView(view, callback); 189 | // } 190 | 191 | public void onHideCustomView() { 192 | parentEngine.getCordovaWebView().hideCustomView(); 193 | } 194 | 195 | /** 196 | * Ask the host application for a custom progress view to show while 197 | * a