diff --git a/core/core.services.yml b/core/core.services.yml
index 72bf10e..d1f055c 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -278,7 +278,7 @@ services:
     arguments: ['%container.modules%', '@cache.bootstrap']
   theme_handler:
     class: Drupal\Core\Extension\ThemeHandler
-    arguments: ['@config.factory', '@module_handler', '@state', '@info_parser', '@logger.channel.default', '@asset.css.collection_optimizer', '@config.installer', '@router.builder']
+    arguments: ['@config.factory', '@module_handler', '@state', '@info_parser', '@logger.channel.default', '@asset.css.collection_optimizer', '@config.installer', '@config.manager', '@router.builder']
   entity.manager:
     class: Drupal\Core\Entity\EntityManager
     arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation', '@class_resolver', '@typed_data_manager']
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index d9ef77e..df83a02 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\ConfigInstallerInterface;
+use Drupal\Core\Config\ConfigManagerInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Routing\RouteBuilder;
 use Psr\Log\LoggerInterface;
@@ -109,6 +110,13 @@ class ThemeHandler implements ThemeHandlerInterface {
   protected $cssCollectionOptimizer;
 
   /**
+   * The config manager used to uninstall a theme.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
    * Constructs a new ThemeHandler.
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
@@ -119,20 +127,22 @@ class ThemeHandler implements ThemeHandlerInterface {
    *   The state store.
    * @param \Drupal\Core\Extension\InfoParserInterface $info_parser
    *   The info parser to parse the theme.info.yml files.
-   * @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $css_collection_optimizer
-   *   The CSS asset collection optimizer service.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
+   * @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $css_collection_optimizer
+   *   The CSS asset collection optimizer service.
    * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer
    *   (optional) The config installer to install configuration. This optional
    *   to allow the theme handler to work before Drupal is installed and has a
    *   database.
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The config manager used to uninstall a theme.
    * @param \Drupal\Core\Routing\RouteBuilder $route_builder
    *   (optional) The route builder to rebuild the routes if a theme is enabled.
    * @param \Drupal\Core\Extension\ExtensionDiscovery $extension_discovery
    *   (optional) A extension discovery instance (for unit tests).
    */
-  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, StateInterface $state, InfoParserInterface $info_parser,LoggerInterface $logger, AssetCollectionOptimizerInterface $css_collection_optimizer = NULL, ConfigInstallerInterface $config_installer = NULL, RouteBuilder $route_builder = NULL, ExtensionDiscovery $extension_discovery = NULL) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, StateInterface $state, InfoParserInterface $info_parser,LoggerInterface $logger, AssetCollectionOptimizerInterface $css_collection_optimizer = NULL, ConfigInstallerInterface $config_installer = NULL, ConfigManagerInterface $config_manager = NULL, RouteBuilder $route_builder = NULL, ExtensionDiscovery $extension_discovery = NULL) {
     $this->configFactory = $config_factory;
     $this->moduleHandler = $module_handler;
     $this->state = $state;
@@ -140,6 +150,7 @@ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandle
     $this->logger = $logger;
     $this->cssCollectionOptimizer = $css_collection_optimizer;
     $this->configInstaller = $config_installer;
+    $this->configManager = $config_manager;
     $this->routeBuilder = $route_builder;
     $this->extensionDiscovery = $extension_discovery;
   }
