Skip to content

Commit 19c6dfe

Browse files
committed
Merge branch 'master' into CB-7179
2 parents 7f5fa2a + d9cafcd commit 19c6dfe

File tree

6 files changed

+134
-20
lines changed

6 files changed

+134
-20
lines changed

README.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ Although `window.open` is in the global scope, InAppBrowser is not available unt
7171
console.log("window.open works well");
7272
}
7373

74-
Report issues with this plugin on the [Apache Cordova issue tracker](https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20%28Open%2C%20%22In%20Progress%22%2C%20Reopened%29%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20%22cordova-plugin-inappbrowser%22%20ORDER%20BY%20priority%20DESC%2C%20summary%20ASC%2C%20updatedDate%20DESC)
75-
76-
77-
## <a id="reference">Reference</a>
7874
## Installation
7975

8076
cordova plugin add cordova-plugin-inappbrowser
@@ -115,8 +111,9 @@ instance, or the system browser.
115111
Android supports these additional options:
116112

117113
- __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.
118-
- __clearcache__: set to `yes` to have the browser's cookie cache cleared before the new window is opened.
119-
- __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened.
114+
- __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages are actually loaded in the browser.
115+
- __clearcache__: set to `yes` to have the browser's cookie cache cleared before the new window is opened
116+
- __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened
120117
- __closebuttoncaption__: set to a string to use as the close button's caption instead of a X. Note that you need to localize this value yourself.
121118
- __closebuttoncolor__: set to a valid hex color string, for example: `#00ff00`, and it will change the
122119
close button color from default, regardless of being a text or default X. Only has effect if user has location set to `yes`.
@@ -138,6 +135,7 @@ instance, or the system browser.
138135

