Skip to content

Commit

Permalink
apacheGH-359: Distinguish between GET and POST requests when applied …
Browse files Browse the repository at this point in the history
…beforeload.

For now only GET is supported with beforeload, so document this.
  • Loading branch information
dpa99c committed Dec 10, 2018
1 parent 0fd43ae commit a6f2427
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 42 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ instance, or the system browser.
Android 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.
- __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages are actually loaded in the browser.
- __beforeload__: set to enable the `beforeload` event to modify which pages are actually loaded in the browser. Accepted values are `get` to intercept only GET requests, `post` to intercept on POST requests or `yes` to intercept both GET & POST requests. Note that POST requests are not currently supported and will be ignored (if you set `beforeload=post` it will raise an error).
- __clearcache__: set to `yes` to have the browser's 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
- __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.
Expand All @@ -130,7 +130,7 @@ instance, or the system browser.

- __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)).
- __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.
- __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages are actually loaded in the browser.
- __beforeload__: set to enable the `beforeload` event to modify which pages are actually loaded in the browser. Accepted values are `get` to intercept only GET requests, `post` to intercept on POST requests or `yes` to intercept both GET & POST requests. Note that POST requests are not currently supported and will be ignored (if you set `beforeload=post` it will raise an error).
- __clearcache__: set to `yes` to have the browser's 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. For WKWebView, requires iOS 11+ on target device.
- __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
Expand Down Expand Up @@ -212,7 +212,7 @@ The object returned from a call to `cordova.InAppBrowser.open` when the target i
- __loadstop__: event fires when the `InAppBrowser` finishes loading a URL.
- __loaderror__: event fires when the `InAppBrowser` encounters an error when loading a URL.
- __exit__: event fires when the `InAppBrowser` window is closed.
- __beforeload__: event fires when the `InAppBrowser` decides whether to load an URL or not (only with option `beforeload=yes`).
- __beforeload__: event fires when the `InAppBrowser` decides whether to load an URL or not (only with option `beforeload` set).

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

Expand Down
137 changes: 118 additions & 19 deletions src/android/InAppBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Licensed to the Apache Software Foundation (ASF) under one
package org.apache.cordova.inappbrowser;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
Expand Down Expand Up @@ -50,6 +51,8 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.webkit.HttpAuthHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
Expand Down Expand Up @@ -139,7 +142,7 @@ public class InAppBrowser extends CordovaPlugin {
private boolean hideUrlBar = false;
private boolean showFooter = false;
private String footerColor = "";
private boolean useBeforeload = false;
private String beforeload = "";
private String[] allowedSchemes;

/**
Expand Down Expand Up @@ -249,8 +252,8 @@ else if (action.equals("close")) {
closeDialog();
}
else if (action.equals("loadAfterBeforeload")) {
if (!useBeforeload) {
LOG.e(LOG_TAG, "unexpected loadAfterBeforeload called without feature beforeload=yes");
if (beforeload == null) {
LOG.e(LOG_TAG, "unexpected loadAfterBeforeload called without feature beforeload=yes");
}
final String url = args.getString(0);
this.cordova.getActivity().runOnUiThread(new Runnable() {
Expand Down Expand Up @@ -690,9 +693,8 @@ public String showWebPage(final String url, HashMap<String, String> features) {
if (footerColorSet != null) {
footerColor = footerColorSet;
}
String beforeload = features.get(BEFORELOAD);
if (beforeload != null) {
useBeforeload = beforeload.equals("yes") ? true : false;
if (features.get(BEFORELOAD) != null) {
beforeload = features.get(BEFORELOAD);
}
}

Expand Down Expand Up @@ -944,7 +946,7 @@ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)
}

});
WebViewClient client = new InAppBrowserClient(thatWebView, edittext, useBeforeload);
WebViewClient client = new InAppBrowserClient(thatWebView, edittext, beforeload);
inAppWebView.setWebViewClient(client);
WebSettings settings = inAppWebView.getSettings();
settings.setJavaScriptEnabled(true);
Expand Down Expand Up @@ -1105,7 +1107,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
public class InAppBrowserClient extends WebViewClient {
EditText edittext;
CordovaWebView webView;
boolean useBeforeload;
String beforeload;
boolean waitForBeforeload;

/**
Expand All @@ -1114,35 +1116,86 @@ public class InAppBrowserClient extends WebViewClient {
* @param webView
* @param mEditText
*/
public InAppBrowserClient(CordovaWebView webView, EditText mEditText, boolean useBeforeload) {
public InAppBrowserClient(CordovaWebView webView, EditText mEditText, String beforeload) {
this.webView = webView;
this.edittext = mEditText;
this.useBeforeload = useBeforeload;
this.waitForBeforeload = useBeforeload;
this.beforeload = beforeload;
this.waitForBeforeload = beforeload != null;
}

/**
* Override the URL that should be loaded
*
* This handles a small subset of all the URIs that would be encountered.
* Legacy (deprecated in API 24)
* For Android 6 and below.
*
* @param webView
* @param url
*/
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
return shouldOverrideUrlLoading(url, null);
}

/**
* Override the URL that should be loaded
*
* New (added in API 24)
* For Android 7 and above.
*
* @param webView
* @param request
*/
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request) {
return shouldOverrideUrlLoading(request.getUrl().toString(), request.getMethod());
}