@@ -354,6 +365,32 @@ public function disable(array $theme_list) {
   /**
    * {@inheritdoc}
    */
+  public function uninstall(array $theme_list) {
+    $extension_config = $this->configFactory->get('core.extension');
+
+    foreach ($theme_list as $key) {
+      if ($extension_config->get("theme.$key") !== NULL) {
+        throw new \InvalidArgumentException("Theme $key is still enabled.");
+      }
+      if ($extension_config->get("disabled.theme.$key") === NULL) {
+        throw new \InvalidArgumentException("Theme $key is not installed.");
+      }
+    }
+
+    foreach ($theme_list as $key) {
+      // Remove all configuration belonging to the theme.
+      $this->configManager->uninstall('theme', $key);
+
+      $extension_config->clear("disabled.theme.$key");
+    }
+    $extension_config->save();
+
+    $this->moduleHandler->invokeAll('themes_uninstalled', [$theme_list]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function listInfo() {
     if (!isset($this->list)) {
       $this->list = array();
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php b/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
index 74f9ad2..353ab81 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
@@ -42,6 +42,22 @@ public function enable(array $theme_list, $enable_dependencies = TRUE);
   public function disable(array $theme_list);
 
   /**
+   * Uninstalls a given list of disabled themes.
+   *
+   * Uninstalling a theme removes all related configuration (like blocks) and
+   * invokes the 'themes_uninstalled' hook.
+   *
+   * @param array $theme_list
+   *   The themes to uninstall.
+   *
+   * @throws \InvalidArgumentException
+   *   Thrown when you uninstall an not installed or not disabled theme.
+   *
+   * @see hook_themes_uninstalled()
+   */
+  public function uninstall(array $theme_list);
+
+  /**
    * Returns a list of currently enabled themes.
    *
    * @return \Drupal\Core\Extension\Extension[]
@@ -140,6 +156,16 @@ public function getName($theme);
   public function getDefault();
 
   /**
+   * Sets a new default theme.
+   *
+   * @param string $theme
+   *   The new default theme.
+   *
+   * @return $this
+   */
+  public function setDefault($theme);
+
+  /**
    * Returns an array of directories for all enabled themes.
    *
    * Useful for tasks such as finding a file that exists in all theme
diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php
index ebd4a7c..abfd375 100644
--- a/core/modules/block/src/Tests/BlockTest.php
+++ b/core/modules/block/src/Tests/BlockTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\block\Tests;
 
+use Drupal\block\Entity\Block;
 use Drupal\Core\Cache\Cache;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Component\Utility\String;
@@ -376,4 +377,25 @@ public function testBlockCacheTags() {
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
   }
 
+  /**
+   * Tests that uninstalling a theme removes its block configuration.
+   */
+  public function testUninstallTheme() {
+    /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
+    $theme_handler = \Drupal::service('theme_handler');
+
+    $theme_handler->enable(['seven']);
+    $theme_handler->setDefault('seven');
+    $block = $this->drupalPlaceBlock('system_powered_by_block', ['theme' => 'seven', 'region' => 'help']);
+    $this->drupalGet('<front>');
+    $this->assertText('Powered by Drupal');
+
+    $theme_handler->setDefault('stark');
+    $theme_handler->disable(['seven']);
+    $theme_handler->uninstall(['seven']);
+
+    // Ensure that the block configuration does not exist anymore.
+    $this->assertIdentical(NULL, Block::load($block->id()));
+  }
+
 }
diff --git a/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php b/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php
index f652bfd..1dbabe0 100644
--- a/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php
+++ b/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php
@@ -331,6 +331,60 @@ function testDisableNonExisting() {
   }
 
   /**
+   * Tests uninstalling a theme.
+   */
+  function testUninstall() {
+    $name = 'test_basetheme';
+
+    $this->themeHandler()->enable(array($name));
+    $this->themeHandler()->disable(array($name));
+    $this->assertTrue($this->config("$name.settings")->get());
+
+    $this->themeHandler()->uninstall(array($name));
+
+    $this->assertFalse(array_keys($this->themeHandler()->listInfo()));
+    $this->assertFalse(array_keys(system_list('theme')));
+
+    $this->assertFalse($this->config("$name.settings")->get());
+  }
+
+  /**
+   * Tests uninstalling a theme that is not installed.
+   */
+  function testUninstallNotInstalled() {
+    $name = 'test_basetheme';
+
+    try {
+      $message = 'ThemeHandler::uninstall() throws InvalidArgumentException upon uninstalling a theme that is not installed.';
+      $this->themeHandler()->uninstall(array($name));
+      $this->fail($message);
+    }
+    catch (\InvalidArgumentException $e) {
+      $this->pass(get_class($e) . ': ' . $e->getMessage());
+    }
+  }
+
+  /**
+   * Tests uninstalling a theme that is not disabled.
+   */
+  function testUninstallEnabled() {
+    $name = 'test_basetheme';
+
+    $this->themeHandler()->enable(array($name));
+
+    try {
+      $message = 'ThemeHandler::uninstall() throws InvalidArgumentException upon uninstalling a theme that is not installed.';
+      $this->themeHandler()->uninstall(array($name));
+      $this->fail($message);
+    }
+    catch (\InvalidArgumentException $e) {
+      $this->pass(get_class($e) . ': ' . $e->getMessage());
+    }
+
+    $this->assertTrue($this->config("$name.settings")->get());
+  }
+
+  /**
    * Tests that theme info can be altered by a module.
    *
    * @see module_test_system_info_alter()
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 59922b7..75987fa 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1397,6 +1397,42 @@ function hook_module_preuninstall($module) {
 }
 
 /**
+ * Perform necessary actions when themes are enabled.
+ *
+ * @param array $themes
+ *   An array of theme names which are enabled.
+ */
+function hook_themes_enabled(array $themes) {
+  // Add some state entries depending on the theme.
+  foreach ($themes as $theme) {
+    \Drupal::state()->set('example.' . $theme, 'some-value');
+  }
+}
+
+/**
+ * Perform necessary actions when themes are disabled.
+ *
+ * @param array $themes
+ *   An array of theme names which are enabled.
+ */
+function hook_themes_disabled(array $themes) {
+  // Update some state entries depending on the theme.
+  foreach ($themes as $theme) {
+    \Drupal::state()->set('example.' . $theme, 0);
+  }
+}
+
+/**
+ * Perform necessary actions when themes are uninstalled.
+ */
+function hook_themes_uninstalled(array $themes) {
+  // Remove some state entries depending on the theme.
+  foreach ($themes as $theme) {
+    \Drupal::state()->delete('example.' . $theme);
+  }
+}
+
+/**
  * Perform necessary actions after modules are uninstalled.
  *
  * This function differs from hook_uninstall() in that it gives all other
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index eb6cb0e..5ec5e21 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -64,6 +64,13 @@ class ThemeHandlerTest extends UnitTestCase {
   protected $configInstaller;
 
   /**
+   * The mocked config manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $configManager;
+
+  /**
    * The extension discovery.
    *
    * @var \Drupal\Core\Extension\ExtensionDiscovery|\PHPUnit_Framework_MockObject_MockObject
@@ -101,6 +108,7 @@ protected function setUp() {
     $this->state = new State(new KeyValueMemoryFactory());
     $this->infoParser = $this->getMock('Drupal\Core\Extension\InfoParserInterface');
     $this->configInstaller = $this->getMock('Drupal\Core\Config\ConfigInstallerInterface');
+    $this->configManager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
     $this->routeBuilder = $this->getMockBuilder('Drupal\Core\Routing\RouteBuilder')
       ->disableOriginalConstructor()
       ->getMock();
@@ -111,7 +119,7 @@ protected function setUp() {
       ->disableOriginalConstructor()
       ->getMock();
     $logger = $this->getMock('Psr\Log\LoggerInterface');
-    $this->themeHandler = new TestThemeHandler($this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $logger, $this->cssCollectionOptimizer, $this->configInstaller, $this->routeBuilder, $this->extensionDiscovery);
+    $this->themeHandler = new TestThemeHandler($this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $logger, $this->cssCollectionOptimizer, $this->configInstaller, $this->configManager, $this->routeBuilder, $this->extensionDiscovery);
 
     $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
     $this->getContainerWithCacheBins($cache_backend);