139136
- __usewkwebview__: set to `yes` to use WKWebView engine for the InappBrowser. Omit or set to `no` (default) to use UIWebView. Note: Using `usewkwebview=yes` requires that a WKWebView engine plugin be installed in the Cordova project (e.g. [cordova-plugin-wkwebview-engine](https://github.com/apache/cordova-plugin-wkwebview-engine) or [cordova-plugin-ionic-webview](https://github.com/ionic-team/cordova-plugin-ionic-webview)).
140137
- __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.
138+
- __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages are actually loaded in the browser.
141139
- __clearcache__: set to `yes` to have the browser's cookie cache cleared before the new window is opened
142140
- __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened. For WKWebView, requires iOS 11+ on target device.
143141
- __cleardata__: set to `yes` to have the browser's entire local storage cleared (cookies, HTML5 local storage, IndexedDB, etc.) before the new window is opened
@@ -219,6 +217,7 @@ The object returned from a call to `cordova.InAppBrowser.open` when the target i
219217
- __loadstop__: event fires when the `InAppBrowser` finishes loading a URL.
220218
- __loaderror__: event fires when the `InAppBrowser` encounters an error when loading a URL.
221219
- __exit__: event fires when the `InAppBrowser` window is closed.
220+
- __beforeload__: event fires when the `InAppBrowser` decides whether to load an URL or not (only with option `beforeload=yes`).
222221

223222
- __callback__: the function that executes when the event fires. The function is passed an `InAppBrowserEvent` object as a parameter.
224223

@@ -232,7 +231,7 @@ function showHelp(url) {
232231

233232
var target = "_blank";
234233

235-
var options = "location=yes,hidden=yes";
234+
var options = "location=yes,hidden=yes,beforeload=yes";
236235

237236
inAppBrowserRef = cordova.InAppBrowser.open(url, target, options);
238237

@@ -242,6 +241,8 @@ function showHelp(url) {
242241

243242
inAppBrowserRef.addEventListener('loaderror', loadErrorCallBack);
244243

244+
inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
245+
245246
}
246247

247248
function loadStartCallBack() {
@@ -290,6 +291,20 @@ function executeScriptCallBack(params) {
290291

291292
}
292293

294+
function beforeloadCallback(params, callback) {
295+
296+
if (params.url.startsWith("http://www.example.com/")) {
297+
298+
// Load this URL in the inAppBrowser.
299+
callback(params.url);
300+
} else {
301+
302+
// The callback is not invoked, so the page will not be loaded.
303+
$('#status-message').text("This browser only opens pages on http://www.example.com/");
304+
}
305+
306+
}
307+
293308
```
294309

295310
### InAppBrowserEvent Properties

src/android/InAppBrowser.java

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public class InAppBrowser extends CordovaPlugin {
110110
private static final String HIDE_URL = "hideurlbar";
111111
private static final String FOOTER = "footer";
112112
private static final String FOOTER_COLOR = "footercolor";
113+
private static final String BEFORELOAD = "beforeload";
113114

114115
private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
115116

@@ -138,6 +139,7 @@ public class InAppBrowser extends CordovaPlugin {
138139
private boolean hideUrlBar = false;
139140
private boolean showFooter = false;
140141
private String footerColor = "";
142+
private boolean useBeforeload = false;
141143
private String[] allowedSchemes;
142144

143145
/**
@@ -246,6 +248,20 @@ else if (SYSTEM.equals(target)) {
246248
else if (action.equals("close")) {
247249
closeDialog();
248250
}
251+
else if (action.equals("loadAfterBeforeload")) {
252+
if (!useBeforeload) {
253+
LOG.e(LOG_TAG, "unexpected loadAfterBeforeload called without feature beforeload=yes");
254+
}
255+
final String url = args.getString(0);
256+
this.cordova.getActivity().runOnUiThread(new Runnable() {
257+
@SuppressLint("NewApi")
258+
@Override
259+
public void run() {
260+
((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload = false;
261+
inAppWebView.loadUrl(url);
262+
}
263+
});
264+
}
249265
else if (action.equals("injectScriptCode")) {
250266
String jsWrapper = null;
251267
if (args.getBoolean(1)) {
@@ -674,6 +690,10 @@ public String showWebPage(final String url, HashMap<String, String> features) {
674690
if (footerColorSet != null) {
675691
footerColor = footerColorSet;
676692
}
693+
String beforeload = features.get(BEFORELOAD);
694+
if (beforeload != null) {
695+
useBeforeload = beforeload.equals("yes") ? true : false;
696+
}
677697
}
678698

679699
final CordovaWebView thatWebView = this.webView;
@@ -924,7 +944,7 @@ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)
924944
}
925945

926946
});
927-
WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
947+
WebViewClient client = new InAppBrowserClient(thatWebView, edittext, useBeforeload);
928948
inAppWebView.setWebViewClient(client);
929949
WebSettings settings = inAppWebView.getSettings();
930950
settings.setJavaScriptEnabled(true);
@@ -1085,16 +1105,20 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
10851105
public class InAppBrowserClient extends WebViewClient {
10861106
EditText edittext;
10871107
CordovaWebView webView;
1108+
boolean useBeforeload;
1109+
boolean waitForBeforeload;
10881110

10891111
/**
10901112
* Constructor.
10911113
*
10921114
* @param webView
10931115
* @param mEditText
10941116
*/
1095-
public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
1117+
public InAppBrowserClient(CordovaWebView webView, EditText mEditText, boolean useBeforeload) {
10961118
this.webView = webView;
10971119
this.edittext = mEditText;
1120+
this.useBeforeload = useBeforeload;
1121+
this.waitForBeforeload = useBeforeload;
10981122
}
10991123

11001124
/**
@@ -1107,12 +1131,27 @@ public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
11071131
*/
11081132
@Override
11091133
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
1134+
boolean override = false;
1135+
1136+
// On first URL change, initiate JS callback. Only after the beforeload event, continue.
1137+
if (this.waitForBeforeload) {
1138+
try {
1139+
JSONObject obj = new JSONObject();
1140+
obj.put("type", "beforeload");
1141+
obj.put("url", url);
1142+
sendUpdate(obj, true);
1143+
return true;
1144+
} catch (JSONException ex) {
1145+
LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
1146+
}
1147+
}
1148+
11101149
if (url.startsWith(WebView.SCHEME_TEL)) {
11111150
try {
11121151
Intent intent = new Intent(Intent.ACTION_DIAL);
11131152
intent.setData(Uri.parse(url));
11141153
cordova.getActivity().startActivity(intent);
1115-
return true;
1154+
override = true;
11161155
} catch (android.content.ActivityNotFoundException e) {
11171156
LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
11181157
}
@@ -1121,7 +1160,7 @@ public boolean shouldOverrideUrlLoading(WebView webView, String url) {
11211160
Intent intent = new Intent(Intent.ACTION_VIEW);
11221161
intent.setData(Uri.parse(url));
11231162
cordova.getActivity().startActivity(intent);
1124-
return true;
1163+
override = true;
11251164
} catch (android.content.ActivityNotFoundException e) {
11261165
LOG.e(LOG_TAG, "Error with " + url + ": " + e.toString());
11271166
}
@@ -1152,7 +1191,7 @@ else if (url.startsWith("sms:")) {
11521191
intent.putExtra("address", address);
11531192
intent.setType("vnd.android-dir/mms-sms");
11541193
cordova.getActivity().startActivity(intent);
1155-
return true;
1194+
override = true;
11561195
} catch (android.content.ActivityNotFoundException e) {
11571196
LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
11581197
}
@@ -1173,7 +1212,7 @@ else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^
11731212
obj.put("type", "customscheme");
11741213
obj.put("url", url);
11751214
sendUpdate(obj, true);
1176-
return true;
1215+
override = true;
11771216
} catch (JSONException ex) {
11781217
LOG.e(LOG_TAG, "Custom Scheme URI passed in has caused a JSON error.");
11791218
}
@@ -1182,7 +1221,10 @@ else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^
11821221
}
11831222
}
11841223

1185-
return false;
1224+
if (this.useBeforeload) {
1225+
this.waitForBeforeload = true;
1226+
}
1227+
return override;
11861228
}
11871229

11881230

@@ -1304,4 +1346,4 @@ public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, Str
13041346
super.onReceivedHttpAuthRequest(view, handler, host, realm);
13051347
}
13061348
}
1307-
}
1349+
}

src/ios/CDVInAppBrowserOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
@property (nonatomic, assign) BOOL suppressesincrementalrendering;
4646
@property (nonatomic, assign) BOOL hidden;
4747
@property (nonatomic, assign) BOOL disallowoverscroll;
48+
@property (nonatomic, assign) BOOL beforeload;
4849

4950
+ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
5051

src/ios/CDVUIInAppBrowser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333

3434
@interface CDVUIInAppBrowser : CDVPlugin {
3535
UIWindow * tmpWindow;
36+
37+
@private
38+
BOOL _useBeforeload;
39+
BOOL _waitForBeforeload;
3640
}
3741

3842
@property (nonatomic, retain) CDVUIInAppBrowserViewController* inAppBrowserViewController;
@@ -45,6 +49,7 @@
4549
- (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
4650
- (void)show:(CDVInvokedUrlCommand*)command;
4751
- (void)hide:(CDVInvokedUrlCommand*)command;
52+
- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command;
4853

4954
@end
5055

src/ios/CDVUIInAppBrowser.m

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ - (void)pluginInitialize
5353
instance = self;
5454
_previousStatusBarStyle = -1;
5555
_callbackIdPattern = nil;
56+
_useBeforeload = NO;
57+
_waitForBeforeload = NO;
5658
}
5759

5860
- (id)settingForKey:(NSString*)key
@@ -216,6 +218,10 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
216218
self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
217219
}
218220

221+
// use of beforeload event
222+
_useBeforeload = browserOptions.beforeload;
223+
_waitForBeforeload = browserOptions.beforeload;
224+
219225
[self.inAppBrowserViewController navigateTo:url];
220226
if (!browserOptions.hidden) {
221227
[self show:nil];
@@ -312,6 +318,27 @@ - (void)openInSystem:(NSURL*)url
312318
}
313319
}
314320

321+
- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
322+
{
323+
NSString* urlStr = [command argumentAtIndex:0];
324+
325+
if (!_useBeforeload) {
326+
NSLog(@"unexpected loadAfterBeforeload called without feature beforeload=yes");
327+
}
328+
if (self.inAppBrowserViewController == nil) {
329+
NSLog(@"Tried to invoke loadAfterBeforeload on IAB after it was closed.");
330+
return;
331+
}
332+
if (urlStr == nil) {
333+
NSLog(@"loadAfterBeforeload called with nil argument, ignoring.");
334+
return;
335+
}
336+
337+
NSURL* url = [NSURL URLWithString:urlStr];
338+
_waitForBeforeload = NO;
339+
[self.inAppBrowserViewController navigateTo:url];
340+
}
341+
315342
// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
316343
// provides a consistent method for injecting JavaScript code into the document.
317344
//
@@ -421,6 +448,7 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
421448
{
422449
NSURL* url = request.URL;
423450
BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
451+
BOOL shouldStart = YES;
424452

425453
// See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
426454
// and the path, if present, should be a JSON-encoded value to pass to the callback.
@@ -448,11 +476,22 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
448476
return NO;
449477
}
450478
}
479+
480+
// When beforeload=yes, on first URL change, initiate JS callback. Only after the beforeload event, continue.
481+
if (_waitForBeforeload && isTopLevelNavigation) {
482+
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
483+
messageAsDictionary:@{@"type":@"beforeload", @"url":[url absoluteString]}];
484+
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
485+
486+
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
487+
return NO;
488+
}
489+
451490
//if is an app store link, let the system handle it, otherwise it fails to load it
452-
else if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
491+
if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
453492
[theWebView stopLoading];
454493
[self openInSystem:url];
455-
return NO;
494+
shouldStart = NO;
456495
}
457496
else if ((self.callbackId != nil) && isTopLevelNavigation) {
458497
// Send a loadstart event for each top-level navigation (includes redirects).
@@ -463,8 +502,11 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
463502
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
464503
}
465504

466-
return YES;
467-
}
505+
if (_useBeforeload && isTopLevelNavigation) {
506+
_waitForBeforeload = YES;
507+
}
508+
509+
return shouldStart;
468510

469511
- (void)webViewDidStartLoad:(UIWebView*)theWebView
470512
{

www/inappbrowser.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
function InAppBrowser () {
3535
this.channels = {
36+
'beforeload': channel.create('beforeload'),
3637
'loadstart': channel.create('loadstart'),
3738
'loadstop': channel.create('loadstop'),
3839
'loaderror': channel.create('loaderror'),
@@ -44,9 +45,17 @@
4445
InAppBrowser.prototype = {
4546
_eventHandler: function (event) {
4647
if (event && (event.type in this.channels)) {
47-
this.channels[event.type].fire(event);
48+
if (event.type === 'beforeload') {
49+
this.channels[event.type].fire(event, this._loadAfterBeforeload);
50+
} else {
51+
this.channels[event.type].fire(event);
52+
}
4853
}
4954
},
55+
_loadAfterBeforeload: function (strUrl) {
56+
strUrl = urlutil.makeAbsolute(strUrl);
57+
exec(null, null, 'InAppBrowser', 'loadAfterBeforeload', [strUrl]);
58+
},
5059
close: function (eventname) {
5160
exec(null, null, 'InAppBrowser', 'close', []);
5261
},

0 commit comments

Comments
 (0)