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 0000000..c3c9f20
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Context/Context.php
@@ -0,0 +1,82 @@
+<?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 class name or an array definition to which a context must conform.
+   *
+   * @var string|array
+   */
+  protected $contextDefinition;
+
+  /**
+   * Sets the contextDefinition for us without needing to call the setter.
+   */
+  public function __construct($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($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().
+   */
+  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 (is_string($this->contextDefinition)) {
+      if ($value instanceof $this->contextDefinition) {
+        return $value;
+      }
+      throw new ContextException("The context passed was not an instance of $this->contextDefinition.");
+    }
+    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 0000000..ab88543
--- /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($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 0000000..ebf56ea
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
@@ -0,0 +1,110 @@
+<?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() {
+    $definition = $this->getDefinition();
+    // If there are no contexts defined by the plugin, return an empty array.
+    if (empty($definition['context'])) {
+      return array();
+    }
+    if (empty($this->context)) {
+      throw new PluginException("There are no set contexts.");
+    }
+    $contexts = array();
+    foreach (array_keys($definition['context']) 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) {
+    $definition = $this->getDefinition();
+    if (empty($definition['context'][$key])) {
+      throw new PluginException("The $key context is not a valid context.");
+    }
+    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 0000000..68d8012
--- /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 0000000..0618251
--- /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 0000000..2a7f087
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Context/Context.php
@@ -0,0 +1,68 @@
+<?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.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   */
+  public function getTypedContext() {
+    return parent::getContextValue();
+  }
+
+  /**
+   * Override for \Drupal\Component\Plugin\Context\Context::validate().
+   */
+  public function validate($value) {
+    // Check to see if we have a typed data definition instead of a class name.
+    if (is_array($this->contextDefinition)) {
+      $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 0000000..028befd
--- /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 0000000..2eab5fa
--- /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 derivative plugins are correctly discovered.
+ */
+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 getDefinitions() and getDefinition() with a derivativeDecorator.
+   */
+  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' => 'Drupal\user\Plugin\Core\Entity\User'));
+
+    // Test the getContextDefinition() method for a valid context.
+    $this->assertEqual($plugin->getContextDefinition('user'), '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 5db9322..f91675c 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' => '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' => 'Drupal\user\Plugin\Core\Entity\User',
+          'node' => '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 fcf1824..4ef8283 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' => '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' => 'Drupal\user\Plugin\Core\Entity\User',
+        'node' => '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 0000000..1cb657a
--- /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 0000000..3fc1f84
--- /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 0000000..14e0ab3
--- /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');
+  }
+}
