Skip to content
This repository has been archived by the owner on Oct 1, 2018. It is now read-only.

Commit

Permalink
Allow adding headers to the url session
Browse files Browse the repository at this point in the history
  • Loading branch information
davidovich committed Dec 2, 2015
1 parent bac5667 commit a5b557b
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 13 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ When you publish your application on the store - you pack in it all your web con
1. Publish new version of the app on the store. But it takes time, especially with the App Store.
2. Sacrifice the offline feature and load all the pages online. But as soon as Internet connection goes down - application won't work.

This plugin is intended to fix all that. When user starts the app for the first time - it copies all the web files onto the external storage. From this moment all pages are loaded from the external folder and not from the packed bundle. On every launch plugin connects to your server and checks if the new version of web project is available for download. If so - it loads it on the device and installs on the next launch.
This plugin is intended to fix all that. When user starts the app for the first time - it copies all the web files onto the external storage. From this moment all pages are loaded from the external folder and not from the packed bundle. On every launch plugin connects to your server (with optional authentication, see fetchUpdate() below) and checks if the new version of web project is available for download. If so - it loads it on the device and installs on the next launch.

As a result, your application receives updates of the web content as soon as possible, and still can work in offline mode. Also, plugin allows you to specify dependency between the web release and the native version to make sure, that new release will work on the older versions of the application.

Expand Down Expand Up @@ -307,6 +307,8 @@ To disable updates auto downloads add to `config.xml`:
```
By default preference is set to `true`.

Note that in order to authenticate to the server, this should typically be set to false, and a manual download should be initiated with credentials in the [fetchUpdate()](#fetch-update) call.

##### auto-install
Defines if plugin is allowed to install updates. Originally update installation is performed automatically, but you can disable it and do that manually through the JavaScript module.

Expand Down Expand Up @@ -539,6 +541,7 @@ By default, all update checking->downloading->installation cycle is performed au
It allows you to:
- subscribe for update related events;
- check and download new releases from the server;
- override authentication and other request headers to the server;
- install loaded updates;
- change plugin preferences;
- request user to download new version of the app from the store.
Expand Down Expand Up @@ -656,13 +659,15 @@ From now on we will know, when update is loaded and ready for installation. By u

In order to force update check you can call from your web page:
```js
chcp.fetchUpdate(updateCallback);
chcp.fetchUpdate(updateCallback, headers /* optional */);

function updateCallback(error, data) {
// do some work
}
```

For authorization and other headers see [Change plugin preferences at runtime](#change-plugin-preferences-at-runtime) section.

Callback function gets called with two parameters:
- `error` - error if any happened during the update check; `null` if everything went fine;
- `data` - additional data, sent from the native side. For now it can be ignored.
Expand Down Expand Up @@ -781,7 +786,7 @@ app.initialize();

**Be advised:** even if you call `installUpdate` method with a callback function - installation related events are still broadcasted.

#### Change plugin preferences on runtime
#### Change plugin preferences at runtime

Normally all plugin preferences are set through the Cordova's `config.xml`. But you can change some of them through the JavaScript module.

Expand All @@ -801,7 +806,7 @@ Supported options:

Those options must be set on `deviceready` event. You should do that on every page load, because if application gets updated through the store - those options will be overridden with the corresponding values from the `config.xml`.

`auto-download` and `auto-install` can be used when you want to perform update download and installation manually. Let us extend previous example with `configure` method:
`auto-download` and `auto-install` can be used when you want to perform update download and installation manually. You will need to do this if you want to provide authentication credentials or other headers. Let us extend previous example with `configure` method:

```js
var app = {
Expand Down Expand Up @@ -847,8 +852,15 @@ var app = {
}
},

// This function will typically handle authorization with a provider.
makeAuthHeaders: function() {
var auth = "Basic " + btoa("usename:password");

return { Authorization : auth };
},

checkForUpdate: function() {
chcp.fetchUpdate(this.fetchUpdateCallback);
chcp.fetchUpdate(this.fetchUpdateCallback, this.makeAuthHeaders());
},

