Skip to content

Commit 0e2b00a

Browse files
committed
(issue-#361) (iOS & Android) add request headers support
1 parent 0fd43ae commit 0e2b00a

9 files changed

+105
-34
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ simply hook `window.open` during initialization. For example:
8383
Opens a URL in a new `InAppBrowser` instance, the current browser
8484
instance, or the system browser.
8585

86-
var ref = cordova.InAppBrowser.open(url, target, options);
86+
var ref = cordova.InAppBrowser.open(url, target, options, headers);
8787

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

@@ -158,6 +158,9 @@ instance, or the system browser.
158158
- __hardwareback__: works the same way as on Android platform.
159159
- __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.
160160

161+
- __headers__: Headers for the http request. Optional. _(String)_ or _(javascript object)_
162+
- _(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.
163+
- _(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.
161164

162165
### Supported Platforms
163166

src/android/InAppBrowser.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public boolean execute(String action, CordovaArgs args, final CallbackContext ca
160160
}
161161
final String target = t;
162162
final HashMap<String, String> features = parseFeature(args.optString(2));
163+
final HashMap<String, String> headers = parseHeaders(args.optString(3));
163164

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

@@ -225,7 +226,7 @@ else if (url.startsWith(WebView.SCHEME_TEL))
225226
// load in InAppBrowser
226227
else {
227228
LOG.d(LOG_TAG, "loading in InAppBrowser");
228-
result = showWebPage(url, features);
229+
result = showWebPage(url, features, headers);
229230
}
230231
}
231232
// SYSTEM
@@ -236,7 +237,7 @@ else if (SYSTEM.equals(target)) {
236237
// BLANK - or anything else
237238
else {
238239
LOG.d(LOG_TAG, "in blank");
239-
result = showWebPage(url, features);
240+
result = showWebPage(url, features, headers);
240241
}
241242

242243
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
@@ -258,7 +259,7 @@ else if (action.equals("loadAfterBeforeload")) {
258259
@Override
259260
public void run() {
260261
((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload = false;
261-
inAppWebView.loadUrl(url);
262+
inAppWebView.loadUrl(url, null);
262263
}
263264
});
264265
}
@@ -395,7 +396,7 @@ private void injectDeferredObject(String source, String jsWrapper) {
395396
public void run() {
396397
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
397398
// This action will have the side-effect of blurring the currently focused element
398-
inAppWebView.loadUrl("javascript:" + finalScriptToInject);
399+
inAppWebView.loadUrl("javascript:" + finalScriptToInject, null);
399400
} else {
400401
inAppWebView.evaluateJavascript(finalScriptToInject, null);
401402
}
@@ -434,6 +435,31 @@ private HashMap<String, String> parseFeature(String optString) {
434435
}
435436
}
436437

438+
/**
439+
* Put the headers string into a hash map
440+
*
441+
* @param headersString string of headers comma separated (key=value)
442+
* @return map of headers
443+
*/
444+
private HashMap<String, String> parseHeaders(String headersString) {
445+
if (headersString.equals(NULL)) {
446+
return null;
447+
} else {
448+
HashMap<String, String> map = new HashMap<String, String>();
449+
StringTokenizer headers = new StringTokenizer(headersString, ",");
450+
StringTokenizer header;
451+
while(headers.hasMoreElements()) {
452+
header = new StringTokenizer(headers.nextToken(), "=");
453+
if (header.hasMoreElements()) {
454+
String key = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
455+
String value = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
456+
map.put(key, value);
457+
}
458+
}
459+
return map;
460+
}
461+
}
462+
437463
/**
438464
* Display a new browser with the specified URL.
439465
*
@@ -529,7 +555,7 @@ public void onPageFinished(WebView view, String url) {
529555
// NB: From SDK 19: "If you call methods on WebView from any thread
530556
// other than your app's UI thread, it can cause unexpected results."
531557
// http://developer.android.com/guide/webapps/migrating.html#Threads
532-
childView.loadUrl("about:blank");
558+
childView.loadUrl("about:blank", null);
533559

534560
try {
535561
JSONObject obj = new JSONObject();
@@ -586,9 +612,9 @@ private void navigate(String url) {
586612
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
587613

588614
if (!url.startsWith("http") && !url.startsWith("file:")) {
589-
this.inAppWebView.loadUrl("http://" + url);
615+
this.inAppWebView.loadUrl("http://" + url, null);
590616
} else {
591-
this.inAppWebView.loadUrl(url);
617+
this.inAppWebView.loadUrl(url, null);
592618
}
593619
this.inAppWebView.requestFocus();
594620
}
@@ -612,8 +638,9 @@ private InAppBrowser getInAppBrowser(){
612638
*
613639
* @param url the url to load.
614640
* @param features jsonObject
641+
* @param headers headers for navigation
615642
*/
616-
public String showWebPage(final String url, HashMap<String, String> features) {
643+
public String showWebPage(final String url, HashMap<String, String> features, final HashMap<String, String> headers) {
617644
// Determine if we should hide the location bar.
618645
showLocationBar = true;
619646
showZoomControls = true;
@@ -987,7 +1014,7 @@ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)
9871014
CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
9881015
}
9891016

990-
inAppWebView.loadUrl(url);
1017+
inAppWebView.loadUrl(url, headers);
9911018
inAppWebView.setId(Integer.valueOf(6));
9921019
inAppWebView.getSettings().setLoadWithOverviewMode(true);
9931020
inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);

src/ios/CDVInAppBrowserOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@
4848
@property (nonatomic, assign) BOOL beforeload;
4949

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

5253
@end

src/ios/CDVInAppBrowserOptions.m

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,22 @@ + (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
8888
return obj;
8989
}
9090

91+
+ (NSMutableURLRequest*)createRequest:(NSURL*)url headers:(NSString*)headers
92+
{
93+
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
94+
if (headers != nil) {
95+
NSArray* pairs = [headers componentsSeparatedByString:@","];
96+
for (NSString* pair in pairs) {
97+
NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
98+
99+
if ([keyvalue count] == 2) {
100+
NSString* key = [[[[keyvalue objectAtIndex:0] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
101+
NSString* value = [[[[keyvalue objectAtIndex:1] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
102+
[request setValue:value forHTTPHeaderField:key];
103+
}
104+
}
105+
}
106+
return request;
107+
}
108+
91109
@end

src/ios/CDVUIInAppBrowser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
@property (nonatomic) NSURL* currentURL;
8282

8383
- (void)close;
84-
- (void)navigateTo:(NSURL*)url;
84+
- (void)navigateTo:(NSURL*)url headers:(NSString *)headers;
8585
- (void)showLocationBar:(BOOL)show;
8686
- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
8787
- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString;

src/ios/CDVUIInAppBrowser.m

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
9393
NSString* url = [command argumentAtIndex:0];
9494
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
9595
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
96+
NSString* headers = [command argumentAtIndex:3 withDefault:@"" andClass:[NSString class]];
9697

9798
self.callbackId = command.callbackId;
9899

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

111112
if ([target isEqualToString:kInAppBrowserTargetSelf]) {
112-
[self openInCordovaWebView:absoluteUrl withOptions:options];
113+
[self openInCordovaWebView:absoluteUrl withOptions:options withHeaders:headers];
113114
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
114115
[self openInSystem:absoluteUrl];
115116
} else { // _blank or anything else
116-
[self openInInAppBrowser:absoluteUrl withOptions:options];
117+
[self openInInAppBrowser:absoluteUrl withOptions:options withHeaders:headers];
117118
}
118119

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

128-
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
129+
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
129130
{
130131
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
131132

@@ -222,7 +223,7 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
222223
_useBeforeload = browserOptions.beforeload;
223224
_waitForBeforeload = browserOptions.beforeload;
224225

225-
[self.inAppBrowserViewController navigateTo:url];
226+
[self.inAppBrowserViewController navigateTo:url headers:headers];
226227
if (!browserOptions.hidden) {
227228
[self show:nil];
228229
}
@@ -291,9 +292,9 @@ - (void)hide:(CDVInvokedUrlCommand*)command
291292
});
292293
}
293294

294-
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
295+
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
295296
{
296-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
297+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
297298

298299
#ifdef __CORDOVA_4_0_0
299300
// the webview engine itself will filter for this according to <allow-navigation> policy
@@ -334,7 +335,7 @@ - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
334335

335336
NSURL* url = [NSURL URLWithString:urlStr];
336337
_waitForBeforeload = NO;
337-
[self.inAppBrowserViewController navigateTo:url];
338+
[self.inAppBrowserViewController navigateTo:url headers:nil];
338339
}
339340

340341
// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
@@ -901,9 +902,9 @@ - (void)close
901902
});
902903
}
903904

904-
- (void)navigateTo:(NSURL*)url
905+
- (void)navigateTo:(NSURL*)url headers:(NSString*)headers
905906
{
906-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
907+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
907908

908909
if (_userAgentLockToken != 0) {
909910
[self.webView loadRequest:request];

src/ios/CDVWKInAppBrowser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
@property (nonatomic) NSURL* currentURL;
7171

7272
- (void)close;
73-
- (void)navigateTo:(NSURL*)url;
73+
- (void)navigateTo:(NSURL*)url headers:(NSString *)headers;
7474
- (void)showLocationBar:(BOOL)show;
7575
- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
7676
- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString;

src/ios/CDVWKInAppBrowser.m

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
100100
NSString* url = [command argumentAtIndex:0];
101101
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
102102
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
103+
NSString* headers = [command argumentAtIndex:3 withDefault:@"" andClass:[NSString class]];
103104

104105
self.callbackId = command.callbackId;
105106

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

118119
if ([target isEqualToString:kInAppBrowserTargetSelf]) {
119-
[self openInCordovaWebView:absoluteUrl withOptions:options];
120+
[self openInCordovaWebView:absoluteUrl withOptions:options withHeaders:headers];
120121
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
121122
[self openInSystem:absoluteUrl];
122123
} else { // _blank or anything else
123-
[self openInInAppBrowser:absoluteUrl withOptions:options];
124+
[self openInInAppBrowser:absoluteUrl withOptions:options withHeaders:headers];
124125
}
125126

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

135-
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
136+
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
136137
{
137138
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
138139

@@ -269,7 +270,7 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
269270
_useBeforeload = browserOptions.beforeload;
270271
_waitForBeforeload = browserOptions.beforeload;
271272

272-
[self.inAppBrowserViewController navigateTo:url];
273+
[self.inAppBrowserViewController navigateTo:url headers:headers];
273274
[self show:nil withNoAnimate:browserOptions.hidden];
274275
}
275276

@@ -352,9 +353,9 @@ - (void)hide:(CDVInvokedUrlCommand*)command
352353
});
353354
}
354355

355-
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
356+
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
356357
{
357-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
358+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
358359

359360
#ifdef __CORDOVA_4_0_0
360361
// the webview engine itself will filter for this according to <allow-navigation> policy
@@ -364,7 +365,7 @@ - (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
364365
if ([self.commandDelegate URLIsWhitelisted:url]) {
365366
[self.webView loadRequest:request];
366367
} else { // this assumes the InAppBrowser can be excepted from the white-list
367-
[self openInInAppBrowser:url withOptions:options];
368+
[self openInInAppBrowser:url withOptions:options withHeaders:headers];
368369
}
369370
#endif
370371
}
@@ -393,7 +394,7 @@ - (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
393394

394395
NSURL* url = [NSURL URLWithString:urlStr];
395396
_waitForBeforeload = NO;
396-
[self.inAppBrowserViewController navigateTo:url];
397+
[self.inAppBrowserViewController navigateTo:url headers:nil];
397398
}
398399

399400
// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
@@ -1020,9 +1021,9 @@ - (void)close
10201021
});
10211022
}
10221023

