Commit 361bc379 authored by Jennie Shi's avatar Jennie Shi

WebviewChange

parent eab5633c
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
<allow-intent href="mailto:*" /> <allow-intent href="mailto:*" />
<allow-intent href="tel:*" /> <allow-intent href="tel:*" />
<allow-navigation href="mailto:*" /> <allow-navigation href="mailto:*" />
<allow-navigation href="http://localhost:8080/*"/>
<allow-navigation href="tel:*" /> <allow-navigation href="tel:*" />
<allow-navigation href="http://wechat.hand-china.com/*" /> <allow-navigation href="http://wechat.hand-china.com/*" />
<allow-navigation href="https://www.pgyer.com/*" /> <allow-navigation href="https://www.pgyer.com/*" />
...@@ -32,6 +33,10 @@ ...@@ -32,6 +33,10 @@
<feature name="StatusBar"> <feature name="StatusBar">
<param name="ios-package" onload="true" value="CDVStatusBar" /> <param name="ios-package" onload="true" value="CDVStatusBar" />
</feature> </feature>
<feature name="CDVWKWebViewEngine">
<param name="ios-package" value="CDVWKWebViewEngine" />
</feature>
<preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />
<platform name="android"> <platform name="android">
<allow-intent href="market:*" /> <allow-intent href="market:*" />
<hook src="hooks/copy-build-extras-gradle.js" type="before_build" /> <hook src="hooks/copy-build-extras-gradle.js" type="before_build" />
......
...@@ -2699,6 +2699,11 @@ ...@@ -2699,6 +2699,11 @@
"resolved": "https://registry.npm.taobao.org/cordova-plugin-device/download/cordova-plugin-device-2.0.3.tgz?cache=0&sync_timestamp=1562089310547&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcordova-plugin-device%2Fdownload%2Fcordova-plugin-device-2.0.3.tgz", "resolved": "https://registry.npm.taobao.org/cordova-plugin-device/download/cordova-plugin-device-2.0.3.tgz?cache=0&sync_timestamp=1562089310547&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcordova-plugin-device%2Fdownload%2Fcordova-plugin-device-2.0.3.tgz",
"integrity": "sha1-wrQbfv0EVd0Jf4k1bYW/3V2t6w8=" "integrity": "sha1-wrQbfv0EVd0Jf4k1bYW/3V2t6w8="
}, },
"cordova-plugin-ionic-webview": {
"version": "4.1.3",
"resolved": "https://registry.npm.taobao.org/cordova-plugin-ionic-webview/download/cordova-plugin-ionic-webview-4.1.3.tgz",
"integrity": "sha1-fzljIIcIlR/t2XXAgIpdJzgoEqc="
},
"cordova-plugin-whitelist": { "cordova-plugin-whitelist": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npm.taobao.org/cordova-plugin-whitelist/download/cordova-plugin-whitelist-1.3.4.tgz", "resolved": "https://registry.npm.taobao.org/cordova-plugin-whitelist/download/cordova-plugin-whitelist-1.3.4.tgz",
......
{
"prepare_queue": {
"installed": [],
"uninstalled": []
},
"config_munge": {
"files": {}
},
"installed_plugins": {},
"dependent_plugins": {}
}
Apache Cordova
Copyright 2014 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org)
This software includes software developed at Intel Corporation.
Copyright 2014 Intel Corporation
### Directions for Non-CLI Android-Only cordova project
* Pull down the Cordova Android
```
$ git clone https://github.com/apache/cordova-android.git
```
* Generate a project, e.g creating HelloWorld
```
$ /path/to/cordova-android/bin/create hello com.example.hello HelloWorld
```
* Navigate to the project folder
```
$ cd hello
```
* Install Crosswalk engine plugin by plugman (version >= 0.22.17)
```
$ plugman install --platform android --plugin https://github.com/MobileChromeApps/cordova-crosswalk-engine.git --project .
```
* Build
```
$ ./cordova/build
```
The build script will automatically fetch the Crosswalk WebView libraries from Crosswalk project download site (https://download.01.org/crosswalk/releases/crosswalk/android/) and build for both X86 and ARM architectures.
For example, building HelloWorld generates:
```
/path/to/hello/build/outputs/apk/hello-x86-debug.apk
/path/to/hello/build/outputs/apk/hello-armv7-debug.apk
```
# cordova-plugin-crosswalk-webview
Makes your Cordova application use the [Crosswalk WebView](https://crosswalk-project.org/)
instead of the System WebView. Requires cordova-android 4.0 or greater.
### Benefits
* WebView doesn't change depending on Android version
* Capabilities: such as WebRTC, WebAudio, Web Components
* Performance improvements (compared to older system webviews)
### Drawbacks
* Increased memory footprint
* An overhead of ~30MB (as reported by the RSS column of ps)
* Increased APK size (about 17MB)
* Increased size on disk when installed (about 50MB)
* Crosswalk WebView stores data (IndexedDB, LocalStorage, etc) separately from System WebView
* You'll need to manually migrate local data when switching between the two (note: this is fixed in Crosswalk 15)
### Install
The following directions are for cordova-cli (most people). Alternatively you can use the [Android platform scripts workflow](PlatformScriptsWorkflow.md).
* Open an existing cordova project, with cordova-android 4.0.0+, and using the latest CLI. Crosswalk variables can be configured as an option when installing the plugin
* Add this plugin
```
$ cordova plugin add cordova-plugin-crosswalk-webview
```
* Build
```
$ cordova build android
```
The build script will automatically fetch the Crosswalk WebView libraries from Crosswalk project download site (https://download.01.org/crosswalk/releases/crosswalk/android/maven2/) and build for both X86 and ARM architectures.
For example, building android with Crosswalk generates:
```
/path/to/hello/platforms/android/build/outputs/apk/hello-x86-debug.apk
/path/to/hello/platforms/android/build/outputs/apk/hello-armv7-debug.apk
```
Note that you might have to run `cordova clean` before building, if you previously built the app without cordova-plugin-crosswalk-webview. Also, manually uninstall the app from the device/emulator before attempting to install the crosswalk-enabled version.
Also note that it is also possible to publish a multi-APK application on the Play Store that uses Crosswalk for Pre-L devices, and the (updatable) system webview for L+:
To build Crosswalk-enabled apks, add this plugin and run:
$ cordova build --release
To build System-webview apk, remove this plugin and run:
$ cordova build --release -- --minSdkVersion=21
### Configure
You can try out a different Crosswalk version by specifying certain variables while installing the plugin, or by changing the value of `xwalkVersion` in your `config.xml` after installing the plugin. Some examples:
<!-- These are all equivalent -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="org.xwalk:xwalk_core_library:14+"
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="xwalk_core_library:14+"
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="14+"
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="14"
<preference name="xwalkVersion" value="org.xwalk:xwalk_core_library:14+" />
<preference name="xwalkVersion" value="xwalk_core_library:14+" />
<preference name="xwalkVersion" value="14+" />
<preference name="xwalkVersion" value="14" />
You can also use a Crosswalk beta version. Some examples:
<!-- These are all equivalent -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="org.xwalk:xwalk_core_library_beta:14+"
<preference name="xwalkVersion" value="org.xwalk:xwalk_core_library_beta:14+" />
You can set [command-line flags](http://peter.sh/experiments/chromium-command-line-switches/) as well:
<!-- This is the default -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_COMMANDLINE="--disable-pull-to-refresh-effect"
<preference name="xwalkCommandLine" value="--disable-pull-to-refresh-effect" />
You can use the Crosswalk [shared mode](https://crosswalk-project.org/documentation/shared_mode.html) which allows multiple Crosswalk applications to share one Crosswalk runtime downloaded from the Play Store.
<!-- These are all equivalent -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_MODE="shared"
<preference name="xwalkMode" value="shared" />
You can also use a Crosswalk beta version on shared mode, e.g.:
<!-- Using a Crosswalk shared mode beta version -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="org.xwalk:xwalk_shared_library_beta:14+"
You can use the Crosswalk [lite mode](https://crosswalk-project.org/documentation/crosswalk_lite.html) which is the Crosswalk runtime designed to be as small as possible by removing less common libraries and features and compressing the APK.
<!-- These are all equivalent -->
cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_MODE="lite"
<preference name="xwalkMode" value="lite" />
You can set background color with the preference of BackgroundColor.
<!-- Set red background color -->
<preference name="BackgroundColor" value="0xFFFF0000" />
You can also set user agent with the preference of xwalkUserAgent.
<preference name="xwalkUserAgent" value="customer UA" />
### Release Notes
#### 2.2.0 (November 4, 2016)
* Uses the latest Crosswalk 22 stable version by default
* Keep compatible for Cordova-android 6.0 with evaluating Javascript bridge
#### 2.1.0 (September 9, 2016)
* Uses the latest Crosswalk 21 stable version by default
#### 2.0.0 (August 17, 2016)
* Uses the latest Crosswalk 20 stable version by default
* Discontinue support for Android 4.0 (ICS) in Crosswalk starting with version 20
#### 1.8.0 (June 30, 2016)
* Uses the latest Crosswalk 19 stable version by default
#### 1.7.0 (May 4, 2016)
* Uses the latest Crosswalk 18 stable version by default
* Support to use [Crosswalk Lite](https://crosswalk-project.org/documentation/crosswalk_lite.html), It's possible to specify lite value with the variable of XWALK_MODE at install plugin time.
* [Cordova screenshot plugin](https://github.com/gitawego/cordova-screenshot.git) can capture the visible content of web page with Crosswalk library.
* Doesn't work with Crosswalk 17 and earlier
#### 1.6.0 (March 11, 2016)
* Uses the latest Crosswalk 17 stable version by default
* Support to [package apps for 64-bit devices](https://crosswalk-project.org/documentation/android/android_64bit.html), it's possible to specify 64-bit targets using the `--xwalk64bit` option in the build command:
cordova build android --xwalk64bit
#### 1.5.0 (January 18, 2016)
* Uses the latest Crosswalk 16 stable version by default
* The message of xwalk's ready can be listened
#### 1.4.0 (November 5, 2015)
* Uses the latest Crosswalk 15 stable version by default
* Support User Agent and Background Color configuration preferences
* Compatible with the newest Cordova version 5.3.4
#### 1.3.0 (August 28, 2015)
* Crosswalk variables can be configured as an option via CLI
* Support for [Crosswalk's shared mode](https://crosswalk-project.org/documentation/shared_mode.html) via the XWALK_MODE install variable or xwalkMode preference
* Uses the latest Crosswalk 14 stable version by default
* The ANIMATABLE_XWALK_VIEW preference is false by default
* Doesn't work with Crosswalk 14.43.343.17 and earlier
#### 1.2.0 (April 22, 2015)
* Made Crosswalk command-line configurable via `<preference name="xwalkCommandLine" value="..." />`
* Disabled pull-down-to-refresh by default
#### 1.1.0 (April 21, 2015)
* Based on Crosswalk v13
* Made Crosswalk version configurable via `<preference name="xwalkVersion" value="..." />`
#### 1.0.0 (Mar 25, 2015)
* Initial release
* Based on Crosswalk v11
#!/usr/bin/env node
module.exports = function(context) {
/** @external */
var deferral = context.requireCordovaModule('q').defer(),
UpdateConfig = require('./../update_config.js'),
updateConfig = new UpdateConfig(context);
/** Main method */
var main = function() {
// Remove the xwalk variables
updateConfig.afterBuild64bit();
deferral.resolve();
};
main();
return deferral.promise;
};
#!/usr/bin/env node
module.exports = function(context) {
/** @external */
var deferral = context.requireCordovaModule('q').defer(),
UpdateConfig = require('./../update_config.js'),
updateConfig = new UpdateConfig(context);
/** Main method */
var main = function() {
// Add xwalk preference to config.xml
updateConfig.addPreferences();
deferral.resolve();
};
main();
return deferral.promise;
};
#!/usr/bin/env node
module.exports = function(context) {
/** @external */
var deferral = context.requireCordovaModule('q').defer(),
UpdateConfig = require('./../update_config.js'),
updateConfig = new UpdateConfig(context);
/** Main method */
var main = function() {
// Remove the xwalk variables
updateConfig.beforeBuild64bit();
deferral.resolve();
};
main();
return deferral.promise;
};
#!/usr/bin/env node
module.exports = function(context) {
/** @external */
var deferral = context.requireCordovaModule('q').defer(),
UpdateConfig = require('./../update_config.js'),
updateConfig = new UpdateConfig(context);
/** Main method */
var main = function() {
// Remove the xwalk variables
updateConfig.removePreferences();
deferral.resolve();
};
main();
return deferral.promise;
};
#!/usr/bin/env node
module.exports = function(context) {
var ConfigParser, XmlHelpers;
try {
// cordova-lib >= 5.3.4 doesn't contain ConfigParser and xml-helpers anymore
ConfigParser = context.requireCordovaModule("cordova-common").ConfigParser;
XmlHelpers = context.requireCordovaModule("cordova-common").xmlHelpers;
} catch (e) {
ConfigParser = context.requireCordovaModule("cordova-lib/src/configparser/ConfigParser");
XmlHelpers = context.requireCordovaModule("cordova-lib/src/util/xml-helpers");
}
/** @external */
var fs = context.requireCordovaModule('fs'),
path = context.requireCordovaModule('path'),
et = context.requireCordovaModule('elementtree');
/** @defaults */
var xwalkVariables = {},
argumentsString = context.cmdLine,
pluginConfigurationFile = path.join(context.opts.plugin.dir, 'plugin.xml'),
androidPlatformDir = path.join(context.opts.projectRoot,
'platforms', 'android'),
projectConfigurationFile = path.join(context.opts.projectRoot,
'config.xml'),
platformConfigurationFile = path.join(androidPlatformDir,
'res', 'xml', 'config.xml'),
projectManifestFile = path.join(androidPlatformDir,
'AndroidManifest.xml'),
xwalk64bit = "xwalk64bit",
xwalkLiteVersion = "",
specificVersion = false;
/** Init */
var CordovaConfig = new ConfigParser(platformConfigurationFile);
var addPermission = function() {
var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
XmlHelpers.graftXML(projectManifestXmlRoot, [child], '/manifest');
fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
}
var removePermission = function() {
var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
XmlHelpers.pruneXML(projectManifestXmlRoot, [child], '/manifest');
fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
}
var defaultPreferences = function() {
var pluginPreferences = {};
var pluginXmlRoot = XmlHelpers.parseElementtreeSync(pluginConfigurationFile),
tagName = "preference",
containerName = "config-file",
targetPlatform = 'android',
targetPlatformTag = pluginXmlRoot.find('./platform[@name="' + targetPlatform + '"]');
var tagsInRoot = pluginXmlRoot.findall(tagName) || [],
tagsInPlatform = targetPlatformTag ? targetPlatformTag.findall(tagName) : [],
tagsInContainer = targetPlatformTag ? targetPlatformTag.findall(containerName) : [],
tagsList = tagsInRoot.concat(tagsInContainer);
// Parses <preference> tags within <config-file>-blocks
tagsList.map(function(prefTag) {
prefTag.getchildren().forEach(function(element) {
if ((element.tag == 'preference') && (element.attrib['name']) && element.attrib['default']) {
// Don't add xwalkLiteVersion in the app/config.xml
if (element.attrib['name'] == "xwalkLiteVersion") {
xwalkLiteVersion = element.attrib['default'];
} else {
pluginPreferences[element.attrib['name']] = element.attrib['default'];
}
}
});
});
return pluginPreferences;
}
/** The style of name align with config.xml */
var setConfigPreference = function(name, value) {
var trimName = name.replace('_', '');
for (var localName in xwalkVariables) {
if (localName.toUpperCase() == trimName.toUpperCase()) {
xwalkVariables[localName] = value;
if (localName == 'xwalkVersion') {
specificVersion = true;
}
}
}
}
/** Pase the cli command to get the specific preference*/
var parseCliPreference = function() {
var commandlineVariablesList = argumentsString.split('--variable');
if (commandlineVariablesList) {
commandlineVariablesList.forEach(function(element) {
element = element.trim();
if(element && element.indexOf('XWALK') == 0) {
var preference = element.split('=');
if (preference && preference.length == 2) {
setConfigPreference(preference[0], preference[1]);
}
}
});
}
}
/** Add preference */
this.addPreferences = function() {
// Pick the xwalk variables with the cli preferences
// parseCliPreference();
// Add the permission of writing external storage when using shared mode
if (CordovaConfig.getGlobalPreference('xwalkMode') == 'shared') {
addPermission();
}
// Configure the final value in the config.xml
// var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
// var preferenceUpdated = false;
// for (var name in xwalkVariables) {
// var child = configXmlRoot.find('./preference[@name="' + name + '"]');
// if(!child) {
// preferenceUpdated = true;
// child = et.XML('<preference name="' + name + '" value="' + xwalkVariables[name] + '" />');
// XmlHelpers.graftXML(configXmlRoot, [child], '/*');
// }
// }
// if(preferenceUpdated) {
// fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
// }
}
/** Remove preference*/
this.removePreferences = function() {
if (CordovaConfig.getGlobalPreference('xwalkMode') == 'shared') {
// Add the permission of write_external_storage in shared mode
removePermission();
}
// var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
// for (var name in xwalkVariables) {
// var child = configXmlRoot.find('./preference[@name="' + name + '"]');
// if (child) {
// XmlHelpers.pruneXML(configXmlRoot, [child], '/*');
// }
// }
// fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
}
var build64bit = function() {
var build64bit = false;
var commandlineVariablesList = argumentsString.split('--');
if (commandlineVariablesList) {
commandlineVariablesList.forEach(function(element) {
element = element.trim();
if(element && element.indexOf(xwalk64bit) == 0) {
build64bit = true;
}
});
}
return build64bit;
}
this.beforeBuild64bit = function() {
if(build64bit()) {
var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
var child = configXmlRoot.find('./preference[@name="' + xwalk64bit + '"]');
if(!child) {
child = et.XML('<preference name="' + xwalk64bit + '" value="' + xwalk64bit + '" />');
XmlHelpers.graftXML(configXmlRoot, [child], '/*');
fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
}
}
}
this.afterBuild64bit = function() {
if(build64bit()) {
var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
var child = configXmlRoot.find('./preference[@name="' + xwalk64bit + '"]');
if (child) {
XmlHelpers.pruneXML(configXmlRoot, [child], '/*');
fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
}
}
console.log("Crosswalk info:");
console.log(" After much discussion and analysis of the market,");
console.log(" we have decided to discontinue support for Android 4.0 (ICS) in Crosswalk starting with version 20,");
console.log(" so the minSdkVersion of Cordova project is configured to 16 by default. \n");
}
xwalkVariables = defaultPreferences();
};
{
"name": "cordova-plugin-crosswalk-webview",
"version": "2.2.0",
"description": "Changes the default WebView to CrossWalk",
"cordova": {
"id": "cordova-plugin-crosswalk-webview",
"platforms": [
"android"
]
},
"repository": {
"type": "git",
"url": "https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview.git"
},
"keywords": [
"cordova",
"chromium",
"crosswalk",
"webview",
"engine",
"ecosystem:cordova",
"cordova-android"
],
"engines": {
"cordovaDependencies": {
"2.0.0": {
"cordova": ">=5.2.0",
"cordova-android": "4 - 5"
},
"2.1.0": {
"cordova": ">=5.2.0",
"cordova-android": "4 - 5"
},
"2.2.0": {
"cordova": ">=5.2.0",
"cordova-android": ">=6"
},
"3.0.0": {
"cordova": ">100"
}
}
},
"author": "",
"license": "Apache 2.0",
"bugs": {
"url": "https://crosswalk-project.org/jira"
},
"homepage": "https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview"
}
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-crosswalk-webview"
version="2.2.0">
<name>Crosswalk WebView Engine</name>
<description>Changes the default WebView to CrossWalk</description>
<license>Apache 2.0</license>
<keywords>cordova,chromium,crosswalk,webview</keywords>
<repo>https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview</repo>
<issue>https://crosswalk-project.org/jira</issue>
<engines>
<engine name="cordova-android" version=">=6"/>
<engine name="cordova-plugman" version=">=5.2.0"/><!-- needed for gradleReference support -->
</engines>
<!-- android -->
<platform name="android">
<preference name="XWALK_VERSION" default="22+"/>
<preference name="XWALK_LITEVERSION" default="xwalk_core_library_canary:17+"/>
<preference name="XWALK_COMMANDLINE" default="--disable-pull-to-refresh-effect"/>
<preference name="XWALK_MODE" default="embedded" />
<preference name="XWALK_MULTIPLEAPK" default="true" />
<config-file target="res/xml/config.xml" parent="/*">
<preference name="webView" value="org.crosswalk.engine.XWalkWebViewEngine"/>
<preference name="xwalkVersion" value="$XWALK_VERSION"/>
<preference name="xwalkLiteVersion" value="$XWALK_LITEVERSION"/>
<preference name="xwalkCommandLine" value="$XWALK_COMMANDLINE"/>
<preference name="xwalkMode" value="$XWALK_MODE" />
<preference name="xwalkMultipleApk" value="$XWALK_MULTIPLEAPK" />
<preference name="android-minSdkVersion" value="16" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</config-file>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkWebViewEngine.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkExposedJsApi.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaResourceClient.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaUiClient.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaView.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaCookieManager.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaClientCertRequest.java" target-dir="src/org/crosswalk/engine"/>
<source-file src="platforms/android/src/org/crosswalk/engine/XWalkCordovaHttpAuthHandler.java" target-dir="src/org/crosswalk/engine"/>
<framework src="platforms/android/xwalk.gradle" custom="true" type="gradleReference"/>
<hook type="after_plugin_install" src="hooks/after_plugin_install/000-shared_mode_special.js"/>
<hook type="before_plugin_uninstall" src="hooks/before_plugin_uninstall/000-shared_mode_special.js"/>
<hook type="after_build" src="hooks/after_build/000-build_64_bit.js"/>
<hook type="before_build" src="hooks/before_build/000-build_64_bit.js"/>
</platform>
<info>
After much discussion and analysis of the market, we have decided to discontinue support for Android 4.0 (ICS) in Crosswalk starting with version 20.
So the minSdkVersion of Cordova project is configured to 16 by default.
</info>
</plugin>
version: 2
aliases:
- &restore-cache
keys:
- dependency-cache-{{ checksum "package.json" }}-1
- &save-cache
key: dependency-cache-{{ checksum "package.json" }}-1
paths:
- node_modules
defaults: &defaults
docker:
- image: circleci/node:10
working_directory: /tmp/workspace
jobs:
build:
<<: *defaults
steps:
- checkout
- restore_cache: *restore-cache
- run: npm install
- save_cache: *save-cache
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
deploy:
<<: *defaults
environment:
GIT_AUTHOR_NAME: Ionitron
GIT_AUTHOR_EMAIL: hi@ionicframework.com
GIT_COMMITTER_NAME: Ionitron
GIT_COMMITTER_EMAIL: hi@ionicframework.com
steps:
- add_ssh_keys:
fingerprints:
- "ae:6d:3a:f1:cf:39:e1:94:6e:22:2a:9f:54:f9:b0:1b" # ionitron user key
- checkout
- attach_workspace:
at: /tmp/workspace
- run: npx semantic-release
workflows:
version: 2
build:
jobs:
- build
- deploy:
requires: [build]
filters:
branches:
only: stable
This diff is collapsed.
# Contributing
:mega: **Support/Questions?**: Please see our [Support Page](https://ionicframework.com/support) for general support questions. The issues on GitHub should be reserved for bug reports and feature requests.
### Bug Reports
Please create an issue describing the bug in detail.
### Feature Requests
Please create an issue!
## Developing
Please familiarize yourself with [Cordova plugin development](https://cordova.apache.org/docs/en/latest/guide/hybrid/plugins/).
You can use `cordova plugin add` with a local directory to copy and compile plugin changes into a test project.
### Workflow
This repo uses [semantic-release](https://github.com/semantic-release/semantic-release), so it's important to follow a strict workflow to ensure properly automated releases.
* Work off of `master` branch (create new branch or fork)
* Make changes
* Use `npm run cz` (or `git cz` if [commitizen](https://github.com/commitizen/cz-cli) is installed globally) to make commits
* Create a pull request
* Pull requests will be approved and squashed into the `master` branch
* Try to make pull requests with a single objective (don't have multiple features in one PR, don't mix fixes and features in one PR, etc.)
### Publishing
Releases are automated in CI using [semantic-release](https://github.com/semantic-release/semantic-release) when the `stable` branch is pushed to Github. Rebase `master` with `stable`. Commits in `master` should be appropriately formatted from the PR workflow (see [Workflow](#workflow)).
...@@ -200,36 +200,3 @@ ...@@ -200,36 +200,3 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
/************************************************/
This product bundles CordovaXWalkCoreExtensionBridge.java as well
as the XWalk.pak and the Crosswalk JSApi which is available under a
"3-clause BSD" license. For details, see below:
Copyright (c) 2013 Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!--
# license: 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.
-->
<!-- TODO: remove beta in README.md and CONTRIBUTING.md -->
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&identifier=104773211)](https://dependabot.com)
[![npm](https://img.shields.io/npm/v/cordova-plugin-ionic-webview.svg)](https://www.npmjs.com/package/cordova-plugin-ionic-webview)
# Ionic Web View for Cordova
A Web View plugin for Cordova, focused on providing the highest performance experience for Ionic apps (but can be used with any Cordova app).
This plugin uses WKWebView on iOS and the latest evergreen webview on Android. Additionally, this plugin makes it easy to use HTML5 style routing that web developers expect for building single-page apps.
Note: This repo and its documentation are for `cordova-plugin-ionic-webview` @ `4.x`, which uses the new features that may not work with all apps. See [Requirements](#plugin-requirements) and [Migrating to 4.x](#migrating-to-4x).
2.x documentation can be found [here](https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/2.x/README.md).
:book: **Documentation**: [https://beta.ionicframework.com/docs/building/webview][ionic-webview-docs]
:mega: **Support/Questions?** Please see our [Support Page][ionic-support] for general support questions. The issues on GitHub should be reserved for bug reports and feature requests.
:sparkling_heart: **Want to contribute?** Please see [CONTRIBUTING.md](https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/CONTRIBUTING.md).
## Configuration
This plugin has several configuration options that can be set in `config.xml`.
### Android and iOS Preferences
Preferences available for both iOS and Android
#### Hostname
`<preference name="Hostname" value="app" />`
Default value is `localhost`.
Example `ionic://app` on iOS, `http://app` on Android.
If you change it, you'll need to add a new `allow-navigation` entry in the `config.xml` for the configured url (i.e `<allow-navigation href="http://app/*"/>` if `Hostname` is set to `app`).
This is only needed for the Android url when using `http://`, `https://` or a custom scheme. All `ionic://` urls are whitelisted by the plugin.
### Android Preferences
Preferences only available Android platform
#### Scheme
```xml
<preference name="Scheme" value="https" />
```
Default value is `http`
Configures the Scheme the app uses to load the content.
#### MixedContentMode
```xml
<preference name="MixedContentMode" value="2" />
```
Configures the WebView's behavior when an origin attempts to load a resource from a different origin.
Default value is `0` (`MIXED_CONTENT_ALWAYS_ALLOW`), which allows loading resources from other origins.
Other possible values are `1` (`MIXED_CONTENT_NEVER_ALLOW`) and `2` (`MIXED_CONTENT_COMPATIBILITY_MODE`)
[Android documentation](https://developer.android.com/reference/android/webkit/WebSettings.html#setMixedContentMode(int))
### iOS Preferences
Preferences only available for iOS platform
#### iosScheme
```xml
<preference name="iosScheme" value="httpsionic" />
```
Default value is `ionic`
Configures the Scheme the app uses to load the content.
Values like `http`, `https` or `file` are not valid and will use default value instead.
If you change it, you'll need to add a new `allow-navigation` entry in the `config.xml` for the configured scheme (i.e `<allow-navigation href="httpsionic://*"/>` if `iosScheme` is set to `httpsionic`).
#### WKSuspendInBackground
```xml
<preference name="WKSuspendInBackground" value="false" />
```
Default value is `true` (suspend).
Set to false to stop WKWebView suspending in background too eagerly.
#### KeyboardAppearanceDark
```xml
<preference name="KeyboardAppearanceDark" value="false" />
```
Whether to use a dark styled keyboard on iOS
#### ScrollEnabled
```xml
<preference name="ScrollEnabled" value="true" />
```
Ionic apps work better if the WKWebView is not scrollable, so the scroll is disabled by default, but can be enabled with this preference. This only affects the main ScrollView of the WKWebView, so only affects the body, not other scrollable components.
## Plugin Requirements
* **Cordova CLI**: 7.1.0+
* **iOS**: iOS 11+ and `cordova-ios` 4+
* **Android**: Android 4.4+ and `cordova-android` 6.4+
## Migrating to 4.x
1. Remove and re-add the Web View plugin:
```
cordova plugin rm cordova-plugin-ionic-webview
cordova plugin add cordova-plugin-ionic-webview@latest
```
1. Apps are now served from HTTP on Android by default.
* The default origin for requests from the Android WebView is `http://localhost`. If `Hostname` and `Scheme` preferences are set, then origin will be `schemeValue://HostnameValue`.
1. Apps are now served from `ionic://` scheme on iOS by default.
* The default origin for requests from the iOS WebView is `ionic://localhost`. If `Hostname` and `iosScheme` preferences are set, then origin will be `iosSchemeValue://HostnameValue`.
1. The WebView is not able to display images, videos or other files from file or content protocols or if it doesn't have protocol at all. For those cases use `window.Ionic.WebView.convertFileSrc()` to get the proper url.
1. Replace any usages of `window.Ionic.normalizeURL()` with `window.Ionic.WebView.convertFileSrc()`.
* For Ionic Angular projects, there is an [Ionic Native wrapper](https://beta.ionicframework.com/docs/native/ionic-webview):
```
npm install @ionic-native/ionic-webview@beta
```
[ionic-homepage]: https://ionicframework.com
[ionic-docs]: https://ionicframework.com/docs
[ionic-webview-docs]: https://beta.ionicframework.com/docs/building/webview
[ionic-support]: https://ionicframework.com/support
{
"_from": "cordova-plugin-ionic-webview@latest",
"_id": "cordova-plugin-ionic-webview@4.1.3",
"_inBundle": false,
"_integrity": "sha1-fzljIIcIlR/t2XXAgIpdJzgoEqc=",
"_location": "/cordova-plugin-ionic-webview",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "cordova-plugin-ionic-webview@latest",
"name": "cordova-plugin-ionic-webview",
"escapedName": "cordova-plugin-ionic-webview",
"rawSpec": "latest",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npm.taobao.org/cordova-plugin-ionic-webview/download/cordova-plugin-ionic-webview-4.1.3.tgz",
"_shasum": "7f3963208708951fedd975c0808a5d27382812a7",
"_spec": "cordova-plugin-ionic-webview@latest",
"_where": "/Users/jeshi/Documents/徐工/hls-xcmg-vue-app",
"author": {
"name": "Ionic Team"
},
"bugs": {
"url": "https://github.com/ionic-team/cordova-plugin-ionic-webview/issues"
},
"bundleDependencies": false,
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"deprecated": false,
"description": "Ionic Web View Engine Plugin",
"devDependencies": {
"@semantic-release/changelog": "^3.0.0",
"@semantic-release/exec": "^3.3.0",
"@semantic-release/git": "^7.0.4",
"@semantic-release/github": "^5.0.6",
"@semantic-release/npm": "^5.0.4",
"commitizen": "^4.0.3",
"cz-conventional-changelog": "^3.0.2",
"semantic-release": "^15.9.17",
"sync-cordova-xml": "^0.4.0"
},
"engines": {
"cordovaDependencies": {
"2.0.0": {
"cordova-android": ">=6.4.0",
"cordova-ios": ">=4.0.0-dev"
},
"3.1.0": {
"cordova": ">=7.1.0",
"cordova-android": ">=6.4.0",
"cordova-ios": ">=4.0.0-dev"
}
}
},
"homepage": "https://github.com/ionic-team/cordova-plugin-ionic-webview#readme",
"keywords": [
"cordova",
"wkwebview"
],
"license": "Apache-2.0",
"name": "cordova-plugin-ionic-webview",
"release": {
"branch": "stable",
"verifyConditions": [
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git",
"@semantic-release/github"
],
"prepare": [
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/exec",
"@semantic-release/git"
],
"publish": [
"@semantic-release/github",
"@semantic-release/npm"
],
"success": [
"@semantic-release/github"
],
"failure": [
"@semantic-release/github"
],
"prepareCmd": "npm run version"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ionic-team/cordova-plugin-ionic-webview.git"
},
"scripts": {
"cz": "git-cz",
"sync_plugin_xml": "sync-cordova-xml package.json plugin.xml --output=plugin.xml",
"version": "npm run sync_plugin_xml && git add plugin.xml"
},
"version": "4.1.3"
}
<?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.
-->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:rim="http://www.blackberry.com/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-ionic-webview" version="4.1.3">
<name>cordova-plugin-ionic-webview</name>
<description>Ionic Web View Engine Plugin</description>
<license>Apache-2.0</license>
<keywords>cordova,wkwebview</keywords>
<repo>https://github.com/ionic-team/cordova-plugin-ionic-webview</repo>
<engines>
<engine name="cordova" version=">=7.1.0"/>
<engine name="cordova-ios" version=">=4.0.0-dev"/>
<engine name="apple-ios" version=">=11.0"/>
<engine name="cordova-android" version=">=6.4.0"/>
</engines>
<js-module src="src/www/util.js" name="IonicWebView">
<clobbers target="Ionic.WebView"/>
</js-module>
<platform name="android">
<config-file target="config.xml" parent="/*">
<allow-navigation href="http://localhost/*"/>
<allow-navigation href="https://localhost/*"/>
<allow-navigation href="ionic://*"/>
<preference name="webView" value="com.ionicframework.cordova.webview.IonicWebViewEngine"/>
<feature name="IonicWebView">
<param name="android-package" value="com.ionicframework.cordova.webview.IonicWebView"/>
</feature>
</config-file>
<source-file src="src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java" target-dir="src/com/ionicframework/cordova/webview"/>
<source-file src="src/android/com/ionicframework/cordova/webview/IonicWebView.java" target-dir="src/com/ionicframework/cordova/webview"/>
<source-file src="src/android/com/ionicframework/cordova/webview/AndroidProtocolHandler.java" target-dir="src/com/ionicframework/cordova/webview"/>
<source-file src="src/android/com/ionicframework/cordova/webview/UriMatcher.java" target-dir="src/com/ionicframework/cordova/webview"/>
<source-file src="src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java" target-dir="src/com/ionicframework/cordova/webview"/>
<preference name="ANDROID_SUPPORT_ANNOTATIONS_VERSION" default="27.+"/>
<framework src="com.android.support:support-annotations:$ANDROID_SUPPORT_ANNOTATIONS_VERSION"/>
</platform>
<!-- ios -->
<platform name="ios">
<js-module src="src/www/ios/ios-wkwebview-exec.js" name="ios-wkwebview-exec">
<clobbers target="cordova.exec"/>
</js-module>
<config-file target="config.xml" parent="/*">
<allow-navigation href="ionic://*"/>
<preference name="deployment-target" value="11.0"/>
<feature name="IonicWebView">
<param name="ios-package" value="CDVWKWebViewEngine"/>
</feature>
<preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine"/>
</config-file>
<framework src="WebKit.framework" weak="true"/>
<header-file src="src/ios/CDVWKWebViewEngine.h"/>
<source-file src="src/ios/CDVWKWebViewEngine.m"/>
<header-file src="src/ios/CDVWKWebViewUIDelegate.h"/>
<source-file src="src/ios/CDVWKWebViewUIDelegate.m"/>
<header-file src="src/ios/CDVWKProcessPoolFactory.h"/>
<source-file src="src/ios/CDVWKProcessPoolFactory.m"/>
<header-file src="src/ios/IONAssetHandler.h"/>
<source-file src="src/ios/IONAssetHandler.m"/>
<asset src="src/ios/wk-plugin.js" target="wk-plugin.js"/>
</platform>
<issue>https://github.com/ionic-team/cordova-plugin-ionic-webview/issues</issue>
<author>Ionic Team</author>
</plugin>
package com.ionicframework.cordova.webview;
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import android.content.Context;
import android.content.res.AssetManager;
import android.net.Uri;
import android.util.Log;
import android.util.TypedValue;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class AndroidProtocolHandler {
private static final String TAG = "AndroidProtocolHandler";
private Context context;
public AndroidProtocolHandler(Context context) {
this.context = context;
}
public InputStream openAsset(String path) throws IOException {
return context.getAssets().open(path, AssetManager.ACCESS_STREAMING);
}
public InputStream openResource(Uri uri) {
assert uri.getPath() != null;
// The path must be of the form ".../asset_type/asset_name.ext".
List<String> pathSegments = uri.getPathSegments();
String assetType = pathSegments.get(pathSegments.size() - 2);
String assetName = pathSegments.get(pathSegments.size() - 1);
// Drop the file extension.
assetName = assetName.split("\\.")[0];
try {
// Use the application context for resolving the resource package name so that we do
// not use the browser's own resources. Note that if 'context' here belongs to the
// test suite, it does not have a separate application context. In that case we use
// the original context object directly.
if (context.getApplicationContext() != null) {
context = context.getApplicationContext();
}
int fieldId = getFieldId(context, assetType, assetName);
int valueType = getValueType(context, fieldId);
if (valueType == TypedValue.TYPE_STRING) {
return context.getResources().openRawResource(fieldId);
} else {
Log.e(TAG, "Asset not of type string: " + uri);
return null;
}
} catch (ClassNotFoundException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
} catch (NoSuchFieldException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
} catch (IllegalAccessException e) {
Log.e(TAG, "Unable to open resource URL: " + uri, e);
return null;
}
}
public InputStream openFile(String filePath) throws IOException {
String realPath = filePath.replace(WebViewLocalServer.fileStart, "");
File localFile = new File(realPath);
return new FileInputStream(localFile);
}
public InputStream openContentUrl(Uri uri) throws IOException {
Integer port = uri.getPort();
String realPath;
if (port == -1) {
realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + WebViewLocalServer.contentStart, "content:/");
} else {
realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + ":" + port + WebViewLocalServer.contentStart, "content:/");
}
InputStream stream = null;
try {
stream = context.getContentResolver().openInputStream(Uri.parse(realPath));
} catch (SecurityException e) {
Log.e(TAG, "Unable to open content URL: " + uri, e);
}
return stream;
}
private static int getFieldId(Context context, String assetType, String assetName)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class<?> d = context.getClassLoader()
.loadClass(context.getPackageName() + ".R$" + assetType);
java.lang.reflect.Field field = d.getField(assetName);
int id = field.getInt(null);
return id;
}
private static int getValueType(Context context, int fieldId) {
TypedValue value = new TypedValue();
context.getResources().getValue(fieldId, value, true);
return value.type;
}
}
package com.ionicframework.cordova.webview;
import android.app.Activity;
import android.content.SharedPreferences;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
public class IonicWebView extends CordovaPlugin {
public static final String WEBVIEW_PREFS_NAME = "WebViewSettings";
public static final String CDV_SERVER_PATH = "serverBasePath";
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("setServerBasePath")) {
final String path = args.getString(0);
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
((IonicWebViewEngine)webView.getEngine()).setServerBasePath(path);
}
});
return true;
} else if (action.equals("getServerBasePath")) {
callbackContext.success(((IonicWebViewEngine)webView.getEngine()).getServerBasePath());
return true;
} else if (action.equals("persistServerBasePath")) {
String path = ((IonicWebViewEngine)webView.getEngine()).getServerBasePath();
SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(CDV_SERVER_PATH, path);
editor.apply();
return true;
}
return false;
}
}
package com.ionicframework.cordova.webview;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.NativeToJsMessageQueue;
import org.apache.cordova.PluginManager;
import org.apache.cordova.engine.SystemWebViewClient;
import org.apache.cordova.engine.SystemWebViewEngine;
import org.apache.cordova.engine.SystemWebView;
public class IonicWebViewEngine extends SystemWebViewEngine {
public static final String TAG = "IonicWebViewEngine";
private WebViewLocalServer localServer;
private String CDV_LOCAL_SERVER;
private String scheme;
private static final String LAST_BINARY_VERSION_CODE = "lastBinaryVersionCode";
private static final String LAST_BINARY_VERSION_NAME = "lastBinaryVersionName";
/**
* Used when created via reflection.
*/
public IonicWebViewEngine(Context context, CordovaPreferences preferences) {
super(new SystemWebView(context), preferences);
Log.d(TAG, "Ionic Web View Engine Starting Right Up 1...");
}
public IonicWebViewEngine(SystemWebView webView) {
super(webView, null);
Log.d(TAG, "Ionic Web View Engine Starting Right Up 2...");
}
public IonicWebViewEngine(SystemWebView webView, CordovaPreferences preferences) {
super(webView, preferences);
Log.d(TAG, "Ionic Web View Engine Starting Right Up 3...");
}
@Override
public void init(CordovaWebView parentWebView, CordovaInterface cordova, final CordovaWebViewEngine.Client client,
CordovaResourceApi resourceApi, PluginManager pluginManager,
NativeToJsMessageQueue nativeToJsMessageQueue) {
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(cordova.getActivity());
String hostname = preferences.getString("Hostname", "localhost");
scheme = preferences.getString("Scheme", "http");
CDV_LOCAL_SERVER = scheme + "://" + hostname;
localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme);
localServer.hostAssets("www");
webView.setWebViewClient(new ServerClient(this, parser));
super.init(parentWebView, cordova, client, resourceApi, pluginManager, nativeToJsMessageQueue);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final WebSettings settings = webView.getSettings();
int mode = preferences.getInteger("MixedContentMode", 0);
settings.setMixedContentMode(mode);
}
SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
String path = prefs.getString(IonicWebView.CDV_SERVER_PATH, null);
if (!isDeployDisabled() && !isNewBinary() && path != null && !path.isEmpty()) {
setServerBasePath(path);
}
}
private boolean isNewBinary() {
String versionCode = "";
String versionName = "";
SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
String lastVersionCode = prefs.getString(LAST_BINARY_VERSION_CODE, null);
String lastVersionName = prefs.getString(LAST_BINARY_VERSION_NAME, null);
try {
PackageInfo pInfo = this.cordova.getActivity().getPackageManager().getPackageInfo(this.cordova.getActivity().getPackageName(), 0);
versionCode = Integer.toString(pInfo.versionCode);
versionName = pInfo.versionName;
} catch(Exception ex) {
Log.e(TAG, "Unable to get package info", ex);
}
if (!versionCode.equals(lastVersionCode) || !versionName.equals(lastVersionName)) {
SharedPreferences.Editor editor = prefs.edit();
editor.putString(LAST_BINARY_VERSION_CODE, versionCode);
editor.putString(LAST_BINARY_VERSION_NAME, versionName);
editor.putString(IonicWebView.CDV_SERVER_PATH, "");
editor.apply();
return true;
}
return false;
}
private boolean isDeployDisabled() {
return preferences.getBoolean("DisableDeploy", false);
}
private class ServerClient extends SystemWebViewClient {
private ConfigXmlParser parser;
public ServerClient(SystemWebViewEngine parentEngine, ConfigXmlParser parser) {
super(parentEngine);
this.parser = parser;
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return localServer.shouldInterceptRequest(request.getUrl(), request);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return localServer.shouldInterceptRequest(Uri.parse(url), null);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
String launchUrl = parser.getLaunchUrl();
if (!launchUrl.contains(WebViewLocalServer.httpsScheme) && !launchUrl.contains(WebViewLocalServer.httpScheme) && url.equals(launchUrl)) {
view.stopLoading();
// When using a custom scheme the app won't load if server start url doesn't end in /
String startUrl = CDV_LOCAL_SERVER;
if (!scheme.equalsIgnoreCase(WebViewLocalServer.httpsScheme) && !scheme.equalsIgnoreCase(WebViewLocalServer.httpScheme)) {
startUrl += "/";
}
view.loadUrl(startUrl);
}
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() { " +
"window.WEBVIEW_SERVER_URL = '" + CDV_LOCAL_SERVER + "';" +
"})()");
}
}
public void setServerBasePath(String path) {
localServer.hostFiles(path);
webView.loadUrl(CDV_LOCAL_SERVER);
}
public String getServerBasePath() {
return this.localServer.getBasePath();
}
}
package com.ionicframework.cordova.webview;
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed 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 com.google.webviewlocalserver.third_party.android;
import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public class UriMatcher {
/**
* Creates the root node of the URI tree.
*
* @param code the code to match for the root URI
*/
public UriMatcher(Object code) {
mCode = code;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
private UriMatcher() {
mCode = null;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
/**
* Add a URI to match, and the code to return when this URI is
* matched. URI nodes may be exact match string, the token "*"
* that matches any text, or the token "#" that matches only
* numbers.
* <p>
* Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
* this method will accept a leading slash in the path.
*
* @param authority the authority to match
* @param path the path to match. * may be used as a wild card for
* any text, and # may be used as a wild card for numbers.
* @param code the code that is returned when a URI is matched
* against the given components. Must be positive.
*/
public void addURI(String scheme, String authority, String path, Object code) {
if (code == null) {
throw new IllegalArgumentException("Code can't be null");
}
String[] tokens = null;
if (path != null) {
String newPath = path;
// Strip leading slash if present.
if (path.length() > 0 && path.charAt(0) == '/') {
newPath = path.substring(1);
}
tokens = PATH_SPLIT_PATTERN.split(newPath);
}
int numTokens = tokens != null ? tokens.length : 0;
UriMatcher node = this;
for (int i = -2; i < numTokens; i++) {
String token;
if (i == -2)
token = scheme;
else if (i == -1)
token = authority;
else
token = tokens[i];
ArrayList<UriMatcher> children = node.mChildren;
int numChildren = children.size();
UriMatcher child;
int j;
for (j = 0; j < numChildren; j++) {
child = children.get(j);
if (token.equals(child.mText)) {
node = child;
break;
}
}
if (j == numChildren) {
// Child not found, create it
child = new UriMatcher();
if (token.equals("**")) {
child.mWhich = REST;
} else if (token.equals("*")) {
child.mWhich = TEXT;
} else {
child.mWhich = EXACT;
}
child.mText = token;
node.mChildren.add(child);
node = child;
}
}
node.mCode = code;
}
static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/");
/**
* Try to match against the path in a url.
*
* @param uri The url whose path we will match against.
* @return The code for the matched node (added using addURI),
* or null if there is no matched node.
*/
public Object match(Uri uri) {
final List<String> pathSegments = uri.getPathSegments();
final int li = pathSegments.size();
UriMatcher node = this;
if (li == 0 && uri.getAuthority() == null) {
return this.mCode;
}
for (int i = -2; i < li; i++) {
String u;
if (i == -2)
u = uri.getScheme();
else if (i == -1)
u = uri.getAuthority();
else
u = pathSegments.get(i);
ArrayList<UriMatcher> list = node.mChildren;
if (list == null) {
break;
}
node = null;
int lj = list.size();
for (int j = 0; j < lj; j++) {
UriMatcher n = list.get(j);
which_switch:
switch (n.mWhich) {
case EXACT:
if (n.mText.equals(u)) {
node = n;
}
break;
case TEXT:
node = n;
break;
case REST:
return n.mCode;
}
if (node != null) {
break;
}
}
if (node == null) {
return null;
}
}
return node.mCode;
}
private static final int EXACT = 0;
private static final int TEXT = 1;
private static final int REST = 2;
private Object mCode;
private int mWhich;
private String mText;
private ArrayList<UriMatcher> mChildren;
}
/*
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.
*/
#import <WebKit/WebKit.h>
@interface CDVWKProcessPoolFactory : NSObject
@property (nonatomic, retain) WKProcessPool* sharedPool;
+(instancetype) sharedFactory;
-(WKProcessPool*) sharedProcessPool;
@end
/*
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.
*/
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#import "CDVWKProcessPoolFactory.h"
static CDVWKProcessPoolFactory *factory = nil;
@implementation CDVWKProcessPoolFactory
+ (instancetype)sharedFactory
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
factory = [[CDVWKProcessPoolFactory alloc] init];
});
return factory;
}
- (instancetype)init
{
if (self = [super init]) {
_sharedPool = [[WKProcessPool alloc] init];
}
return self;
}
- (WKProcessPool*) sharedProcessPool {
return _sharedPool;
}
@end
/*
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.
*/
#import <WebKit/WebKit.h>
#import <Cordova/CDV.h>
@interface CDVWKWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol, WKScriptMessageHandler, WKNavigationDelegate>
@property (nonatomic, strong, readonly) id <WKUIDelegate> uiDelegate;
@property (nonatomic, strong) NSString * basePath;
-(void)setServerBasePath:(CDVInvokedUrlCommand*)command;
-(void)getServerBasePath:(CDVInvokedUrlCommand*)command;
@end
/*
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.
*/
#import <WebKit/WebKit.h>
@interface CDVWKWebViewUIDelegate : NSObject <WKUIDelegate>
@property (nonatomic, copy) NSString* title;
- (instancetype)initWithTitle:(NSString*)title;
@end
/*
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.
*/
#import "CDVWKWebViewUIDelegate.h"
@implementation CDVWKWebViewUIDelegate
- (instancetype)initWithTitle:(NSString*)title
{
self = [super init];
if (self) {
self.title = title;
}
return self;
}
- (void) webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message
initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action)
{
completionHandler();
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
[rootController presentViewController:alert animated:YES completion:nil];
}
- (void) webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message
initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler
{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action)
{
completionHandler(YES);
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action)
{
completionHandler(NO);
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
[rootController presentViewController:alert animated:YES completion:nil];
}
- (void) webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame
completionHandler:(void (^)(NSString* result))completionHandler
{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
message:prompt
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action)
{
completionHandler(((UITextField*)alert.textFields[0]).text);
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action)
{
completionHandler(nil);
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
[alert addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.text = defaultText;
}];
UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
[rootController presentViewController:alert animated:YES completion:nil];
}
@end
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface IONAssetHandler : NSObject <WKURLSchemeHandler>
@property (nonatomic, strong) NSString * basePath;
@property (nonatomic, strong) NSString * scheme;
-(void)setAssetPath:(NSString *)assetPath;
- (instancetype)initWithBasePath:(NSString *)basePath andScheme:(NSString *)scheme;
@end
#import "IONAssetHandler.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "CDVWKWebViewEngine.h"
@implementation IONAssetHandler
-(void)setAssetPath:(NSString *)assetPath {
self.basePath = assetPath;
}
- (instancetype)initWithBasePath:(NSString *)basePath andScheme:(NSString *)scheme {
self = [super init];
if (self) {
_basePath = basePath;
_scheme = scheme;
}
return self;
}
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
{
NSString * startPath = @"";
NSURL * url = urlSchemeTask.request.URL;
NSString * stringToLoad = url.path;
NSString * scheme = url.scheme;
if ([scheme isEqualToString:self.scheme]) {
if ([stringToLoad hasPrefix:@"/_app_file_"]) {
startPath = [stringToLoad stringByReplacingOccurrencesOfString:@"/_app_file_" withString:@""];
} else {
startPath = self.basePath;
if ([stringToLoad isEqualToString:@""] || [url.pathExtension isEqualToString:@""]) {
startPath = [startPath stringByAppendingString:@"/index.html"];
} else {
startPath = [startPath stringByAppendingString:stringToLoad];
}
}
}
NSError * fileError = nil;
NSData * data = nil;
if ([self isMediaExtension:url.pathExtension]) {
data = [NSData dataWithContentsOfFile:startPath options:NSDataReadingMappedIfSafe error:&fileError];
}
if (!data || fileError) {
data = [[NSData alloc] initWithContentsOfFile:startPath];
}
NSInteger statusCode = 200;
if (!data) {
statusCode = 404;
}
NSURL * localUrl = [NSURL URLWithString:url.absoluteString];
NSString * mimeType = [self getMimeType:url.pathExtension];
id response = nil;
if (data && [self isMediaExtension:url.pathExtension]) {
response = [[NSURLResponse alloc] initWithURL:localUrl MIMEType:mimeType expectedContentLength:data.length textEncodingName:nil];
} else {
NSDictionary * headers = @{ @"Content-Type" : mimeType, @"Cache-Control": @"no-cache"};
response = [[NSHTTPURLResponse alloc] initWithURL:localUrl statusCode:statusCode HTTPVersion:nil headerFields:headers];
}
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
}
- (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask
{
NSLog(@"stop");
}
-(NSString *) getMimeType:(NSString *)fileExtension {
if (fileExtension && ![fileExtension isEqualToString:@""]) {
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL);
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
return contentType ? contentType : @"application/octet-stream";
} else {
return @"text/html";
}
}
-(BOOL) isMediaExtension:(NSString *) pathExtension {
NSArray * mediaExtensions = @[@"m4v", @"mov", @"mp4",
@"aac", @"ac3", @"aiff", @"au", @"flac", @"m4a", @"mp3", @"wav"];
if ([mediaExtensions containsObject:pathExtension.lowercaseString]) {
return YES;
}
return NO;
}
@end
Copyright (c) 2012 Niklas von Hertzen
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
(function _wk_plugin() {
// Check if we are running in WKWebView
if (!window.webkit || !window.webkit.messageHandlers) {
return;
}
// Initialize Ionic
window.Ionic = window.Ionic || {};
function normalizeURL(url) {
console.warn('normalizeURL is deprecated, use window.Ionic.WebView.convertFileSrc');
return window.Ionic.WebView.convertFileSrc(url);
}
if (typeof window.wkRewriteURL === 'undefined') {
window.wkRewriteURL = function (url) {
console.warn('wkRewriteURL is deprecated, use window.Ionic.WebView.convertFileSrc instead');
return window.Ionic.WebView.convertFileSrc(url);
}
}
window.Ionic.normalizeURL = normalizeURL;
var stopScrollHandler = window.webkit.messageHandlers.stopScroll;
if (!stopScrollHandler) {
console.error('Can not find stopScroll handler');
return;
}
var stopScrollFunc = null;
var stopScroll = {
stop: function stop(callback) {
if (!stopScrollFunc) {
stopScrollFunc = callback;
stopScrollHandler.postMessage('');
}
},
fire: function fire() {
stopScrollFunc && stopScrollFunc();
stopScrollFunc = null;
},
cancel: function cancel() {
stopScrollFunc = null;
}
};
window.Ionic.StopScroll = stopScroll;
// deprecated
window.IonicStopScroll = stopScroll;
console.debug("Ionic Stop Scroll injected!");
})();
/*
*
* 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.
*
*/
/**
* Creates the exec bridge used to notify the native code of
* commands.
*/
var cordova = require('cordova');
var utils = require('cordova/utils');
var base64 = require('cordova/base64');
function massageArgsJsToNative (args) {
if (!args || utils.typeName(args) !== 'Array') {
return args;
}
var ret = [];
args.forEach(function (arg, i) {
if (utils.typeName(arg) === 'ArrayBuffer') {
ret.push({
'CDVType': 'ArrayBuffer',
'data': base64.fromArrayBuffer(arg)
});
} else {
ret.push(arg);
}
});
return ret;
}
function massageMessageNativeToJs (message) {
if (message.CDVType === 'ArrayBuffer') {
var stringToArrayBuffer = function (str) {
var ret = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
ret[i] = str.charCodeAt(i);
}
return ret.buffer;
};
var base64ToArrayBuffer = function (b64) {
return stringToArrayBuffer(atob(b64)); // eslint-disable-line no-undef
};
message = base64ToArrayBuffer(message.data);
}
return message;
}
function convertMessageToArgsNativeToJs (message) {
var args = [];
if (!message || !message.hasOwnProperty('CDVType')) {
args.push(message);
} else if (message.CDVType === 'MultiPart') {
message.messages.forEach(function (e) {
args.push(massageMessageNativeToJs(e));
});
} else {
args.push(massageMessageNativeToJs(message));
}
return args;
}
var iOSExec = function () {
// detect change in bridge, if there is a change, we forward to new bridge
// if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
// bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
// }
var successCallback, failCallback, service, action, actionArgs;
var callbackId = null;
if (typeof arguments[0] !== 'string') {
// FORMAT ONE
successCallback = arguments[0];
failCallback = arguments[1];
service = arguments[2];
action = arguments[3];
actionArgs = arguments[4];
// Since we need to maintain backwards compatibility, we have to pass
// an invalid callbackId even if no callback was provided since plugins
// will be expecting it. The Cordova.exec() implementation allocates
// an invalid callbackId and passes it even if no callbacks were given.
callbackId = 'INVALID';
} else {
throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' + // eslint-disable-line
'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);');
}
// If actionArgs is not provided, default to an empty array
actionArgs = actionArgs || [];
// Register the callbacks and add the callbackId to the positional
// arguments if given.
if (successCallback || failCallback) {
callbackId = service + cordova.callbackId++;
cordova.callbacks[callbackId] =
{success: successCallback, fail: failCallback};
}
actionArgs = massageArgsJsToNative(actionArgs);
// CB-10133 DataClone DOM Exception 25 guard (fast function remover)
var command = [callbackId, service, action, JSON.parse(JSON.stringify(actionArgs))];
window.webkit.messageHandlers.cordova.postMessage(command);
};
iOSExec.nativeCallback = function (callbackId, status, message, keepCallback, debug) {
var success = status === 0 || status === 1;
var args = convertMessageToArgsNativeToJs(message);
Promise.resolve().then(function () {
cordova.callbackFromNative(callbackId, success, status, args, keepCallback); // eslint-disable-line
});
};
// for backwards compatibility
iOSExec.nativeEvalAndFetch = function (func) {
try {
func();
} catch (e) {
console.log(e);
}
};
// Proxy the exec for bridge changes. See CB-10106
function cordovaExec () {
var cexec = require('cordova/exec');
var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
return (cexec_valid && execProxy !== cexec) ? cexec : iOSExec;
}
function execProxy () {
cordovaExec().apply(null, arguments);
}
execProxy.nativeFetchMessages = function () {
return cordovaExec().nativeFetchMessages.apply(null, arguments);
};
execProxy.nativeEvalAndFetch = function () {
return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
};
execProxy.nativeCallback = function () {
return cordovaExec().nativeCallback.apply(null, arguments);
};
module.exports = execProxy;
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
// unregister the old bridge
cordova.define.remove('cordova/exec');
// redefine bridge to our new bridge
cordova.define('cordova/exec', function (require, exports, module) {
module.exports = execProxy;
});
}
var exec = require('cordova/exec');
var WebView = {
convertFileSrc: function(url) {
if (!url) {
return url;
}
if (url.startsWith('/')) {
return window.WEBVIEW_SERVER_URL + '/_app_file_' + url;
}
if (url.startsWith('file://')) {
return window.WEBVIEW_SERVER_URL + url.replace('file://', '/_app_file_');
}
if (url.startsWith('content://')) {
return window.WEBVIEW_SERVER_URL + url.replace('content:/', '/_app_content_');
}
return url;
},
setServerBasePath: function(path) {
exec(null, null, 'IonicWebView', 'setServerBasePath', [path]);
},
getServerBasePath: function(callback) {
exec(callback, null, 'IonicWebView', 'getServerBasePath', []);
},
persistServerBasePath: function() {
exec(null, null, 'IonicWebView', 'persistServerBasePath', []);
}
}
module.exports = WebView;
\ No newline at end of file
...@@ -209,5 +209,13 @@ ...@@ -209,5 +209,13 @@
}, },
"is_top_level": true, "is_top_level": true,
"variables": {} "variables": {}
},
"cordova-plugin-ionic-webview": {
"source": {
"type": "registry",
"id": "cordova-plugin-ionic-webview@latest"
},
"is_top_level": true,
"variables": {}
} }
} }
\ No newline at end of file
...@@ -766,7 +766,8 @@ export default { ...@@ -766,7 +766,8 @@ export default {
let error = function () { let error = function () {
hlsPopup.showLongCenter('请选择图片') hlsPopup.showLongCenter('请选择图片')
} }
vm.hlsUtil.takePicture(cameraoptions, success, error) // vm.hlsUtil.takePicture(cameraoptions, success, error)
vm.hlsUtil.takePictureIonic('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581679239261&di=8712258044d24c94e1a86a17dfcda44f&imgtype=jpg&src=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D3573372459%2C4199107735%26fm%3D214%26gp%3D0.jpg')
}, },
openCamera (ocrType, type) { openCamera (ocrType, type) {
let vm = this let vm = this
......
...@@ -308,6 +308,11 @@ export default { ...@@ -308,6 +308,11 @@ export default {
} }
}, },
takePictureIonic: function (url) {
window.Ionic.normalizeURL(url)
debugger
},
/** /**
* 录制视频 * 录制视频
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment