diff --git a/core/core.services.yml b/core/core.services.yml
index 6134359..6568923 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -662,6 +662,11 @@ services:
     class: Zend\Feed\Writer\Extension\Threading\Renderer\Entry
   feed.writer.wellformedwebrendererentry:
     class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry
+  theme.initialisation:
+    class: Drupal\Core\Theme\Initialisation
+    arguments: ['@theme_handler', '@theme.negotiator']
+    calls:
+      - [setRequest, ['@?request=']]
   theme.registry:
     class: Drupal\Core\Theme\Registry
     arguments: ['@cache.cache', '@lock', '@module_handler']
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 6dfc270..c3aea66 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -417,6 +417,17 @@ function install_begin_request(&$install_state) {
       ->addArgument(new Reference('module_handler'))
       ->addTag('needs_destruction');
 
+    $container
+      ->register('theme.initialisation', 'Drupal\Core\Theme\Initialisation')
+      ->addArgument(new Reference('theme_handler'))
+      ->addArgument(new Reference('theme.negotiator'));
+    $container
+      ->register('theme.negotiator', 'Drupal\Core\Theme\ThemeNegotiator')
+      ->addArgument(new Reference('access_check.theme'))
+      ->setMethodCalls(array(array('setRequest', array(new Reference('request')))));
+    $container
+      ->register('access_check.theme', 'Drupal\Core\Theme\ThemeAccessCheck');
+
     // Register a module handler for managing enabled modules.
     $container
       ->register('module_handler', 'Drupal\Core\Extension\ModuleHandler');
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 46113c6..8d1999d 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -84,199 +84,7 @@ function drupal_theme_access($theme) {
  * Initializes the theme system by loading the theme.
  */
 function drupal_theme_initialize() {
-  global $theme, $user, $theme_key;
-
-  // If $theme is already set, assume the others are set, too, and do nothing
-  if (isset($theme)) {
-    return;
-  }
-
-  $themes = list_themes();
-
-  // @todo Let the theme.negotiator listen to the kernel request event.
-  // Determine the active theme for the theme negotiator service. This includes
-  // the default theme as well as really specific ones like the ajax base theme.
-  $request = \Drupal::request();
-  $theme = \Drupal::service('theme.negotiator')->determineActiveTheme($request) ?: 'stark';
-
-  // Store the identifier for retrieving theme settings with.
-  $theme_key = $theme;
-
-  // Find all our ancestor themes and put them in an array.
-  $base_theme = array();
-  $ancestor = $theme;
-  while ($ancestor && isset($themes[$ancestor]->base_theme)) {
-    $ancestor = $themes[$ancestor]->base_theme;
-    $base_theme[] = $themes[$ancestor];
-  }
-  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme));
-}
-
-/**
- * Initializes the theme system given already loaded information.
- *
- * This function is useful to initialize a theme when no database is present.
- *
- * @param $theme
- *   An object with the following information:
- *     filename
- *       The .info.yml file for this theme. The 'path' to
- *       the theme will be in this file's directory. (Required)
- *     owner
- *       The path to the .theme file or the .engine file to load for
- *       the theme. (Required)
- *     stylesheet
- *       The primary stylesheet for the theme. (Optional)
- *     engine
- *       The name of theme engine to use. (Optional)
- * @param $base_theme
- *    An optional array of objects that represent the 'base theme' if the
- *    theme is meant to be derivative of another theme. It requires
- *    the same information as the $theme object. It should be in
- *    'oldest first' order, meaning the top level of the chain will
- *    be first.
- */
-function _drupal_theme_initialize($theme, $base_theme = array()) {
-  global $theme_info, $base_theme_info, $theme_engine, $theme_path;
-  $theme_info = $theme;
-  $base_theme_info = $base_theme;
-
-  $theme_path = dirname($theme->filename);
-
-  // Prepare stylesheets from this theme as well as all ancestor themes.
-  // We work it this way so that we can have child themes override parent
-  // theme stylesheets easily.
-  $final_stylesheets = array();
-  // CSS file basenames to override, pointing to the final, overridden filepath.
-  $theme->stylesheets_override = array();
-  // CSS file basenames to remove.
-  $theme->stylesheets_remove = array();
-
-  // Grab stylesheets from base theme
-  foreach ($base_theme as $base) {
-    if (!empty($base->stylesheets)) {
-      foreach ($base->stylesheets as $media => $stylesheets) {
-        foreach ($stylesheets as $name => $stylesheet) {
-          $final_stylesheets[$media][$name] = $stylesheet;
-        }
-      }
-    }
-    $base_theme_path = dirname($base->filename);
-    if (!empty($base->info['stylesheets-remove'])) {
-      foreach ($base->info['stylesheets-remove'] as $basename) {
-        $theme->stylesheets_remove[$basename] = $base_theme_path . '/' . $basename;
-      }
-    }
-    if (!empty($base->info['stylesheets-override'])) {
-      foreach ($base->info['stylesheets-override'] as $name) {
-        $basename = drupal_basename($name);
-        $theme->stylesheets_override[$basename] = $base_theme_path . '/' . $name;
-      }
-    }
-  }
-
-  // Add stylesheets used by this theme.
-  if (!empty($theme->stylesheets)) {
-    foreach ($theme->stylesheets as $media => $stylesheets) {
-      foreach ($stylesheets as $name => $stylesheet) {
-        $final_stylesheets[$media][$name] = $stylesheet;
-      }
-    }
-  }
-  if (!empty($theme->info['stylesheets-remove'])) {
-    foreach ($theme->info['stylesheets-remove'] as $basename) {
-      $theme->stylesheets_remove[$basename] = $theme_path . '/' . $basename;
-
-      if (isset($theme->stylesheets_override[$basename])) {
-        unset($theme->stylesheets_override[$basename]);
-      }
-    }
-  }
-  if (!empty($theme->info['stylesheets-override'])) {
-    foreach ($theme->info['stylesheets-override'] as $name) {
-      $basename = drupal_basename($name);
-      $theme->stylesheets_override[$basename] = $theme_path . '/' . $name;
-
-      if (isset($theme->stylesheets_remove[$basename])) {
-        unset($theme->stylesheets_remove[$basename]);
-      }
-    }
-  }
-
-  // And now add the stylesheets properly.
-  $css = array();
-  foreach ($final_stylesheets as $media => $stylesheets) {
-    foreach ($stylesheets as $stylesheet) {
-      $css['#attached']['css'][$stylesheet] = array(
-        'group' => CSS_AGGREGATE_THEME,
-        'every_page' => TRUE,
-        'media' => $media
-      );
-    }
-  }
-  drupal_render($css);
-
-  // Do basically the same as the above for scripts
-  $final_scripts = array();
-
-  // Grab scripts from base theme
-  foreach ($base_theme as $base) {
-    if (!empty($base->scripts)) {
-      foreach ($base->scripts as $name => $script) {
-        $final_scripts[$name] = $script;
-      }
-    }
-  }
-
-  // Add scripts used by this theme.
-  if (!empty($theme->scripts)) {
-    foreach ($theme->scripts as $name => $script) {
-      $final_scripts[$name] = $script;
-    }
-  }
-
-  // Add scripts used by this theme.
-  $js = array();
-  foreach ($final_scripts as $script) {
-    $js['#attached']['js'][] = array(
-      'data' => $script,
-      'group' => JS_THEME,
-      'every_page' => TRUE,
-    );
-  }
-  drupal_render($js);
-
-  $theme_engine = NULL;
-
-  // Initialize the theme.
-  if (isset($theme->engine)) {
-    // Include the engine.
-    include_once DRUPAL_ROOT . '/' . $theme->owner;
-
-    $theme_engine = $theme->engine;
-    if (function_exists($theme_engine . '_init')) {
-      foreach ($base_theme as $base) {
-        call_user_func($theme_engine . '_init', $base);
-      }
-      call_user_func($theme_engine . '_init', $theme);
-    }
-  }
-  else {
-    // include non-engine theme files
-    foreach ($base_theme as $base) {
-      // Include the theme file or the engine.
-      if (!empty($base->owner)) {
-        include_once DRUPAL_ROOT . '/' . $base->owner;
-      }
-    }
-    // and our theme gets one too.
-    if (!empty($theme->owner)) {
-      include_once DRUPAL_ROOT . '/' . $theme->owner;
-    }
-  }
-
-  // Always include Twig as the default theme engine.
-  include_once DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine';
+  \Drupal::service('theme.initialisation')->initThemeSystem();
 }
 
 /**
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index 96dcd2f..e5826e3 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -90,8 +90,8 @@ function _drupal_maintenance_theme() {
     $base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme];
     $ancestor = $themes[$ancestor]->base_theme;
   }
-  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme), '_theme_load_offline_registry');
-  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme));
+  \Drupal::service('theme.initialisation')->addAssets($themes[$theme], array_reverse($base_theme));
+  \Drupal::service('theme.initialisation')->loadIncludes($themes[$theme], array_reverse($base_theme));
   // Prime the theme registry.
   // @todo Remove global theme variables.
   Drupal::service('theme.registry');
diff --git a/core/lib/Drupal/Core/Theme/DefaultNegotiator.php b/core/lib/Drupal/Core/Theme/DefaultNegotiator.php
index b08882d..94dc4e6 100644
--- a/core/lib/Drupal/Core/Theme/DefaultNegotiator.php
+++ b/core/lib/Drupal/Core/Theme/DefaultNegotiator.php
@@ -16,11 +16,11 @@
 class DefaultNegotiator implements ThemeNegotiatorInterface {
 
   /**
-   * The system theme config object.
+   * The config factory
    *
-   * @var \Drupal\Core\Config\Config
+   * @var \Drupal\Core\Config\ConfigFactory
    */