fetchUpdateCallback: function(error, data) {
Expand Down
2 changes: 2 additions & 0 deletions src/ios/HCPPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@
*/
- (void)jsRequestAppUpdate:(CDVInvokedUrlCommand *)command;

@property (nonatomic, retain) NSDictionary* headers;

@end
7 changes: 6 additions & 1 deletion src/ios/HCPPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ - (BOOL)_fetchUpdate:(NSString *)callbackId {
return NO;
}

NSString *taskId = [_updatesLoader addUpdateTaskToQueueWithConfigUrl:_pluginXmllConfig.configUrl];
NSString *taskId = [_updatesLoader addUpdateTaskToQueueWithConfigUrl:_pluginXmllConfig.configUrl headers: self.headers];
[self storeCallback:callbackId forFetchTask:taskId];

return taskId != nil;
Expand Down Expand Up @@ -626,6 +626,11 @@ - (void)jsFetchUpdate:(CDVInvokedUrlCommand *)command {
if (!_isPluginReadyForWork) {
return;
}

// headers may be passed as first argument, as a dict
if (command.arguments.count == 1) {
self.headers = command.arguments[0];
}

[self _fetchUpdate:command.callbackId];
}
Expand Down
3 changes: 3 additions & 0 deletions src/ios/Network/HCPFileDownloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ typedef void (^HCPDataDownloadCompletionBlock)(NSData *data, NSError *error);
*/
- (void) downloadFiles:(NSArray *)filesList fromURL:(NSURL *)contentURL toFolder:(NSURL *)folderURL completionBlock:(HCPFileDownloadCompletionBlock)block;

// headers to add to the session
@property (nonatomic, retain) NSDictionary* headers;

@end
6 changes: 6 additions & 0 deletions src/ios/Network/HCPFileDownloader.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ @implementation HCPFileDownloader
- (void) downloadDataFromUrl:(NSURL*) url completionBlock:(HCPDataDownloadCompletionBlock) block {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
if (self.headers) {
[configuration setHTTPAdditionalHeaders:self.headers];
}
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

NSURLSessionDataTask* dowloadTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
Expand All @@ -28,6 +31,9 @@ - (void) downloadDataFromUrl:(NSURL*) url completionBlock:(HCPDataDownloadComple
- (void) downloadFiles:(NSArray *)filesList fromURL:(NSURL *)contentURL toFolder:(NSURL *)folderURL completionBlock:(HCPFileDownloadCompletionBlock)block {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
if (self.headers) {
[configuration setHTTPAdditionalHeaders:self.headers];
}
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

__block NSMutableSet* startedTasks = [NSMutableSet set];
Expand Down
3 changes: 2 additions & 1 deletion src/ios/Updater/HCPUpdateLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
* Add update download task to queue. It will be executed as fast as possible.
*
* @param configUrl url to the application config on the server
* @param optional authorization header
*
* @return id of the created worker
*/
- (NSString *)addUpdateTaskToQueueWithConfigUrl:(NSURL *)configUrl;
- (NSString *)addUpdateTaskToQueueWithConfigUrl:(NSURL *)configUrl headers: (NSDictionary*) headers;

/**
* Setup loader. Should be called on application startup before any real work is performed.
Expand Down
7 changes: 4 additions & 3 deletions src/ios/Updater/HCPUpdateLoader.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ - (void)setup:(id<HCPFilesStructure>)filesStructure {
_filesStructure = filesStructure;
}

- (NSString *)addUpdateTaskToQueueWithConfigUrl:(NSURL *)configUrl {
- (NSString *)addUpdateTaskToQueueWithConfigUrl:(NSURL *)configUrl headers: (NSDictionary*) headers {
// TODO: add better communication between installer and loader.
// For now - skip update load request if installation or download is in progress.
if ([HCPUpdateInstaller sharedInstance].isInstallationInProgress || _isExecuting) {
return nil;
}

id<HCPWorker> task = [[HCPUpdateLoaderWorker alloc] initWithConfigUrl:configUrl filesStructure:_filesStructure];
HCPUpdateLoaderWorker* task = [[HCPUpdateLoaderWorker alloc] initWithConfigUrl:configUrl filesStructure:_filesStructure];

task.headers = headers;
[self executeTask:task];

return task.workerId;
Expand Down
1 change: 1 addition & 0 deletions src/ios/Updater/HCPUpdateLoaderWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@
*/
- (instancetype)initWithConfigUrl:(NSURL *)configURL filesStructure:(id<HCPFilesStructure>)fileStructure;

@property (nonatomic, retain) NSDictionary* headers;
@end
5 changes: 4 additions & 1 deletion src/ios/Updater/HCPUpdateLoaderWorker.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ - (void)runWithComplitionBlock:(void (^)(void))updateLoaderComplitionBlock {
}

HCPFileDownloader *configDownloader = [[HCPFileDownloader alloc] init];
configDownloader.headers = self.headers;

// download new application config
[configDownloader downloadDataFromUrl:_configURL completionBlock:^(NSData *data, NSError *error) {
Expand Down Expand Up @@ -125,7 +126,9 @@ - (void)downloadUpdatedFiles:(NSArray *)updatedFiles appConfig:(HCPApplicationCo

// download files
HCPFileDownloader *downloader = [[HCPFileDownloader alloc] init];
// TODO: set credentials on downloader

// pass headers (auth or other)
downloader.headers = self.headers;

[downloader downloadFiles:updatedFiles
fromURL:newAppConfig.contentConfig.contentURL
Expand Down
10 changes: 8 additions & 2 deletions www/chcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,22 @@ var chcp = {
* Usually this is done automatically by the plugin, but can be triggered at any time from the web page.
*
* @param {Callback(error, data)} callback - called when native side finished update process
* @param headers - provide optional headers object. This will be used to configure server request
*/
fetchUpdate: function(callback) {
fetchUpdate: function(callback, headers) {
var innerCallback = function(msg) {
var resultObj = processMessageFromNative(msg);
if (callback !== undefined && callback != null) {
callback(resultObj.error, resultObj.data);
}
};

var _headers = []
if (headers !== undefined && headers != null) {
_headers = [headers];
}

exec(innerCallback, null, PLUGIN_NAME, pluginNativeMethod.FETCH_UPDATE, []);
exec(innerCallback, null, PLUGIN_NAME, pluginNativeMethod.FETCH_UPDATE, _headers);
},

/**
Expand Down

0 comments on commit a5b557b

Please sign in to comment.