diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index 1b06282..f3c52e7 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -308,6 +308,11 @@ block_settings:
     provider:
       type: string
       label: 'Provider'
+    context_mapping:
+      type: sequence
+      label: 'Context assignments'
+      sequence:
+        - type: string
 
 condition.plugin:
   type: mapping
diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index ba1026b..58f79a3 100644
--- a/core/lib/Drupal/Core/Block/BlockBase.php
+++ b/core/lib/Drupal/Core/Block/BlockBase.php
@@ -10,6 +10,7 @@
 use Drupal\block\BlockInterface;
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
 use Drupal\Core\Plugin\ContextAwarePluginBase;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\NestedArray;
@@ -29,6 +30,8 @@
  */
 abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface {
 
+  use ContextAwarePluginAssignmentTrait;
+
   /**
    * The transliteration service.
    *
@@ -228,6 +231,9 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       $form['cache']['contexts']['#description'] .= ' ' . t('This block is <em>always</em> varied by the following contexts: %required-context-list.', array('%required-context-list' => $required_context_list));
     }
 
+    // Add context form elements.
+    $contexts = $form_state->getTemporaryValue('gathered_contexts') ?: [];
+    $form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts);
     // Add plugin-specific settings for this block type.
     $form += $this->blockForm($form, $form_state);
     return $form;
diff --git a/core/lib/Drupal/Core/Block/BlockManager.php b/core/lib/Drupal/Core/Block/BlockManager.php
index 75f9527..661a3df 100644
--- a/core/lib/Drupal/Core/Block/BlockManager.php
+++ b/core/lib/Drupal/Core/Block/BlockManager.php
@@ -100,9 +100,9 @@ public function getCategories() {
   /**
    * {@inheritdoc}
    */
-  public function getSortedDefinitions() {
+  public function getSortedDefinitions(array $contexts = array()) {
     // Sort the plugins first by category, then by label.
-    $definitions = $this->getDefinitionsForContexts();
+    $definitions = $this->getDefinitionsForContexts($contexts);
     uasort($definitions, function ($a, $b) {
       if ($a['category'] != $b['category']) {
         return strnatcasecmp($a['category'], $b['category']);
diff --git a/core/lib/Drupal/Core/Block/BlockManagerInterface.php b/core/lib/Drupal/Core/Block/BlockManagerInterface.php
index 2fa8611..8b984b2 100644
--- a/core/lib/Drupal/Core/Block/BlockManagerInterface.php
+++ b/core/lib/Drupal/Core/Block/BlockManagerInterface.php
@@ -25,9 +25,11 @@ public function getCategories();
   /**
    * Gets the sorted definitions.
    *
+   * @param array $contexts
+   *
    * @return array
    *   An array of plugin definitions, sorted by category and admin label.
    */
-  public function getSortedDefinitions();
+  public function getSortedDefinitions(array $contexts = array());
 
 }
diff --git a/core/modules/aggregator/src/AggregatorServiceProvider.php b/core/modules/aggregator/src/AggregatorServiceProvider.php
new file mode 100644
index 0000000..e61d7bf
--- /dev/null
+++ b/core/modules/aggregator/src/AggregatorServiceProvider.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\AggregatorServiceProvider.
+ */
+
+namespace Drupal\aggregator;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\DependencyInjection\ServiceProviderBase;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Provides a block context event subscriber if the block module is enabled.
+ */
+class AggregatorServiceProvider extends ServiceProviderBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function register(ContainerBuilder $container) {
+    parent::register($container);
+    $modules = $container->getParameter('container.modules');
+    if (isset($modules['block'])) {
+      $container->register('block.aggregator_feed_context', 'Drupal\aggregator\EventSubscriber\AggregatorFeedContext')
+        ->addArgument(new Reference('entity.manager'))
+        ->addArgument(new Reference('theme.manager'))
+        ->addTag('event_subscriber');
+    }
+  }
+
+}
diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php
index 6532f36..6125e16 100644
--- a/core/modules/aggregator/src/Entity/Feed.php
+++ b/core/modules/aggregator/src/Entity/Feed.php
@@ -114,9 +114,13 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti
     parent::postDelete($storage, $entities);
     if (\Drupal::moduleHandler()->moduleExists('block')) {
       // Make sure there are no active blocks for these feeds.
+      $context_ids = array_keys($entities);
+      foreach ($context_ids as $key => $value) {
+        $context_ids[$key] = 'aggregator.feed:' . $value;
+      }
       $ids = \Drupal::entityQuery('block')
         ->condition('plugin', 'aggregator_feed_block')
-        ->condition('settings.feed', array_keys($entities))
+        ->condition('settings.context_mapping.feed', $context_ids)
         ->execute();
       if ($ids) {
         $block_storage = \Drupal::entityManager()->getStorage('block');
diff --git a/core/modules/aggregator/src/EventSubscriber/AggregatorFeedContext.php b/core/modules/aggregator/src/EventSubscriber/AggregatorFeedContext.php
new file mode 100644
index 0000000..09dd845
--- /dev/null
+++ b/core/modules/aggregator/src/EventSubscriber/AggregatorFeedContext.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\EventSubscriber\AggregatorFeedContext.
+ */
+
+namespace Drupal\aggregator\EventSubscriber;
+
+use Drupal\block\Event\BlockContextEvent;
+use Drupal\block\EventSubscriber\BlockContextSubscriberBase;
+use Drupal\Component\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Theme\ThemeManagerInterface;
+
+/**
+ * Provides aggregator feeds as context.
+ */
+class AggregatorFeedContext extends BlockContextSubscriberBase {
+
+  /**
+   * The entity storage for feeds.
+   *
+   * @var \Drupal\aggregator\FeedStorageInterface
+   */
+  protected $feedStorage;
+
+  /**
+   * The block storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $blockStorage;
+
+  /**
+   * The theme manager.
+   *
+   * @var \Drupal\Core\Theme\ThemeManagerInterface
+   */
+  protected $themeManager;
+
+  /**
+   * Constructs a new NodeRouteContext.
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
+   *   The theme manager.
+   */
+  public function __construct(EntityManagerInterface $entity_manager, ThemeManagerInterface $theme_manager) {
+    $this->feedStorage = $entity_manager->getStorage('aggregator_feed');
+    $this->blockStorage = $entity_manager->getStorage('block');
+    $this->themeManager = $theme_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onBlockActiveContext(BlockContextEvent $event) {
+    foreach ($this->blockStorage->loadByProperties(['plugin' => 'aggregator_feed_block', 'theme' => $this->themeManager->getActiveTheme()->getName()]) as $block_id => $block) {
+      /** @var $block \Drupal\block\Entity\Block */
+      $block_plugin = $block->getPlugin();
+      if ($block_plugin instanceof ContextAwarePluginInterface) {
+        $contexts = $block_plugin->getContextMapping();
+        list(, $fid) = explode(':', $contexts['feed'], 2);
+        $feed = $this->feedStorage->load($fid);
+        $context = new Context(new ContextDefinition('entity:aggregator_feed'));
+        $context->setContextValue($feed);
+        $event->setContext('aggregator.feed:' . $feed->id(), $context);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onBlockAdministrativeContext(BlockContextEvent $event) {
+    $feeds = $this->feedStorage->loadMultiple();
+    foreach ($feeds as $feed) {
+      $context = new Context(new ContextDefinition('entity:aggregator_feed', $feed->label()));
+      $context->setContextValue($feed);
+      $event->setContext('aggregator.feed:' . $feed->id(), $context);
+    }
+  }
+
+}
diff --git a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
index 16ca1af..7272d7f 100644
--- a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
+++ b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\aggregator\Plugin\Block;
 
-use Drupal\aggregator\FeedStorageInterface;
 use Drupal\aggregator\ItemStorageInterface;
 use Drupal\Core\Block\BlockBase;
 use Drupal\Core\Cache\Cache;
@@ -23,19 +22,16 @@
  * @Block(
  *   id = "aggregator_feed_block",
  *   admin_label = @Translation("Aggregator feed"),
- *   category = @Translation("Lists (Views)")
+ *   category = @Translation("Lists (Views)"),
+ *   context = {
+ *     "feed" = @ContextDefinition("entity:aggregator_feed", label = @Translation("Aggregator feed"))
+ *   }
  * )
+ *
  */
 class AggregatorFeedBlock extends BlockBase implements ContainerFactoryPluginInterface {
 
   /**
-   * The entity storage for feeds.
-   *
-   * @var \Drupal\aggregator\FeedStorageInterface
-   */
-  protected $feedStorage;
-
-  /**
    * The entity storage for items.
    *
    * @var \Drupal\aggregator\ItemStorageInterface
@@ -58,16 +54,13 @@ class AggregatorFeedBlock extends BlockBase implements ContainerFactoryPluginInt
    *   The plugin_id for the plugin instance.
    * @param mixed $plugin_definition
    *   The plugin implementation definition.
-   * @param \Drupal\aggregator\FeedStorageInterface $feed_storage
-   *   The entity storage for feeds.
    * @param \Drupal\aggregator\ItemStorageInterface $item_storage
    *   The entity storage for feed items.
    * @param \Drupal\Core\Entity\Query\QueryInterface $item_query
    *   The entity query object for feed items.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, FeedStorageInterface $feed_storage, ItemStorageInterface $item_storage, QueryInterface $item_query) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ItemStorageInterface $item_storage, QueryInterface $item_query) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->feedStorage = $feed_storage;
     $this->itemStorage = $item_storage;
     $this->itemQuery = $item_query;
   }
@@ -81,7 +74,6 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration,
       $plugin_id,
       $plugin_definition,
-      $container->get('entity.manager')->getStorage('aggregator_feed'),
       $container->get('entity.manager')->getStorage('aggregator_item'),
       $container->get('entity.query')->get('aggregator_item')
     );
@@ -118,17 +110,6 @@ protected function blockAccess(AccountInterface $account) {
    * {@inheritdoc}
    */
   public function blockForm($form, FormStateInterface $form_state) {
-    $feeds = $this->feedStorage->loadMultiple();
-    $options = array();
-    foreach ($feeds as $feed) {
-      $options[$feed->id()] = $feed->label();
-    }
-    $form['feed'] = array(
-      '#type' => 'select',
-      '#title' => t('Select the feed that should be displayed'),
-      '#default_value' => $this->configuration['feed'],
-      '#options' => $options,
-    );
     $range = range(2, 20);
     $form['block_count'] = array(
       '#type' => 'select',
@@ -152,40 +133,40 @@ public function blockSubmit($form, FormStateInterface $form_state) {
    */
   public function build() {
     // Load the selected feed.
-    if ($feed = $this->feedStorage->load($this->configuration['feed'])) {
-      $result = $this->itemQuery
-        ->condition('fid', $feed->id())
-        ->range(0, $this->configuration['block_count'])
-        ->sort('timestamp', 'DESC')
-        ->sort('iid', 'DESC')
-        ->execute();
-
-      $items = $this->itemStorage->loadMultiple($result);
-
-      $more_link = array(
-        '#type' => 'more_link',
-        '#url' => $feed->urlInfo(),
-        '#attributes' => array('title' => $this->t("View this feed's recent news.")),
+    /** @var $feed \Drupal\aggregator\Entity\Feed */
+    $feed = $this->getContextValue('feed');
+    $result = $this->itemQuery
+      ->condition('fid', $feed->id())
+      ->range(0, $this->configuration['block_count'])
+      ->sort('timestamp', 'DESC')
+      ->sort('iid', 'DESC')
+      ->execute();
+
+    $items = $this->itemStorage->loadMultiple($result);
+
+    $more_link = array(
+      '#type' => 'more_link',
+      '#url' => $feed->urlInfo(),
+      '#attributes' => array('title' => $this->t("View this feed's recent news.")),
+    );
+    $read_more = drupal_render($more_link);
+    $rendered_items = array();
+    foreach ($items as $item) {
+      $aggregator_block_item = array(
+        '#theme' => 'aggregator_block_item',
+        '#item' => $item,
+      );
+      $rendered_items[] = drupal_render($aggregator_block_item);
+    }
+    // Only display the block if there are items to show.
+    if (count($rendered_items) > 0) {
+      $item_list = array(
+        '#theme' => 'item_list',
+        '#items' => $rendered_items,
+      );
+      return array(
+        '#children' => drupal_render($item_list) . $read_more,
       );
-      $read_more = drupal_render($more_link);
-      $rendered_items = array();
-      foreach ($items as $item) {
-        $aggregator_block_item = array(
-          '#theme' => 'aggregator_block_item',
-          '#item' => $item,
-        );
-        $rendered_items[] = drupal_render($aggregator_block_item);
-      }
-      // Only display the block if there are items to show.
-      if (count($rendered_items) > 0) {
-        $item_list = array(
-          '#theme' => 'item_list',
-          '#items' => $rendered_items,
-        );
-        return array(
-          '#children' => drupal_render($item_list) . $read_more,
-        );
-      }
     }
   }
 
@@ -194,7 +175,7 @@ public function build() {
    */
   public function getCacheTags() {
     $cache_tags = parent::getCacheTags();
-    $feed = $this->feedStorage->load($this->configuration['feed']);
+    $feed = $this->getContextValue('feed');
     return Cache::mergeTags($cache_tags, $feed->getCacheTags());
   }
 
diff --git a/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php b/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
index efb3d2f..573d8ce 100644
--- a/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
+++ b/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
@@ -44,7 +44,7 @@ public function testBlockLinks() {
     $block = $this->drupalPlaceBlock("aggregator_feed_block", array('label' => 'feed-' . $feed->label()));
 
     // Configure the feed that should be displayed.
-    $block->getPlugin()->setConfigurationValue('feed', $feed->id());
+    $block->getPlugin()->setContextMapping(['feed' => 'aggregator.feed:' . $feed->id()]);
     $block->getPlugin()->setConfigurationValue('block_count', 2);
     $block->save();
 
diff --git a/core/modules/aggregator/src/Tests/DeleteFeedTest.php b/core/modules/aggregator/src/Tests/DeleteFeedTest.php
index 6ec7c50..c4b4bab 100644
--- a/core/modules/aggregator/src/Tests/DeleteFeedTest.php
+++ b/core/modules/aggregator/src/Tests/DeleteFeedTest.php
@@ -30,10 +30,10 @@ function testDeleteFeed() {
 
     // Place a block for both feeds.
     $block = $this->drupalPlaceBlock('aggregator_feed_block');
-    $block->getPlugin()->setConfigurationValue('feed', $feed1->id());
+    $block->getPlugin()->setContextMapping(['feed' => 'aggregator.feed:' . $feed1->id()]);
     $block->save();
     $block2 = $this->drupalPlaceBlock('aggregator_feed_block');
-    $block2->getPlugin()->setConfigurationValue('feed', $feed2->id());
+    $block2->getPlugin()->setContextMapping(['feed' => 'aggregator.feed:' . $feed2->id()]);
     $block2->save();
 
     // Delete feed.
diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php
index 23d6ca0..2df35f9 100644
--- a/core/modules/block/src/BlockForm.php
+++ b/core/modules/block/src/BlockForm.php
@@ -306,7 +306,12 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     $settings = (new FormState())->setValues($form_state->getValue('settings'));
 
     // Call the plugin submit handler.
-    $entity->getPlugin()->submitConfigurationForm($form, $settings);
+    $block = $entity->getPlugin();
+    $block->submitConfigurationForm($form, $settings);
+    if ($block instanceof ContextAwarePluginInterface) {
+      $context_mapping = $settings->getValue('context_mapping', []);
+      $block->setContextMapping($context_mapping);
+    }
     // Update the original form values.
     $form_state->setValue('settings', $settings->getValues());
 
diff --git a/core/modules/block/src/BlockListBuilder.php b/core/modules/block/src/BlockListBuilder.php
index 1d11f99..1b507cb 100644
--- a/core/modules/block/src/BlockListBuilder.php
+++ b/core/modules/block/src/BlockListBuilder.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\block;
 
+use Drupal\block\Event\BlockContextEvent;
+use Drupal\block\Event\BlockEvents;
 use Drupal\Core\Block\BlockManagerInterface;
 use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\String;
@@ -18,6 +20,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -56,6 +59,13 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
   protected $blockManager;
 
   /**
+   * The event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
+   */
+  protected $eventDispatcher;
+
+  /**
    * Constructs a new BlockListBuilder object.
    *
    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
@@ -64,11 +74,14 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
    *   The entity storage class.
    * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
    *   The block manager.
+   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
+   *   The event dispatcher.
    */
-  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, BlockManagerInterface $block_manager) {
+  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, BlockManagerInterface $block_manager, EventDispatcherInterface $event_dispatcher) {
     parent::__construct($entity_type, $storage);
 
     $this->blockManager = $block_manager;
+    $this->eventDispatcher = $event_dispatcher;
   }
 
   /**
@@ -78,7 +91,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_type,
       $container->get('entity.manager')->getStorage($entity_type->id()),
-      $container->get('plugin.manager.block')
+      $container->get('plugin.manager.block'),
+      $container->get('event_dispatcher')
     );
   }
 
@@ -335,7 +349,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['place_blocks']['list']['#attributes']['class'][] = 'entity-meta';
 
     // Sort the plugins first by category, then by label.
-    $plugins = $this->blockManager->getSortedDefinitions();
+    $event = new BlockContextEvent();
+    $contexts = $this->eventDispatcher->dispatch(BlockEvents::ADMINISTRATIVE_CONTEXT, $event)->getContexts();
+    $plugins = $this->blockManager->getSortedDefinitions($contexts);
     foreach ($plugins as $plugin_id => $plugin_definition) {
       $category = String::checkPlain($plugin_definition['category']);
       $category_key = 'category-' . $category;
diff --git a/core/modules/block/src/BlockRepository.php b/core/modules/block/src/BlockRepository.php
index c11a4fe..99f9b01 100644
--- a/core/modules/block/src/BlockRepository.php
+++ b/core/modules/block/src/BlockRepository.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Plugin\Context\ContextHandlerInterface;
 use Drupal\Core\Theme\ThemeManagerInterface;
+use Drupal\Component\Plugin\ContextAwarePluginInterface;
 
 /**
  * Provides a repository for Block config entities.
@@ -76,6 +77,10 @@ public function getVisibleBlocksPerRegion(array $contexts) {
     $full = array();
     foreach ($this->blockStorage->loadByProperties(array('theme' => $this->getTheme())) as $block_id => $block) {
       /** @var \Drupal\block\BlockInterface $block */
+      $block_plugin = $block->getPlugin();
+      if ($block_plugin instanceof ContextAwarePluginInterface) {
+        $this->contextHandler->applyContextMapping($block_plugin, $contexts);
+      }
       // Set the contexts on the block before checking access.
       if ($block->setContexts($contexts)->access('view')) {
         $full[$block->get('region')][$block_id] = $block;
diff --git a/core/modules/block/src/Tests/BlockInterfaceTest.php b/core/modules/block/src/Tests/BlockInterfaceTest.php
index 3c7ecb0..716f6db 100644
--- a/core/modules/block/src/Tests/BlockInterfaceTest.php
+++ b/core/modules/block/src/Tests/BlockInterfaceTest.php
@@ -112,6 +112,7 @@ public function testBlockInterface() {
           ),
         ),
       ),
+      'context_mapping' => array(),
       'display_message' => array(
         '#type' => 'textfield',
         '#title' => t('Display message'),
