/* * 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 picker = requireNapi('file.picker'); let photoAccessHelper = requireNapi('file.photoAccessHelper'); let cameraPicker = requireNapi('multimedia.cameraPicker'); let camera = requireNapi('multimedia.camera'); let accessControl = requireNapi('abilityAccessCtrl'); let deviceinfo = requireInternal('deviceInfo'); 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); class BusinessError extends Error { constructor(code, errorMsg = 'undefined') { if (errorMsg === 'undefined') { let msg = errMsgMap.get(code); super(msg); } else { super(errorMsg); } this.code = code; } } 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(param, selectResult) { try { let pickerProfileOptions = { 'cameraPosition': camera.CameraPosition.CAMERA_POSITION_BACK, }; let acceptTypes = param.getAcceptType(); let mediaType = []; if (isContainImageMimeType(acceptTypes) && !isContainVideoMimeType(acceptTypes)) { mediaType.push(cameraPicker.PickerMediaType.PHOTO); } else if (!isContainImageMimeType(acceptTypes) && isContainVideoMimeType(acceptTypes)) { mediaType.push(cameraPicker.PickerMediaType.VIDEO); } else { mediaType.push(cameraPicker.PickerMediaType.PHOTO); mediaType.push(cameraPicker.PickerMediaType.VIDEO); } cameraPicker.pick(getContext(this), mediaType, pickerProfileOptions) .then((pickerResult) => { if (pickerResult.resultCode === 0) { selectResult.handleFileList([pickerResult.resultUri]); } }).catch((error) => { console.log('selectFile error:' + JSON.stringify(error)); }); } catch (error) { console.log('the pick call failed, error code' + JSON.stringify(error)); } } function needShowDialog(params) { let result = false; try { let currentDevice = deviceinfo.deviceType.toLowerCase(); if (currentDevice !== 'phone') { 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(param, result) { try { let documentSelectOptions = createDocumentSelectionOptions(param); let documentPicker = new picker.DocumentViewPicker(); documentPicker.select(documentSelectOptions) .then((documentSelectResult) => { if (documentSelectResult && documentSelectResult.length > 0) { let filePath = documentSelectResult; result.handleFileList(filePath); } }).catch((error) => { console.log('selectFile error: ' + JSON.stringify(error)); }); } catch (error) { console.log('picker error: ' + JSON.stringify(error)); } } function createDocumentSelectionOptions(param) { let documentSelectOptions = new picker.DocumentSelectOptions(); try { let defaultSelectNumber = 500; let defaultSelectMode = picker.DocumentSelectMode.MIXED; documentSelectOptions.maxSelectNumber = defaultSelectNumber; documentSelectOptions.selectMode = defaultSelectMode; 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; case FileSelectorMode.FileSaveMode: break; default: break; } documentSelectOptions.fileSuffixFilters = []; let suffix = param.getAcceptType().join(','); if (suffix) { documentSelectOptions.fileSuffixFilters.push(suffix); } documentSelectOptions.fileSuffixFilters.push('.*'); } catch (error) { console.log('selectFile error: ' + + JSON.stringify(error)); return documentSelectOptions; } return documentSelectOptions; } function isContainImageMimeType(acceptTypes) { if (!(acceptTypes instanceof Array) || acceptTypes.length < 1) { return false; } 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) || acceptTypes.length < 1) { return false; } 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; } function selectPicture(param, selectResult) { try { let photoResultArray = []; let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); if (param.getMode() === FileSelectorMode.FileOpenMode) { console.log('allow select single photo or video'); photoSelectOptions.maxSelectNumber = 1; } let acceptTypes = param.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) => { if (photoSelectResult.photoUris.length <= 0) { return; } for (let i = 0; i < photoSelectResult.photoUris.length; i++) { photoResultArray.push(photoSelectResult.photoUris[i]); } selectResult.handleFileList(photoResultArray); }); } catch (error) { console.log('selectPicture error' + JSON.stringify(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.' ); } getCertificatePromise(certChainData).then(x509CertArray => { callback(undefined, x509CertArray); }).catch(error => { callback(error, undefined); }); } } }); Object.defineProperty(webview.WebviewController.prototype, 'fileSelectorShowFromUserWeb', { value: function (callback) { let currentDevice = deviceinfo.deviceType.toLowerCase(); if (needShowDialog(callback.fileparam)) { ActionSheet.show({ title: '选择上传', autoCancel: true, confirm: { defaultFocus: true, value: '取消', style: DialogButtonStyle.DEFAULT, action: () => { console.log('Get Alert Dialog handled'); } }, cancel: () => { console.log('actionSheet canceled'); }, alignment: DialogAlignment.Bottom, offset: { dx: 0, dy: -10 }, sheets: [ { icon: $r('sys.media.ohos_ic_public_albums'), title: '图片', action: () => { selectPicture(callback.fileparam, callback.fileresult); } }, { icon: $r('sys.media.ohos_ic_public_camera'), title: '拍照', action: () => { takePhoto(callback.fileparam, callback.fileresult); } }, { icon: $r('sys.media.ohos_ic_public_email'), title: '文件', action: () => { selectFile(callback.fileparam, callback.fileresult); } } ] }); } else if (currentDevice === 'phone' && callback.fileparam.isCapture()) { console.log('take photo will be directly invoked due to the capture property'); takePhoto(callback.fileparam, callback.fileresult); } else { console.log('selectFile will be invoked by web'); selectFile(callback.fileparam, callback.fileresult); } } }); 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}`); callback.result.continueLoad(); } } }); export default webview;