[Notification] Added validation for JS UserNotification 22/141822/2
authorPiotr Kosko <p.kosko@samsung.com>
Tue, 1 Aug 2017 11:57:01 +0000 (13:57 +0200)
committerTomasz Marciniak <t.marciniak@samsung.com>
Mon, 7 Aug 2017 07:58:28 +0000 (09:58 +0200)
[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 <p.kosko@samsung.com>
src/notification/common_notification.cc
src/notification/notification_api.js

index 71abbd3..ea7f87c 100644 (file)
@@ -1334,26 +1334,28 @@ PlatformResult CommonNotification::SetDetailInfosFromJson(const picojson::value&
                                                           notification_h noti_handle) {
   LoggerD("Enter");
   const picojson::object& noti_obj = noti_value.get<picojson::object>();
-  const picojson::array& array = FromJson<picojson::array>(noti_obj, "detailInfo");
+  if (noti_value.contains("detailInfo") && !IsNull(noti_obj, "detailInfo")) {
+    const picojson::array& array = FromJson<picojson::array>(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<picojson::object>(item);
+    for (auto& item : array) {
+      const picojson::object& obj = JsonCast<picojson::object>(item);
 
-    PlatformResult status =
-        SetText(noti_handle,
-                info_map_.at(idx),
-                FromJson<std::string>(obj, "mainText"));
-    CHECK_ERROR(status);
+      PlatformResult status =
+          SetText(noti_handle,
+                  info_map_.at(idx),
+                  FromJson<std::string>(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);
 }
index 6fc32b0..af65a3e 100644 (file)
@@ -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