Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(android,ios): add request headers support #363

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ simply hook `window.open` during initialization. For example:
Opens a URL in a new `InAppBrowser` instance, the current browser
instance, or the system browser.

var ref = cordova.InAppBrowser.open(url, target, options);
var ref = cordova.InAppBrowser.open(url, target, options, headers);

- __ref__: Reference to the `InAppBrowser` window when the target is set to `'_blank'`. _(InAppBrowser)_

Expand Down Expand Up @@ -162,6 +162,9 @@ instance, or the system browser.
- __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.

- __headers__: Headers for the http request. Optional. _(String)_ or _(javascript object)_
- _(String)_: headers must be in `header=value` form, separated by commas : `header1=value1,header2=value2`. don't use _(String)_ if commas or equals can be contained in headers or values.
- _(javascript object)_: headers are stored in object's properties like this `{ 'header1': 'value1', 'header2': 'value2'}`. this storage always works even if headers contain commas or equals.

### Supported Platforms

Expand Down
45 changes: 36 additions & 9 deletions src/android/InAppBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ public boolean execute(String action, CordovaArgs args, final CallbackContext ca
}
final String target = t;
final HashMap<String, String> features = parseFeature(args.optString(2));
final HashMap<String, String> headers = parseHeaders(args.optString(3));

LOG.d(LOG_TAG, "target = " + target);

Expand Down Expand Up @@ -233,7 +234,7 @@ else if (url.startsWith(WebView.SCHEME_TEL))
// load in InAppBrowser
else {
LOG.d(LOG_TAG, "loading in InAppBrowser");
result = showWebPage(url, features);
result = showWebPage(url, features, headers);
}
}
// SYSTEM
Expand All @@ -244,7 +245,7 @@ else if (SYSTEM.equals(target)) {
// BLANK - or anything else
else {
LOG.d(LOG_TAG, "in blank");
result = showWebPage(url, features);
result = showWebPage(url, features, headers);
}

PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
Expand All @@ -271,7 +272,7 @@ public void run() {
} else {
((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload = false;
}
inAppWebView.loadUrl(url);
inAppWebView.loadUrl(url, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why all those changes to the loadUrl calls if we don't actually change the method signature ourselves? Couldn't we just keep these as they are and only add the headers in the places where we need it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this was to explicitely mark headers were null for easier code navigation

}
});
}
Expand Down Expand Up @@ -408,7 +409,7 @@ private void injectDeferredObject(String source, String jsWrapper) {
public void run() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
// This action will have the side-effect of blurring the currently focused element
inAppWebView.loadUrl("javascript:" + finalScriptToInject);
inAppWebView.loadUrl("javascript:" + finalScriptToInject, null);
} else {
inAppWebView.evaluateJavascript(finalScriptToInject, null);
}
Expand Down Expand Up @@ -447,6 +448,31 @@ private HashMap<String, String> parseFeature(String optString) {
}
}

/**
* Put the headers string into a hash map
*
* @param headersString string of headers comma separated (key=value)
* @return map of headers
*/
private HashMap<String, String> parseHeaders(String headersString) {
if (headersString.equals(NULL)) {
return null;
} else {
HashMap<String, String> map = new HashMap<String, String>();
StringTokenizer headers = new StringTokenizer(headersString, ",");
StringTokenizer header;
while(headers.hasMoreElements()) {
header = new StringTokenizer(headers.nextToken(), "=");
if (header.hasMoreElements()) {
String key = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
String value = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
map.put(key, value);
}
}
return map;
}
}