-  protected $config;
+  protected $configFactory;
 
   /**
    * Constructs a DefaultNegotiator object.
@@ -29,7 +29,7 @@ class DefaultNegotiator implements ThemeNegotiatorInterface {
    *   The config factory.
    */
   public function __construct(ConfigFactory $config_factory) {
-    $this->config = $config_factory->get('system.theme');
+    $this->configFactory = $config_factory;
   }
 
   /**
@@ -43,7 +43,7 @@ public function applies(Request $request) {
    * {@inheritdoc}
    */
   public function determineActiveTheme(Request $request) {
-    return $this->config->get('default');
+    return $this->configFactory->get('system.theme')->get('default');
   }
 
 }
diff --git a/core/lib/Drupal/Core/Theme/Initialisation.php b/core/lib/Drupal/Core/Theme/Initialisation.php
new file mode 100644
index 0000000..688c4b4
--- /dev/null
+++ b/core/lib/Drupal/Core/Theme/Initialisation.php
@@ -0,0 +1,269 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Theme\Initialisation.
+ */
+
+namespace Drupal\Core\Theme;
+
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Provides the theme initialisation logic.
+ */
+class Initialisation {
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * The theme negotiator.
+   *
+   * @var \Drupal\Core\Theme\ThemeNegotiator
+   */
+  protected $themeNegotiator;
+
+  /**
+   * The current request.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * Constructs a new Initialisation instance.
+   *
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
+   * @param \Drupal\Core\Theme\ThemeNegotiator $theme_negotiator
+   *   The theme negotiator.
+   */
+  public function __construct(ThemeHandlerInterface $theme_handler, ThemeNegotiator $theme_negotiator) {
+    $this->themeHandler = $theme_handler;
+    $this->themeNegotiator = $theme_negotiator;
+  }
+
+  /**
+   * Sets the current theme.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   */
+  public function setRequest(Request $request) {
+    $this->request = $request;
+  }
+
+  public function initThemeSystem() {
+    global $theme, $theme_key;
+
+    // If $theme is already set, assume the others are set, too, and do nothing
+    if (isset($theme)) {
+      return;
+    }
+
+    $themes = $this->themeHandler->listInfo();
+
+    // @todo Let the theme.negotiator listen to the kernel request event.
+    // Determine the active theme for the theme negotiator service. This includes
+    // the default theme as well as really specific ones like the ajax base theme.
+    $theme = $this->themeNegotiator->determineActiveTheme($this->request) ?: 'stark';
+
+    // Store the identifier for retrieving theme settings with.
+    $theme_key = $theme;
+
+    // Find all our ancestor themes and put them in an array.
+    $base_theme = array();
+    $ancestor = $theme;
+    while ($ancestor && isset($themes[$ancestor]->base_theme)) {
+      $ancestor = $themes[$ancestor]->base_theme;
+      $base_theme[] = $themes[$ancestor];
+    }
+    $this->addAssets($themes[$theme], array_reverse($base_theme));
+    $this->loadIncludes($themes[$theme], array_reverse($base_theme));
+  }
+
+  /**
+   * Initializes the theme system given already loaded information.
+   *
+   * This function is useful to initialize a theme when no database is present.
+   *
+   * @param $theme
+   *   An object with the following information:
+   *     filename
+   *       The .info.yml file for this theme. The 'path' to
+   *       the theme will be in this file's directory. (Required)
+   *     owner
+   *       The path to the .theme file or the .engine file to load for
+   *       the theme. (Required)
+   *     stylesheet
+   *       The primary stylesheet for the theme. (Optional)
+   *     engine
+   *       The name of theme engine to use. (Optional)
+   * @param $base_theme
+   *    An optional array of objects that represent the 'base theme' if the
+   *    theme is meant to be derivative of another theme. It requires
+   *    the same information as the $theme object. It should be in
+   *    'oldest first' order, meaning the top level of the chain will
+   *    be first.
+   */
+  public function addAssets($theme, $base_theme = array()) {
+    global $theme_info, $base_theme_info, $theme_path;
+    $theme_info = $theme;
+    $base_theme_info = $base_theme;
+
+    $theme_path = dirname($theme->filename);
+
+    // Prepare stylesheets from this theme as well as all ancestor themes.
+    // We work it this way so that we can have child themes override parent
+    // theme stylesheets easily.
+    $final_stylesheets = array();
+    // CSS file basenames to override, pointing to the final, overridden filepath.
+    $theme->stylesheets_override = array();
+    // CSS file basenames to remove.
+    $theme->stylesheets_remove = array();
+
+    // Grab stylesheets from base theme
+    foreach ($base_theme as $base) {
+      if (!empty($base->stylesheets)) {
+        foreach ($base->stylesheets as $media => $stylesheets) {
+          foreach ($stylesheets as $name => $stylesheet) {
+            $final_stylesheets[$media][$name] = $stylesheet;
+          }
+        }
+      }
+      $base_theme_path = dirname($base->filename);
+      if (!empty($base->info['stylesheets-remove'])) {
+        foreach ($base->info['stylesheets-remove'] as $basename) {
+          $theme->stylesheets_remove[$basename] = $base_theme_path . '/' . $basename;
+        }
+      }
+      if (!empty($base->info['stylesheets-override'])) {
+        foreach ($base->info['stylesheets-override'] as $name) {
+          $basename = drupal_basename($name);
+          $theme->stylesheets_override[$basename] = $base_theme_path . '/' . $name;
+        }
+      }
+    }
+
+    // Add stylesheets used by this theme.
+    if (!empty($theme->stylesheets)) {
+      foreach ($theme->stylesheets as $media => $stylesheets) {
+        foreach ($stylesheets as $name => $stylesheet) {
+          $final_stylesheets[$media][$name] = $stylesheet;
+        }
+      }
+    }
+    if (!empty($theme->info['stylesheets-remove'])) {
+      foreach ($theme->info['stylesheets-remove'] as $basename) {
+        $theme->stylesheets_remove[$basename] = $theme_path . '/' . $basename;
+
+        if (isset($theme->stylesheets_override[$basename])) {
+          unset($theme->stylesheets_override[$basename]);
+        }
+      }
+    }
+    if (!empty($theme->info['stylesheets-override'])) {
+      foreach ($theme->info['stylesheets-override'] as $name) {
+        $basename = drupal_basename($name);
+        $theme->stylesheets_override[$basename] = $theme_path . '/' . $name;
+
+        if (isset($theme->stylesheets_remove[$basename])) {
+          unset($theme->stylesheets_remove[$basename]);
+        }
+      }
+    }
+
+    // And now add the stylesheets properly.
+    $css = array();
+    foreach ($final_stylesheets as $media => $stylesheets) {
+      foreach ($stylesheets as $stylesheet) {
+        $css['#attached']['css'][$stylesheet] = array(
+          'group' => CSS_AGGREGATE_THEME,
+          'every_page' => TRUE,
+          'media' => $media
+        );
+      }
+    }
+    drupal_render($css);
+
+    // Do basically the same as the above for scripts
+    $final_scripts = array();
+
+    // Grab scripts from base theme
+    foreach ($base_theme as $base) {
+      if (!empty($base->scripts)) {
+        foreach ($base->scripts as $name => $script) {
+          $final_scripts[$name] = $script;
+        }
+      }
+    }
+
+    // Add scripts used by this theme.
+    if (!empty($theme->scripts)) {
+      foreach ($theme->scripts as $name => $script) {
+        $final_scripts[$name] = $script;
+      }
+    }
+
+    // Add scripts used by this theme.
+    $js = array();
+    foreach ($final_scripts as $script) {
+      $js['#attached']['js'][] = array(
+        'data' => $script,
+        'group' => JS_THEME,
+        'every_page' => TRUE,
+      );
+    }
+    drupal_render($js);
+  }
+
+  /**
+   * @param \stdClass $theme
+   * @param \stdClass $base_theme
+   *
+   * @return string
+   */
+  public function loadIncludes($theme, $base_theme) {
+    global $theme_engine;
+
+    $theme_engine = NULL;
+
+    // Initialize the theme.
+    if (isset($theme->engine)) {
+      // Include the engine.
+      include_once DRUPAL_ROOT . '/' . $theme->owner;
+
+      $theme_engine = $theme->engine;
+      if (function_exists($theme_engine . '_init')) {
+        foreach ($base_theme as $base) {
+          call_user_func($theme_engine . '_init', $base);
+        }
+        call_user_func($theme_engine . '_init', $theme);
+      }
+    }
+    else {
+      // include non-engine theme files
+      foreach ($base_theme as $base) {
+        // Include the theme file or the engine.
+        if (!empty($base->owner)) {
+          include_once DRUPAL_ROOT . '/' . $base->owner;
+        }
+      }
+      // and our theme gets one too.
+      if (!empty($theme->owner)) {
+        include_once DRUPAL_ROOT . '/' . $theme->owner;
+      }
+    }
+
+    // Always include Twig as the default theme engine.
+    include_once DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine';
+    return $theme_engine;
+  }
+
+}