/**
* Override the URL that should be loaded
*
* This handles a small subset of all the URIs that would be encountered.
*
* @param url
* @param method
*/
public boolean shouldOverrideUrlLoading(String url, String method) {
boolean override = false;
boolean useBeforeload = false;
String errorMessage = null;

if(beforeload.equals("yes")
//TODO handle POST requests then this condition can be removed:
&& !method.equals("POST"))
{
useBeforeload = true;
}else if(beforeload.equals("get") && (method == null || method.equals("GET"))){
useBeforeload = true;
}else if(beforeload.equals("post") && (method == null || method.equals("POST"))){
//TODO handle POST requests
errorMessage = "beforeload doesn't yet support POST requests";
}

// On first URL change, initiate JS callback. Only after the beforeload event, continue.
if (this.waitForBeforeload) {
if (useBeforeload && this.waitForBeforeload) {
if(sendBeforeLoad(url, method)){
return true;
}
}

if(errorMessage != null){
try {
LOG.e(LOG_TAG, errorMessage);
JSONObject obj = new JSONObject();
obj.put("type", "beforeload");
obj.put("type", LOAD_ERROR_EVENT);
obj.put("url", url);
sendUpdate(obj, true);
return true;
} catch (JSONException ex) {
LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
obj.put("code", -1);
obj.put("message", errorMessage);
sendUpdate(obj, true, PluginResult.Status.ERROR);
}catch(Exception e){
LOG.e(LOG_TAG, "Error sending loaderror for " + url + ": " + e.toString());
}
}

Expand Down Expand Up @@ -1221,12 +1274,58 @@ else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^
}
}

if (this.useBeforeload) {
if (useBeforeload) {
this.waitForBeforeload = true;
}
return override;
}

private boolean sendBeforeLoad(String url, String method){
try {
JSONObject obj = new JSONObject();
obj.put("type", "beforeload");
obj.put("url", url);
if(method != null){
obj.put("method", method);
}
sendUpdate(obj, true);
return true;
} catch (JSONException ex) {
LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
}
return false;
}


/**
* Legacy (deprecated in API 21)
* For Android 4.4 and below.
* @param view
* @param url
* @return
*/
@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {
return shouldInterceptRequest(url, super.shouldInterceptRequest(view, url), null);
}