/**
* Display a new browser with the specified URL.
*
Expand Down Expand Up @@ -542,7 +568,7 @@ public void onPageFinished(WebView view, String url) {
// NB: From SDK 19: "If you call methods on WebView from any thread
// other than your app's UI thread, it can cause unexpected results."
// http://developer.android.com/guide/webapps/migrating.html#Threads
childView.loadUrl("about:blank");
childView.loadUrl("about:blank", null);

try {
JSONObject obj = new JSONObject();
Expand Down Expand Up @@ -599,9 +625,9 @@ private void navigate(String url) {
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);

if (!url.startsWith("http") && !url.startsWith("file:")) {
this.inAppWebView.loadUrl("http://" + url);
this.inAppWebView.loadUrl("http://" + url, null);
} else {
this.inAppWebView.loadUrl(url);
this.inAppWebView.loadUrl(url, null);
}
this.inAppWebView.requestFocus();
}
Expand All @@ -625,8 +651,9 @@ private InAppBrowser getInAppBrowser(){
*
* @param url the url to load.
* @param features jsonObject
* @param headers headers for navigation
*/
public String showWebPage(final String url, HashMap<String, String> features) {
public String showWebPage(final String url, HashMap<String, String> features, final HashMap<String, String> headers) {
// Determine if we should hide the location bar.
showLocationBar = true;
showZoomControls = true;
Expand Down Expand Up @@ -1029,7 +1056,7 @@ public void postMessage(String data) {
CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
}

inAppWebView.loadUrl(url);
inAppWebView.loadUrl(url, headers);
inAppWebView.setId(Integer.valueOf(6));
inAppWebView.getSettings().setLoadWithOverviewMode(true);
inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);
Expand Down
1 change: 1 addition & 0 deletions src/ios/CDVInAppBrowserOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@
@property (nonatomic, copy) NSString* beforeload;

+ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
+ (NSMutableURLRequest*)createRequest:(NSURL*)url headers:(NSString*)headers;

@end
18 changes: 18 additions & 0 deletions src/ios/CDVInAppBrowserOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,22 @@ + (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
return obj;
}

+ (NSMutableURLRequest*)createRequest:(NSURL*)url headers:(NSString*)headers
{
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
if (headers != nil) {
NSArray* pairs = [headers componentsSeparatedByString:@","];
for (NSString* pair in pairs) {
NSArray* keyvalue = [pair componentsSeparatedByString:@"="];

if ([keyvalue count] == 2) {
NSString* key = [[[[keyvalue objectAtIndex:0] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
NSString* value = [[[[keyvalue objectAtIndex:1] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
[request setValue:value forHTTPHeaderField:key];
}
}
}
return request;
}

@end
2 changes: 1 addition & 1 deletion src/ios/CDVUIInAppBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
@property (nonatomic) NSURL* currentURL;

- (void)close;
- (void)navigateTo:(NSURL*)url;
- (void)navigateTo:(NSURL*)url headers:(NSString *)headers;
- (void)showLocationBar:(BOOL)show;
- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString : (int) buttonIndex;
Expand Down
19 changes: 10 additions & 9 deletions src/ios/CDVUIInAppBrowser.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
NSString* headers = [command argumentAtIndex:3 withDefault:@"" andClass:[NSString class]];

self.callbackId = command.callbackId;

Expand All @@ -109,11 +110,11 @@ - (void)open:(CDVInvokedUrlCommand*)command
}

if ([target isEqualToString:kInAppBrowserTargetSelf]) {
[self openInCordovaWebView:absoluteUrl withOptions:options];
[self openInCordovaWebView:absoluteUrl withOptions:options withHeaders:headers];
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
[self openInSystem:absoluteUrl];
} else { // _blank or anything else
[self openInInAppBrowser:absoluteUrl withOptions:options];
[self openInInAppBrowser:absoluteUrl withOptions:options withHeaders:headers];
}

pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
Expand All @@ -125,7 +126,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
{
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];

Expand Down Expand Up @@ -227,7 +228,7 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
}
_waitForBeforeload = ![_beforeload isEqualToString:@""];

[self.inAppBrowserViewController navigateTo:url];
[self.inAppBrowserViewController navigateTo:url headers:headers];
if (!browserOptions.hidden) {
[self show:nil];
}
Expand Down Expand Up @@ -296,9 +297,9 @@ - (void)hide:(CDVInvokedUrlCommand*)command
});
}

- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];

#ifdef __CORDOVA_4_0_0
// the webview engine itself will filter for this according to <allow-navigation> policy
Expand Down Expand Up @@ -339,7 +340,7 @@ - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command

NSURL* url = [NSURL URLWithString:urlStr];
_waitForBeforeload = NO;
[self.inAppBrowserViewController navigateTo:url];
[self.inAppBrowserViewController navigateTo:url headers:nil];
}

-(void)createIframeBridge
Expand Down Expand Up @@ -960,9 +961,9 @@ - (void)close
});
}

- (void)navigateTo:(NSURL*)url
- (void)navigateTo:(NSURL*)url headers:(NSString*)headers
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];

