diff --git a/README.md b/README.md index dd89053..5ac4996 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,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)_ @@ -155,6 +155,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 diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java index 76dc150..2b28a48 100644 --- a/src/android/InAppBrowser.java +++ b/src/android/InAppBrowser.java @@ -168,6 +168,7 @@ public class InAppBrowser extends CordovaPlugin { } final String target = t; final HashMap features = parseFeature(args.optString(2)); + final HashMap headers = parseHeaders(args.optString(3)); LOG.d(LOG_TAG, "target = " + target); @@ -233,7 +234,7 @@ public class InAppBrowser extends CordovaPlugin { // load in InAppBrowser else { LOG.d(LOG_TAG, "loading in InAppBrowser"); - result = showWebPage(url, features); + result = showWebPage(url, features, headers); } } // SYSTEM @@ -244,7 +245,7 @@ public class InAppBrowser extends CordovaPlugin { // 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); @@ -271,7 +272,7 @@ public class InAppBrowser extends CordovaPlugin { } else { ((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload = false; } - inAppWebView.loadUrl(url); + inAppWebView.loadUrl(url, null); } }); } @@ -446,6 +447,31 @@ public class InAppBrowser extends CordovaPlugin { } } + /** + * Put the headers string into a hash map + * + * @param headersString string of headers comma separated (key=value) + * @return map of headers + */ + private HashMap parseHeaders(String headersString) { + if (headersString.equals(NULL)) { + return null; + } else { + HashMap map = new HashMap(); + 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. * @@ -541,7 +567,7 @@ public class InAppBrowser extends CordovaPlugin { // 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(); @@ -598,9 +624,9 @@ public class InAppBrowser extends CordovaPlugin { 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(); } @@ -624,8 +650,9 @@ public class InAppBrowser extends CordovaPlugin { * * @param url the url to load. * @param features jsonObject + * @param headers headers for navigation */ - public String showWebPage(final String url, HashMap features) { + public String showWebPage(final String url, HashMap features, final HashMap headers) { // Determine if we should hide the location bar. showLocationBar = true; showZoomControls = true; @@ -994,7 +1021,7 @@ public class InAppBrowser extends CordovaPlugin { // Enable Thirdparty Cookies 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); diff --git a/src/ios/CDVInAppBrowserOptions.h b/src/ios/CDVInAppBrowserOptions.h index c1c9fa5..b66c3ea 100644 --- a/src/ios/CDVInAppBrowserOptions.h +++ b/src/ios/CDVInAppBrowserOptions.h @@ -46,5 +46,6 @@ @property (nonatomic, copy) NSString* beforeload; + (CDVInAppBrowserOptions*)parseOptions:(NSString*)options; ++ (NSMutableURLRequest*)createRequest:(NSURL*)url headers:(NSString*)headers; @end diff --git a/src/ios/CDVInAppBrowserOptions.m b/src/ios/CDVInAppBrowserOptions.m index e20d1a8..ab15066 100644 --- a/src/ios/CDVInAppBrowserOptions.m +++ b/src/ios/CDVInAppBrowserOptions.m @@ -87,4 +87,22 @@ 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 diff --git a/src/ios/CDVWKInAppBrowser.h b/src/ios/CDVWKInAppBrowser.h index 2f650b8..da8ffdc 100644 --- a/src/ios/CDVWKInAppBrowser.h +++ b/src/ios/CDVWKInAppBrowser.h @@ -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; diff --git a/src/ios/CDVWKInAppBrowser.m b/src/ios/CDVWKInAppBrowser.m index 2adcf0c..e365f86 100644 --- a/src/ios/CDVWKInAppBrowser.m +++ b/src/ios/CDVWKInAppBrowser.m @@ -96,6 +96,7 @@ static CDVWKInAppBrowser* instance = nil; 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; @@ -108,11 +109,11 @@ static CDVWKInAppBrowser* instance = nil; } 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]; @@ -124,7 +125,7 @@ static CDVWKInAppBrowser* instance = nil; [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]; @@ -257,7 +258,7 @@ static CDVWKInAppBrowser* instance = nil; } _waitForBeforeload = ![_beforeload isEqualToString:@""]; - [self.inAppBrowserViewController navigateTo:url]; + [self.inAppBrowserViewController navigateTo:url headers:headers]; if (!browserOptions.hidden) { [self show:nil withNoAnimate:browserOptions.hidden]; } @@ -349,9 +350,9 @@ static CDVWKInAppBrowser* instance = nil; }); } -- (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]; // the webview engine itself will filter for this according to policy // in config.xml for cordova-ios-4.0 [self.webViewEngine loadRequest:request]; @@ -384,7 +385,7 @@ static CDVWKInAppBrowser* instance = nil; 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 @@ -1105,12 +1106,13 @@ BOOL isExiting = FALSE; }); } -- (void)navigateTo:(NSURL*)url +- (void)navigateTo:(NSURL*)url headers:(NSString*)headers { if ([url.scheme isEqualToString:@"file"]) { [self.webView loadFileURL:url allowingReadAccessToURL:url]; } else { - NSURLRequest* request = [NSURLRequest requestWithURL:url]; + NSMutableURLRequest* request = [CDVInAppBrowserOptions createRequest:url headers:headers]; + // NSURLRequest* request = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:request]; } } diff --git a/www/inappbrowser.js b/www/inappbrowser.js index 3dcab21..e5c7d5d 100644 --- a/www/inappbrowser.js +++ b/www/inappbrowser.js @@ -92,7 +92,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'); @@ -110,10 +110,29 @@ var cb = function (eventname) { iab._eventHandler(eventname); }; - + var strWindowHeaders = ''; + if (windowHeaders) { + if (typeof windowHeaders === 'string' || windowHeaders instanceof String) { + strWindowHeaders = windowHeaders.replace(/@/gi, '@a'); + } 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; }; })();