Index: include/AdblockPlus.h
diff --git a/include/AdblockPlus.h b/include/AdblockPlus.h
index 8f9c8fea977a48d51a890ef8edaf0a82e76ba78b..f952edef4b151861bc324c91367be1ee75469ca1 100644
--- a/include/AdblockPlus.h
+++ b/include/AdblockPlus.h
@@ -41,5 +41,6 @@
 #include <AdblockPlus/JsValue.h>
 #include <AdblockPlus/ReferrerMapping.h>
 #include <AdblockPlus/WebRequest.h>
+#include "AdblockPlus/Notification.h"
 
 #endif
Index: include/AdblockPlus/FilterEngine.h
diff --git a/include/AdblockPlus/FilterEngine.h b/include/AdblockPlus/FilterEngine.h
index b81433f5c9bf1b540cf837f6df1a1662bc623454..a6fa146265620ebd4faa813689ae907955092c8c 100644
--- a/include/AdblockPlus/FilterEngine.h
+++ b/include/AdblockPlus/FilterEngine.h
@@ -24,6 +24,7 @@
 #include <vector>
 #include <AdblockPlus/JsEngine.h>
 #include <AdblockPlus/JsValue.h>
+#include <AdblockPlus/Notification.h>
 
 #include "tr1_memory.h"
 
