* Copyright (c) 2023 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.
*/
let cert = requireInternal('security.cert');
let webview = requireInternal('web.webview');
let fileIo = requireNapi('file.fs');
let fileUri = requireNapi('file.fileuri');
let picker = requireNapi('file.picker');
let photoAccessHelper = requireNapi('file.photoAccessHelper');
let cameraPicker = requireNapi('multimedia.cameraPicker');
let camera = requireNapi('multimedia.camera');
let accessControl = requireNapi('abilityAccessCtrl');
let avsession = requireNapi('multimedia.avsession');
let deviceinfo = requireInternal('deviceInfo');
let promptAction = requireNapi('promptAction');
let dataShare = requireNapi('data.dataShare');
let webNativeMessagingExtensionManager = requireNapi('web.webnativemessagingextensionmanager_napi');
let { LengthMetrics } = requireNapi('arkui.node');
let commonEventManager = requireNapi('commonEventManager');
let resourceManager = requireNapi('resourceManager');
const PARAM_CHECK_ERROR = 401;
const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter';
let errMsgMap = new Map();
errMsgMap.set(PARAM_CHECK_ERROR, ERROR_MSG_INVALID_PARAM);
let customDialogComponentId = 0;
let onShowFileSelectorEvent = undefined;
let defaultPublicPath = '/storage/Users/currentUser/';
let publicDirectoryMap = new Map([
['desktop', defaultPublicPath + 'desktop'],
['documents', defaultPublicPath + 'documents'],
['downloads', defaultPublicPath + 'download'],
['music', defaultPublicPath + 'music'],
['pictures', defaultPublicPath + 'images'],
['videos', defaultPublicPath + 'videos'],
]);
class BusinessError extends Error {
constructor(code, errorMsg = 'undefined') {
if (errorMsg === 'undefined') {
let msg = errMsgMap.get(code);
super(msg);
} else {
super(errorMsg);
}
this.code = code;
}
}
export let AVCastPickerState;
(function(pickerState) {
pickerState[pickerState.STATE_APPEARING = 0] = 'STATE_APPEARING';
pickerState[pickerState.STATE_DISAPPEARING = 1] = 'STATE_DISAPPEARING';
})(AVCastPickerState || (AVCastPickerState = {}));
function getCertificatePromise(certChainData) {
let x509CertArray = [];
if (!(certChainData instanceof Array)) {
console.log('failed, cert chain data type is not array');
return Promise.all(x509CertArray);
}
for (let i = 0; i < certChainData.length; i++) {
let encodeBlobData = {
data: certChainData[i],
encodingFormat: cert.EncodingFormat.FORMAT_DER
};
x509CertArray[i] = cert.createX509Cert(encodeBlobData);
}
return Promise.all(x509CertArray);
}
function takePhoto(callback) {
let pickerProfileOptions = {
'cameraPosition': camera.CameraPosition.CAMERA_POSITION_BACK,
};
let acceptTypes = callback.fileparam.getAcceptType();
let mediaType = [];
if (isContainImageMimeType(acceptTypes)) {
mediaType.push(cameraPicker.PickerMediaType.PHOTO);
}
if (isContainVideoMimeType(acceptTypes)) {
mediaType.push(cameraPicker.PickerMediaType.VIDEO);
}
let result = [];
cameraPicker.pick(getContext(this), mediaType, pickerProfileOptions)
?.then((pickerResult) => {
result.push(pickerResult.resultUri);
}).catch((error) => {
console.log('selectFile error:' + JSON.stringify(error));
promptAction.showToast({ message: '无法打开拍照功能,请检查是否具备拍照功能' });
}).finally(() => {
onShowFileSelectorEvent?.fileresult.handleFileList(result);
onShowFileSelectorEvent = undefined;
});
}
function needShowDialog(params) {
let result = false;
try {
let currentDevice = deviceinfo.deviceType.toLowerCase();
if (currentDevice === '2in1') {
return false;
}
if (params.isCapture()) {
console.log('input element contain capture tag, not show dialog');
return false;
}
let acceptTypes = params.getAcceptType();
if (isContainImageMimeType(acceptTypes) || isContainVideoMimeType(acceptTypes)) {
result = true;
}
} catch (error) {
console.log('show dialog happend error:' + JSON.stringify(error));
}
return result;
}
function selectFile(callback) {
let documentPicker = new picker.DocumentViewPicker();
let result = [];
if (callback.fileparam.getMode() !== FileSelectorMode.FileSaveMode) {
documentPicker.select(createDocumentSelectionOptions(callback.fileparam))
.then((documentSelectResult) => {
result = documentSelectResult;
}).catch((error) => {
console.log('selectFile error: ' + JSON.stringify(error));
promptAction.showToast({ message: '无法打开文件功能,请检查是否具备文件功能' });
}).finally(() => {
onShowFileSelectorEvent?.fileresult.handleFileList(result);
onShowFileSelectorEvent = undefined;
});
} else {
documentPicker.save(createDocumentSaveOptions(callback.fileparam))
.then((documentSaveResult)=>{
let tempUri = saveFile(documentSaveResult);
result.push(tempUri);
}).catch((error) => {
console.log('saveFile error: ' + JSON.stringify(error));
promptAction.showToast({ message: '无法打开文件功能,请检查是否具备文件功能' });
}).finally(() => {
onShowFileSelectorEvent?.fileresult.handleFileList(result);
onShowFileSelectorEvent = undefined;
});
}
}
function saveFile(documentSaveResult) {
let filePaths = documentSaveResult;
let tempUri = '';
if (filePaths.length > 0) {
let tempPath = '';
try {
let fileName = filePaths[0].substr(filePaths[0].lastIndexOf('/'));
tempPath = getContext(this).filesDir + fileName;
tempUri = fileUri.getUriFromPath(tempPath);
let randomAccessFile = fileIo.createRandomAccessFileSync(tempPath, fileIo.OpenMode.CREATE);
randomAccessFile.close();
} catch (err) {
console.error(`saveFile failed when getPath with error message: ${err.message}, error code: ${err.code}`);
}
let watcher = fileIo.createWatcher(tempPath, 0x4, () => {
let tempFile = null;
let destinyFile = null;
let arrayBuffer;
Promise.all([fileIo.lstat(tempPath),
fileIo.open(tempPath, fileIo.OpenMode.READ_ONLY),
fileIo.open(filePaths[0], fileIo.OpenMode.READ_WRITE)])
.then(([stat, tmpFile, destFile]) => {
tempFile = tmpFile;
destinyFile = destFile;
arrayBuffer = new ArrayBuffer(stat.size);
return fileIo.read(tempFile.fd, arrayBuffer);
})
.then(readLen => {
if (readLen) {
console.log(`saveFile read data to file succeed and size is ${readLen}`);
return fileIo.write(destinyFile.fd, arrayBuffer);
}
throw new Error('read file is Empty');
})
.then(writeLen => {
if (writeLen) {
console.log(`saveFile write data to file succeed and size is ${writeLen}`);
return;
}
throw new Error('write file length is 0');
})
.catch((err) => {
console.error(`saveFile failed with error message: ${err.message}, error code: ${err.code}`);
})
.finally(() => {
let finalSet = new Set();
if (tempFile) {
finalSet.add(fileIo.close(tempFile));
}
if (destinyFile) {
finalSet.add(fileIo.close(destinyFile));
}
watcher.stop();
return Promise.all(finalSet).finally(() => {
fileIo.unlink(tempPath);
});
})
.catch((err) => {
console.error(`saveFile end failed with error message: ${err.message}, error code: ${err.code}`);
})
});
watcher.start();
}
return tempUri;
}
function createDocumentSelectionOptions(param) {
let documentSelectOptions = new picker.DocumentSelectOptions();
let currentDevice = deviceinfo.deviceType.toLowerCase();
try {
let defaultSelectNumber = 500;
let defaultSelectMode = picker.DocumentSelectMode.MIXED;
documentSelectOptions.maxSelectNumber = defaultSelectNumber;
documentSelectOptions.selectMode = defaultSelectMode;
documentSelectOptions.defaultFilePathUri = getDefaultPath(param);
let mode = param.getMode();
switch (mode) {
case FileSelectorMode.FileOpenMode:
documentSelectOptions.maxSelectNumber = 1;
documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE;
break;
case FileSelectorMode.FileOpenMultipleMode:
documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE;
break;
case FileSelectorMode.FileOpenFolderMode:
documentSelectOptions.selectMode = picker.DocumentSelectMode.FOLDER;
break;
default:
break;
}
documentSelectOptions.fileSuffixFilters = [];
let suffix = param.getAcceptType().join(',');
let accepts = param.getAcceptableFileTypes();
let descriptions = param.getDescriptions();
if (accepts && accepts.length > 0) {
suffixFromAccepts(documentSelectOptions.fileSuffixFilters, descriptions, accepts);
} else if (suffix) {
documentSelectOptions.fileSuffixFilters.push(suffix);
}
if (currentDevice !== 'phone' && !param.isAcceptAllOptionExcluded()) {
documentSelectOptions.fileSuffixFilters.push('.*');
}
} catch (error) {
console.log('selectFile error: ' + + JSON.stringify(error));
}
return documentSelectOptions;
}
function createDocumentSaveOptions(param) {
let documentSaveOptions = new picker.DocumentSaveOptions();
let currentDevice = deviceinfo.deviceType.toLowerCase();
try {
documentSaveOptions.pickerMode = picker.DocumentPickerMode.DEFAULT;
documentSaveOptions.fileSuffixChoices = [];
documentSaveOptions.newFileNames = [ param.getSuggestedName() ];
documentSaveOptions.defaultFilePathUri = getDefaultPath(param);
let suffix = param.getAcceptType().join(',');
let accepts = param.getAcceptableFileTypes();
let descriptions = param.getDescriptions();
if (accepts && accepts.length > 0) {
suffixFromAccepts(documentSaveOptions.fileSuffixChoices, descriptions, accepts);
} else if (suffix) {
documentSaveOptions.fileSuffixChoices.push(suffix);
}
if (currentDevice !== 'phone' && !param.isAcceptAllOptionExcluded()) {
documentSaveOptions.fileSuffixChoices.push('.*');
}
} catch (error) {
console.log('saveFile error: ' + + JSON.stringify(error));
}
return documentSaveOptions;
}
function getDefaultPath(param) {
let path = param.getDefaultPath();
if (publicDirectoryMap.get(path) !== undefined) {
path = publicDirectoryMap.get(path);
}
return fileUri.getUriFromPath(path);
}
function suffixFromAccepts(suffix, descriptions, accepts) {
let n = accepts.length;
for (let i = 0; i < n; i++) {
let m = accepts[i].length;
let extList = [];
for (let j = 0; j < m; j++) {
extList.push(accepts[i][j].acceptableType.join(','));
}
let ext = extList.join(',');
let desc = descriptions[i] + '(' + ext + ')' + '|';
suffix.push(desc + ext);
}
}
function isContainImageMimeType(acceptTypes) {
if (!(acceptTypes instanceof Array)) {
return false;
}
if (acceptTypes.length < 1) {
return true;
}
let imageTypes = ['tif', 'xbm', 'tiff', 'pjp', 'jfif', 'bmp', 'avif', 'apng', 'ico',
'webp', 'svg', 'gif', 'svgz', 'jpg', 'jpeg', 'png', 'pjpeg'];
for (let i = 0; i < acceptTypes.length; i++) {
for (let j = 0; j < imageTypes.length; j++) {
if (acceptTypes[i].includes(imageTypes[j])) {
return true;
}
}
}
return false;
}
function isContainVideoMimeType(acceptTypes) {
if (!(acceptTypes instanceof Array)) {
return false;
}
if (acceptTypes.length < 1) {
return true;
}
let videoTypes = ['ogm', 'ogv', 'mpg', 'mp4', 'mpeg', 'm4v', 'webm'];
for (let i = 0; i < acceptTypes.length; i++) {
for (let j = 0; j < videoTypes.length; j++) {
if (acceptTypes[i].includes(videoTypes[j])) {
return true;
}
}
}
return false;
}
class SelectorDialog extends ViewPU {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
super(parent, __localStorage, elmtId, extraInfo);
if (typeof paramsLambda === 'function') {
this.paramsGenerator_ = paramsLambda;
}
this.__choose_to_upload = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.choose_to_upload'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'choose_to_upload');
this.__general_cancel = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.general_cancel'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'general_cancel');
this.__taking_photos_or_videos = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.taking_photos_or_videos'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'taking_photos_or_videos');
this.__taking_photos = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.taking_photos'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'taking_photos');
this.__video_recording = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.video_recording'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'video_recording');
this.__gallery = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.gallery'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'gallery');
this.__document = new ObservedPropertyObjectPU({ 'id': -1, 'type': -1, params: ['sys.string.document'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }, this, 'document');
this.setInitiallyProvidedValue(params);
}
setInitiallyProvidedValue(params) {
if (params.callback !== undefined) {
this.callback = params.callback;
}
}
purgeVariableDependenciesOnElmtId(rmElmtId) {
this.__choose_to_upload.purgeDependencyOnElmtId(rmElmtId);
this.__general_cancel.purgeDependencyOnElmtId(rmElmtId);
this.__taking_photos_or_videos.purgeDependencyOnElmtId(rmElmtId);
this.__taking_photos.purgeDependencyOnElmtId(rmElmtId);
this.__video_recording.purgeDependencyOnElmtId(rmElmtId);
this.__gallery.purgeDependencyOnElmtId(rmElmtId);
this.__document.purgeDependencyOnElmtId(rmElmtId);
}
aboutToBeDeleted() {
commonEventManager.unsubscribe(this.subscriber, (err) => {
if (err) {
console.error(`Failed to unsubscribe. Code is ${err.code}, message is ${err.message}`);
return;
}
this.subscriber = undefined;
console.info('Succeeded in unsubscribing.');
});
this.__choose_to_upload.aboutToBeDeleted();
this.__general_cancel.aboutToBeDeleted();
this.__taking_photos_or_videos.aboutToBeDeleted();
this.__taking_photos.aboutToBeDeleted();
this.__video_recording.aboutToBeDeleted();
this.__gallery.aboutToBeDeleted();
this.__document.aboutToBeDeleted();
SubscriberManager.Get().delete(this.id__());
this.aboutToBeDeletedInternal();
}
get choose_to_upload() {
return this.__choose_to_upload.get();
}
set choose_to_upload(newValue) {
this.__choose_to_upload.set(newValue);
}
get general_cancel() {
return this.__general_cancel.get();
}
set general_cancel(newValue) {
this.__general_cancel.set(newValue);
}
get taking_photos_or_videos() {
return this.__taking_photos_or_videos.get();
}
set taking_photos_or_videos(newValue) {
this.__taking_photos_or_videos.set(newValue);
}
get taking_photos() {
return this.__taking_photos.get();
}
set taking_photos(newValue) {
this.__taking_photos.set(newValue);
}
get video_recording() {
return this.__video_recording.get();
}
set video_recording(newValue) {
this.__video_recording.set(newValue);
}
get gallery() {
return this.__gallery.get();
}
set gallery(newValue) {
this.__gallery.set(newValue);
}
get document() {
return this.__document.get();
}
set document(newValue) {
this.__document.set(newValue);
}
fileSelectorListItem(callback, sysResource, text, func) {
this.observeComponentCreation2((elmtId, isInitialRender) => {
Row.create();
Row.onClick(() => {
promptAction.closeCustomDialog(customDialogComponentId);
func(callback);
});
Row.width('calc(100% - 48vp)');
}, Row);
this.observeComponentCreation2((elmtId, isInitialRender) => {
SymbolGlyph.create({ 'id': -1, 'type': -1, params: [sysResource], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' });
SymbolGlyph.fontSize('24vp');
SymbolGlyph.fontWeight(FontWeight.Medium);
SymbolGlyph.margin({
end: LengthMetrics.vp(16)
});
SymbolGlyph.fontColor([{ 'id': -1, 'type': -1, params: ['sys.color.font_primary'], 'bundleName': 'com.example.selectdialog', 'moduleName': 'entry' }]);
}, SymbolGlyph);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Row.create();
Row.constraintSize({ minHeight: 56 });
Row.width('calc(100% - 40vp)');
Row.border({ width: { bottom: 0.5 }, color: '#33000000' });
}, Row);
this.observeComponentCreation2((elmtId, isInitialRender) => {
switch (text) {
case 'sys.string.gallery':
Text.create(this.gallery);
break;
case 'sys.string.taking_photos_or_videos':
Text.create(this.taking_photos_or_videos);
break;
case 'sys.string.taking_photos':
Text.create(this.taking_photos);
break;
case 'sys.string.video_recording':
Text.create(this.video_recording);
break;
case 'sys.string.document':
Text.create(this.document);
}
Text.fontSize('16vp');
Text.fontWeight(FontWeight.Medium);
}, Text);
Text.pop();
Row.pop();
Row.pop();
}
fileSelectorDialog(callback) {
this.observeComponentCreation2((elmtId, isInitialRender) => {
Scroll.create();
}, Scroll);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
this.fileSelectorListItem.bind(this)(callback, 'sys.symbol.picture', 'sys.string.gallery', selectPicture);
let acceptTypes = callback.fileparam.getAcceptType();
let cameraOption = 'sys.string.taking_photos_or_videos';
if (isContainImageMimeType(acceptTypes) && !isContainVideoMimeType(acceptTypes)) {
cameraOption = 'sys.string.taking_photos';
}
if (!isContainImageMimeType(acceptTypes) && isContainVideoMimeType(acceptTypes)) {
cameraOption = 'sys.string.video_recording';
}
this.fileSelectorListItem.bind(this)(callback, 'sys.symbol.camera', cameraOption, takePhoto);
this.fileSelectorListItem.bind(this)(callback, 'sys.symbol.doc_text', 'sys.string.document', selectFile);
Column.pop();
Scroll.pop();
}
fileSelectorDialogForPhone(callback) {
this.observeComponentCreation2((elmtId, isInitialRender) => {
Flex.create({ justifyContent: FlexAlign.Center, direction: FlexDirection.Column, alignItems: ItemAlign.Center });
Flex.height('auto');
}, Flex);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Row.create();
Row.constraintSize({ minHeight: 56 });
Row.width('calc(100% - 48vp)');
Row.justifyContent(FlexAlign.Center);
}, Row);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Text.create(this.choose_to_upload);
Text.fontSize('20vp');
Text.fontWeight(FontWeight.Bold);
Text.textAlign(TextAlign.Center);
}, Text);
Text.pop();
Row.pop();
this.fileSelectorDialog.bind(this)(callback);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Row.create();
Row.onClick(() => {
try {
console.log('Get Alert Dialog handled');
onShowFileSelectorEvent?.fileresult.handleFileList([]);
onShowFileSelectorEvent = undefined;
promptAction.closeCustomDialog(customDialogComponentId);
}
catch (error) {
let message = error.message;
let code = error.code;
console.error(`closeCustomDialog error code is ${code}, message is ${message}`);
}
});
Row.constraintSize({ minHeight: 40 });
Row.margin({
top: 8,
bottom: 16
});
Row.width('calc(100% - 32vp)');
Row.justifyContent(FlexAlign.Center);
Row.flexShrink(0);
}, Row);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Text.create(this.general_cancel);
Text.fontColor('#FF0A59F7');
Text.fontSize('16vp');
Text.fontWeight(FontWeight.Medium);
Text.textAlign(TextAlign.Center);
}, Text);
Text.pop();
Row.pop();
Flex.pop();
}
setResource() {
let manager = resourceManager.getSysResourceManager();
setTimeout(() => {
manager.getStringByName('choose_to_upload')
.then((value) => {
this.choose_to_upload = value;
});
manager.getStringByName('general_cancel')
.then((value) => {
this.general_cancel = value;
});
manager.getStringByName('taking_photos_or_videos')
.then((value) => {
this.taking_photos_or_videos = value;
});
manager.getStringByName('taking_photos')
.then((value) => {
this.taking_photos = value;
});
manager.getStringByName('video_recording')
.then((value) => {
this.video_recording = value;
});
manager.getStringByName('gallery')
.then((value) => {
this.gallery = value;
});
manager.getStringByName('document')
.then((value) => {
this.document = value;
});
}, 200);
}
initialRender() {
this.fileSelectorDialogForPhone.bind(this)(this.callback);
commonEventManager.createSubscriber({ events: [commonEventManager.Support.COMMON_EVENT_LOCALE_CHANGED] })
.then((commonEventSubscriber) => {
this.subscriber = commonEventSubscriber;
commonEventManager.subscribe(commonEventSubscriber, (err, data) => {
if (err) {
console.error(`Failed to subscribe. Code is ${err.code}, message is ${err.message}`);
return;
}
this.setResource();
});
}).catch((err) => {
console.error(`CreateSubscriber failed. Code is ${err.code}, message is ${err.message}`);
});
let that = this;
this.getUIContext().getHostContext()?.getApplicationContext().on('applicationStateChange', {
onApplicationForeground() {
console.info('SelectorDialog onApplicationForeground');
that.setResource();
},
onApplicationBackground() {
console.info('SelectorDialog onApplicationBackground');
}
});
}
rerender() {
this.updateDirtyElements();
}
static getEntryName() {
return 'SelectorDialog';
}
}
function selectPicture(callback) {
let photoResultArray = [];
let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
if (callback.fileparam.getMode() === FileSelectorMode.FileOpenMode) {
console.log('allow select single photo or video');
photoSelectOptions.maxSelectNumber = 1;
}
let acceptTypes = callback.fileparam.getAcceptType();
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
if (isContainImageMimeType(acceptTypes) && !isContainVideoMimeType(acceptTypes)) {
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
}
if (!isContainImageMimeType(acceptTypes) && isContainVideoMimeType(acceptTypes)) {
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE;
}
let photoPicker = new photoAccessHelper.PhotoViewPicker();
photoPicker.select(photoSelectOptions).then((photoSelectResult) => {
for (let i = 0; i < photoSelectResult.photoUris.length; i++) {
photoResultArray.push(photoSelectResult.photoUris[i]);
}
}).catch((error) => {
console.log('selectPicture error' + JSON.stringify(error));
promptAction.showToast({ message: '无法打开图片功能,请检查是否具备图片功能' });
}).finally(() => {
onShowFileSelectorEvent?.fileresult.handleFileList(photoResultArray);
onShowFileSelectorEvent = undefined;
});
}
async function getManifestData(bundleName, connectExtensionOrigin, notifyCallback, callback) {
try {
const dsProxyHelper = await dataShare.createDataProxyHandle();
const urisToGet = [`datashareproxy://${bundleName}/browserNativeMessagingHosts`];
const config = {
type: dataShare.DataProxyType.SHARED_CONFIG,
};
const results = await dsProxyHelper.get(urisToGet, config);
let foundValid = false;
for (let i = 0; i < results.length; i++) {
try {
const result = results[i];
const json = result.value;
let info = JSON.parse(json);
const infoPath = info.path;
if (typeof infoPath === 'string') {
info.path = JSON.parse(infoPath);
info.abilityName = info.path.abilityName;
}
if (info.name && info.description && info.allowed_origins && info.abilityName) {
console.info('Native message json info is ok');
if (!Array.isArray(info.allowed_origins)) {
info.allowed_origins = [info.allowed_origins];
}
if (!info.allowed_origins.includes(connectExtensionOrigin)) {
console.error('Origin not allowed, continue searching');
continue;
}
foundValid = true;
callback(info);
break;
}
} catch (error) {
console.error('NativeMessage JSON parse error:', error);
}
}
if (!foundValid) {
console.error('NativeMessage JSON no valid manifest found');
callback(undefined);
}
} catch (error) {
callback(undefined);
console.error('Error getting config:', error);
}
}
Object.defineProperty(webview.WebviewController.prototype, 'getCertificate', {
value: function (callback) {
if (arguments.length !== 0 && arguments.length !== 1) {
throw new BusinessError(PARAM_CHECK_ERROR,
'BusinessError 401: Parameter error. The number of params must be zero or one.');
}
let certChainData = this.innerGetCertificate();
if (callback === undefined) {
console.log('get certificate promise');
return getCertificatePromise(certChainData);
} else {
console.log('get certificate async callback');
if (typeof callback !== 'function') {
throw new BusinessError(PARAM_CHECK_ERROR,
'BusinessError 401: Parameter error. The type of "callback" must be function.');
}
return getCertificatePromise(certChainData).then(x509CertArray => {
callback(undefined, x509CertArray);
}).catch(error => {
callback(error, undefined);
});
}
}
});
Object.defineProperty(webview.WebviewController.prototype, 'fileSelectorShowFromUserWeb', {
value: function (callback) {
if (onShowFileSelectorEvent) {
onShowFileSelectorEvent = callback;
return;
}
onShowFileSelectorEvent = callback;
let currentDevice = deviceinfo.deviceType.toLowerCase();
if (needShowDialog(callback.fileparam)) {
promptAction.openCustomDialog({
builder: () => {
ViewPU.create(new SelectorDialog(undefined, { callback: callback }));
},
onWillDismiss: (dismissDialogAction) => {
console.info('reason' + JSON.stringify(dismissDialogAction.reason));
console.log('dialog onWillDismiss');
if (dismissDialogAction.reason === DismissReason.PRESS_BACK) {
onShowFileSelectorEvent?.fileresult.handleFileList([]);
dismissDialogAction.dismiss();
}
if (dismissDialogAction.reason === DismissReason.TOUCH_OUTSIDE) {
onShowFileSelectorEvent?.fileresult.handleFileList([]);
dismissDialogAction.dismiss();
}
onShowFileSelectorEvent = undefined;
}
}).then((dialogId) => {
customDialogComponentId = dialogId;
})
.catch((error) => {
onShowFileSelectorEvent?.fileresult.handleFileList([]);
onShowFileSelectorEvent = undefined;
console.error(`openCustomDialog error code is ${error.code}, message is ${error.message}`);
});
} else if (currentDevice !== '2in1' && callback.fileparam.isCapture() &&
(isContainImageMimeType(callback.fileparam.getAcceptType()) || isContainVideoMimeType(callback.fileparam.getAcceptType()))) {
console.log('take photo will be directly invoked due to the capture property');
takePhoto(callback);
} else {
console.log('selectFile will be invoked by web');
selectFile(callback);
}
}
});
Object.defineProperty(webview.WebviewController.prototype, 'OnMediaCastEnter', {
value: function () {
console.log('webview_export OnMediaCastEnter');
let avCastPicker = new avsession.AVCastPickerHelper(getContext(this));
try {
avCastPicker.select();
console.log('webview_export OnMediaCastEnter select, success');
onPickerStateChange(avCastPicker);
} catch (error) {
console.log('webview_export OnMediaCastEnter select, fail: ', error);
}
}
});
async function onPickerStateChange(avCastPicker) {
console.log('webview_export onPickerStateChange, enter');
try {
avCastPicker.on('pickerStateChange', (state) => {
console.info(`webview_export pickerStateChange: picker state change : ${state}`);
if(state === AVCastPickerState.STATE_APPEARING) {
console.log('webview_export pickerStateChange, The picker showing.');
} else if (state === AVCastPickerState.STATE_DISAPPEARING) {
console.log('webview_export pickerStateChange, The picker hiding');
avCastPicker = undefined;
}
});
} catch (error) {
console.log('webview_export onPickerStateChange, fail: ', error);
}
}
Object.defineProperty(webview.WebviewController.prototype, 'requestPermissionsFromUserWeb', {
value: function (callback) {
let accessManger = accessControl.createAtManager();
let abilityContext = getContext(this);
accessManger.requestPermissionsFromUser(abilityContext, ['ohos.permission.READ_PASTEBOARD'])
.then((PermissionRequestResult) => {
if (PermissionRequestResult.authResults[0] === 0) {
console.log('requestPermissionsFromUserWeb is allowed');
callback.request.grant(callback.request.getAccessibleResource());
}
else {
console.log('requestPermissionsFromUserWeb is refused');
callback.request.deny();
}
})
.catch((error) => {
callback.request.deny();
});
}
});
Object.defineProperty(webview.WebviewController.prototype, 'openAppLink', {
value: function (callback) {
let abilityContext = getContext(this);
try {
let option = {
appLinkingOnly: true
};
console.log('begin openAppLink');
abilityContext.openLink(callback.url, option, null)
.then(() => {
console.log('applink success openLink');
callback.result.cancelLoad();
})
.catch((error) => {
console.log(`applink openLink ErrorCode: ${error.code}, Message: ${error.message}`);
callback.result.continueLoad();
});
} catch (err) {
console.log(`applink openLink ErrorCode: ${err.code}, Message: ${err.message}`);
setTimeout(() => {
callback.result.continueLoad();
}, 1);
}
}
});
Object.defineProperty(webview.WebviewController.prototype, 'innerWebNativeMessageManager', {
value: function (callback) {
console.info('innerWebNativeMessageManager called');
try {
let bundleName = callback.bundleName;
let readPipe = callback.readPipe;
let writePipe = callback.writePipe;
let connectExtensionOrigin = callback.extensionOrigin;
getManifestData(bundleName, connectExtensionOrigin, callback.result, (result) => {
try {
if (!result) {
console.error(`NativeMessage find DateShare is no ${bundleName} config`);
callback.result.onFailed(4001);
return;
}
let wantInfo = {
bundleName: callback.bundleName,
abilityName: result.abilityName,
parameters: {
'ohos.arkweb.messageReadPipe': { 'type': 'FD', 'value': readPipe },
'ohos.arkweb.messageWritePipe': { 'type': 'FD', 'value': writePipe },
'ohos.arkweb.extensionOrigin': connectExtensionOrigin
},
};
console.debug(`innerWebNativeMessageManager want ${JSON.stringify(wantInfo)}`);
let options = {
onConnect(connection) {
callback.result.onConnect(connection.connectionId);
},
onDisconnect(connection) {
callback.result.onDisconnect(connection.connectionId);
},
onFailed(code) {
callback.result.onFailed(code);
}
};
let abilityContext = getContext(this);
let connectId = webNativeMessagingExtensionManager.connectNative(abilityContext, wantInfo, options);
console.log(`innerWebNativeMessageManager connectionId : ${connectId}` );
} catch (error) {
console.log(`inner callback error Message: ${JSON.stringify(error)}`);
}
});
} catch (err) {
console.log(`innerWebNativeMessageManager Message: ${JSON.stringify(err)}`);
}
}
});
Object.defineProperty(webview.WebviewController.prototype, 'innerNativeMessageDisconnect', {
value: function (callback) {
try {
if (!callback) {
console.error('Messaging disconnect failed: callback is undefined or null');
return;
}
let connectId = callback.connectId;
if (connectId === undefined || connectId === null) {
console.error('Messaging disconnect failed: connectId is undefined or null');
return;
}
console.log(`Messaging disconnect connectId= ${connectId}`);
webNativeMessagingExtensionManager.disconnectNative(connectId);
} catch (error) {
console.error(`Messaging disconnect error: ${JSON.stringify(error)}`);
}
}
});
Object.defineProperty(webview.WebviewController.prototype, 'innerCanIUse', {
value: function (callback) {
let result = canIUse(callback.syscap);
return result;
}
});
export default webview;