diff --git a/core/core.services.yml b/core/core.services.yml
index 2d00da1..b6dd9e1 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -971,6 +971,9 @@ services:
   plugin.manager.mail:
     class: Drupal\Core\Mail\MailManager
     arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@config.factory', '@logger.factory', '@string_translation']
+  plugin.manager.event:
+    class: Drupal\Core\Condition\EventManager
+    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@context.handler']
   plugin.manager.condition:
     class: Drupal\Core\Condition\ConditionManager
     parent: default_plugin_manager
diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
index b684630..4072c90 100644
--- a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
@@ -7,139 +7,11 @@
 
 namespace Drupal\Component\Plugin;
 
-use Drupal\Component\Plugin\Context\ContextInterface;
-use Drupal\Component\Plugin\Exception\ContextException;
-use Drupal\Component\Plugin\Context\Context;
-use Symfony\Component\Validator\ConstraintViolationList;
-
 /**
  * Base class for plugins that are context aware.
  */
 abstract class ContextAwarePluginBase extends PluginBase implements ContextAwarePluginInterface {
 
-  /**
-   * The data objects representing the context of this plugin.
-   *
-   * @var \Drupal\Component\Plugin\Context\ContextInterface[]
-   */
-  protected $context;
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
-   *
-   * Overrides the construction of context aware plugins to allow for
-   * unvalidated constructor based injection of contexts.
-   *
-   * @param array $configuration
-   *   The plugin configuration, i.e. an array with configuration values keyed
-   *   by configuration option name. The special key 'context' may be used to
-   *   initialize the defined contexts by setting it to an array of context
-   *   values keyed by context names.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
-    $context = array();
-    if (isset($configuration['context'])) {
-      $context = $configuration['context'];
-      unset($configuration['context']);
-    }
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    foreach ($context as $key => $value) {
-      $context_definition = $this->getContextDefinition($key);
-      $this->context[$key] = new Context($context_definition);
-      $this->context[$key]->setContextValue($value);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContextDefinitions() {
-    $definition = $this->getPluginDefinition();
-    return !empty($definition['context']) ? $definition['context'] : array();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContextDefinition($name) {
-    $definition = $this->getPluginDefinition();
-    if (empty($definition['context'][$name])) {
-      throw new ContextException(sprintf("The %s context is not a valid context.", $name));
-    }
-    return $definition['context'][$name];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContexts() {
-    // Make sure all context objects are initialized.
-    foreach ($this->getContextDefinitions() as $name => $definition) {
-      $this->getContext($name);
-    }
-    return $this->context;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($name) {
-    // Check for a valid context value.
-    if (!isset($this->context[$name])) {
-      $this->context[$name] = new Context($this->getContextDefinition($name));
-    }
-    return $this->context[$name];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContext($name, ContextInterface $context) {
-    $this->context[$name] = $context;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContextValues() {
-    $values = array();
-    foreach ($this->getContextDefinitions() as $name => $definition) {
-      $values[$name] = isset($this->context[$name]) ? $this->context[$name]->getContextValue() : NULL;
-    }
-    return $values;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContextValue($name) {
-    return $this->getContext($name)->getContextValue();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContextValue($name, $value) {
-    $this->getContext($name)->setContextValue($value);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateContexts() {
-    $violations = new ConstraintViolationList();
-    // @todo: Implement symfony validator API to let the validator traverse
-    // and set property paths accordingly.
-
-    foreach ($this->getContexts() as $context) {
-      $violations->addAll($context->validate());
-    }
-    return $violations;
-  }
+  use ContextAwarePluginTrait;
 
 }
diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginTrait.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginTrait.php
new file mode 100644
index 0000000..d0547b1
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginTrait.php
@@ -0,0 +1,149 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\ContextAwarePluginBase
+ */
+
+namespace Drupal\Component\Plugin;
+
+use Drupal\Component\Plugin\Context\ContextInterface;
+use Drupal\Component\Plugin\Exception\ContextException;
+use Drupal\Component\Plugin\Context\Context;
+use Symfony\Component\Validator\ConstraintViolationList;
+
+/**
+ * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface.
+ */
+trait ContextAwarePluginTrait {
+
+  /**
+   * The data objects representing the context of this plugin.
+   *
+   * @var \Drupal\Component\Plugin\Context\ContextInterface[]
+   */
+  protected $context;
+
+  /**
+   * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
+   *
+   * Overrides the construction of context aware plugins to allow for
+   * unvalidated constructor based injection of contexts.
+   *
+   * @param array $configuration
+   *   The plugin configuration, i.e. an array with configuration values keyed
+   *   by configuration option name. The special key 'context' may be used to
+   *   initialize the defined contexts by setting it to an array of context
+   *   values keyed by context names.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
+    $context = array();
+    if (isset($configuration['context'])) {
+      $context = $configuration['context'];
+      unset($configuration['context']);
+    }
+    $this->configuration = $configuration;
+    $this->pluginId = $plugin_id;
+    $this->pluginDefinition = $plugin_definition;
+    foreach ($context as $key => $value) {
+      $context_definition = $this->getContextDefinition($key);
+      $this->context[$key] = new Context($context_definition);
+      $this->context[$key]->setContextValue($value);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextDefinitions() {
+    /** @var \Drupal\Component\Plugin\ContextAwarePluginInterface $this */
+    $definition = $this->getPluginDefinition();
+    return !empty($definition['context']) ? $definition['context'] : array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextDefinition($name) {
+    /** @var \Drupal\Component\Plugin\ContextAwarePluginInterface $this */
+    $definition = $this->getPluginDefinition();
+    if (empty($definition['context'][$name])) {
+      throw new ContextException(sprintf("The %s context is not a valid context.", $name));
+    }
+    return $definition['context'][$name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContexts() {
+    // Make sure all context objects are initialized.
+    foreach ($this->getContextDefinitions() as $name => $definition) {
+      $this->getContext($name);
+    }
+    return $this->context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext($name) {
+    // Check for a valid context value.
+    if (!isset($this->context[$name])) {
+      $this->context[$name] = new Context($this->getContextDefinition($name));
+    }
+    return $this->context[$name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContext($name, ContextInterface $context) {
+    $this->context[$name] = $context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextValues() {
+    $values = array();
+    foreach ($this->getContextDefinitions() as $name => $definition) {
+      $values[$name] = isset($this->context[$name]) ? $this->context[$name]->getContextValue() : NULL;
+    }
+    return $values;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextValue($name) {
+    return $this->getContext($name)->getContextValue();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContextValue($name, $value) {
+    $this->getContext($name)->setContextValue($value);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateContexts() {
+    $violations = new ConstraintViolationList();
+    // @todo: Implement symfony validator API to let the validator traverse
+    // and set property paths accordingly.
+
+    foreach ($this->getContexts() as $context) {
+      $violations->addAll($context->validate());
+    }
+    return $violations;
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/PluginBase.php b/core/lib/Drupal/Component/Plugin/PluginBase.php
index aeff157..39e283d 100644
--- a/core/lib/Drupal/Component/Plugin/PluginBase.php
+++ b/core/lib/Drupal/Component/Plugin/PluginBase.php
@@ -11,89 +11,6 @@
  */
 abstract class PluginBase implements PluginInspectionInterface, DerivativeInspectionInterface {
 
-  /**
-   * A string which is used to separate base plugin IDs from the derivative ID.
-   */
-  const DERIVATIVE_SEPARATOR = ':';
+  use PluginTrait;
 
-  /**
-   * The plugin_id.
-   *
-   * @var string
-   */
-  protected $pluginId;
-
-  /**
-   * The plugin implementation definition.
-   *
-   * @var array
-   */
-  protected $pluginDefinition;
-
-  /**
-   * Configuration information passed into the plugin.
-   *
-   * When using an interface like
-   * \Drupal\Component\Plugin\ConfigurablePluginInterface, this is where the
-   * configuration should be stored.
-   *
-   * Plugin configuration is optional, so plugin implementations must provide
-   * their own setters and getters.
-   *
-   * @var array
-   */
-  protected $configuration;
-
-  /**
-   * Constructs a Drupal\Component\Plugin\PluginBase object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
-    $this->configuration = $configuration;
-    $this->pluginId = $plugin_id;
-    $this->pluginDefinition = $plugin_definition;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPluginId() {
-    return $this->pluginId;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getBaseId() {
-    $plugin_id = $this->getPluginId();
-    if (strpos($plugin_id, static::DERIVATIVE_SEPARATOR)) {
-      list($plugin_id) = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 2);
-    }
-    return $plugin_id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDerivativeId() {
-    $plugin_id = $this->getPluginId();
-    $derivative_id = NULL;
-    if (strpos($plugin_id, static::DERIVATIVE_SEPARATOR)) {
-      list(, $derivative_id) = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 2);
-    }
-    return $derivative_id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPluginDefinition() {
-    return $this->pluginDefinition;
-  }
 }
diff --git a/core/lib/Drupal/Component/Plugin/PluginTrait.php b/core/lib/Drupal/Component/Plugin/PluginTrait.php
new file mode 100644
index 0000000..6661186
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/PluginTrait.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\PluginTrait.
+ */
+
+namespace Drupal\Component\Plugin;
+
+/**
+ * Provides a base for plugins wishing to support metadata inspection.
+ */
+trait PluginTrait {
+
+  /**
+   * The plugin_id.
+   *
+   * @var string
+   */
+  protected $pluginId;
+
+  /**
+   * The plugin implementation definition.
+   *
+   * @var array
+   */
+  protected $pluginDefinition;
+
+  /**
+   * Configuration information passed into the plugin.
+   *
+   * When using an interface like
+   * \Drupal\Component\Plugin\ConfigurablePluginInterface, this is where the
+   * configuration should be stored.
+   *
+   * Plugin configuration is optional, so plugin implementations must provide
+   * their own setters and getters.
+   *
+   * @var array
+   */
+  protected $configuration;
+
+  /**
+   * Constructs a Drupal\Component\Plugin\PluginBase object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
+    $this->configuration = $configuration;
+    $this->pluginId = $plugin_id;
+    $this->pluginDefinition = $plugin_definition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPluginId() {
+    return $this->pluginId;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBaseId() {
+    $plugin_id = $this->getPluginId();
+    if (strpos($plugin_id, $this->getDerivativeSeparator())) {
+      list($plugin_id) = explode($this->getDerivativeSeparator(), $plugin_id, 2);
+    }
+    return $plugin_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeId() {
+    $plugin_id = $this->getPluginId();
+    $derivative_id = NULL;
+    if (strpos($plugin_id, $this->getDerivativeSeparator())) {
+      list(, $derivative_id) = explode($this->getDerivativeSeparator(), $plugin_id, 2);
+    }
+    return $derivative_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPluginDefinition() {
+    return $this->pluginDefinition;
+  }
+
+  /**
+   * Gets the separator of base plugin IDs and derivative plugin IDs.
+   *
+   * @return string
+   */
+  protected function getDerivativeSeparator() {
+    return ':';
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Event/Annotation/Event.php b/core/lib/Drupal/Core/Event/Annotation/Event.php
new file mode 100644
index 0000000..1e3e21d
--- /dev/null
+++ b/core/lib/Drupal/Core/Event/Annotation/Event.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Core\Condition\Annotation\Condition.
+ */
+
+namespace Drupal\Core\Event\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Provides an annotation for event plugins.
+ *
+ * @see \Drupal\Core\Event\EventInterface
+ *
+ * @ingroup plugin_api
+ *
+ * @Annotation
+ */
+class Event extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The human-readable plugin label.
+   *
+   * @ingroup plugin_translatable
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   */
+  public $label;
+
+  /**
+   * The human-readable plugin description.
+   *
+   * @ingroup plugin_translatable
+   *
+   * @var \Drupal\Core\Annotation\Translation|null
+   */
+  public $description;
+
+  /**
+   * The name of the module providing the plugin.
+   *
+   * @var string
+   */
+  public $module;
+
+}
diff --git a/core/lib/Drupal/Core/Event/EventBase.php b/core/lib/Drupal/Core/Event/EventBase.php
new file mode 100644
index 0000000..6b30068
--- /dev/null
+++ b/core/lib/Drupal/Core/Event/EventBase.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Event\EventBase.
+ */
+
+namespace Drupal\Core\Event;
+
+use Drupal\Component\Plugin\ContextAwarePluginTrait;
+use Drupal\Component\Plugin\PluginTrait;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Provides a base event plugin.
+ *
+ * @see \Drupal\Core\Event\Annotation\Event
+ * @see \Drupal\Core\Event\EventInterface
+ *
+ * @ingroup plugin_api
+ */
+abstract class EventBase extends Event implements EventInterface {
+
+  use ContextAwarePluginTrait;
+  use PluginTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Event/EventInterface.php b/core/lib/Drupal/Core/Event/EventInterface.php
new file mode 100644
index 0000000..5dc8e69
--- /dev/null
+++ b/core/lib/Drupal/Core/Event/EventInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Event\EventInterface.
+ */
+
+namespace Drupal\Core\Event;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+
+/**
+ * Defines an event plugin.
+ *
+ * @see \Drupal\Core\Event\Annotation\Event
+ * @see \Drupal\Core\Event\EventBase
+ *
+ * @ingroup plugin_api
+ */
+interface EventInterface extends ContextAwarePluginInterface, PluginInspectionInterface {
+}
diff --git a/core/lib/Drupal/Core/Event/EventManager.php b/core/lib/Drupal/Core/Event/EventManager.php
new file mode 100644
index 0000000..521bf17
--- /dev/null
+++ b/core/lib/Drupal/Core/Event/EventManager.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Event\EventManager.
+ */
+
+namespace Drupal\Core\Event;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\Context\ContextHandlerInterface;
+use Drupal\Core\Plugin\DefaultPluginManager;
+
+/**
+ * Provides a plugin manager for event plugins.
+ *
+ * @see \Drupal\Core\Event\Annotation\Event
+ * @see \Drupal\Core\Event\EventInterface
+ * @see \Drupal\Core\Event\EventBase
+ *
+ * @ingroup plugin_api
+ */
+class EventManager extends DefaultPluginManager implements EventManagerInterface {
+
+  /**
+   * The context handler.
+   *
+   * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
+   */
+  protected $contextHandler;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke the alter hook with.
+   * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
+   *   The context handler.
+   */
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ContextHandlerInterface $context_handler) {
+    $this->alterInfo('condition_info');
+    $this->setCacheBackend($cache_backend, 'condition_plugins');
+    $this->contextHandler = $context_handler;
+
+    parent::__construct('Plugin/Condition', $namespaces, $module_handler, 'Drupal\Core\Condition\ConditionInterface', 'Drupal\Core\Condition\Annotation\Condition');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createInstance($plugin_id, array $configuration = array()) {
+    $plugin = $this->factory->createInstance($plugin_id, $configuration);
+
+    // If we receive any context values via config set it into the plugin.
+    if (!empty($configuration['context'])) {
+      foreach ($configuration['context'] as $name => $context) {
+        $plugin->setContextValue($name, $context);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinitionsForContexts(array $contexts = array()) {
+    return $this->contextHandler->filterPluginDefinitionsByContexts($contexts, $this->getDefinitions());
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Event/EventManagerInterface.php b/core/lib/Drupal/Core/Event/EventManagerInterface.php
new file mode 100644
index 0000000..51cfdda
--- /dev/null
+++ b/core/lib/Drupal/Core/Event/EventManagerInterface.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\PluginManagerInterface
+ */
+
+namespace Drupal\Core\Event;
+
+use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Core\Plugin\Context\ContextAwarePluginManagerInterface;
+
+/**
+ * Defines an event plugin manager.
+ *
+ * @ingroup plugin_api
+ */
+interface EventManagerInterface extends PluginManagerInterface, ContextAwarePluginManagerInterface {
+}
