Compare commits

...

55 Commits

Author SHA1 Message Date
Simon MacDonald
7b3724972b Tagging to 2.3.0rc1 2012-11-26 16:09:52 -05:00
Simon MacDonald
9ca2a16218 Updating JS so that InAppBrowser will work out of the box 2012-11-23 09:38:49 -05:00
Simon MacDonald
f1e8400abf Merge branch 'master' of http://git-wip-us.apache.org/repos/asf/cordova-android 2012-11-22 22:28:34 -05:00
Andrew Grieve
11e0ffa90a Add @JavascriptInterface annotations to ExposedJsApi.
And re-enable the JS bridge on 4.2.
https://issues.apache.org/jira/browse/CB-1879
2012-11-22 22:23:51 -05:00
Anis Kadri
2ee4326a4d updating create command 2012-11-22 22:23:51 -05:00
Anis Kadri
226e72ac18 adding release command 2012-11-22 22:23:51 -05:00
Anis Kadri
65c78b8f3f removing ApplicationInfo.class 2012-11-22 22:23:51 -05:00
Anis Kadri
6137c7ca06 removing appinfo.jar 2012-11-22 22:23:51 -05:00
Simon MacDonald
5bebf11b37 CB-1888: Can't add a Photo from a HTTPS address to Contact 2012-11-22 22:23:51 -05:00
Anis Kadri
68161d2714 refactoring windows scripts 2012-11-22 22:23:51 -05:00
Anis Kadri
a6473cb826 adding install function 2012-11-22 22:23:51 -05:00
Anis Kadri
0084c6f96a refactoring android commands 2012-11-22 22:23:51 -05:00
Simon MacDonald
a87825dbee CB-1508: Implement InAppBrowser feature
Initial checkin. Need to clean up the UI and add eventing.
2012-11-22 22:21:24 -05:00
Andrew Grieve
3566154cd0 Add @JavascriptInterface annotations to ExposedJsApi.
And re-enable the JS bridge on 4.2.
https://issues.apache.org/jira/browse/CB-1879
2012-11-22 12:39:18 -05:00
Anis Kadri
92d69e320f updating create command 2012-11-21 16:35:27 -08:00
Anis Kadri
08a190ef5b adding release command 2012-11-21 16:35:16 -08:00
Anis Kadri
98339ee5d8 removing ApplicationInfo.class 2012-11-21 13:37:19 -08:00
Anis Kadri
fa387fd758 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-21 13:33:21 -08:00
Anis Kadri
54979f2fc4 removing appinfo.jar 2012-11-21 13:33:09 -08:00
Simon MacDonald
538e90f23a CB-1888: Can't add a Photo from a HTTPS address to Contact 2012-11-21 11:27:25 -05:00
Anis Kadri
d9107bcac6 refactoring windows scripts 2012-11-20 18:49:16 -08:00
Anis Kadri
3f3a0b9140 adding install function 2012-11-20 14:49:49 -08:00
Anis Kadri
e1347e434e refactoring android commands 2012-11-20 14:39:37 -08:00
Joe Bowser
7657faa9c3 CB-1852: Android version of model implemented, too bad it's all code names and not human readable 2012-11-19 13:26:22 -08:00
Joe Bowser
28ef765913 Upgrading App plugin to CordovaPlugin 2012-11-19 11:33:21 -08:00
Joe Bowser
d2f59391a2 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-19 10:36:45 -08:00
Joe Bowser
df90bdb350 Fixing up the tests so they crash less. 2012-11-19 10:36:26 -08:00
Joe Bowser
c416c77d7a Fix for CB-1879 by Tom Clarkson. Hacked in due to lack of pull request 2012-11-19 10:35:47 -08:00
Andrew Grieve
ce05a720d1 Update .gitignore 2012-11-16 15:41:38 -05:00
Joe Bowser
6c19a440f5 CB-1864: Figured out how to simulate back button, test both the CordovaWebView back button and the general DroidGap case using the default implementation 2012-11-15 16:04:09 -08:00
Joe Bowser
f4612fdb5d Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-15 13:48:15 -08:00
Joe Bowser
04b9a0b09e Death to tabs while working on CB-1864 2012-11-15 13:47:52 -08:00
Simon MacDonald
f93c438067 CB-1860: NPE in onReceivedError with non local errorUrl 2012-11-15 11:04:50 -05:00
Joe Bowser
e1d608443a Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-14 13:23:35 -08:00
Joe Bowser
9233c3a898 Fixing error with the tests, backbuttonmultipage wasn't added 2012-11-14 13:22:58 -08:00
Simon MacDonald
dfa514334b Bumping Android API version to 17 2012-11-14 16:05:50 -05:00
Joe Bowser
5810a96e62 Adding reflection so that this compiles, need to test against HTC Desire HD 2.3.6 device before resolving CB-1845 2012-11-14 11:15:22 -08:00
Joe Bowser
70473a80af Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-13 14:31:33 -08:00
Joe Bowser
525fd30cb2 Merge branch 'Android_2.3.4_camera_crash' of git://github.com/IuriiO/incubator-cordova-android into null_camera 2012-11-13 11:37:40 -08:00
Andrew Grieve
5212cd4dcd Disable JS Interface on Honeycomb
Fixes https://issues.apache.org/jira/browse/CB-1818
2012-11-13 12:50:15 -05:00
Simon MacDonald
e95bde62a2 Correctly report the mime type of 3ga files 2012-11-12 10:22:35 -05:00
Simon MacDonald
4fe73cf6ad CB-1835: Camera.getPicture gives error when get a picture from photo library with spaces in its name on Android 2012-11-12 10:00:32 -05:00
Simon MacDonald
78b2835da4 Merge branch 'master' of https://github.com/ilbambino/incubator-cordova-android 2012-11-12 09:57:19 -05:00
Iurii Okhmat
f9a49efae9 Removed unnecessary import. 2012-11-09 16:44:33 -08:00
Iurii Okhmat
b9ddc9e678 Camera plugin (HTC Incredible) is crashing on 2.3.4 devices without SD card 2012-11-09 16:40:56 -08:00
Simon MacDonald
dc459c84a3 CB-1829: Online/Offline events do not fire on subsequent pages of an app 2012-11-09 11:28:50 -05:00
Alvaro
1d26239809 not getting the path correctly if the URI contains a file://
Previous to 2.2 this function was crashing if the URI wasn't different
than a 'content://' but still if it is a 'file://' it fails getting the
correct path.
This happens for example picking a picture from dropbox instead of
local gallery.
2012-11-09 09:28:26 +02:00
Simon MacDonald
e51b4897a3 Guard against null mimeType in MediaFile.getFormatData 2012-11-08 14:01:46 -05:00
Anis Kadri
81f283e56f CB-1794 fixing cordova commands for paths with spaces in them 2012-11-07 13:22:14 -08:00
Anis Kadri
ccdd2fd2ca CB-1809 create script should print out meaningful error messages 2012-11-05 17:51:32 -08:00
Joe Bowser
69f11a29e1 Updating the project so that the activities are clearly separated from Test and Helper code 2012-11-02 16:15:51 -07:00
Joe Bowser
cf494f3238 Fixing the tests so that they run as an Activity again 2012-11-02 13:48:05 -07:00
Joe Bowser
d5895c635a Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-11-02 13:33:13 -07:00
Simon MacDonald
2ac9873613 CB-1808: FileEntry.moveTo across file systems incorrectly calls the success callback 2012-11-02 14:50:24 -04:00
Joe Bowser
eb59e76cde Fixing CB-1801 2012-11-01 12:23:18 -07:00
68 changed files with 7953 additions and 644 deletions

19
.gitignore vendored
View File

@@ -4,28 +4,29 @@ gen
assets/www/cordova.js
framework/assets/www/.tmp*
local.properties
framework/proguard.cfg
framework/cordova.jar
framework/cordova-*.jar
framework/phonegap-*.jar
framework/lib
proguard.cfg
proguard.cfg
proguard-project.txt
framework/bin
framework/test/org/apache/cordova/*.class
framework/assets/www/.DS_Store
framework/assets/www/cordova-*.js
framework/assets/www/phonegap-*.js
framework/libs
test/libs
example
./test
test/bin
test/assets/www/.tmp*
tmp/**
*.tmp
test/libs/*.jar
bin/node_modules
.metadata
*.bak
tmp/**/*
*.swp
Thumbs.db
Desktop.ini
*.tmp
*.bak
*.swp
*.class
*.jar

View File

@@ -1 +1 @@
2.2.0
2.3.0rc1

View File

