Skip to content

Commit 281a110

Browse files
committed
Adding custom header support, sourced from:
apache#363
1 parent 22739ba commit 281a110

File tree

5 files changed

+98
-23
lines changed

5 files changed

+98
-23
lines changed

README.md

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

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

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

@@ -133,6 +133,9 @@ instance, or the system browser.
133133
- __mediaPlaybackRequiresUserAction__: Set to `yes` to prevent HTML5 audio or video from autoplaying (defaults to `no`).
134134
- __shouldPauseOnSuspend__: Set to `yes` to make InAppBrowser WebView to pause/resume with the app to stop background audio (this may be required to avoid Google Play issues like described in [CB-11013](https://issues.apache.org/jira/browse/CB-11013)).
135135
- __useWideViewPort__: Sets whether the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. When the value of the setting is `no`, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. When the value is `yes` and the page contains the viewport meta tag, the value of the width specified in the tag is used. If the page does not contain the tag or does not provide a width, then a wide viewport will be used. (defaults to `yes`).
136+
- __headers__: Headers for the http request. Optional. _(String)_ or _(javascript object)_
137+
- _(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.
138+
- _(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.
136139

137140
iOS supports these additional options:
138141

@@ -156,6 +159,9 @@ instance, or the system browser.
156159
- __transitionstyle__: Set to `fliphorizontal`, `crossdissolve` or `coververtical` to set the [transition style](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/modalTransitionStyle) (defaults to `coververtical`).
157160
- __toolbarposition__: Set to `top` or `bottom` (default is `bottom`). Causes the toolbar to be at the top or bottom of the window.
158161
- __hidespinner__: Set to `yes` or `no` to change the visibility of the loading indicator (defaults to `no`).
162+
- __headers__: Headers for the http request. Optional. _(String)_ or _(javascript object)_
163+
- _(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.
164+
- _(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.
159165

160166
Windows supports these additional options:
161167

src/android/InAppBrowser.java

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public boolean execute(String action, CordovaArgs args, final CallbackContext ca
158158
}
159159
final String target = t;
160160
final HashMap<String, String> features = parseFeature(args.optString(2));
161+
final HashMap<String, String> headers = parseHeaders(args.optString(3));
161162

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

@@ -223,7 +224,7 @@ else if (url.startsWith(WebView.SCHEME_TEL))
223224
// load in InAppBrowser
224225
else {
225226
LOG.d(LOG_TAG, "loading in InAppBrowser");
226-
result = showWebPage(url, features);
227+
result = showWebPage(url, features, headers);
227228
}
228229
}
229230
// SYSTEM
@@ -234,7 +235,7 @@ else if (SYSTEM.equals(target)) {
234235
// BLANK - or anything else
235236
else {
236237
LOG.d(LOG_TAG, "in blank");
237-
result = showWebPage(url, features);
238+
result = showWebPage(url, features, headers);
238239
}
239240

240241
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
@@ -379,7 +380,7 @@ private void injectDeferredObject(String source, String jsWrapper) {
379380
public void run() {
380381
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
381382
// This action will have the side-effect of blurring the currently focused element
382-
inAppWebView.loadUrl("javascript:" + finalScriptToInject);
383+
inAppWebView.loadUrl("javascript:" + finalScriptToInject, null);
383384
} else {
384385
inAppWebView.evaluateJavascript(finalScriptToInject, null);
385386
}
@@ -418,6 +419,32 @@ private HashMap<String, String> parseFeature(String optString) {
418419
}
419420
}
420421

422+
/**
423+
* Put the headers string into a hash map
424+
*
425+
* @param headersString string of headers comma separated (key=value)
426+
* @return map of headers
427+
*/
428+
private HashMap<String, String> parseHeaders(String headersString) {
429+
if (headersString.equals(NULL)) {
430+
return null;
431+
}
432+
433+
HashMap<String, String> map = new HashMap<String, String>();
434+
StringTokenizer headers = new StringTokenizer(headersString, ",");
435+
StringTokenizer header;
436+
while(headers.hasMoreElements()) {
437+
header = new StringTokenizer(headers.nextToken(), "=");
438+
if (header.hasMoreElements()) {
439+
String key = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
440+
String value = header.nextToken().replace("@e","=").replace("@c", ",").replace("@a","@");
441+
map.put(key, value);
442+
}
443+
}
444+
445+
return map;
446+
}
447+
421448
/**
422449
* Display a new browser with the specified URL.
423450
*
@@ -465,19 +492,19 @@ public void run() {
465492
public void onPageFinished(WebView view, String url) {
466493
if (dialog != null) {
467494
try {
468-
dialog.dismiss();
495+
dialog.dismiss();
469496
} catch (IllegalArgumentException e) {
470497
LOG.d(LOG_TAG, "Exception dismissing window: " + e.getLocalizedMessage());
471498
}
472-
499+
473500
dialog = null;
474501
}
475502
}
476503
});
477504
// NB: From SDK 19: "If you call methods on WebView from any thread
478505
// other than your app's UI thread, it can cause unexpected results."
479506
// http://developer.android.com/guide/webapps/migrating.html#Threads
480-
childView.loadUrl("about:blank");
507+
childView.loadUrl("about:blank", null);
481508

482509
try {
483510
JSONObject obj = new JSONObject();
@@ -534,9 +561,9 @@ private void navigate(String url) {
534561
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
535562

536563
if (!url.startsWith("http") && !url.startsWith("file:")) {
537-
this.inAppWebView.loadUrl("http://" + url);
564+
this.inAppWebView.loadUrl("http://" + url, null);
538565
} else {
539-
this.inAppWebView.loadUrl(url);
566+
this.inAppWebView.loadUrl(url, null);
540567
}
541568
this.inAppWebView.requestFocus();
542569
}
@@ -561,7 +588,7 @@ private InAppBrowser getInAppBrowser(){
561588
* @param url the url to load.
562589
* @param features jsonObject
563590
*/
564-
public String showWebPage(final String url, HashMap<String, String> features) {
591+
public String showWebPage(final String url, HashMap<String, String> features, final HashMap<String, String> headers) {
565592
// Determine if we should hide the location bar.
566593
showLocationBar = true;
567594
enableZoomControls = true;
@@ -986,7 +1013,7 @@ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)
9861013
CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
9871014
}
9881015

989-
inAppWebView.loadUrl(url);
1016+
inAppWebView.loadUrl(url, headers);
9901017
inAppWebView.setId(Integer.valueOf(6));
9911018
inAppWebView.getSettings().setLoadWithOverviewMode(true);
9921019
inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);

src/ios/CDVInAppBrowser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
@property (nonatomic, assign) BOOL disallowoverscroll;
7373

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

7677
@end
7778

@@ -103,7 +104,7 @@
103104
@property (nonatomic) NSURL* currentURL;
104105

105106
- (void)close;
106-
- (void)navigateTo:(NSURL*)url;
107+
- (void)navigateTo:(NSURL*)url headers:(NSString *)headers;
107108
- (void)showLocationBar:(BOOL)show;
108109
- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
109110
- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString;

src/ios/CDVInAppBrowser.m

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
8484
NSString* url = [command argumentAtIndex:0];
8585
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
8686
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
87+
NSString* headers = [command argumentAtIndex:3 withDefault:@"" andClass:[NSString class]];
8788

8889
self.callbackId = command.callbackId;
8990

@@ -100,11 +101,11 @@ - (void)open:(CDVInvokedUrlCommand*)command
100101
}
101102

102103
if ([target isEqualToString:kInAppBrowserTargetSelf]) {
103-
[self openInCordovaWebView:absoluteUrl withOptions:options];
104+
[self openInCordovaWebView:absoluteUrl withOptions:options withHeaders:headers];
104105
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
105106
[self openInSystem:absoluteUrl];
106107
} else { // _blank or anything else
107-
[self openInInAppBrowser:absoluteUrl withOptions:options];
108+
[self openInInAppBrowser:absoluteUrl withOptions:options withHeaders:headers];
108109
}
109110

110111
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
@@ -116,7 +117,7 @@ - (void)open:(CDVInvokedUrlCommand*)command
116117
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
117118
}
118119

119-
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
120+
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
120121
{
121122
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
122123

@@ -209,7 +210,7 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
209210
self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
210211
}
211212

212-
[self.inAppBrowserViewController navigateTo:url];
213+
[self.inAppBrowserViewController navigateTo:url headers:headers];
213214
if (!browserOptions.hidden) {
214215
[self show:nil];
215216
}
@@ -279,9 +280,9 @@ - (void)hide:(CDVInvokedUrlCommand*)command
279280
});
280281
}
281282