if (_userAgentLockToken != 0) {
[self.webView loadRequest:request];
Expand Down
2 changes: 1 addition & 1 deletion src/ios/CDVWKInAppBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
@property (nonatomic) NSURL* currentURL;

- (void)close;
- (void)navigateTo:(NSURL*)url;
- (void)navigateTo:(NSURL*)url headers:(NSString *)headers;
- (void)showLocationBar:(BOOL)show;
- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString : (int) buttonIndex;
Expand Down
21 changes: 11 additions & 10 deletions src/ios/CDVWKInAppBrowser.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
NSString* headers = [command argumentAtIndex:3 withDefault:@"" andClass:[NSString class]];

self.callbackId = command.callbackId;

Expand All @@ -116,11 +117,11 @@ - (void)open:(CDVInvokedUrlCommand*)command
}

if ([target isEqualToString:kInAppBrowserTargetSelf]) {
[self openInCordovaWebView:absoluteUrl withOptions:options];
[self openInCordovaWebView:absoluteUrl withOptions:options withHeaders:headers];
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
[self openInSystem:absoluteUrl];
} else { // _blank or anything else
[self openInInAppBrowser:absoluteUrl withOptions:options];
[self openInInAppBrowser:absoluteUrl withOptions:options withHeaders:headers];
}

pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
Expand All @@ -132,7 +133,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
{
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];

Expand Down Expand Up @@ -274,7 +275,7 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
}
_waitForBeforeload = ![_beforeload isEqualToString:@""];

[self.inAppBrowserViewController navigateTo:url];
[self.inAppBrowserViewController navigateTo:url headers:headers];
[self show:nil withNoAnimate:browserOptions.hidden];
}

Expand Down Expand Up @@ -357,9 +358,9 @@ - (void)hide:(CDVInvokedUrlCommand*)command
});
}

- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];

#ifdef __CORDOVA_4_0_0
// the webview engine itself will filter for this according to <allow-navigation> policy
Expand All @@ -369,7 +370,7 @@ - (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
if ([self.commandDelegate URLIsWhitelisted:url]) {
[self.webView loadRequest:request];
} else { // this assumes the InAppBrowser can be excepted from the white-list
[self openInInAppBrowser:url withOptions:options];
[self openInInAppBrowser:url withOptions:options withHeaders:headers];
}
#endif
}
Expand Down Expand Up @@ -399,7 +400,7 @@ - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
NSURL* url = [NSURL URLWithString:urlStr];
//_beforeload = @"";
_waitForBeforeload = NO;
[self.inAppBrowserViewController navigateTo:url];
[self.inAppBrowserViewController navigateTo:url headers:nil];
}

// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
Expand Down Expand Up @@ -1077,9 +1078,9 @@ - (void)close
});
}

- (void)navigateTo:(NSURL*)url
- (void)navigateTo:(NSURL*)url headers:(NSString*)headers
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];

if (_userAgentLockToken != 0) {
[self.webView loadRequest:request];
Expand Down
25 changes: 22 additions & 3 deletions www/inappbrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
}
};

module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
module.exports = function (strUrl, strWindowName, strWindowFeatures, windowHeaders, callbacks) {
// Don't catch calls that write to existing frames (e.g. named iframes).
if (window.frames && window.frames[strWindowName]) {
var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
Expand All @@ -116,10 +116,29 @@
var cb = function (eventname) {
iab._eventHandler(eventname);
};

var strWindowHeaders = '';
if (windowHeaders) {
if (typeof windowHeaders === 'string' || windowHeaders instanceof String) {
strWindowHeaders = windowHeaders.replace(/@/gi, '@a');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what exactly is the reason for all the replacements of @ and = if you just re-replace it in the corresponding Java/Objective-C code?

Wouldn't it be more readable and clearer to pass in a JSON object and then use Android's included JSONObject support to create a HashMap and iOS' included NSJSONSerialization?

} else {
var first = true;
for (var k in windowHeaders) {
if (windowHeaders.hasOwnProperty(k)) {
var key = k.replace(/@/gi, '@a').replace(/,/gi, '@c').replace(/=/gi, '@e');
var value = windowHeaders[k].toString().replace(/@/gi, '@a').replace(/,/gi, '@c').replace(/=/gi, '@e');
if (first) {
first = false;
} else {
strWindowHeaders += ',';
}
strWindowHeaders += key + '=' + value;
}
}
}
}
strWindowFeatures = strWindowFeatures || '';

exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures, strWindowHeaders]);
return iab;
};
})();