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

Commit

Permalink
Switch to cordova-plugin-advanced-http for update downloads (#513)
Browse files Browse the repository at this point in the history
* Update plugin.xml

* patch XCode 10 usage with `build.json` flags

- add build.json to pass additional flags to cordova
- use build.json to pass `UseModernBuildSystem=0` avoiding build failure

* switch from plugin-file-transfer to to raw XHR

* rollback config.xml tweak

* remove plugin-file-transfer from project

* Eliminated file-transfer from workaround hook

* fix ProgressEvent typings, TS defs, commit JS

* add cordova plugin file as an explicit dependency

* CORS: drop xhr in favor of advanced-http plugin

* fix: dependency minor version

* switch from promises to callbacks

* add dependency on plugin-zip

* fix typo

* update advanced-http dependency

* use plugin-advanced-http for all http requests

* fix body serialization

* added getDataDirectory call to ensure path

 - as discussed in #513, with move to advanced-http, the update payload
   began to fail
 - The call to getDataDirectory triggers path creation, if it doesn't
   exist yet

Co-authored-by: Alexander Goncharov <v-algonc@microsoft.com>

Co-authored-by: David Pfeffer <bytenik@bytenik.com>
Co-authored-by: unknown <david@ballstreettrading.com>
Co-authored-by: Alexander Goncharov <v-algonc@microsoft.com>
  • Loading branch information
4 people authored Jul 27, 2020
1 parent 15fe2c8 commit 1c661bc
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 133 deletions.
2 changes: 1 addition & 1 deletion bin/www/fileUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ var FileUtil = (function () {
fileEntry.file(function (file) {
var fileReader = new FileReader();
fileReader.onloadend = function (ev) {
callback(null, ev.target.result);
callback(null, fileReader.result);
};
fileReader.onerror = function () {
callback(new Error("Could not get file. Error: " + fileReader.error.message), null);
Expand Down
85 changes: 53 additions & 32 deletions bin/www/httpRequester.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,79 @@


"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var CodePushUtil = require("./codePushUtil");
var HttpRequester = (function () {
function HttpRequester(contentType) {
this.contentType = contentType;
cordova.plugin.http.setHeader("X-CodePush-Plugin-Name", "cordova-plugin-code-push");
cordova.plugin.http.setHeader("X-CodePush-Plugin-Version", cordova.require("cordova/plugin_list").metadata["cordova-plugin-code-push"]);
cordova.plugin.http.setHeader("X-CodePush-SDK-Version", cordova.require("cordova/plugin_list").metadata["code-push"]);
if (contentType) {
cordova.plugin.http.setHeader("Content-Type", contentType);
}
}
HttpRequester.prototype.request = function (verb, url, callbackOrRequestBody, callback) {
var requestBody;
var requestCallback = callback;
var options = HttpRequester.getInitialOptionsForVerb(verb);
if (options instanceof Error) {
CodePushUtil.logError("Could not make the HTTP request", options);
requestCallback && requestCallback(options, undefined);
return;
}
if (!requestCallback && typeof callbackOrRequestBody === "function") {
requestCallback = callbackOrRequestBody;
}
if (typeof callbackOrRequestBody === "string") {
requestBody = callbackOrRequestBody;
}
var xhr = new XMLHttpRequest();
var methodName = this.getHttpMethodName(verb);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
var response = { statusCode: xhr.status, body: xhr.responseText };
requestCallback && requestCallback(null, response);
}
};
xhr.open(methodName, url, true);
if (this.contentType) {
xhr.setRequestHeader("Content-Type", this.contentType);
options.serializer = "utf8";
options.data = callbackOrRequestBody;
}
xhr.setRequestHeader("X-CodePush-Plugin-Name", "cordova-plugin-code-push");
xhr.setRequestHeader("X-CodePush-Plugin-Version", cordova.require("cordova/plugin_list").metadata["cordova-plugin-code-push"]);
xhr.setRequestHeader("X-CodePush-SDK-Version", cordova.require("cordova/plugin_list").metadata["code-push"]);
xhr.send(requestBody);
options.responseType = "text";
cordova.plugin.http.sendRequest(url, options, function (success) {
requestCallback && requestCallback(null, {
body: success.data,
statusCode: success.status,
});
}, function (failure) {
requestCallback && requestCallback(new Error(failure.error), null);
});
};
HttpRequester.prototype.getHttpMethodName = function (verb) {
HttpRequester.getInitialOptionsForVerb = function (verb) {
switch (verb) {
case 0:
return "GET";
case 7:
return "CONNECT";
return { method: "get" };
case 4:
return "DELETE";
return { method: "delete" };
case 1:
return "HEAD";
case 6:
return "OPTIONS";
return { method: "head" };
case 8:
return "PATCH";
return { method: "patch" };
case 2:
return "POST";
return { method: "post" };
case 3:
return "PUT";
return { method: "put" };
case 5:
return "TRACE";
case 6:
case 7:
default:
return null;
return new ((function (_super) {
__extends(UnsupportedMethodError, _super);
function UnsupportedMethodError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return UnsupportedMethodError;
}(Error)))("Unsupported HTTP method code [" + verb + "]");
}
};
return HttpRequester;
Expand Down
44 changes: 24 additions & 20 deletions bin/www/remotePackage.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ var __extends = (this && this.__extends) || (function () {
})();
var LocalPackage = require("./localPackage");
var Package = require("./package");
var FileUtil = require("./fileUtil");
var NativeAppInfo = require("./nativeAppInfo");
var CodePushUtil = require("./codePushUtil");
var Sdk = require("./sdk");
var RemotePackage = (function (_super) {
__extends(RemotePackage, _super);
function RemotePackage() {
return _super !== null && _super.apply(this, arguments) || this;
var _this = _super.call(this) || this;
_this.isDownloading = false;
FileUtil.getDataDirectory(LocalPackage.DownloadDir, true, function (error, _) {
if (error) {
CodePushUtil.logError("Can't create directory for download update.", error);
}
});
return _this;
}
RemotePackage.prototype.download = function (successCallback, errorCallback, downloadProgress) {
var _this = this;
Expand All @@ -39,9 +47,15 @@ var RemotePackage = (function (_super) {
CodePushUtil.invokeErrorCallback(new Error("The remote package does not contain a download URL."), errorCallback);
}
else {
this.currentFileTransfer = new FileTransfer();
var downloadSuccess = function (fileEntry) {
_this.currentFileTransfer = null;
this.isDownloading = true;
var onFileError_1 = function (fileError, stage) {
var error = new Error("Could not access local package. Stage:" + stage + "Error code: " + fileError.code);
CodePushUtil.invokeErrorCallback(error, errorCallback);
CodePushUtil.logMessage(stage + ":" + fileError);
_this.isDownloading = false;
};
var onFileReady = function (fileEntry) {
_this.isDownloading = false;
fileEntry.file(function (file) {
NativeAppInfo.isFailedUpdate(_this.packageHash, function (installFailed) {
var localPackage = new LocalPackage();
Expand All @@ -58,21 +72,11 @@ var RemotePackage = (function (_super) {
successCallback && successCallback(localPackage);
Sdk.reportStatusDownload(localPackage, localPackage.deploymentKey);
});
}, function (fileError) {
CodePushUtil.invokeErrorCallback(new Error("Could not access local package. Error code: " + fileError.code), errorCallback);
});
};
var downloadError = function (error) {
_this.currentFileTransfer = null;
CodePushUtil.invokeErrorCallback(new Error(error.body), errorCallback);
};
this.currentFileTransfer.onprogress = function (progressEvent) {

This comment has been minimized.

Copy link
@ecorona

ecorona Nov 5, 2020

Removing this is avoiding progressEvent to be called.

if (downloadProgress) {
var dp = { receivedBytes: progressEvent.loaded, totalBytes: progressEvent.total };
downloadProgress(dp);
}
}, function (fileError) { return onFileError_1(fileError, "READ_FILE"); });
};
this.currentFileTransfer.download(this.downloadUrl, cordova.file.dataDirectory + LocalPackage.DownloadDir + "/" + LocalPackage.PackageUpdateFileName, downloadSuccess, downloadError);
var filedir = cordova.file.dataDirectory + LocalPackage.DownloadDir + "/";
var filename = LocalPackage.PackageUpdateFileName;
cordova.plugin.http.downloadFile(this.downloadUrl, {}, {}, filedir + filename, onFileReady, onFileError_1);
}
}
catch (e) {
Expand All @@ -81,8 +85,8 @@ var RemotePackage = (function (_super) {
};
RemotePackage.prototype.abortDownload = function (abortSuccess, abortError) {
try {
if (this.currentFileTransfer) {
this.currentFileTransfer.abort();
if (this.isDownloading) {
this.isDownloading = false;
abortSuccess && abortSuccess();
}
}
Expand Down
7 changes: 0 additions & 7 deletions hooks/afterPluginAdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ module.exports = function (ctx) {
plugins = execSync(cordovaCLI + ' plugin').toString();
}

if (!isPluginInListOrInXmlConfig("cordova-plugin-file-transfer", plugins)) {
console.log("Adding the cordova-plugin-file-transfer@1.6.3... ");
var output = execSync(cordovaCLI + ' plugin add cordova-plugin-file-transfer@1.6.3').toString();
console.log(output);
plugins = execSync(cordovaCLI + ' plugin').toString();
}

if (!isPluginInListOrInXmlConfig("cordova-plugin-zip", plugins)) {
console.log("Adding the cordova-plugin-zip@3.1.0... ");
var output = execSync(cordovaCLI + ' plugin add cordova-plugin-zip@3.1.0').toString();
Expand Down
5 changes: 4 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
<license>MIT</license>
<keywords>cordova,code,push</keywords>
<repo>https://github.com/Microsoft/cordova-plugin-code-push.git</repo>

<dependency id="code-push" version="3.0.1" />
<dependency id="cordova-plugin-dialogs" version=">=1.1.1" />
<dependency id="cordova-plugin-device" version=">=1.1.0" />
<dependency id="cordova-plugin-file" version=">=6.0.1" />
<dependency id="cordova-plugin-advanced-http" version=">=2.2.0" />
<dependency id="cordova-plugin-zip" version=">=3.1.0" />

<hook type="after_plugin_add" src="hooks/afterPluginAdd.js" />

Expand Down
1 change: 1 addition & 0 deletions test/template/build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "ios": { "debug": { "buildFlag": [ "-UseModernBuildSystem=0" ] }, "release": { "buildFlag": [ "-UseModernBuildSystem=0" ] } } }
86 changes: 85 additions & 1 deletion typings/codePush.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,92 @@
// Copyright (c) Microsoft Corporation
// All rights reserved.
// Licensed under the MIT license.
/// <reference types="cordova-plugin-file" />

// Types used in file handling
/**
* A function which accepts @type {FileEntry} containing a file
*/
type FileSaverCompletionHandler = (entry: FileEntry) => void;
/**
* A function which is called if file handling has failed
*/
type FileSaverErrorHandler = (error: FileError, at: string) => void;

/**
* @namespace AdvancedHttp describes the select types from cordova-plugin-advanced-http
* The plugin authors do not provide typescript typings, relying on ionic-native typings,
* which require the project to use ionic promisify-style plugin versions.
*
* @see https://github.com/silkimen/cordova-plugin-advanced-http/issues/32
*
* For additional type documentation:
* - @see README for cordova-plugin-advanced-http and the
* - @see https://github.com/ionic-team/ionic-native/blob/master/src/%40ionic-native/plugins/http/index.ts
* for partial typings provided by ionic
*/
declare namespace AdvancedHttp {

/**
* Response is passed to @method sendRequest callbacks.
*/
export interface Response {
/**
* The status number of the response
*/
status: number;
/**
* The headers of the response
*/
headers: any;
/**
* The URL of the response. This property will be the final URL obtained after any redirects.
*/
url: string;
/**
* The data that is in the response. This property usually exists when a promise returned by a request method resolves.
*/
data?: any;
/**
* Error response from the server. This property usually exists when a promise returned by a request method rejects.
*/
error?: string;
}

/**
* Options object configures @method sendRequest calls
*/
export interface Options {
method: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'upload' | 'download';
data?: { [index: string]: any };
params?: { [index: string]: string | number };
serializer?: 'json' | 'urlencoded' | 'utf8';
timeout?: number;
headers?: { [index: string]: string };
filePath?: string | string[];
name?: string | string[];
responseType?: 'text' | 'arraybuffer' | 'blob' | 'json';
}

export class Plugin {
/**
* setHeader sets global headers for cordova-plugin-advanced-http calls
*/
setHeader(arg1: string, arg2: string, arg3?: string): void;
/**
* sendRequest handles the lifetime of an HTTP call
*/
sendRequest(url: string, options: Options, onSuccess: (r: Response) => void, onError: (r: Response) => void): void;
/**
* downloadFile wraps @method sendRequest to provide an easy interface for working with files
*/
downloadFile(url: string, body: object, headers: object, filePath: string, onSuccess: FileSaverCompletionHandler, onFailure: FileSaverErrorHandler): void;
}

}

declare module Http {
// Integer based verbs that will be passed by Acquisition SDK
export const enum Verb {
GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH
}
Expand Down Expand Up @@ -405,4 +489,4 @@ interface DownloadProgress {
interface DeploymentResult {
deployDir: DirectoryEntry,
isDiffUpdate: boolean
}
}
1 change: 0 additions & 1 deletion www/codePush.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// <reference path="../typings/codePush.d.ts" />
/// <reference types="cordova-plugin-file" />
/// <reference types="cordova-plugin-file-transfer" />
/// <reference types="cordova" />
/// <reference types="cordova-plugin-dialogs" />

Expand Down
4 changes: 2 additions & 2 deletions www/fileUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ class FileUtil {
public static readFileEntry(fileEntry: FileEntry, callback: Callback<string>): void {
fileEntry.file((file: File) => {
var fileReader = new FileReader();
fileReader.onloadend = (ev: any) => {
callback(null, ev.target.result);
fileReader.onloadend = (ev: ProgressEvent) => {
callback(null, fileReader.result as string);
};

fileReader.onerror = () => {
Expand Down
Loading

0 comments on commit 1c661bc

Please sign in to comment.