/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AsyncCallback, Callback } from '@ohos.base';
import { BusinessError } from '@ohos.base';
import BaseContext from 'application.BaseContext';
import hilog from '@ohos.hilog';
export default namespace request {
namespace agent {
loadLibrary("requestmodule_ani");
interface FileSpec {
path: string;
filename?: string;
}
interface FormItem {
name: string;
value: string | FileSpec | Array<FileSpec>;
}
enum Action {
DOWNLOAD,
UPLOAD
}
interface HttpResponse {
readonly version: string;
readonly statusCode: number;
readonly reason: string;
}
export class HttpResponseImpl implements HttpResponse {
readonly version: string;
readonly statusCode: number;
readonly reason: string;
constructor(version: string, statusCode: number, reason: string) {
this.version = version;
this.statusCode = statusCode;
this.reason = reason;
}
}
enum State {
INITIALIZED = 0x00,
WAITING = 0x10,
RUNNING = 0x20,
RETRYING = 0x21,
PAUSED = 0x30,
STOPPED = 0x31,
COMPLETED = 0x40,
FAILED = 0x41,
REMOVED = 0x50
}
interface Progress {
readonly state: State;
readonly index: number;
readonly processed: number;
}
const StateMap: Record<number, State> = {
0x00: State.INITIALIZED,
0x10: State.WAITING,
0x20: State.RUNNING,
0x21: State.RETRYING,
0x30: State.PAUSED,
0x31: State.STOPPED,
0x40: State.COMPLETED,
0x41: State.FAILED,
0x50: State.REMOVED
};
export class ProgressImpl implements Progress {
readonly state: State;
readonly index: number;
readonly processed: number;
constructor(state: number, index: number, processed: number) {
const resolvedState = StateMap[state];
if (resolvedState !== undefined) {
this.state = resolvedState;
} else {
this.state = State.INITIALIZED;
}
this.index = index;
this.processed = processed;
}
}
interface Config {
action: Action;
url: string;
method?: string;
data?: string | Array<FormItem>;
saveas?: string;
}
interface Task {
start(callback: AsyncCallback<void>): void;
start(): Promise<void>;
on(event: 'response' | 'completed', callback: Callback<HttpResponse | Progress>): void;
};
class Cleaner {
static callback(cleaner: Cleaner): void {
hilog.info(0x0000, 'request', "enter Cleaner.callback");
cleaner.clean()
}
constructor(targetPtr: long) {
this.targetPtr = targetPtr
}
native clean(): void
private targetPtr: long = 0;
}
class FinalizationAgent<T extends Object> {
static register<T extends Object>(obj: T, ptr: long): FinalizationAgent<T> {
let instance: FinalizationAgent<T> = new FinalizationAgent<T>();
instance.init(obj, ptr);
return instance;
}
unregister(): void {
finalizer.unregister(this.unregisterToken);
}
private init(obj: T, ptr: long): void {
this.unregisterToken = {};
this.cleaner = new Cleaner(ptr);
finalizer.register(obj, this.cleaner!, this.unregisterToken);
}
private cleaner: Cleaner | null = null;
private unregisterToken: object;
}
let finalizer = new FinalizationRegistry<Cleaner>(Cleaner.callback)
export class TaskImpl implements Task {
nativePtr: long = 0;
private fzAgent: FinalizationAgent<TaskImpl>;
constructor(context: long) {
hilog.info(0x0000, 'request', "in constructor, context is " + context)
this.nativePtr = context;
this.fzAgent = FinalizationAgent.register<TaskImpl>(this, this.nativePtr);
}
unregisterCleaner(): void {
this.fzAgent.unregister();
}
on(event: 'response' | 'completed', callback: Callback<HttpResponse | Progress>): void {
this.onSync(event, callback);
};
start(callback: AsyncCallback<void>): void {
let p1 = taskpool.execute((): void => {
this.startSync();
});
p1.then((data: Any): void => {
let e = new BusinessError<void>;
callback(e, undefined);
}).catch((error: Any) => {
let err = error as BusinessError<void>;
callback(err, undefined);
});
};
start(): Promise<void> {
let p = new Promise<void>((resolve: (v: undefined) => void, reject: (error: Error) => void) : void => {
let p1 = taskpool.execute((): void => {
this.startSync();
});
p1.then((e: Any) : void => {
resolve(undefined);
}).catch((err: Error) : void => {
reject(err);
});
});
return p;
}
native onSync(event: string, callback: Callback<HttpResponse | Progress>): void;
native startSync(): void;
};
export native function createSync(context: BaseContext, config: Config): Task;
export function create(context: BaseContext, config: Config, callback: AsyncCallback<Task>): void {
let p1 = taskpool.execute(createSync, context, config);
p1.then((data: Any) => {
let r = data as Task;
let err = new BusinessError<void>;
callback(err, r);
}).catch((error: Any) => {
let err = error as BusinessError<void>;
let data: Task;
callback(err, data);
});
};
export function create(context: BaseContext, config: Config): Promise<Task> {
let p = new Promise<Task>((resolve: (v: Task) => void,
reject: (error: Error) => void): void => {
let p1 = taskpool.execute(createSync, context, config);
p1.then((e: Any): void => {
resolve(e as Task);
}).catch((err: Error) : void => {
reject(err);
});
});
return p;
}
}
}