| @@ -0,0 +1,69 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| /** | ||
| * The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource | ||
| */ | ||
| public class AuthenticationToken { | ||
| private String userName; | ||
| private String password; | ||
|
|
||
| /** | ||
| * Gets the user name. | ||
| * | ||
| * @return the user name | ||
| */ | ||
| public String getUserName() { | ||
| return userName; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the user name. | ||
| * | ||
| * @param userName | ||
| * the new user name | ||
| */ | ||
| public void setUserName(String userName) { | ||
| this.userName = userName; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the password. | ||
| * | ||
| * @return the password | ||
| */ | ||
| public String getPassword() { | ||
| return password; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the password. | ||
| * | ||
| * @param password | ||
| * the new password | ||
| */ | ||
| public void setPassword(String password) { | ||
| this.password = password; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| } |
| @@ -0,0 +1,144 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import org.json.JSONArray; | ||
|
|
||
| import android.util.Log; | ||
|
|
||
| import org.apache.cordova.CordovaWebView; | ||
| import org.apache.cordova.PluginResult; | ||
| import org.json.JSONObject; | ||
|
|
||
| public class CallbackContext { | ||
| private static final String LOG_TAG = "CordovaPlugin"; | ||
|
|
||
| private String callbackId; | ||
| private CordovaWebView webView; | ||
| protected boolean finished; | ||
| private int changingThreads; | ||
|
|
||
| public CallbackContext(String callbackId, CordovaWebView webView) { | ||
| this.callbackId = callbackId; | ||
| this.webView = webView; | ||
| } | ||
|
|
||
| public boolean isFinished() { | ||
| return finished; | ||
| } | ||
|
|
||
| public boolean isChangingThreads() { | ||
| return changingThreads > 0; | ||
| } | ||
|
|
||
| public String getCallbackId() { | ||
| return callbackId; | ||
| } | ||
|
|
||
| public void sendPluginResult(PluginResult pluginResult) { | ||
| synchronized (this) { | ||
| if (finished) { | ||
| Log.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage()); | ||
| return; | ||
| } else { | ||
| finished = !pluginResult.getKeepCallback(); | ||
| } | ||
| } | ||
| webView.sendPluginResult(pluginResult, callbackId); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| * | ||
| * @param message The message to add to the success result. | ||
| */ | ||
| public void success(JSONObject message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| * | ||
| * @param message The message to add to the success result. | ||
| */ | ||
| public void success(String message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| * | ||
| * @param message The message to add to the success result. | ||
| */ | ||
| public void success(JSONArray message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| * | ||
| * @param message The message to add to the success result. | ||
| */ | ||
| public void success(byte[] message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| * | ||
| * @param message The message to add to the success result. | ||
| */ | ||
| public void success(int message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for success callbacks that just returns the Status.OK by default | ||
| */ | ||
| public void success() { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.OK)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for error callbacks that just returns the Status.ERROR by default | ||
| * | ||
| * @param message The message to add to the error result. | ||
| */ | ||
| public void error(JSONObject message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for error callbacks that just returns the Status.ERROR by default | ||
| * | ||
| * @param message The message to add to the error result. | ||
| */ | ||
| public void error(String message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message)); | ||
| } | ||
|
|
||
| /** | ||
| * Helper for error callbacks that just returns the Status.ERROR by default | ||
| * | ||
| * @param message The message to add to the error result. | ||
| */ | ||
| public void error(int message) { | ||
| sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message)); | ||
| } | ||
| } |
| @@ -0,0 +1,72 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import android.app.Activity; | ||
| import android.util.Log; | ||
|
|
||
| @Deprecated // Use Whitelist, CordovaPrefences, etc. directly. | ||
| public class Config { | ||
| private static final String TAG = "Config"; | ||
|
|
||
| static ConfigXmlParser parser; | ||
|
|
||
| private Config() { | ||
| } | ||
|
|
||
| public static void init(Activity action) { | ||
| parser = new ConfigXmlParser(); | ||
| parser.parse(action); | ||
| //TODO: Add feature to bring this back. Some preferences should be overridden by intents, but not all | ||
| parser.getPreferences().setPreferencesBundle(action.getIntent().getExtras()); | ||
| } | ||
|
|
||
| // Intended to be used for testing only; creates an empty configuration. | ||
| public static void init() { | ||
| if (parser == null) { | ||
| parser = new ConfigXmlParser(); | ||
| } | ||
| } | ||
|
|
||
| public static String getStartUrl() { | ||
| if (parser == null) { | ||
| return "file:///android_asset/www/index.html"; | ||
| } | ||
| return parser.getLaunchUrl(); | ||
| } | ||
|
|
||
| public static String getErrorUrl() { | ||
| return parser.getPreferences().getString("errorurl", null); | ||
| } | ||
|
|
||
| public static List<PluginEntry> getPluginEntries() { | ||
| return parser.getPluginEntries(); | ||
| } | ||
|
|
||
| public static CordovaPreferences getPreferences() { | ||
| return parser.getPreferences(); | ||
| } | ||
|
|
||
| public static boolean isInitialized() { | ||
| return parser != null; | ||
| } | ||
| } |
| @@ -0,0 +1,145 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.ArrayList; | ||
| import java.util.Locale; | ||
| import java.util.regex.Matcher; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| import org.xmlpull.v1.XmlPullParser; | ||
| import org.xmlpull.v1.XmlPullParserException; | ||
|
|
||
| import android.content.Context; | ||
|
|
||
| public class ConfigXmlParser { | ||
| private static String TAG = "ConfigXmlParser"; | ||
|
|
||
| private String launchUrl = "file:///android_asset/www/index.html"; | ||
| private CordovaPreferences prefs = new CordovaPreferences(); | ||
| private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20); | ||
|
|
||
| public CordovaPreferences getPreferences() { | ||
| return prefs; | ||
| } | ||
|
|
||
| public ArrayList<PluginEntry> getPluginEntries() { | ||
| return pluginEntries; | ||
| } | ||
|
|
||
| public String getLaunchUrl() { | ||
| return launchUrl; | ||
| } | ||
|
|
||
| public void parse(Context action) { | ||
| // First checking the class namespace for config.xml | ||
| int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName()); | ||
| if (id == 0) { | ||
| // If we couldn't find config.xml there, we'll look in the namespace from AndroidManifest.xml | ||
| id = action.getResources().getIdentifier("config", "xml", action.getPackageName()); | ||
| if (id == 0) { | ||
| LOG.e(TAG, "res/xml/config.xml is missing!"); | ||
| return; | ||
| } | ||
| } | ||
| parse(action.getResources().getXml(id)); | ||
| } | ||
|
|
||
| boolean insideFeature = false; | ||
| String service = "", pluginClass = "", paramType = ""; | ||
| boolean onload = false; | ||
|
|
||
| public void parse(XmlPullParser xml) { | ||
| int eventType = -1; | ||
|
|
||
| while (eventType != XmlPullParser.END_DOCUMENT) { | ||
| if (eventType == XmlPullParser.START_TAG) { | ||
| handleStartTag(xml); | ||
| } | ||
| else if (eventType == XmlPullParser.END_TAG) | ||
| { | ||
| handleEndTag(xml); | ||
| } | ||
| try { | ||
| eventType = xml.next(); | ||
| } catch (XmlPullParserException e) { | ||
| e.printStackTrace(); | ||
| } catch (IOException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public void handleStartTag(XmlPullParser xml) { | ||
| String strNode = xml.getName(); | ||
| if (strNode.equals("feature")) { | ||
| //Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc) | ||
| //Set the bit for reading params | ||
| insideFeature = true; | ||
| service = xml.getAttributeValue(null, "name"); | ||
| } | ||
| else if (insideFeature && strNode.equals("param")) { | ||
| paramType = xml.getAttributeValue(null, "name"); | ||
| if (paramType.equals("service")) // check if it is using the older service param | ||
| service = xml.getAttributeValue(null, "value"); | ||
| else if (paramType.equals("package") || paramType.equals("android-package")) | ||
| pluginClass = xml.getAttributeValue(null,"value"); | ||
| else if (paramType.equals("onload")) | ||
| onload = "true".equals(xml.getAttributeValue(null, "value")); | ||
| } | ||
| else if (strNode.equals("preference")) { | ||
| String name = xml.getAttributeValue(null, "name").toLowerCase(Locale.ENGLISH); | ||
| String value = xml.getAttributeValue(null, "value"); | ||
| prefs.set(name, value); | ||
| } | ||
| else if (strNode.equals("content")) { | ||
| String src = xml.getAttributeValue(null, "src"); | ||
| if (src != null) { | ||
| setStartUrl(src); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public void handleEndTag(XmlPullParser xml) { | ||
| String strNode = xml.getName(); | ||
| if (strNode.equals("feature")) { | ||
| pluginEntries.add(new PluginEntry(service, pluginClass, onload)); | ||
|
|
||
| service = ""; | ||
| pluginClass = ""; | ||
| insideFeature = false; | ||
| onload = false; | ||
| } | ||
| } | ||
|
|
||
| private void setStartUrl(String src) { | ||
| Pattern schemeRegex = Pattern.compile("^[a-z-]+://"); | ||
| Matcher matcher = schemeRegex.matcher(src); | ||
| if (matcher.find()) { | ||
| launchUrl = src; | ||
| } else { | ||
| if (src.charAt(0) == '/') { | ||
| src = src.substring(1); | ||
| } | ||
| launchUrl = "file:///android_asset/www/" + src; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,113 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import org.json.JSONArray; | ||
| import org.json.JSONException; | ||
| import org.json.JSONObject; | ||
|
|
||
| import android.util.Base64; | ||
|
|
||
| public class CordovaArgs { | ||
| private JSONArray baseArgs; | ||
|
|
||
| public CordovaArgs(JSONArray args) { | ||
| this.baseArgs = args; | ||
| } | ||
|
|
||
|
|
||
| // Pass through the basics to the base args. | ||
| public Object get(int index) throws JSONException { | ||
| return baseArgs.get(index); | ||
| } | ||
|
|
||
| public boolean getBoolean(int index) throws JSONException { | ||
| return baseArgs.getBoolean(index); | ||
| } | ||
|
|
||
| public double getDouble(int index) throws JSONException { | ||
| return baseArgs.getDouble(index); | ||
| } | ||
|
|
||
| public int getInt(int index) throws JSONException { | ||
| return baseArgs.getInt(index); | ||
| } | ||
|
|
||
| public JSONArray getJSONArray(int index) throws JSONException { | ||
| return baseArgs.getJSONArray(index); | ||
| } | ||
|
|
||
| public JSONObject getJSONObject(int index) throws JSONException { | ||
| return baseArgs.getJSONObject(index); | ||
| } | ||
|
|
||
| public long getLong(int index) throws JSONException { | ||
| return baseArgs.getLong(index); | ||
| } | ||
|
|
||
| public String getString(int index) throws JSONException { | ||
| return baseArgs.getString(index); | ||
| } | ||
|
|
||
|
|
||
| public Object opt(int index) { | ||
| return baseArgs.opt(index); | ||
| } | ||
|
|
||
| public boolean optBoolean(int index) { | ||
| return baseArgs.optBoolean(index); | ||
| } | ||
|
|
||
| public double optDouble(int index) { | ||
| return baseArgs.optDouble(index); | ||
| } | ||
|
|
||
| public int optInt(int index) { | ||
| return baseArgs.optInt(index); | ||
| } | ||
|
|
||
| public JSONArray optJSONArray(int index) { | ||
| return baseArgs.optJSONArray(index); | ||
| } | ||
|
|
||
| public JSONObject optJSONObject(int index) { | ||
| return baseArgs.optJSONObject(index); | ||
| } | ||
|
|
||
| public long optLong(int index) { | ||
| return baseArgs.optLong(index); | ||
| } | ||
|
|
||
| public String optString(int index) { | ||
| return baseArgs.optString(index); | ||
| } | ||
|
|
||
| public boolean isNull(int index) { | ||
| return baseArgs.isNull(index); | ||
| } | ||
|
|
||
|
|
||
| // The interesting custom helpers. | ||
| public byte[] getArrayBuffer(int index) throws JSONException { | ||
| String encoded = baseArgs.getString(index); | ||
| return Base64.decode(encoded, Base64.DEFAULT); | ||
| } | ||
| } | ||
|
|
||
|
|
| @@ -0,0 +1,184 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import java.security.SecureRandom; | ||
|
|
||
| import org.json.JSONArray; | ||
| import org.json.JSONException; | ||
|
|
||
| import android.util.Log; | ||
|
|
||
| /** | ||
| * Contains APIs that the JS can call. All functions in here should also have | ||
| * an equivalent entry in CordovaChromeClient.java, and be added to | ||
| * cordova-js/lib/android/plugin/android/promptbasednativeapi.js | ||
| */ | ||
| public class CordovaBridge { | ||
| private static final String LOG_TAG = "CordovaBridge"; | ||
| private PluginManager pluginManager; | ||
| private NativeToJsMessageQueue jsMessageQueue; | ||
| private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread. | ||
|
|
||
| public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) { | ||
| this.pluginManager = pluginManager; | ||
| this.jsMessageQueue = jsMessageQueue; | ||
| } | ||
|
|
||
| public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException { | ||
| if (!verifySecret("exec()", bridgeSecret)) { | ||
| return null; | ||
| } | ||
| // If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666. | ||
| // We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string. | ||
| if (arguments == null) { | ||
| return "@Null arguments."; | ||
| } | ||
|
|
||
| jsMessageQueue.setPaused(true); | ||
| try { | ||
| // Tell the resourceApi what thread the JS is running on. | ||
| CordovaResourceApi.jsThread = Thread.currentThread(); | ||
|
|
||
| pluginManager.exec(service, action, callbackId, arguments); | ||
| String ret = null; | ||
| if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) { | ||
| ret = jsMessageQueue.popAndEncode(false); | ||
| } | ||
| return ret; | ||
| } catch (Throwable e) { | ||
| e.printStackTrace(); | ||
| return ""; | ||
| } finally { | ||
| jsMessageQueue.setPaused(false); | ||
| } | ||
| } | ||
|
|
||
| public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException { | ||
| if (!verifySecret("setNativeToJsBridgeMode()", bridgeSecret)) { | ||
| return; | ||
| } | ||
| jsMessageQueue.setBridgeMode(value); | ||
| } | ||
|
|
||
| public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException { | ||
| if (!verifySecret("retrieveJsMessages()", bridgeSecret)) { | ||
| return null; | ||
| } | ||
| return jsMessageQueue.popAndEncode(fromOnlineEvent); | ||
| } | ||
|
|
||
| private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException { | ||
| if (!jsMessageQueue.isBridgeEnabled()) { | ||
| if (bridgeSecret == -1) { | ||
| Log.d(LOG_TAG, action + " call made before bridge was enabled."); | ||
| } else { | ||
| Log.d(LOG_TAG, "Ignoring " + action + " from previous page load."); | ||
| } | ||
| return false; | ||
| } | ||
| // Bridge secret wrong and bridge not due to it being from the previous page. | ||
| if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) { | ||
| Log.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!"); | ||
| clearBridgeSecret(); | ||
| throw new IllegalAccessException(); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** Called on page transitions */ | ||
| void clearBridgeSecret() { | ||
| expectedBridgeSecret = -1; | ||
| } | ||
|
|
||
| public boolean isSecretEstablished() { | ||
| return expectedBridgeSecret != -1; | ||
| } | ||
|
|
||
| /** Called by cordova.js to initialize the bridge. */ | ||
| int generateBridgeSecret() { | ||
| SecureRandom randGen = new SecureRandom(); | ||
| expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE); | ||
| return expectedBridgeSecret; | ||
| } | ||
|
|
||
| public void reset() { | ||
| jsMessageQueue.reset(); | ||
| clearBridgeSecret(); | ||
| } | ||
|
|
||
| public String promptOnJsPrompt(String origin, String message, String defaultValue) { | ||
| if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) { | ||
| JSONArray array; | ||
| try { | ||
| array = new JSONArray(defaultValue.substring(4)); | ||
| int bridgeSecret = array.getInt(0); | ||
| String service = array.getString(1); | ||
| String action = array.getString(2); | ||
| String callbackId = array.getString(3); | ||
| String r = jsExec(bridgeSecret, service, action, callbackId, message); | ||
| return r == null ? "" : r; | ||
| } catch (JSONException e) { | ||
| e.printStackTrace(); | ||
| } catch (IllegalAccessException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return ""; | ||
| } | ||
| // Sets the native->JS bridge mode. | ||
| else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) { | ||
| try { | ||
| int bridgeSecret = Integer.parseInt(defaultValue.substring(16)); | ||
| jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message)); | ||
| } catch (NumberFormatException e){ | ||
| e.printStackTrace(); | ||
| } catch (IllegalAccessException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return ""; | ||
| } | ||
| // Polling for JavaScript messages | ||
| else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) { | ||
| int bridgeSecret = Integer.parseInt(defaultValue.substring(9)); | ||
| try { | ||
| String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message)); | ||
| return r == null ? "" : r; | ||
| } catch (IllegalAccessException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return ""; | ||
| } | ||
| else if (defaultValue != null && defaultValue.startsWith("gap_init:")) { | ||
| // Protect against random iframes being able to talk through the bridge. | ||
| // Trust only pages which the app would have been allowed to navigate to anyway. | ||
| if (pluginManager.shouldAllowBridgeAccess(origin)) { | ||
| // Enable the bridge | ||
| int bridgeMode = Integer.parseInt(defaultValue.substring(9)); | ||
| jsMessageQueue.setBridgeMode(bridgeMode); | ||
| // Tell JS the bridge secret. | ||
| int secret = generateBridgeSecret(); | ||
| return ""+secret; | ||
| } else { | ||
| Log.e(LOG_TAG, "gap_init called from restricted origin: " + origin); | ||
| } | ||
| return ""; | ||
| } | ||
| return null; | ||
| } | ||
| } |
| @@ -0,0 +1,96 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import java.security.Principal; | ||
| import java.security.PrivateKey; | ||
| import java.security.cert.X509Certificate; | ||
|
|
||
| import android.webkit.ClientCertRequest; | ||
|
|
||
| /** | ||
| * Implementation of the ICordovaClientCertRequest for Android WebView. | ||
| */ | ||
| public class CordovaClientCertRequest implements ICordovaClientCertRequest { | ||
|
|
||
| private final ClientCertRequest request; | ||
|
|
||
| public CordovaClientCertRequest(ClientCertRequest request) { | ||
| this.request = request; | ||
| } | ||
|
|
||
| /** | ||
| * Cancel this request | ||
| */ | ||
| public void cancel() | ||
| { | ||
| request.cancel(); | ||
| } | ||
|
|
||
| /* | ||
| * Returns the host name of the server requesting the certificate. | ||
| */ | ||
| public String getHost() | ||
| { | ||
| return request.getHost(); | ||
| } | ||
|
|
||
| /* | ||
| * Returns the acceptable types of asymmetric keys (can be null). | ||
| */ | ||
| public String[] getKeyTypes() | ||
| { | ||
| return request.getKeyTypes(); | ||
| } | ||
|
|
||
| /* | ||
| * Returns the port number of the server requesting the certificate. | ||
| */ | ||
| public int getPort() | ||
| { | ||
| return request.getPort(); | ||
| } | ||
|
|
||
| /* | ||
| * Returns the acceptable certificate issuers for the certificate matching the private key (can be null). | ||
| */ | ||
| public Principal[] getPrincipals() | ||
| { | ||
| return request.getPrincipals(); | ||
| } | ||
|
|
||
| /* | ||
| * Ignore the request for now. Do not remember user's choice. | ||
| */ | ||
| public void ignore() | ||
| { | ||
| request.ignore(); | ||
| } | ||
|
|
||
| /* | ||
| * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests. | ||
| * | ||
| * @param privateKey The privateKey | ||
| * @param chain The certificate chain | ||
| */ | ||
| public void proceed(PrivateKey privateKey, X509Certificate[] chain) | ||
| { | ||
| request.proceed(privateKey, chain); | ||
| } | ||
| } |
| @@ -0,0 +1,152 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import android.app.AlertDialog; | ||
| import android.content.Context; | ||
| import android.content.DialogInterface; | ||
| import android.view.KeyEvent; | ||
| import android.widget.EditText; | ||
|
|
||
| /** | ||
| * Helper class for WebViews to implement prompt(), alert(), confirm() dialogs. | ||
| */ | ||
| public class CordovaDialogsHelper { | ||
| private final Context context; | ||
| private AlertDialog lastHandledDialog; | ||
|
|
||
| public CordovaDialogsHelper(Context context) { | ||
| this.context = context; | ||
| } | ||
|
|
||
| public void showAlert(String message, final Result result) { | ||
| AlertDialog.Builder dlg = new AlertDialog.Builder(context); | ||
| dlg.setMessage(message); | ||
| dlg.setTitle("Alert"); | ||
| //Don't let alerts break the back button | ||
| dlg.setCancelable(true); | ||
| dlg.setPositiveButton(android.R.string.ok, | ||
| new AlertDialog.OnClickListener() { | ||
| public void onClick(DialogInterface dialog, int which) { | ||
| result.gotResult(true, null); | ||
| } | ||
| }); | ||
| dlg.setOnCancelListener( | ||
| new DialogInterface.OnCancelListener() { | ||
| public void onCancel(DialogInterface dialog) { | ||
| result.gotResult(false, null); | ||
| } | ||
| }); | ||
| dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { | ||
| //DO NOTHING | ||
| public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { | ||
| if (keyCode == KeyEvent.KEYCODE_BACK) | ||
| { | ||
| result.gotResult(true, null); | ||
| return false; | ||
| } | ||
| else | ||
| return true; | ||
| } | ||
| }); | ||
| lastHandledDialog = dlg.show(); | ||
| } | ||
|
|
||
| public void showConfirm(String message, final Result result) { | ||
| AlertDialog.Builder dlg = new AlertDialog.Builder(context); | ||
| dlg.setMessage(message); | ||
| dlg.setTitle("Confirm"); | ||
| dlg.setCancelable(true); | ||
| dlg.setPositiveButton(android.R.string.ok, | ||
| new DialogInterface.OnClickListener() { | ||
| public void onClick(DialogInterface dialog, int which) { | ||
| result.gotResult(true, null); | ||
| } | ||
| }); | ||
| dlg.setNegativeButton(android.R.string.cancel, | ||
| new DialogInterface.OnClickListener() { | ||
| public void onClick(DialogInterface dialog, int which) { | ||
| result.gotResult(false, null); | ||
| } | ||
| }); | ||
| dlg.setOnCancelListener( | ||
| new DialogInterface.OnCancelListener() { | ||
| public void onCancel(DialogInterface dialog) { | ||
| result.gotResult(false, null); | ||
| } | ||
| }); | ||
| dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { | ||
| //DO NOTHING | ||
| public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { | ||
| if (keyCode == KeyEvent.KEYCODE_BACK) | ||
| { | ||
| result.gotResult(false, null); | ||
| return false; | ||
| } | ||
| else | ||
| return true; | ||
| } | ||
| }); | ||
| lastHandledDialog = dlg.show(); | ||
| } | ||
|
|
||
| /** | ||
| * Tell the client to display a prompt dialog to the user. | ||
| * If the client returns true, WebView will assume that the client will | ||
| * handle the prompt dialog and call the appropriate JsPromptResult method. | ||
| * | ||
| * Since we are hacking prompts for our own purposes, we should not be using them for | ||
| * this purpose, perhaps we should hack console.log to do this instead! | ||
| */ | ||
| public void showPrompt(String message, String defaultValue, final Result result) { | ||
| // Returning false would also show a dialog, but the default one shows the origin (ugly). | ||
| AlertDialog.Builder dlg = new AlertDialog.Builder(context); | ||
| dlg.setMessage(message); | ||
| final EditText input = new EditText(context); | ||
| if (defaultValue != null) { | ||
| input.setText(defaultValue); | ||
| } | ||
| dlg.setView(input); | ||
| dlg.setCancelable(false); | ||
| dlg.setPositiveButton(android.R.string.ok, | ||
| new DialogInterface.OnClickListener() { | ||
| public void onClick(DialogInterface dialog, int which) { | ||
| String userText = input.getText().toString(); | ||
| result.gotResult(true, userText); | ||
| } | ||
| }); | ||
| dlg.setNegativeButton(android.R.string.cancel, | ||
| new DialogInterface.OnClickListener() { | ||
| public void onClick(DialogInterface dialog, int which) { | ||
| result.gotResult(false, null); | ||
| } | ||
| }); | ||
| lastHandledDialog = dlg.show(); | ||
| } | ||
|
|
||
| public void destroyLastDialog(){ | ||
| if (lastHandledDialog != null){ | ||
| lastHandledDialog.cancel(); | ||
| } | ||
| } | ||
|
|
||
| public interface Result { | ||
| public void gotResult(boolean success, String value); | ||
| } | ||
| } |
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import android.webkit.HttpAuthHandler; | ||
|
|
||
| /** | ||
| * Specifies interface for HTTP auth handler object which is used to handle auth requests and | ||
| * specifying user credentials. | ||
| */ | ||
| public class CordovaHttpAuthHandler implements ICordovaHttpAuthHandler { | ||
|
|
||
| private final HttpAuthHandler handler; | ||
|
|
||
| public CordovaHttpAuthHandler(HttpAuthHandler handler) { | ||
| this.handler = handler; | ||
| } | ||
|
|
||
| /** | ||
| * Instructs the WebView to cancel the authentication request. | ||
| */ | ||
| public void cancel () { | ||
| this.handler.cancel(); | ||
| } | ||
|
|
||
| /** | ||
| * Instructs the WebView to proceed with the authentication with the given credentials. | ||
| * | ||
| * @param username | ||
| * @param password | ||
| */ | ||
| public void proceed (String username, String password) { | ||
| this.handler.proceed(username, password); | ||
| } | ||
| } |
| @@ -0,0 +1,88 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import android.app.Activity; | ||
| import android.content.Intent; | ||
|
|
||
| import org.apache.cordova.CordovaPlugin; | ||
|
|
||
| import java.util.concurrent.ExecutorService; | ||
|
|
||
| /** | ||
| * The Activity interface that is implemented by CordovaActivity. | ||
| * It is used to isolate plugin development, and remove dependency on entire Cordova library. | ||
| */ | ||
| public interface CordovaInterface { | ||
|
|
||
| /** | ||
| * Launch an activity for which you would like a result when it finished. When this activity exits, | ||
| * your onActivityResult() method will be called. | ||
| * | ||
| * @param command The command object | ||
| * @param intent The intent to start | ||
| * @param requestCode The request code that is passed to callback to identify the activity | ||
| */ | ||
| abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode); | ||
|
|
||
| /** | ||
| * Set the plugin to be called when a sub-activity exits. | ||
| * | ||
| * @param plugin The plugin on which onActivityResult is to be called | ||
| */ | ||
| abstract public void setActivityResultCallback(CordovaPlugin plugin); | ||
|
|
||
| /** | ||
| * Get the Android activity. | ||
| * | ||
| * @return the Activity | ||
| */ | ||
| public abstract Activity getActivity(); | ||
|
|
||
|
|
||
| /** | ||
| * Called when a message is sent to plugin. | ||
| * | ||
| * @param id The message id | ||
| * @param data The message data | ||
| * @return Object or null | ||
| */ | ||
| public Object onMessage(String id, Object data); | ||
|
|
||
| /** | ||
| * Returns a shared thread pool that can be used for background tasks. | ||
| */ | ||
| public ExecutorService getThreadPool(); | ||
|
|
||
| /** | ||
| * Sends a permission request to the activity for one permission. | ||
| */ | ||
| public void requestPermission(CordovaPlugin plugin, int requestCode, String permission); | ||
|
|
||
| /** | ||
| * Sends a permission request to the activity for a group of permissions | ||
| */ | ||
| public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions); | ||
|
|
||
| /** | ||
| * Check for a permission. Returns true if the permission is granted, false otherwise. | ||
| */ | ||
| public boolean hasPermission(String permission); | ||
|
|
||
| } |
| @@ -0,0 +1,238 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import android.app.Activity; | ||
| import android.content.Intent; | ||
| import android.content.pm.PackageManager; | ||
| import android.os.Build; | ||
| import android.os.Bundle; | ||
| import android.util.Log; | ||
|
|
||
| import org.json.JSONException; | ||
| import org.json.JSONObject; | ||
|
|
||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
|
|
||
| /** | ||
| * Default implementation of CordovaInterface. | ||
| */ | ||
| public class CordovaInterfaceImpl implements CordovaInterface { | ||
| private static final String TAG = "CordovaInterfaceImpl"; | ||
| protected Activity activity; | ||
| protected ExecutorService threadPool; | ||
| protected PluginManager pluginManager; | ||
|
|
||
| protected ActivityResultHolder savedResult; | ||
| protected CordovaPlugin activityResultCallback; | ||
| protected CordovaPlugin permissionResultCallback; | ||
| protected String initCallbackService; | ||
| protected int activityResultRequestCode; | ||
| protected boolean activityWasDestroyed = false; | ||
| protected Bundle savedPluginState; | ||
|
|
||
| public CordovaInterfaceImpl(Activity activity) { | ||
| this(activity, Executors.newCachedThreadPool()); | ||
| } | ||
|
|
||
| public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) { | ||
| this.activity = activity; | ||
| this.threadPool = threadPool; | ||
| } | ||
|
|
||
| @Override | ||
| public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) { | ||
| setActivityResultCallback(command); | ||
| try { | ||
| activity.startActivityForResult(intent, requestCode); | ||
| } catch (RuntimeException e) { // E.g.: ActivityNotFoundException | ||
| activityResultCallback = null; | ||
| throw e; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void setActivityResultCallback(CordovaPlugin plugin) { | ||
| // Cancel any previously pending activity. | ||
| if (activityResultCallback != null) { | ||
| activityResultCallback.onActivityResult(activityResultRequestCode, Activity.RESULT_CANCELED, null); | ||
| } | ||
| activityResultCallback = plugin; | ||
| } | ||
|
|
||
| @Override | ||
| public Activity getActivity() { | ||
| return activity; | ||
| } | ||
|
|
||
| @Override | ||
| public Object onMessage(String id, Object data) { | ||
| if ("exit".equals(id)) { | ||
| activity.finish(); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public ExecutorService getThreadPool() { | ||
| return threadPool; | ||
| } | ||
|
|
||
| /** | ||
| * Dispatches any pending onActivityResult callbacks and sends the resume event if the | ||
| * Activity was destroyed by the OS. | ||
| */ | ||
| public void onCordovaInit(PluginManager pluginManager) { | ||
| this.pluginManager = pluginManager; | ||
| if (savedResult != null) { | ||
| onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent); | ||
| } else if(activityWasDestroyed) { | ||
| // If there was no Activity result, we still need to send out the resume event if the | ||
| // Activity was destroyed by the OS | ||
| activityWasDestroyed = false; | ||
|
|
||
| CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME); | ||
| if(appPlugin != null) { | ||
| JSONObject obj = new JSONObject(); | ||
| try { | ||
| obj.put("action", "resume"); | ||
| } catch (JSONException e) { | ||
| LOG.e(TAG, "Failed to create event message", e); | ||
| } | ||
| appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, obj)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Routes the result to the awaiting plugin. Returns false if no plugin was waiting. | ||
| */ | ||
| public boolean onActivityResult(int requestCode, int resultCode, Intent intent) { | ||
| CordovaPlugin callback = activityResultCallback; | ||
| if(callback == null && initCallbackService != null) { | ||
| // The application was restarted, but had defined an initial callback | ||
| // before being shut down. | ||
| savedResult = new ActivityResultHolder(requestCode, resultCode, intent); | ||
| if (pluginManager != null) { | ||
| callback = pluginManager.getPlugin(initCallbackService); | ||
| if(callback != null) { | ||
| callback.onRestoreStateForActivityResult(savedPluginState.getBundle(callback.getServiceName()), | ||
| new ResumeCallback(callback.getServiceName(), pluginManager)); | ||
| } | ||
| } | ||
| } | ||
| activityResultCallback = null; | ||
|
|
||
| if (callback != null) { | ||
| Log.d(TAG, "Sending activity result to plugin"); | ||
| initCallbackService = null; | ||
| savedResult = null; | ||
| callback.onActivityResult(requestCode, resultCode, intent); | ||
| return true; | ||
| } | ||
| Log.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : ".")); | ||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Call this from your startActivityForResult() overload. This is required to catch the case | ||
| * where plugins use Activity.startActivityForResult() + CordovaInterface.setActivityResultCallback() | ||
| * rather than CordovaInterface.startActivityForResult(). | ||
| */ | ||
| public void setActivityResultRequestCode(int requestCode) { | ||
| activityResultRequestCode = requestCode; | ||
| } | ||
|
|
||
| /** | ||
| * Saves parameters for startActivityForResult(). | ||
| */ | ||
| public void onSaveInstanceState(Bundle outState) { | ||
| if (activityResultCallback != null) { | ||
| String serviceName = activityResultCallback.getServiceName(); | ||
| outState.putString("callbackService", serviceName); | ||
| } | ||
|
|
||
| outState.putBundle("plugin", pluginManager.onSaveInstanceState()); | ||
| } | ||
|
|
||
| /** | ||
| * Call this from onCreate() so that any saved startActivityForResult parameters will be restored. | ||
| */ | ||
| public void restoreInstanceState(Bundle savedInstanceState) { | ||
| initCallbackService = savedInstanceState.getString("callbackService"); | ||
| savedPluginState = savedInstanceState.getBundle("plugin"); | ||
| activityWasDestroyed = true; | ||
| } | ||
|
|
||
| private static class ActivityResultHolder { | ||
| private int requestCode; | ||
| private int resultCode; | ||
| private Intent intent; | ||
|
|
||
| public ActivityResultHolder(int requestCode, int resultCode, Intent intent) { | ||
| this.requestCode = requestCode; | ||
| this.resultCode = resultCode; | ||
| this.intent = intent; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Called by the system when the user grants permissions | ||
| * | ||
| * @param requestCode | ||
| * @param permissions | ||
| * @param grantResults | ||
| */ | ||
| public void onRequestPermissionResult(int requestCode, String[] permissions, | ||
| int[] grantResults) throws JSONException { | ||
| if(permissionResultCallback != null) | ||
| { | ||
| permissionResultCallback.onRequestPermissionResult(requestCode, permissions, grantResults); | ||
| permissionResultCallback = null; | ||
| } | ||
| } | ||
|
|
||
| public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) { | ||
| permissionResultCallback = plugin; | ||
| String[] permissions = new String [1]; | ||
| permissions[0] = permission; | ||
| getActivity().requestPermissions(permissions, requestCode); | ||
| } | ||
|
|
||
| public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) | ||
| { | ||
| permissionResultCallback = plugin; | ||
| getActivity().requestPermissions(permissions, requestCode); | ||
| } | ||
|
|
||
| public boolean hasPermission(String permission) | ||
| { | ||
| if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) | ||
| { | ||
| int result = activity.checkSelfPermission(permission); | ||
| return PackageManager.PERMISSION_GRANTED == result; | ||
| } | ||
| else | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,101 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Locale; | ||
| import java.util.Map; | ||
|
|
||
| import org.apache.cordova.LOG; | ||
|
|
||
| import android.app.Activity; | ||
| import android.os.Bundle; | ||
|
|
||
| public class CordovaPreferences { | ||
| private HashMap<String, String> prefs = new HashMap<String, String>(20); | ||
| private Bundle preferencesBundleExtras; | ||
|
|
||
| public void setPreferencesBundle(Bundle extras) { | ||
| preferencesBundleExtras = extras; | ||
| } | ||
|
|
||
| public void set(String name, String value) { | ||
| prefs.put(name.toLowerCase(Locale.ENGLISH), value); | ||
| } | ||
|
|
||
| public void set(String name, boolean value) { | ||
| set(name, "" + value); | ||
| } | ||
|
|
||
| public void set(String name, int value) { | ||
| set(name, "" + value); | ||
| } | ||
|
|
||
| public void set(String name, double value) { | ||
| set(name, "" + value); | ||
| } | ||
|
|
||
| public Map<String, String> getAll() { | ||
| return prefs; | ||
| } | ||
|
|
||
| public boolean getBoolean(String name, boolean defaultValue) { | ||
| name = name.toLowerCase(Locale.ENGLISH); | ||
| String value = prefs.get(name); | ||
| if (value != null) { | ||
| return Boolean.parseBoolean(value); | ||
| } | ||
| return defaultValue; | ||
| } | ||
|
|
||
| // Added in 4.0.0 | ||
| public boolean contains(String name) { | ||
| return getString(name, null) != null; | ||
| } | ||
|
|
||
| public int getInteger(String name, int defaultValue) { | ||
| name = name.toLowerCase(Locale.ENGLISH); | ||
| String value = prefs.get(name); | ||
| if (value != null) { | ||
| // Use Integer.decode() can't handle it if the highest bit is set. | ||
| return (int)(long)Long.decode(value); | ||
| } | ||
| return defaultValue; | ||
| } | ||
|
|
||
| public double getDouble(String name, double defaultValue) { | ||
| name = name.toLowerCase(Locale.ENGLISH); | ||
| String value = prefs.get(name); | ||
| if (value != null) { | ||
| return Double.valueOf(value); | ||
| } | ||
| return defaultValue; | ||
| } | ||
|
|
||
| public String getString(String name, String defaultValue) { | ||
| name = name.toLowerCase(Locale.ENGLISH); | ||
| String value = prefs.get(name); | ||
| if (value != null) { | ||
| return value; | ||
| } | ||
| return defaultValue; | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,142 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| import android.content.Context; | ||
| import android.content.Intent; | ||
| import android.view.View; | ||
| import android.webkit.WebChromeClient.CustomViewCallback; | ||
|
|
||
| /** | ||
| * Main interface for interacting with a Cordova webview - implemented by CordovaWebViewImpl. | ||
| * This is an interface so that it can be easily mocked in tests. | ||
| * Methods may be added to this interface without a major version bump, as plugins & embedders | ||
| * are not expected to implement it. | ||
| */ | ||
| public interface CordovaWebView { | ||
| public static final String CORDOVA_VERSION = "5.1.0"; | ||
|
|
||
| void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences); | ||
|
|
||
| boolean isInitialized(); | ||
|
|
||
| View getView(); | ||
|
|
||
| void loadUrlIntoView(String url, boolean recreatePlugins); | ||
|
|
||
| void stopLoading(); | ||
|
|
||
| boolean canGoBack(); | ||
|
|
||
| void clearCache(); | ||
|
|
||
| /** Use parameter-less overload */ | ||
| @Deprecated | ||
| void clearCache(boolean b); | ||
|
|
||
| void clearHistory(); | ||
|
|
||
| boolean backHistory(); | ||
|
|
||
| void handlePause(boolean keepRunning); | ||
|
|
||
| void onNewIntent(Intent intent); | ||
|
|
||
| void handleResume(boolean keepRunning); | ||
|
|
||
| void handleStart(); | ||
|
|
||
| void handleStop(); | ||
|
|
||
| void handleDestroy(); | ||
|
|
||
| /** | ||
| * Send JavaScript statement back to JavaScript. | ||
| * | ||
| * Deprecated (https://issues.apache.org/jira/browse/CB-6851) | ||
| * Instead of executing snippets of JS, you should use the exec bridge | ||
| * to create a Java->JS communication channel. | ||
| * To do this: | ||
| * 1. Within plugin.xml (to have your JS run before deviceready): | ||
| * <js-module><runs/></js-module> | ||
| * 2. Within your .js (call exec on start-up): | ||
| * require('cordova/channel').onCordovaReady.subscribe(function() { | ||
| * require('cordova/exec')(win, null, 'Plugin', 'method', []); | ||
| * function win(message) { | ||
| * ... process message from java here ... | ||
| * } | ||
| * }); | ||
| * 3. Within your .java: | ||
| * PluginResult dataResult = new PluginResult(PluginResult.Status.OK, CODE); | ||
| * dataResult.setKeepCallback(true); | ||
| * savedCallbackContext.sendPluginResult(dataResult); | ||
| */ | ||
| @Deprecated | ||
| void sendJavascript(String statememt); | ||
|
|
||
| /** | ||
| * Load the specified URL in the Cordova webview or a new browser instance. | ||
| * | ||
| * NOTE: If openExternal is false, only whitelisted URLs can be loaded. | ||
| * | ||
| * @param url The url to load. | ||
| * @param openExternal Load url in browser instead of Cordova webview. | ||
| * @param clearHistory Clear the history stack, so new page becomes top of history | ||
| * @param params Parameters for new app | ||
| */ | ||
| void showWebPage(String url, boolean openExternal, boolean clearHistory, Map<String, Object> params); | ||
|
|
||
| /** | ||
| * Deprecated in 4.0.0. Use your own View-toggling logic. | ||
| */ | ||
| @Deprecated | ||
| boolean isCustomViewShowing(); | ||
|
|
||
| /** | ||
| * Deprecated in 4.0.0. Use your own View-toggling logic. | ||
| */ | ||
| @Deprecated | ||
| void showCustomView(View view, CustomViewCallback callback); | ||
|
|
||
| /** | ||
| * Deprecated in 4.0.0. Use your own View-toggling logic. | ||
| */ | ||
| @Deprecated | ||
| void hideCustomView(); | ||
|
|
||
| CordovaResourceApi getResourceApi(); | ||
|
|
||
| void setButtonPlumbedToJs(int keyCode, boolean override); | ||
| boolean isButtonPlumbedToJs(int keyCode); | ||
|
|
||
| void sendPluginResult(PluginResult cr, String callbackId); | ||
|
|
||
| PluginManager getPluginManager(); | ||
| CordovaWebViewEngine getEngine(); | ||
| CordovaPreferences getPreferences(); | ||
| ICordovaCookieManager getCookieManager(); | ||
|
|
||
| String getUrl(); | ||
|
|
||
| // TODO: Work on deleting these by removing refs from plugins. | ||
| Context getContext(); | ||
| void loadUrl(String url); | ||
| Object postMessage(String id, Object data); | ||
| } |
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import android.view.KeyEvent; | ||
| import android.view.View; | ||
|
|
||
| /** | ||
| * Interface for all Cordova engines. | ||
| * No methods will be added to this class (in order to be compatible with existing engines). | ||
| * Instead, we will create a new interface: e.g. CordovaWebViewEngineV2 | ||
| */ | ||
| public interface CordovaWebViewEngine { | ||
| void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client, | ||
| CordovaResourceApi resourceApi, PluginManager pluginManager, | ||
| NativeToJsMessageQueue nativeToJsMessageQueue); | ||
|
|
||
| CordovaWebView getCordovaWebView(); | ||
| ICordovaCookieManager getCookieManager(); | ||
| View getView(); | ||
|
|
||
| void loadUrl(String url, boolean clearNavigationStack); | ||
|
|
||
| void stopLoading(); | ||
|
|
||
| /** Return the currently loaded URL */ | ||
| String getUrl(); | ||
|
|
||
| void clearCache(); | ||
|
|
||
| /** After calling clearHistory(), canGoBack() should be false. */ | ||
| void clearHistory(); | ||
|
|
||
| boolean canGoBack(); | ||
|
|
||
| /** Returns whether a navigation occurred */ | ||
| boolean goBack(); | ||
|
|
||
| /** Pauses / resumes the WebView's event loop. */ | ||
| void setPaused(boolean value); | ||
|
|
||
| /** Clean up all resources associated with the WebView. */ | ||
| void destroy(); | ||
|
|
||
| /** | ||
| * Used to retrieve the associated CordovaWebView given a View without knowing the type of Engine. | ||
| * E.g. ((CordovaWebView.EngineView)activity.findViewById(android.R.id.webView)).getCordovaWebView(); | ||
| */ | ||
| public interface EngineView { | ||
| CordovaWebView getCordovaWebView(); | ||
| } | ||
|
|
||
| /** | ||
| * Contains methods that an engine uses to communicate with the parent CordovaWebView. | ||
| * Methods may be added in future cordova versions, but never removed. | ||
| */ | ||
| public interface Client { | ||
| Boolean onDispatchKeyEvent(KeyEvent event); | ||
| void clearLoadTimeoutTimer(); | ||
| void onPageStarted(String newUrl); | ||
| void onReceivedError(int errorCode, String description, String failingUrl); | ||
| void onPageFinishedLoading(String url); | ||
| boolean onNavigationAttempt(String url); | ||
| } | ||
| } |
| @@ -0,0 +1,360 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import org.json.JSONArray; | ||
| import org.json.JSONException; | ||
| import org.json.JSONObject; | ||
|
|
||
| import android.content.BroadcastReceiver; | ||
| import android.content.Context; | ||
| import android.content.Intent; | ||
| import android.content.IntentFilter; | ||
| import android.telephony.TelephonyManager; | ||
| import android.view.KeyEvent; | ||
|
|
||
| import java.util.HashMap; | ||
|
|
||
| /** | ||
| * This class exposes methods in Cordova that can be called from JavaScript. | ||
| */ | ||
| class CoreAndroid extends CordovaPlugin { | ||
|
|
||
| public static final String PLUGIN_NAME = "CoreAndroid"; | ||
| protected static final String TAG = "CordovaApp"; | ||
| private BroadcastReceiver telephonyReceiver; | ||
| private CallbackContext messageChannel; | ||
| private PluginResult pendingResume; | ||
| private final Object messageChannelLock = new Object(); | ||
|
|
||
| /** | ||
| * Send an event to be fired on the Javascript side. | ||
| * | ||
| * @param action The name of the event to be fired | ||
| */ | ||
| public void fireJavascriptEvent(String action) { | ||
| sendEventMessage(action); | ||
| } | ||
|
|
||
| /** | ||
| * Sets the context of the Command. This can then be used to do things like | ||
| * get file paths associated with the Activity. | ||
| */ | ||
| @Override | ||
| public void pluginInitialize() { | ||
| this.initTelephonyReceiver(); | ||
| } | ||
|
|
||
| /** | ||
| * Executes the request and returns PluginResult. | ||
| * | ||
| * @param action The action to execute. | ||
| * @param args JSONArry of arguments for the plugin. | ||
| * @param callbackContext The callback context from which we were invoked. | ||
| * @return A PluginResult object with a status and message. | ||
| */ | ||
| public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { | ||
| PluginResult.Status status = PluginResult.Status.OK; | ||
| String result = ""; | ||
|
|
||
| try { | ||
| if (action.equals("clearCache")) { | ||
| this.clearCache(); | ||
| } | ||
| else if (action.equals("show")) { | ||
| // This gets called from JavaScript onCordovaReady to show the webview. | ||
| // I recommend we change the name of the Message as spinner/stop is not | ||
| // indicative of what this actually does (shows the webview). | ||
| cordova.getActivity().runOnUiThread(new Runnable() { | ||
| public void run() { | ||
| webView.getPluginManager().postMessage("spinner", "stop"); | ||
| } | ||
| }); | ||
| } | ||
| else if (action.equals("loadUrl")) { | ||
| this.loadUrl(args.getString(0), args.optJSONObject(1)); | ||
| } | ||
| else if (action.equals("cancelLoadUrl")) { | ||
| //this.cancelLoadUrl(); | ||
| } | ||
| else if (action.equals("clearHistory")) { | ||
| this.clearHistory(); | ||
| } | ||
| else if (action.equals("backHistory")) { | ||
| this.backHistory(); | ||
| } | ||
| else if (action.equals("overrideButton")) { | ||
| this.overrideButton(args.getString(0), args.getBoolean(1)); | ||
| } | ||
| else if (action.equals("overrideBackbutton")) { | ||
| this.overrideBackbutton(args.getBoolean(0)); | ||
| } | ||
| else if (action.equals("exitApp")) { | ||
| this.exitApp(); | ||
| } | ||
| else if (action.equals("messageChannel")) { | ||
| synchronized(messageChannelLock) { | ||
| messageChannel = callbackContext; | ||
| if (pendingResume != null) { | ||
| sendEventMessage(pendingResume); | ||
| pendingResume = null; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| callbackContext.sendPluginResult(new PluginResult(status, result)); | ||
| return true; | ||
| } catch (JSONException e) { | ||
| callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| // LOCAL METHODS | ||
| //-------------------------------------------------------------------------- | ||
|
|
||
| /** | ||
| * Clear the resource cache. | ||
| */ | ||
| public void clearCache() { | ||
| cordova.getActivity().runOnUiThread(new Runnable() { | ||
| public void run() { | ||
| webView.clearCache(true); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Load the url into the webview. | ||
| * | ||
| * @param url | ||
| * @param props Properties that can be passed in to the Cordova activity (i.e. loadingDialog, wait, ...) | ||
| * @throws JSONException | ||
| */ | ||
| public void loadUrl(String url, JSONObject props) throws JSONException { | ||
| LOG.d("App", "App.loadUrl("+url+","+props+")"); | ||
| int wait = 0; | ||
| boolean openExternal = false; | ||
| boolean clearHistory = false; | ||
|
|
||
| // If there are properties, then set them on the Activity | ||
| HashMap<String, Object> params = new HashMap<String, Object>(); | ||
| if (props != null) { | ||
| JSONArray keys = props.names(); | ||
| for (int i = 0; i < keys.length(); i++) { | ||
| String key = keys.getString(i); | ||
| if (key.equals("wait")) { | ||
| wait = props.getInt(key); | ||
| } | ||
| else if (key.equalsIgnoreCase("openexternal")) { | ||
| openExternal = props.getBoolean(key); | ||
| } | ||
| else if (key.equalsIgnoreCase("clearhistory")) { | ||
| clearHistory = props.getBoolean(key); | ||
| } | ||
| else { | ||
| Object value = props.get(key); | ||
| if (value == null) { | ||
|
|
||
| } | ||
| else if (value.getClass().equals(String.class)) { | ||
| params.put(key, (String)value); | ||
| } | ||
| else if (value.getClass().equals(Boolean.class)) { | ||
| params.put(key, (Boolean)value); | ||
| } | ||
| else if (value.getClass().equals(Integer.class)) { | ||
| params.put(key, (Integer)value); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If wait property, then delay loading | ||
|
|
||
| if (wait > 0) { | ||
| try { | ||
| synchronized(this) { | ||
| this.wait(wait); | ||
| } | ||
| } catch (InterruptedException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
| this.webView.showWebPage(url, openExternal, clearHistory, params); | ||
| } | ||
|
|
||
| /** | ||
| * Clear page history for the app. | ||
| */ | ||
| public void clearHistory() { | ||
| cordova.getActivity().runOnUiThread(new Runnable() { | ||
| public void run() { | ||
| webView.clearHistory(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Go to previous page displayed. | ||
| * This is the same as pressing the backbutton on Android device. | ||
| */ | ||
| public void backHistory() { | ||
| cordova.getActivity().runOnUiThread(new Runnable() { | ||
| public void run() { | ||
| webView.backHistory(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Override the default behavior of the Android back button. | ||
| * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired. | ||
| * | ||
| * @param override T=override, F=cancel override | ||
| */ | ||
| public void overrideBackbutton(boolean override) { | ||
| LOG.i("App", "WARNING: Back Button Default Behavior will be overridden. The backbutton event will be fired!"); | ||
| webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_BACK, override); | ||
| } | ||
|
|
||
| /** | ||
| * Override the default behavior of the Android volume buttons. | ||
| * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired. | ||
| * | ||
| * @param button volumeup, volumedown | ||
| * @param override T=override, F=cancel override | ||
| */ | ||
| public void overrideButton(String button, boolean override) { | ||
| LOG.i("App", "WARNING: Volume Button Default Behavior will be overridden. The volume event will be fired!"); | ||
| if (button.equals("volumeup")) { | ||
| webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override); | ||
| } | ||
| else if (button.equals("volumedown")) { | ||
| webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_DOWN, override); | ||
| } | ||
| else if (button.equals("menubutton")) { | ||
| webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_MENU, override); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Return whether the Android back button is overridden by the user. | ||
| * | ||
| * @return boolean | ||
| */ | ||
| public boolean isBackbuttonOverridden() { | ||
| return webView.isButtonPlumbedToJs(KeyEvent.KEYCODE_BACK); | ||
| } | ||
|
|
||
| /** | ||
| * Exit the Android application. | ||
| */ | ||
| public void exitApp() { | ||
| this.webView.getPluginManager().postMessage("exit", null); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Listen for telephony events: RINGING, OFFHOOK and IDLE | ||
| * Send these events to all plugins using | ||
| * CordovaActivity.onMessage("telephone", "ringing" | "offhook" | "idle") | ||
| */ | ||
| private void initTelephonyReceiver() { | ||
| IntentFilter intentFilter = new IntentFilter(); | ||
| intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); | ||
| //final CordovaInterface mycordova = this.cordova; | ||
| this.telephonyReceiver = new BroadcastReceiver() { | ||
|
|
||
| @Override | ||
| public void onReceive(Context context, Intent intent) { | ||
|
|
||
| // If state has changed | ||
| if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { | ||
| if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) { | ||
| String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE); | ||
| if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) { | ||
| LOG.i(TAG, "Telephone RINGING"); | ||
| webView.getPluginManager().postMessage("telephone", "ringing"); | ||
| } | ||
| else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { | ||
| LOG.i(TAG, "Telephone OFFHOOK"); | ||
| webView.getPluginManager().postMessage("telephone", "offhook"); | ||
| } | ||
| else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) { | ||
| LOG.i(TAG, "Telephone IDLE"); | ||
| webView.getPluginManager().postMessage("telephone", "idle"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| // Register the receiver | ||
| webView.getContext().registerReceiver(this.telephonyReceiver, intentFilter); | ||
| } | ||
|
|
||
| private void sendEventMessage(String action) { | ||
| JSONObject obj = new JSONObject(); | ||
| try { | ||
| obj.put("action", action); | ||
| } catch (JSONException e) { | ||
| LOG.e(TAG, "Failed to create event message", e); | ||
| } | ||
| sendEventMessage(new PluginResult(PluginResult.Status.OK, obj)); | ||
| } | ||
|
|
||
| private void sendEventMessage(PluginResult payload) { | ||
| payload.setKeepCallback(true); | ||
| if (messageChannel != null) { | ||
| messageChannel.sendPluginResult(payload); | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * Unregister the receiver | ||
| * | ||
| */ | ||
| public void onDestroy() | ||
| { | ||
| webView.getContext().unregisterReceiver(this.telephonyReceiver); | ||
| } | ||
|
|
||
| /** | ||
| * Used to send the resume event in the case that the Activity is destroyed by the OS | ||
| * | ||
| * @param resumeEvent PluginResult containing the payload for the resume event to be fired | ||
| */ | ||
| public void sendResumeEvent(PluginResult resumeEvent) { | ||
| // This operation must be synchronized because plugin results that trigger resume | ||
| // events can be processed asynchronously | ||
| synchronized(messageChannelLock) { | ||
| if (messageChannel != null) { | ||
| sendEventMessage(resumeEvent); | ||
| } else { | ||
| // Might get called before the page loads, so we need to store it until the | ||
| // messageChannel gets created | ||
| this.pendingResume = resumeEvent; | ||
| } | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,31 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| import org.json.JSONException; | ||
|
|
||
| /* | ||
| * Any exposed Javascript API MUST implement these three things! | ||
| */ | ||
| public interface ExposedJsApi { | ||
| public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException; | ||
| public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException; | ||
| public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException; | ||
| } |
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import java.security.Principal; | ||
| import java.security.PrivateKey; | ||
| import java.security.cert.X509Certificate; | ||
|
|
||
| /** | ||
| * Specifies interface for handling certificate requests. | ||
| */ | ||
| public interface ICordovaClientCertRequest { | ||
| /** | ||
| * Cancel this request | ||
| */ | ||
| public void cancel(); | ||
|
|
||
| /* | ||
| * Returns the host name of the server requesting the certificate. | ||
| */ | ||
| public String getHost(); | ||
|
|
||
| /* | ||
| * Returns the acceptable types of asymmetric keys (can be null). | ||
| */ | ||
| public String[] getKeyTypes(); | ||
|
|
||
| /* | ||
| * Returns the port number of the server requesting the certificate. | ||
| */ | ||
| public int getPort(); | ||
|
|
||
| /* | ||
| * Returns the acceptable certificate issuers for the certificate matching the private key (can be null). | ||
| */ | ||
| public Principal[] getPrincipals(); | ||
|
|
||
| /* | ||
| * Ignore the request for now. Do not remember user's choice. | ||
| */ | ||
| public void ignore(); | ||
|
|
||
| /* | ||
| * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests. | ||
| * | ||
| * @param privateKey The privateKey | ||
| * @param chain The certificate chain | ||
| */ | ||
| public void proceed(PrivateKey privateKey, X509Certificate[] chain); | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
|
|
||
| package org.apache.cordova; | ||
|
|
||
| public interface ICordovaCookieManager { | ||
|
|
||
| public void setCookiesEnabled(boolean accept); | ||
|
|
||
| public void setCookie(final String url, final String value); | ||
|
|
||
| public String getCookie(final String url); | ||
|
|
||
| public void clearCookies(); | ||
|
|
||
| public void flush(); | ||
| }; |
| @@ -0,0 +1,38 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| /** | ||
| * Specifies interface for HTTP auth handler object which is used to handle auth requests and | ||
| * specifying user credentials. | ||
| */ | ||
| public interface ICordovaHttpAuthHandler { | ||
| /** | ||
| * Instructs the WebView to cancel the authentication request. | ||
| */ | ||
| public void cancel (); | ||
|
|
||
| /** | ||
| * Instructs the WebView to proceed with the authentication with the given credentials. | ||
| * | ||
| * @param username The user name | ||
| * @param password The password | ||
| */ | ||
| public void proceed (String username, String password); | ||
| } |
| @@ -0,0 +1,234 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import android.util.Log; | ||
|
|
||
| /** | ||
| * Log to Android logging system. | ||
| * | ||
| * Log message can be a string or a printf formatted string with arguments. | ||
| * See http://developer.android.com/reference/java/util/Formatter.html | ||
| */ | ||
| public class LOG { | ||
|
|
||
| public static final int VERBOSE = Log.VERBOSE; | ||
| public static final int DEBUG = Log.DEBUG; | ||
| public static final int INFO = Log.INFO; | ||
| public static final int WARN = Log.WARN; | ||
| public static final int ERROR = Log.ERROR; | ||
|
|
||
| // Current log level | ||
| public static int LOGLEVEL = Log.ERROR; | ||
|
|
||
| /** | ||
| * Set the current log level. | ||
| * | ||
| * @param logLevel | ||
| */ | ||
| public static void setLogLevel(int logLevel) { | ||
| LOGLEVEL = logLevel; | ||
| Log.i("CordovaLog", "Changing log level to " + logLevel); | ||
| } | ||
|
|
||
| /** | ||
| * Set the current log level. | ||
| * | ||
| * @param logLevel | ||
| */ | ||
| public static void setLogLevel(String logLevel) { | ||
| if ("VERBOSE".equals(logLevel)) LOGLEVEL = VERBOSE; | ||
| else if ("DEBUG".equals(logLevel)) LOGLEVEL = DEBUG; | ||
| else if ("INFO".equals(logLevel)) LOGLEVEL = INFO; | ||
| else if ("WARN".equals(logLevel)) LOGLEVEL = WARN; | ||
| else if ("ERROR".equals(logLevel)) LOGLEVEL = ERROR; | ||
| Log.i("CordovaLog", "Changing log level to " + logLevel + "(" + LOGLEVEL + ")"); | ||
| } | ||
|
|
||
| /** | ||
| * Determine if log level will be logged | ||
| * | ||
| * @param logLevel | ||
| * @return true if the parameter passed in is greater than or equal to the current log level | ||
| */ | ||
| public static boolean isLoggable(int logLevel) { | ||
| return (logLevel >= LOGLEVEL); | ||
| } | ||
|
|
||
| /** | ||
| * Verbose log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| */ | ||
| public static void v(String tag, String s) { | ||
| if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s); | ||
| } | ||
|
|
||
| /** | ||
| * Debug log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| */ | ||
| public static void d(String tag, String s) { | ||
| if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s); | ||
| } | ||
|
|
||
| /** | ||
| * Info log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| */ | ||
| public static void i(String tag, String s) { | ||
| if (LOG.INFO >= LOGLEVEL) Log.i(tag, s); | ||
| } | ||
|
|
||
| /** | ||
| * Warning log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| */ | ||
| public static void w(String tag, String s) { | ||
| if (LOG.WARN >= LOGLEVEL) Log.w(tag, s); | ||
| } | ||
|
|
||
| /** | ||
| * Error log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| */ | ||
| public static void e(String tag, String s) { | ||
| if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s); | ||
| } | ||
|
|
||
| /** | ||
| * Verbose log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param e | ||
| */ | ||
| public static void v(String tag, String s, Throwable e) { | ||
| if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s, e); | ||
| } | ||
|
|
||
| /** | ||
| * Debug log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param e | ||
| */ | ||
| public static void d(String tag, String s, Throwable e) { | ||
| if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s, e); | ||
| } | ||
|
|
||
| /** | ||
| * Info log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param e | ||
| */ | ||
| public static void i(String tag, String s, Throwable e) { | ||
| if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e); | ||
| } | ||
|
|
||
| /** | ||
| * Warning log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param e | ||
| */ | ||
| public static void w(String tag, String s, Throwable e) { | ||
| if (LOG.WARN >= LOGLEVEL) Log.w(tag, s, e); | ||
| } | ||
|
|
||
| /** | ||
| * Error log message. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param e | ||
| */ | ||
| public static void e(String tag, String s, Throwable e) { | ||
| if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s, e); | ||
| } | ||
|
|
||
| /** | ||
| * Verbose log message with printf formatting. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param args | ||
| */ | ||
| public static void v(String tag, String s, Object... args) { | ||
| if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, String.format(s, args)); | ||
| } | ||
|
|
||
| /** | ||
| * Debug log message with printf formatting. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param args | ||
| */ | ||
| public static void d(String tag, String s, Object... args) { | ||
| if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, String.format(s, args)); | ||
| } | ||
|
|
||
| /** | ||
| * Info log message with printf formatting. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param args | ||
| */ | ||
| public static void i(String tag, String s, Object... args) { | ||
| if (LOG.INFO >= LOGLEVEL) Log.i(tag, String.format(s, args)); | ||
| } | ||
|
|
||
| /** | ||
| * Warning log message with printf formatting. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param args | ||
| */ | ||
| public static void w(String tag, String s, Object... args) { | ||
| if (LOG.WARN >= LOGLEVEL) Log.w(tag, String.format(s, args)); | ||
| } | ||
|
|
||
| /** | ||
| * Error log message with printf formatting. | ||
| * | ||
| * @param tag | ||
| * @param s | ||
| * @param args | ||
| */ | ||
| public static void e(String tag, String s, Object... args) { | ||
| if (LOG.ERROR >= LOGLEVEL) Log.e(tag, String.format(s, args)); | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,70 @@ | ||
| /* | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| */ | ||
| package org.apache.cordova; | ||
|
|
||
| import org.apache.cordova.CordovaPlugin; | ||
|
|
||
| /** | ||
| * This class represents a service entry object. | ||
| */ | ||
| public final class PluginEntry { | ||
|
|
||
| /** | ||
| * The name of the service that this plugin implements | ||
| */ | ||
| public final String service; | ||
|
|
||
| /** | ||
| * The plugin class name that implements the service. | ||
| */ | ||
| public final String pluginClass; | ||
|
|
||
| /** | ||
| * The pre-instantiated plugin to use for this entry. | ||
| */ | ||
| public final CordovaPlugin plugin; | ||
|
|
||
| /** | ||
| * Flag that indicates the plugin object should be created when PluginManager is initialized. | ||
| */ | ||
| public final boolean onload; | ||
|
|
||
| /** | ||
| * Constructs with a CordovaPlugin already instantiated. | ||
| */ | ||
| public PluginEntry(String service, CordovaPlugin plugin) { | ||
| this(service, plugin.getClass().getName(), true, plugin); | ||
| } | ||
|
|
||
| /** | ||
| * @param service The name of the service | ||
| * @param pluginClass The plugin class name | ||
| * @param onload Create plugin object when HTML page is loaded | ||
| */ | ||
| public PluginEntry(String service, String pluginClass, boolean onload) { | ||
| this(service, pluginClass, onload, null); | ||
| } | ||
|
|
||
| private PluginEntry(String service, String pluginClass, boolean onload, CordovaPlugin plugin) { | ||
| this.service = service; | ||
| this.pluginClass = pluginClass; | ||
| this.onload = onload; | ||
| this.plugin = plugin; | ||
| } | ||
| } |