@@ -237,6 +238,14 @@ namespace AdblockPlus
     std::vector<SubscriptionPtr> FetchAvailableSubscriptions() const;
 
     /**
+     * Determines which notification is to be shown next.
+     * @param url URL to match notifications to (optional).
+     * @return Notification to be shown, or `null` if there is no any.
+     */
+    NotificationPtr GetNextNotificationToShow(
+      const std::string& url = std::string());
+
+    /**
      * Checks if any active filter matches the supplied URL.
      * @param url URL to match.
      * @param contentType Content type of the requested resource.
Index: include/AdblockPlus/Notification.h
diff --git a/include/AdblockPlus/Notification.h b/include/AdblockPlus/Notification.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9b2b24ec28bcb5ad5d1e9bbdf1228e81e10e3f4
--- /dev/null
+++ b/include/AdblockPlus/Notification.h
@@ -0,0 +1,83 @@
+/*
+ * 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/>.
+ */
+
+#ifndef ADBLOCK_PLUS_NOTIFICATION_H
+#define ADBLOCK_PLUS_NOTIFICATION_H
+
+#include <string>
+#include <vector>
+#include "tr1_memory.h"
+
+namespace AdblockPlus
+{
+  class FilterEngine;
+  /**
+   * Possible notification types.
+   */
+  enum NotificationType
+  {
+    NOTIFICATION_TYPE_INFORMATION,
+    NOTIFICATION_TYPE_QUESTION,
+    NOTIFICATION_TYPE_CRITICAL
+  };
+
+  /**
+   * Wrapper for an Adblock Plus notification object.
+   */
+  class Notification: public JsValue
+  {
+    friend class FilterEngine;
+  protected:
+    static std::tr1::shared_ptr<Notification> JsValueToNotification(const JsValuePtr& jsValue);
+    /**
+     * Constructor.
+     * @param jsValue `JsValuePtr` notification JavaScript object.
+     */
+    explicit Notification(const JsValuePtr& jsValue);
+  public:
+    /**
+     * Retrieves the type of this notification.
+     * @return Type of this notification.
+     */
+    NotificationType GetType() const;
+
+    /**
+     * Retrieves the title of this notification.
+     * @return Title of this notification.
+     */
+    const std::string& GetTitle() const;
+
+    /**
+     * Retrieves the message of this notification.
+     * @return Message of this notification.
+     */
+    const std::string& GetMessageString() const;
+
+    /**
+     * Marks this notification as shown. It is only relevant for question
+     * notifications. Other notifications are marked automatically.
+     */
+    void MarkAsShown();
+  private:
+    std::string title;
+    std::string message;
+    NotificationType type;
+  };
+  typedef std::tr1::shared_ptr<Notification> NotificationPtr;
+}
+
+#endif
\ No newline at end of file
Index: lib/api.js
diff --git a/lib/api.js b/lib/api.js
index b294274d51ce5053485fa0eddd109e51d50cb802..03f135cd69a00513cd86162b0e4d521e83083814 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -26,6 +26,7 @@ var API = (function()
   var Synchronizer = require("synchronizer").Synchronizer;
   var Prefs = require("prefs").Prefs;
   var checkForUpdates = require("updater").checkForUpdates;
+  var Notification = require("notification").Notification;
 
   return {
     getFilterFromText: function(text)
@@ -136,6 +137,20 @@ var API = (function()
       return result;
     },
 
+    getNextNotificationToShow: function(url)
+    {
+      return Notification.getNextToShow(url);
+    },
+
+    getNotificationTexts: function(notification)
+    {
+      return Notification.getLocalizedTexts(notification);
+    },
+
+    markNotificationAsShown: function(id)
+    {
+      Notification.markAsShown(id);
+    },
     checkFilterMatch: function(url, contentType, documentUrl)
     {
       var requestHost = extractHostFromURL(url);
Index: lib/prefs.js
diff --git a/lib/prefs.js b/lib/prefs.js
index 4705ba02603ec1ce256c6b7bc3b0ea13b7be80c0..a62cb6f5ba9df2f51e3123cd45b83e5f51099346 100644
--- a/lib/prefs.js
+++ b/lib/prefs.js
@@ -39,7 +39,9 @@ let defaults = {
   update_last_error: 0,
   update_soft_expiration: 0,
   update_hard_expiration: 0,
-  currentVersion: "0.0"
+  currentVersion: "0.0",
+  notificationdata: {},
+  notificationurl: "https://notification.adblockplus.org/notification.json"
 };
 
 let values = Object.create(defaults);
Index: libadblockplus.gyp
diff --git a/libadblockplus.gyp b/libadblockplus.gyp
index 4876727006c8271da73d8f02cf56d3d175996e4f..e0ee14dcd888021703ca5ead31caff79d78b867b 100644
--- a/libadblockplus.gyp
+++ b/libadblockplus.gyp
@@ -35,6 +35,7 @@
       'src/JsEngine.cpp',
       'src/JsError.cpp',
       'src/JsValue.cpp',
+      'src/Notification.cpp',
       'src/ReferrerMapping.cpp',
       'src/Thread.cpp',
       'src/Utils.cpp',
@@ -106,6 +107,7 @@
           'adblockplus/lib/matcher.js',
           'adblockplus/lib/filterListener.js',
           'adblockplus/lib/downloader.js',
+          'adblockplus/lib/notification.js',
           'adblockplus/lib/synchronizer.js',
           'lib/filterUpdateRegistration.js',
           'adblockplus/chrome/content/ui/subscriptions.xml',
@@ -156,6 +158,7 @@
       'test/GlobalJsObject.cpp',
       'test/JsEngine.cpp',
       'test/JsValue.cpp',
+      'test/Notification.cpp',
       'test/Prefs.cpp',
       'test/ReferrerMapping.cpp',
       'test/Thread.cpp',
Index: src/FilterEngine.cpp
diff --git a/src/FilterEngine.cpp b/src/FilterEngine.cpp
index 3d4770dfe98ca93df67a5bbdcd97d3cf551996e0..96c4571fbf593f47041bd3415fc44d73f55da7f1 100644
--- a/src/FilterEngine.cpp
+++ b/src/FilterEngine.cpp
@@ -257,6 +257,17 @@ std::vector<SubscriptionPtr> FilterEngine::FetchAvailableSubscriptions() const
   return result;
 }
 
+NotificationPtr FilterEngine::GetNextNotificationToShow(const std::string& url)
+{
+  JsValuePtr func = jsEngine->Evaluate("API.getNextNotificationToShow");
+  JsValueList params;
+  if (!url.empty())
+  {
+    params.push_back(jsEngine->NewValue(url));
+  }
+  return Notification::JsValueToNotification(func->Call(params));
+}
+
 AdblockPlus::FilterPtr FilterEngine::Matches(const std::string& url,
     ContentType contentType,
     const std::string& documentUrl) const
Index: src/Notification.cpp
diff --git a/src/Notification.cpp b/src/Notification.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0791f3db86d0464c162812bce203f6fb9a03f0ca
--- /dev/null
+++ b/src/Notification.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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;
+  NotificationTypes InitNotificationTypes()
+  {
+    NotificationTypes retValue;
+    retValue.push_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_QUESTION, "question"));
+    retValue.push_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_CRITICAL, "critical"));
+    retValue.push_back(std::make_pair(NotificationType::NOTIFICATION_TYPE_INFORMATION, "information"));
+    return retValue;
+  }
+
+  const NotificationTypes notificationTypes = InitNotificationTypes();
+
+  NotificationType StringToNotificationType(const std::string& value)
+  {
+    struct IsSecondEqualToPredicate
+    {
+      std::string value;
+      bool operator()(const NotificationTypeString& pair) const
+      {
+        return value == pair.second;
+      }
+    } findBySecond = {value};
+    NotificationTypes::const_iterator notificationTypeIterator = std::find_if(
+      notificationTypes.begin(), notificationTypes.end(), findBySecond);
+    if (notificationTypeIterator == notificationTypes.end())
+    {
+      return NotificationType::NOTIFICATION_TYPE_INFORMATION;
+    }
+    return notificationTypeIterator->first;
+  }
+}
+
+Notification::Notification(const JsValuePtr& jsValue)
+  : JsValue(jsValue)
+{
+}
+
+NotificationType Notification::GetType() const
+{
+  return type;
+}
+
+const std::string& Notification::GetTitle() const
+{
+  return title;
+}
+
+const std::string& Notification::GetMessageString() const
+{
+  return message;
+}
+
+void Notification::MarkAsShown()
+{
+  JsValueList params;
+  params.push_back(GetProperty("id"));
+  jsEngine->Evaluate("API.markNotificationAsShown")->Call(params);
+}
+
+NotificationPtr Notification::JsValueToNotification(const JsValuePtr& jsValue)
+{
+  if (!jsValue || !jsValue->IsObject())
+  {
+    return NotificationPtr();
+  }
+
+  NotificationPtr notification(new Notification(jsValue));
+  JsValuePtr jsType = notification->GetProperty("type");
+  notification->type = StringToNotificationType(jsType ? jsType->AsString() : "");
+
+  JsValueList params;
+  params.push_back(notification);
+  JsValuePtr func = notification->jsEngine->Evaluate("API.getNotificationTexts");
+  JsValuePtr jsTexts = func->Call(params);
+  JsValuePtr jsTitle = jsTexts->GetProperty("title");
+  if (jsTitle->IsString())
+  {
+    notification->title = jsTitle->AsString();
+  }
+  JsValuePtr jsMessage = jsTexts->GetProperty("message");
+  if (jsMessage->IsString())
+  {
+    notification->message = jsMessage->AsString();
+  }
+  return notification;
+}
\ No newline at end of file
Index: test/Notification.cpp
diff --git a/test/Notification.cpp b/test/Notification.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59d6e3cdf10d87f4ec33d65154c885b6cd60f19e
--- /dev/null
+++ b/test/Notification.cpp
@@ -0,0 +1,169 @@
+/*
+ * 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 "BaseJsTest.h"
+
+using namespace AdblockPlus;
+
+// This define enables NotificationMockWebRequestTest but to run it
+// one need to set INITIAL_DELAY to about 2000 msec in notification.js.
+//#define NotificationMockWebRequestTest_ENABLED
+
+namespace
+{
+  typedef std::tr1::shared_ptr<FilterEngine> FilterEnginePtr;
+
+  class NotificationTest : public BaseJsTest
+  {
+  protected:
+    FilterEnginePtr filterEngine;
+    void SetUp() override
+    {
+      BaseJsTest::SetUp();
+      jsEngine->SetFileSystem(FileSystemPtr(new LazyFileSystem()));
+      jsEngine->SetWebRequest(WebRequestPtr(new LazyWebRequest()));
+      jsEngine->SetLogSystem(LogSystemPtr(new DefaultLogSystem()));
+      filterEngine = std::tr1::make_shared<FilterEngine>(jsEngine);
+    }
+
+    void AddNotification(const std::string& notification)
+    {
+      jsEngine->Evaluate("(function()"
+      "{"
+        "require('notification').Notification.addNotification(" + notification + ");"
+      "})();");
+    }
+  };
+
+  class MockWebRequest : public WebRequest
+  {
+  public:
+    std::string responseText;
+    explicit MockWebRequest(const std::string& notification)
+      : responseText(notification)
+    {
+    }
+    ServerResponse GET(const std::string& url,
+      const HeaderList& requestHeaders) const
+    {
+      if (url.find("/notification.json") == std::string::npos)
+      {
+        return ServerResponse();
+      }
+      ServerResponse serverResponse;
+      serverResponse.status = NS_OK;
+      serverResponse.responseStatus = 200;
+      serverResponse.responseText = responseText;
+      return serverResponse;
+    }
+  };
+
+#ifdef NotificationMockWebRequestTest_ENABLED
+  class NotificationMockWebRequestTest : public BaseJsTest
+  {
+  protected:
+    FilterEnginePtr filterEngine;
+    void SetUp() override
+    {
+      BaseJsTest::SetUp();
+      jsEngine->SetFileSystem(std::tr1::make_shared<LazyFileSystem>());
+      const char* responseJsonText = "{"
+        "\"notifications\": [{"
+          "\"id\": \"some id\","
+          "\"type\": \"information\","
+          "\"message\": {"
+             "\"en-US\": \"message\""
+          "},"
+          "\"title\": \"Title\""
+        "}]"
+        "}";
+      jsEngine->SetWebRequest(std::tr1::make_shared<MockWebRequest>(responseJsonText));
+      jsEngine->SetLogSystem(LogSystemPtr(new DefaultLogSystem()));
+      filterEngine = std::tr1::make_shared<FilterEngine>(jsEngine);
+    }
+  };
+#endif
+}
+
+TEST_F(NotificationTest, NoNotifications)
+{
+  NotificationPtr notification = filterEngine->GetNextNotificationToShow();
+  EXPECT_EQ(NULL, notification.get());
+}
+
+#ifdef NotificationMockWebRequestTest_ENABLED
+TEST_F(NotificationMockWebRequestTest, SingleNotification)
+{
+  AdblockPlus::Sleep(5000/*msec*/); // it's a hack
+  NotificationPtr notification = filterEngine->GetNextNotificationToShow();
+  // try another one immediately to avoid queuing of the next notification by
+  // the timer.
+  EXPECT_EQ(NULL, filterEngine->GetNextNotificationToShow().get());
+  ASSERT_TRUE(notification);
+  EXPECT_EQ(NotificationType::NOTIFICATION_TYPE_INFORMATION, notification->GetType());
+  EXPECT_EQ("Title", notification->GetTitle());
+  EXPECT_EQ("message", notification->GetMessageString());
+}
+#endif
+
+TEST_F(NotificationTest, AddNotification)
+{
+  AddNotification("{"
+      "type: 'critical',"
+      "title: 'testTitle',"
+      "message: 'testMessage',"
+    "}");
+  NotificationPtr notification = filterEngine->GetNextNotificationToShow();
+  ASSERT_TRUE(notification);
+  EXPECT_EQ(NotificationType::NOTIFICATION_TYPE_CRITICAL, notification->GetType());
+  EXPECT_EQ("testTitle", notification->GetTitle());
+  EXPECT_EQ("testMessage", notification->GetMessageString());
+}
+
+TEST_F(NotificationTest, FilterByUrl)
+{
+  AddNotification("{ id: 'no-filter', type: 'critical' }");
+  AddNotification("{ id: 'www.com', type: 'information',"
+    "urlFilters:['http://www.com']"
+  "}");
+  AddNotification("{ id: 'www.de', type: 'question',"
+    "urlFilters:['http://www.de']"
+  "}");
+
+  NotificationPtr notification = filterEngine->GetNextNotificationToShow();
+  ASSERT_TRUE(notification);
+  EXPECT_EQ(NotificationType::NOTIFICATION_TYPE_CRITICAL, notification->GetType());
+
+  notification = filterEngine->GetNextNotificationToShow("http://www.de");
+  ASSERT_TRUE(notification);
+  EXPECT_EQ(NotificationType::NOTIFICATION_TYPE_QUESTION, notification->GetType());
+
+  notification = filterEngine->GetNextNotificationToShow("http://www.com");
+  ASSERT_TRUE(notification);
+  EXPECT_EQ(NotificationType::NOTIFICATION_TYPE_INFORMATION, notification->GetType());
+}
+
+TEST_F(NotificationTest, MarkAsShown)
+{
+  AddNotification("{ id: 'id', type: 'question' }");
+  NotificationPtr notification = filterEngine->GetNextNotificationToShow();
+  EXPECT_TRUE(notification);
+  notification = filterEngine->GetNextNotificationToShow();
+  ASSERT_TRUE(notification);
+  notification->MarkAsShown();
+  EXPECT_EQ(NULL, filterEngine->GetNextNotificationToShow().get());
+}
\ No newline at end of file
