diff --git a/core/lib/Drupal/Component/Plugin/Context/Context.php b/core/lib/Drupal/Component/Plugin/Context/Context.php
new file mode 100644
index 0000000000000000000000000000000000000000..9f4396b62371ce908b1955d89a9145144596fa4d
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Context/Context.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\Context\Context.
+ */
+
+namespace Drupal\Component\Plugin\Context;
+
+use Drupal\Component\Plugin\Exception\ContextException;
+
+/**
+ * A generic context class for wrapping data a plugin needs to operate.
+ */
+class Context implements ContextInterface {
+
+  /**
+   * The value of the context.
+   *
+   * @var mixed
+   */
+  protected $contextValue;
+
+  /**
+   * The definition to which a context must conform.
+   *
+   * @var array
+   */
+  protected $contextDefinition;
+
+  /**
+   * Sets the contextDefinition for us without needing to call the setter.
+   */
+  public function __construct(array $context_definition) {
+    $this->contextDefinition = $context_definition;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\Context\ContextInterface::setContextValue().
+   */
+  public function setContextValue($value) {
+    $value = $this->validate($value);
+    $this->contextValue = $value;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\Context\ContextInterface::getContextValue().
+   */
+  public function getContextValue() {
+    return $this->contextValue;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\Context\ContextInterface::setContextDefinition().
+   */
+  public function setContextDefinition(array $context_definition) {
+    $this->contextDefinition = $context_definition;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\Context\ContextInterface::getContextDefinition().
+   */
+  public function getContextDefinition() {
+    return $this->contextDefinition;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\Context\ContextInterface::validate().
+   *
+   * The default validation method only supports instance of checks between the
+   * contextDefintion and the contextValue. Other formats of context
+   * definitions can be supported through a subclass.
+   */
+  public function validate($value) {
+    // Check to make sure we have a class name, and that the passed context is
+    // an instance of that class name.
+    if (!empty($this->contextDefinition['class'])) {
+      if ($value instanceof $this->contextDefinition['class']) {
+        return $value;
+      }
+      throw new ContextException("The context passed was not an instance of {$this->contextDefinition['class']}.");
+    }
+    throw new ContextException("An error was encountered while trying to validate the context.");
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php b/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c4373dff0249a8df833b97657045880936d8494
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\Context\ContextInterface.
+ */
+
+namespace Drupal\Component\Plugin\Context;
+
+use Drupal\Component\Plugin\Exception\ContextException;
+
+/**
+ * A generic context interface for wrapping data a plugin needs to operate.
+ */
+interface ContextInterface {
+
+  /**
+   * Sets the context value.
+   *
+   * @param mixed $value
+   *   The value of this context, generally an object based upon the class
+   *   matching the definition passed to setContextDefinition().
+   */
+  public function setContextValue($value);
+
+  /**
+   * Gets the context value.
+   *
+   * @return mixed
+   *   The currently set context value within this class.
+   */
+  public function getContextValue();
+
+  /**
+   * Sets the definition that the context must conform to.
+   *
+   * @param mixed $contextDefinition
+   *   A defining characteristic representation of the context against which
+   *   that context can be validated. This is typically a class name, but could
+   *   be extended to support other validation notation.
+   */
+  public function setContextDefinition(array $contextDefinition);
+
+  /**
+   * Gets the provided definition that the context must conform to.
+   *
+   * @return mixed
+   *   The defining characteristic representation of the context.
+   */
+  public function getContextDefinition();
+
+  /**
+   * Validate the provided context value against the provided definition.
+   *
+   * @param mixed $value
+   *   The context value that should be validated against the context
+   *   definition.
+   *
+   * @return mixed
+   *   Returns the context value passed to it. If it fails validation, an
+   *   exception will be thrown.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\ContextException
+   *   If validation fails.
+   */
+  public function validate($value);
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..a628f99d2b5dd4067b43708fc1a4b99902182b96
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\ContextAwarePluginBase
+ */
+
+namespace Drupal\Component\Plugin;
+
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Plugin\Context\Context;
+
+/**
+ * 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 array
+   */
+  protected $context;
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinitions().
+   */
+  public function getContextDefinitions() {
+    $definition = $this->getDefinition();
+    return !empty($definition['context']) ? $definition['context'] : NULL;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinition().
+   */
+  public function getContextDefinition($key) {
+    $definition = $this->getDefinition();
+    if (empty($definition['context'][$key])) {
+      throw new PluginException("The $key context is not a valid context.");
+    }
+    return $definition['context'][$key];
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContexts().
+   */
+  public function getContexts() {
+    $definitions = $this->getContextDefinitions();
+    // If there are no contexts defined by the plugin, return an empty array.
+    if (empty($definitions)) {
+      return array();
+    }
+    if (empty($this->context)) {
+      throw new PluginException("There are no set contexts.");
+    }
+    $contexts = array();
+    foreach (array_keys($definitions) as $key) {
+      if (empty($this->context[$key])) {
+        throw new PluginException("The $key context is not yet set.");
+      }
+      $contexts[$key] = $this->context[$key];
+    }
+    return $contexts;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContext().
+   */
+  public function getContext($key) {
+    // Check for a valid context definition.
+    $this->getContextDefinition($key);
+    // Check for a valid context value.
+    if (empty($this->context[$key])) {
+      throw new PluginException("The $key context is not yet set.");
+    }
+
+    return $this->context[$key];
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValues().
+   */
+  public function getContextValues() {
+    $contexts = array();
+    foreach ($this->getContexts() as $key => $context) {
+      $contexts[$key] = $context->getContextValue();
+    }
+    return $contexts;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValue().
+   */
+  public function getContextValue($key) {
+    return $this->getContext($key)->getContextValue();
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::setContextValue().
+   */
+  public function setContextValue($key, $value) {
+    $context_definition = $this->getContextDefinition($key);
+    $this->context[$key] = new Context($context_definition);
+    $this->context[$key]->setContextValue($value);
+
+    return $this;
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..68d8012e319bdafa0b0b87b884f6183e8c3e81a1
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\ContextAwarePluginInterface.
+ */
+
+namespace Drupal\Component\Plugin;
+
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Plugin\Context\Context;
+
+/**
+ * Interface for defining context aware plugins.
+ */
+interface ContextAwarePluginInterface extends PluginInspectionInterface {
+
+  /**
+   * Gets the context definitions of the plugin.
+   *
+   * @return array|null
+   *   The context definitions if set, otherwise NULL.
+   */
+  public function getContextDefinitions();
+
+  /**
+   * Gets the a specific context definition of the plugin.
+   *
+   * @param string $key
+   *   The name of the context in the plugin definition.
+   *
+   * @return mixed
+   *   The definition against which the context value must validate.
+   */
+  public function getContextDefinition($key);
+
+  /**
+   * Gets the defined contexts.
+   *
+   * @return array
+   *   The set context objects.
+   */
+  public function getContexts();
+
+  /**
+   * Gets a defined context.
+   *
+   * @param string $key
+   *   The name of the context in the plugin configuration. This string is
+   *   usually identical to the representative string in the plugin definition.
+   *
+   * @return \Drupal\Component\Plugin\Context\ContextInterface
+   *   The context object.
+   */
+  public function getContext($key);
+
+  /**
+   * Gets the values for all defined contexts.
+   *
+   * @return array
+   *   The set context object values.
+   */
+  public function getContextValues();
+
+  /**
+   * Gets the value for a defined context.
+   *
+   * @param string $key
+   *   The name of the context in the plugin configuration. This string is
+   *   usually identical to the representative string in the plugin definition.
+   *
+   * @return mixed
+   *   The currently set context value.
+   */
+  public function getContextValue($key);
+
+  /**
+   * Sets the value for a defined context.
+   *
+   * @param string $key
+   *   The name of the context in the plugin definition.
+   * @param mixed $value
+   *   The variable to set the context to. This should validate against the
+   *   provided context definition.
+   *
+   * @return \Drupal\Component\Plugin\ContextAwarePluginInterface.
+   *   A context aware plugin object for chaining.
+   */
+  public function setContextValue($key, $value);
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Exception/ContextException.php b/core/lib/Drupal/Component/Plugin/Exception/ContextException.php
new file mode 100644
index 0000000000000000000000000000000000000000..061825118de75b5e168c0c6cb95ce0a5ff8ca525
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Exception/ContextException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\Exception\ContextException.
+ */
+
+namespace Drupal\Component\Plugin\Exception;
+
+use Exception;
+
+/**
+ * An exception class to be thrown for context plugin exceptions.
+ */
+class ContextException extends Exception implements ExceptionInterface { }
diff --git a/core/lib/Drupal/Core/Plugin/Context/Context.php b/core/lib/Drupal/Core/Plugin/Context/Context.php
new file mode 100644
index 0000000000000000000000000000000000000000..bcab7e1871bad928f1625395180e4c2c9c7317c2
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Context/Context.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Plugin\Context\Context.
+ */
+
+namespace Drupal\Core\Plugin\Context;
+
+use Drupal\Component\Plugin\Context\Context as ComponentContext;
+use Drupal\Component\Plugin\Exception\ContextException;
+use Drupal\Core\TypedData\TypedDataManager;
+use Drupal\Core\TypedData\TypedDataInterface;
+
+/**
+ * A Drupal specific context wrapper class.
+ *
+ * The validate method is specifically overridden in order to support typed
+ * data definitions instead of just class names in the contextual definitions
+ * of plugins that extend ContextualPluginBase.
+ */
+class Context extends ComponentContext {
+
+  /**
+   * Overrides \Drupal\Component\Plugin\Context\Context::getContextValue().
+   */
+  public function getContextValue() {
+    $typed_value = parent::getContextValue();
+    // If the data is of a primitive type, directly return the plain value.
+    // That way, e.g. a string will be return as plain PHP string.
+    if ($typed_value instanceof \Drupal\Core\TypedData\TypedDataInterface) {
+      $type_definition = typed_data()->getDefinition($typed_value->getType());
+      if (!empty($type_definition['primitive type'])) {
+        return $typed_value->getValue();
+      }
+    }
+    return $typed_value;
+  }
+
+  /**
+   * Gets the context value as typed data object.
+   *
+   * parent::getContextValue() does not do all the processing required to
+   * return plain value of a TypedData object. This class overrides that method
+   * to return the appropriate values from TypedData objects, but the object
+   * itself can be useful as well, so this method is provided to allow for
+   * access to the TypedData object. Since parent::getContextValue() already
+   * does all the processing we need, we simply proxy to it here.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   */
+  public function getTypedContext() {
+    return parent::getContextValue();
+  }
+
+  /**
+   * Override for \Drupal\Component\Plugin\Context\Context::validate().
+   */
+  public function validate($value) {
+    if (!empty($this->contextDefinition['type'])) {
+      $typed_data_manager = new TypedDataManager();
+      $typed_data = $typed_data_manager->create($this->contextDefinition, $value);
+      // If we do have a typed data definition, validate it and return the
+      // typed data instance instead.
+      $violations = $typed_data->validate();
+      if (count($violations) == 0) {
+        return $typed_data;
+      }
+      throw new ContextException("The context passed could not be validated through typed data.");
+    }
+    return parent::validate($value);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..028befde28b602f654e7992905e9788dafb3dae5
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Plugin\ContextAwarePluginBase
+ */
+
+namespace Drupal\Core\Plugin;
+
+use Drupal\Component\Plugin\ContextAwarePluginBase as PluginBase;
+use Drupal\Core\Plugin\Context\Context;
+
+/**
+ * Drupal specific class for plugins that use context.
+ *
+ * This class specifically overrides setContextValue to use the core version of
+ * the Context class. This code is exactly the same as what is in Component
+ * ContextAwarePluginBase but it is using a different Context class.
+ */
+abstract class ContextAwarePluginBase extends PluginBase {
+
+  /**
+   * Override of \Drupal\Component\Plugin\ContextAwarePluginBase::setContextValue().
+   */
+  public function setContextValue($key, $value) {
+    $context_definition = $this->getContextDefinition($key);
+    $this->context[$key] = new Context($context_definition);
+    $this->context[$key]->setContextValue($value);
+
+    return $this;
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..888f1e66149aaf8d940ed8045f377948c57b6e8c
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php
@@ -0,0 +1,203 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Plugin\ContextPluginTest.
+ */
+
+namespace Drupal\system\Tests\Plugin;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+use Drupal\plugin_test\Plugin\MockBlockManager;
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Plugin\Exception\ContextException;
+
+/**
+ * Tests that context aware plugins function correctly.
+ */
+class ContextPluginTest extends DrupalUnitTestBase {
+
+  public static $modules = array('system', 'user', 'node');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Contextual Plugins',
+      'description' => 'Tests that contexts are properly set and working within plugins.',
+      'group' => 'Plugin API',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+    $this->installSchema('node', 'node_type');
+  }
+
+  /**
+   * Tests basic context definition and value getters and setters.
+   */
+  function testContext() {
+    $name = $this->randomName();
+    $manager = new MockBlockManager();
+    $plugin = $manager->createInstance('user_name');
+    // Create a node, add it as context, catch the exception.
+    $node = entity_create('node', array('title' => $name));
+
+    // Try to get a valid context that has not been set.
+    try {
+      $plugin->getContext('user');
+      $this->fail('The user context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The user context is not yet set.');
+    }
+
+    // Try to get an invalid context.
+    try {
+      $plugin->getContext('node');
+      $this->fail('The node context should not be a valid context.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The node context is not a valid context.');
+    }
+
+    // Try to get a valid context value that has not been set.
+    try {
+      $plugin->getContextValue('user');
+      $this->fail('The user context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The user context is not yet set.');
+    }
+
+    // Try to call a method of the plugin that requires context before it has
+    // been set.
+    try {
+      $plugin->getTitle();
+      $this->fail('The user context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The user context is not yet set.');
+    }
+
+    // Try to get a context value that is not valid.
+    try {
+      $plugin->getContextValue('node');
+      $this->fail('The node context should not be a valid context.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The node context is not a valid context.');
+    }
+
+    // Try to pass the wrong class type as a context value.
+    try {
+      $plugin->setContextValue('user', $node);
+      $this->fail('The node context should fail validation for a user context.');
+    }
+    catch (ContextException $e) {
+      $this->assertEqual($e->getMessage(), 'The context passed was not an instance of Drupal\user\Plugin\Core\Entity\User.');
+    }
+
+    // Set an appropriate context value appropriately and check to make sure
+    // its methods work as expected.
+    $user = entity_create('user', array('name' => $name));
+    $plugin->setContextValue('user', $user);
+    $this->assertEqual($user->label(), $plugin->getTitle());
+
+    // Test the getContextDefinitions() method.
+    $this->assertIdentical($plugin->getContextDefinitions(), array('user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User')));
+
+    // Test the getContextDefinition() method for a valid context.
+    $this->assertEqual($plugin->getContextDefinition('user'), array('class' => 'Drupal\user\Plugin\Core\Entity\User'));
+
+    // Test the getContextDefinition() method for an invalid context.
+    try {
+      $plugin->getContextDefinition('node');
+      $this->fail('The node context should not be a valid context.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The node context is not a valid context.');
+    }
+
+    // Test typed data context plugins.
+    $typed_data_plugin = $manager->createInstance('string_context');
+
+    // Try to get a valid context value that has not been set.
+    try {
+      $typed_data_plugin->getContextValue('string');
+      $this->fail('The string context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The string context is not yet set.');
+    }
+
+    // Try to call a method of the plugin that requires a context value before
+    // it has been set.
+    try {
+      $typed_data_plugin->getTitle();
+      $this->fail('The string context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The string context is not yet set.');
+    }
+
+    // Set the context value appropriately and check the title.
+    $typed_data_plugin->setContextValue('string', $name);
+    $this->assertEqual($name, $typed_data_plugin->getTitle());
+
+    // Test Complex compound context handling.
+    $complex_plugin = $manager->createInstance('complex_context');
+
+    // With no contexts set, try to get the contexts.
+    try {
+      $complex_plugin->getContexts();
+      $this->fail('There should not be any contexts set yet.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'There are no set contexts.');
+    }
+
+    // With no contexts set, try to get the context values.
+    try {
+      $complex_plugin->getContextValues();
+      $this->fail('There should not be any contexts set yet.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'There are no set contexts.');
+    }
+
+    // Set the user context value.
+    $complex_plugin->setContextValue('user', $user);
+
+    // With only the user context set, try to get the contexts.
+    try {
+      $complex_plugin->getContexts();
+      $this->fail('The node context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The node context is not yet set.');
+    }
+
+    // With only the user context set, try to get the context values.
+    try {
+      $complex_plugin->getContextValues();
+      $this->fail('The node context should not yet be set.');
+    }
+    catch (PluginException $e) {
+      $this->assertEqual($e->getMessage(), 'The node context is not yet set.');
+    }
+
+    $complex_plugin->setContextValue('node', $node);
+    $context_wrappers = $complex_plugin->getContexts();
+    // Make sure what came out of the wrappers is good.
+    $this->assertEqual($context_wrappers['user']->getContextValue()->label(), $user->label());
+    $this->assertEqual($context_wrappers['node']->getContextValue()->label(), $node->label());
+
+    // Make sure what comes out of the context values is good.
+    $contexts = $complex_plugin->getContextValues();
+    $this->assertEqual($contexts['user']->label(), $user->label());
+    $this->assertEqual($contexts['node']->label(), $node->label());
+
+    // Test the title method for the complex context plugin.
+    $this->assertEqual($user->label() . ' -- ' . $node->label(), $complex_plugin->getTitle());
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
index 5db932203ca0c7c431785a578090c935b270caca..c927f7eb241992058fae73ee2df22fcee20fbc95 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
@@ -70,6 +70,28 @@ public function setUp() {
         'label' => 'Layout Foo',
         'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
       ),
+      'user_name' => array(
+        'label' => 'User name',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
+        'context' => array(
+          'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User')
+        ),
+      ),
+      'string_context' => array(
+        'label' => 'String typed data',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock',
+        'context' => array(
+          'string' => array('type' => 'string'),
+        ),
+      ),
+      'complex_context' => array(
+        'label' => 'Complex context',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock',
+        'context' => array(
+          'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'),
+          'node' => array('class' => 'Drupal\node\Plugin\Core\Entity\Node'),
+        ),
+      ),
     );
     $this->defaultsTestPluginExpectedDefinitions = array(
       'test_block1' => array(
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
index fcf18245125fe9e78531ee785749a88ed62d4958..7e292597367ac4a95c05dbbfc46d0cec19af5d8a 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
@@ -66,6 +66,35 @@ public function __construct() {
       'derivative' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlockDeriver',
     ));
 
+    // A block plugin that requires context to function. This block requires a
+    // user object in order to return the user name from the getTitle() method.
+    $this->discovery->setDefinition('user_name', array(
+      'label' => t('User name'),
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
+      'context' => array(
+        'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User')
+      ),
+    ));
+
+    // A block plugin that requires a typed data string context to function.
+    $this->discovery->setDefinition('string_context', array(
+      'label' => t('String typed data'),
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock',
+      'context' => array(
+        'string' => array('type' => 'string'),
+      ),
+    ));
+
+    // A complex context plugin that requires both a user and node for context.
+    $this->discovery->setDefinition('complex_context', array(
+      'label' => t('Complex context'),
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock',
+      'context' => array(
+        'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'),
+        'node' => array('class' => 'Drupal\node\Plugin\Core\Entity\Node'),
+      ),
+    ));
+
     // In addition to finding all of the plugins available for a type, a plugin
     // type must also be able to create instances of that plugin. For example, a
     // specific instance of a "Main menu" menu block, configured to show just
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..1cb657a4a61da8dd62cae6cac2e5a825ff61d3be
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
+
+use Drupal\Core\Plugin\ContextAwarePluginBase;
+
+/**
+ * Implementation of a complex context plugin used by Plugin API context tests.
+ *
+ * @see \Drupal\plugin_test\Plugin\MockBlockManager
+ */
+class MockComplexContextBlock extends ContextAwarePluginBase {
+
+  public function getTitle() {
+    $user = $this->getContextValue('user');
+    $node = $this->getContextValue('node');
+    return $user->label() . ' -- ' . $node->label();
+  }
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fc1f849d1e92183fa450990a4ff9a5c1a46f52d
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
+
+use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+
+/**
+ * Implementation of a user name block plugin used by Plugin API context test.
+ *
+ * @see \Drupal\plugin_test\Plugin\MockBlockManager
+ */
+class MockUserNameBlock extends ContextAwarePluginBase {
+
+  public function getTitle() {
+    $user = $this->getContextValue('user');
+    return $user->label();
+  }
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..14e0ab3bf7efe6f7af743b7be6d442c638304f14
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
+
+use Drupal\Core\Plugin\ContextAwarePluginBase;
+
+/**
+ * Implementation of a String TypedData contextual block plugin used by Plugin
+ * API context test.
+ *
+ * @see \Drupal\plugin_test\Plugin\MockBlockManager
+ */
+class TypedDataStringBlock extends ContextAwarePluginBase {
+
+  public function getTitle() {
+    return $this->getContextValue('string');
+  }
+}