282-
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
283+
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options withHeaders:(NSString*)headers
283284
{
284-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
285+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
285286

286287
#ifdef __CORDOVA_4_0_0
287288
// the webview engine itself will filter for this according to <allow-navigation> policy
@@ -291,7 +292,7 @@ - (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
291292
if ([self.commandDelegate URLIsWhitelisted:url]) {
292293
[self.webView loadRequest:request];
293294
} else { // this assumes the InAppBrowser can be excepted from the white-list
294-
[self openInInAppBrowser:url withOptions:options];
295+
[self openInInAppBrowser:url withOptions:options withHeaders:headers];
295296
}
296297
#endif
297298
}
@@ -894,9 +895,9 @@ - (void)close
894895
});
895896
}
896897

897-
- (void)navigateTo:(NSURL*)url
898+
- (void)navigateTo:(NSURL*)url headers:(NSString*)headers
898899
{
899-
NSURLRequest* request = [NSURLRequest requestWithURL:url];
900+
NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers];
900901

901902
if (_userAgentLockToken != 0) {
902903
[self.webView loadRequest:request];
@@ -1127,6 +1128,24 @@ + (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
11271128
return obj;
11281129
}
11291130

1131+
+ (NSMutableURLRequest*)createRequest:(NSURL*)url headers:(NSString*)headers
1132+
{
1133+
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
1134+
if (headers != nil) {
1135+
NSArray* pairs = [headers componentsSeparatedByString:@","];
1136+
for (NSString* pair in pairs) {
1137+
NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
1138+
1139+
if ([keyvalue count] == 2) {
1140+
NSString* key = [[[[keyvalue objectAtIndex:0] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
1141+
NSString* value = [[[[keyvalue objectAtIndex:1] stringByReplacingOccurrencesOfString:@"@e" withString:@"="] stringByReplacingOccurrencesOfString:@"@c" withString:@","] stringByReplacingOccurrencesOfString:@"@a" withString:@"@"];
1142+
[request setValue:value forHTTPHeaderField:key];
1143+
}
1144+
}
1145+
}
1146+
return request;
1147+
}
1148+
11301149
@end
11311150

11321151
@implementation CDVInAppBrowserNavigationController : UINavigationController

www/inappbrowser.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
}
8989
};
9090

91-
module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
91+
module.exports = function (strUrl, strWindowName, strWindowFeatures, windowHeaders, callbacks) {
9292
// Don't catch calls that write to existing frames (e.g. named iframes).
9393
if (window.frames && window.frames[strWindowName]) {
9494
var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
@@ -107,9 +107,31 @@
107107
iab._eventHandler(eventname);
108108
};
109109

110+
var strWindowHeaders = '';
111+
112+
if (windowHeaders) {
113+
if (typeof windowHeaders === 'string' || windowHeaders instanceof String) {
114+
strWindowHeaders = windowHeaders.replace(/@/gi, '@a');
115+
} else {
116+
var first = true;
117+
for (var k in windowHeaders) {
118+
if (windowHeaders.hasOwnProperty(k)) {
119+
var key = k.replace(/@/gi, '@a').replace(/,/gi, '@c').replace(/=/gi, '@e');
120+
var value = windowHeaders[k].toString().replace(/@/gi, '@a').replace(/,/gi, '@c').replace(/=/gi, '@e');
121+
if (first) {
122+
first = false;
123+
} else {
124+
strWindowHeaders += ',';
125+
}
126+
strWindowHeaders += key + '=' + value;
127+
}
128+
}
129+
}
130+
}
131+
110132
strWindowFeatures = strWindowFeatures || '';
111133

112-
exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
134+
exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures, strWindowHeaders]);
113135
return iab;
114136
};
115137
})();

0 commit comments

Comments
 (0)