Commit a72d4a9a by mergen

local web server

parent a1b5f1e9
package org.apache.cordova.x5engine;
import android.content.Context;
import android.content.res.AssetManager;
import android.net.Uri;
import android.util.Log;
import android.util.TypedValue;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class AndroidProtocolHandler {
private static final String TAG = "AndroidProtocolHandler";
private Context context;
public AndroidProtocolHandler(Context context) {
this.context = context;
}
public InputStream openAsset(String path) throws IOException {
return context.getAssets().open(path, AssetManager.ACCESS_STREAMING);
}
public InputStream openResource(Uri uri) {
assert uri.getPath() != null;
// The path must be of the form ".../asset_type/asset_name.ext".
List<String> pathSegments = uri.getPathSegments();
String assetType = pathSegments.get(pathSegments.size() - 2);
String assetName = pathSegments.get(pathSegments.size() - 1);
// Drop the file extension.
assetName = assetName.split("\\.")[0];
try {
// Use the application context for resolving the resource package name so that we do
// not use the browser's own resources. Note that if 'context' here belongs to the
// test suite, it does not have a separate application context. In that case we use
// the original context object directly.
if (context.getApplicationContext() != null) {
context = context.getApplicationContext();
}
int fieldId = getFieldId(context, assetType, assetName);
int valueType = getValueType(context, fieldId);
if (valueType == TypedValue.TYPE_STRING) {
return context.getResources().openRawResource(fieldId);
} else {
Log.e(TAG, "Asset not of type string: " + uri);
return null;
}
} catch (ClassNotFoundException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
} catch (NoSuchFieldException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
} catch (IllegalAccessException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
}
}
public InputStream openFile(String filePath) throws IOException {
String realPath = filePath.replace(X5WebViewLocalServer.fileStart, "");
File localFile = new File(realPath);
return new FileInputStream(localFile);
}
public InputStream openContentUrl(Uri uri) throws IOException {
Integer port = uri.getPort();
String realPath;
if (port == -1) {
realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + X5WebViewLocalServer.contentStart, "content:/");
} else {
realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + ":" + port + X5WebViewLocalServer.contentStart, "content:/");
}
InputStream stream = null;
try {
stream = context.getContentResolver().openInputStream(Uri.parse(realPath));
} catch (SecurityException e) {
Log.e(TAG, "Unable to open content URL: " + uri, e);
}
return stream;
}
private static int getFieldId(Context context, String assetType, String assetName)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class<?> d = context.getClassLoader()
.loadClass(context.getPackageName() + ".R$" + assetType);
java.lang.reflect.Field field = d.getField(assetName);
int id = field.getInt(null);
return id;
}
private static int getValueType(Context context, int fieldId) {
TypedValue value = new TypedValue();
context.getResources().getValue(fieldId, value, true);
return value.type;
}
}
package org.apache.cordova.x5engine;
import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public class UriMatcher {
/**
* Creates the root node of the URI tree.
*
* @param code the code to match for the root URI
*/
public UriMatcher(Object code) {
mCode = code;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
private UriMatcher() {
mCode = null;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
/**
* Add a URI to match, and the code to return when this URI is
* matched. URI nodes may be exact match string, the token "*"
* that matches any text, or the token "#" that matches only
* numbers.
* <p>
* Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
* this method will accept a leading slash in the path.
*
* @param authority the authority to match
* @param path the path to match. * may be used as a wild card for
* any text, and # may be used as a wild card for numbers.
* @param code the code that is returned when a URI is matched
* against the given components. Must be positive.
*/
public void addURI(String scheme, String authority, String path, Object code) {
if (code == null) {
throw new IllegalArgumentException("Code can't be null");
}
String[] tokens = null;
if (path != null) {
String newPath = path;
// Strip leading slash if present.
if (path.length() > 0 && path.charAt(0) == '/') {
newPath = path.substring(1);
}
tokens = PATH_SPLIT_PATTERN.split(newPath);
}
int numTokens = tokens != null ? tokens.length : 0;
UriMatcher node = this;
for (int i = -2; i < numTokens; i++) {
String token;
if (i == -2)
token = scheme;
else if (i == -1)
token = authority;
else
token = tokens[i];
ArrayList<UriMatcher> children = node.mChildren;
int numChildren = children.size();
UriMatcher child;
int j;
for (j = 0; j < numChildren; j++) {
child = children.get(j);
if (token.equals(child.mText)) {
node = child;
break;
}
}
if (j == numChildren) {
// Child not found, create it
child = new UriMatcher();
if (token.equals("**")) {
child.mWhich = REST;
} else if (token.equals("*")) {
child.mWhich = TEXT;
} else {
child.mWhich = EXACT;
}
child.mText = token;
node.mChildren.add(child);
node = child;
}
}
node.mCode = code;
}
static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/");
/**
* Try to match against the path in a url.
*
* @param uri The url whose path we will match against.
* @return The code for the matched node (added using addURI),
* or null if there is no matched node.
*/
public Object match(Uri uri) {
final List<String> pathSegments = uri.getPathSegments();
final int li = pathSegments.size();
UriMatcher node = this;
if (li == 0 && uri.getAuthority() == null) {
return this.mCode;
}
for (int i = -2; i < li; i++) {
String u;
if (i == -2)
u = uri.getScheme();
else if (i == -1)
u = uri.getAuthority();
else
u = pathSegments.get(i);
ArrayList<UriMatcher> list = node.mChildren;
if (list == null) {
break;
}
node = null;
int lj = list.size();
for (int j = 0; j < lj; j++) {
UriMatcher n = list.get(j);
which_switch:
switch (n.mWhich) {
case EXACT:
if (n.mText.equals(u)) {
node = n;
}
break;
case TEXT:
node = n;
break;
case REST:
return n.mCode;
}
if (node != null) {
break;
}
}
if (node == null) {
return null;
}
}
return node.mCode;
}
private static final int EXACT = 0;
private static final int TEXT = 1;
private static final int REST = 2;
private Object mCode;
private int mWhich;
private String mText;
private ArrayList<UriMatcher> mChildren;
}
...@@ -24,6 +24,7 @@ import com.tencent.smtt.sdk.WebChromeClient; ...@@ -24,6 +24,7 @@ import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebView; import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient; import com.tencent.smtt.sdk.WebViewClient;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine; import org.apache.cordova.CordovaWebViewEngine;
...@@ -56,6 +57,35 @@ public class X5WebView extends WebView implements CordovaWebViewEngine.EngineVie ...@@ -56,6 +57,35 @@ public class X5WebView extends WebView implements CordovaWebViewEngine.EngineVie
} }
} }
void initWithLocalServer(X5WebViewEngine parentEngine,
CordovaInterface cordova ,
ConfigXmlParser parser,
X5WebViewLocalServer server,
String CDV_LOCAL_SERVER_REF){
//init the webview with server
this.cordova = cordova;
this.parentEngine = parentEngine;
if (this.viewClient == null){
setWebViewClient(
new X5WebViewClient(
parentEngine ,
parser ,
server ,
CDV_LOCAL_SERVER_REF
)
);
}
if (this.chromeClient == null) {
setWebChromeClient(new X5WebChromeClient(parentEngine));
}
}
@Override @Override
public CordovaWebView getCordovaWebView() { public CordovaWebView getCordovaWebView() {
return parentEngine != null ? parentEngine.getCordovaWebView() : null; return parentEngine != null ? parentEngine.getCordovaWebView() : null;
......
...@@ -34,6 +34,7 @@ import com.tencent.smtt.sdk.WebSettings; ...@@ -34,6 +34,7 @@ import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm; import com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm;
import com.tencent.smtt.sdk.WebView; import com.tencent.smtt.sdk.WebView;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaBridge; import org.apache.cordova.CordovaBridge;
import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPreferences; import org.apache.cordova.CordovaPreferences;
...@@ -72,6 +73,12 @@ public class X5WebViewEngine implements CordovaWebViewEngine { ...@@ -72,6 +73,12 @@ public class X5WebViewEngine implements CordovaWebViewEngine {
protected NativeToJsMessageQueue nativeToJsMessageQueue; protected NativeToJsMessageQueue nativeToJsMessageQueue;
private BroadcastReceiver receiver; private BroadcastReceiver receiver;
private String CDV_LOCAL_SERVER;
private X5WebViewLocalServer localServer;
/** Used when created via reflection. */ /** Used when created via reflection. */
public X5WebViewEngine(Context context, CordovaPreferences preferences) { public X5WebViewEngine(Context context, CordovaPreferences preferences) {
this(new X5WebView(context), preferences); this(new X5WebView(context), preferences);
...@@ -91,6 +98,19 @@ public class X5WebViewEngine implements CordovaWebViewEngine { ...@@ -91,6 +98,19 @@ public class X5WebViewEngine implements CordovaWebViewEngine {
public void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client, public void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client,
CordovaResourceApi resourceApi, PluginManager pluginManager, CordovaResourceApi resourceApi, PluginManager pluginManager,
NativeToJsMessageQueue nativeToJsMessageQueue) { NativeToJsMessageQueue nativeToJsMessageQueue) {
// init the local servr
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(cordova.getActivity());
String hostname = preferences.getString("Hostname", "localhost");
String scheme = preferences.getString("Scheme", "http");
CDV_LOCAL_SERVER = scheme + "://" + hostname;
Context corAct = cordova.getActivity();
localServer = new X5WebViewLocalServer(corAct, hostname, true, parser, scheme);
localServer.hostAssets("www");
if (this.cordova != null) { if (this.cordova != null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
...@@ -104,7 +124,12 @@ public class X5WebViewEngine implements CordovaWebViewEngine { ...@@ -104,7 +124,12 @@ public class X5WebViewEngine implements CordovaWebViewEngine {
this.resourceApi = resourceApi; this.resourceApi = resourceApi;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
this.nativeToJsMessageQueue = nativeToJsMessageQueue; this.nativeToJsMessageQueue = nativeToJsMessageQueue;
webView.init(this, cordova);
//加载服务器
//webView.init(this, cordova);
webView.initWithLocalServer(this , cordova , parser , localServer , CDV_LOCAL_SERVER);
initWebViewSettings(); initWebViewSettings();
...@@ -149,6 +174,22 @@ public class X5WebViewEngine implements CordovaWebViewEngine { ...@@ -149,6 +174,22 @@ public class X5WebViewEngine implements CordovaWebViewEngine {
settings.setJavaScriptEnabled(true); settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
//We don't save any form data in the application
settings.setSaveFormData(false);
settings.setSavePassword(false);
// Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
// while we do this
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setMediaPlaybackRequiresUserGesture(false);
// Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2) // Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
try { try {
...@@ -183,6 +224,8 @@ public class X5WebViewEngine implements CordovaWebViewEngine { ...@@ -183,6 +224,8 @@ public class X5WebViewEngine implements CordovaWebViewEngine {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
settings.setMediaPlaybackRequiresUserGesture(false); settings.setMediaPlaybackRequiresUserGesture(false);
} }
// Enable database // Enable database
// We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16 // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
String databasePath = webView.getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); String databasePath = webView.getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment