diff --git a/core/core.services.yml b/core/core.services.yml
index 802d143..1fa3efb 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -80,7 +80,9 @@ services:
     arguments: ['@config.storage', '@event_dispatcher', '@config.typed']
   config.installer:
     class: Drupal\Core\Config\ConfigInstaller
-    arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher']
+    arguments: ['@config.factory', '@config.storage', '@config.typed', '@event_dispatcher']
+    calls:
+      - [setConfigManager, ['@config.manager']]
   config.storage.staging:
     class: Drupal\Core\Config\FileStorage
     factory_class: Drupal\Core\Config\FileStorageFactory
@@ -180,9 +182,13 @@ services:
   module_handler:
     class: Drupal\Core\Extension\CachedModuleHandler
     arguments: ['%container.modules%', '@state', '@cache.bootstrap']
+    calls:
+      - [setThemeNegotiator, ['@?theme.negotiator']]
   theme_handler:
     class: Drupal\Core\Extension\ThemeHandler
-    arguments: ['@config.factory', '@module_handler', '@cache.cache', '@info_parser', '@config.installer', '@router.builder']
+    arguments: ['@config.factory', '@module_handler', '@cache.cache', '@info_parser', '@router.builder']
+    calls:
+      - [setConfigInstaller, ['@config.installer']]
   entity.manager:
     class: Drupal\Core\Entity\EntityManager
     arguments: ['@container.namespaces', '@service_container', '@module_handler', '@cache.cache', '@language_manager', '@string_translation']
@@ -470,7 +476,7 @@ services:
     class: Drupal\Core\Access\CsrfTokenGenerator
     arguments: ['@private_key']
     calls:
-      - [setCurrentUser, ['@?current_user']]
+      - [setCurrentUser, ['@?current_user=']]
   access_manager:
     class: Drupal\Core\Access\AccessManager
     arguments: ['@router.route_provider', '@url_generator', '@paramconverter_manager']
@@ -504,6 +510,7 @@ services:
       - { name: access_check, applies_to: _entity_create_access }
   access_check.theme:
     class: Drupal\Core\Theme\ThemeAccessCheck
+    arguments: ['@theme_handler']
     tags:
       - { name: access_check, applies_to: _access_theme }
   access_check.custom:
@@ -692,7 +699,7 @@ services:
     class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry
   theme.registry:
     class: Drupal\Core\Theme\Registry
-    arguments: ['@cache.cache', '@lock', '@module_handler']
+    arguments: ['@cache.cache', '@lock', '@module_handler', '@theme.negotiator']
     tags:
       - { name: needs_destruction }
   authentication:
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 9e5c50f..c580cb4 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1333,8 +1333,17 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
  */
 function drupal_anonymous_user() {
   try {
-    $request = \Drupal::request();
-    $hostname = $request->getClientIP();
+    if (\Drupal::hasRequest()) {
+      $request = \Drupal::request();
+      $hostname = $request->getClientIP();
+    }
+    else {
+      $hostname = '';
+    }
+  }
+  catch (InvalidArgumentException $e) {
+    // We are not in a request context.
+    $hostname = '';
   }
   catch (DependencyInjectionRuntimeException $e) {
     // We are not in a request context.
diff --git a/core/includes/common.inc b/core/includes/common.inc
index a2226c8..8342aeb 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2251,7 +2251,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
     // Don't add settings if there is no other JavaScript on the page, unless
     // this is an AJAX request.
     if (!empty($items['settings']) || $is_ajax) {
-      global $theme_key;
+      $theme_key = \Drupal::themeNegotiator()->getActiveTheme();
       // Provide the page with information about the theme that's used, so that
       // a later AJAX request can be rendered using the same theme.
       // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
@@ -4568,9 +4568,9 @@ function drupal_render_cache_by_query($query, $function, $expire = Cache::PERMAN
  *   $granularity was passed in, more parts are added.
  */
 function drupal_render_cid_parts($granularity = NULL) {
-  global $theme, $base_root;
+  global $base_root;
 
-  $cid_parts[] = $theme;
+  $cid_parts[] = \Drupal::themeNegotiator()->getActiveTheme();
 
   // If we have only one language enabled we do not need it as cid part.
   $language_manager = \Drupal::languageManager();
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index f699d4b..435994f 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -101,7 +101,7 @@ function drupal_theme_initialize() {
   // 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';
+  $theme = \Drupal::service('theme.negotiator')->getActiveTheme($request) ?: 'stark';
 
   // Store the identifier for retrieving theme settings with.
   $theme_key = $theme;
@@ -739,7 +739,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
       }
     }
   }
-  global $theme;
+  $theme = \Drupal::themeNegotiator()->getActiveTheme();
   $subtheme_paths = isset($theme_paths[$theme]) ? $theme_paths[$theme] : array();
 
   // Escape the periods in the extension.
@@ -841,7 +841,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
 
   // If no key is given, use the current theme if we can determine it.
   if (!isset($theme)) {
-    $theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : '';
+    $theme = \Drupal::themeNegotiator()->getActiveTheme();
   }
 
   if (empty($cache[$theme])) {
@@ -2239,7 +2239,8 @@ function template_preprocess_maintenance_page(&$variables) {
     drupal_render($build);
   }
 
-  foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
+  $theme = \Drupal::themeNegotiator()->getActiveTheme();
+  foreach (system_region_list($theme) as $region_key => $region_name) {
     if (!isset($variables[$region_key])) {
       $variables[$region_key] = array();
     }
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index d49338d..1756749 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -15,12 +15,13 @@
  * complete. Seven is always used for the initial install and update
  * operations. In other cases, Bartik is used, but this can be overridden by
  * setting a "maintenance_theme" key in the $settings variable in settings.php.
+ *
+ * @todo Figure out whether this logic could be put into a theme negotiator
+ *   itself.
  */
 function _drupal_maintenance_theme() {
-  global $theme, $theme_key;
-
   // If $theme is already set, assume the others are set too, and do nothing.
-  if (isset($theme)) {
+  if (\Drupal::themeNegotiator()->hasActiveTheme()) {
     return;
   }
 
@@ -87,6 +88,7 @@ function _drupal_maintenance_theme() {
 
   // Store the identifier for retrieving theme settings with.
   $theme_key = $theme;
+  \Drupal::themeNegotiator()->setActiveTheme($theme_key);
 
   // Find all our ancestor themes and put them in an array.
   $base_theme = array();
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index a646096..00b14dd 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -403,6 +403,15 @@ public static function moduleHandler() {
   }
 
   /**
+   * Returns the theme negotiator.
+   *
+   * @return \Drupal\Core\Theme\ThemeNegotiator
+   */
+  public static function themeNegotiator() {
+    return static::$container->get('theme.negotiator');
+  }
+
+  /**
    * Returns the typed data manager service.
    *
    * Use the typed data manager service for creating typed data objects.
diff --git a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
index ae108dc..c7c21e8 100644
--- a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
+++ b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Authentication\Provider;
 
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
+use Drupal\Core\Database\Database;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\Request;
@@ -33,6 +34,9 @@ public function authenticate(Request $request) {
     // Global $user is deprecated, but the session system is still based on it.
     global $user;
     require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
+    if (!Database::getConnection()->schema()->tableExists('users')) {
+      return NULL;
+    }
     drupal_session_initialize();
     if (drupal_session_started()) {
       return $user;
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 2bb06b3..f373787 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -56,20 +56,27 @@ class ConfigInstaller implements ConfigInstallerInterface {
    *   The active configuration storage.
    * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
    *   The typed configuration manager.
-   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
-   *   The configuration manager.
    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
    *   The event dispatcher.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher) {
+  public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, EventDispatcherInterface $event_dispatcher) {
     $this->configFactory = $config_factory;
     $this->activeStorage = $active_storage;
     $this->typedConfig = $typed_config;
-    $this->configManager = $config_manager;
     $this->eventDispatcher = $event_dispatcher;
   }
 
   /**
+   * Sets the config manager.
+   *
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The configuration manager.
+   */
+  public function setConfigManager(ConfigManagerInterface $config_manager) {
+    $this->configManager = $config_manager;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function installDefaultConfig($type, $name) {
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 425ed58..d9690bd 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Extension;
 
 use Drupal\Component\Graph\Graph;
+use Drupal\Core\Theme\ThemeNegotiator;
 use Symfony\Component\Yaml\Parser;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\CacheBackendInterface;
@@ -63,6 +64,13 @@ class ModuleHandler implements ModuleHandlerInterface {
   protected $alterFunctions;
 
   /**
+   * The theme negotiator.
+   *
+   * @var \Drupal\Core\Theme\ThemeNegotiator
+   */
+  protected $themeNegotiator;
+
+  /**
    * Constructs a ModuleHandler object.
    *
    * @param array $module_list
@@ -81,6 +89,16 @@ public function __construct(array $module_list = array()) {
   }
 
   /**
+   * Set the theme negotiator.
+   *
+   * @param \Drupal\Core\Theme\ThemeNegotiator $theme_negotiator
+   *   The theme negotiator.
+   */
+  public function setThemeNegotiator(ThemeNegotiator $theme_negotiator) {
+    $this->themeNegotiator = $theme_negotiator;
+  }
+
+  /**
    * Implements \Drupal\Core\Extension\ModuleHandlerInterface::load().
    */
   public function load($name) {
@@ -409,8 +427,8 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
       }
       // Allow the theme to alter variables after the theme system has been
       // initialized.
-      global $theme, $base_theme_info;
-      if (isset($theme)) {
+      global $base_theme_info;
+      if ($this->themeNegotiator && $this->themeNegotiator->hasActiveTheme() && $theme = $this->themeNegotiator->getActiveTheme()) {
         $theme_keys = array();
         foreach ($base_theme_info as $base) {
           $theme_keys[] = $base->getName();
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index db22e5f..08eea95 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -103,26 +103,33 @@ class ThemeHandler implements ThemeHandlerInterface {
    *   The cache backend to clear the local tasks cache.
    * @param \Drupal\Core\Extension\InfoParserInterface $info_parser
    *   The info parser to parse the theme.info.yml files.
-   * @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\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, CacheBackendInterface $cache_backend, InfoParserInterface $info_parser, ConfigInstallerInterface $config_installer = NULL, RouteBuilder $route_builder = NULL, ExtensionDiscovery $extension_discovery = NULL) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, InfoParserInterface $info_parser, RouteBuilder $route_builder = NULL, ExtensionDiscovery $extension_discovery = NULL) {
     $this->configFactory = $config_factory;
     $this->moduleHandler = $module_handler;
     $this->cacheBackend = $cache_backend;
     $this->infoParser = $info_parser;
-    $this->configInstaller = $config_installer;
     $this->routeBuilder = $route_builder;
     $this->extensionDiscovery = $extension_discovery;
   }
 
   /**
+   * Sets the config installer.
+   *
+   * @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.
+   */
+  public function setConfigInstaller(ConfigInstallerInterface $config_installer) {
+    $this->configInstaller = $config_installer;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function enable(array $theme_list) {
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 2389a62..9ea4ff6 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -75,6 +75,7 @@ public function alter(ContainerBuilder $container) {
       $definition = $container->getDefinition($id);
       $definition->clearTag('persist');
     }
+    $container->set('current_user', drupal_anonymous_user());
   }
 
 }
diff --git a/core/lib/Drupal/Core/Theme/Registry.php b/core/lib/Drupal/Core/Theme/Registry.php
index e84b33b..f25f9d7 100644
--- a/core/lib/Drupal/Core/Theme/Registry.php
+++ b/core/lib/Drupal/Core/Theme/Registry.php
@@ -115,6 +115,13 @@ class Registry implements DestructableInterface {
   protected $runtimeRegistry;
 
   /**
+   * The theme negotiation.
+   *
+   * @var \Drupal\Core\Theme\ThemeNegotiator
+   */
+  protected $theme_negotiator;
+
+  /**
    * Constructs a \Drupal\Core\\Theme\Registry object.
    *
    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
@@ -123,13 +130,16 @@ class Registry implements DestructableInterface {
    *   The lock backend.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler to use to load modules.
+   * @param \Drupal\Core\Theme\ThemeNegotiator $theme_negotiator
+   *   The theme negotiator.
    * @param string $theme_name
    *   (optional) The name of the theme for which to construct the registry.
    */
-  public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, ModuleHandlerInterface $module_handler, $theme_name = NULL) {
+  public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, ModuleHandlerInterface $module_handler, ThemeNegotiator $theme_negotiator, $theme_name = NULL) {
     $this->cache = $cache;
     $this->lock = $lock;
     $this->moduleHandler = $module_handler;
+    $this->themeNegotiator = $theme_negotiator;
     $this->init($theme_name);
   }
 
@@ -147,14 +157,14 @@ protected function init($theme_name = NULL) {
     if (!isset($theme_name)) {
       // #1: The theme registry might get instantiated before the theme was
       // initialized. Cope with that.
-      if (!isset($GLOBALS['theme_info']) || !isset($GLOBALS['theme'])) {
+      if (!isset($GLOBALS['theme_info']) || !$this->themeNegotiator->hasActiveTheme()) {
         unset($this->runtimeRegistry);
         unset($this->registry);
         drupal_theme_initialize();
       }
       // #2: The testing framework only cares for the global $theme variable at
       // this point. Cope with that.
-      if ($GLOBALS['theme'] != $GLOBALS['theme_info']->getName()) {
+      if ($this->themeNegotiator->getActiveTheme() != $GLOBALS['theme_info']->getName()) {
         unset($this->runtimeRegistry);
         unset($this->registry);
         $this->initializeTheme();
diff --git a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
index 75afddc..121fa6b 100644
--- a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
+++ b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Theme;
 
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Routing\Access\AccessInterface;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -18,6 +19,23 @@
 class ThemeAccessCheck implements AccessInterface {
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * Constructs a ThemeAccessCheck instance.
+   *
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
+   */
+  public function __construct(ThemeHandlerInterface $theme_handler) {
+    $this->themeHandler = $theme_handler;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function access(Route $route, Request $request, AccountInterface $account) {
@@ -34,7 +52,7 @@ public function access(Route $route, Request $request, AccountInterface $account
    *   TRUE if the theme is enabled, FALSE otherwise.
    */
   public function checkAccess($theme) {
-    $themes = list_themes();
+    $themes = $this->themeHandler->listInfo();
     return !empty($themes[$theme]->status);
   }
 
diff --git a/core/lib/Drupal/Core/Theme/ThemeNegotiator.php b/core/lib/Drupal/Core/Theme/ThemeNegotiator.php
index 21ba80c..285f471 100644
--- a/core/lib/Drupal/Core/Theme/ThemeNegotiator.php
+++ b/core/lib/Drupal/Core/Theme/ThemeNegotiator.php
@@ -118,6 +118,23 @@ public function getActiveTheme() {
   }
 
   /**
+   * Is there already an active theme.
+   */
+  public function hasActiveTheme() {
+    return $this->request->attributes->has('_theme_active');
+  }
+
+  /**
+   * Sets the current active theme for the request.
+   *
+   * @param string $theme
+   *   The theme name.
+   */
+  public function setActiveTheme($theme) {
+    $this->request->attributes->set('_theme_active', $theme);
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function applies(Request $request) {
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 1bca18b..4af3f42 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -112,10 +112,9 @@ function block_menu_link_defaults() {
  * Renders blocks into their regions.
  */
 function block_page_build(&$page) {
-  global $theme;
-
   // The theme system might not yet be initialized. We need $theme.
   drupal_theme_initialize();
+  $theme = \Drupal::themeNegotiator()->getActiveTheme();
 
   // Fetch a list of regions for the current theme.
   $all_regions = system_region_list($theme);
@@ -326,7 +325,7 @@ function block_list($region) {
   $blocks = &drupal_static(__FUNCTION__);
 
   if (!isset($blocks)) {
-    global $theme;
+    $theme = \Drupal::themeNegotiator()->getActiveTheme();
     $blocks = array();
     foreach (entity_load_multiple_by_properties('block', array('theme' => $theme)) as $block_id => $block) {
       // Onlye include valid blocks in the list.
diff --git a/core/modules/block/lib/Drupal/block/BlockListController.php b/core/modules/block/lib/Drupal/block/BlockListController.php
index 65db261..d6b271f 100644
--- a/core/modules/block/lib/Drupal/block/BlockListController.php
+++ b/core/modules/block/lib/Drupal/block/BlockListController.php
@@ -87,7 +87,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
   public function load() {
     // If no theme was specified, use the current theme.
     if (!$this->theme) {
-      $this->theme = $GLOBALS['theme'];
+      $this->theme = \Drupal::themeNegotiator()->getActiveTheme();
     }
 
     // Store the region list.
@@ -117,7 +117,7 @@ public function load() {
   public function render($theme = NULL, Request $request = NULL) {
     $this->request = $request;
     // If no theme was specified, use the current theme.
-    $this->theme = $theme ?: $GLOBALS['theme_key'];
+    $this->theme = $theme ?: \Drupal::themeNegotiator()->getActiveTheme();;
 
     return drupal_get_form($this);
   }
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 7809f5f..f9da95a 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -62,7 +62,7 @@ function color_form_system_theme_settings_alter(&$form, &$form_state) {
  * Replaces style sheets with color-altered style sheets.
  */
 function color_css_alter(&$css) {
-  global $theme_key;
+  $theme_key =  \Drupal::themeNegotiator()->getActiveTheme();
   $themes = list_themes();
 
   // Override stylesheets.
@@ -92,7 +92,7 @@ function color_css_alter(&$css) {
  * Replace the logo with the colored version if available.
  */
 function color_preprocess_page(&$variables) {
-  global $theme_key;
+  $theme_key = \Drupal::themeNegotiator()->getActiveTheme();
 
   // Override logo.
   $logo = \Drupal::config('color.' . $theme_key)->get('logo');
diff --git a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
index 9459aad..137bd64 100644
--- a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
@@ -282,8 +282,8 @@ public function buildForm(array $form, array &$form_state, $theme = '') {
       // Save the name of the current theme (if any), so that we can temporarily
       // override the current theme and allow theme_get_setting() to work
       // without having to pass the theme name to it.
-      $default_theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : NULL;
-      $GLOBALS['theme_key'] = $theme;
+      $default_theme = \Drupal::themeNegotiator()->getActiveTheme();
+      \Drupal::themeNegotiator()->setActiveTheme($theme);
 
       // Process the theme and all its base themes.
       foreach ($theme_keys as $theme) {
@@ -302,10 +302,10 @@ public function buildForm(array $form, array &$form_state, $theme = '') {
 
       // Restore the original current theme.
       if (isset($default_theme)) {
-        $GLOBALS['theme_key'] = $default_theme;
+        \Drupal::themeNegotiator()->setActiveTheme($default_theme);
       }
       else {
-        unset($GLOBALS['theme_key']);
+        \Drupal::themeNegotiator()->setActiveTheme(NULL);
       }
     }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/AlterTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/AlterTest.php
index e02c590..e249652 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/AlterTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/AlterTest.php
@@ -35,8 +35,8 @@ public static function getInfo() {
   function testDrupalAlter() {
     // This test depends on Bartik, so make sure that it is always the current
     // active theme.
-    global $theme, $base_theme_info;
-    $theme = 'bartik';
+    global $base_theme_info;
+    \Drupal::themeNegotiator()->setActiveTheme('bartik');
     $base_theme_info = array();
 
     $array = array('foo' => 'bar');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RegionContentTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RegionContentTest.php
index e8b8201..6450010 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RegionContentTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RegionContentTest.php
@@ -25,7 +25,7 @@ public static function getInfo() {
    * Tests setting and retrieving content for theme regions.
    */
   function testRegions() {
-    global $theme_key;
+    $theme_key = \Drupal::themeNegotiator()->getActiveTheme();
 
     $block_regions = array_keys(system_region_list($theme_key));
     $delimiter = $this->randomName(32);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
index 638d8e5..1f08a89 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
@@ -223,7 +223,7 @@ function testListThemes() {
    * Test the theme_get_setting() function.
    */
   function testThemeGetSetting() {
-    $GLOBALS['theme_key'] = 'test_theme';
+    \Drupal::themeNegotiator()->setActiveTheme('test_theme');
     $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', 'theme_get_setting() uses the default theme automatically.');
     $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), 'Base theme\'s default settings values can be overridden by subtheme.');
     $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', 'Base theme\'s default settings values are inherited by subtheme.');
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 9227c8a..589569b 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1896,7 +1896,7 @@ function system_retrieve_file($url, $destination = NULL, $managed = FALSE, $repl
 function system_page_alter(&$page) {
   // Find all non-empty page regions, and add a theme wrapper function that
   // allows them to be consistently themed.
-  $regions = system_region_list($GLOBALS['theme']);
+  $regions = system_region_list(\Drupal::themeNegotiator()->getActiveTheme());
   foreach (array_keys($regions) as $region) {
     if (!empty($page[$region])) {
       $page[$region]['#theme_wrappers'][] = 'region';
diff --git a/core/modules/system/tests/modules/batch_test/batch_test.module b/core/modules/system/tests/modules/batch_test/batch_test.module
index b97f966..96d39c2 100644
--- a/core/modules/system/tests/modules/batch_test/batch_test.module
+++ b/core/modules/system/tests/modules/batch_test/batch_test.module
@@ -374,8 +374,7 @@ function _batch_test_theme_callback() {
   // theme is being used on the batch processing page by viewing that page
   // directly. Instead, we save the theme being used in a variable here, so
   // that it can be loaded and inspected in the thread running the test.
-  global $theme;
-  batch_test_stack($theme);
+  batch_test_stack(\Drupal::themeNegotiator()->getActiveTheme());
 }
 
 /**
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.module b/core/modules/system/tests/modules/menu_test/menu_test.module
index 08e6382..aecd648 100644
--- a/core/modules/system/tests/modules/menu_test/menu_test.module
+++ b/core/modules/system/tests/modules/menu_test/menu_test.module
@@ -262,9 +262,9 @@ function menu_test_custom_403_404_callback() {
  * @deprecated Use \Drupal\menu_test\Controller\MenuTestController::themePage()
  */
 function menu_test_theme_page_callback($inherited = FALSE) {
-  global $theme_key;
   // Initialize the theme system so that $theme_key will be populated.
   drupal_theme_initialize();
+  $theme_key = \Drupal::themeNegotiator()->getActiveTheme();
   // Now we check what the theme negotiator service returns.
   $active_theme = \Drupal::service('theme.negotiator')->getActiveTheme('getActiveTheme');
   $output = "Active theme: $active_theme. Actual theme: $theme_key.";
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
index 665b7a5..2d1e0d0 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
@@ -314,7 +314,7 @@ public function generateOutputKey() {
         'result' => $this->view->result,
         'roles' => $user->getRoles(),
         'super-user' => $user->id() == 1, // special caching for super user.
-        'theme' => $GLOBALS['theme'],
+        'theme' => \Drupal::themeNegotiator()->getActiveTheme(),
         'langcode' => \Drupal::languageManager()->getCurrentLanguage()->id,
         'base_url' => $GLOBALS['base_url'],
       );
