Compare commits

..

1 Commits

Author SHA1 Message Date
sgrebnov 79e35d9790 CB-10441 Add auto tests for InAppBrowser plugin 2016-01-27 13:00:28 +03:00
11 changed files with 227 additions and 406 deletions
-27
View File
@@ -35,30 +35,3 @@ The details are explained there, but the important items are:
- Run the tests so your patch doesn't break existing functionality. - Run the tests so your patch doesn't break existing functionality.
We look forward to your contributions! We look forward to your contributions!
The notes on [Commit Workflow](https://github.com/apache/cordova-coho/blob/master/docs/committer-workflow.md#commit-workflow) can be helpful even if you are not a committer.
## Running plugin tests
* clone and install [cordova-plugin-test-framework](https://github.com/apache/cordova-plugin-test-framework)
```
git clone git@github.com:apache/cordova-plugin-test-framework.git
```
* edit ```cordova-plugin-test-framework/www/assets/index.html``` and add the following line
```
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com http://cordova.apache.org http://google.co.uk https://google.co.uk 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
```
* create test project
```
cordova create plugintest
cd plugintest
cordova platform add android
cordova plugin add ../cordova-plugin-inappbrowser
cordova plugin add ../cordova-plugin-inappbrowser/tests
cordova plugin add ../cordova-plugin-test-framework
```
* edit ```config.xml``` and replace ```<content src="index.html" />``` with ```<content src="cdvtests/index.html" />```
* run application
```
cordova run
```
+1 -2
View File
@@ -100,7 +100,6 @@ instance, or the system browser.
- __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened
- __zoom__: set to `yes` to show Android browser's zoom controls, set to `no` to hide them. Default value is `yes`. - __zoom__: set to `yes` to show Android browser's zoom controls, set to `no` to hide them. Default value is `yes`.
- __hardwareback__: set to `yes` to use the hardware back button to navigate backwards through the `InAppBrowser`'s history. If there is no previous page, the `InAppBrowser` will close. The default value is `yes`, so you must set it to `no` if you want the back button to simply close the InAppBrowser. - __hardwareback__: set to `yes` to use the hardware back button to navigate backwards through the `InAppBrowser`'s history. If there is no previous page, the `InAppBrowser` will close. The default value is `yes`, so you must set it to `no` if you want the back button to simply close the InAppBrowser.
- __mediaPlaybackRequiresUserAction__: Set to `yes` to prevent HTML5 audio or video from autoplaying (defaults to `no`).
iOS only: iOS only:
@@ -111,7 +110,7 @@ instance, or the system browser.
- __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened
- __toolbar__: set to `yes` or `no` to turn the toolbar on or off for the InAppBrowser (defaults to `yes`) - __toolbar__: set to `yes` or `no` to turn the toolbar on or off for the InAppBrowser (defaults to `yes`)
- __enableViewportScale__: Set to `yes` or `no` to prevent viewport scaling through a meta tag (defaults to `no`). - __enableViewportScale__: Set to `yes` or `no` to prevent viewport scaling through a meta tag (defaults to `no`).
- __mediaPlaybackRequiresUserAction__: Set to `yes` to prevent HTML5 audio or video from autoplaying (defaults to `no`). - __mediaPlaybackRequiresUserAction__: Set to `yes` or `no` to prevent HTML5 audio or video from autoplaying (defaults to `no`).
- __allowInlineMediaPlayback__: Set to `yes` or `no` to allow in-line HTML5 media playback, displaying within the browser window rather than a device-specific playback interface. The HTML's `video` element must also include the `webkit-playsinline` attribute (defaults to `no`) - __allowInlineMediaPlayback__: Set to `yes` or `no` to allow in-line HTML5 media playback, displaying within the browser window rather than a device-specific playback interface. The HTML's `video` element must also include the `webkit-playsinline` attribute (defaults to `no`)
- __keyboardDisplayRequiresUserAction__: Set to `yes` or `no` to open the keyboard when form elements receive focus via JavaScript's `focus()` call (defaults to `yes`). - __keyboardDisplayRequiresUserAction__: Set to `yes` or `no` to open the keyboard when form elements receive focus via JavaScript's `focus()` call (defaults to `yes`).
- __suppressesIncrementalRendering__: Set to `yes` or `no` to wait until all new view content is received before being rendered (defaults to `no`). - __suppressesIncrementalRendering__: Set to `yes` or `no` to wait until all new view content is received before being rendered (defaults to `no`).
-21
View File
@@ -20,27 +20,6 @@
--> -->
# Release Notes # Release Notes
### 1.3.0 (Feb 09, 2016)
* [CB-3360](https://issues.apache.org/jira/browse/CB-3360) Set custom inappbrowser user agent for android
* [CB-10538](https://issues.apache.org/jira/browse/CB-10538) cordova-plugin-inappbrowser timeout issue
* [CB-10395](https://issues.apache.org/jira/browse/CB-10395) InAppBrowser's WebView not storing cookies reliable on Android
* Edit package.json license to match SPDX id
* [CB-10305](https://issues.apache.org/jira/browse/CB-10305) Gray bar appears in the wrong place on iOS
* [CB-7786](https://issues.apache.org/jira/browse/CB-7786) Support mediaPlaybackRequiresUserAction on Android
* [CB-7500](https://issues.apache.org/jira/browse/CB-7500) executeScript with callback kills/blurs inAppBrowser window on Android
### 1.2.1 (Feb 02, 2016)
* [CB-10407](https://issues.apache.org/jira/browse/CB-10407) InAppBrowser not firing loadstart event on android
* [CB-10428](https://issues.apache.org/jira/browse/CB-10428) Fix syntax error when browserifying inAppBrowser plugin
* handle app store urls in system browser
* [CB-6702](https://issues.apache.org/jira/browse/CB-6702) InAppBrowser hangs when opening more than one instance
* [CB-10456](https://issues.apache.org/jira/browse/CB-10456) InAppBrowser is not closed if I close it programmatically on Android
* [CB-10451](https://issues.apache.org/jira/browse/CB-10451) InAppBrowser: loadstart event is not triggered on Windows
* [CB-10452](https://issues.apache.org/jira/browse/CB-10452) InAppBrowser: 'exit' event is not triggered on Windows
* [CB-10454](https://issues.apache.org/jira/browse/CB-10454) InAppBrowser: 'loaderror' event does not have code and message on Windows
* [CB-10450](https://issues.apache.org/jira/browse/CB-10450) InAppBrowser: Unable to get property 'canGoBack' of undefined on Windows
* [CB-10441](https://issues.apache.org/jira/browse/CB-10441) Add auto tests for InAppBrowser plugin
### 1.2.0 (Jan 15, 2016) ### 1.2.0 (Jan 15, 2016)
* CB-8180: Changing methods of interception in `WebViewClient` class * CB-8180: Changing methods of interception in `WebViewClient` class
* CB-10009 Improve `InAppBrowser` toolbar look and feel on **Windows** * CB-10009 Improve `InAppBrowser` toolbar look and feel on **Windows**
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "cordova-plugin-inappbrowser", "name": "cordova-plugin-inappbrowser",
"version": "1.3.0", "version": "1.2.1-dev",
"description": "Cordova InAppBrowser Plugin", "description": "Cordova InAppBrowser Plugin",
"cordova": { "cordova": {
"id": "cordova-plugin-inappbrowser", "id": "cordova-plugin-inappbrowser",
@@ -44,5 +44,5 @@
} }
], ],
"author": "Apache Software Foundation", "author": "Apache Software Foundation",
"license": "Apache-2.0" "license": "Apache 2.0"
} }
+1 -1
View File
@@ -20,7 +20,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-inappbrowser" id="cordova-plugin-inappbrowser"
version="1.3.0"> version="1.2.1-dev">
<name>InAppBrowser</name> <name>InAppBrowser</name>
<description>Cordova InAppBrowser Plugin</description> <description>Cordova InAppBrowser Plugin</description>
+16 -53
View File
@@ -41,7 +41,6 @@ import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
@@ -86,7 +85,6 @@ public class InAppBrowser extends CordovaPlugin {
private static final String CLEAR_ALL_CACHE = "clearcache"; private static final String CLEAR_ALL_CACHE = "clearcache";
private static final String CLEAR_SESSION_CACHE = "clearsessioncache"; private static final String CLEAR_SESSION_CACHE = "clearsessioncache";
private static final String HARDWARE_BACK_BUTTON = "hardwareback"; private static final String HARDWARE_BACK_BUTTON = "hardwareback";
private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction";
private InAppBrowserDialog dialog; private InAppBrowserDialog dialog;
private WebView inAppWebView; private WebView inAppWebView;
@@ -98,7 +96,6 @@ public class InAppBrowser extends CordovaPlugin {
private boolean clearAllCache = false; private boolean clearAllCache = false;
private boolean clearSessionCache = false; private boolean clearSessionCache = false;
private boolean hadwareBackButton = true; private boolean hadwareBackButton = true;
private boolean mediaPlaybackRequiresUserGesture = false;
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
@@ -203,7 +200,7 @@ public class InAppBrowser extends CordovaPlugin {
else if (action.equals("injectScriptCode")) { else if (action.equals("injectScriptCode")) {
String jsWrapper = null; String jsWrapper = null;
if (args.getBoolean(1)) { if (args.getBoolean(1)) {
jsWrapper = String.format("(function(){prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')})()", callbackContext.getCallbackId()); jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId());
} }
injectDeferredObject(args.getString(0), jsWrapper); injectDeferredObject(args.getString(0), jsWrapper);
} }
@@ -365,22 +362,20 @@ public class InAppBrowser extends CordovaPlugin {
* Closes the dialog * Closes the dialog
*/ */
public void closeDialog() { public void closeDialog() {
final WebView childView = this.inAppWebView;
// The JS protects against multiple calls, so this should happen only when
// closeDialog() is called by other native code.
if (childView == null) {
return;
}
this.cordova.getActivity().runOnUiThread(new Runnable() { this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
final WebView childView = inAppWebView;
// The JS protects against multiple calls, so this should happen only when
// closeDialog() is called by other native code.
if (childView == null) {
return;
}
childView.setWebViewClient(new WebViewClient() { childView.setWebViewClient(new WebViewClient() {
// NB: wait for about:blank before dismissing // NB: wait for about:blank before dismissing
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
if (dialog != null) { if (dialog != null) {
dialog.dismiss(); dialog.dismiss();
dialog = null;
} }
} }
}); });
@@ -388,16 +383,16 @@ public class InAppBrowser extends CordovaPlugin {
// other than your app's UI thread, it can cause unexpected results." // other than your app's UI thread, it can cause unexpected results."
// http://developer.android.com/guide/webapps/migrating.html#Threads // http://developer.android.com/guide/webapps/migrating.html#Threads
childView.loadUrl("about:blank"); childView.loadUrl("about:blank");
try {
JSONObject obj = new JSONObject();
obj.put("type", EXIT_EVENT);
sendUpdate(obj, false);
} catch (JSONException ex) {
Log.d(LOG_TAG, "Should never happen");
}
} }
}); });
try {
JSONObject obj = new JSONObject();
obj.put("type", EXIT_EVENT);
sendUpdate(obj, false);
} catch (JSONException ex) {
Log.d(LOG_TAG, "Should never happen");
}
} }
/** /**
@@ -476,8 +471,6 @@ public class InAppBrowser extends CordovaPlugin {
showLocationBar = true; showLocationBar = true;
showZoomControls = true; showZoomControls = true;
openWindowHidden = false; openWindowHidden = false;
mediaPlaybackRequiresUserGesture = false;
if (features != null) { if (features != null) {
Boolean show = features.get(LOCATION); Boolean show = features.get(LOCATION);
if (show != null) { if (show != null) {
@@ -495,10 +488,6 @@ public class InAppBrowser extends CordovaPlugin {
if (hardwareBack != null) { if (hardwareBack != null) {
hadwareBackButton = hardwareBack.booleanValue(); hadwareBackButton = hardwareBack.booleanValue();
} }
Boolean mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION);
if (mediaPlayback != null) {
mediaPlaybackRequiresUserGesture = mediaPlayback.booleanValue();
}
Boolean cache = features.get(CLEAR_ALL_CACHE); Boolean cache = features.get(CLEAR_ALL_CACHE);
if (cache != null) { if (cache != null) {
clearAllCache = cache.booleanValue(); clearAllCache = cache.booleanValue();
@@ -530,12 +519,6 @@ public class InAppBrowser extends CordovaPlugin {
@SuppressLint("NewApi") @SuppressLint("NewApi")
public void run() { public void run() {
// CB-6702 InAppBrowser hangs when opening more than one instance
if (dialog != null) {
dialog.dismiss();
};
// Let's create the main dialog // Let's create the main dialog
dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar); dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog; dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
@@ -669,20 +652,6 @@ public class InAppBrowser extends CordovaPlugin {
settings.setBuiltInZoomControls(showZoomControls); settings.setBuiltInZoomControls(showZoomControls);
settings.setPluginState(android.webkit.WebSettings.PluginState.ON); settings.setPluginState(android.webkit.WebSettings.PluginState.ON);
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
settings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture);
}
String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
String appendUserAgent = preferences.getString("AppendUserAgent", null);
if (overrideUserAgent != null) {
settings.setUserAgentString(overrideUserAgent);
}
if (appendUserAgent != null) {
settings.setUserAgentString(settings.getUserAgentString() + appendUserAgent);
}
//Toggle whether this is enabled or not! //Toggle whether this is enabled or not!
Bundle appSettings = cordova.getActivity().getIntent().getExtras(); Bundle appSettings = cordova.getActivity().getIntent().getExtras();
boolean enableDatabase = appSettings == null ? true : appSettings.getBoolean("InAppBrowserStorageEnabled", true); boolean enableDatabase = appSettings == null ? true : appSettings.getBoolean("InAppBrowserStorageEnabled", true);
@@ -893,13 +862,6 @@ public class InAppBrowser extends CordovaPlugin {
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url); super.onPageFinished(view, url);
// CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().flush();
} else {
CookieSyncManager.getInstance().sync();
}
try { try {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("type", LOAD_STOP_EVENT); obj.put("type", LOAD_STOP_EVENT);
@@ -961,3 +923,4 @@ public class InAppBrowser extends CordovaPlugin {
} }
} }
} }
+2 -26
View File
@@ -390,14 +390,7 @@
[self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId]; [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
return NO; return NO;
} }
} } else if ((self.callbackId != nil) && isTopLevelNavigation) {
//if is an app store link, let the system handle it, otherwise it fails to load it
else if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
[theWebView stopLoading];
[self openInSystem:url];
return NO;
}
else if ((self.callbackId != nil) && isTopLevelNavigation) {
// Send a loadstart event for each top-level navigation (includes redirects). // Send a loadstart event for each top-level navigation (includes redirects).
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}]; messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}];
@@ -755,10 +748,6 @@
return UIStatusBarStyleDefault; return UIStatusBarStyleDefault;
} }
- (BOOL)prefersStatusBarHidden {
return NO;
}
- (void)close - (void)close
{ {
[CDVUserAgentUtil releaseLock:&_userAgentLockToken]; [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
@@ -1004,26 +993,13 @@
// simplified from: http://stackoverflow.com/a/25669695/219684 // simplified from: http://stackoverflow.com/a/25669695/219684
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:[self invertFrameIfNeeded:frame]]; UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:frame];
bgToolbar.barStyle = UIBarStyleDefault; bgToolbar.barStyle = UIBarStyleDefault;
[bgToolbar setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[self.view addSubview:bgToolbar]; [self.view addSubview:bgToolbar];
[super viewDidLoad]; [super viewDidLoad];
} }
- (CGRect) invertFrameIfNeeded:(CGRect)rect {
// We need to invert since on iOS 7 frames are always in Portrait context
if (!IsAtLeastiOSVersion(@"8.0")) {
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
CGFloat temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
rect.origin = CGPointZero;
}
}
return rect;
}
#pragma mark CDVScreenOrientationDelegate #pragma mark CDVScreenOrientationDelegate
+176 -199
View File
@@ -25,6 +25,7 @@
var cordova = require('cordova'), var cordova = require('cordova'),
channel = require('cordova/channel'),
urlutil = require('cordova/urlutil'); urlutil = require('cordova/urlutil');
var browserWrap, var browserWrap,
@@ -34,12 +35,11 @@ var browserWrap,
backButton, backButton,
forwardButton, forwardButton,
closeButton, closeButton,
bodyOverflowStyle, bodyOverflowStyle;
navigationEventsCallback;
// x-ms-webview is available starting from Windows 8.1 (platformId is 'windows') // x-ms-webview is available starting from Windows 8.1 (platformId is 'windows')
// http://msdn.microsoft.com/en-us/library/windows/apps/dn301831.aspx // http://msdn.microsoft.com/en-us/library/windows/apps/dn301831.aspx
var isWebViewAvailable = cordova.platformId === 'windows'; var isWebViewAvailable = cordova.platformId == 'windows';
function attachNavigationEvents(element, callback) { function attachNavigationEvents(element, callback) {
if (isWebViewAvailable) { if (isWebViewAvailable) {
@@ -48,21 +48,17 @@ function attachNavigationEvents(element, callback) {
}); });
element.addEventListener("MSWebViewNavigationCompleted", function (e) { element.addEventListener("MSWebViewNavigationCompleted", function (e) {
if (e.isSuccess) { callback({ type: e.isSuccess ? "loadstop" : "loaderror", url: e.uri}, {keepCallback: true});
callback({ type: "loadstop", url: e.uri }, { keepCallback: true });
} else {
callback({ type: "loaderror", url: e.uri, code: e.webErrorStatus, message: "Navigation failed with error code " + e.webErrorStatus}, { keepCallback: true });
}
}); });
element.addEventListener("MSWebViewUnviewableContentIdentified", function (e) { element.addEventListener("MSWebViewUnviewableContentIdentified", function (e) {
// WebView found the content to be not HTML. // WebView found the content to be not HTML.
// http://msdn.microsoft.com/en-us/library/windows/apps/dn609716.aspx // http://msdn.microsoft.com/en-us/library/windows/apps/dn609716.aspx
callback({ type: "loaderror", url: e.uri, code: e.webErrorStatus, message: "Navigation failed with error code " + e.webErrorStatus}, { keepCallback: true }); callback({ type: "loaderror", url: e.uri}, {keepCallback: true});
}); });
element.addEventListener("MSWebViewContentLoading", function (e) { element.addEventListener("MSWebViewContentLoading", function (e) {
if (navigationButtonsDiv && popup) { if (navigationButtonsDiv) {
if (popup.canGoBack) { if (popup.canGoBack) {
backButton.removeAttribute("disabled"); backButton.removeAttribute("disabled");
} else { } else {
@@ -96,228 +92,209 @@ function attachNavigationEvents(element, callback) {
var IAB = { var IAB = {
close: function (win, lose) { close: function (win, lose) {
setImmediate(function () { if (browserWrap) {
if (browserWrap) { if (win) win({ type: "exit" });
if (navigationEventsCallback) {
navigationEventsCallback({ type: "exit" });
}
browserWrap.parentNode.removeChild(browserWrap); browserWrap.parentNode.removeChild(browserWrap);
// Reset body overflow style to initial value // Reset body overflow style to initial value
document.body.style.msOverflowStyle = bodyOverflowStyle; document.body.style.msOverflowStyle = bodyOverflowStyle;
browserWrap = null; browserWrap = null;
popup = null; popup = null;
} }
});
}, },
show: function (win, lose) { show: function (win, lose) {
setImmediate(function () { if (browserWrap) {
if (browserWrap) { browserWrap.style.display = "block";
browserWrap.style.display = "block"; }
}
});
}, },
open: function (win, lose, args) { open: function (win, lose, args) {
// make function async so that we can add navigation events handlers before view is loaded and navigation occured var strUrl = args[0],
setImmediate(function () { target = args[1],
var strUrl = args[0], features = args[2],
target = args[1], url;
features = args[2],
url;
navigationEventsCallback = win; if (target === "_system") {
url = new Windows.Foundation.Uri(strUrl);
Windows.System.Launcher.launchUriAsync(url);
} else if (target === "_self" || !target) {
window.location = strUrl;
} else {
// "_blank" or anything else
if (!browserWrap) {
var browserWrapStyle = document.createElement('link');
browserWrapStyle.rel = "stylesheet";
browserWrapStyle.type = "text/css";
browserWrapStyle.href = urlutil.makeAbsolute("/www/css/inappbrowser.css");
if (target === "_system") { document.head.appendChild(browserWrapStyle);
url = new Windows.Foundation.Uri(strUrl);
Windows.System.Launcher.launchUriAsync(url);
} else if (target === "_self" || !target) {
window.location = strUrl;
} else {
// "_blank" or anything else
if (!browserWrap) {
var browserWrapStyle = document.createElement('link');
browserWrapStyle.rel = "stylesheet";
browserWrapStyle.type = "text/css";
browserWrapStyle.href = urlutil.makeAbsolute("/www/css/inappbrowser.css");
document.head.appendChild(browserWrapStyle); browserWrap = document.createElement("div");
browserWrap.className = "inAppBrowserWrap";
browserWrap = document.createElement("div"); if (features.indexOf("fullscreen=yes") > -1) {
browserWrap.className = "inAppBrowserWrap"; browserWrap.classList.add("inAppBrowserWrapFullscreen");
if (features.indexOf("fullscreen=yes") > -1) {
browserWrap.classList.add("inAppBrowserWrapFullscreen");
}
// Save body overflow style to be able to reset it back later
bodyOverflowStyle = document.body.style.msOverflowStyle;
browserWrap.onclick = function () {
setTimeout(function () {
IAB.close(navigationEventsCallback);
}, 0);
};
document.body.appendChild(browserWrap);
// Hide scrollbars for the whole body while inappbrowser's window is open
document.body.style.msOverflowStyle = "none";
} }
if (features.indexOf("hidden=yes") !== -1) { // Save body overflow style to be able to reset it back later
browserWrap.style.display = "none"; bodyOverflowStyle = document.body.style.msOverflowStyle;
}
popup = document.createElement(isWebViewAvailable ? "x-ms-webview" : "iframe"); browserWrap.onclick = function () {
if (popup instanceof HTMLIFrameElement) { setTimeout(function () {
// For iframe we need to override bacground color of parent element here IAB.close(win);
// otherwise pages without background color set will have transparent background }, 0);
popup.style.backgroundColor = "white"; };
}
popup.style.borderWidth = "0px";
popup.style.width = "100%";
browserWrap.appendChild(popup); document.body.appendChild(browserWrap);
// Hide scrollbars for the whole body while inappbrowser's window is open
if (features.indexOf("location=yes") !== -1 || features.indexOf("location") === -1) { document.body.style.msOverflowStyle = "none";
popup.style.height = "calc(100% - 70px)";
navigationButtonsDiv = document.createElement("div");
navigationButtonsDiv.className = "inappbrowser-app-bar";
navigationButtonsDiv.onclick = function (e) {
e.cancelBubble = true;
};
navigationButtonsDivInner = document.createElement("div");
navigationButtonsDivInner.className = "inappbrowser-app-bar-inner"
navigationButtonsDivInner.onclick = function (e) {
e.cancelBubble = true;
};
backButton = document.createElement("div");
backButton.innerText = "back";
backButton.className = "app-bar-action action-back";
backButton.addEventListener("click", function (e) {
if (popup.canGoBack)
popup.goBack();
});
forwardButton = document.createElement("div");
forwardButton.innerText = "forward";
forwardButton.className = "app-bar-action action-forward";
forwardButton.addEventListener("click", function (e) {
if (popup.canGoForward)
popup.goForward();
});
closeButton = document.createElement("div");
closeButton.innerText = "close";
closeButton.className = "app-bar-action action-close";
closeButton.addEventListener("click", function (e) {
setTimeout(function () {
IAB.close(navigationEventsCallback);
}, 0);
});
if (!isWebViewAvailable) {
// iframe navigation is not yet supported
backButton.setAttribute("disabled", "true");
forwardButton.setAttribute("disabled", "true");
}
navigationButtonsDivInner.appendChild(backButton);
navigationButtonsDivInner.appendChild(forwardButton);
navigationButtonsDivInner.appendChild(closeButton);
navigationButtonsDiv.appendChild(navigationButtonsDivInner);
browserWrap.appendChild(navigationButtonsDiv);
} else {
popup.style.height = "100%";
}
// start listening for navigation events
attachNavigationEvents(popup, navigationEventsCallback);
if (isWebViewAvailable) {
strUrl = strUrl.replace("ms-appx://", "ms-appx-web://");
}
popup.src = strUrl;
} }
});
if (features.indexOf("hidden=yes") !== -1) {
browserWrap.style.display = "none";
}
popup = document.createElement(isWebViewAvailable ? "x-ms-webview" : "iframe");
if (popup instanceof HTMLIFrameElement) {
// For iframe we need to override bacground color of parent element here
// otherwise pages without background color set will have transparent background
popup.style.backgroundColor = "white";
}
popup.style.borderWidth = "0px";
popup.style.width = "100%";
browserWrap.appendChild(popup);
if (features.indexOf("location=yes") !== -1 || features.indexOf("location") === -1) {
popup.style.height = "calc(100% - 70px)";
navigationButtonsDiv = document.createElement("div");
navigationButtonsDiv.className = "inappbrowser-app-bar";
navigationButtonsDiv.onclick = function (e) {
e.cancelBubble = true;
};
navigationButtonsDivInner = document.createElement("div");
navigationButtonsDivInner.className = "inappbrowser-app-bar-inner"
navigationButtonsDivInner.onclick = function (e) {
e.cancelBubble = true;
};
backButton = document.createElement("div");
backButton.innerText = "back";
backButton.className = "app-bar-action action-back";
backButton.addEventListener("click", function (e) {
if (popup.canGoBack)
popup.goBack();
});
forwardButton = document.createElement("div");
forwardButton.innerText = "forward";
forwardButton.className = "app-bar-action action-forward";
forwardButton.addEventListener("click", function (e) {
if (popup.canGoForward)
popup.goForward();
});
closeButton = document.createElement("div");
closeButton.innerText = "close";
closeButton.className = "app-bar-action action-close";
closeButton.addEventListener("click", function (e) {
setTimeout(function () {
IAB.close(win);
}, 0);
});
if (!isWebViewAvailable) {
// iframe navigation is not yet supported
backButton.setAttribute("disabled", "true");
forwardButton.setAttribute("disabled", "true");
}
navigationButtonsDivInner.appendChild(backButton);
navigationButtonsDivInner.appendChild(forwardButton);
navigationButtonsDivInner.appendChild(closeButton);
navigationButtonsDiv.appendChild(navigationButtonsDivInner);
browserWrap.appendChild(navigationButtonsDiv);
} else {
popup.style.height = "100%";
}
// start listening for navigation events
attachNavigationEvents(popup, win);
if (isWebViewAvailable) {
strUrl = strUrl.replace("ms-appx://", "ms-appx-web://");
}
popup.src = strUrl;
}
}, },
injectScriptCode: function (win, fail, args) { injectScriptCode: function (win, fail, args) {
setImmediate(function () { var code = args[0],
var code = args[0], hasCallback = args[1];
hasCallback = args[1];
if (isWebViewAvailable && browserWrap && popup) { if (isWebViewAvailable && browserWrap && popup) {
var op = popup.invokeScriptAsync("eval", code); var op = popup.invokeScriptAsync("eval", code);
op.oncomplete = function (e) { op.oncomplete = function (e) {
// return null if event target is unavailable by some reason // return null if event target is unavailable by some reason
var result = (e && e.target) ? [e.target.result] : [null]; var result = (e && e.target) ? [e.target.result] : [null];
hasCallback && win(result); hasCallback && win(result);
}; };
op.onerror = function () { }; op.onerror = function () { };
op.start(); op.start();
} }
});
}, },
injectScriptFile: function (win, fail, args) { injectScriptFile: function (win, fail, args) {
setImmediate(function () { var filePath = args[0],
var filePath = args[0], hasCallback = args[1];
hasCallback = args[1];
if (!!filePath) { if (!!filePath) {
filePath = urlutil.makeAbsolute(filePath); filePath = urlutil.makeAbsolute(filePath);
} }
if (isWebViewAvailable && browserWrap && popup) { if (isWebViewAvailable && browserWrap && popup) {
var uri = new Windows.Foundation.Uri(filePath); var uri = new Windows.Foundation.Uri(filePath);
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) { Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) {
Windows.Storage.FileIO.readTextAsync(file).done(function (code) { Windows.Storage.FileIO.readTextAsync(file).done(function (code) {
var op = popup.invokeScriptAsync("eval", code); var op = popup.invokeScriptAsync("eval", code);
op.oncomplete = function(e) { op.oncomplete = function(e) {
var result = [e.target.result]; var result = [e.target.result];
hasCallback && win(result); hasCallback && win(result);
}; };
op.onerror = function () { }; op.onerror = function () { };
op.start(); op.start();
});
}); });
} });
}); }
}, },
injectStyleCode: function (win, fail, args) { injectStyleCode: function (win, fail, args) {
setImmediate(function () { var code = args[0],
var code = args[0], hasCallback = args[1];
hasCallback = args[1];
if (isWebViewAvailable && browserWrap && popup) { if (isWebViewAvailable && browserWrap && popup) {
injectCSS(popup, code, hasCallback && win); injectCSS(popup, code, hasCallback && win);
} }
});
}, },
injectStyleFile: function (win, fail, args) { injectStyleFile: function (win, fail, args) {
setImmediate(function () { var filePath = args[0],
var filePath = args[0], hasCallback = args[1];
hasCallback = args[1];
filePath = filePath && urlutil.makeAbsolute(filePath); filePath = filePath && urlutil.makeAbsolute(filePath);
if (isWebViewAvailable && browserWrap && popup) { if (isWebViewAvailable && browserWrap && popup) {
var uri = new Windows.Foundation.Uri(filePath); var uri = new Windows.Foundation.Uri(filePath);
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) { Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file); return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (code) { }).done(function (code) {
injectCSS(popup, code, hasCallback && win); injectCSS(popup, code, hasCallback && win);
}, function () { }, function () {
// no-op, just catch an error // no-op, just catch an error
}); });
} }
});
} }
}; };
+1 -3
View File
@@ -20,12 +20,10 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-inappbrowser-tests" id="cordova-plugin-inappbrowser-tests"
version="1.3.0"> version="1.2.1-dev">
<name>Cordova InAppBrowser Plugin Tests</name> <name>Cordova InAppBrowser Plugin Tests</name>
<license>Apache 2.0</license> <license>Apache 2.0</license>
<dependency id="cordova-plugin-dialogs" />
<js-module src="tests.js" name="tests"> <js-module src="tests.js" name="tests">
</js-module> </js-module>
-3
View File
@@ -38,8 +38,5 @@
<button onclick="document.getElementById('player').play()"> play </button> <button onclick="document.getElementById('player').play()"> play </button>
<button onclick="document.getElementById('player').pause()"> pause </button> <button onclick="document.getElementById('player').pause()"> pause </button>
</div> </div>
<script>
document.getElementById('player').play();
</script>
</body> </body>
</html> </html>
+22 -63
View File
@@ -34,64 +34,50 @@ exports.defineAutoTests = function () {
it("inappbrowser.spec.2 should contain open function", function () { it("inappbrowser.spec.2 should contain open function", function () {
expect(cordova.InAppBrowser.open).toBeDefined(); expect(cordova.InAppBrowser.open).toBeDefined();
expect(cordova.InAppBrowser.open).toEqual(jasmine.any(Function)); expect(typeof cordova.InAppBrowser.open === 'function').toBe(true);
}); });
}); });
describe('open method', function () { describe('open method', function () {
var iabInstance; var iabInsance;
var originalTimeout; var originalTimeout;
var url = 'https://dist.apache.org/repos/dist/dev/cordova/'; var url = 'http://apache.org/';
var badUrl = 'http://bad-uri/';
beforeEach(function () { beforeEach(function () {
// increase timeout to ensure test url could be loaded within test time // increase timeout to ensure test url could be loaded within test time
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
iabInstance = null; iabInsance = null;
}); });
afterEach(function (done) { afterEach(function () {
// restore original timeout // restore original timeout
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
if (iabInstance !== null && iabInstance.close) { if (iabInsance && iabInsance.close) {
iabInstance.close(); iabInsance.close();
} }
iabInstance = null; iabInsance = null;
// add some extra time so that iab dialog is closed
setTimeout(done, 2000);
}); });
function verifyEvent(evt, type) { function verifyEvent(evt, type) {
expect(evt).toBeDefined(); expect(evt).toBeDefined();
expect(evt.type).toEqual(type); expect(evt.type).toEqual(type);
if (type !== 'exit') { // `exit` event does not have url field expect(evt.url).toEqual(url);
expect(evt.url).toEqual(url);
}
} }
function verifyLoadErrorEvent(evt) { it("inappbrowser.spec.3 should retun InAppBrowser class instance", function () {
expect(evt).toBeDefined(); iabInsance = cordova.InAppBrowser.open(url, '_blank');
expect(evt.type).toEqual('loaderror');
expect(evt.url).toEqual(badUrl);
expect(evt.code).toEqual(jasmine.any(Number));
expect(evt.message).toEqual(jasmine.any(String));
}
it("inappbrowser.spec.3 should retun InAppBrowser instance with required methods", function () { expect(iabInsance).toBeDefined();
iabInstance = cordova.InAppBrowser.open(url, '_blank');
expect(iabInstance).toBeDefined(); expect(iabInsance.addEventListener).toBeDefined();
expect(typeof iabInsance.addEventListener === 'function').toBe(true);
expect(iabInsance.close).toBeDefined();
expect(typeof iabInsance.close === 'function').toBe(true);
expect(iabInstance.addEventListener).toEqual(jasmine.any(Function));
expect(iabInstance.removeEventListener).toEqual(jasmine.any(Function));
expect(iabInstance.close).toEqual(jasmine.any(Function));
expect(iabInstance.show).toEqual(jasmine.any(Function));
expect(iabInstance.executeScript).toEqual(jasmine.any(Function));
expect(iabInstance.insertCSS).toEqual(jasmine.any(Function));
}); });
it("inappbrowser.spec.4 should support loadstart and loadstop events", function (done) { it("inappbrowser.spec.4 should support loadstart and loadstop events", function (done) {
@@ -99,32 +85,14 @@ exports.defineAutoTests = function () {
verifyEvent(evt, 'loadstart'); verifyEvent(evt, 'loadstart');
}); });
iabInstance = cordova.InAppBrowser.open(url, '_blank'); iabInsance = cordova.InAppBrowser.open(url, '_blank');
iabInstance.addEventListener('loadstart', onLoadStart); iabInsance.addEventListener('loadstart', onLoadStart);
iabInstance.addEventListener('loadstop', function (evt) { iabInsance.addEventListener('loadstop', function (evt) {
verifyEvent(evt, 'loadstop'); verifyEvent(evt, 'loadstop');
expect(onLoadStart).toHaveBeenCalled(); expect(onLoadStart).toHaveBeenCalled();
done(); done();
}); });
}); });
it("inappbrowser.spec.5 should support exit event", function (done) {
iabInstance = cordova.InAppBrowser.open(url, '_blank');
iabInstance.addEventListener('exit', function (evt) {
verifyEvent(evt, 'exit');
done();
});
iabInstance.close();
iabInstance = null;
});
it("inappbrowser.spec.6 should support loaderror event", function (done) {
iabInstance = cordova.InAppBrowser.open(badUrl, '_blank');
iabInstance.addEventListener('loaderror', function (evt) {
verifyLoadErrorEvent(evt);
done();
});
});
}); });
}; };
@@ -423,11 +391,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
var video_tag_tests = '<h1>Video tag</h1>' + var video_tag_tests = '<h1>Video tag</h1>' +
'<div id="openRemoteVideo"></div>' + '<div id="openRemoteVideo"></div>' +
'Expected result: open successfully in InAppBrowser with an embedded video plays automatically on iOS and Android.' + 'Expected result: open successfully in InAppBrowser with an embedded video that works after clicking the "play" button.';
'<div id="openRemoteNeedUserNoVideo"></div>' +
'Expected result: open successfully in InAppBrowser with an embedded video plays automatically on iOS and Android.' +
'<div id="openRemoteNeedUserYesVideo"></div>' +
'Expected result: open successfully in InAppBrowser with an embedded video does not play automatically on iOS and Android but rather works after clicking the "play" button.';
var local_with_anchor_tag_tests = '<h1>Local with anchor tag</h1>' + var local_with_anchor_tag_tests = '<h1>Local with anchor tag</h1>' +
'<div id="openAnchor1"></div>' + '<div id="openAnchor1"></div>' +
@@ -615,12 +579,6 @@ exports.defineManualTests = function (contentEl, createActionButton) {
createActionButton('Remote Video', function () { createActionButton('Remote Video', function () {
doOpen(videohtml, '_blank'); doOpen(videohtml, '_blank');
}, 'openRemoteVideo'); }, 'openRemoteVideo');
createActionButton('Remote Need User No Video', function () {
doOpen(videohtml, '_blank', 'mediaPlaybackRequiresUserAction=no');
}, 'openRemoteNeedUserNoVideo');
createActionButton('Remote Need User Yes Video', function () {
doOpen(videohtml, '_blank', 'mediaPlaybackRequiresUserAction=yes');
}, 'openRemoteNeedUserYesVideo');
//Local With Anchor Tag //Local With Anchor Tag
createActionButton('Anchor1', function () { createActionButton('Anchor1', function () {
@@ -630,3 +588,4 @@ exports.defineManualTests = function (contentEl, createActionButton) {
doOpen(localhtml + '#anchor2', '_blank'); doOpen(localhtml + '#anchor2', '_blank');
}, 'openAnchor2'); }, 'openAnchor2');
}; };