From 11a6363d5822356016ab2ee8d45a58ff3f9dc163 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Tue, 1 Aug 2017 13:57:01 +0200 Subject: [PATCH] [Notification] Added validation for JS UserNotification [Feature] Added validation of members of UserNotification object Invalid values are replaced with default ones. [Verification] TCT passrate didn't change. Checked in chrome console for several invalid values, seems working well. Change-Id: Id67026153c548a818c6fb35437adb9424b11ad09 Signed-off-by: Piotr Kosko --- src/notification/common_notification.cc | 34 +- src/notification/notification_api.js | 490 +++++++++++++++++++++--- 2 files changed, 446 insertions(+), 78 deletions(-) diff --git a/src/notification/common_notification.cc b/src/notification/common_notification.cc index 71abbd34..ea7f87c3 100644 --- a/src/notification/common_notification.cc +++ b/src/notification/common_notification.cc @@ -1334,26 +1334,28 @@ PlatformResult CommonNotification::SetDetailInfosFromJson(const picojson::value& notification_h noti_handle) { LoggerD("Enter"); const picojson::object& noti_obj = noti_value.get(); - const picojson::array& array = FromJson(noti_obj, "detailInfo"); + if (noti_value.contains("detailInfo") && !IsNull(noti_obj, "detailInfo")) { + const picojson::array& array = FromJson(noti_obj, "detailInfo"); - if (array.size() > info_map_.size()) { - return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, - "Too many values in notification detailInfo array"); - } - size_t idx = 0; + if (array.size() > info_map_.size()) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, + "Too many values in notification detailInfo array"); + } + size_t idx = 0; - for (auto& item : array) { - const picojson::object& obj = JsonCast(item); + for (auto& item : array) { + const picojson::object& obj = JsonCast(item); - PlatformResult status = - SetText(noti_handle, - info_map_.at(idx), - FromJson(obj, "mainText")); - CHECK_ERROR(status); + PlatformResult status = + SetText(noti_handle, + info_map_.at(idx), + FromJson(obj, "mainText")); + CHECK_ERROR(status); - SetTextFromJson(picojson::value(obj), info_sub_map_.at(idx), "subText", noti_handle); - CHECK_ERROR(status); - ++idx; + SetTextFromJson(picojson::value(obj), info_sub_map_.at(idx), "subText", noti_handle); + CHECK_ERROR(status); + ++idx; + } } return PlatformResult(ErrorCode::NO_ERROR); } diff --git a/src/notification/notification_api.js b/src/notification/notification_api.js index 6fc32b0d..af65a3e2 100644 --- a/src/notification/notification_api.js +++ b/src/notification/notification_api.js @@ -345,6 +345,58 @@ NotificationManager.prototype.createNotificationFromTemplate = function(name) { return returnObject; }; +var _checkProgressValue = function(v, _progressType) { + if ((_progressType === NotificationProgressType.PERCENTAGE && (v >= 0 && v <= 100)) + || (_progressType === NotificationProgressType.BYTE && + converter_.toUnsignedLong(v) >= 0)) { + return true; + } + return false; +}; + +var _checkDetailInfo = function(v) { + if (type_.isNull(v)) { + return true; + } + if (!type_.isArray(v)) { + return false; + } + for (var i = 0; i < v.length; ++i) { + if (!(v[i] instanceof tizen.NotificationDetailInfo)) { + return false; + } + } + return true; +}; + +var _setDetailInfo = function(v) { + var _d = []; + for (var i = 0; i < v.length; ++i) { + _d.push(new tizen.NotificationDetailInfo(v[i].mainText, v[i].subText || null)); + } + return _d; +}; + +var _checkStringArray = function(v) { + if (type_.isNull(v)) { + return true; + } + if (!type_.isArray(v)) { + return false; + } + for (var i = 0; i < v.length; ++i) { + if (!type_.isString(v[i])) { + return false; + } + } + return true; +}; + +var _isHex = function(v) { + return v.length === 7 && v.substr(0, 1) === '#' && (/^([0-9A-Fa-f]{2})+$/).test(v.substr(1, 7)); +}; + + function NotificationInitDict(data) { var _iconPath = null; var _soundPath = null; @@ -353,60 +405,15 @@ function NotificationInitDict(data) { var _appId = null; var _progressType = NotificationProgressType.PERCENTAGE; var _progressValue = null; - var checkProgressValue = function(v) { - if ((_progressType === NotificationProgressType.PERCENTAGE && (v >= 0 && v <= 100)) - || (_progressType === NotificationProgressType.BYTE && - converter_.toUnsignedLong(v) >= 0)) { - return true; - } - return false; - }; var _number = null; var _subIconPath = null; var _detailInfo = []; - var checkDetailInfo = function(v) { - if (type_.isNull(v)) { - return true; - } - if (!type_.isArray(v)) { - return false; - } - for (var i = 0; i < v.length; ++i) { - if (!(v[i] instanceof tizen.NotificationDetailInfo)) { - return false; - } - } - return true; - }; - var setDetailInfo = function(v) { - var _d = []; - for (var i = 0; i < v.length; ++i) { - _d.push(new tizen.NotificationDetailInfo(v[i].mainText, v[i].subText || null)); - } - return _d; - }; var _ledColor = null; - var isHex = function(v) { - return v.length === 7 && v.substr(0, 1) === '#' && (/^([0-9A-Fa-f]{2})+$/).test(v.substr(1, 7)); - }; var _ledOnPeriod = 0; var _ledOffPeriod = 0; var _backgroundImagePath = null; var _thumbnails = []; - var checkThumbnails = function(v) { - if (type_.isNull(v)) { - return true; - } - if (!type_.isArray(v)) { - return false; - } - for (var i = 0; i < v.length; ++i) { - if (!type_.isString(v[i])) { - return false; - } - } - return true; - }; + Object.defineProperties(this, { iconPath: { @@ -481,7 +488,7 @@ function NotificationInitDict(data) { _progressValue = v; return; } - if (checkProgressValue(v)) { + if (_checkProgressValue(v, _progressType)) { _progressValue = (_progressType === NotificationProgressType.PERCENTAGE) ? v / 100 : converter_.toUnsignedLong(v); @@ -512,7 +519,7 @@ function NotificationInitDict(data) { return _detailInfo; }, set: function(v) { - _detailInfo = _edit.canEdit && v ? setDetailInfo(v) : checkDetailInfo(v) ? v : _detailInfo; + _detailInfo = _edit.canEdit && v ? _setDetailInfo(v) : _checkDetailInfo(v) ? v : _detailInfo; }, enumerable: true }, @@ -521,7 +528,7 @@ function NotificationInitDict(data) { return _ledColor; }, set: function(v) { - _ledColor = (type_.isString(v) && isHex(v)) || type_.isNull(v) ? v : _ledColor; + _ledColor = (type_.isString(v) && _isHex(v)) || type_.isNull(v) ? v : _ledColor; }, enumerable: true }, @@ -557,7 +564,7 @@ function NotificationInitDict(data) { return _thumbnails; }, set: function(v) { - _thumbnails = checkThumbnails(v) ? v : _thumbnails; + _thumbnails = _checkStringArray(v) ? v : _thumbnails; }, enumerable: true } @@ -694,6 +701,363 @@ function NotificationDetailInfo(mainText, subText) { }); } +function TextContentsInitDict(data) { + if (!this) return; + var _progressType = NotificationProgressType.PERCENTAGE; + var _progressValue = null; + var _number = null; + var _detailInfo = []; + var _buttonsTexts = []; + var _contentForOff = null; + + Object.defineProperties(this, { + progressType: { + get: function() { + return _progressType; + }, + set: function(v) { + _progressType = Object.keys(NotificationProgressType).indexOf(v) >= 0 ? v : _progressType; + }, + enumerable: true + }, + progressValue: { + get: function() { + if (null === _progressValue) { + return _progressValue; + } + + return (_progressType === NotificationProgressType.PERCENTAGE) + ? _progressValue * 100 + : _progressValue; + }, + set: function(v) { + if (type_.isNull(v)) { + _progressValue = v; + return; + } + if (_checkProgressValue(v, _progressType)) { + _progressValue = (_progressType === NotificationProgressType.PERCENTAGE) + ? v / 100 + : converter_.toUnsignedLong(v); + } + }, + enumerable: true + }, + eventsNumber: { + get: function() { + return _number; + }, + set: function(v) { + _number = type_.isNumber(v) || type_.isNull(v) ? v : _number; + }, + enumerable: true + }, + detailInfo: { + get: function() { + return _detailInfo; + }, + set: function(v) { + _detailInfo = _edit.canEdit && v ? _setDetailInfo(v) : _checkDetailInfo(v) ? v : _detailInfo; + }, + enumerable: true + }, + buttonsTexts: { + get: function() { + return _buttonsTexts; + }, + set: function(v) { + _buttonsTexts = _checkStringArray(v) ? v : _buttonsTexts; + }, + enumerable: true + }, + contentForOff: { + get: function() { + return _contentForOff; + }, + set: function(v) { + _contentForOff = type_.isString(v) || type_.isNull(v) ? v : _contentForOff; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +function ImagesInitDict(data) { + if (!this) return; + var _iconPath = null; + var _subIconPath = null; + var _indicatorIconPath = null; + var _lockScreenIconPath = null; + var _buttonIconPaths = []; + var _backgroundImagePath = null; + + Object.defineProperties(this, { + iconPath: { + get: function() { + return _iconPath; + }, + set: function(v) { + _iconPath = type_.isString(v) || type_.isNull(v) ? v : _iconPath; + }, + enumerable: true + }, + subIconPath: { + get: function() { + return _subIconPath; + }, + set: function(v) { + _subIconPath = type_.isString(v) || type_.isNull(v) ? v : _subIconPath; + }, + enumerable: true + }, + indicatorIconPath: { + get: function() { + return _indicatorIconPath; + }, + set: function(v) { + _indicatorIconPath = type_.isString(v) || type_.isNull(v) ? v : _indicatorIconPath; + }, + enumerable: true + }, + lockScreenIconPath: { + get: function() { + return _lockScreenIconPath; + }, + set: function(v) { + _lockScreenIconPath = type_.isString(v) || type_.isNull(v) ? v : _lockScreenIconPath; + }, + enumerable: true + }, + buttonIconPaths: { + get: function() { + return _buttonIconPaths; + }, + set: function(v) { + _buttonIconPaths = _checkStringArray(v) ? v : _buttonIconPaths; + }, + enumerable: true + }, + backgroundImagePath: { + get: function() { + return _backgroundImagePath; + }, + set: function(v) { + _backgroundImagePath = type_.isString(v) || type_.isNull(v) ? v : _backgroundImagePath; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +function ThumbnailsInitDict(data) { + if (!this) return; + var _lockScreenThumbnailIconPath = null; + var _thumbnailIconPath = null; + var _thumbnails = []; + + Object.defineProperties(this, { + lockScreenThumbnailIconPath: { + get: function() { + return _lockScreenThumbnailIconPath; + }, + set: function(v) { + _lockScreenThumbnailIconPath = type_.isString(v) || type_.isNull(v) ? v : _lockScreenThumbnailIconPath; + }, + enumerable: true + }, + thumbnailIconPath: { + get: function() { + return _thumbnailIconPath; + }, + set: function(v) { + _thumbnailIconPath = type_.isString(v) || type_.isNull(v) ? v : _thumbnailIconPath; + }, + enumerable: true + }, + thumbnails: { + get: function() { + return _thumbnails; + }, + set: function(v) { + _thumbnails = _checkStringArray(v) ? v : _thumbnails; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +function ActionsInitDict(data) { + if (!this) return; + var _soundPath = null; + var _vibration = false; + var _appControl = null; + var _appId = null; + + Object.defineProperties(this, { + soundPath: { + get: function() { + return _soundPath; + }, + set: function(v) { + _soundPath = type_.isString(v) || type_.isNull(v) ? v : _soundPath; + }, + enumerable: true + }, + vibration: { + get: function() { + return _vibration; + }, + set: function(v) { + _vibration = type_.isBoolean(v) ? v : _vibration; + }, + enumerable: true + }, + appControl: { + get: function() { + return _appControl; + }, + set: function(v) { + _appControl = _edit.canEdit && v + ? new tizen.ApplicationControl(v.operation, v.uri || null, v.mime || null, v.category + || null, v.data || []) + : v instanceof tizen.ApplicationControl || type_.isNull(v) ? v : _appControl; + }, + enumerable: true + }, + appId: { + get: function() { + return _appId; + }, + set: function(v) { + _appId = type_.isString(v) && !(/\s/.test(v)) || type_.isNull(v) ? v : _appId; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +function GroupContentsInitDict(data) { + if (!this) return; + var _groupTitle = null; + var _groupContent = null; + var _groupContentForOff = null; + + Object.defineProperties(this, { + groupTitle: { + get: function() { + return _groupTitle; + }, + set: function(v) { + _groupTitle = type_.isString(v) || type_.isNull(v) ? v : _groupTitle; + }, + enumerable: true + }, + groupContent: { + get: function() { + return _groupContent; + }, + set: function(v) { + _groupContent = type_.isString(v) || type_.isNull(v) ? v : _groupContent; + }, + enumerable: true + }, + groupContentForOff: { + get: function() { + return _groupContentForOff; + }, + set: function(v) { + _groupContentForOff = type_.isString(v) || type_.isNull(v) ? v : _groupContentForOff; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + +function LedsInitDict(data) { + if (!this) return; + var _ledColor = null; + var _ledOnPeriod = 0; + var _ledOffPeriod = 0; + + Object.defineProperties(this, { + ledColor: { + get: function() { + return _ledColor; + }, + set: function(v) { + _ledColor = (type_.isString(v) && _isHex(v)) || type_.isNull(v) ? v : _ledColor; + }, + enumerable: true + }, + ledOnPeriod: { + get: function() { + return _ledOnPeriod; + }, + set: function(v) { + _ledOnPeriod = type_.isNumber(v) ? v : _ledOnPeriod; + }, + enumerable: true + }, + ledOffPeriod: { + get: function() { + return _ledOffPeriod; + }, + set: function(v) { + _ledOffPeriod = type_.isNumber(v) ? v : _ledOffPeriod; + }, + enumerable: true + } + }); + + if (data instanceof _global.Object) { + for (var prop in data) { + if (this.hasOwnProperty(prop)) { + this[prop] = data[prop]; + } + } + } +} + function UserNotification(userType, title, notificationGropedInitDict) { validator_.isConstructorCall(this, UserNotification); type_.isObject(notificationGropedInitDict) ? @@ -702,6 +1066,14 @@ function UserNotification(userType, title, notificationGropedInitDict) { UserNotificationInitDict.call(this, notificationGropedInitDict); Notification.call(this, notificationGropedInitDict); + // validation of each member - setting default values instead of incorrect ones + TextContentsInitDict.call(this.textContents, notificationGropedInitDict.textContents); + ImagesInitDict.call(this.images, notificationGropedInitDict.images); + ThumbnailsInitDict.call(this.thumbnails, notificationGropedInitDict.thumbnails); + ActionsInitDict.call(this.actions, notificationGropedInitDict.actions); + LedsInitDict.call(this.leds, notificationGropedInitDict.leds); + GroupContentsInitDict.call(this.groupContents, notificationGropedInitDict.groupContents); + var _userType = (Object.keys(UserNotificationType)).indexOf(userType) >= 0 ? userType : StatusNotificationType.SIMPLE; @@ -723,12 +1095,12 @@ UserNotification.prototype = new Notification(); UserNotification.prototype.constructor = UserNotification; function UserNotificationInitDict(data) { - var _textContents; - var _images; - var _thumbnails; - var _actions; - var _groupContents; - var _leds; + var _textContents = null; + var _images = null; + var _thumbnails = null; + var _actions = null; + var _groupContents = null; + var _leds = null; Object.defineProperties(this, { textContents: { @@ -736,7 +1108,6 @@ function UserNotificationInitDict(data) { return _textContents; }, set: function(v) { - // TODO additional validation of members is needed _textContents = type_.isObject(v) || type_.isNull(v) ? v : _textContents; }, enumerable: true @@ -746,7 +1117,6 @@ function UserNotificationInitDict(data) { return _images; }, set: function(v) { - // TODO additional validation of members is needed _images = type_.isObject(v) || type_.isNull(v) ? v : _images; }, enumerable: true @@ -756,7 +1126,6 @@ function UserNotificationInitDict(data) { return _thumbnails; }, set: function(v) { - // TODO additional validation of members is needed _thumbnails = type_.isObject(v) || type_.isNull(v) ? v : _thumbnails; }, enumerable: true @@ -766,7 +1135,6 @@ function UserNotificationInitDict(data) { return _actions; }, set: function(v) { - // TODO additional validation of members is needed _actions = type_.isObject(v) || type_.isNull(v) ? v : _actions; }, enumerable: true @@ -776,7 +1144,6 @@ function UserNotificationInitDict(data) { return _groupContents; }, set: function(v) { - // TODO additional validation of members is needed _groupContents = type_.isObject(v) || type_.isNull(v) ? v : _groupContents; }, enumerable: true @@ -786,7 +1153,6 @@ function UserNotificationInitDict(data) { return _leds; }, set: function(v) { - // TODO additional validation of members is needed _leds = type_.isObject(v) || type_.isNull(v) ? v : _leds; }, enumerable: true -- 2.34.1