/**
* New (added in API 21)
* For Android 5.0 and above.
*
* @param webView
* @param request
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return shouldInterceptRequest(request.getUrl().toString(), super.shouldInterceptRequest(view, request), request.getMethod());
}

public WebResourceResponse shouldInterceptRequest(String url, WebResourceResponse response, String method){
return response;
}

/*
* onPageStarted fires the LOAD_START_EVENT
Expand Down
2 changes: 1 addition & 1 deletion src/ios/CDVInAppBrowserOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
@property (nonatomic, assign) BOOL suppressesincrementalrendering;
@property (nonatomic, assign) BOOL hidden;
@property (nonatomic, assign) BOOL disallowoverscroll;
@property (nonatomic, assign) BOOL beforeload;
@property (nonatomic, copy) NSString* beforeload;

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

Expand Down
1 change: 1 addition & 0 deletions src/ios/CDVInAppBrowserOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ - (id)init
self.closebuttoncolor = nil;
self.toolbarcolor = nil;
self.toolbartranslucent = YES;
self.beforeload = @"";
}

return self;
Expand Down
2 changes: 1 addition & 1 deletion src/ios/CDVUIInAppBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
UIWindow * tmpWindow;

@private
BOOL _useBeforeload;
NSString* _beforeload;
BOOL _waitForBeforeload;
}

Expand Down
44 changes: 36 additions & 8 deletions src/ios/CDVUIInAppBrowser.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ - (void)pluginInitialize
instance = self;
_previousStatusBarStyle = -1;
_callbackIdPattern = nil;
_useBeforeload = NO;
_beforeload = @"";
_waitForBeforeload = NO;
}

Expand Down Expand Up @@ -219,8 +219,12 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
}

// use of beforeload event
_useBeforeload = browserOptions.beforeload;
_waitForBeforeload = browserOptions.beforeload;
if([browserOptions.beforeload isKindOfClass:[NSString class]]){
_beforeload = browserOptions.beforeload;
}else{
_beforeload = @"yes";
}
_waitForBeforeload = ![_beforeload isEqualToString:@""];

[self.inAppBrowserViewController navigateTo:url];
if (!browserOptions.hidden) {
Expand Down Expand Up @@ -320,7 +324,7 @@ - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
{
NSString* urlStr = [command argumentAtIndex:0];

if (!_useBeforeload) {
if ([_beforeload isEqualToString:@""]) {
NSLog(@"unexpected loadAfterBeforeload called without feature beforeload=yes");
}
if (self.inAppBrowserViewController == nil) {
Expand Down Expand Up @@ -447,6 +451,22 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
NSURL* url = request.URL;
BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
BOOL shouldStart = YES;
BOOL useBeforeLoad = NO;
NSString* httpMethod = request.HTTPMethod;
NSString* errorMessage = nil;

if([_beforeload isEqualToString:@"post"]){
//TODO handle POST requests by preserving POST data then remove this condition
errorMessage = @"beforeload doesn't yet support POST requests";
}
else if(isTopLevelNavigation && (
[_beforeload isEqualToString:@"yes"]
|| ([_beforeload isEqualToString:@"get"] && [httpMethod isEqualToString:@"GET"])
// TODO comment in when POST requests are handled
// || ([_beforeload isEqualToString:@"post"] && [httpMethod isEqualToString:@"POST"])
)){
useBeforeLoad = YES;
}

// See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
// and the path, if present, should be a JSON-encoded value to pass to the callback.
Expand Down Expand Up @@ -475,15 +495,23 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
}
}

// When beforeload=yes, on first URL change, initiate JS callback. Only after the beforeload event, continue.
if (_waitForBeforeload && isTopLevelNavigation) {
// When beforeload, on first URL change, initiate JS callback. Only after the beforeload event, continue.
if (_waitForBeforeload && useBeforeLoad) {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"type":@"beforeload", @"url":[url absoluteString]}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];

[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
return NO;
}

if(errorMessage != nil){
NSLog(errorMessage);
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
messageAsDictionary:@{@"type":@"loaderror", @"url":[url absoluteString], @"code": @"-1", @"message": errorMessage}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}

//if is an app store link, let the system handle it, otherwise it fails to load it
if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
Expand All @@ -500,7 +528,7 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}

if (_useBeforeload && isTopLevelNavigation) {
if (useBeforeLoad) {
_waitForBeforeload = YES;
}

Expand Down
2 changes: 1 addition & 1 deletion src/ios/CDVWKInAppBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

@interface CDVWKInAppBrowser : CDVPlugin {
@private
BOOL _useBeforeload;
NSString* _beforeload;
BOOL _waitForBeforeload;
}

Expand Down
Loading

0 comments on commit a6f2427

Please sign in to comment.