diff --git a/core/lib/Drupal/Component/Plugin/DependentPluginInterface.php b/core/lib/Drupal/Component/Plugin/DependentPluginInterface.php
index 44d65fcf5f..1747685648 100644
--- a/core/lib/Drupal/Component/Plugin/DependentPluginInterface.php
+++ b/core/lib/Drupal/Component/Plugin/DependentPluginInterface.php
@@ -31,6 +31,7 @@
    *
    * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
    * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName()
+   * @see \Drupal\Core\Plugin\RemovableDependentPluginInterface
    */
   public function calculateDependencies();
 
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index 08e7e19170..8b22314369 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Core\Config\Entity;
 
+use Drupal\Core\Entity\EntityWithDependentPluginCollectionInterface;
+use Drupal\Core\Plugin\RemovableDependentPluginInterface;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\Schema\SchemaIncompleteException;
@@ -498,13 +500,82 @@ public function getConfigTarget() {
    * {@inheritdoc}
    */
   public function onDependencyRemoval(array $dependencies) {
-    $changed = FALSE;
+    $third_party_settings_changed = FALSE;
     if (!empty($this->third_party_settings)) {
       $old_count = count($this->third_party_settings);
       $this->third_party_settings = array_diff_key($this->third_party_settings, array_flip($dependencies['module']));
-      $changed = $old_count != count($this->third_party_settings);
+      $third_party_settings_changed = $old_count != count($this->third_party_settings);
     }
-    return $changed;
+
+    // Allow plugins to react to dependency removal.
+    $plugin_configuration_changed = FALSE;
+    if ($this instanceof EntityWithDependentPluginCollectionInterface) {
+      foreach ($this->getPluginCollections() as $collection_group => $plugin_collection) {
+        foreach ($plugin_collection as $instance) {
+          if ($instance instanceof RemovableDependentPluginInterface) {
+            // Give instance the opportunity to react on dependency removal.
+            $instance_removed_dependencies = $this->getPluginRemovedDependencies($instance->calculateDependencies(), $dependencies);
+            if ($instance_removed_dependencies) {
+              if ($instance->onDependencyRemoval($instance_removed_dependencies)) {
+                // Let the config entity react.
+                $this->onPluginDependencyRemoval($collection_group, $instance);
+                $plugin_configuration_changed = TRUE;
+              }
+              // If there are unresolved deleted dependencies left, allow the
+              // config entity make a final decision.
+              if ($this->getPluginRemovedDependencies($instance->calculateDependencies(), $dependencies)) {
+                $this->onUnresolvedPluginDependencyRemoval($collection_group, $instance);
+                $plugin_configuration_changed = TRUE;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return $third_party_settings_changed || $plugin_configuration_changed;
+  }
+
+  /**
+   * Returns the plugin dependencies being removed.
+   *
+   * The function recursively computes the intersection between all plugin
+   * dependencies and all removed dependencies.
+   *
+   * Note: The two arguments do not have the same structure.
+   *
+   * @param array[] $plugin_dependencies
+   *   A list of dependencies having the same structure as the return value of
+   *   ConfigEntityInterface::calculateDependencies().
+   * @param array[] $removed_dependencies
+   *   A list of dependencies having the same structure as the input argument of
+   *   ConfigEntityInterface::onDependencyRemoval().
+   *
+   * @return array
+   *   A recursively computed intersection.
+   *
+   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
+   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
+   */
+  protected function getPluginRemovedDependencies(array $plugin_dependencies, array $removed_dependencies) {
+    $intersect = [];
+    foreach ($plugin_dependencies as $type => $dependencies) {
+      if ($removed_dependencies[$type]) {
+        // Config and content entities have the dependency names as keys while
+        // module and theme dependencies are indexed arrays of dependency names.
+        // @see \Drupal\Core\Config\ConfigManager::callOnDependencyRemoval()
+        if (in_array($type, ['config', 'content'])) {
+          $removed = array_intersect_key($removed_dependencies[$type], array_flip($dependencies));
+        }
+        else {
+          $removed = array_values(array_intersect($removed_dependencies[$type], $dependencies));
+        }
+        if ($removed) {
+          $intersect[$type] = $removed;
+        }
+      }
+    }
+    return $intersect;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
index b6c73e5550..67a8fc3aeb 100644
--- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
@@ -503,48 +503,6 @@ public function onDependencyRemoval(array $dependencies) {
   }
 
   /**
-   * Returns the plugin dependencies being removed.
-   *
-   * The function recursively computes the intersection between all plugin
-   * dependencies and all removed dependencies.
-   *
-   * Note: The two arguments do not have the same structure.
-   *
-   * @param array[] $plugin_dependencies
-   *   A list of dependencies having the same structure as the return value of
-   *   ConfigEntityInterface::calculateDependencies().
-   * @param array[] $removed_dependencies
-   *   A list of dependencies having the same structure as the input argument of
-   *   ConfigEntityInterface::onDependencyRemoval().
-   *
-   * @return array
-   *   A recursively computed intersection.
-   *
-   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
-   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
-   */
-  protected function getPluginRemovedDependencies(array $plugin_dependencies, array $removed_dependencies) {
-    $intersect = [];
-    foreach ($plugin_dependencies as $type => $dependencies) {
-      if ($removed_dependencies[$type]) {
-        // Config and content entities have the dependency names as keys while
-        // module and theme dependencies are indexed arrays of dependency names.
-        // @see \Drupal\Core\Config\ConfigManager::callOnDependencyRemoval()
-        if (in_array($type, ['config', 'content'])) {
-          $removed = array_intersect_key($removed_dependencies[$type], array_flip($dependencies));
-        }
-        else {
-          $removed = array_values(array_intersect($removed_dependencies[$type], $dependencies));
-        }
-        if ($removed) {
-          $intersect[$type] = $removed;
-        }
-      }
-    }
-    return $intersect;
-  }
-
-  /**
    * Gets the default region.
    *
    * @return string
diff --git a/core/lib/Drupal/Core/Entity/EntityWithDependentPluginCollectionInterface.php b/core/lib/Drupal/Core/Entity/EntityWithDependentPluginCollectionInterface.php
new file mode 100644
index 0000000000..fc9a55454a
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EntityWithDependentPluginCollectionInterface.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Drupal\Core\Entity;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+
+/**
+ * Provides an interface for entities with plugin collections with dependencies.
+ *
+ * @ingroup plugin_api
+ */
+interface EntityWithDependentPluginCollectionInterface extends EntityWithPluginCollectionInterface {
+
+  /**
+   * Reacts when a dependency of one of its plugins gets removed.
+   *
+   * Config entities
+   *
+   * @param string $collection_group
+   *   The the plugin collection group.
+   * @param \Drupal\Component\Plugin\PluginInspectionInterface $plugin
+   *   The plugin instance.
+   */
+  public function onPluginDependencyRemoval($collection_group, PluginInspectionInterface $plugin);
+
+  /**
+   * Reacts if there are still unresolved dependencies left.
+   *
+   * @param string $collection_group
+   *   The the plugin collection group.
+   * @param \Drupal\Component\Plugin\PluginInspectionInterface $plugin
+   *   The plugin instance.
+   */
+  public function onUnresolvedPluginDependencyRemoval($collection_group, PluginInspectionInterface $plugin);
+
+}
diff --git a/core/lib/Drupal/Core/Field/PluginSettingsBase.php b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
index a6196ec525..d382b88cab 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsBase.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\Core\Field;
 
-use Drupal\Component\Plugin\DependentPluginInterface;
+use Drupal\Core\Plugin\RemovableDependentPluginInterface;
 use Drupal\Core\Plugin\PluginBase;
 
 /**
@@ -10,7 +10,7 @@
  *
  * This class handles lazy replacement of default settings values.
  */
-abstract class PluginSettingsBase extends PluginBase implements PluginSettingsInterface, DependentPluginInterface {
+abstract class PluginSettingsBase extends PluginBase implements PluginSettingsInterface, RemovableDependentPluginInterface {
 
   /**
    * The plugin settings.
diff --git a/core/lib/Drupal/Core/Plugin/RemovableDependentPluginInterface.php b/core/lib/Drupal/Core/Plugin/RemovableDependentPluginInterface.php
new file mode 100644
index 0000000000..caea8bc737
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/RemovableDependentPluginInterface.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Drupal\Core\Plugin;
+
+use Drupal\Component\Plugin\DependentPluginInterface;
+
+/**
+ * Provides an interface for plugins that react when dependencies are removed.
+ *
+ * @ingroup plugin_api
+ */
+interface RemovableDependentPluginInterface extends DependentPluginInterface {
+
+  /**
+   * Informs the plugin that entities it depends on will be deleted.
+   *
+   * This method allows plugins to to remove dependencies from their
+   * configuration. If a plugin integrates with a specific module for example,
+   * it should remove that module from its own configuration when it is
+   * uninstalled.
+   *
+   * If this method returns TRUE then the entity the plugin is attached to needs
+   * to be re-saved by the caller for the changes to take effect.
+   *
+   * @param array $dependencies
+   *   An array of dependencies that will be deleted keyed by dependency type.
+   *   Dependency types are content, config, module and theme.
+   *
+   * @return bool
+   *   TRUE if the entity has been changed as a result, FALSE if not.
+   *
+   * @see \Drupal\Core\Entity\EntityWithPluginCollectionInterface
+   * @see \Drupal\Component\Plugin\DependentPluginInterface
+   * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
+   * @see \Drupal\Core\Config\ConfigEntityBase::preDelete()
+   * @see \Drupal\Core\Config\ConfigManager::uninstall()
+   * @see \Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
+   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
+   */
+  public function onDependencyRemoval(array $dependencies);
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 4710765dd0..ebe7452ddb 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Config\Entity;
 
+use Drupal\Component\Plugin\PluginBase;
 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Language\Language;
@@ -222,31 +223,9 @@ public function testAddDependency() {
    * @dataProvider providerCalculateDependenciesWithPluginCollections
    */
   public function testCalculateDependenciesWithPluginCollections($definition, $expected_dependencies) {
-    $values = array();
-    $this->entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginCollections')
-      ->setConstructorArgs(array($values, $this->entityTypeId))
-      ->setMethods(array('getPluginCollections'))
-      ->getMock();
-
     // Create a configurable plugin that would add a dependency.
-    $instance_id = $this->randomMachineName();
-    $instance = new TestConfigurablePlugin(array(), $instance_id, $definition);
-
-    // Create a plugin collection to contain the instance.
-    $pluginCollection = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultLazyPluginCollection')
-      ->disableOriginalConstructor()
-      ->setMethods(array('get'))
-      ->getMock();
-    $pluginCollection->expects($this->atLeastOnce())
-      ->method('get')
-      ->with($instance_id)
-      ->will($this->returnValue($instance));
-    $pluginCollection->addInstanceId($instance_id);
-
-    // Return the mocked plugin collection.
-    $this->entity->expects($this->once())
-      ->method('getPluginCollections')
-      ->will($this->returnValue(array($pluginCollection)));
+    $instance = new TestConfigurablePlugin(array(), $this->randomMachineName(), $definition);
+    $this->entity = $this->getMockEntityWithPluginCollection($instance);
 
     $this->assertEquals($expected_dependencies, $this->entity->calculateDependencies()->getDependencies());
   }
@@ -292,6 +271,84 @@ public function providerCalculateDependenciesWithPluginCollections() {
   }
 
   /**
+   * @covers ::onDependencyRemoval
+   *
+   * @dataProvider providerOnDependencyRemovalWithPluginCollections
+   */
+  public function testOnDependencyRemovalWithPluginCollections($dependencies_removed) {
+    // Create an entity with a plugin to test.
+    $instance = $this->getMockBuilder('Drupal\Tests\Core\Plugin\Fixtures\TestConfigurablePlugin')
+      ->setConstructorArgs([[], $this->randomMachineName(), ['provider' => 'foo']])
+      ->setMethods(['onDependencyRemoval'])
+      ->getMock();
+    // A simple onDependencyRemoval which indicates if the plugin was able to
+    // remove dependencies or not.
+    $instance
+      ->expects($this->exactly(1))
+      ->method('onDependencyRemoval')
+      ->willReturn($dependencies_removed);
+
+    $this->entity = $this->getMockEntityWithPluginCollection($instance);
+
+    // Ensure the entities onDependencyRemoval method propagates removal of
+    // dependencies to the plugin. The actual dependencies used here do not
+    // matter because each plugins dependency management will need to be
+    // individually tested, this simply ensures that the plugin was given the
+    // chance to act.
+    $changed = $this->entity->onDependencyRemoval([]);
+    $this->assertEquals($dependencies_removed, $changed);
+  }
+
+  /**
+   * Data provider for testOnDependencyRemovalWithPluginCollections.
+   */
+  public function providerOnDependencyRemovalWithPluginCollections() {
+    return [
+      'Plugin removed dependencies' => [
+        TRUE,
+      ],
+      'Plugin did not remove dependencies' => [
+        FALSE,
+      ],
+    ];
+  }
+
+  /**
+   * Get a mock entity with a plugin collection.
+   *
+   * @param \Drupal\Component\Plugin\PluginBase $plugin
+   *   A plugin the entity will have a collection containing.
+   *
+   * @return \Drupal\Core\Config\Entity\ConfigEntityBase|\PHPUnit_Framework_MockObject_MockObject
+   *   A mock entity with a plugin collection containing the given plugin.
+   */
+  protected function getMockEntityWithPluginCollection(PluginBase $plugin) {
+    $values = array();
+    $entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginCollections')
+      ->setConstructorArgs(array($values, $this->entityTypeId))
+      ->setMethods(array('getPluginCollections'))
+      ->getMock();
+
+    // Create a plugin collection to contain the instance.
+    $pluginCollection = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultLazyPluginCollection')
+      ->disableOriginalConstructor()
+      ->setMethods(array('get'))
+      ->getMock();
+    $pluginCollection->expects($this->atLeastOnce())
+      ->method('get')
+      ->with($plugin->getPluginId())
+      ->will($this->returnValue($plugin));
+    $pluginCollection->addInstanceId($plugin->getPluginId());
+
+    // Return the mocked plugin collection.
+    $entity->expects($this->once())
+      ->method('getPluginCollections')
+      ->will($this->returnValue(array($pluginCollection)));
+
+    return $entity;
+  }
+
+  /**
    * @covers ::calculateDependencies
    * @covers ::getDependencies
    * @covers ::onDependencyRemoval
diff --git a/core/tests/Drupal/Tests/Core/Plugin/Fixtures/TestConfigurablePlugin.php b/core/tests/Drupal/Tests/Core/Plugin/Fixtures/TestConfigurablePlugin.php
index 30b3e45e20..1d658248e0 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/Fixtures/TestConfigurablePlugin.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/Fixtures/TestConfigurablePlugin.php
@@ -4,8 +4,9 @@
 
 use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Plugin\RemovableDependentPluginInterface;
 
-class TestConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface {
+class TestConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface, RemovableDependentPluginInterface {
 
   /**
    * {@inheritdoc}
@@ -35,4 +36,11 @@ public function calculateDependencies() {
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function onDependencyRemoval(array $dependencies) {
+    return FALSE;
+  }
+
 }
