Compare commits

..

1 Commits

Author SHA1 Message Date
Niklas Merz
8bc15de222 Revert "fix: explicitly import dependencies, instead of relying on PCH files. This is important in Swift projects, where you cannot use prefix headers. (#927)"
This reverts commit 31860cf6c3a10de87844062dac116aa635e85a2e.
2023-11-03 19:16:03 +01:00
18 changed files with 2853 additions and 2240 deletions

View File

@ -149,12 +149,20 @@ instance, or the system browser.
- __toolbarposition__: Set to `top` or `bottom` (default is `bottom`). Causes the toolbar to be at the top or bottom of the window. - __toolbarposition__: Set to `top` or `bottom` (default is `bottom`). Causes the toolbar to be at the top or bottom of the window.
- __hidespinner__: Set to `yes` or `no` to change the visibility of the loading indicator (defaults to `no`). - __hidespinner__: Set to `yes` or `no` to change the visibility of the loading indicator (defaults to `no`).
Windows supports these additional options:
- __hidden__: set to `yes` to create the browser and load the page, but not show it. The loadstop event fires when loading is complete. Omit or set to `no` (default) to have the browser open and load normally.
- __hardwareback__: works the same way as on Android platform.
- __fullscreen__: set to `yes` to create the browser control without a border around it. Please note that if __location=no__ is also specified, there will be no control presented to user to close IAB window.
### Supported Platforms ### Supported Platforms
- Android - Android
- Browser - Browser
- iOS - iOS
- OSX
- Windows
### Example ### Example
@ -356,11 +364,17 @@ function downloadListener(params){
- Android - Android
- Browser - Browser
- iOS - iOS
- Windows
- OSX
### Browser Quirks ### Browser Quirks
`loadstart`, `loaderror`, `message` events are not fired. `loadstart`, `loaderror`, `message` events are not fired.
### Windows Quirks
`message` event is not fired.
### Quick Example ### Quick Example
var ref = cordova.InAppBrowser.open('https://apache.org', '_blank', 'location=yes'); var ref = cordova.InAppBrowser.open('https://apache.org', '_blank', 'location=yes');
@ -391,6 +405,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- Browser - Browser
- iOS - iOS
- Windows
### Quick Example ### Quick Example
@ -412,6 +427,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- Browser - Browser
- iOS - iOS
- Windows
### Quick Example ### Quick Example
@ -431,6 +447,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- Browser - Browser
- iOS - iOS
- Windows
### Quick Example ### Quick Example
@ -450,6 +467,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- iOS - iOS
- Windows
### Quick Example ### Quick Example
@ -481,6 +499,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- Browser - Browser
- iOS - iOS
- Windows
### Quick Example ### Quick Example
@ -493,6 +512,10 @@ The function is passed an `InAppBrowserEvent` object.
- only __code__ key is supported. - only __code__ key is supported.
### Windows Quirks
Due to [MSDN docs](https://msdn.microsoft.com/en-us/library/windows.ui.xaml.controls.webview.invokescriptasync.aspx) the invoked script can return only string values, otherwise the parameter, passed to __callback__ will be `[null]`.
## InAppBrowser.insertCSS ## InAppBrowser.insertCSS
> Injects CSS into the `InAppBrowser` window. (Only available when the target is set to `'_blank'`) > Injects CSS into the `InAppBrowser` window. (Only available when the target is set to `'_blank'`)
@ -511,6 +534,7 @@ The function is passed an `InAppBrowserEvent` object.
- Android - Android
- iOS - iOS
- Windows
### Quick Example ### Quick Example

View File

@ -20,31 +20,6 @@
--> -->
# Release Notes # Release Notes
### 6.0.0 (Nov 10, 2023)
* [GH-1033](https://github.com/apache/cordova-plugin-inappbrowser/pull/1033) chore: bump to next major release 6.0.0 & update deependencies
* [GH-1032](https://github.com/apache/cordova-plugin-inappbrowser/pull/1032) chore(lint): update eslint config and apply fixes
* [GH-1030](https://github.com/apache/cordova-plugin-inappbrowser/pull/1030) fix!: remove deprecated platforms **Windows** & osx
* [GH-1031](https://github.com/apache/cordova-plugin-inappbrowser/pull/1031) fix(ios): Remove deprecation warnings and old code
* [GH-927](https://github.com/apache/cordova-plugin-inappbrowser/pull/927) fix: explicitly import dependencies, instead of relying on PCH files. This is important in Swift projects, where you cannot use prefix headers.
* [GH-968](https://github.com/apache/cordova-plugin-inappbrowser/pull/968) GH-706 **Android**: Allow permissions requests
* [GH-1029](https://github.com/apache/cordova-plugin-inappbrowser/pull/1029) chore: update asf config
* [GH-1019](https://github.com/apache/cordova-plugin-inappbrowser/pull/1019) feat(android): Download event
* [GH-1020](https://github.com/apache/cordova-plugin-inappbrowser/pull/1020) ci(gh-action): Paramedic CI sync
* [GH-1015](https://github.com/apache/cordova-plugin-inappbrowser/pull/1015) feat(ios): Make WebView inspectable
* [GH-1016](https://github.com/apache/cordova-plugin-inappbrowser/pull/1016) chore: use https urls in tests and `README`
* [GH-1017](https://github.com/apache/cordova-plugin-inappbrowser/pull/1017) chore: Update SUPPORT_QUESTION.md template
* [GH-977](https://github.com/apache/cordova-plugin-inappbrowser/pull/977) fix(docs): missing xml indicator in code block
* [GH-971](https://github.com/apache/cordova-plugin-inappbrowser/pull/971) ci: sync workflow with paramedic
* [GH-964](https://github.com/apache/cordova-plugin-inappbrowser/pull/964) dep(npm): bump package-lock v2 w/ rebuild
* [GH-957](https://github.com/apache/cordova-plugin-inappbrowser/pull/957) ci(android): update java requirement for `cordova-android`@11
* [GH-946](https://github.com/apache/cordova-plugin-inappbrowser/pull/946) fix(android): increase toolbar to 48dp
* [GH-912](https://github.com/apache/cordova-plugin-inappbrowser/pull/912) ci(ios): update workflow w/ **iOS** 15
* [GH-907](https://github.com/apache/cordova-plugin-inappbrowser/pull/907) ci: add action-badge
* [GH-906](https://github.com/apache/cordova-plugin-inappbrowser/pull/906) ci: remove travis & appveyor
* [GH-903](https://github.com/apache/cordova-plugin-inappbrowser/pull/903) ci: add gh-actions workflows
* [GH-861](https://github.com/apache/cordova-plugin-inappbrowser/pull/861) fix(android): add space between default useragent and custom AppendUserAgent
* [GH-881](https://github.com/apache/cordova-plugin-inappbrowser/pull/881) fix(ios): make system open tel, sms, mailto and geo links
### 5.0.0 (Feb 10, 2021) ### 5.0.0 (Feb 10, 2021)
* [GH-828](https://github.com/apache/cordova-plugin-inappbrowser/pull/828) feat(ios): add `InAppBrowser`StatusBarStyle 'darkcontent' configuration option * [GH-828](https://github.com/apache/cordova-plugin-inappbrowser/pull/828) feat(ios): add `InAppBrowser`StatusBarStyle 'darkcontent' configuration option
* [GH-823](https://github.com/apache/cordova-plugin-inappbrowser/pull/823) chore: bump engines requirements * [GH-823](https://github.com/apache/cordova-plugin-inappbrowser/pull/823) chore: bump engines requirements

3979
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "cordova-plugin-inappbrowser", "name": "cordova-plugin-inappbrowser",
"version": "6.0.1-dev", "version": "5.1.0-dev",
"description": "Cordova InAppBrowser Plugin", "description": "Cordova InAppBrowser Plugin",
"types": "./types/index.d.ts", "types": "./types/index.d.ts",
"cordova": { "cordova": {
@ -8,7 +8,9 @@
"platforms": [ "platforms": [
"android", "android",
"browser", "browser",
"ios" "ios",
"osx",
"windows"
] ]
}, },
"repository": "github:apache/cordova-plugin-inappbrowser", "repository": "github:apache/cordova-plugin-inappbrowser",
@ -22,7 +24,9 @@
"ecosystem:cordova", "ecosystem:cordova",
"cordova-android", "cordova-android",
"cordova-browser", "cordova-browser",
"cordova-ios" "cordova-ios",
"cordova-osx",
"cordova-windows"
], ],
"scripts": { "scripts": {
"test": "npm run lint", "test": "npm run lint",
@ -42,12 +46,7 @@
"cordova-ios": ">=6.0.0", "cordova-ios": ">=6.0.0",
"cordova": ">=9.0.0" "cordova": ">=9.0.0"
}, },
"6.0.1-dev": { "6.0.0": {
"cordova-android": ">=10.0.0",
"cordova-ios": ">=6.0.0",
"cordova": ">=9.0.0"
},
"7.0.0": {
"cordova": ">100" "cordova": ">100"
} }
} }
@ -55,6 +54,6 @@
"author": "Apache Software Foundation", "author": "Apache Software Foundation",
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@cordova/eslint-config": "^5.0.0" "@cordova/eslint-config": "^3.0.0"
} }
} }

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="6.0.1-dev"> version="5.1.0-dev">
<name>InAppBrowser</name> <name>InAppBrowser</name>
<description>Cordova InAppBrowser Plugin</description> <description>Cordova InAppBrowser Plugin</description>
@ -91,6 +91,32 @@
<framework src="CoreGraphics.framework" /> <framework src="CoreGraphics.framework" />
</platform> </platform>
<!-- osx -->
<platform name="osx">
<js-module src="www/inappbrowser.js" name="inappbrowser">
<clobbers target="cordova.InAppBrowser.open" />
</js-module>
<config-file target="config.xml" parent="/*">
<feature name="InAppBrowser">
<param name="osx-package" value="CDVInAppBrowser" />
</feature>
</config-file>
<header-file src="src/osx/CDVInAppBrowser.h" />
<source-file src="src/osx/CDVInAppBrowser.m" />
</platform>
<!-- windows -->
<platform name="windows">
<js-module src="www/inappbrowser.js" name="inappbrowser">
<clobbers target="cordova.InAppBrowser.open" />
</js-module>
<js-module src="src/windows/InAppBrowserProxy.js" name="InAppBrowserProxy">
<runs />
</js-module>
<asset src="www/inappbrowser.css" target="css/inappbrowser.css" />
</platform>
<!-- browser --> <!-- browser -->
<platform name="browser"> <platform name="browser">
<js-module src="www/inappbrowser.js" name="inappbrowser"> <js-module src="www/inappbrowser.js" name="inappbrowser">

View File

@ -19,35 +19,35 @@
* *
*/ */
const modulemapper = require('cordova/modulemapper'); var modulemapper = require('cordova/modulemapper');
let browserWrap, popup, navigationButtonsDiv, navigationButtonsDivInner, backButton, forwardButton, closeButton; var browserWrap, popup, navigationButtonsDiv, navigationButtonsDivInner, backButton, forwardButton, closeButton;
function attachNavigationEvents (element, callback) { function attachNavigationEvents (element, callback) {
const onError = function () { var onError = function () {
try { try {
callback({ type: 'loaderror', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loaderror', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} catch (err) { } catch (err) {
// blocked by CORS :\ // blocked by CORS :\
callback({ type: 'loaderror', url: null }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loaderror', url: null }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} }
}; };
element.addEventListener('pageshow', function () { element.addEventListener('pageshow', function () {
try { try {
callback({ type: 'loadstart', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loadstart', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} catch (err) { } catch (err) {
// blocked by CORS :\ // blocked by CORS :\
callback({ type: 'loadstart', url: null }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loadstart', url: null }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} }
}); });
element.addEventListener('load', function () { element.addEventListener('load', function () {
try { try {
callback({ type: 'loadstop', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loadstop', url: this.contentWindow.location.href }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} catch (err) { } catch (err) {
// blocked by CORS :\ // blocked by CORS :\
callback({ type: 'loadstop', url: null }, { keepCallback: true }); // eslint-disable-line n/no-callback-literal callback({ type: 'loadstop', url: null }, { keepCallback: true }); // eslint-disable-line standard/no-callback-literal
} }
}); });
@ -55,7 +55,7 @@ function attachNavigationEvents (element, callback) {
element.addEventListener('abort', onError); element.addEventListener('abort', onError);
} }
const IAB = { var IAB = {
close: function (win, lose) { close: function (win, lose) {
if (browserWrap) { if (browserWrap) {
// use the "open" function callback so that the exit event is fired properly // use the "open" function callback so that the exit event is fired properly
@ -74,9 +74,9 @@ const IAB = {
}, },
open: function (win, lose, args) { open: function (win, lose, args) {
const strUrl = args[0]; var strUrl = args[0];
const target = args[1]; var target = args[1];
const features = args[2]; var features = args[2];
IAB._win = win; IAB._win = win;
@ -200,8 +200,8 @@ const IAB = {
}, },
injectScriptCode: function (win, fail, args) { injectScriptCode: function (win, fail, args) {
const code = args[0]; var code = args[0];
const hasCallback = args[1]; var hasCallback = args[1];
if (browserWrap && popup) { if (browserWrap && popup) {
try { try {
@ -216,7 +216,7 @@ const IAB = {
}, },
injectScriptFile: function (win, fail, args) { injectScriptFile: function (win, fail, args) {
const msg = 'Browser cordova-plugin-inappbrowser injectScriptFile is not yet implemented'; var msg = 'Browser cordova-plugin-inappbrowser injectScriptFile is not yet implemented';
console.warn(msg); console.warn(msg);
if (fail) { if (fail) {
fail(msg); fail(msg);
@ -224,7 +224,7 @@ const IAB = {
}, },
injectStyleCode: function (win, fail, args) { injectStyleCode: function (win, fail, args) {
const msg = 'Browser cordova-plugin-inappbrowser injectStyleCode is not yet implemented'; var msg = 'Browser cordova-plugin-inappbrowser injectStyleCode is not yet implemented';
console.warn(msg); console.warn(msg);
if (fail) { if (fail) {
fail(msg); fail(msg);
@ -232,7 +232,7 @@ const IAB = {
}, },
injectStyleFile: function (win, fail, args) { injectStyleFile: function (win, fail, args) {
const msg = 'Browser cordova-plugin-inappbrowser injectStyleFile is not yet implemented'; var msg = 'Browser cordova-plugin-inappbrowser injectStyleFile is not yet implemented';
console.warn(msg); console.warn(msg);
if (fail) { if (fail) {
fail(msg); fail(msg);

View File

@ -17,7 +17,6 @@
under the License. under the License.
*/ */
#import <UIKit/UINavigationController.h>
#import <Cordova/CDVScreenOrientationDelegate.h> #import <Cordova/CDVScreenOrientationDelegate.h>

View File

@ -17,7 +17,6 @@
under the License. under the License.
*/ */
#import <Foundation/Foundation.h>
@interface CDVInAppBrowserOptions : NSObject {} @interface CDVInAppBrowserOptions : NSObject {}

View File

@ -19,7 +19,13 @@
#import "CDVWKInAppBrowser.h" #import "CDVWKInAppBrowser.h"
#import <Cordova/NSDictionary+CordovaPreferences.h> #import <Cordova/NSDictionary+CordovaPreferences.h>
#import <Cordova/CDVWebViewProcessPoolFactory.h>
#if __has_include(<Cordova/CDVWebViewProcessPoolFactory.h>) // Cordova-iOS >=6
#import <Cordova/CDVWebViewProcessPoolFactory.h>
#elif __has_include("CDVWKProcessPoolFactory.h") // Cordova-iOS <6 with WKWebView plugin
#import "CDVWKProcessPoolFactory.h"
#endif
#import <Cordova/CDVPluginResult.h> #import <Cordova/CDVPluginResult.h>
#define kInAppBrowserTargetSelf @"_self" #define kInAppBrowserTargetSelf @"_self"
@ -37,6 +43,11 @@
#pragma mark CDVWKInAppBrowser #pragma mark CDVWKInAppBrowser
@interface CDVWKInAppBrowser () {
NSInteger _previousStatusBarStyle;
}
@end
@implementation CDVWKInAppBrowser @implementation CDVWKInAppBrowser
static CDVWKInAppBrowser* instance = nil; static CDVWKInAppBrowser* instance = nil;
@ -48,6 +59,7 @@ static CDVWKInAppBrowser* instance = nil;
- (void)pluginInitialize - (void)pluginInitialize
{ {
instance = self; instance = self;
_previousStatusBarStyle = -1;
_callbackIdPattern = nil; _callbackIdPattern = nil;
_beforeload = @""; _beforeload = @"";
_waitForBeforeload = NO; _waitForBeforeload = NO;
@ -128,27 +140,64 @@ static CDVWKInAppBrowser* instance = nil;
} }
if (browserOptions.clearcache) { if (browserOptions.clearcache) {
// Deletes all cookies bool isAtLeastiOS11 = false;
WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
[cookieStore getAllCookies:^(NSArray* cookies) { if (@available(iOS 11.0, *)) {
NSHTTPCookie* cookie; isAtLeastiOS11 = true;
for(cookie in cookies){ }
[cookieStore deleteCookie:cookie completionHandler:nil]; #endif
}
}]; if(isAtLeastiOS11){
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
// Deletes all cookies
WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
[cookieStore getAllCookies:^(NSArray* cookies) {
NSHTTPCookie* cookie;
for(cookie in cookies){
[cookieStore deleteCookie:cookie completionHandler:nil];
}
}];
#endif
}else{
// https://stackoverflow.com/a/31803708/777265
// Only deletes domain cookies (not session cookies)
[dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records) {
for (WKWebsiteDataRecord *record in records){
NSSet<NSString*>* dataTypes = record.dataTypes;
if([dataTypes containsObject:WKWebsiteDataTypeCookies]){
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes
forDataRecords:@[record]
completionHandler:^{}];
}
}
}];
}
} }
if (browserOptions.clearsessioncache) { if (browserOptions.clearsessioncache) {
// Deletes session cookies bool isAtLeastiOS11 = false;
WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
[cookieStore getAllCookies:^(NSArray* cookies) { if (@available(iOS 11.0, *)) {
NSHTTPCookie* cookie; isAtLeastiOS11 = true;
for(cookie in cookies){ }
if(cookie.sessionOnly){ #endif
[cookieStore deleteCookie:cookie completionHandler:nil]; if (isAtLeastiOS11) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
// Deletes session cookies
WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
[cookieStore getAllCookies:^(NSArray* cookies) {
NSHTTPCookie* cookie;
for(cookie in cookies){
if(cookie.sessionOnly){
[cookieStore deleteCookie:cookie completionHandler:nil];
}
} }
} }];
}]; #endif
}else{
NSLog(@"clearsessioncache not available below iOS 11.0");
}
} }
if (self.inAppBrowserViewController == nil) { if (self.inAppBrowserViewController == nil) {
@ -230,6 +279,14 @@ static CDVWKInAppBrowser* instance = nil;
NSLog(@"Tried to show IAB after it was closed."); NSLog(@"Tried to show IAB after it was closed.");
return; return;
} }
if (_previousStatusBarStyle != -1) {
NSLog(@"Tried to show IAB while already shown");
return;
}
if(!initHidden){
_previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
}
__block CDVInAppBrowserNavigationController* nav = [[CDVInAppBrowserNavigationController alloc] __block CDVInAppBrowserNavigationController* nav = [[CDVInAppBrowserNavigationController alloc]
initWithRootViewController:self.inAppBrowserViewController]; initWithRootViewController:self.inAppBrowserViewController];
@ -277,10 +334,17 @@ static CDVWKInAppBrowser* instance = nil;
} }
if (_previousStatusBarStyle == -1) {
NSLog(@"Tried to hide IAB while already hidden");
return;
}
_previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
// Run later to avoid the "took a long time" log message. // Run later to avoid the "took a long time" log message.
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (self.inAppBrowserViewController != nil) { if (self.inAppBrowserViewController != nil) {
_previousStatusBarStyle = -1;
[self.inAppBrowserViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; [self.inAppBrowserViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
} }
}); });
@ -290,17 +354,16 @@ static CDVWKInAppBrowser* instance = nil;
{ {
NSURLRequest* request = [NSURLRequest requestWithURL:url]; NSURLRequest* request = [NSURLRequest requestWithURL:url];
// the webview engine itself will filter for this according to <allow-navigation> policy // the webview engine itself will filter for this according to <allow-navigation> policy
// in config.xml // in config.xml for cordova-ios-4.0
[self.webViewEngine loadRequest:request]; [self.webViewEngine loadRequest:request];
} }
- (void)openInSystem:(NSURL*)url - (void)openInSystem:(NSURL*)url
{ {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) { if ([[UIApplication sharedApplication] openURL:url] == NO) {
if (!success) { [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; [[UIApplication sharedApplication] openURL:url];
} }
}];
} }
- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
@ -619,6 +682,15 @@ static CDVWKInAppBrowser* instance = nil;
// Based on https://stackoverflow.com/questions/4544489/how-to-remove-a-uiwindow // Based on https://stackoverflow.com/questions/4544489/how-to-remove-a-uiwindow
self->tmpWindow.hidden = YES; self->tmpWindow.hidden = YES;
self->tmpWindow = nil; self->tmpWindow = nil;
if (IsAtLeastiOSVersion(@"7.0")) {
if (_previousStatusBarStyle != -1) {
[[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle];
}
}
_previousStatusBarStyle = -1; // this value was reset before reapplying it. caused statusbar to stay black on ios7
} }
@end //CDVWKInAppBrowser @end //CDVWKInAppBrowser
@ -680,11 +752,15 @@ BOOL isExiting = FALSE;
//WKWebView options //WKWebView options
configuration.allowsInlineMediaPlayback = _browserOptions.allowinlinemediaplayback; configuration.allowsInlineMediaPlayback = _browserOptions.allowinlinemediaplayback;
configuration.ignoresViewportScaleLimits = _browserOptions.enableviewportscale; if (IsAtLeastiOSVersion(@"10.0")) {
if(_browserOptions.mediaplaybackrequiresuseraction == YES){ configuration.ignoresViewportScaleLimits = _browserOptions.enableviewportscale;
configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll; if(_browserOptions.mediaplaybackrequiresuseraction == YES){
}else{ configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;
configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; }else{
configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
}
}else{ // iOS 9
configuration.mediaPlaybackRequiresUserAction = _browserOptions.mediaplaybackrequiresuseraction;
} }
if (@available(iOS 13.0, *)) { if (@available(iOS 13.0, *)) {
@ -737,7 +813,11 @@ BOOL isExiting = FALSE;
self.webView.allowsLinkPreview = NO; self.webView.allowsLinkPreview = NO;
self.webView.allowsBackForwardNavigationGestures = NO; self.webView.allowsBackForwardNavigationGestures = NO;
[self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
if (@available(iOS 11.0, *)) {
[self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
#endif
self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.spinner.alpha = 1.000; self.spinner.alpha = 1.000;
@ -867,7 +947,7 @@ BOOL isExiting = FALSE;
// but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one) // but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one)
self.closeButton = nil; self.closeButton = nil;
// Initialize with title if title is set, otherwise the title will be 'Done' localized // Initialize with title if title is set, otherwise the title will be 'Done' localized
self.closeButton = title != nil ? [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:self action:@selector(close)] : [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)]; self.closeButton = title != nil ? [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)] : [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
self.closeButton.enabled = YES; self.closeButton.enabled = YES;
// If color on closebutton is requested then initialize with that that color, otherwise use initialize with default // If color on closebutton is requested then initialize with that that color, otherwise use initialize with default
self.closeButton.tintColor = colorString != nil ? [self colorFromHexString:colorString] : [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1]; self.closeButton.tintColor = colorString != nil ? [self colorFromHexString:colorString] : [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
@ -1068,8 +1148,13 @@ BOOL isExiting = FALSE;
[super viewWillAppear:animated]; [super viewWillAppear:animated];
} }
//
// On iOS 7 the status bar is part of the view's dimensions, therefore it's height has to be taken into account.
// The height of it could be hardcoded as 20 pixels, but that would assume that the upcoming releases of iOS won't
// change that value.
//
- (float) getStatusBarOffset { - (float) getStatusBarOffset {
return (float) [[UIApplication sharedApplication] statusBarFrame].size.height; return (float) IsAtLeastiOSVersion(@"7.0") ? [[UIApplication sharedApplication] statusBarFrame].size.height : 0.0;
} }
- (void) rePositionViews { - (void) rePositionViews {

30
src/osx/CDVInAppBrowser.h Normal file
View File

@ -0,0 +1,30 @@
/*
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 <Cordova/CDVPlugin.h>
@interface CDVInAppBrowser : CDVPlugin {
}
@property (nonatomic, copy) NSString* callbackId;
- (void)open:(CDVInvokedUrlCommand*)command;
@end

89
src/osx/CDVInAppBrowser.m Normal file
View File

@ -0,0 +1,89 @@
/*
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 "CDVInAppBrowser.h"
#import <Cordova/CDVPluginResult.h>
#define kInAppBrowserTargetSelf @"_self"
#define kInAppBrowserTargetSystem @"_system"
#define kInAppBrowserTargetBlank @"_blank"
@interface CDVInAppBrowser () {
}
@end
@implementation CDVInAppBrowser
- (void)pluginInitialize
{
}
- (BOOL) isSystemUrl:(NSURL*)url
{
if ([[url host] isEqualToString:@"itunes.apple.com"]) {
return YES;
}
return NO;
}
- (void)open:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult;
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
self.callbackId = command.callbackId;
if (url != nil) {
NSURL* baseUrl = [NSURL URLWithString:url];
NSURL* absoluteUrl = [[NSURL URLWithString:url relativeToURL:baseUrl] absoluteURL];
if ([self isSystemUrl:absoluteUrl]) {
target = kInAppBrowserTargetSystem;
}
if ([target isEqualToString:kInAppBrowserTargetSelf]) {
//[self openInCordovaWebView:absoluteUrl withOptions:options];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Not Yet Implemented for OSX: [self openInCordovaWebView:absoluteUrl withOptions:options]"];
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
[self openInSystem:absoluteUrl];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else { // _blank or anything else
//[self openInInAppBrowser:absoluteUrl withOptions:options];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Not Yet Implemented for OSX: [self openInInAppBrowser:absoluteUrl withOptions:options]"];
}
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"];
}
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
- (void)openInSystem:(NSURL*)url
{
[[NSWorkspace sharedWorkspace] openURL:url];
}
@end

View File

@ -0,0 +1,407 @@
/*
*
* 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.
*
*/
/* eslint-disable standard/no-callback-literal */
/* global Windows, setImmediate */
var cordova = require('cordova');
var urlutil = require('cordova/urlutil');
var browserWrap,
popup,
navigationButtonsDiv,
navigationButtonsDivInner,
backButton,
forwardButton,
closeButton,
bodyOverflowStyle,
navigationEventsCallback,
hardwareBackCallback;
// x-ms-webview is available starting from Windows 8.1 (platformId is 'windows')
// http://msdn.microsoft.com/en-us/library/windows/apps/dn301831.aspx
var isWebViewAvailable = cordova.platformId === 'windows';
function attachNavigationEvents (element, callback) {
if (isWebViewAvailable) {
element.addEventListener('MSWebViewNavigationStarting', function (e) {
callback({ type: 'loadstart', url: e.uri }, { keepCallback: true });
});
element.addEventListener('MSWebViewNavigationCompleted', function (e) {
if (e.isSuccess) {
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) {
// WebView found the content to be not HTML.
// 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 }
);
});
element.addEventListener('MSWebViewContentLoading', function (e) {
if (navigationButtonsDiv && popup) {
if (popup.canGoBack) {
backButton.removeAttribute('disabled');
} else {
backButton.setAttribute('disabled', 'true');
}
if (popup.canGoForward) {
forwardButton.removeAttribute('disabled');
} else {
forwardButton.setAttribute('disabled', 'true');
}
}
});
} else {
var onError = function () {
callback({ type: 'loaderror', url: this.contentWindow.location }, { keepCallback: true });
};
element.addEventListener('unload', function () {
callback({ type: 'loadstart', url: this.contentWindow.location }, { keepCallback: true });
});
element.addEventListener('load', function () {
callback({ type: 'loadstop', url: this.contentWindow.location }, { keepCallback: true });
});
element.addEventListener('error', onError);
element.addEventListener('abort', onError);
}
}
var IAB = {
close: function (win, lose) {
setImmediate(function () {
if (browserWrap) {
if (navigationEventsCallback) {
navigationEventsCallback({ type: 'exit' });
}
browserWrap.parentNode.removeChild(browserWrap);
// Reset body overflow style to initial value
document.body.style.msOverflowStyle = bodyOverflowStyle;
browserWrap = null;
popup = null;
document.removeEventListener('backbutton', hardwareBackCallback, false);
}
});
},
show: function (win, lose) {
setImmediate(function () {
if (browserWrap) {
browserWrap.style.display = 'block';
}
});
},
hide: function (win, lose) {
if (browserWrap) {
browserWrap.style.display = 'none';
}
},
open: function (win, lose, args) {
// make function async so that we can add navigation events handlers before view is loaded and navigation occured
setImmediate(function () {
var strUrl = args[0];
var target = args[1];
var features = args[2];
var 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');
document.head.appendChild(browserWrapStyle);
browserWrap = document.createElement('div');
browserWrap.className = 'inAppBrowserWrap';
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) {
browserWrap.style.display = 'none';
}
popup = document.createElement(isWebViewAvailable ? 'x-ms-webview' : 'iframe');
if (popup instanceof HTMLIFrameElement) {
// eslint-disable-line no-undef
// 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%';
popup.style.marginBottom = '-5px';
browserWrap.appendChild(popup);
var closeHandler = function (e) {
setTimeout(function () {
IAB.close(navigationEventsCallback);
}, 0);
};
if (features.indexOf('hardwareback=yes') > -1 || features.indexOf('hardwareback') === -1) {
hardwareBackCallback = function () {
if (browserWrap.style.display === 'none') {
// NOTE: backbutton handlers have to throw an exception in order to prevent
// returning 'true' inside cordova-js, which would mean that the event is handled by user.
// Throwing an exception means that the default/system navigation behavior will take place,
// which is to exit the app if the navigation stack is empty.
throw 'Exit the app'; // eslint-disable-line no-throw-literal
}
if (popup.canGoBack) {
popup.goBack();
} else {
closeHandler();
}
};
} else if (features.indexOf('hardwareback=no') > -1) {
hardwareBackCallback = function () {
if (browserWrap.style.display === 'none') {
// See comment above
throw 'Exit the app'; // eslint-disable-line no-throw-literal
}
closeHandler();
};
}
document.addEventListener('backbutton', hardwareBackCallback, false);
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', closeHandler);
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;
}
});
},
injectScriptCode: function (win, fail, args) {
setImmediate(function () {
var code = args[0];
var hasCallback = args[1];
if (isWebViewAvailable && browserWrap && popup) {
var op = popup.invokeScriptAsync('eval', code);
op.oncomplete = function (e) {
if (hasCallback) {
// return null if event target is unavailable by some reason
var result = e && e.target ? [e.target.result] : [null];
win(result);
}
};
op.onerror = function () {};
op.start();
}
});
},
injectScriptFile: function (win, fail, args) {
setImmediate(function () {
var filePath = args[0];
var hasCallback = args[1];
if (filePath) {
filePath = urlutil.makeAbsolute(filePath);
}
if (isWebViewAvailable && browserWrap && popup) {
// CB-12364 getFileFromApplicationUriAsync does not support ms-appx-web
var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) {
Windows.Storage.FileIO.readTextAsync(file).done(function (code) {
var op = popup.invokeScriptAsync('eval', code);
op.oncomplete = function (e) {
if (hasCallback) {
var result = [e.target.result];
win(result);
}
};
op.onerror = function () {};
op.start();
});
});
}
});
},
injectStyleCode: function (win, fail, args) {
setImmediate(function () {
var code = args[0];
var hasCallback = args[1];
if (isWebViewAvailable && browserWrap && popup) {
injectCSS(popup, code, hasCallback && win);
}
});
},
injectStyleFile: function (win, fail, args) {
setImmediate(function () {
var filePath = args[0];
var hasCallback = args[1];
filePath = filePath && urlutil.makeAbsolute(filePath);
if (isWebViewAvailable && browserWrap && popup) {
// CB-12364 getFileFromApplicationUriAsync does not support ms-appx-web
var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri)
.then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
})
.done(
function (code) {
injectCSS(popup, code, hasCallback && win);
},
function () {
// no-op, just catch an error
}
);
}
});
}
};
function injectCSS (webView, cssCode, callback) {
// This will automatically escape all thing that we need (quotes, slashes, etc.)
var escapedCode = JSON.stringify(cssCode);
var evalWrapper = "(function(d){var c=d.createElement('style');c.innerHTML=%s;d.head.appendChild(c);})(document)".replace(
'%s',
escapedCode
);
var op = webView.invokeScriptAsync('eval', evalWrapper);
op.oncomplete = function () {
if (callback) {
callback([]);
}
};
op.onerror = function () {};
op.start();
}
module.exports = IAB;
require('cordova/exec/proxy').add('InAppBrowser', module.exports);

View File

@ -1,6 +1,6 @@
{ {
"name": "cordova-plugin-inappbrowser-tests", "name": "cordova-plugin-inappbrowser-tests",
"version": "6.0.1-dev", "version": "5.1.0-dev",
"description": "", "description": "",
"cordova": { "cordova": {
"id": "cordova-plugin-inappbrowser-tests", "id": "cordova-plugin-inappbrowser-tests",

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-tests" id="cordova-plugin-inappbrowser-tests"
version="6.0.1-dev"> version="5.1.0-dev">
<name>Cordova InAppBrowser Plugin Tests</name> <name>Cordova InAppBrowser Plugin Tests</name>
<license>Apache 2.0</license> <license>Apache 2.0</license>

View File

@ -17,5 +17,5 @@
* under the License. * under the License.
*/ */
const d = document.getElementById('header'); var d = document.getElementById('header');
d.innerHTML = 'Script file successfully injected'; d.innerHTML = 'Script file successfully injected';

View File

@ -19,15 +19,22 @@
* *
*/ */
const cordova = require('cordova'); /* global MSApp */
const isIos = cordova.platformId === 'ios';
const isAndroid = cordova.platformId === 'android'; var cordova = require('cordova');
const isBrowser = cordova.platformId === 'browser'; var isWindows = cordova.platformId === 'windows';
var isIos = cordova.platformId === 'ios';
var isAndroid = cordova.platformId === 'android';
var isBrowser = cordova.platformId === 'browser';
window.alert = window.alert || navigator.notification.alert; window.alert = window.alert || navigator.notification.alert;
if (isWindows && navigator && navigator.notification && navigator.notification.alert) {
// window.alert is defined but not functional on UWP
window.alert = navigator.notification.alert;
}
exports.defineAutoTests = function () { exports.defineAutoTests = function () {
const createTests = function (platformOpts) { var createTests = function (platformOpts) {
platformOpts = platformOpts || ''; platformOpts = platformOpts || '';
describe('cordova.InAppBrowser', function () { describe('cordova.InAppBrowser', function () {
@ -47,10 +54,10 @@ exports.defineAutoTests = function () {
return; return;
} }
let iabInstance; var iabInstance;
let originalTimeout; var originalTimeout;
const url = 'https://dist.apache.org/repos/dist/dev/cordova/'; var url = 'https://dist.apache.org/repos/dist/dev/cordova/';
const badUrl = 'http://bad-uri/'; 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
@ -104,7 +111,7 @@ exports.defineAutoTests = 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) {
const onLoadStart = jasmine.createSpy('loadstart event callback').and.callFake(function (evt) { var onLoadStart = jasmine.createSpy('loadstart event callback').and.callFake(function (evt) {
verifyEvent(evt, 'loadstart'); verifyEvent(evt, 'loadstart');
}); });
@ -150,8 +157,8 @@ exports.defineAutoTests = function () {
if (!isAndroid && !isIos) { if (!isAndroid && !isIos) {
return pending(cordova.platformId + " platform doesn't support message event"); return pending(cordova.platformId + " platform doesn't support message event");
} }
const messageKey = 'my_message'; var messageKey = 'my_message';
const messageValue = 'is_this'; var messageValue = 'is_this';
iabInstance = cordova.InAppBrowser.open(url, '_blank', platformOpts); iabInstance = cordova.InAppBrowser.open(url, '_blank', platformOpts);
iabInstance.addEventListener('message', function (evt) { iabInstance.addEventListener('message', function (evt) {
// Verify message event // Verify message event
@ -163,7 +170,7 @@ exports.defineAutoTests = function () {
done(); done();
}); });
iabInstance.addEventListener('loadstop', function (evt) { iabInstance.addEventListener('loadstop', function (evt) {
const code = var code =
'(function(){\n' + '(function(){\n' +
' var message = {' + ' var message = {' +
messageKey + messageKey +
@ -172,7 +179,7 @@ exports.defineAutoTests = function () {
'"};\n' + '"};\n' +
' webkit.messageHandlers.cordova_iab.postMessage(JSON.stringify(message));\n' + ' webkit.messageHandlers.cordova_iab.postMessage(JSON.stringify(message));\n' +
'})()'; '})()';
iabInstance.executeScript({ code }); iabInstance.executeScript({ code: code });
}); });
}); });
}); });
@ -181,17 +188,17 @@ exports.defineAutoTests = function () {
}; };
exports.defineManualTests = function (contentEl, createActionButton) { exports.defineManualTests = function (contentEl, createActionButton) {
const platformOpts = ''; var platformOpts = '';
const platform_info = ''; var platform_info = '';
function doOpen (url, target, params, numExpectedRedirects, useWindowOpen) { function doOpen (url, target, params, numExpectedRedirects, useWindowOpen) {
numExpectedRedirects = numExpectedRedirects || 0; numExpectedRedirects = numExpectedRedirects || 0;
useWindowOpen = useWindowOpen || false; useWindowOpen = useWindowOpen || false;
console.log('Opening ' + url); console.log('Opening ' + url);
let counts; var counts;
let lastLoadStartURL; var lastLoadStartURL;
let wasReset = false; var wasReset = false;
function reset () { function reset () {
counts = { counts = {
loaderror: 0, loaderror: 0,
@ -203,8 +210,8 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
reset(); reset();
let iab; var iab;
const callbacks = { var callbacks = {
loaderror: logEvent, loaderror: logEvent,
loadstart: logEvent, loadstart: logEvent,
loadstop: logEvent, loadstop: logEvent,
@ -258,7 +265,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
// Verify that loadend / loaderror was called. // Verify that loadend / loaderror was called.
if (e.type === 'exit') { if (e.type === 'exit') {
const numStopEvents = counts.loadstop + counts.loaderror; var numStopEvents = counts.loadstop + counts.loaderror;
if (numStopEvents === 0 && !wasReset) { if (numStopEvents === 0 && !wasReset) {
alert('Unexpected: browser closed without a loadstop or loaderror.'); // eslint-disable-line no-undef alert('Unexpected: browser closed without a loadstop or loaderror.'); // eslint-disable-line no-undef
} else if (numStopEvents > 1) { } else if (numStopEvents > 1) {
@ -271,8 +278,8 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
function doHookOpen (url, target, params, numExpectedRedirects) { function doHookOpen (url, target, params, numExpectedRedirects) {
const originalFunc = window.open; var originalFunc = window.open;
const wasClobbered = Object.prototype.hasOwnProperty.call(window, 'open'); var wasClobbered = Object.prototype.hasOwnProperty.call(window, 'open');
window.open = cordova.InAppBrowser.open; window.open = cordova.InAppBrowser.open;
try { try {
@ -288,8 +295,8 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
function openWithStyle (url, cssUrl, useCallback) { function openWithStyle (url, cssUrl, useCallback) {
const iab = doOpen(url, '_blank', 'location=yes'); var iab = doOpen(url, '_blank', 'location=yes');
const callback = function (results) { var callback = function (results) {
if (results && results.length === 0) { if (results && results.length === 0) {
alert('Results verified'); // eslint-disable-line no-undef alert('Results verified'); // eslint-disable-line no-undef
} else { } else {
@ -309,7 +316,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
function openWithScript (url, jsUrl, useCallback) { function openWithScript (url, jsUrl, useCallback) {
const iab = doOpen(url, '_blank', 'location=yes'); var iab = doOpen(url, '_blank', 'location=yes');
if (jsUrl) { if (jsUrl) {
iab.addEventListener('loadstop', function (event) { iab.addEventListener('loadstop', function (event) {
iab.executeScript( iab.executeScript(
@ -327,14 +334,14 @@ exports.defineManualTests = function (contentEl, createActionButton) {
}); });
} else { } else {
iab.addEventListener('loadstop', function (event) { iab.addEventListener('loadstop', function (event) {
const code = var code =
'(function(){\n' + '(function(){\n' +
' var header = document.getElementById("header");\n' + ' var header = document.getElementById("header");\n' +
' header.innerHTML = "Script literal successfully injected";\n' + ' header.innerHTML = "Script literal successfully injected";\n' +
' return "abc";\n' + ' return "abc";\n' +
'})()'; '})()';
iab.executeScript( iab.executeScript(
{ code }, { code: code },
useCallback && useCallback &&
function (results) { function (results) {
if (results && results.length === 1 && results[0] === 'abc') { if (results && results.length === 1 && results[0] === 'abc') {
@ -348,12 +355,12 @@ exports.defineManualTests = function (contentEl, createActionButton) {
}); });
} }
} }
let hiddenwnd = null; var hiddenwnd = null;
const loadlistener = function (event) { var loadlistener = function (event) {
alert('background window loaded '); alert('background window loaded ');
}; // eslint-disable-line no-undef }; // eslint-disable-line no-undef
function openHidden (url, startHidden) { function openHidden (url, startHidden) {
let shopt = startHidden ? 'hidden=yes' : ''; var shopt = startHidden ? 'hidden=yes' : '';
if (platformOpts) { if (platformOpts) {
shopt += (shopt ? ',' : '') + platformOpts; shopt += (shopt ? ',' : '') + platformOpts;
} }
@ -377,7 +384,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
} }
} }
const info_div = var info_div =
'<h1>InAppBrowser</h1>' + '<h1>InAppBrowser</h1>' +
'<div id="info">' + '<div id="info">' +
'Make sure http://cordova.apache.org and http://google.co.uk and https://www.google.co.uk are white listed. </br>' + 'Make sure http://cordova.apache.org and http://google.co.uk and https://www.google.co.uk are white listed. </br>' +
@ -386,7 +393,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<h4>User-Agent: <span id="user-agent"> </span></hr>' + '<h4>User-Agent: <span id="user-agent"> </span></hr>' +
'</div>'; '</div>';
const local_tests = var local_tests =
'<h1>Local URL</h1>' + '<h1>Local URL</h1>' +
'<div id="openLocal"></div>' + '<div id="openLocal"></div>' +
'Expected result: opens successfully in CordovaWebView.' + 'Expected result: opens successfully in CordovaWebView.' +
@ -407,7 +414,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/><div id="openLocalRandomToolBarTopNoLocation"></div>' + '<p/><div id="openLocalRandomToolBarTopNoLocation"></div>' +
'Expected result: open successfully in InAppBrowser with no locationBar. On iOS the toolbar is at the top.'; 'Expected result: open successfully in InAppBrowser with no locationBar. On iOS the toolbar is at the top.';
const white_listed_tests = var white_listed_tests =
'<h1>White Listed URL</h1>' + '<h1>White Listed URL</h1>' +
'<div id="openWhiteListed"></div>' + '<div id="openWhiteListed"></div>' +
'Expected result: open successfully in CordovaWebView to cordova.apache.org' + 'Expected result: open successfully in CordovaWebView to cordova.apache.org' +
@ -424,7 +431,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openWhiteListedRandomNoLocation"></div>' + '<p/> <div id="openWhiteListedRandomNoLocation"></div>' +
'Expected result: open successfully in InAppBrowser to cordova.apache.org with no location bar.'; 'Expected result: open successfully in InAppBrowser to cordova.apache.org with no location bar.';
const non_white_listed_tests = var non_white_listed_tests =
'<h1>Non White Listed URL</h1>' + '<h1>Non White Listed URL</h1>' +
'<div id="openNonWhiteListed"></div>' + '<div id="openNonWhiteListed"></div>' +
'Expected result: open successfully in InAppBrowser to apple.com.' + 'Expected result: open successfully in InAppBrowser to apple.com.' +
@ -441,21 +448,21 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openNonWhiteListedRandomNoLocation"></div>' + '<p/> <div id="openNonWhiteListedRandomNoLocation"></div>' +
'Expected result: open successfully in InAppBrowser to apple.com without locationBar.'; 'Expected result: open successfully in InAppBrowser to apple.com without locationBar.';
const page_with_redirects_tests = var page_with_redirects_tests =
'<h1>Page with redirect</h1>' + '<h1>Page with redirect</h1>' +
'<div id="openRedirect301"></div>' + '<div id="openRedirect301"></div>' +
'Expected result: should 301 and open successfully in InAppBrowser to https://www.google.co.uk.' + 'Expected result: should 301 and open successfully in InAppBrowser to https://www.google.co.uk.' +
'<p/> <div id="openRedirect302"></div>' + '<p/> <div id="openRedirect302"></div>' +
'Expected result: should 302 and open successfully in InAppBrowser to www.zhihu.com/answer/16714076.'; 'Expected result: should 302 and open successfully in InAppBrowser to www.zhihu.com/answer/16714076.';
const pdf_url_tests = var pdf_url_tests =
'<h1>PDF URL</h1>' + '<h1>PDF URL</h1>' +
'<div id="openPDF"></div>' + '<div id="openPDF"></div>' +
'Expected result: InAppBrowser opens. PDF should render on iOS.' + 'Expected result: InAppBrowser opens. PDF should render on iOS.' +
'<p/> <div id="openPDFBlank"></div>' + '<p/> <div id="openPDFBlank"></div>' +
'Expected result: InAppBrowser opens. PDF should render on iOS.'; 'Expected result: InAppBrowser opens. PDF should render on iOS.';
const invalid_url_tests = var invalid_url_tests =
'<h1>Invalid URL</h1>' + '<h1>Invalid URL</h1>' +
'<div id="openInvalidScheme"></div>' + '<div id="openInvalidScheme"></div>' +
'Expected result: fail to load in InAppBrowser.' + 'Expected result: fail to load in InAppBrowser.' +
@ -464,7 +471,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openInvalidMissing"></div>' + '<p/> <div id="openInvalidMissing"></div>' +
'Expected result: fail to load in InAppBrowser (404).'; 'Expected result: fail to load in InAppBrowser (404).';
const css_js_injection_tests = var css_js_injection_tests =
'<h1>CSS / JS Injection</h1>' + '<h1>CSS / JS Injection</h1>' +
'<div id="openOriginalDocument"></div>' + '<div id="openOriginalDocument"></div>' +
'Expected result: open successfully in InAppBrowser without text "Style updated from..."' + 'Expected result: open successfully in InAppBrowser without text "Style updated from..."' +
@ -485,7 +492,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openScriptLiteralInjectionCallback"></div>' + '<p/> <div id="openScriptLiteralInjectionCallback"></div>' +
'Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" and alert dialog with the text "Results verified".'; 'Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" and alert dialog with the text "Results verified".';
const open_hidden_tests = var open_hidden_tests =
'<h1>Open Hidden </h1>' + '<h1>Open Hidden </h1>' +
'<div id="openHidden"></div>' + '<div id="openHidden"></div>' +
'Expected result: no additional browser window. Alert appears with the text "background window loaded".' + 'Expected result: no additional browser window. Alert appears with the text "background window loaded".' +
@ -498,14 +505,14 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openVisibleAndHide"></div>' + '<p/> <div id="openVisibleAndHide"></div>' +
'Expected result: open successfully in InAppBrowser to https://www.google.co.uk. Hide after 2 seconds'; 'Expected result: open successfully in InAppBrowser to https://www.google.co.uk. Hide after 2 seconds';
const clearing_cache_tests = var clearing_cache_tests =
'<h1>Clearing Cache</h1>' + '<h1>Clearing Cache</h1>' +
'<div id="openClearCache"></div>' + '<div id="openClearCache"></div>' +
'Expected result: ?' + 'Expected result: ?' +
'<p/> <div id="openClearSessionCache"></div>' + '<p/> <div id="openClearSessionCache"></div>' +
'Expected result: ?'; 'Expected result: ?';
const video_tag_tests = var video_tag_tests =
'<h1>Video tag</h1>' + '<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 plays automatically on iOS and Android.' +
@ -514,14 +521,14 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<div id="openRemoteNeedUserYesVideo"></div>' + '<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.'; '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.';
const local_with_anchor_tag_tests = var local_with_anchor_tag_tests =
'<h1>Local with anchor tag</h1>' + '<h1>Local with anchor tag</h1>' +
'<div id="openAnchor1"></div>' + '<div id="openAnchor1"></div>' +
'Expected result: open successfully in InAppBrowser to the local page, scrolled to the top as normal.' + 'Expected result: open successfully in InAppBrowser to the local page, scrolled to the top as normal.' +
'<p/> <div id="openAnchor2"></div>' + '<p/> <div id="openAnchor2"></div>' +
'Expected result: open successfully in InAppBrowser to the local page, scrolled to the beginning of the tall div with border.'; 'Expected result: open successfully in InAppBrowser to the local page, scrolled to the beginning of the tall div with border.';
const hardwareback_tests = var hardwareback_tests =
'<h1>HardwareBack</h1>' + '<h1>HardwareBack</h1>' +
'<p/> <div id="openHardwareBackDefault"></div>' + '<p/> <div id="openHardwareBackDefault"></div>' +
'Expected result: By default hardwareback is yes so pressing back button should navigate backwards in history then close InAppBrowser' + 'Expected result: By default hardwareback is yes so pressing back button should navigate backwards in history then close InAppBrowser' +
@ -532,32 +539,54 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'<p/> <div id="openHardwareBackDefaultAfterNo"></div>' + '<p/> <div id="openHardwareBackDefaultAfterNo"></div>' +
'Expected result: consistently open browsers with with the appropriate option: hardwareback=defaults to yes then hardwareback=no then hardwareback=defaults to yes. By default hardwareback is yes so pressing back button should navigate backwards in history then close InAppBrowser'; 'Expected result: consistently open browsers with with the appropriate option: hardwareback=defaults to yes then hardwareback=no then hardwareback=defaults to yes. By default hardwareback is yes so pressing back button should navigate backwards in history then close InAppBrowser';
contentEl.innerHTML = // CB-7490 We need to wrap this code due to Windows security restrictions
info_div + // see http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx#differences for details
platform_info + if (window.MSApp && window.MSApp.execUnsafeLocalFunction) {
local_tests + MSApp.execUnsafeLocalFunction(function () {
white_listed_tests + contentEl.innerHTML =
non_white_listed_tests + info_div +
page_with_redirects_tests + platform_info +
pdf_url_tests + local_tests +
invalid_url_tests + white_listed_tests +
css_js_injection_tests + non_white_listed_tests +
open_hidden_tests + page_with_redirects_tests +
clearing_cache_tests + pdf_url_tests +
video_tag_tests + invalid_url_tests +
local_with_anchor_tag_tests + css_js_injection_tests +
hardwareback_tests; open_hidden_tests +
clearing_cache_tests +
video_tag_tests +
local_with_anchor_tag_tests +
hardwareback_tests;
});
} else {
contentEl.innerHTML =
info_div +
platform_info +
local_tests +
white_listed_tests +
non_white_listed_tests +
page_with_redirects_tests +
pdf_url_tests +
invalid_url_tests +
css_js_injection_tests +
open_hidden_tests +
clearing_cache_tests +
video_tag_tests +
local_with_anchor_tag_tests +
hardwareback_tests;
}
document.getElementById('user-agent').textContent = navigator.userAgent; document.getElementById('user-agent').textContent = navigator.userAgent;
// we are already in cdvtests directory // we are already in cdvtests directory
const basePath = 'iab-resources/'; var basePath = 'iab-resources/';
const localhtml = basePath + 'local.html'; var localhtml = basePath + 'local.html';
const localpdf = basePath + 'local.pdf'; var localpdf = basePath + 'local.pdf';
const injecthtml = basePath + 'inject.html'; var injecthtml = basePath + 'inject.html';
const injectjs = 'inject.js'; var injectjs = isWindows ? basePath + 'inject.js' : 'inject.js';
const injectcss = 'inject.css'; var injectcss = isWindows ? basePath + 'inject.css' : 'inject.css';
const videohtml = basePath + 'video.html'; var videohtml = basePath + 'video.html';
// Local // Local
createActionButton( createActionButton(
@ -878,7 +907,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
createActionButton( createActionButton(
'google.co.uk shown for 2 seconds than hidden', 'google.co.uk shown for 2 seconds than hidden',
function () { function () {
const iab = doOpen('https://www.google.co.uk/', 'random_sting'); var iab = doOpen('https://www.google.co.uk/', 'random_sting');
setTimeout(function () { setTimeout(function () {
iab.hide(); iab.hide();
}, 2000); }, 2000);
@ -966,12 +995,12 @@ exports.defineManualTests = function (contentEl, createActionButton) {
createActionButton( createActionButton(
'no hardwareback -> hardwareback=no -> no hardwareback', 'no hardwareback -> hardwareback=no -> no hardwareback',
function () { function () {
const ref = cordova.InAppBrowser.open('https://google.com', '_blank', 'location=yes' + (platformOpts ? ',' + platformOpts : '')); var ref = cordova.InAppBrowser.open('https://google.com', '_blank', 'location=yes' + (platformOpts ? ',' + platformOpts : ''));
ref.addEventListener('loadstop', function () { ref.addEventListener('loadstop', function () {
ref.close(); ref.close();
}); });
ref.addEventListener('exit', function () { ref.addEventListener('exit', function () {
const ref2 = cordova.InAppBrowser.open( var ref2 = cordova.InAppBrowser.open(
'https://google.com', 'https://google.com',
'_blank', '_blank',
'location=yes,hardwareback=no' + (platformOpts ? ',' + platformOpts : '') 'location=yes,hardwareback=no' + (platformOpts ? ',' + platformOpts : '')

114
www/inappbrowser.css Normal file
View File

@ -0,0 +1,114 @@
/*
* 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.
*/
.inAppBrowserWrap {
margin: 0;
padding: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: 0 0;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999999;
box-sizing: border-box;
border: 40px solid #bfbfbf;
border: 40px solid rgba(0, 0, 0, 0.25);
}
.inAppBrowserWrapFullscreen {
border: 0;
}
.inappbrowser-app-bar {
height: 70px;
background-color: #404040;
z-index: 9999999;
}
.inappbrowser-app-bar-inner {
padding-top: 10px;
height: 60px;
width: 155px;
margin: 0 auto;
background-color: #404040;
z-index: 9999999;
}
.app-bar-action {
width: auto;
height: 40px;
margin-left: 20px;
font-family: "Segoe UI Symbol";
float: left;
color: white;
font-size: 12px;
text-transform: lowercase;
text-align: center;
cursor: default;
}
.app-bar-action[disabled] {
color: gray;
/*disable click*/
pointer-events: none;
}
.app-bar-action::before {
font-size: 28px;
display: block;
height: 36px;
}
/* Back */
.action-back {
margin-left: 0px;
}
.action-back::before {
content: "\E0BA";
}
.action-back:not([disabled]):hover::before {
content: "\E0B3";
}
/* Forward */
.action-forward::before {
content: "\E0AC";
}
.action-forward:not([disabled]):hover::before {
content: "\E0AF";
}
/* Close */
.action-close::before {
content: "\E0C7";
/* close icon is larger so we re-size it to fit other icons */
font-size: 20px;
line-height: 40px;
}
.action-close:not([disabled]):hover::before {
content: "\E0CA";
}

View File

@ -20,10 +20,10 @@
*/ */
(function () { (function () {
const exec = require('cordova/exec'); var exec = require('cordova/exec');
const channel = require('cordova/channel'); var channel = require('cordova/channel');
const modulemapper = require('cordova/modulemapper'); var modulemapper = require('cordova/modulemapper');
const urlutil = require('cordova/urlutil'); var urlutil = require('cordova/urlutil');
function InAppBrowser () { function InAppBrowser () {
this.channels = { this.channels = {
@ -100,19 +100,19 @@
module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) { module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
// Don't catch calls that write to existing frames (e.g. named iframes). // Don't catch calls that write to existing frames (e.g. named iframes).
if (window.frames && window.frames[strWindowName]) { if (window.frames && window.frames[strWindowName]) {
const origOpenFunc = modulemapper.getOriginalSymbol(window, 'open'); var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
return origOpenFunc.apply(window, arguments); return origOpenFunc.apply(window, arguments);
} }
strUrl = urlutil.makeAbsolute(strUrl); strUrl = urlutil.makeAbsolute(strUrl);
const iab = new InAppBrowser(); var iab = new InAppBrowser();
callbacks = callbacks || {}; callbacks = callbacks || {};
for (const callbackName in callbacks) { for (var callbackName in callbacks) {
iab.addEventListener(callbackName, callbacks[callbackName]); iab.addEventListener(callbackName, callbacks[callbackName]);
} }
const cb = function (eventname) { var cb = function (eventname) {
iab._eventHandler(eventname); iab._eventHandler(eventname);
}; };