@@ -66,12 +66,14 @@ function createAppInfoJar {
}
function on_error {
echo "An error occurred. Deleting project..."
echo "An unexpected error occurred: $previous_command exited with $?"
echo "Deleting project..."
[ -d "$PROJECT_PATH" ] && rm -rf "$PROJECT_PATH"
exit "$?"
}
function replace {
local pattern=$1
local pattern=$1
local filename=$2
# Mac OS X requires -i argument
if [[ "$OSTYPE" =~ "darwin" ]]
@@ -84,6 +86,7 @@ function replace {
}
# we do not want the script to silently fail
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
trap on_error ERR
trap on_exit EXIT
@@ -144,13 +147,13 @@ replace "s/__ACTIVITY__/${ACTIVITY}/g" "$MANIFEST_PATH"
replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
replace "s/__APILEVEL__/${API_LEVEL}/g" "$MANIFEST_PATH"
# creating cordova folder and copying emulate/debug/log/launch scripts
# creating cordova folder and copying run/build/log/launch scripts
mkdir "$PROJECT_PATH"/cordova
createAppInfoJar
cp "$BUILD_PATH"/bin/templates/cordova/appinfo.jar "$PROJECT_PATH"/cordova/appinfo.jar
cp "$BUILD_PATH"/bin/templates/cordova/cordova "$PROJECT_PATH"/cordova/cordova
cp "$BUILD_PATH"/bin/templates/cordova/debug "$PROJECT_PATH"/cordova/debug
cp "$BUILD_PATH"/bin/templates/cordova/build "$PROJECT_PATH"/cordova/build
cp "$BUILD_PATH"/bin/templates/cordova/release "$PROJECT_PATH"/cordova/release
cp "$BUILD_PATH"/bin/templates/cordova/clean "$PROJECT_PATH"/cordova/clean
cp "$BUILD_PATH"/bin/templates/cordova/log "$PROJECT_PATH"/cordova/log
cp "$BUILD_PATH"/bin/templates/cordova/emulate "$PROJECT_PATH"/cordova/emulate
cp "$BUILD_PATH"/bin/templates/cordova/BOOM "$PROJECT_PATH"/cordova/BOOM
cp "$BUILD_PATH"/bin/templates/cordova/run "$PROJECT_PATH"/cordova/run

View File

@@ -198,10 +198,9 @@ exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\appinfo.jar ' + PRO
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.js ' + PROJECT_PATH + '\\cordova\\cordova.js /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.bat ' + PROJECT_PATH + '\\cordova\\cordova.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\clean.bat ' + PROJECT_PATH + '\\cordova\\clean.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\debug.bat ' + PROJECT_PATH + '\\cordova\\debug.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\build.bat ' + PROJECT_PATH + '\\cordova\\build.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\log.bat ' + PROJECT_PATH + '\\cordova\\log.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\emulate.bat ' + PROJECT_PATH + '\\cordova\\emulate.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\BOOM.bat ' + PROJECT_PATH + '\\cordova\\BOOM.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\run.bat ' + PROJECT_PATH + '\\cordova\\run.bat /Y');
// interpolate the activity name and package
WScript.Echo("Updating AndroidManifest.xml and Main Activity...");

View File

@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash $CORDOVA_PATH/cordova emulate
bash "$CORDOVA_PATH"/cordova build

View File

@@ -15,4 +15,4 @@
:: specific language governing permissions and limitations
:: under the License.
%~dp0\cordova.bat BOOM
%~dp0\cordova.bat build

View File

@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash $CORDOVA_PATH/cordova clean
bash "$CORDOVA_PATH"/cordova clean

View File

@@ -17,12 +17,12 @@
#!/bin/bash
set -e
PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd )
function check_devices {
local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}'`
# FIXME
local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device`
if [ -z "$devices" ] ; then
echo "1"
else
@@ -37,7 +37,6 @@ function emulate {
# Do not launch an emulator if there is already one running or if a device is attached
if [ $(check_devices) == 0 ] ; then
echo "Device attached or emulator already running"
return
fi
@@ -62,8 +61,9 @@ function emulate {
do
echo "$i) ${avd_list[$i]}"
done
echo -n "> "
read avd_id
read -t 5 -p "> " avd_id
# default value if input timeout
if [ $avd_id -eq 1000 ] ; then avd_id=0 ; fi
done
emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 &
fi
@@ -78,25 +78,82 @@ function log {
adb logcat
}
function debug {
if [ $(check_devices) == 0 ] ; then
ant debug install
function run {
clean && emulate && wait_for_device && install && launch
}
function install {
declare -a devices=($(adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device | cut -f 1))
local device_id="1000" #FIXME: hopefully user does not have 1000 AVDs
if [ ${#devices[@]} == 0 ]
then
# should not reach here. Emulator should launch or device should be attached
echo "Emulator not running or device not attached. Could not install debug package"
exit 70
fi
if [ ${#devices[@]} == 1 ]
then
export ANDROID_SERIAL=${devices[0]}
# User has more than 1 AVD
elif [ ${#devices[@]} -gt 1 ]
then
while [ -z ${devices[$device_id]} ]
do
echo "Choose from one of the following devices/emulators [0 to $((${#devices[@]}-1))]:"
for(( i = 0 ; i < ${#devices[@]} ; i++ ))
do
echo "$i) ${devices[$i]}"
done
read -t 5 -p "> " device_id
# default value if input timeout
if [ $device_id -eq 1000 ] ; then device_id=0 ; fi
done
export ANDROID_SERIAL=${devices[$device_id]}
fi
ant debug install
}
function build {
ant debug
}
function release {
ant release
}
function wait_for_device {
local i="0"
echo -n "Waiting for device..."
while [ $i -lt 300 ]
do
if [ $(check_devices) -eq 0 ]
then
break
else
sleep 1
i=$[i+1]
echo -n "."
fi
done
# Device timeout: emulator has not started in time or device not attached
if [ $i -eq 300 ]
then
echo "device timeout!"
exit 69
else
ant debug
echo "##################################################################"
echo "# Plug in your device or launch an emulator with cordova/emulate #"
echo "##################################################################"
echo "connected!"
fi
}
function launch {
local launch_str=$(java -jar $PROJECT_PATH/cordova/appinfo.jar $PROJECT_PATH/AndroidManifest.xml)
local launch_str=$(java -jar "$PROJECT_PATH"/cordova/appinfo.jar "$PROJECT_PATH"/AndroidManifest.xml)
adb shell am start -n $launch_str
}
function BOOM {
clean && debug && launch
}
# TODO parse arguments
(cd $PROJECT_PATH && $1)
(cd "$PROJECT_PATH" && $1)

View File

@@ -34,17 +34,19 @@ function exec(command) {
return output;
}
function emulator_running() {
function device_running() {
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
if(local_devices.match(/emulator/)) {
if(local_devices.match(/\w+\tdevice/)) {
WScript.Echo("Yes");
return true;
}
WScript.Echo("No");
return false;
}
function emulate() {
// don't run emulator if a device is plugged in or if emulator is already running
if(emulator_running()) {
WScript.Echo("Device or Emulator already running!");
if(device_running()) {
//WScript.Echo("Device or Emulator already running!");
return;
}
var oExec = shell.Exec("%comspec% /c android.bat list avd");
@@ -84,18 +86,18 @@ function emulate() {
}
function clean() {
WScript.Echo("Cleaning project...");
exec("%comspec% /c ant.bat clean -f "+ROOT+"\\build.xml 2>&1");
}
function debug() {
if(emulator_running()) {
exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
} else {
exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
WScript.Echo("##################################################################");
WScript.Echo("# Plug in your device or launch an emulator with cordova/emulate #");
WScript.Echo("##################################################################");
}
function build() {
WScript.Echo("Building project...");
exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
}
function install() {
WScript.Echo("Building/Installing project...");
exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
}
function log() {
@@ -103,14 +105,28 @@ function log() {
}
function launch() {
WScript.Echo("Launching app...");
var launch_str=exec("%comspec% /c java -jar "+ROOT+"\\cordova\\appinfo.jar "+ROOT+"\\AndroidManifest.xml");
//WScript.Echo(launch_str);
exec("%comspec% /c adb shell am start -n "+launch_str+" 2>&1");
}
function BOOM() {
function run() {
var i=0;
clean();
debug();
emulate();
WScript.Stdout.Write('Waiting for device...');
while(!device_running() && i < 300) {
WScript.Stdout.Write('.');
WScript.sleep(1000);
i += 1;
}
if(i == 300) {
WScript.Stderr.WriteLine("device/emulator timeout!");
} else {
WScript.Stdout.WriteLine("connected!");
}
install();
launch();
}
var args = WScript.Arguments;

View File

@@ -1,18 +0,0 @@
:: 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.
%~dp0\cordova.bat debug

View File

@@ -1 +0,0 @@
%~dp0\cordova.bat emulate

View File

@@ -19,6 +19,6 @@
set -e
PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd )
CORDOVA_PATH=$( cd "$( dirname "$0" )/.." && pwd )
bash $PROJECT_PATH/cordova/cordova log
bash "$CORDOVA_PATH"/cordova/cordova log

View File

@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash $CORDOVA_PATH/cordova debug
bash "$CORDOVA_PATH"/cordova release

View File

@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash $CORDOVA_PATH/cordova BOOM
bash "$CORDOVA_PATH"/cordova run

View File

@@ -0,0 +1 @@
%~dp0\cordova.bat run

View File

@@ -33,7 +33,7 @@
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova-2.2.0.js"></script>
<script type="text/javascript" src="cordova-2.3.0rc1.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();

View File

@@ -1,6 +1,6 @@
// commit 02b91c5313ff37d74a58f71775170afd360f4a1f
// commit 54335c8f70223b053f4c039185d13cb95801d043
// File generated at :: Wed Oct 31 2012 10:40:25 GMT-0700 (PDT)
// File generated at :: Mon Nov 26 2012 16:05:15 GMT-0500 (EST)
/*
Licensed to the Apache Software Foundation (ASF) under one
@@ -314,6 +314,65 @@ channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
module.exports = cordova;
});
// file: lib/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) {
var exec = require('cordova/exec');
var moduleExports = module.exports;
var typeMap = {
'A': 'Array',
'D': 'Date',
'N': 'Number',
'S': 'String',
'F': 'Function',
'O': 'Object'
};
function extractParamName(callee, argIndex) {
return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
}
function checkArgs(spec, functionName, args, opt_callee) {
if (!moduleExports.enableChecks) {
return;
}
var errMsg = null;
var type;
for (var i = 0; i < spec.length; ++i) {
var c = spec.charAt(i),
cUpper = c.toUpperCase(),
arg = args[i];
// Asterix means allow anything.
if (c == '*') {
continue;
}
type = Object.prototype.toString.call(arg).slice(8, -1);
if ((arg === null || arg === undefined) && c == cUpper) {
continue;
}
if (type != typeMap[cUpper]) {
errMsg = 'Expected ' + typeMap[cUpper];
break;
}
}
if (errMsg) {
errMsg += ', but got ' + type + '.';
errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
// Don't log when running jake test.
if (typeof jasmine == 'undefined') {
console.error(errMsg);
}
throw TypeError(errMsg);
}
}
moduleExports.checkArgs = checkArgs;
moduleExports.enableChecks = true;
});
// file: lib/common/builder.js
@@ -329,14 +388,24 @@ function each(objects, func, context) {
}
}
function clobber(obj, key, value) {
obj[key] = value;
// Getters can only be overridden by getters.
if (obj[key] !== value) {
utils.defineGetter(obj, key, function() {
return value;
});
}
}
function assignOrWrapInDeprecateGetter(obj, key, value, message) {
if (message) {
utils.defineGetter(obj, key, function() {
window.console && console.log(message);
console.log(message);
return value;
});
} else {
obj[key] = value;
clobber(obj, key, value);
}
}
@@ -395,8 +464,11 @@ function recursiveMerge(target, src) {
// If the target object is a constructor override off prototype.
target.prototype[prop] = src[prop];
} else {
target[prop] = typeof src[prop] === 'object' ? recursiveMerge(
target[prop], src[prop]) : src[prop];
if (typeof src[prop] === 'object') {
target[prop] = recursiveMerge(target[prop], src[prop]);
} else {
clobber(target, prop, src[prop]);
}
}
}
}
@@ -404,18 +476,14 @@ function recursiveMerge(target, src) {
}
module.exports = {
build: function (objects) {
return {
intoButDoNotClobber: function (target) {
include(target, objects, false, false);
},
intoAndClobber: function(target) {
include(target, objects, true, false);
},
intoAndMerge: function(target) {
include(target, objects, true, true);
}
};
buildIntoButDoNotClobber: function(objects, target) {
include(target, objects, false, false);
},
buildIntoAndClobber: function(objects, target) {
include(target, objects, true, false);
},
buildIntoAndMerge: function(objects, target) {
include(target, objects, true, true);
}
};
@@ -701,7 +769,7 @@ module.exports = {
define("cordova/common", function(require, exports, module) {
module.exports = {
objects: {
defaults: {
cordova: {
path: 'cordova',
children: {
@@ -720,6 +788,9 @@ module.exports = {
}
}
},
open : {
path: 'cordova/plugin/InAppBrowser'
},
navigator: {
children: {
notification: {
@@ -737,9 +808,6 @@ module.exports = {
compass:{
path: 'cordova/plugin/compass'
},
connection: {
path: 'cordova/plugin/network'
},
contacts: {
path: 'cordova/plugin/contacts'
},
@@ -907,6 +975,15 @@ module.exports = {
resolveLocalFileSystemURI:{
path: 'cordova/plugin/resolveLocalFileSystemURI'
}
},
clobbers: {
navigator: {
children: {
connection: {
path: 'cordova/plugin/network'
}
}
}
}
};
@@ -961,6 +1038,7 @@ var cordova = require('cordova'),
function androidExec(success, fail, service, action, args) {
// Set default bridge modes if they have not already been set.
// By default, we use the failsafe, since addJavascriptInterface breaks too often
if (jsToNativeBridgeMode === undefined) {
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
}
@@ -1199,7 +1277,7 @@ module.exports = {
exec(null, null, "App", "show", []);
}, [channel.onCordovaReady]);
},
objects: {
clobbers: {
navigator: {
children: {
app:{
@@ -1218,6 +1296,9 @@ module.exports = {
},
MediaError: { // exists natively on Android WebView on Android 4.x
path: "cordova/plugin/MediaError"
},
open: {
path: "cordova/plugin/InAppBrowser"
}
},
merges: {
@@ -3237,6 +3318,25 @@ module.exports = GlobalizationError;
});
// file: lib/common/plugin/InAppBrowser.js
define("cordova/plugin/InAppBrowser", function(require, exports, module) {
var exec = require('cordova/exec');
var InAppBrowser = {
open : function(strUrl, strWindowName, strWindowFeatures) {
exec(null, null, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
return InAppBrowser;
},
close : function() {
exec(null, null, "InAppBrowser", "close", []);
}
};
module.exports = InAppBrowser.open;
});
// file: lib/common/plugin/LocalFileSystem.js
define("cordova/plugin/LocalFileSystem", function(require, exports, module) {
@@ -3673,7 +3773,8 @@ define("cordova/plugin/accelerometer", function(require, exports, module) {
* This class provides access to device accelerometer data.
* @constructor
*/
var utils = require("cordova/utils"),
var argscheck = require('cordova/argscheck'),
utils = require("cordova/utils"),
exec = require("cordova/exec"),
Acceleration = require('cordova/plugin/Acceleration');
@@ -3737,10 +3838,7 @@ var accelerometer = {
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
*/
getCurrentAcceleration: function(successCallback, errorCallback, options) {
// successCallback required
if (typeof successCallback !== "function") {
throw "getCurrentAcceleration must be called with at least a success callback function as first parameter.";
}
argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
var p;
var win = function(a) {
@@ -3749,7 +3847,7 @@ var accelerometer = {
};
var fail = function(e) {
removeListeners(p);
errorCallback(e);
errorCallback && errorCallback(e);
};
p = createCallbackPair(win, fail);
@@ -3769,20 +3867,16 @@ var accelerometer = {
* @return String The watch id that must be passed to #clearWatch to stop watching.
*/
watchAcceleration: function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
// Default interval (10 sec)
var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
// successCallback required
if (typeof successCallback !== "function") {
throw "watchAcceleration must be called with at least a success callback function as first parameter.";
}
// Keep reference to watch id, and report accel readings as often as defined in frequency
var id = utils.createUUID();
var p = createCallbackPair(function(){}, function(e) {
removeListeners(p);
errorCallback(e);
errorCallback && errorCallback(e);
});
listeners.push(p);
@@ -3798,7 +3892,7 @@ var accelerometer = {
if (running) {
// If we're already running then immediately invoke the success callback
// but only if we have retrieved a value, sample code does not check for null ...
if(accel) {
if (accel) {
successCallback(accel);
}
} else {
@@ -4592,7 +4686,8 @@ module.exports = new Capture();
// file: lib/common/plugin/compass.js
define("cordova/plugin/compass", function(require, exports, module) {
var exec = require('cordova/exec'),
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
utils = require('cordova/utils'),
CompassHeading = require('cordova/plugin/CompassHeading'),
CompassError = require('cordova/plugin/CompassError'),
@@ -4607,23 +4702,13 @@ var exec = require('cordova/exec'),
* @param {CompassOptions} options The options for getting the heading data (not used).
*/
getCurrentHeading:function(successCallback, errorCallback, options) {
// successCallback required
if (typeof successCallback !== "function") {
console.log("Compass Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Compass Error: errorCallback is not a function");
return;
}
argscheck.checkArgs('fFO', 'compass.getCurrentHeading', arguments);
var win = function(result) {
var ch = new CompassHeading(result.magneticHeading, result.trueHeading, result.headingAccuracy, result.timestamp);
successCallback(ch);
};
var fail = function(code) {
var fail = errorCallback && function(code) {
var ce = new CompassError(code);
errorCallback(ce);
};
@@ -4643,22 +4728,11 @@ var exec = require('cordova/exec'),
* specifies to watch via a distance filter rather than time.
*/
watchHeading:function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'compass.watchHeading', arguments);
// Default interval (100 msec)
var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100;
var filter = (options !== undefined && options.filter !== undefined) ? options.filter : 0;
// successCallback required
if (typeof successCallback !== "function") {
console.log("Compass Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Compass Error: errorCallback is not a function");
return;
}
var id = utils.createUUID();
if (filter > 0) {
// is an iOS request for watch by filter, no timer needed
@@ -4682,8 +4756,8 @@ var exec = require('cordova/exec'),
// Stop javascript timer & remove from timer list
if (id && timers[id]) {
if (timers[id] != "iOS") {
clearInterval(timers[id]);
} else {
clearInterval(timers[id]);
} else {
// is iOS watch by filter so call into device to stop
exec(null, null, "Compass", "stopHeading", []);
}
@@ -4871,7 +4945,8 @@ for (var key in console) {
// file: lib/common/plugin/contacts.js
define("cordova/plugin/contacts", function(require, exports, module) {
var exec = require('cordova/exec'),
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
ContactError = require('cordova/plugin/ContactError'),
utils = require('cordova/utils'),
Contact = require('cordova/plugin/Contact');
@@ -4890,13 +4965,9 @@ var contacts = {
* @return array of Contacts matching search criteria
*/
find:function(fields, successCB, errorCB, options) {
if (!successCB) {
throw new TypeError("You must specify a success callback for the find command.");
}
if (!fields || (utils.isArray(fields) && fields.length === 0)) {
if (typeof errorCB === "function") {
errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
}
argscheck.checkArgs('afFO', 'contacts.find', arguments);
if (!fields.length) {
errorCB && errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
} else {
var win = function(result) {
var cs = [];
@@ -4917,9 +4988,9 @@ var contacts = {
* @returns new Contact object
*/
create:function(properties) {
var i;
argscheck.checkArgs('O', 'contacts.create', arguments);
var contact = new Contact();
for (i in properties) {
for (var i in properties) {
if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
contact[i] = properties[i];
}
@@ -4935,7 +5006,8 @@ module.exports = contacts;
// file: lib/common/plugin/device.js
define("cordova/plugin/device", function(require, exports, module) {
var channel = require('cordova/channel'),
var argscheck = require('cordova/argscheck'),
channel = require('cordova/channel'),
utils = require('cordova/utils'),
exec = require('cordova/exec');
@@ -4954,6 +5026,7 @@ function Device() {
this.name = null;
this.uuid = null;
this.cordova = null;
this.model = null;
var me = this;
@@ -4965,6 +5038,7 @@ function Device() {
me.name = info.name;
me.uuid = info.uuid;
me.cordova = info.cordova;
me.model = info.model;
channel.onCordovaInfoReady.fire();
},function(e) {
me.available = false;
@@ -4980,20 +5054,7 @@ function Device() {
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
*/
Device.prototype.getInfo = function(successCallback, errorCallback) {
// successCallback required
if (typeof successCallback !== "function") {
console.log("Device Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Device Error: errorCallback is not a function");
return;
}
// Get info
argscheck.checkArgs('fF', 'Device.getInfo', arguments);
exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
};
@@ -5024,7 +5085,8 @@ module.exports = function(successCallback, errorCallback, message, forceAsync) {
// file: lib/common/plugin/geolocation.js
define("cordova/plugin/geolocation", function(require, exports, module) {
var utils = require('cordova/utils'),
var argscheck = require('cordova/argscheck'),
utils = require('cordova/utils'),
exec = require('cordova/exec'),
PositionError = require('cordova/plugin/PositionError'),
Position = require('cordova/plugin/Position');
@@ -5081,9 +5143,7 @@ var geolocation = {
* @param {PositionOptions} options The options for getting the position data. (OPTIONAL)
*/
getCurrentPosition:function(successCallback, errorCallback, options) {
if (arguments.length === 0) {
throw new Error("getCurrentPosition must be called with at least one argument.");
}
argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments);
options = parseParameters(options);
// Timer var that will fire an error callback if no position is retrieved from native
@@ -5159,9 +5219,7 @@ var geolocation = {
* @return String The watch id that must be passed to #clearWatch to stop watching.
*/
watchPosition:function(successCallback, errorCallback, options) {
if (arguments.length === 0) {
throw new Error("watchPosition must be called with at least one argument.");
}
argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments);
options = parseParameters(options);
var id = utils.createUUID();
@@ -5223,7 +5281,8 @@ module.exports = geolocation;
// file: lib/common/plugin/globalization.js
define("cordova/plugin/globalization", function(require, exports, module) {
var exec = require('cordova/exec'),
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
GlobalizationError = require('cordova/plugin/GlobalizationError');
var globalization = {
@@ -5246,18 +5305,7 @@ var globalization = {
* function () {});
*/
getPreferredLanguage:function(successCB, failureCB) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getPreferredLanguage Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getPreferredLanguage Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fF', 'Globalization.getPreferredLanguage', arguments);
exec(successCB, failureCB, "Globalization","getPreferredLanguage", []);
},
@@ -5279,17 +5327,7 @@ getPreferredLanguage:function(successCB, failureCB) {
* function () {});
*/
getLocaleName:function(successCB, failureCB) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getLocaleName Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getLocaleName Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fF', 'Globalization.getLocaleName', arguments);
exec(successCB, failureCB, "Globalization","getLocaleName", []);
},
@@ -5320,27 +5358,9 @@ getLocaleName:function(successCB, failureCB) {
* {formatLength:'short'});
*/
dateToString:function(date, successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.dateToString Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.dateToString Error: failureCB is not a function");
return;
}
if (date instanceof Date){
var dateValue;
dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "dateToString", [{"date": dateValue, "options": options}]);
}
else {
console.log("Globalization.dateToString Error: date is not a Date object");
}
argscheck.checkArgs('dfFO', 'Globalization.dateToString', arguments);
var dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "dateToString", [{"date": dateValue, "options": options}]);
},
@@ -5380,23 +5400,8 @@ dateToString:function(date, successCB, failureCB, options) {
* {selector:'date'});
*/
stringToDate:function(dateString, successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.stringToDate Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.stringToDate Error: failureCB is not a function");
return;
}
if (typeof dateString == "string"){
exec(successCB, failureCB, "Globalization", "stringToDate", [{"dateString": dateString, "options": options}]);
}
else {
console.log("Globalization.stringToDate Error: dateString is not a string");
}
argscheck.checkArgs('sfFO', 'Globalization.stringToDate', arguments);
exec(successCB, failureCB, "Globalization", "stringToDate", [{"dateString": dateString, "options": options}]);
},
@@ -5433,18 +5438,7 @@ stringToDate:function(dateString, successCB, failureCB, options) {
* {formatLength:'short'});
*/
getDatePattern:function(successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getDatePattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getDatePattern Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fFO', 'Globalization.getDatePattern', arguments);
exec(successCB, failureCB, "Globalization", "getDatePattern", [{"options": options}]);
},
@@ -5475,17 +5469,7 @@ getDatePattern:function(successCB, failureCB, options) {
* function () {});
*/
getDateNames:function(successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getDateNames Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getDateNames Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fFO', 'Globalization.getDateNames', arguments);
exec(successCB, failureCB, "Globalization", "getDateNames", [{"options": options}]);
},
@@ -5510,28 +5494,9 @@ getDateNames:function(successCB, failureCB, options) {
* function () {});
*/
isDayLightSavingsTime:function(date, successCB, failureCB) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.isDayLightSavingsTime Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.isDayLightSavingsTime Error: failureCB is not a function");
return;
}
if (date instanceof Date){
var dateValue;
dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "isDayLightSavingsTime", [{"date": dateValue}]);
}
else {
console.log("Globalization.isDayLightSavingsTime Error: date is not a Date object");
}
argscheck.checkArgs('dfF', 'Globalization.isDayLightSavingsTime', arguments);
var dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "isDayLightSavingsTime", [{"date": dateValue}]);
},
/**
@@ -5553,18 +5518,7 @@ isDayLightSavingsTime:function(date, successCB, failureCB) {
* function () {});
*/
getFirstDayOfWeek:function(successCB, failureCB) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getFirstDayOfWeek Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getFirstDayOfWeek Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fF', 'Globalization.getFirstDayOfWeek', arguments);
exec(successCB, failureCB, "Globalization", "getFirstDayOfWeek", []);
},
@@ -5593,24 +5547,8 @@ getFirstDayOfWeek:function(successCB, failureCB) {
* {type:'decimal'});
*/
numberToString:function(number, successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.numberToString Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.numberToString Error: failureCB is not a function");
return;
}
if(typeof number == "number") {
exec(successCB, failureCB, "Globalization", "numberToString", [{"number": number, "options": options}]);
}
else {
console.log("Globalization.numberToString Error: number is not a number");
}
argscheck.checkArgs('nfFO', 'Globalization.numberToString', arguments);
exec(successCB, failureCB, "Globalization", "numberToString", [{"number": number, "options": options}]);
},
/**
@@ -5637,24 +5575,8 @@ numberToString:function(number, successCB, failureCB, options) {
* function () { alert('Error parsing number');});
*/
stringToNumber:function(numberString, successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.stringToNumber Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.stringToNumber Error: failureCB is not a function");
return;
}
if(typeof numberString == "string") {
exec(successCB, failureCB, "Globalization", "stringToNumber", [{"numberString": numberString, "options": options}]);
}
else {
console.log("Globalization.stringToNumber Error: numberString is not a string");
}
argscheck.checkArgs('sfFO', 'Globalization.stringToNumber', arguments);
exec(successCB, failureCB, "Globalization", "stringToNumber", [{"numberString": numberString, "options": options}]);
},
/**
@@ -5690,18 +5612,7 @@ stringToNumber:function(numberString, successCB, failureCB, options) {
* function () {});
*/
getNumberPattern:function(successCB, failureCB, options) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getNumberPattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getNumberPattern Error: failureCB is not a function");
return;
}
argscheck.checkArgs('fFO', 'Globalization.getNumberPattern', arguments);
exec(successCB, failureCB, "Globalization", "getNumberPattern", [{"options": options}]);
},
@@ -5733,24 +5644,8 @@ getNumberPattern:function(successCB, failureCB, options) {
* function () {});
*/
getCurrencyPattern:function(currencyCode, successCB, failureCB) {
// successCallback required
if (typeof successCB != "function") {
console.log("Globalization.getCurrencyPattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getCurrencyPattern Error: failureCB is not a function");
return;
}
if(typeof currencyCode == "string") {
exec(successCB, failureCB, "Globalization", "getCurrencyPattern", [{"currencyCode": currencyCode}]);
}
else {
console.log("Globalization.getCurrencyPattern Error: currencyCode is not a currency code");
}
argscheck.checkArgs('sfF', 'Globalization.getCurrencyPattern', arguments);
exec(successCB, failureCB, "Globalization", "getCurrencyPattern", [{"currencyCode": currencyCode}]);
}
};
@@ -6004,49 +5899,9 @@ if (typeof navigator != 'undefined') {
});
}
var NetworkConnection = function () {
this.type = null;
this._firstRun = true;
this._timer = null;
this.timeout = 500;
var me = this;
channel.onCordovaReady.subscribe(function() {
me.getInfo(function (info) {
me.type = info;
if (info === "none") {
// set a timer if still offline at the end of timer send the offline event
me._timer = setTimeout(function(){
cordova.fireDocumentEvent("offline");
me._timer = null;
}, me.timeout);
} else {
// If there is a current offline event pending clear it
if (me._timer !== null) {
clearTimeout(me._timer);
me._timer = null;
}
cordova.fireDocumentEvent("online");
}
// should only fire this once
if (me._firstRun) {
me._firstRun = false;
channel.onCordovaConnectionReady.fire();
}
},
function (e) {
// If we can't get the network info we should still tell Cordova
// to fire the deviceready event.
if (me._firstRun) {
me._firstRun = false;
channel.onCordovaConnectionReady.fire();
}
console.log("Error initializing Network Connection: " + e);
});
});
};
function NetworkConnection() {
this.type = 'unknown';
}
/**
* Get connection info
@@ -6054,12 +5909,48 @@ var NetworkConnection = function () {
* @param {Function} successCallback The function to call when the Connection data is available
* @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL)
*/
NetworkConnection.prototype.getInfo = function (successCallback, errorCallback) {
// Get info
NetworkConnection.prototype.getInfo = function(successCallback, errorCallback) {
exec(successCallback, errorCallback, "NetworkStatus", "getConnectionInfo", []);
};
module.exports = new NetworkConnection();
var me = new NetworkConnection();
var timerId = null;
var timeout = 500;
channel.onCordovaReady.subscribe(function() {
me.getInfo(function(info) {
me.type = info;
if (info === "none") {
// set a timer if still offline at the end of timer send the offline event
timerId = setTimeout(function(){
cordova.fireDocumentEvent("offline");
timerId = null;
}, timeout);
} else {
// If there is a current offline event pending clear it
if (timerId !== null) {
clearTimeout(timerId);
timerId = null;
}
cordova.fireDocumentEvent("online");
}
// should only fire this once
if (channel.onCordovaConnectionReady.state !== 2) {
channel.onCordovaConnectionReady.fire();
}
},
function (e) {
// If we can't get the network info we should still tell Cordova
// to fire the deviceready event.
if (channel.onCordovaConnectionReady.state !== 2) {
channel.onCordovaConnectionReady.fire();
}
console.log("Error initializing Network Connection: " + e);
});
});
module.exports = me;
});
@@ -6128,7 +6019,8 @@ module.exports = {
// file: lib/common/plugin/requestFileSystem.js
define("cordova/plugin/requestFileSystem", function(require, exports, module) {
var FileError = require('cordova/plugin/FileError'),
var argscheck = require('cordova/argscheck'),
FileError = require('cordova/plugin/FileError'),
FileSystem = require('cordova/plugin/FileSystem'),
exec = require('cordova/exec');
@@ -6140,10 +6032,9 @@ var FileError = require('cordova/plugin/FileError'),
* @param errorCallback invoked if error occurs retrieving file system
*/
var requestFileSystem = function(type, size, successCallback, errorCallback) {
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
var fail = function(code) {
if (typeof errorCallback === 'function') {
errorCallback(new FileError(code));
}
errorCallback && errorCallback(new FileError(code));
};
if (type < 0 || type > 3) {
@@ -6152,7 +6043,7 @@ var requestFileSystem = function(type, size, successCallback, errorCallback) {
// if successful, return a FileSystem object
var success = function(file_system) {
if (file_system) {
if (typeof successCallback === 'function') {
if (successCallback) {
// grab the name and root from the file system object
var result = new FileSystem(file_system.name, file_system.root);
successCallback(result);
@@ -6174,7 +6065,8 @@ module.exports = requestFileSystem;
// file: lib/common/plugin/resolveLocalFileSystemURI.js
define("cordova/plugin/resolveLocalFileSystemURI", function(require, exports, module) {
var DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
var argscheck = require('cordova/argscheck'),
DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
FileEntry = require('cordova/plugin/FileEntry'),
FileError = require('cordova/plugin/FileError'),
exec = require('cordova/exec');
@@ -6186,11 +6078,10 @@ var DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
* @param errorCallback invoked if error occurs retrieving file system entry
*/
module.exports = function(uri, successCallback, errorCallback) {
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
// error callback
var fail = function(error) {
if (typeof errorCallback === 'function') {
errorCallback(new FileError(error));
}
errorCallback && errorCallback(new FileError(error));
};
// sanity check for 'not:valid:filename'
if(!uri || uri.split(":").length > 2) {
@@ -6203,15 +6094,10 @@ module.exports = function(uri, successCallback, errorCallback) {
var success = function(entry) {
var result;
if (entry) {
if (typeof successCallback === 'function') {
if (successCallback) {
// create appropriate Entry object
result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath) : new FileEntry(entry.name, entry.fullPath);
try {
successCallback(result);
}
catch (e) {
console.log('Error invoking callback: ' + e);
}
successCallback(result);
}
}
else {
@@ -6259,6 +6145,30 @@ utils.defineGetter = function(obj, key, func) {
}
};
utils.arrayIndexOf = function(a, item) {
if (a.indexOf) {
return a.indexOf(item);
}
var len = a.length;
for (var i = 0; i < len; ++i) {
if (a[i] == item) {
return i;
}
}
return -1;
};
/**
* Returns whether the item was found in the array.
*/
utils.arrayRemove = function(a, item) {
var index = utils.arrayIndexOf(a, item);
if (index != -1) {
a.splice(index, 1);
}
return index != -1;
};
/**
* Returns an indication of whether the argument is an array or not
*/
@@ -6454,10 +6364,10 @@ window.cordova = require('cordova');
(function (context) {
// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
// We replace it so that properties that can't be clobbered can instead be overridden.
if (typeof navigator != 'undefined') {
var CordovaNavigator = function () {};
CordovaNavigator.prototype = navigator;
navigator = new CordovaNavigator();
if (context.navigator) {
function CordovaNavigator() {}
CordovaNavigator.prototype = context.navigator;
context.navigator = new CordovaNavigator();
}
var channel = require("cordova/channel"),
@@ -6472,17 +6382,13 @@ window.cordova = require('cordova');
platform = require('cordova/platform');
// Drop the common globals into the window object, but be nice and don't overwrite anything.
builder.build(base.objects).intoButDoNotClobber(window);
builder.buildIntoButDoNotClobber(base.defaults, context);
builder.buildIntoAndMerge(base.merges, context);
builder.buildIntoAndClobber(base.clobbers, context);
// Drop the platform-specific globals into the window object
// and clobber any existing object.
builder.build(platform.objects).intoAndClobber(window);
// Merge the platform-specific overrides/enhancements into
// the window object.
if (typeof platform.merges !== 'undefined') {
builder.build(platform.merges).intoAndMerge(window);
}
builder.buildIntoButDoNotClobber(platform.defaults, context);
builder.buildIntoAndMerge(platform.merges, context);
builder.buildIntoAndClobber(platform.clobbers, context);
// Call the platform-specific initialization
platform.initialize();

View File

@@ -19,7 +19,7 @@
<html>
<head>
<title></title>
<script src="cordova-2.2.0.js"></script>
<script src="cordova-2.3.0rc1.js"></script>
</head>
<body>

View File

@@ -10,7 +10,7 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=Google Inc.:Google APIs:16
target=Google Inc.:Google APIs:17
apk-configurations=
renderscript.opt.level=O0
android.library=true

View File

@@ -51,6 +51,7 @@
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
<plugin name="Echo" value="org.apache.cordova.Echo" />
<plugin name="Globalization" value="org.apache.cordova.Globalization"/>
<plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser"/>
</plugins>
</cordova>

View File

@@ -19,6 +19,7 @@
package org.apache.cordova;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
@@ -30,7 +31,7 @@ import java.util.HashMap;
/**
* This class exposes methods in DroidGap that can be called from JavaScript.
*/
public class App extends Plugin {
public class App extends CordovaPlugin {
/**
* Executes the request and returns PluginResult.

View File

@@ -289,6 +289,17 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// If sending base64 image back
if (destType == DATA_URL) {
bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString()));
if (bitmap == null) {
// Try to get the bitmap from intent.
bitmap = (Bitmap)intent.getExtras().get("data");
}
// Double-check the bitmap.
if (bitmap == null) {
Log.d(LOG_TAG, "I either have a null image path or bitmap");
this.failPicture("Unable to create bitmap!");
return;
}
if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif);
@@ -567,6 +578,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options);
if (unscaledBitmap == null) {
return null;
}
return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true);
}

View File

@@ -127,7 +127,7 @@ public class Capture extends CordovaPlugin {
// If the mimeType isn't set the rest will fail
// so let's see if we can determine it.
if (mimeType == null || mimeType.equals("")) {
if (mimeType == null || mimeType.equals("") || "null".equals(mimeType)) {
mimeType = FileUtils.getMimeType(filePath);
}
Log.d(LOG_TAG, "Mime type = " + mimeType);

View File

@@ -1579,7 +1579,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
Uri uri = Uri.parse(path);
return mApp.getActivity().getContentResolver().openInputStream(uri);
}
if (path.startsWith("http:") || path.startsWith("file:")) {
if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
URL url = new URL(path);
return url.openStream();
}

View File

@@ -20,6 +20,8 @@
package org.apache.cordova;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -35,6 +37,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -96,8 +99,8 @@ public class CordovaWebView extends WebView {
private long lastMenuEventTime = 0;
NativeToJsMessageQueue jsMessageQueue;
ExposedJsApi exposedJsApi;
NativeToJsMessageQueue jsMessageQueue;
ExposedJsApi exposedJsApi;
/** custom view created by the browser (a video player for example) */
private View mCustomView;
@@ -181,8 +184,8 @@ public class CordovaWebView extends WebView {
* @param defStyle
* @param privateBrowsing
*/
@TargetApi(11)
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
@TargetApi(11)
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context, attrs, defStyle, privateBrowsing);
if (CordovaInterface.class.isInstance(context))
{
@@ -225,15 +228,28 @@ public class CordovaWebView extends WebView {
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
//Set the nav dump for HTC 2.x devices (disabling for ICS/Jellybean)
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
settings.setNavDump(true);
// Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
try {
Method gingerbread_getMethod = WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
{
gingerbread_getMethod.invoke(settings, true);
}
} catch (NoSuchMethodException e) {
Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
} catch (IllegalArgumentException e) {
Log.d(TAG, "Doing the NavDump failed with bad arguments");
} catch (IllegalAccessException e) {
Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
} catch (InvocationTargetException e) {
Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
}
// Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
// while we do this
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
Level16Apis.enableUniversalAccess(settings);
Level16Apis.enableUniversalAccess(settings);
// Enable database
settings.setDatabaseEnabled(true);
String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
@@ -269,17 +285,19 @@ public class CordovaWebView extends WebView {
}
private void updateUserAgentString() {
this.getSettings().getUserAgentString();
this.getSettings().getUserAgentString();
}
private void exposeJsInterface() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
int SDK_INT = Build.VERSION.SDK_INT;
boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just
// use the prompt bridge instead.
return;
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
} else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
// addJavascriptInterface crashes on the 2.3 emulator.
Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
return;
@@ -590,7 +608,7 @@ public class CordovaWebView extends WebView {
// Check webview first to see if there is a history
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
if (super.canGoBack()) {
printBackForwardList();
printBackForwardList();
super.goBack();
return true;
@@ -688,6 +706,12 @@ public class CordovaWebView extends WebView {
* <log level="DEBUG" />
*/
private void loadConfiguration() {
Activity action = this.cordova.getActivity();
if(action == null)
{
LOG.i("CordovaLog", "There is no activity. Is this on the lock screen?");
return;
}
int id = getResources().getIdentifier("config", "xml", this.cordova.getActivity().getPackageName());
if(id == 0)
{
@@ -815,27 +839,27 @@ public class CordovaWebView extends WebView {
// If back key
if (keyCode == KeyEvent.KEYCODE_BACK) {
// A custom view is currently displayed (e.g. playing a video)
if(mCustomView != null) {
this.hideCustomView();
} else {
// The webview is currently displayed
// If back key is bound, then send event to JavaScript
if (this.bound) {
this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
return true;
} else {
// If not bound
// Go to previous page in webview if it is possible to go back
if (this.backHistory()) {
return true;
}
// If not, then invoke default behaviour
else {
//this.activityState = ACTIVITY_EXITING;
return false;
}
}
}
if(mCustomView != null) {
this.hideCustomView();
} else {
// The webview is currently displayed
// If back key is bound, then send event to JavaScript
if (this.bound) {
this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
return true;
} else {
// If not bound
// Go to previous page in webview if it is possible to go back
if (this.backHistory()) {
return true;
}
// If not, then invoke default behaviour
else {
//this.activityState = ACTIVITY_EXITING;
return false;
}
}
}
}
// Legacy
else if (keyCode == KeyEvent.KEYCODE_MENU) {
@@ -978,14 +1002,14 @@ public class CordovaWebView extends WebView {
}
public void printBackForwardList() {
WebBackForwardList currentList = this.copyBackForwardList();
int currentSize = currentList.getSize();
for(int i = 0; i < currentSize; ++i)
{
WebHistoryItem item = currentList.getItemAtIndex(i);
String url = item.getUrl();
LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url );
}
WebBackForwardList currentList = this.copyBackForwardList();
int currentSize = currentList.getSize();
for(int i = 0; i < currentSize; ++i)
{
WebHistoryItem item = currentList.getItemAtIndex(i);
String url = item.getUrl();
LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url );
}
}
@@ -1002,8 +1026,8 @@ public class CordovaWebView extends WebView {
}
public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "showing Custom View");
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "showing Custom View");
// if a view already exists then immediately terminate the new one
if (mCustomView != null) {
callback.onCustomViewHidden();
@@ -1011,46 +1035,46 @@ public class CordovaWebView extends WebView {
}
// Store the view and its callback for later (to kill it properly)
mCustomView = view;
mCustomViewCallback = callback;
mCustomView = view;
mCustomViewCallback = callback;
// Add the custom view to its container.
ViewGroup parent = (ViewGroup) this.getParent();
parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
// Hide the content view.
this.setVisibility(View.GONE);
// Finally show the custom view container.
parent.setVisibility(View.VISIBLE);
parent.bringToFront();
ViewGroup parent = (ViewGroup) this.getParent();
parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
// Hide the content view.
this.setVisibility(View.GONE);
// Finally show the custom view container.
parent.setVisibility(View.VISIBLE);
parent.bringToFront();
}
public void hideCustomView() {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "Hidding Custom View");
if (mCustomView == null) return;
public void hideCustomView() {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "Hidding Custom View");
if (mCustomView == null) return;
// Hide the custom view.
mCustomView.setVisibility(View.GONE);
// Remove the custom view from its container.
ViewGroup parent = (ViewGroup) this.getParent();
parent.removeView(mCustomView);
mCustomView = null;
mCustomViewCallback.onCustomViewHidden();
// Hide the custom view.
mCustomView.setVisibility(View.GONE);
// Remove the custom view from its container.
ViewGroup parent = (ViewGroup) this.getParent();
parent.removeView(mCustomView);
mCustomView = null;
mCustomViewCallback.onCustomViewHidden();
// Show the content view.
this.setVisibility(View.VISIBLE);
}
/**
* if the video overlay is showing then we need to know
* as it effects back button handling
*
* @return
*/
public boolean isCustomViewShowing() {
return mCustomView != null;
}
}
/**
* if the video overlay is showing then we need to know
* as it effects back button handling
*
* @return
*/
public boolean isCustomViewShowing() {
return mCustomView != null;
}
}

View File

@@ -39,7 +39,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin {
public static final String TAG = "Device";
public static String cordovaVersion = "2.2.0"; // Cordova version
public static String cordovaVersion = "2.3.0rc1"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
@@ -80,9 +80,7 @@ public class Device extends CordovaPlugin {
r.put("platform", Device.platform);
r.put("name", this.getProductName());
r.put("cordova", Device.cordovaVersion);
//JSONObject pg = new JSONObject();
//pg.put("version", Device.CordovaVersion);
//r.put("cordova", pg);
r.put("model", this.getProductName());
callbackContext.success(r);
}
else {

View File

@@ -40,7 +40,6 @@ import android.graphics.Color;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
@@ -156,11 +155,6 @@ public class DroidGap extends Activity implements CordovaInterface {
private static int ACTIVITY_EXITING = 2;
private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down
// The base of the initial URL for our app.
// Does not include file name. Ends with /
// ie http://server/path/
String baseUrl = null;
// Plugin to call when activity result is received
protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning;
@@ -830,7 +824,7 @@ public class DroidGap extends Activity implements CordovaInterface {
// If errorUrl specified, then load it
final String errorUrl = me.getStringProperty("errorUrl", null);
if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
if ((errorUrl != null) && (errorUrl.startsWith("file://") || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
// Load URL on UI thread
me.runOnUiThread(new Runnable() {

View File

@@ -18,6 +18,7 @@
*/
package org.apache.cordova;
import android.webkit.JavascriptInterface;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.api.PluginResult;
import org.json.JSONException;
@@ -37,6 +38,7 @@ import org.json.JSONException;
this.jsMessageQueue = jsMessageQueue;
}
@JavascriptInterface
public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
jsMessageQueue.setPaused(true);
try {
@@ -51,10 +53,12 @@ import org.json.JSONException;
}
}
@JavascriptInterface
public void setNativeToJsBridgeMode(int value) {
jsMessageQueue.setBridgeMode(value);
}
@JavascriptInterface
public String retrieveJsMessages() {
return jsMessageQueue.popAndEncode();
}

View File

@@ -43,6 +43,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
//import android.app.Activity;
@@ -317,8 +318,9 @@ public class FileUtils extends CordovaPlugin {
* @throws InvalidModificationException
* @throws EncodingException
* @throws JSONException
* @throws FileExistsException
*/
private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException {
private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
fileName = stripFileProtocol(fileName);
newParent = stripFileProtocol(newParent);
@@ -406,6 +408,16 @@ public class FileUtils extends CordovaPlugin {
throw new InvalidModificationException("Can't rename a file to a directory");
}
copyAction(srcFile, destFile);
return getEntry(destFile);
}
/**
* Moved this code into it's own method so moveTo could use it when the move is across file systems
*/
private void copyAction(File srcFile, File destFile)
throws FileNotFoundException, IOException {
FileInputStream istream = new FileInputStream(srcFile);
FileOutputStream ostream = new FileOutputStream(destFile);
FileChannel input = istream.getChannel();
@@ -419,8 +431,6 @@ public class FileUtils extends CordovaPlugin {
input.close();
output.close();
}
return getEntry(destFile);
}
/**
@@ -495,7 +505,7 @@ public class FileUtils extends CordovaPlugin {
* @throws InvalidModificationException
* @throws JSONException
*/
private JSONObject moveFile(File srcFile, File destFile) throws JSONException, InvalidModificationException {
private JSONObject moveFile(File srcFile, File destFile) throws IOException, JSONException, InvalidModificationException {
// Renaming a file to an existing directory should fail
if (destFile.exists() && destFile.isDirectory()) {
throw new InvalidModificationException("Can't rename a file to a directory");
@@ -507,6 +517,12 @@ public class FileUtils extends CordovaPlugin {
// Now we have to do things the hard way
// 1) Copy all the old file
// 2) delete the src file
copyAction(srcFile, destFile);
if (destFile.exists()) {
srcFile.delete();
} else {
throw new IOException("moved failed");
}
}
return getEntry(destFile);
@@ -521,8 +537,10 @@ public class FileUtils extends CordovaPlugin {
* @throws JSONException
* @throws IOException
* @throws InvalidModificationException
* @throws NoModificationAllowedException
* @throws FileExistsException
*/
private JSONObject moveDirectory(File srcDir, File destinationDir) throws JSONException, InvalidModificationException {
private JSONObject moveDirectory(File srcDir, File destinationDir) throws IOException, JSONException, InvalidModificationException, NoModificationAllowedException, FileExistsException {
// Renaming a file to an existing directory should fail
if (destinationDir.exists() && destinationDir.isFile()) {
throw new InvalidModificationException("Can't rename a file to a directory");
@@ -546,6 +564,12 @@ public class FileUtils extends CordovaPlugin {
// Now we have to do things the hard way
// 1) Copy all the old files
// 2) delete the src directory
copyDirectory(srcDir, destinationDir);
if (destinationDir.exists()) {
removeDirRecursively(srcDir);
} else {
throw new IOException("moved failed");
}
}
return getEntry(destinationDir);
@@ -960,8 +984,16 @@ public class FileUtils extends CordovaPlugin {
* @return a mime type
*/
public static String getMimeType(String filename) {
// Stupid bug in getFileExtensionFromUrl when the file name has a space
// So we need to replace the space with a url encoded %20
String url = filename.replace(" ", "%20");
MimeTypeMap map = MimeTypeMap.getSingleton();
return map.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(filename));
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension.toLowerCase().equals("3ga")) {
return "audio/3gpp";
} else {
return map.getMimeTypeFromExtension(extension);
}
}
/**
@@ -1045,16 +1077,18 @@ public class FileUtils extends CordovaPlugin {
*/
@SuppressWarnings("deprecation")
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) {
String uri = contentUri.toString();
if (uri.startsWith("content:")) {
final String scheme = contentUri.getScheme();
if (scheme.compareTo("content") == 0) {
String[] proj = { _DATA };
Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} else if (scheme.compareTo("file") == 0) {
return contentUri.getPath();
} else {
return uri;
return contentUri.toString();
}
}
}

View File

@@ -0,0 +1,515 @@
/*
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.InputStream;
import java.util.HashMap;
import java.util.StringTokenizer;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
public class InAppBrowser extends CordovaPlugin {
private static final String NULL = "null";
protected static final String LOG_TAG = "InAppBrowser";
private static final String SELF = "_self";
private static final String SYSTEM = "_system";
private static final String BLANK = "_blank";
private static final String LOCATION = "location";
private static int CLOSE_EVENT = 0;
private static int LOCATION_CHANGED_EVENT = 1;
private String browserCallbackId = null;
private Dialog dialog;
private WebView inAppWebView;
private EditText edittext;
private boolean showLocationBar = true;
private CallbackContext callbackContext;
/**
* Executes the request and returns PluginResult.
*
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript.
* @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 = "";
this.callbackContext = callbackContext;
try {
if (action.equals("open")) {
String url = args.getString(0);
String target = args.optString(1);
if (target == null || target.equals("") || target.equals(NULL)) {
target = SELF;
}
HashMap<String, Boolean> features = parseFeature(args.optString(2));
Log.d(LOG_TAG, "target = " + target);
url = updateUrl(url);
// SELF
if (SELF.equals(target)) {
Log.d(LOG_TAG, "in self");
// load in webview
if (url.startsWith("file://") || url.startsWith("javascript:")
|| this.webView.isUrlWhiteListed(url)) {
this.webView.loadUrl(url);
}
// load in InAppBrowser
else {
result = this.showWebPage(url, features);
}
}
// SYSTEM
else if (SYSTEM.equals(target)) {
Log.d(LOG_TAG, "in system");
result = this.openExternal(url);
}
// BLANK - or anything else
else {
Log.d(LOG_TAG, "in blank");
result = this.showWebPage(url, features);
}
}
else if (action.equals("close")) {
closeDialog();
JSONObject obj = new JSONObject();
obj.put("type", CLOSE_EVENT);
PluginResult pluginResult = new PluginResult(status, obj);
pluginResult.setKeepCallback(false);
this.callbackContext.sendPluginResult(pluginResult);
}
else {
status = PluginResult.Status.INVALID_ACTION;
}
this.callbackContext.sendPluginResult(new PluginResult(status, result));
} catch (JSONException e) {
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
}
return true;
}
/**
* Put the list of features into a hash map
*
* @param optString
* @return
*/
private HashMap<String, Boolean> parseFeature(String optString) {
if (optString.equals(NULL)) {
return null;
} else {
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
StringTokenizer features = new StringTokenizer(optString, ",");
StringTokenizer option;
while(features.hasMoreElements()) {
option = new StringTokenizer(features.nextToken(), "=");
if (option.hasMoreElements()) {
String key = option.nextToken();
Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
map.put(key, value);
}
}
return map;
}
}
/**
* Convert relative URL to full path
*
* @param url
* @return
*/
private String updateUrl(String url) {
Uri newUrl = Uri.parse(url);
if (newUrl.isRelative()) {
url = this.webView.getUrl().substring(0, this.webView.getUrl().lastIndexOf("/")+1) + url;
}
return url;
}
/**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param usePhoneGap Load url in PhoneGap webview
* @return "" if ok, or error message.
*/
public String openExternal(String url) {
try {
Intent intent = null;
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
this.cordova.getActivity().startActivity(intent);
return "";
} catch (android.content.ActivityNotFoundException e) {
Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
return e.toString();
}
}
/**
* Closes the dialog
*/
private void closeDialog() {
// TODO: fire 'exit' event
if (dialog != null) {
dialog.dismiss();
}
}
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
private void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
/**
* Checks to see if it is possible to go forward one page in history, then does so.
*/
private void goForward() {
if (this.inAppWebView.canGoForward()) {
this.inAppWebView.goForward();
}
}
/**
* Navigate to the new page
*
* @param url to load
*/
private void navigate(String url) {
InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
if (!url.startsWith("http") && !url.startsWith("file:")) {
this.inAppWebView.loadUrl("http://" + url);
} else {
this.inAppWebView.loadUrl(url);
}
this.inAppWebView.requestFocus();
}
/**
* Should we show the location bar?
*
* @return boolean
*/
private boolean getShowLocationBar() {
return this.showLocationBar;
}
/**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param jsonObject
*/
public String showWebPage(final String url, HashMap<String, Boolean> features) {
// Determine if we should hide the location bar.
showLocationBar = true;
if (features != null) {
showLocationBar = features.get(LOCATION).booleanValue();
}
// Create dialog in new thread
Runnable runnable = new Runnable() {
/**
* Convert our DIP units to Pixels
*
* @return int
*/
private int dpToPixels(int dipValue) {
int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
(float) dipValue,
cordova.getActivity().getResources().getDisplayMetrics()
);
return value;
}
public void run() {
// Let's create the main dialog
dialog = new Dialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
try {
JSONObject obj = new JSONObject();
obj.put("type", CLOSE_EVENT);
sendUpdate(obj, false);
} catch (JSONException e) {
Log.d(LOG_TAG, "Should never happen");
}
}
});
// Main container layout
LinearLayout main = new LinearLayout(cordova.getActivity());
main.setOrientation(LinearLayout.VERTICAL);
// Toolbar layout
RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, this.dpToPixels(44)));
toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
toolbar.setHorizontalGravity(Gravity.LEFT);
toolbar.setVerticalGravity(Gravity.TOP);
// Action Button Container layout
RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
actionButtonContainer.setId(1);
// Back button
Button back = new Button(cordova.getActivity());
RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
back.setLayoutParams(backLayoutParams);
back.setContentDescription("Back Button");
back.setId(2);
back.setText("<");
back.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goBack();
}
});
// Forward button
Button forward = new Button(cordova.getActivity());
RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
forward.setLayoutParams(forwardLayoutParams);
forward.setContentDescription("Forward Button");
forward.setId(3);
forward.setText(">");
forward.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goForward();
}
});
// Edit Text Box
edittext = new EditText(cordova.getActivity());
RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
edittext.setLayoutParams(textLayoutParams);
edittext.setId(4);
edittext.setSingleLine(true);
edittext.setText(url);
edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
edittext.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
navigate(edittext.getText().toString());
return true;
}
return false;
}
});
// Close button
Button close = new Button(cordova.getActivity());
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
close.setLayoutParams(closeLayoutParams);
forward.setContentDescription("Close Button");
close.setId(5);
close.setText("Done");
close.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
closeDialog();
}
});
// WebView
inAppWebView = new WebView(cordova.getActivity());
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
inAppWebView.setWebChromeClient(new WebChromeClient());
WebViewClient client = new InAppBrowserClient(edittext);
inAppWebView.setWebViewClient(client);
WebSettings settings = inAppWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setBuiltInZoomControls(true);
settings.setPluginsEnabled(true);
settings.setDomStorageEnabled(true);
inAppWebView.loadUrl(url);
inAppWebView.setId(6);
inAppWebView.getSettings().setLoadWithOverviewMode(true);
inAppWebView.getSettings().setUseWideViewPort(true);
inAppWebView.requestFocus();
inAppWebView.requestFocusFromTouch();
// Add the back and forward buttons to our action button container layout
actionButtonContainer.addView(back);
actionButtonContainer.addView(forward);
// Add the views to our toolbar
toolbar.addView(actionButtonContainer);
toolbar.addView(edittext);
toolbar.addView(close);
// Don't add the toolbar if its been disabled
if (getShowLocationBar()) {
// Add our toolbar to our main view/layout
main.addView(toolbar);
}
// Add our webview to our main view/layout
main.addView(inAppWebView);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.FILL_PARENT;
lp.height = WindowManager.LayoutParams.FILL_PARENT;
dialog.setContentView(main);
dialog.show();
dialog.getWindow().setAttributes(lp);
}
private Bitmap loadDrawable(String filename) throws java.io.IOException {
InputStream input = cordova.getActivity().getAssets().open(filename);
return BitmapFactory.decodeStream(input);
}
};
this.cordova.getActivity().runOnUiThread(runnable);
return "";
}
/**
* Create a new plugin result and send it back to JavaScript
*
* @param obj a JSONObject contain event payload information
*/
private void sendUpdate(JSONObject obj, boolean keepCallback) {
if (this.browserCallbackId != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
result.setKeepCallback(keepCallback);
this.callbackContext.sendPluginResult(result);
}
}
/**
* The webview client receives notifications about appView
*/
public class InAppBrowserClient extends WebViewClient {
EditText edittext;
/**
* Constructor.
*
* @param mContext
* @param edittext
*/
public InAppBrowserClient(EditText mEditText) {
this.edittext = mEditText;
}
/**
* Notify the host application that a page has started loading.
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
String newloc;
if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
newloc = url;
} else {
newloc = "http://" + url;
}
if (!newloc.equals(edittext.getText().toString())) {
edittext.setText(newloc);
}
// TODO: Fire 'loadstart' event
try {
JSONObject obj = new JSONObject();
obj.put("type", LOCATION_CHANGED_EVENT);
obj.put("location", url);
sendUpdate(obj, true);
} catch (JSONException e) {
Log.d("InAppBrowser", "This should never happen");
}
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// TODO: Fire 'loadstop' event
}
}
}

View File

@@ -147,13 +147,6 @@ public class NetworkManager extends CordovaPlugin {
}
}
/**
* Stop the network receiver on navigation.
*/
public void onReset() {
this.onDestroy();
}
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------

View File

@@ -59,24 +59,17 @@
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".CordovaWebViewTestActivity" >
android:name=".actions.CordovaWebViewTestActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="tests" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".JailActivity" >
android:name=".actions.backbbuttonmultipage" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
@@ -86,8 +79,8 @@
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".CordovaDriverAction" >
<intent-filter >
android:name=".actions.background" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
@@ -96,62 +89,181 @@
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".CordovaActivity" >
android:name=".actions.basicauth" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="splashscreen" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.CordovaActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="timeout" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.CordovaDriverAction" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="htmlnotfound" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.errorurl" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="errorurl" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="userwebview" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.htmlnotfound" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="menus" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.iframe" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="loading" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.jqmtabbackbutton" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="lifecycle" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.lifecycle" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="jqmtabbackbutton" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.loading" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="backbuttonmultipage" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.menus" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="whitelist" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.splashscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="background" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.tests" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="iframe" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.timeout" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="xhr" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.userwebview" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="basicauth" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.whitelist" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="fullscreen" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.xhr" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name="backgroundcolor" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.backbuttonmultipage" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
</application>
</manifest>

File diff suppressed because it is too large Load Diff

View File

@@ -45,24 +45,24 @@
<h4>Cordova Version: <span id="cordova">&nbsp;</span></h4>
</div>
<div id="info">
<h4>Run each of the tests below:</h4>
<h4>Run each of the test activities below:</h4>
</div>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.jqmtabbackbutton');">Backbutton jQM tab</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.backbuttonmultipage');">Backbutton with multiple pages</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.backgroundcolor');">Background Color</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.basicauth');">Basic Authentication</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.errorurl');">Error URL</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.fullscreen');">Full Screen</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.htmlnotfound');">HTML not found</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.iframe');">IFrame</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.lifecycle');">Lifecycle</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.loading');">Loading indicator</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.menus');">Menus</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.background');">No multitasking</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.splashscreen');">Splash screen</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.timeout');">Load timeout</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.userwebview');">User WebView/Client/Chrome</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.whitelist');">Whitelist</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.xhr');">XHR</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.jqmtabbackbutton');">Backbutton jQM tab</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.backbuttonmultipage');">Backbutton with multiple pages</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.backgroundcolor');">Background Color</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.basicauth');">Basic Authentication</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.errorurl');">Error URL</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.fullscreen');">Full Screen</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.htmlnotfound');">HTML not found</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.iframe');">IFrame</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.lifecycle');">Lifecycle</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.loading');">Loading indicator</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.menus');">Menus</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.background');">No multitasking</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.splashscreen');">Splash screen</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.timeout');">Load timeout</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.userwebview');">User WebView/Client/Chrome</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.whitelist');">Whitelist</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.actions.xhr');">XHR</button>
</body>
</html>

56
test/res/xml/config.xml Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<cordova>
<!--
access elements control the Android whitelist.
Domains are assumed blocked unless set otherwise
-->
<access origin="http://127.0.0.1*"/> <!-- allow local pages -->
<!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
<!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
<access origin=".*"/>
<log level="DEBUG"/>
<preference name="useBrowserHistory" value="true" />
<plugins>
<plugin name="App" value="org.apache.cordova.App"/>
<plugin name="Activity" value="org.apache.cordova.test.ActivityPlugin"/>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
<plugin name="Device" value="org.apache.cordova.Device"/>
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
<plugin name="File" value="org.apache.cordova.FileUtils"/>
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
<plugin name="Echo" value="org.apache.cordova.Echo" />
</plugins>
</cordova>

View File

@@ -22,9 +22,11 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.actions.backbuttonmultipage;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
@@ -96,6 +98,54 @@ public class BackButtonMultiPageTest extends ActivityInstrumentationTestCase2<ba
assertTrue(didGoBack);
}
public void testViaBackButtonOnView() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(testView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
public void testViaBackButtonOnLayout() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(containerView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
private void sleep() {
try {
Thread.sleep(TIMEOUT);

View File

@@ -21,6 +21,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.test.actions.CordovaActivity;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;

View File

@@ -20,6 +20,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.test.actions.CordovaWebViewTestActivity;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
@@ -48,10 +49,13 @@ public class CordovaTest extends
}
public void testForCordovaView() {
//Sleep for no reason!!!!
sleep();
String className = testView.getClass().getSimpleName();
assertTrue(className.equals("CordovaWebView"));
}
/*
/*
public void testForPluginManager() {
CordovaWebView v = (CordovaWebView) testView;
PluginManager p = v.getPluginManager();

View File

@@ -22,6 +22,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.actions.errorurl;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;

View File

@@ -22,6 +22,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.test.actions.CordovaWebViewTestActivity;
import android.content.Context;
import android.content.res.AssetManager;

View File

@@ -22,6 +22,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.actions.htmlnotfound;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;

View File

@@ -21,6 +21,8 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.test.actions.iframe;
import android.test.ActivityInstrumentationTestCase2;
public class IFrameTest extends ActivityInstrumentationTestCase2<iframe> {

View File

@@ -21,6 +21,8 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.test.actions.jqmtabbackbutton;
import android.test.ActivityInstrumentationTestCase2;
public class JQMTabTest extends ActivityInstrumentationTestCase2<jqmtabbackbutton> {

View File

@@ -21,6 +21,8 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.test.actions.lifecycle;
import android.test.ActivityInstrumentationTestCase2;
public class LifecycleTest extends ActivityInstrumentationTestCase2<lifecycle> {

View File

@@ -21,6 +21,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.test.actions.CordovaWebViewTestActivity;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;

View File

@@ -22,6 +22,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.actions.splashscreen;
import android.app.Dialog;
import android.test.ActivityInstrumentationTestCase2;

View File

@@ -24,6 +24,7 @@ package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewClient;
import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.test.actions.userwebview;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;

View File

@@ -21,6 +21,8 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.test.actions.xhr;
import android.test.ActivityInstrumentationTestCase2;
public class XhrTest extends ActivityInstrumentationTestCase2<xhr> {

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import org.apache.cordova.DroidGap;

View File

@@ -17,7 +17,7 @@
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import java.util.concurrent.ExecutorService;

View File

@@ -17,13 +17,18 @@
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.test.R;
import org.apache.cordova.test.R.id;
import org.apache.cordova.test.R.layout;
import android.app.Activity;
import android.content.Context;
@@ -33,6 +38,8 @@ import android.os.Bundle;
public class CordovaWebViewTestActivity extends Activity implements CordovaInterface {
CordovaWebView cordovaWebView;
private final ExecutorService threadPool = Executors.newCachedThreadPool();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -46,14 +53,6 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
}
public void onDestroy()
{
super.onDestroy();
if (cordovaWebView.pluginManager != null) {
cordovaWebView.pluginManager.onDestroy();
}
}
public Context getContext() {
return this;
}
@@ -69,9 +68,9 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
}
//Note: This must always return an activity!
public Activity getActivity() {
// TODO Auto-generated method stub
return null;
return this;
}
@Deprecated
@@ -87,6 +86,19 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
public ExecutorService getThreadPool() {
// TODO Auto-generated method stub
return null;
return threadPool;
}
@Override
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
super.onDestroy();
if (cordovaWebView != null) {
// Send destroy event to JavaScript
cordovaWebView.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
cordovaWebView.handleDestroy();
}
}
}

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import android.view.ContextMenu;

View File

@@ -16,10 +16,12 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;
import org.apache.cordova.test.R;
import org.apache.cordova.test.R.drawable;
public class splashscreen extends DroidGap {
@Override

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import android.webkit.WebView;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import android.webkit.WebView;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.test.actions;
import android.os.Bundle;
import org.apache.cordova.*;