1023-
- (void)navigateTo:(NSURL*)url
1024+
- (void)navigateTo:(NSURL*)url headers:(NSString*)headers
10241025
{
1025-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
1026+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
10261027

10271028
if (_userAgentLockToken != 0) {
10281029
[self.webView loadRequest:request];

www/inappbrowser.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
}
9898
};
9999

100-
module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
100+
module.exports = function (strUrl, strWindowName, strWindowFeatures, windowHeaders, callbacks) {
101101
// Don't catch calls that write to existing frames (e.g. named iframes).
102102
if (window.frames && window.frames[strWindowName]) {
103103
var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
@@ -115,10 +115,30 @@
115115
var cb = function (eventname) {
116116
iab._eventHandler(eventname);
117117
};
118-
118+
var strWindowHeaders = '';
119+
if (windowHeaders) {
120+
if (typeof windowHeaders === 'string' || windowHeaders instanceof String) {
121+
strWindowHeaders = windowHeaders.replace(/@/gi,'@a');
122+
}
123+
else {
124+
var first = true;
125+
for (var k in windowHeaders) {
126+
if (windowHeaders.hasOwnProperty(k)) {
127+
var key = k.replace(/@/gi,'@a').replace(/,/gi,'@c').replace(/=/gi,'@e');
128+
var value = windowHeaders[k].toString().replace(/@/gi,'@a').replace(/,/gi,'@c').replace(/=/gi,'@e');
129+
if (first) {
130+
first = false;
131+
} else {
132+
strWindowHeaders += ",";
133+
}
134+
strWindowHeaders += key + "=" + value;
135+
}
136+
}
137+
}
138+
}
119139
strWindowFeatures = strWindowFeatures || '';
120140

121-
exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
141+
exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures, strWindowHeaders]);
122142
return iab;
123143
};
124144
})();

0 commit comments

Comments
 (0)