diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
index b684630..0732d4d 100644
--- a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
@@ -22,7 +22,7 @@
    *
    * @var \Drupal\Component\Plugin\Context\ContextInterface[]
    */
-  protected $context;
+  protected $context = [];
 
   /**
    * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index 262fd0c..7b82dba 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\Component\Utility\SafeMarkup;
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContextAwarePluginBase;
 use Drupal\Component\Utility\Unicode;
@@ -303,21 +304,42 @@ public function setTransliteration(TransliterationInterface $transliteration) {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return [];
+    $cache_contexts = [];
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $cache_contexts = Cache::mergeContexts($cache_contexts, $context->getCacheContexts());
+      }
+    }
+    return $cache_contexts;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getCacheTags() {
-    return [];
+    $tags = [];
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $tags = Cache::mergeTags($tags, $context->getCacheTags());
+      }
+    }
+    return $tags;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getCacheMaxAge() {
-    return (int)$this->configuration['cache']['max_age'];
+    $max_age = (int)$this->configuration['cache']['max_age'];
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $max_age = Cache::mergeMaxAges($max_age, $context->getCacheMaxAge());
+      }
+    }
+    return $max_age;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Plugin/Context/Context.php b/core/lib/Drupal/Core/Plugin/Context/Context.php
index fb06a1e..84d2fd8 100644
--- a/core/lib/Drupal/Core/Plugin/Context/Context.php
+++ b/core/lib/Drupal/Core/Plugin/Context/Context.php
@@ -10,6 +10,8 @@
 use Drupal\Component\Plugin\Context\Context as ComponentContext;
 use Drupal\Component\Plugin\Exception\ContextException;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\Core\TypedData\TypedDataTrait;
 
@@ -35,6 +37,13 @@ class Context extends ComponentContext implements ContextInterface {
   protected $contextDefinition;
 
   /**
+   * The cacheable metadata of this context.
+   *
+   * @var \Drupal\Core\Cache\CacheableMetadata
+   */
+  protected $cache;
+
+  /**
    * {@inheritdoc}
    */
   public function getContextValue() {
@@ -53,6 +62,12 @@ public function getContextValue() {
    * {@inheritdoc}
    */
   public function setContextValue($value) {
+    if ($value instanceof CacheableDependencyInterface) {
+      $this->setCacheableMetadata(CacheableMetadata::createFromObject($value));
+    }
+    else {
+      $this->setCacheableMetadata(new CacheableMetadata());
+    }
     if ($value instanceof TypedDataInterface) {
       return $this->setContextData($value);
     }
@@ -97,4 +112,20 @@ public function validate() {
     return $this->getContextData()->validate();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setCacheableMetadata(CacheableMetadata $cache) {
+    $this->cache = $cache;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheableMetadata() {
+    return $this->cache;
+  }
+
+
 }
diff --git a/core/lib/Drupal/Core/Plugin/Context/ContextInterface.php b/core/lib/Drupal/Core/Plugin/Context/ContextInterface.php
index bb38617..71859ca 100644
--- a/core/lib/Drupal/Core/Plugin/Context/ContextInterface.php
+++ b/core/lib/Drupal/Core/Plugin/Context/ContextInterface.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Plugin\Context;
 
 use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\TypedData\TypedDataInterface;
 
 /**
@@ -32,4 +33,22 @@ public function getContextData();
    */
   public function setContextData(TypedDataInterface $data);
 
+
+  /**
+   * Set the CacheableMetadata for this context.
+   *
+   * @param \Drupal\Core\Cache\CacheableMetadata $cache
+   *   A CachableMetadata object for the context value.
+   *
+   * @return $this
+   */
+  public function setCacheableMetadata(CacheableMetadata $cache);
+
+  /**
+   * Gets the CacheableMetadata object for this context.
+   *
+   * @return \Drupal\Core\Cache\CacheableMetadata
+   */
+  public function getCacheableMetadata();
+
 }
diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php
index 216dfa8..a157eb4 100644
--- a/core/modules/block/src/BlockViewBuilder.php
+++ b/core/modules/block/src/BlockViewBuilder.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Entity\EntityViewBuilder;
 use Drupal\Core\Entity\EntityViewBuilderInterface;
 use Drupal\Core\Entity\EntityInterface;
@@ -80,6 +81,12 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
         '#block' => $entity,
       );
       $build[$entity_id]['#configuration']['label'] = SafeMarkup::checkPlain($configuration['label']);
+      /** @var $context \Drupal\Core\Plugin\Context\ContextInterface */
+      foreach ($entity->getVisibilityConditions()->getConditionContexts() as $context) {
+        CacheableMetadata::createFromRenderArray($build[$entity_id])
+          ->merge($context->getCacheableMetadata())
+          ->applyTo($build[$entity_id]);
+      }
 
       // Don't run in ::buildBlock() to ensure cache keys can be altered. If an
       // alter hook wants to modify the block contents, it can append another
diff --git a/core/modules/block/src/EventSubscriber/CurrentUserContext.php b/core/modules/block/src/EventSubscriber/CurrentUserContext.php
index cb70f3d..760e873 100644
--- a/core/modules/block/src/EventSubscriber/CurrentUserContext.php
+++ b/core/modules/block/src/EventSubscriber/CurrentUserContext.php
@@ -8,6 +8,7 @@
 namespace Drupal\block\EventSubscriber;
 
 use Drupal\block\Event\BlockContextEvent;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
@@ -56,6 +57,7 @@ public function onBlockActiveContext(BlockContextEvent $event) {
 
     $context = new Context(new ContextDefinition('entity:user', $this->t('Current user')));
     $context->setContextValue($current_user);
+    $context->getCacheableMetadata()->addCacheContexts(['user']);
     $event->setContext('user.current_user', $context);
   }
 
diff --git a/core/modules/block/src/EventSubscriber/NodeRouteContext.php b/core/modules/block/src/EventSubscriber/NodeRouteContext.php
index 66458c0..111788c 100644
--- a/core/modules/block/src/EventSubscriber/NodeRouteContext.php
+++ b/core/modules/block/src/EventSubscriber/NodeRouteContext.php
@@ -8,6 +8,7 @@
 namespace Drupal\block\EventSubscriber;
 
 use Drupal\block\Event\BlockContextEvent;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
 use Drupal\Core\Routing\RouteMatchInterface;
@@ -43,6 +44,8 @@ public function onBlockActiveContext(BlockContextEvent $event) {
       $context = new Context(new ContextDefinition($route_contexts['node']['type']));
       if ($node = $this->routeMatch->getParameter('node')) {
         $context->setContextValue($node);
+        $cache = $context->getCacheableMetadata();
+        $cache->addCacheContexts(['route']);
       }
       $event->setContext('node.node', $context);
     }
@@ -50,6 +53,8 @@ public function onBlockActiveContext(BlockContextEvent $event) {
       $node_type = $this->routeMatch->getParameter('node_type');
       $context = new Context(new ContextDefinition('entity:node'));
       $context->setContextValue(Node::create(array('type' => $node_type->id())));
+      $cache = $context->getCacheableMetadata();
+      $cache->addCacheContexts(['route']);
       $event->setContext('node.node', $context);
     }
   }
