Index: src/Notification.cpp
diff --git a/src/Notification.cpp b/src/Notification.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..857c98206bd0b29b681f9ee095fe4b4146a6d864
--- /dev/null
+++ b/src/Notification.cpp
@@ -0,0 +1,207 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <AdblockPlus/JsValue.h>
+#include <AdblockPlus/JsEngine.h>
+#include <AdblockPlus/Notification.h>
+#include <algorithm>
+
+using namespace AdblockPlus;
+
+namespace
+{
+  typedef std::pair<NotificationType, std::string> NotificationTypeString;
+  typedef std::vector<NotificationTypeString> NotificationTypes;
+  const NotificationTypes g_notificationTypes = []()->NotificationTypes
+  {
+    NotificationTypes retValue;
+    retValue.emplace_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_QUESTION, "question"));
+    retValue.emplace_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_CRITICAL, "critical"));
+    retValue.emplace_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_INFORMATION, "information"));
+    return retValue;
+  }();
+
+  NotificationType StringToNotificationType(const std::string& value)
+  {
+    auto ii_notificationType = std::find_if(g_notificationTypes.begin(), g_notificationTypes.end(),
+      [&value](const NotificationTypeString& pair)->bool
+    {
+      return value == pair.second;
+    });
+    if (ii_notificationType == g_notificationTypes.end())
+    {
+      return NotificationType::NOTIFICATION_TYPE_INFORMATION;
+    }
+    return ii_notificationType->first;
+  }
+
+  std::string NotificationTypeToString(NotificationType value)
+  {
+    auto ii_notificationType = std::find_if(g_notificationTypes.begin(), g_notificationTypes.end(),
+      [&value](const NotificationTypeString& pair)->bool
+    {
+      return value == pair.first;
+    });
+    if (ii_notificationType == g_notificationTypes.end())
+    {
+      return "information";
+    }
+    return ii_notificationType->second;
+  }
+}
+
+Notification::Notification(NotificationType type, const std::string& id, const JsValuePtr& jsValue, PrivateCtrArg)
+  : JsValue(jsValue)
+{
+  SetProperty("type", NotificationTypeToString(type));
+  SetProperty("id", id);
+}
+
+std::string Notification::GetId() const
+{
+  auto jsValue = GetProperty("id");
+  return jsValue ? jsValue->AsString() : "";
+}
+
+NotificationType Notification::GetType() const
+{
+  auto jsValue = GetProperty("type");
+  return StringToNotificationType(jsValue ? GetProperty("type")->AsString() : "");
+}
+
+NotificationTexts Notification::GetTexts(const std::string& locale)
+{
+  JsValuePtr func = jsEngine->Evaluate("API.getNotificationTexts");
+  if (!func)
+  {
+    return NotificationTexts();
+  }
+  JsValueList params;
+  params.push_back(shared_from_this());
+  if (!locale.empty())
+  {
+    params.push_back(jsEngine->NewValue(locale));
+  }
+  auto jsTexts = func->Call(params);
+  if (!jsTexts)
+  {
+    return NotificationTexts();
+  }
+  return Notification::JsTextsToNotificationTexts(*jsTexts);
+}
+
+void Notification::SetTitle(const std::string& value, const std::string& locale)
+{
+  SetMultilingualProperty("title", value, locale);
+}
+
+void Notification::SetMessage(const std::string& value, const std::string& locale)
+{
+  SetMultilingualProperty("message", value, locale);
+}
+
+void Notification::SetMultilingualProperty(const std::string& propertyName,
+                                           const std::string& value,
+                                           const std::string& locale)
+{
+  if (locale.empty())
+  {
+    SetProperty(propertyName, value);
+  }
+  else
+  {
+    auto multilingualPropertyBag = GetProperty(propertyName);
+    if (!multilingualPropertyBag || !multilingualPropertyBag->IsObject())
+    {
+      multilingualPropertyBag = jsEngine->NewObject();
+      multilingualPropertyBag->SetProperty(locale, value);
+      SetProperty(propertyName, multilingualPropertyBag);
+    }
+    else
+    {
+      multilingualPropertyBag->SetProperty(locale, value);
+    }
+  }
+}
+
+std::vector<std::string> Notification::GetUrlFilters() const
+{
+  std::vector<std::string> retValue;
+  auto jsUrlFilters = GetProperty("urlFilters");
+  if (!jsUrlFilters || !jsUrlFilters->IsArray())
+  {
+    return retValue;
+  }
+  auto urlFiltersList = jsUrlFilters->AsList();
+  for (auto ii_urlFilter = urlFiltersList.begin(); ii_urlFilter != urlFiltersList.end(); ++ii_urlFilter)
+  {
+    if (!*ii_urlFilter)
+    {
+      continue;
+    }
+    retValue.emplace_back((*ii_urlFilter)->AsString());
+  }
+  return retValue;
+}
+
+void Notification::AddUrlFilter(const std::string& value)
+{
+  if (value.empty())
+  {
+    return;
+  }
+  auto jsFilter = jsEngine->NewValue(value);
+  auto jsUrlFilters = GetProperty("urlFilters");
+  if (jsUrlFilters && jsUrlFilters->IsArray())
+  {
+    jsUrlFilters->Push(jsFilter);
+    return;
+  }
+  jsUrlFilters = jsEngine->NewArray();
+  jsUrlFilters->Push(jsFilter);
+  SetProperty("urlFilters", jsUrlFilters);
+}
+
+Notification::Notification(const JsValuePtr& jsValue, PrivateCtrArg)
+  : JsValue(jsValue)
+{
+}
+
+std::tr1::shared_ptr<Notification> Notification::JsValueToNotification(const JsValuePtr& jsValue)
+{
+  if(!jsValue || !jsValue->IsObject())
+  {
+    return std::tr1::shared_ptr<Notification>();
+  }
+  return std::tr1::make_shared<Notification>(jsValue, PrivateCtrArg());
+}
+
+NotificationTexts Notification::JsTextsToNotificationTexts(const JsValue& jsText)
+{
+  NotificationTexts retValue;
+  auto jsTitle = jsText.GetProperty("title");
+  if (jsTitle && jsTitle->IsString())
+  {
+    retValue.title = jsTitle->AsString();
+  }
+  auto jsMessage = jsText.GetProperty("message");
+  if (jsMessage && jsMessage->IsString())
+  {
+    retValue.message = jsMessage->AsString();
+  }
+  return retValue;
+}
\ No newline at end of file
