diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index d49f5cd..8897412 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -105,8 +105,10 @@ function entity_invoke_bundle_hook($hook, $entity_type, $bundle, $bundle_new = N
 
   // Notify the entity storage controller.
   $method = 'onBundle' . ucfirst($hook);
-  Drupal::entityManager()->getStorageController($entity_type)->$method($bundle, $bundle_new);
-
+  $storage_controller = Drupal::entityManager()->getStorageController($entity_type);
+  if (method_exists($storage_controller, $method)) {
+    $storage_controller->$method($bundle, $bundle_new);
+  }
   // Invoke hook_entity_bundle_*() hooks.
   Drupal::moduleHandler()->invokeAll('entity_bundle_' . $hook, array($entity_type, $bundle, $bundle_new));
 }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 8e4b66e..28a4b17 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -995,7 +995,7 @@ function install_base_system(&$install_state) {
 
   // Enable the user module so that sessions can be recorded during the
   // upcoming bootstrap step.
-  module_enable(array('user'), FALSE);
+  Drupal::moduleHandler()->install(array('user'), FALSE);
 
   // Save the list of other modules to install for the upcoming tasks.
   // variable_set() can be used now that system.module is installed.
@@ -2031,7 +2031,7 @@ function _install_module_batch($module, $module_name, &$context) {
   // loaded by drupal_bootstrap in subsequent batch requests, and other
   // modules possibly depending on it can safely perform their installation
   // steps.
-  module_enable(array($module), FALSE);
+  Drupal::moduleHandler()->install(array($module), FALSE);
   $context['results'][] = $module;
   $context['message'] = t('Installed %module module.', array('%module' => $module_name));
 }
@@ -2522,7 +2522,7 @@ function install_configure_form_submit($form, &$form_state) {
 
   // Enable update.module if this option was selected.
   if ($form_state['values']['update_status_module'][1]) {
-    module_enable(array('file', 'update'), FALSE);
+    Drupal::moduleHandler()->install(array('file', 'update'), FALSE);
 
     // Add the site maintenance account's email address to the list of
     // addresses to be notified when updates are available, if selected.
diff --git a/core/includes/language.inc b/core/includes/language.inc
index 44e91c1..9fca508 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -203,8 +203,8 @@ function language_types_disable($types) {
  */
 function language_types_set(array $configurable_language_types) {
   // Ensure that we are getting the defined language negotiation information. An
-  // invocation of module_enable() or module_disable() could outdate the cached
-  // information.
+  // invocation of \Drupal\Core\Extension\ModuleHandler::install() or
+  // module_uninstall() could outdate the cached information.
   drupal_static_reset('language_types_info');
   drupal_static_reset('language_negotiation_info');
 
@@ -343,8 +343,8 @@ function language_negotiation_get_switch_links($type, $path) {
  */
 function language_negotiation_purge() {
   // Ensure that we are getting the defined language negotiation information. An
-  // invocation of module_enable() or module_disable() could outdate the cached
-  // information.
+  // invocation of \Drupal\Core\Extension\ModuleHandler::install() or
+  // module_uninstall() could outdate the cached information.
   drupal_static_reset('language_negotiation_info');
   drupal_static_reset('language_types_info');
 
diff --git a/core/includes/module.inc b/core/includes/module.inc
index 1a32c09..af7ece1 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -201,32 +201,21 @@ function module_load_include($type, $module, $name = NULL) {
   return FALSE;
 }
 
-
 /**
- * Enables or installs a given list of modules.
+ * Installs a given list of modules.
  *
  * @deprecated as of Drupal 8.0. Use
- *   Drupal::moduleHandler()->enable($module_list, $enable_dependencies = TRUE).
+ *   Drupal::moduleHandler()->install($module_list, $enable_dependencies = TRUE)
  */
 function module_enable($module_list, $enable_dependencies = TRUE) {
-  return Drupal::moduleHandler()->enable($module_list, $enable_dependencies);
-}
-
-/**
- * Disables a given set of modules.
- *
- * @deprecated as of Drupal 8.0. Use
- *   Drupal::moduleHandler()->disable($module_list, $disable_dependents = TRUE).
- */
-function module_disable($module_list, $disable_dependents = TRUE) {
-  Drupal::moduleHandler()->disable($module_list, $disable_dependents);
+  return Drupal::moduleHandler()->install($module_list, $enable_dependencies);
 }
 
 /**
- * Uninstalls a given list of disabled modules.
+ * Uninstalls a given list of modules.
  *
  * @deprecated as of Drupal 8.0. Use
- *   Drupal::moduleHandler()->uninstall($module_list, $uninstall_dependents = TRUE).
+ *   Drupal::moduleHandler()->uninstall($module_list, $uninstall_dependents = TRUE)
  */
 function module_uninstall($module_list = array(), $uninstall_dependents = TRUE) {
   return Drupal::moduleHandler()->uninstall($module_list, $uninstall_dependents);
@@ -332,7 +321,7 @@ function module_set_weight($module, $weight) {
       ->save();
 
     // Prepare the new module list, sorted by weight, including filenames.
-    // @see module_enable()
+    // @see \Drupal\Core\Extension\ModuleHandler::install()
     $module_handler = Drupal::moduleHandler();
     $current_module_filenames = $module_handler->getModuleList();
     $current_modules = array_fill_keys(array_keys($current_module_filenames), 0);
@@ -345,13 +334,6 @@ function module_set_weight($module, $weight) {
     $module_handler->setModuleList($module_filenames);
     return;
   }
-  $disabled_config = Drupal::config('system.module.disabled');
-  if ($disabled_config->get($module) !== NULL) {
-    $disabled_config
-      ->set($module, $weight)
-      ->save();
-    return;
-  }
 }
 
 /**
diff --git a/core/includes/update.inc b/core/includes/update.inc
index 5e8ff4e..9fa9269 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -335,7 +335,6 @@ function update_prepare_d8_bootstrap() {
       }
 
       $module_config = Drupal::config('system.module');
-      $disabled_modules = Drupal::config('system.module.disabled');
       $theme_config = Drupal::config('system.theme');
       $disabled_themes = Drupal::config('system.theme.disabled');
       $schema_store = Drupal::keyValue('system.schema');
@@ -375,12 +374,9 @@ function update_prepare_d8_bootstrap() {
         }
 
         if ($record->type == 'module') {
-          if ($record->status && isset($module_data[$record->name])) {
+          if (isset($module_data[$record->name])) {
             $module_config->set('enabled.' . $record->name, $record->weight);
           }
-          else {
-            $disabled_modules->set($record->name, $record->weight);
-          }
         }
         elseif ($record->type == 'theme') {
           if ($record->status) {
@@ -399,7 +395,6 @@ function update_prepare_d8_bootstrap() {
         $sorted_with_filenames[$m] = drupal_get_filename('module', $m);
       }
       Drupal::moduleHandler()->setModuleList($sorted_with_filenames);
-      $disabled_modules->save();
       $theme_config->save();
       $disabled_themes->save();
 
@@ -473,8 +468,7 @@ function update_prepare_stored_includes() {
  */
 function update_prepare_d8_language() {
   if (db_table_exists('languages')) {
-
-    module_enable(array('language'));
+    Drupal::moduleHandler()->install(array('language'));
 
     $languages = db_select('languages', 'l')
       ->fields('l')
@@ -666,7 +660,7 @@ function update_fix_d8_requirements() {
 
     // Make sure that file.module is enabled as it is required for the user
     // picture upgrade path.
-    module_enable(array('file'));
+    Drupal::moduleHandler()->install(array('file'));
 
     $schema = array(
       'description' => 'Generic key/value storage table with an expiration.',
@@ -711,7 +705,7 @@ function update_fix_d8_requirements() {
     // Like any other module APIs and services, Views' services are not available
     // in update.php. Existing listings are migrated into configuration, using
     // the limited standard tools of raw database queries and Drupal::config().
-    module_enable(array('views'));
+    Drupal::moduleHandler()->install(array('views'));
 
     update_variable_set('update_d8_requirements', TRUE);
   }
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index b9e5724..d773ba6 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -11,11 +11,10 @@
 use Symfony\Component\Yaml\Parser;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * Class that manages enabled modules in a Drupal installation.
+ * Class that manages modules in a Drupal installation.
  */
 class ModuleHandler implements ModuleHandlerInterface {
 
@@ -29,7 +28,7 @@ class ModuleHandler implements ModuleHandlerInterface {
   protected $loadedFiles;
 
   /**
-   * List of enabled modules.
+   * List of installed modules.
    *
    * @var array
    *   An associative array whose keys are the names of the modules and whose
@@ -69,7 +68,7 @@ class ModuleHandler implements ModuleHandlerInterface {
    * Constructs a ModuleHandler object.
    *
    * @param array $module_list
-   *   An associative array whose keys are the names of enabled modules and
+   *   An associative array whose keys are the names of installed modules and
    *   whose values are the module filenames. This is normally the
    *   %container.modules% parameter being set up by DrupalKernel.
    *
@@ -502,43 +501,53 @@ protected function parseDependency($dependency) {
   /**
    * {@inheritdoc}
    */
-  public function enable($module_list, $enable_dependencies = TRUE) {
-    if ($enable_dependencies) {
-      // Get all module data so we can find dependencies and sort.
-      $module_data = system_rebuild_module_data();
-      // Create an associative array with weights as values.
-      $module_list = array_flip(array_values($module_list));
+  public function install(array $module_list, $enable_dependencies = TRUE) {
+    // Get all module data so we can find dependencies and sort.
+    $module_data = system_rebuild_module_data();
+    $module_list = $module_list ? array_combine($module_list, $module_list) : array();
+    if (array_diff_key($module_list, $module_data)) {
+      // One or more of the given modules doesn't exist.
+      return FALSE;
+    }
 
-      while (list($module) = each($module_list)) {
-        if (!isset($module_data[$module])) {
-          // This module is not found in the filesystem, abort.
-          return FALSE;
-        }
-        if ($module_data[$module]->status) {
-          // Skip already enabled modules.
-          unset($module_list[$module]);
-          continue;
-        }
-        $module_list[$module] = $module_data[$module]->sort;
+    // Only process currently uninstalled modules.
+    $module_config = \Drupal::config('system.module');
+    $installed_modules = $module_config->get('enabled') ?: array();
+    if (!$module_list = array_diff_key($module_list, $installed_modules)) {
+      // Nothing to do. All modules already installed.
+      return TRUE;
+    }
 
-        // Add dependencies to the list, with a placeholder weight.
-        // The new modules will be processed as the while loop continues.
+    // Conditionally add the dependencies to the list of modules.
+    if ($enable_dependencies) {
+      // Add dependencies to the list. The new modules will be processed as the
+      // while loop continues.
+      while (list($module) = each($module_list)) {
         foreach (array_keys($module_data[$module]->requires) as $dependency) {
-          if (!isset($module_list[$dependency])) {
-            $module_list[$dependency] = 0;
+          if (!isset($module_data[$dependency])) {
+            // The dependency does not exist.
+            return FALSE;
+          }
+
+          // Skip already installed modules.
+          if (!isset($module_list[$dependency]) && !isset($installed_modules[$dependency])) {
+            $module_list[$dependency] = $dependency;
           }
         }
       }
+    }
 
-      if (!$module_list) {
-        // Nothing to do. All modules already enabled.
-        return TRUE;
-      }
+    // Set the actual module weights.
+    $module_list = array_map(function ($module) use ($module_data) {
+      return $module_data[$module]->sort;
+    }, $module_list);
 
-      // Sort the module list by pre-calculated weights.
-      arsort($module_list);
-      $module_list = array_keys($module_list);
-    }
+    // Sort the module list by their weights (reverse).
+    arsort($module_list);
+    $module_list = array_keys($module_list);
+
+    // Required for module installation checks.
+    include_once DRUPAL_ROOT . '/core/includes/install.inc';
 
     foreach ($module_list as $module) {
       // Throw an exception if the module name is too long.
@@ -548,139 +557,95 @@ public function enable($module_list, $enable_dependencies = TRUE) {
           '@max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH,
         )));
       }
-    }
-
-    // Required for module installation checks.
-    include_once DRUPAL_ROOT . '/core/includes/install.inc';
 
-    $modules_installed = array();
-    $modules_enabled = array();
-    $module_config = \Drupal::config('system.module');
-    $disabled_config = \Drupal::config('system.module.disabled');
-    foreach ($module_list as $module) {
-      // Only process modules that are not already enabled.
-      // A module is only enabled if it is configured as enabled. Custom or
-      // overridden module handlers might contain the module already, which means
-      // that it might be loaded, but not necessarily installed or enabled.
-      $enabled = $module_config->get("enabled.$module") !== NULL;
-      if (!$enabled) {
-        $weight = $disabled_config->get($module);
-        if ($weight === NULL) {
-          $weight = 0;
+      $module_config
+        ->set("enabled.$module", 0)
+        ->set('enabled', module_config_sort($module_config->get('enabled')))
+        ->save();
+
+      // Prepare the new module list, sorted by weight, including filenames.
+      // This list is used for both the ModuleHandler and DrupalKernel. It needs
+      // to be kept in sync between both. A DrupalKernel reboot or rebuild will
+      // automatically re-instantiate a new ModuleHandler that uses the new
+      // module list of the kernel. However, DrupalKernel does not cause any
+      // modules to be loaded.
+      // Furthermore, the currently active (fixed) module list can be different
+      // from the configured list of enabled modules. For all active modules not
+      // contained in the configured enabled modules, we assume a weight of 0.
+      $current_module_filenames = $this->getModuleList();
+      $current_modules = array_fill_keys(array_keys($current_module_filenames), 0);
+      $current_modules = module_config_sort(array_merge($current_modules, $module_config->get('enabled')));
+      $module_filenames = array();
+      foreach ($current_modules as $name => $weight) {
+        if (isset($current_module_filenames[$name])) {
+          $module_filenames[$name] = $current_module_filenames[$name];
         }
-        $module_config
-          ->set("enabled.$module", $weight)
-          ->set('enabled', module_config_sort($module_config->get('enabled')))
-          ->save();
-        $disabled_config
-          ->clear($module)
-          ->save();
-
-        // Prepare the new module list, sorted by weight, including filenames.
-        // This list is used for both the ModuleHandler and DrupalKernel. It needs
-        // to be kept in sync between both. A DrupalKernel reboot or rebuild will
-        // automatically re-instantiate a new ModuleHandler that uses the new
-        // module list of the kernel. However, DrupalKernel does not cause any
-        // modules to be loaded.
-        // Furthermore, the currently active (fixed) module list can be different
-        // from the configured list of enabled modules. For all active modules not
-        // contained in the configured enabled modules, we assume a weight of 0.
-        $current_module_filenames = $this->getModuleList();
-        $current_modules = array_fill_keys(array_keys($current_module_filenames), 0);
-        $current_modules = module_config_sort(array_merge($current_modules, $module_config->get('enabled')));
-        $module_filenames = array();
-        foreach ($current_modules as $name => $weight) {
-          if (isset($current_module_filenames[$name])) {
-            $filename = $current_module_filenames[$name];
-          }
-          else {
-            $filename = drupal_get_filename('module', $name);
-          }
-          $module_filenames[$name] = $filename;
+        else {
+          $module_filenames[$name] = drupal_get_filename('module', $name);
         }
+      }
 
-        // Update the module handler in order to load the module's code.
-        // This allows the module to participate in hooks and its existence to be
-        // discovered by other modules.
-        // The current ModuleHandler instance is obsolete with the kernel rebuild
-        // below.
-        $this->setModuleList($module_filenames);
-        $this->load($module);
-        module_load_install($module);
-
-        // Flush theme info caches, since (testing) modules can implement
-        // hook_system_theme_info() to register additional themes.
-        system_list_reset();
-
-        // Update the kernel to include it.
-        // This reboots the kernel to register the module's bundle and its
-        // services in the service container. The $module_filenames argument is
-        // taken over as %container.modules% parameter, which is passed to a fresh
-        // ModuleHandler instance upon first retrieval.
-        // @todo install_begin_request() creates a container without a kernel.
-        if ($kernel = drupal_container()->get('kernel', ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
-          $kernel->updateModules($module_filenames, $module_filenames);
-        }
+      // Update the module handler in order to load the module's code.
+      // This allows the module to participate in hooks and its existence to be
+      // discovered by other modules.
+      // The current ModuleHandler instance is obsolete with the kernel rebuild
+      // below.
+      $this->setModuleList($module_filenames);
+      $this->load($module);
+      module_load_install($module);
+
+      // Flush theme info caches, since (testing) modules can implement
+      // hook_system_theme_info() to register additional themes.
+      system_list_reset();
+
+      // Update the kernel to include it.
+      // This reboots the kernel to register the module's bundle and its
+      // services in the service container. The $module_filenames argument is
+      // taken over as %container.modules% parameter, which is passed to a fresh
+      // ModuleHandler instance upon first retrieval.
+      // @todo install_begin_request() creates a container without a kernel.
+      if ($kernel = \Drupal::service('kernel', ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
+        $kernel->updateModules($module_filenames, $module_filenames);
+      }
 
         // Refresh the schema to include it.
         drupal_get_schema(NULL, TRUE);
         // Update the theme registry to include it.
         drupal_theme_rebuild();
 
-        // Allow modules to react prior to the installation of a module.
-        $this->invokeAll('modules_preinstall', array(array($module)));
-
-        // Clear the entity info cache before importing new configuration.
-        entity_info_cache_clear();
+      // Allow modules to react prior to the installation of a module.
+      $this->invokeAll('module_preinstall', array($module));
 
-        // Now install the module if necessary.
-        if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) {
-          drupal_install_schema($module);
-
-          // Set the schema version to the number of the last update provided
-          // by the module.
-          $versions = drupal_get_schema_versions($module);
-          $version = $versions ? max($versions) : SCHEMA_INSTALLED;
+      // Clear the entity info cache before importing new configuration.
+      entity_info_cache_clear();
 
-          // Install default configuration of the module.
-          config_install_default_config('module', $module);
+      // Now install the module's schema if necessary.
+      drupal_install_schema($module);
 
-          // If the module has no current updates, but has some that were
-          // previously removed, set the version to the value of
-          // hook_update_last_removed().
-          if ($last_removed = $this->invoke($module, 'update_last_removed')) {
-            $version = max($version, $last_removed);
-          }
-          drupal_set_installed_schema_version($module, $version);
-          // Allow the module to perform install tasks.
-          $this->invoke($module, 'install');
-          // Record the fact that it was installed.
-          $modules_installed[] = $module;
-          watchdog('system', '%module module installed.', array('%module' => $module), WATCHDOG_INFO);
-        }
+      // Set the schema version to the number of the last update provided
+      // by the module.
+      $versions = drupal_get_schema_versions($module);
+      $version = $versions ? max($versions) : SCHEMA_INSTALLED;
 
-        // Allow modules to react prior to the enabling of a module.
-        entity_info_cache_clear();
-        $this->invokeAll('modules_preenable', array(array($module)));
+      // Install default configuration of the module.
+      config_install_default_config('module', $module);
 
-        // Enable the module.
-        $this->invoke($module, 'enable');
-
-        // Record the fact that it was enabled.
-        $modules_enabled[] = $module;
-        watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO);
+      // If the module has no current updates, but has some that were
+      // previously removed, set the version to the value of
+      // hook_update_last_removed().
+      if ($last_removed = $this->invoke($module, 'update_last_removed')) {
+        $version = max($version, $last_removed);
       }
-    }
+      drupal_set_installed_schema_version($module, $version);
 
-    // If any modules were newly installed, invoke hook_modules_installed().
-    if (!empty($modules_installed)) {
-      $this->invokeAll('modules_installed', array($modules_installed));
+      // Allow the module to perform install tasks.
+      $this->invoke($module, 'install');
+      // Record the fact that it was installed.
+      watchdog('system', '%module module installed.', array('%module' => $module), WATCHDOG_INFO);
     }
 
-    // If any modules were newly enabled, invoke hook_modules_enabled().
-    if (!empty($modules_enabled)) {
-      $this->invokeAll('modules_enabled', array($modules_enabled));
-    }
+    // If any modules were newly installed, invoke hook_modules_installed().
+    $this->invokeAll('modules_installed', array($module_list));
 
     return TRUE;
   }
@@ -688,184 +653,147 @@ public function enable($module_list, $enable_dependencies = TRUE) {
   /**
    * {@inheritdoc}
    */
-  function disable($module_list, $disable_dependents = TRUE) {
-    if ($disable_dependents) {
-      // Get all module data so we can find dependents and sort.
-      $module_data = system_rebuild_module_data();
-      // Create an associative array with weights as values.
-      $module_list = array_flip(array_values($module_list));
+  public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
+    // Get all module data so we can find dependencies and sort.
+    $module_data = system_rebuild_module_data();
+    $module_list = $module_list ? array_combine($module_list, $module_list) : array();
+    if (array_diff_key($module_list, $module_data)) {
+      // One or more of the given modules doesn't exist.
+      return FALSE;
+    }
+
+    // Only process currently installed modules.
+    $module_config = \Drupal::config('system.module');
+    $installed_modules = $module_config->get('enabled') ?: array();
+    if (!$module_list = array_intersect_key($module_list, $installed_modules)) {
+      // Nothing to do. All modules already uninstalled.
+      return TRUE;
+    }
 
+    if ($uninstall_dependents) {
+      // Add dependent modules to the list. The new modules will be processed as
+      // the while loop continues.
       $profile = drupal_get_profile();
       while (list($module) = each($module_list)) {
-        if (!isset($module_data[$module]) || !$module_data[$module]->status) {
-          // This module doesn't exist or is already disabled, skip it.
-          unset($module_list[$module]);
-          continue;
-        }
-        $module_list[$module] = $module_data[$module]->sort;
+        foreach (array_keys($module_data[$module]->required_by) as $dependent) {
+          if (!isset($module_data[$dependent])) {
+            // The dependent module does not exist.
+            return FALSE;
+          }
 
-        // Add dependent modules to the list, with a placeholder weight.
-        // The new modules will be processed as the while loop continues.
-        foreach ($module_data[$module]->required_by as $dependent => $dependent_data) {
-          if (!isset($module_list[$dependent]) && $dependent != $profile) {
-            $module_list[$dependent] = 0;
+          // Skip already uninstalled modules.
+          if (isset($installed_modules[$dependent]) && !isset($module_list[$dependent]) && $dependent != $profile) {
+            $module_list[$dependent] = TRUE;
           }
         }
       }
-
-      // Sort the module list by pre-calculated weights.
-      asort($module_list);
-      $module_list = array_keys($module_list);
     }
 
-    $invoke_modules = array();
+    // Set the actual module weights.
+    $module_list = array_map(function ($module) use ($module_data) {
+      return $module_data[$module]->sort;
+    }, $module_list);
 
-    $module_config = \Drupal::config('system.module');
-    $disabled_config = \Drupal::config('system.module.disabled');
+    // Sort the module list by their weights.
+    asort($module_list);
+    $module_list = array_keys($module_list);
+
+    // Only process modules that are enabled. A module is only enabled if it is
+    // configured as enabled. Custom or overridden module handlers might contain
+    // the module already, which means that it might be loaded, but not
+    // necessarily installed.
+    $schema_store = \Drupal::keyValue('system.schema');
     foreach ($module_list as $module) {
-      // Only process modules that are enabled.
-      // A module is only enabled if it is configured as enabled. Custom or
-      // overridden module handlers might contain the module already, which means
-      // that it might be loaded, but not necessarily installed or enabled.
-      $enabled = $module_config->get("enabled.$module") !== NULL;
-      if ($enabled) {
-        module_load_install($module);
-        module_invoke($module, 'disable');
-
-        $disabled_config
-          ->set($module, $module_config->get($module))
-          ->save();
-        $module_config
-          ->clear("enabled.$module")
-          ->save();
-
-        // Update the module handler to remove the module.
-        // The current ModuleHandler instance is obsolete with the kernel rebuild
-        // below.
-        $module_filenames = $this->getModuleList();
-        unset($module_filenames[$module]);
-        $this->setModuleList($module_filenames);
-
-        // Record the fact that it was disabled.
-        $invoke_modules[] = $module;
-        watchdog('system', '%module module disabled.', array('%module' => $module), WATCHDOG_INFO);
-      }
-    }
+      // Allow modules to react prior to the uninstallation of a module.
+      $this->invokeAll('module_preuninstall', array($module));
 
-    if (!empty($invoke_modules)) {
-      // @todo Most of the following should happen in above loop already.
+      // Uninstall the module.
+      module_load_install($module);
+      $this->invoke($module, 'uninstall');
+      drupal_uninstall_schema($module);
 
-      // Refresh the system list to exclude the disabled modules.
+      // Remove all configuration belonging to the module.
+      config_uninstall_default_config('module', $module);
+
+      // Remove the module's entry from the config.
+      $module_config->clear("enabled.$module")->save();
+
+      // Update the module handler to remove the module.
+      // The current ModuleHandler instance is obsolete with the kernel rebuild
+      // below.
+      $module_filenames = $this->getModuleList();
+      unset($module_filenames[$module]);
+      $this->setModuleList($module_filenames);
+
+      // Remove any potential cache bins provided by the module.
+      $this->removeCacheBins($module);
+
+      // Refresh the system list to exclude the uninstalled modules.
       // @todo Only needed to rebuild theme info.
       // @see system_list_reset()
       system_list_reset();
 
+      // Clear the entity info cache.
       entity_info_cache_clear();
 
-      // Invoke hook_modules_disabled before disabling modules,
-      // so we can still call module hooks to get information.
-      $this->invokeAll('modules_disabled', array($invoke_modules));
-
-      // Update the kernel to exclude the disabled modules.
-      $enabled = $this->getModuleList();
-      drupal_container()->get('kernel')->updateModules($enabled, $enabled);
+      // Update the kernel to exclude the uninstalled modules.
+      \Drupal::service('kernel')->updateModules($module_filenames, $module_filenames);
 
-      // Update the theme registry to remove the newly-disabled module.
+      // Update the theme registry to remove the newly uninstalled module.
       drupal_theme_rebuild();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function uninstall($module_list = array(), $uninstall_dependents = TRUE) {
-    if ($uninstall_dependents) {
-      // Get all module data so we can find dependents and sort.
-      $module_data = system_rebuild_module_data();
-      // Create an associative array with weights as values.
-      $module_list = array_flip(array_values($module_list));
 
-      $profile = drupal_get_profile();
-      while (list($module) = each($module_list)) {
-        if (!isset($module_data[$module]) || drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED) {
-          // This module doesn't exist or is already uninstalled. Skip it.
-          unset($module_list[$module]);
-          continue;
-        }
-        $module_list[$module] = $module_data[$module]->sort;
-
-        // If the module has any dependents which are not already uninstalled and
-        // not included in the passed-in list, abort. It is not safe to uninstall
-        // them automatically because uninstalling a module is a destructive
-        // operation.
-        foreach (array_keys($module_data[$module]->required_by) as $dependent) {
-          if (!isset($module_list[$dependent]) && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED && $dependent != $profile) {
-            return FALSE;
-          }
-        }
-      }
+      watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
 
-      // Sort the module list by pre-calculated weights.
-      asort($module_list);
-      $module_list = array_keys($module_list);
+      $schema_store->delete($module);
     }
+    drupal_get_installed_schema_version(NULL, TRUE);
 
-    $schema_store = \Drupal::keyValue('system.schema');
-    $disabled_config = \Drupal::config('system.module.disabled');
-    foreach ($module_list as $module) {
-      // Uninstall the module.
-      module_load_install($module);
-      $this->invoke($module, 'uninstall');
-      drupal_uninstall_schema($module);
+    // Let other modules react.
+    $this->invokeAll('modules_uninstalled', array($module_list));
 
-      // Remove all configuration belonging to the module.
-      config_uninstall_default_config('module', $module);
+    drupal_flush_all_caches();
 
-      // Remove any cache bins defined by the module.
-      $service_yaml_file = drupal_get_path('module', $module) . "/$module.services.yml";
-      if (file_exists($service_yaml_file)) {
-        $parser = new Parser;
-        $definitions = $parser->parse(file_get_contents($service_yaml_file));
-        if (isset($definitions['services'])) {
-          foreach ($definitions['services'] as $id => $definition) {
-            if (isset($definition['tags'])) {
-              foreach ($definition['tags'] as $tag) {
-                // This works for the default cache registration and even in some
-                // cases when a non-default "super" factory is used. That should
-                // be extremely rare.
-                if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
-                  try {
-                    $factory = \Drupal::service($definition['factory_service']);
-                    if (method_exists($factory, $definition['factory_method'])) {
-                      $backend = call_user_func_array(array($factory, $definition['factory_method']), $definition['arguments']);
-                      if ($backend instanceof CacheBackendInterface) {
-                        $backend->removeBin();
-                      }
+    return TRUE;
+  }
+
+  /**
+   * Helper method for removing all cache bins registered by a given module.
+   *
+   * @param string $module
+   *   The name of the module for which to remove all registered cache bins.
+   */
+  protected function removeCacheBins($module) {
+    // Remove any cache bins defined by a module.
+    $service_yaml_file = drupal_get_path('module', $module) . "/$module.services.yml";
+    if (file_exists($service_yaml_file)) {
+      $parser = new Parser;
+      $definitions = $parser->parse(file_get_contents($service_yaml_file));
+      if (isset($definitions['services'])) {
+        foreach ($definitions['services'] as $id => $definition) {
+          if (isset($definition['tags'])) {
+            foreach ($definition['tags'] as $tag) {
+              // This works for the default cache registration and even in some
+              // cases when a non-default "super" factory is used. That should
+              // be extremely rare.
+              if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
+                try {
+                  $factory = \Drupal::service($definition['factory_service']);
+                  if (method_exists($factory, $definition['factory_method'])) {
+                    $backend = call_user_func_array(array($factory, $definition['factory_method']), $definition['arguments']);
+                    if ($backend instanceof CacheBackendInterface) {
+                      $backend->removeBin();
                     }
                   }
-                  catch (\Exception $e) {
-                    watchdog_exception('system', $e, 'Failed to remove cache bin defined by the service %id.', array('%id' => $id));
-                  }
+                }
+                catch (\Exception $e) {
+                  watchdog_exception('system', $e, 'Failed to remove cache bin defined by the service %id.', array('%id' => $id));
                 }
               }
             }
           }
         }
       }
-
-      watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
-      $schema_store->delete($module);
-      $disabled_config->clear($module);
     }
-    $disabled_config->save();
-    drupal_get_installed_schema_version(NULL, TRUE);
-
-    if (!empty($module_list)) {
-      // Let other modules react.
-      $this->invokeAll('modules_uninstalled', array($module_list));
-    }
-
-    return TRUE;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php
index b93e3e8..13e19a4 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php
@@ -253,77 +253,50 @@ public function invokeAll($hook, $args = array());
   public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL);
 
   /**
-   * Enables or installs a given list of modules.
-   *
-   * Definitions:
-   * - "Enabling" is the process of activating a module for use by Drupal.
-   * - "Disabling" is the process of deactivating a module.
-   * - "Installing" is the process of enabling it for the first time or after it
-   *   has been uninstalled.
-   * - "Uninstalling" is the process of removing all traces of a module.
+   * Installs a given list of modules.
    *
    * Order of events:
    * - Gather and add module dependencies to $module_list (if applicable).
-   * - For each module that is being enabled:
+   * - For each module that is being installed:
+   *   - Invoke hook_module_preinstall().
    *   - Install module schema and update system registries and caches.
-   *   - If the module is being enabled for the first time or had been
-   *     uninstalled, invoke hook_install() and add it to the list of installed
-   *     modules.
-   *   - Invoke hook_enable().
+   *   - Invoke hook_install() and add it to the list of installed modules.
    * - Invoke hook_modules_installed().
-   * - Invoke hook_modules_enabled().
    *
-   * @param $module_list
+   * @param array $module_list
    *   An array of module names.
    * @param $enable_dependencies
-   *   If TRUE, dependencies will automatically be added and enabled in the
+   *   (optional) If TRUE, dependencies will automatically be installed in the
    *   correct order. This incurs a significant performance cost, so use FALSE
-   *   if you know $module_list is already complete and in the correct order.
+   *   if you know $module_list is already complete.
    *
    * @return
    *   FALSE if one or more dependencies are missing, TRUE otherwise.
    *
+   * @see hook_module_preinstall()
    * @see hook_install()
-   * @see hook_enable()
    * @see hook_modules_installed()
-   * @see hook_modules_enabled()
-   */
-  public function enable($module_list, $enable_dependencies = TRUE);
-
-  /**
-   * Disables a given set of modules.
-   *
-   * @param $module_list
-   *   An array of module names.
-   * @param $disable_dependents
-   *   If TRUE, dependent modules will automatically be added and disabled in the
-   *   correct order. This incurs a significant performance cost, so use FALSE
-   *   if you know $module_list is already complete and in the correct order.
    */
-  public function disable($module_list, $disable_dependents = TRUE);
+  public function install(array $module_list, $enable_dependencies = TRUE);
 
   /**
    * Uninstalls a given list of disabled modules.
    *
    * @param array $module_list
-   *   The modules to uninstall. It is the caller's responsibility to ensure that
-   *   all modules in this list have already been disabled before this function
-   *   is called.
+   *   The modules to uninstall.
    * @param bool $uninstall_dependents
-   *   (optional) If TRUE, the function will check that all modules which depend
-   *   on the passed-in module list either are already uninstalled or contained in
-   *   the list, and it will ensure that the modules are uninstalled in the
-   *   correct order. This incurs a significant performance cost, so use FALSE if
-   *   you know $module_list is already complete and in the correct order.
-   *   Defaults to TRUE.
+   *   (optional) If TRUE, dependent modules will automatically be uninstalled
+   *   in the correct order. This incurs a significant performance cost, so use
+   *   FALSE if you know $module_list is already complete.
    *
    * @return bool
-   *   Returns TRUE if the operation succeeds or FALSE if it aborts due to an
-   *   unsafe condition, namely, $uninstall_dependents is TRUE and a module in
-   *   $module_list has dependents which are not already uninstalled and not also
-   *   included in $module_list).
+   *   FALSE if one or more dependencies are missing, TRUE otherwise.
+   *
+   * @see hook_module_preuninstall()
+   * @see hook_uninstall()
+   * @see hook_modules_uninstalled()
    */
-  public function uninstall($module_list = array(), $uninstall_dependents = TRUE);
+  public function uninstall(array $module_list, $uninstall_dependents = TRUE);
 
   /**
    * Returns an array of directories for all enabled modules. Useful for
diff --git a/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php b/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php
index 78553d9..ef3a9a4 100644
--- a/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php
@@ -58,7 +58,7 @@ public function getImplementations($hook) {
   /**
    * {@inheritdoc}
    */
-  public function enable($module_list, $enable_dependencies = TRUE) {
+  public function install(array $module_list, $enable_dependencies = TRUE) {
     $schema_store = \Drupal::keyValue('system.schema');
     $old_schema = array();
     foreach ($module_list as $module) {
@@ -74,16 +74,13 @@ public function enable($module_list, $enable_dependencies = TRUE) {
           db_create_table($table, $spec);
         }
       }
+
       // Enable the module with a weight of 0.
       $module_config = \Drupal::config('system.module');
       $module_config
         ->set("enabled.$module", 0)
         ->set('enabled', module_config_sort($module_config->get('enabled')))
         ->save();
-      // Ensure the module is not contained in disabled modules.
-      \Drupal::config('system.module.disabled')
-        ->clear($module)
-        ->save();
 
       $current_schema = $schema_store->get($module);
       // Set the schema version if the module was not just disabled before.
@@ -105,7 +102,7 @@ public function enable($module_list, $enable_dependencies = TRUE) {
       $module_config_path = drupal_get_path('module', $module) . '/config';
       if (is_dir($module_config_path)) {
         $module_filestorage = new FileStorage($module_config_path);
-        $config_storage = drupal_container()->get('config.storage');
+        $config_storage = \Drupal::getContainer()->get('config.storage');
         foreach ($module_filestorage->listAll() as $config_name) {
           // If this file already exists, something in the upgrade path went
           // completely wrong and we want to know.
@@ -134,14 +131,7 @@ public function enable($module_list, $enable_dependencies = TRUE) {
   /**
    * {@inheritdoc}
    */
-  public function disable($module_list, $disable_dependents = TRUE) {
-    throw new \LogicException('Disabling modules is not supported during updates');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function uninstall($module_list = array(), $uninstall_dependents = TRUE) {
+  public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
     throw new \LogicException('Uninstalling modules is not supported during updates');
   }
 
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php
index 59d5339..f2f9c5f 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php
@@ -59,7 +59,7 @@ function testSettingsPage() {
 
     // Make sure settings form is still accessible even after disabling a module
     // that provides the selected plugins.
-    module_disable(array('aggregator_test'));
+    module_uninstall(array('aggregator_test'));
     $this->resetAll();
     $this->drupalGet('admin/config/services/aggregator/settings');
     $this->assertResponse(200);
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php
index 2cc1c8c..0c4f810 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php
@@ -72,7 +72,7 @@ function testUpdateFeedItem() {
     // Make sure updating items works even after disabling a module
     // that provides the selected plugins.
     $this->enableTestPlugins();
-    module_disable(array('aggregator_test'));
+    module_uninstall(array('aggregator_test'));
     $this->updateFeedItems($feed);
     $this->assertResponse(200);
   }
diff --git a/core/modules/block/block.install b/core/modules/block/block.install
index 4363ef8..6b9cc26 100644
--- a/core/modules/block/block.install
+++ b/core/modules/block/block.install
@@ -184,7 +184,7 @@ function block_update_8005() {
  * Enable the Custom Block module.
  */
 function block_update_8006() {
-  module_enable(array('custom_block'));
+  Drupal::moduleHandler()->install(array('custom_block'));
 }
 
 /**
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
index 404b436..a09cb14 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
@@ -213,7 +213,7 @@ function moveBlockToRegion(array $block, $region) {
    * Test _block_rehash().
    */
   function testBlockRehash() {
-    module_enable(array('block_test'));
+    \Drupal::moduleHandler()->install(array('block_test'));
     $this->assertTrue(module_exists('block_test'), 'Test block module enabled.');
 
     // Clear the block cache to load the block_test module's block definitions.
@@ -242,100 +242,4 @@ function testBlockRehash() {
     $this->assertEqual($settings['cache'], DRUPAL_NO_CACHE, "Test block's database entry updated to DRUPAL_NO_CACHE.");
   }
 
-  /**
-   * Tests blocks belonging to disabled modules.
-   */
-  function testBlockModuleDisable() {
-    module_enable(array('block_test'));
-    $this->assertTrue(module_exists('block_test'), 'Test block module enabled.');
-
-    // Clear the block cache to load the block_test module's block definitions.
-    $manager = $this->container->get('plugin.manager.block');
-    $manager->clearCachedDefinitions();
-
-    // Add test blocks in different regions and confirm they are displayed.
-    $blocks = array();
-    $regions = array('sidebar_first', 'content', 'footer');
-    foreach ($regions as $region) {
-      $blocks[$region] = $this->drupalPlaceBlock('test_cache', array('region' => $region));
-    }
-    $this->drupalGet('');
-    foreach ($regions as $region) {
-      $this->assertText($blocks[$region]->label());
-    }
-
-    // Disable the block test module and refresh the definitions cache.
-    module_disable(array('block_test'), FALSE);
-    $this->assertFalse(module_exists('block_test'), 'Test block module disabled.');
-    $manager->clearCachedDefinitions();
-
-    // Ensure that the block administration page still functions as expected.
-    $this->drupalGet('admin/structure/block');
-    $this->assertResponse(200);
-    // A 200 response is possible with a fatal error, so check the title too.
-    $this->assertTitle(t('Blocks | Drupal'));
-
-    // Ensure that the disabled module's block instance is not listed.
-    foreach ($regions as $region) {
-      $this->assertNoText($blocks[$region]->label());
-    }
-
-    // Ensure that the disabled module's block plugin is no longer available.
-    $this->drupalGet('admin/structure/block/list/' . \Drupal::config('system.theme')->get('default'));
-    $this->assertNoText(t('Test block caching'));
-
-    // Confirm that the block is no longer displayed on the front page.
-    $this->drupalGet('');
-    $this->assertResponse(200);
-    foreach ($regions as $region) {
-      $this->assertNoText($blocks[$region]->label());
-    }
-
-    // Confirm that a different block instance can still be enabled by
-    // submitting the block library form.
-    // Emulate a POST submission rather than using drupalPlaceBlock() to ensure
-    // that the form still functions as expected.
-    $edit = array(
-      'settings[label]' => $this->randomName(8),
-      'machine_name' => strtolower($this->randomName(8)),
-      'region' => 'sidebar_first',
-    );
-    $this->drupalPost('admin/structure/block/add/system_powered_by_block/stark', $edit, t('Save block'));
-    $this->assertText(t('The block configuration has been saved.'));
-    $this->assertText($edit['settings[label]']);
-
-    // Update the weight of a block.
-    $edit = array('blocks[stark.' . $edit['machine_name'] . '][weight]' => -1);
-    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
-    $this->assertText(t('The block settings have been updated.'));
-
-    // Re-enable the module and refresh the definitions cache.
-    module_enable(array('block_test'), FALSE);
-    $this->assertTrue(module_exists('block_test'), 'Test block module re-enabled.');
-    $manager->clearCachedDefinitions();
-
-    // Reload the admin page and confirm the block can again be configured.
-    $this->drupalGet('admin/structure/block');
-    foreach ($regions as $region) {
-      $this->assertLinkByHref(url('admin/structure/block/manage/' . $blocks[$region]->id()));
-    }
-
-    // Confirm that the blocks are again displayed on the front page in the
-    // correct regions.
-    $this->drupalGet('');
-    foreach ($regions as $region) {
-      // @todo Use a proper method for this.
-      $name_pieces = explode('.', $blocks[$region]->id());
-      $machine_name = array_pop($name_pieces);
-      $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
-        ':region-class' => 'region region-' . drupal_html_class($region),
-        ':block-id' => 'block-' . strtr(strtolower($machine_name), '-', '_'),
-    ));
-      $this->assertFieldByXPath($xpath, NULL, format_string('Block %name found in the %region region.', array(
-        '%name' => $blocks[$region]->label(),
-        '%region' => $region,
-      )));
-    }
-  }
-
 }
diff --git a/core/modules/breakpoint/breakpoint.install b/core/modules/breakpoint/breakpoint.install
index dcc0b35..b0ea7f7 100644
--- a/core/modules/breakpoint/breakpoint.install
+++ b/core/modules/breakpoint/breakpoint.install
@@ -6,15 +6,15 @@
  */
 
 /**
- * Implements hook_enable().
+ * Implements hook_install().
  *
  * Import breakpoints from all enabled themes.
  */
-function breakpoint_enable() {
+function breakpoint_install() {
   // Import breakpoints from themes.
   $themes = list_themes();
   _breakpoint_theme_enabled(array_keys($themes));
 
   // Import breakpoints from modules.
-  _breakpoint_modules_enabled(array_keys(Drupal::moduleHandler()->getModuleList()));
+  _breakpoint_modules_installed(array_keys(Drupal::moduleHandler()->getModuleList()));
 }
diff --git a/core/modules/breakpoint/breakpoint.module b/core/modules/breakpoint/breakpoint.module
index 1a4a80c..93901ae 100644
--- a/core/modules/breakpoint/breakpoint.module
+++ b/core/modules/breakpoint/breakpoint.module
@@ -62,7 +62,7 @@ function breakpoint_themes_disabled($theme_list) {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  *
  * @param array $modules
  *   An array of the modules that were enabled.
@@ -71,8 +71,8 @@ function breakpoint_themes_disabled($theme_list) {
  *
  * @todo: This should be removed if https://drupal.org/node/1813100 is resolved.
  */
-function breakpoint_modules_enabled($modules) {
-  _breakpoint_modules_enabled($modules);
+function breakpoint_modules_installed($modules) {
+  _breakpoint_modules_installed($modules);
 }
 
 /**
@@ -106,12 +106,12 @@ function _breakpoint_theme_enabled($theme_list) {
 }
 
 /**
- * Import breakpoints from all new enabled modules.
+ * Import breakpoints from all new installed modules.
  *
  * @param array $modules
- *   An array of the modules that were enabled.
+ *   An array of the modules that were installed.
  */
-function _breakpoint_modules_enabled($modules) {
+function _breakpoint_modules_installed($modules) {
   foreach ($modules as $module) {
     $media_queries = breakpoint_get_module_media_queries($module);
     _breakpoint_import_media_queries($module, $module, Breakpoint::SOURCE_TYPE_MODULE, $media_queries);
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
index dde38a0..e00af05 100644
--- a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
@@ -118,10 +118,6 @@ public function testThemeBreakpointGroupModule() {
     theme_disable(array('breakpoint_test_theme'));
     $this->assertTrue(entity_load('breakpoint_group', $breakpoint_group_obj->id()), 'Breakpoint group still exists if theme is disabled.');
 
-    // Disable the test module and verify the breakpoint group still exists.
-    module_disable(array('breakpoint_theme_test'));
-    $this->assertTrue(entity_load('breakpoint_group', $breakpoint_group_obj->id()), 'Breakpoint group still exists if module is disabled.');
-
     // Uninstall the test module and verify the breakpoint group is deleted.
     module_uninstall(array('breakpoint_theme_test'));
     $this->assertFalse(entity_load('breakpoint_group', $breakpoint_group_obj->id()), 'Breakpoint group is removed if module is uninstalled.');
diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php
index e0e3cac..5ec423c 100644
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php
@@ -145,7 +145,7 @@ function testAdmin() {
 
     // Now enable the ckeditor_test module, which provides one configurable
     // CKEditor plugin — this should not affect the Editor config entity.
-    module_enable(array('ckeditor_test'));
+    \Drupal::moduleHandler()->install(array('ckeditor_test'));
     $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
     $this->drupalGet('admin/config/content/formats/manage/filtered_html');
     $ultra_llama_mode_checkbox = $this->xpath('//input[@type="checkbox" and @name="editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]" and not(@checked)]');
diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorLoadingTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorLoadingTest.php
index 89628ad..5e05e33 100644
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorLoadingTest.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorLoadingTest.php
@@ -119,7 +119,7 @@ function testLoading() {
     // NOTE: the tests in CKEditorTest already ensure that changing the
     // configuration also results in modified CKEditor configuration, so we
     // don't test that here.
-    module_enable(array('ckeditor_test'));
+    \Drupal::moduleHandler()->install(array('ckeditor_test'));
     $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
     $editor->settings['toolbar']['buttons'][0][] = 'Llama';
     $editor->save();
diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install
index 04e1291..4fe0ccf 100644
--- a/core/modules/comment/comment.install
+++ b/core/modules/comment/comment.install
@@ -17,7 +17,6 @@ function comment_uninstall() {
   )));
   drupal_classloader_register('comment', 'core/modules/comment');
   foreach ($node_types as $node_type) {
-    entity_invoke_bundle_hook('delete', 'comment', 'comment_node_' . $node_type);
     variable_del('comment_' . $node_type);
     variable_del('comment_anonymous_' . $node_type);
     variable_del('comment_controls_' . $node_type);
@@ -34,9 +33,9 @@ function comment_uninstall() {
 }
 
 /**
- * Implements hook_enable().
+ * Implements hook_install().
  */
-function comment_enable() {
+function comment_install() {
   // Insert records into the node_comment_statistics for nodes that are missing.
   $query = db_select('node_field_data', 'n');
   $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid AND n.default_langcode = 1');
@@ -53,12 +52,13 @@ function comment_enable() {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  *
  * Creates comment body fields for node types existing before the Comment module
- * is enabled. We use hook_modules_enabled() rather than hook_enable() so we can
- * react to node types of existing modules, and those of modules being enabled
- * both before and after the Comment module in the loop of module_enable().
+ * is enabled. We use hook_modules_installed() rather than hook_install() so we
+ * can react to node types of existing modules, and those of modules being
+ * enabled both before and after the Comment module in the loop of
+ * \Drupal\Core\Extension\ModuleHandler::install().
  *
  * There is a separate comment bundle for each node type to allow for
  * per-node-type customization of comment fields. Each one of these bundles
@@ -68,7 +68,7 @@ function comment_enable() {
  *
  * @see comment_node_type_insert()
  */
-function comment_modules_enabled($modules) {
+function comment_modules_installed($modules) {
   // Only react if the Comment module is one of the modules being enabled.
   // hook_node_type_insert() is used to create body fields while the comment
   // module is enabled.
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
index f9d25f1..56ff3e2 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
@@ -61,31 +61,32 @@ function testCommentDefaultFields() {
   }
 
   /**
-   * Tests that comment module works when enabled after a content module.
+   * Tests that comment module works when install after a content module.
    */
-  function testCommentEnable() {
+  function testCommentInstallAfterContentModule() {
     // Create a user to do module administration.
     $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules'));
     $this->drupalLogin($this->admin_user);
 
     // Disable the comment module.
     $edit = array();
-    $edit['modules[Core][comment][enable]'] = FALSE;
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+    $edit['uninstall[comment]'] = TRUE;
+    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
+    $this->drupalPost(NULL, array(), t('Uninstall'));
     $this->rebuildContainer();
-    $this->assertFalse(module_exists('comment'), 'Comment module disabled.');
+    $this->assertFalse($this->container->get('module_handler')->moduleExists('comment'), 'Comment module uninstalled.');
 
     // Enable core content type module (book).
     $edit = array();
     $edit['modules[Core][book][enable]'] = 'book';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
 
-    // Now enable the comment module.
+    // Now install the comment module.
     $edit = array();
     $edit['modules[Core][comment][enable]'] = 'comment';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
     $this->rebuildContainer();
-    $this->assertTrue(module_exists('comment'), 'Comment module enabled.');
+    $this->assertTrue($this->container->get('module_handler')->moduleExists('comment'), 'Comment module enabled.');
 
     // Create nodes of each type.
     $book_node = $this->drupalCreateNode(array('type' => 'book'));
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentUninstallTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentUninstallTest.php
index 127a611..67f0712 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentUninstallTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentUninstallTest.php
@@ -46,7 +46,6 @@ function testCommentUninstallWithField() {
     $this->assertNotNull($field, 'The comment_body field exists.');
 
     // Uninstall the comment module which should trigger field deletion.
-    $this->container->get('module_handler')->disable(array('comment'));
     $this->container->get('module_handler')->uninstall(array('comment'));
 
     // Check that the field is now deleted.
@@ -70,7 +69,6 @@ function testCommentUninstallWithoutField() {
 
     // Ensure that uninstallation succeeds even if the field has already been
     // deleted manually beforehand.
-    $this->container->get('module_handler')->disable(array('comment'));
     $this->container->get('module_handler')->uninstall(array('comment'));
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
index 5431a96..3bb7839 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
@@ -37,7 +37,7 @@ function testIntegrationModuleReinstallation() {
     $default_configuration_entity = 'config_test.dynamic.config_integration_test';
 
     // Install the config_test module we're integrating with.
-    module_enable(array('config_test'));
+    \Drupal::moduleHandler()->install(array('config_test'));
 
     // Verify the configuration does not exist prior to installation.
     $config_static = \Drupal::config($default_config);
@@ -46,7 +46,7 @@ function testIntegrationModuleReinstallation() {
     $this->assertIdentical($config_entity->isNew(), TRUE);
 
     // Install the integration module.
-    module_enable(array('config_integration_test'));
+    \Drupal::moduleHandler()->install(array('config_integration_test'));
 
     // Verify that default module config exists.
     $config_static = \Drupal::config($default_config);
@@ -66,20 +66,7 @@ function testIntegrationModuleReinstallation() {
     //   In other words: This test passes even without this reset, but it shouldn't.
     $this->container->get('config.factory')->reset();
 
-    // Disable and enable the integration module.
-    module_disable(array('config_integration_test'));
-    module_enable(array('config_integration_test'));
-
-    // Verify that customized config exists.
-    $config_static = \Drupal::config($default_config);
-    $this->assertIdentical($config_static->isNew(), FALSE);
-    $this->assertIdentical($config_static->get('foo'), 'customized setting');
-    $config_entity = \Drupal::config($default_configuration_entity);
-    $this->assertIdentical($config_entity->isNew(), FALSE);
-    $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
-
     // Disable and uninstall the integration module.
-    module_disable(array('config_integration_test'));
     module_uninstall(array('config_integration_test'));
 
     // Verify the integration module's config was uninstalled.
@@ -92,7 +79,7 @@ function testIntegrationModuleReinstallation() {
     $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
 
     // Reinstall the integration module.
-    module_enable(array('config_integration_test'));
+    \Drupal::moduleHandler()->install(array('config_integration_test'));
 
     // Verify the integration module's config was re-installed.
     $config_static = \Drupal::config($default_config);
diff --git a/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php b/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php
index 0bc89e1..23c2f3b 100644
--- a/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php
+++ b/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php
@@ -104,7 +104,7 @@ function testAddEditorToNewFormat() {
    * Enables the unicorn editor.
    */
   protected function enableUnicornEditor() {
-    module_enable(array('editor_test'));
+    \Drupal::moduleHandler()->install(array('editor_test'));
     $this->rebuildContainer();
     $this->resetAll();
   }
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index a88a10a..1e0e404 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -159,3 +159,18 @@ function entity_entity_bundle_delete($entity_type, $bundle) {
   }
   entity_delete_multiple('entity_form_display', $ids);
 }
+
+/**
+ * Implements hook_module_preuninstall().
+ */
+function entity_module_preuninstall($module) {
+  // Clean up all entity bundles (including field instances) of every entity
+  // type provided by the module that is being uninstalled.
+  foreach (Drupal::entityManager()->getDefinitions() as $entity_type => $entity_info) {
+    if ($entity_info['module'] == $module) {
+      foreach (array_keys(entity_get_bundles($entity_type)) as $bundle) {
+        entity_invoke_bundle_hook('delete', $entity_type, $bundle);
+      }
+    }
+  }
+}
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 1a673bce..592f312 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -358,17 +358,17 @@ function field_rebuild() {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  */
-function field_modules_enabled($modules) {
+function field_modules_installed($modules) {
   // Refresh the 'active' status of fields.
   field_sync_field_status();
 }
 
 /**
- * Implements hook_modules_disabled().
+ * Implements hook_modules_uninstalled().
  */
-function field_modules_disabled($modules) {
+function field_modules_uninstalled($modules) {
   // Refresh the 'active' status of fields.
   field_sync_field_status();
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/ActiveTest.php b/core/modules/field/lib/Drupal/field/Tests/ActiveTest.php
deleted file mode 100644
index 7b021e2..0000000
--- a/core/modules/field/lib/Drupal/field/Tests/ActiveTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\field\Tests\ActiveTest.
- */
-
-namespace Drupal\field\Tests;
-
-class ActiveTest extends FieldTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('field_test', 'entity_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Field active test',
-      'description' => 'Test that fields are properly marked active or inactive.',
-      'group' => 'Field API',
-    );
-  }
-
-  /**
-   * Test that fields are properly marked active or inactive.
-   */
-  function testActive() {
-    $field_name = 'field_1';
-    entity_create('field_entity', array(
-      'name' => $field_name,
-      'entity_type' => 'entity_test',
-      'type' => 'test_field',
-    ))->save();
-
-    // Check that the field is correctly found.
-    $field = field_read_field('entity_test', $field_name);
-    $this->assertFalse(empty($field), 'The field was properly read.');
-
-    // Disable the module providing the field type, and check that the field is
-    // found only if explicitly requesting inactive fields.
-    module_disable(array('field_test'));
-    $field = field_read_field('entity_test', $field_name);
-    $this->assertTrue(empty($field), 'The field is marked inactive when the field type is absent.');
-    $field = field_read_field('entity_test', $field_name, array('include_inactive' => TRUE));
-    $this->assertFalse(empty($field), 'The field is properly read when explicitly fetching inactive fields.');
-
-    // Re-enable the module, and check that the field is active again.
-    module_enable(array('field_test'));
-    $field = field_read_field('entity_test', $field_name);
-    $this->assertFalse(empty($field), 'The field was was marked active.');
-  }
-}
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php
index b6697e7..ff1c584 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php
@@ -46,7 +46,7 @@ function testImportCreateDefault() {
 
     // Enable field_test_config module and check that the field and instance
     // shipped in the module's default config were created.
-    module_enable(array('field_test_config'));
+    \Drupal::moduleHandler()->install(array('field_test_config'));
 
     // A field with one instance.
     $field = entity_load('field_entity', $field_id);
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index 9c433aa..fe97da2 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -191,7 +191,7 @@ function testInstanceDisabledEntityType() {
     entity_create('field_instance', $instance_definition);
 
     // Disable coment module. This clears field_info cache.
-    module_disable(array('comment'));
+    module_uninstall(array('comment'));
     $this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), 'No instances are returned on disabled entity types.');
   }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/reEnableModuleFieldTest.php b/core/modules/field/lib/Drupal/field/Tests/reEnableModuleFieldTest.php
index 0b5400d..12e12b5 100644
--- a/core/modules/field/lib/Drupal/field/Tests/reEnableModuleFieldTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/reEnableModuleFieldTest.php
@@ -91,15 +91,7 @@ function testReEnabledField() {
     $this->drupalPost(NULL, $edit, t('Save'));
     $this->assertRaw('<a href="tel:123456789">');
 
-    // Disable the telephone module and re-enable it.
-    module_disable(array('telephone'));
-    module_enable(array('telephone'));
-
-    // Display the article creation form and verify the widget still exists.
-    $this->drupalGet('node/add/article');
-    $this->assertFieldByName("field_telephone[und][0][value]", '', 'Widget found.');
-
-    // Test that the module can't be disabled from the UI while there is data
+    // Test that the module can't be uninstalled from the UI while there is data
     // for it's fields.
     $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules'));
     $this->drupalLogin($admin_user);
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index adc8ddb..f75d9a8 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -15,12 +15,7 @@ function forum_install() {
   $locked = Drupal::state()->get('node.type.locked');
   $locked['forum'] = 'forum';
   Drupal::state()->set('node.type.locked', $locked);
-}
 
-/**
- * Implements hook_enable().
- */
-function forum_enable() {
   // Create the forum vocabulary if it does not exist.
   // @todo Change Forum module so forum.settings can contain the vocabulary's
   //   machine name.
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
index 466ab8b..16c4395 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
@@ -107,30 +107,6 @@ function setUp() {
   }
 
   /**
-   * Tests disabling and re-enabling the Forum module.
-   */
-  function testEnableForumField() {
-    $this->drupalLogin($this->admin_user);
-
-    // Disable the Forum module.
-    $edit = array();
-    $edit['modules[Core][forum][enable]'] = FALSE;
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-    $this->rebuildContainer();
-    $this->assertFalse(module_exists('forum'), 'Forum module is not enabled.');
-
-    // Attempt to re-enable the Forum module and ensure it does not try to
-    // recreate the taxonomy_forums field.
-    $edit = array();
-    $edit['modules[Core][forum][enable]'] = 'forum';
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-    $this->rebuildContainer();
-    $this->assertTrue(module_exists('forum'), 'Forum module is enabled.');
-  }
-
-  /**
    * Tests forum functionality through the admin and user interfaces.
    */
   function testForum() {
@@ -254,7 +230,7 @@ function testAddOrphanTopic() {
     $this->assertEqual(0, $nid_count, 'A forum node was not created when missing a forum vocabulary.');
 
     // Reset the defaults for future tests.
-    module_enable(array('forum'));
+    \Drupal::moduleHandler()->install(array('forum'));
   }
 
   /**
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
index cce8db0..6eb2014 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
@@ -7,12 +7,12 @@
 
 namespace Drupal\forum\Tests;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\system\Tests\Module\ModuleTestBase;
 
 /**
  * Tests forum module uninstallation.
  */
-class ForumUninstallTest extends WebTestBase {
+class ForumUninstallTest extends ModuleTestBase {
 
   /**
    * Modules to enable.
@@ -32,18 +32,49 @@ public static function getInfo() {
   /**
    * Tests if forum module uninstallation properly deletes the field.
    */
-  function testForumUninstallWithField() {
+  function testForumUninstallAndReinstallWithField() {
     // Ensure that the field exists before uninstallation.
     $field = field_info_field('node', 'taxonomy_forums');
     $this->assertNotNull($field, 'The taxonomy_forums field exists.');
 
     // Uninstall the forum module which should trigger field deletion.
-    $this->container->get('module_handler')->disable(array('forum'));
     $this->container->get('module_handler')->uninstall(array('forum'));
 
     // Check that the field is now deleted.
     $field = field_info_field('node', 'taxonomy_forums');
     $this->assertNull($field, 'The taxonomy_forums field has been deleted.');
+
+    // Uninstall and reinstall the forum module and its dependencies tests the
+    // the module installation and uninstallation APIs.
+    $module_data = system_rebuild_module_data();
+    $module_list = array();
+    foreach (array_keys($module_data['forum']->requires) as $dependency) {
+      // Disable all the dependencies if they are not required.
+      if (empty($module_data[$dependency]->info['required'])) {
+        $module_list[] = $dependency;
+      }
+    }
+
+    $this->container->get('module_handler')->uninstall($module_list);
+    foreach ($module_list as $module) {
+      // Check that the module's database tables no longer exist.
+      $this->assertModuleTablesDoNotExist($module);
+      // Check that the module's config files no longer exist.
+      $this->assertNoModuleConfig($module);
+    }
+
+    $this->container->get('module_handler')->install(array('forum'));
+    foreach ($module_list as $module) {
+      // Check that the module's database tables no longer exist.
+      $this->assertModuleTablesExist($module);
+      // Check that the module's config files no longer exist.
+      $this->assertModuleConfig($module);
+    }
+
+    // Ensure that the field exists after reinstallation.
+    $field = field_info_field('node', 'taxonomy_forums');
+    $this->assertNotNull($field, 'The taxonomy_forums field exists.');
+
   }
 
 
@@ -62,7 +93,6 @@ function testForumUninstallWithoutField() {
 
     // Ensure that uninstallation succeeds even if the field has already been
     // deleted manually beforehand.
-    $this->container->get('module_handler')->disable(array('forum'));
     $this->container->get('module_handler')->uninstall(array('forum'));
   }
 
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index 42f9c37..16d2180 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -21,6 +21,9 @@ function language_install() {
     module_load_include('inc', 'language', 'language.negotiation');
     language_negotiation_set($type, array(LANGUAGE_NEGOTIATION_URL => 0));
   }
+
+  // Update the language count.
+  language_update_count();
 }
 
 /**
@@ -44,24 +47,10 @@ function language_uninstall() {
   // Re-initialize the language system so successive calls to t() and other
   // functions will not expect languages to be present.
   drupal_language_initialize();
-}
-
-/**
- * Implements hook_enable().
- */
-function language_enable() {
-  // Update the language count, if the module was disabled before, the
-  // language_count state was forced to 1.
-  language_update_count();
-}
 
-/**
- * Implements hook_disable().
- */
-function language_disable() {
-  // Force the language_count state to be 1, so that the when checking if the
+  // Force the language_count state to be 1, so that when checking if the
   // site is multilingual (for example in language_multilingual()), the result
-  // will be FALSE, because the language module is disabled.
+  // will be FALSE, because the language module is not installed.
   Drupal::state()->set('language_count', 1);
 }
 
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index f092c86..0522567 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -725,9 +725,9 @@ function language_negotiation_include() {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  */
-function language_modules_enabled($modules) {
+function language_modules_installed($modules) {
   include_once DRUPAL_ROOT . '/core/includes/language.inc';
   // Load configurability options from configuration.
   language_types_set(array());
@@ -735,10 +735,10 @@ function language_modules_enabled($modules) {
 }
 
 /**
- * Implements hook_modules_disabled().
+ * Implements hook_modules_uninstalled().
  */
-function language_modules_disabled($modules) {
-  language_modules_enabled($modules);
+function language_modules_uninstalled($modules) {
+  language_modules_installed($modules);
 }
 
 /**
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
index 6ab71ba..18a4cd9 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
@@ -102,9 +102,9 @@ function testInfoAlterations() {
       $this->assertEqual($langcode, $value, format_string('The negotiated language for %type is %language', array('%type' => $type, '%language' => $value)));
     }
 
-    // Disable language_test and check that everything is set back to the
+    // Uninstall language_test and check that everything is set back to the
     // original status.
-    $this->languageNegotiationUpdate('disable');
+    $this->languageNegotiationUpdate('uninstall');
 
     // Check that only the core language types are available.
     foreach (language_types_get_all() as $type) {
@@ -128,25 +128,24 @@ function testInfoAlterations() {
   /**
    * Update language types/negotiation information.
    *
-   * Manually invoke language_modules_enabled()/language_modules_disabled()
-   * since they would not be invoked after enabling/disabling language_test the
-   * first time.
+   * Manually invoke language_modules_installed()/language_modules_uninstalled()
+   * since they would not be invoked after installing/uninstalling language_test
+   * the first time.
    */
-  protected function languageNegotiationUpdate($op = 'enable') {
+  protected function languageNegotiationUpdate($op = 'install') {
     static $last_op = NULL;
     $modules = array('language_test');
 
-    // Enable/disable language_test only if we did not already before.
+    // Install/uninstall language_test only if we did not already before.
     if ($last_op != $op) {
-      $function = "module_{$op}";
-      $function($modules);
+      call_user_func(array($this->container->get('module_handler'), $op), $modules);
       // Reset hook implementation cache.
       $this->container->get('module_handler')->resetImplementations();
     }
 
     drupal_static_reset('language_types_info');
     drupal_static_reset('language_negotiation_info');
-    $function = "language_modules_{$op}d";
+    $function = "language_modules_{$op}ed";
     if (function_exists($function)) {
       $function($modules);
     }
diff --git a/core/modules/locale/config/locale.settings.yml b/core/modules/locale/config/locale.settings.yml
index 02e8af0..cbc60ab 100644
--- a/core/modules/locale/config/locale.settings.yml
+++ b/core/modules/locale/config/locale.settings.yml
@@ -3,7 +3,7 @@ javascript:
   directory: 'languages'
 translation:
   use_source: 'remote_and_local'
-  check_disabled_modules: '0'
+  check_disabled_projects: '0'
   default_filename: '%project-%version.%language.po'
   default_server_pattern: 'http://ftp.drupal.org/files/translations/%core/%project/%project-%version.%language.po'
   overwrite_customized: '0'
diff --git a/core/modules/locale/config/schema/locale.schema.yml b/core/modules/locale/config/schema/locale.schema.yml
index 029a179..1c31726 100644
--- a/core/modules/locale/config/schema/locale.schema.yml
+++ b/core/modules/locale/config/schema/locale.schema.yml
@@ -21,7 +21,7 @@ locale.settings:
         use_source:
           type: string
           label: 'Translation source'
-        check_disabled_modules:
+        check_disabled_projects:
           type: boolean
           label: 'Check for updates of disabled modules and themes'
         default_filename:
diff --git a/core/modules/locale/lib/Drupal/locale/Form/LocaleSettingsForm.php b/core/modules/locale/lib/Drupal/locale/Form/LocaleSettingsForm.php
index 826ba38..7bf57dc 100644
--- a/core/modules/locale/lib/Drupal/locale/Form/LocaleSettingsForm.php
+++ b/core/modules/locale/lib/Drupal/locale/Form/LocaleSettingsForm.php
@@ -38,10 +38,10 @@ public function buildForm(array $form, array &$form_state) {
       '#description' => t('Select how frequently you want to check for new interface translations for your currently installed modules and themes. <a href="@url">Check updates now</a>.', array('@url' => url('admin/reports/translations/check'))),
     );
 
-    $form['check_disabled_modules'] = array(
+    $form['check_disabled_projects'] = array(
       '#type' => 'checkbox',
-      '#title' => t('Check for updates of disabled modules and themes'),
-      '#default_value' => $config->get('translation.check_disabled_modules'),
+      '#title' => t('Check for updates of disabled projects'),
+      '#default_value' => $config->get('translation.check_disabled_projects'),
     );
 
     if ($directory =\Drupal::config('locale.settings')->get('translation.path')) {
@@ -126,13 +126,13 @@ public function submitForm(array &$form, array &$form_state) {
     }
 
     $config
-      ->set('translation.check_disabled_modules', $values['check_disabled_modules'])
+      ->set('translation.check_disabled_projects', $values['check_disabled_projects'])
       ->save();
 
     // Invalidate the cached translation status when the configuration setting of
-    // 'use_source' and 'check_disabled_modules' change.
+    // 'use_source' and 'check_disabled_projects' change.
     if ($form['use_source']['#default_value'] != $form_state['values']['use_source'] ||
-        $form['check_disabled_modules']['#default_value'] != $form_state['values']['check_disabled_modules']) {
+        $form['check_disabled_projects']['#default_value'] != $form_state['values']['check_disabled_projects']) {
       locale_translation_clear_status();
     }
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
index aa53fbb..72ddbe5 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
@@ -138,8 +138,7 @@ function testConfigTranslation() {
     // Quick test to ensure translation file exists.
     $this->assertEqual(\Drupal::config('locale.config.xx.image.style.medium')->get('label'), $image_style_label);
 
-    // Disable and uninstall the module.
-    $this->drupalPost('admin/modules', array('modules[Core][image][enable]' => FALSE), t('Save configuration'));
+    // Uninstall the module.
     $this->drupalPost('admin/modules/uninstall', array('uninstall[image]' => "image"), t('Uninstall'));
     $this->drupalPost(NULL, array(), t('Uninstall'));
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
index dc990e8..34bd2d6 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
@@ -214,7 +214,7 @@ function testContentTypeDirLang() {
    *  Test filtering Node content by language.
    */
   function testNodeAdminLanguageFilter() {
-    module_enable(array('views'));
+    \Drupal::moduleHandler()->install(array('views'));
     // User to add and remove language.
     $admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
index 1cfb538..71a2043 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
@@ -109,7 +109,6 @@ function testUninstallProcess() {
       ->save();
 
     // Uninstall Locale.
-    module_disable($locale_module);
     module_uninstall($locale_module);
     $this->rebuildContainer();
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
index 9f55abc..9701dc6 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
@@ -65,21 +65,20 @@ function testUpdateProjects() {
    */
   function testUpdateProjectsHidden() {
     module_load_include('compare.inc', 'locale');
-    $config = \Drupal::config('locale.settings');
 
     // Make the test modules look like a normal custom module.
     \Drupal::state()->set('locale.test_system_info_alter', TRUE);
     $this->resetAll();
 
-    // Set test condition: include disabled modules when building a project list.
+    // Set test condition: include disabled themes when building a project list.
     $edit = array(
-      'check_disabled_modules' => TRUE,
+      'check_disabled_projects' => TRUE,
     );
     $this->drupalPost('admin/config/regional/translate/settings', $edit, t('Save configuration'));
 
     $projects = locale_translation_project_list();
-    $this->assertTrue(isset($projects['locale_test_translate']), 'Disabled module found');
-    $this->assertTrue(isset($projects['locale_test']), 'Enabled module found');
+    $this->assertTrue(isset($projects['locale_test_translate']), 'Disabled projects found');
+    $this->assertTrue(isset($projects['locale_test']), 'Enabled projects found');
   }
 
   /**
@@ -332,7 +331,7 @@ function testUpdateImportModeNone() {
   /**
    * Tests automatic translation import when a module is enabled.
    */
-  function testEnableDisableModule() {
+  function testEnableUninstallModule() {
     // Make the hidden test modules look like a normal custom module.
     \Drupal::state()->set('locale.test_system_info_alter', TRUE);
 
@@ -350,11 +349,6 @@ function testEnableDisableModule() {
       array('%number' => 7, '%update' => 0, '%delete' => 0)), 'One translation file imported.');
     $this->assertTranslation('Tuesday', 'Dienstag', 'de');
 
-    // Disable and uninstall a module.
-    $edit = array(
-      'modules[Testing][locale_test_translate][enable]' => FALSE,
-    );
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
     $edit = array(
       'uninstall[locale_test_translate]' => 1,
     );
@@ -375,7 +369,7 @@ function testEnableDisableModule() {
    * enabled modules and will import them. When a language is removed the system
    * will remove all translations of that langugue from the database.
    */
-  function testEnableDisableLanguage() {
+  function testEnableLanguage() {
     // Make the hidden test modules look like a normal custom module.
     \Drupal::state()->set('locale.test_system_info_alter', TRUE);
 
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
index ed4664d..a60c574 100644
--- a/core/modules/locale/locale.compare.inc
+++ b/core/modules/locale/locale.compare.inc
@@ -142,7 +142,7 @@ function locale_translation_project_list() {
     $project_info = new ProjectInfo();
     $project_info->processInfoList($projects, $module_data, 'module', TRUE, $additional_whitelist);
     $project_info->processInfoList($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
-    if ($config->get('translation.check_disabled_modules')) {
+    if ($config->get('translation.check_disabled_projects')) {
       $project_info->processInfoList($projects, $module_data, 'module', FALSE, $additional_whitelist);
       $project_info->processInfoList($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
     }
diff --git a/core/modules/locale/locale.translation.inc b/core/modules/locale/locale.translation.inc
index 30c7b0f..8d452d8 100644
--- a/core/modules/locale/locale.translation.inc
+++ b/core/modules/locale/locale.translation.inc
@@ -330,7 +330,7 @@ function locale_cron_fill_queue() {
   $query->join('locale_project', 'p', 'p.name = f.project');
   $query->condition('f.last_checked', $last, '<');
   $query->fields('f', array('project', 'langcode'));
-  if (!$config->get('translation.check_disabled_modules')) {
+  if (!$config->get('translation.check_disabled_projects')) {
     $query->condition('p.status', 1);
   }
   $files = $query->execute()->fetchAll();
diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install
index f1fc64d..db28791 100644
--- a/core/modules/menu/menu.install
+++ b/core/modules/menu/menu.install
@@ -8,6 +8,41 @@
 use Drupal\Component\Uuid\Uuid;
 
 /**
+ * Implements hook_install().
+ */
+function menu_install() {
+  // Add a link for each custom menu.
+  Drupal::service('router.builder')->rebuild();
+  menu_router_rebuild();
+  $system_link = entity_load_multiple_by_properties('menu_link', array('link_path' => 'admin/structure/menu', 'module' => 'system'));
+  $system_link = reset($system_link);
+
+  $base_link = entity_create('menu_link', array(
+    'menu_name' => $system_link->menu_name,
+    'router_path' => 'admin/structure/menu/manage/%',
+    'module' => 'menu',
+  ));
+
+  $menus = entity_load_multiple('menu');
+  foreach ($menus as $menu) {
+    $link = $base_link->createDuplicate();
+    $link->plid = $system_link->id();
+    $link->link_title = $menu->label();
+    $link->link_path = 'admin/structure/menu/manage/' . $menu->id();
+
+    $query = Drupal::entityQuery('menu_link')
+      ->condition('link_path', $link->link_path)
+      ->condition('plid', $link->plid);
+    $result = $query->execute();
+
+    if (empty($result)) {
+      $link->save();
+    }
+  }
+  menu_cache_clear_all();
+}
+
+/**
  * Implements hook_uninstall().
  */
 function menu_uninstall() {
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index 4906043..c37255a 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -177,42 +177,6 @@ function menu_theme() {
 }
 
 /**
- * Implements hook_enable().
- *
- * Add a link for each custom menu.
- */
-function menu_enable() {
-  Drupal::service('router.builder')->rebuild();
-  menu_router_rebuild();
-  $system_link = entity_load_multiple_by_properties('menu_link', array('link_path' => 'admin/structure/menu', 'module' => 'system'));
-  $system_link = reset($system_link);
-
-  $base_link = entity_create('menu_link', array(
-    'menu_name' => $system_link->menu_name,
-    'router_path' => 'admin/structure/menu/manage/%menu',
-    'module' => 'menu',
-  ));
-
-  $menus = entity_load_multiple('menu');
-  foreach ($menus as $menu) {
-    $link = $base_link->createDuplicate();
-    $link->plid = $system_link->id();
-    $link->link_title = $menu->label();
-    $link->link_path = 'admin/structure/menu/manage/' . $menu->id();
-
-    $query = Drupal::entityQuery('menu_link')
-      ->condition('link_path', $link->link_path)
-      ->condition('plid', $link->plid);
-    $result = $query->execute();
-
-    if (empty($result)) {
-      $link->save();
-    }
-  }
-  menu_cache_clear_all();
-}
-
-/**
  * Load the data for a single custom menu.
  *
  * @param $menu_name
diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
index 593093a..cd117bb 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
@@ -52,7 +52,7 @@ public function testImportCreateDefault() {
 
     // Enable node_test_config module and check that the content type
     // shipped in the module's default config is created.
-    $this->container->get('module_handler')->enable(array('node_test_config'));
+    $this->container->get('module_handler')->install(array('node_test_config'));
     $node_type = entity_load('node_type', $node_type_id);
     $this->assertTrue($node_type, 'The default content type was created.');
   }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
index 1af4979..6b517fd 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
@@ -49,7 +49,7 @@ function testContentAdminSort() {
 
     // Create nodes that have different node.changed values.
     $this->container->get('state')->set('node_test.storage_controller', TRUE);
-    module_enable(array('node_test'));
+    \Drupal::moduleHandler()->install(array('node_test'));
     $changed = REQUEST_TIME;
     foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
       $changed += 1000;
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypePersistenceTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypePersistenceTest.php
index 22aedb4..c311bd7 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypePersistenceTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypePersistenceTest.php
@@ -50,24 +50,7 @@ function testNodeTypeCustomizationPersistence() {
     $this->drupalGet('node/add');
     $this->assertText($description, 'Customized description found');
 
-    // Disable forum and check that the node type gets disabled.
-    $this->drupalPost('admin/modules', $forum_disable, t('Save configuration'));
-    $forum = entity_load('node_type', 'forum');
-    $this->assertTrue($forum->isLocked(), 'Forum node type is node locked');
-    $this->drupalGet('node/add');
-    $this->assertNoText('forum', 'forum type is not found on node/add');
-
-    // Reenable forum and check that the customization survived the module
-    // disable.
-    $this->drupalPost('admin/modules', $forum_enable, t('Save configuration'));
-    $forum = entity_load('node_type', 'forum');
-    $this->assertTrue($forum->id(), 'Forum node type found.');
-    $this->assertTrue($forum->isLocked(), 'Forum node type is locked');
-    $this->drupalGet('node/add');
-    $this->assertText($description, 'Customized description found');
-
-    // Disable and uninstall forum.
-    $this->drupalPost('admin/modules', $forum_disable, t('Save configuration'));
+    // Uninstall forum.
     $edit = array('uninstall[forum]' => 'forum');
     $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
     $this->drupalPost(NULL, array(), t('Uninstall'));
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
index c9e8345..9eec51b 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
@@ -134,7 +134,7 @@ function testNodeTypeEditing() {
    */
   function testNodeTypeStatus() {
     // Enable all core node modules, and all types should be active.
-    $this->container->get('module_handler')->enable(array('book'), FALSE);
+    $this->container->get('module_handler')->install(array('book'), FALSE);
     $types = node_type_get_types();
     foreach (array('book', 'article', 'page') as $type) {
       $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
@@ -143,14 +143,14 @@ function testNodeTypeStatus() {
 
     // Disable book module and the respective type should still be active, since
     // it is not provided by shipped configuration entity.
-    $this->container->get('module_handler')->disable(array('book'), FALSE);
+    $this->container->get('module_handler')->uninstall(array('book'), FALSE);
     $types = node_type_get_types();
     $this->assertFalse($types['book']->isLocked(), "Book module's node type still active.");
     $this->assertFalse($types['article']->isLocked(), 'Article node type still active.');
     $this->assertFalse($types['page']->isLocked(), 'Basic page node type still active.');
 
-    // Re-enable the modules and verify that the types are active again.
-    $this->container->get('module_handler')->enable(array('book'), FALSE);
+    // Re-install the modules and verify that the types are active again.
+    $this->container->get('module_handler')->install(array('book'), FALSE);
     $types = node_type_get_types();
     foreach (array('book', 'article', 'page') as $type) {
       $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
@@ -192,10 +192,9 @@ function testNodeTypeDeletion() {
     );
     $this->assertText(t('This action cannot be undone.'), 'The node type deletion confirmation form is available.');
     // Test that forum node type could not be deleted while forum active.
-    $this->container->get('module_handler')->enable(array('forum'));
+    $this->container->get('module_handler')->install(array('forum'));
     $this->drupalGet('admin/structure/types/manage/forum/delete');
     $this->assertResponse(403);
-    $this->container->get('module_handler')->disable(array('forum'));
     $this->container->get('module_handler')->uninstall(array('forum'));
     $this->drupalGet('admin/structure/types/manage/forum/delete');
     $this->assertResponse(200);
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index 02cc7a0..a2efaaf 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -696,7 +696,7 @@ function node_update_8011() {
  */
 function node_update_8012() {
   // Enable the history module without re-installing the schema.
-  module_enable(array('history'));
+  Drupal::moduleHandler()->install(array('history'));
 }
 
 /**
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 105d2c9..96a44cd 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1442,27 +1442,6 @@ function node_form_block_form_alter(&$form, &$form_state) {
 }
 
 /**
- * Implements hook_modules_uninstalled().
- */
-function node_modules_uninstalled($modules) {
-  // Remove module-specific settings from all node types.
-  $config_names = config_get_storage_names_with_prefix('node.type.');
-  foreach ($config_names as $config_name) {
-    $config = Drupal::config($config_name);
-    $changed = FALSE;
-    foreach ($modules as $module) {
-      if ($config->get('settings.' . $module)) {
-        $config->clear('settings.' . $module);
-        $changed = TRUE;
-      }
-    }
-    if ($changed) {
-      $config->save();
-    }
-  }
-}
-
-/**
  * Implements hook_block_access().
  *
  * Checks the content type specific visibility settings and removes the block
@@ -2305,7 +2284,7 @@ function node_access_needs_rebuild($rebuild = NULL) {
  * rebuild only once he is done.
  *
  * Note : As of Drupal 6, node access modules are not required to (and actually
- * should not) call node_access_rebuild() in hook_enable/disable anymore.
+ * should not) call node_access_rebuild() in hook_install/uninstall anymore.
  *
  * @param $batch_mode
  *   (optional) Set to TRUE to process in 'batch' mode, spawning processing over
@@ -2457,9 +2436,9 @@ function node_requirements($phase) {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  */
-function node_modules_enabled($modules) {
+function node_modules_installed($modules) {
   // Check if any of the newly enabled modules require the node_access table to
   // be rebuilt.
   if (!node_access_needs_rebuild() && array_intersect($modules, Drupal::moduleHandler()->getImplementations('node_grants'))) {
@@ -2468,9 +2447,25 @@ function node_modules_enabled($modules) {
 }
 
 /**
- * Implements hook_modules_disabled().
+ * Implements hook_modules_uninstalled().
  */
-function node_modules_disabled($modules) {
+function node_modules_uninstalled($modules) {
+  // Remove module-specific settings from all node types.
+  $config_names = config_get_storage_names_with_prefix('node.type.');
+  foreach ($config_names as $config_name) {
+    $config = config($config_name);
+    $changed = FALSE;
+    foreach ($modules as $module) {
+      if ($config->get('settings.' . $module)) {
+        $config->clear('settings.' . $module);
+        $changed = TRUE;
+      }
+    }
+    if ($changed) {
+      $config->save();
+    }
+  }
+
   // Check whether any of the disabled modules implemented hook_node_grants(),
   // in which case the node access table needs to be rebuilt.
   foreach ($modules as $module) {
@@ -2567,6 +2562,6 @@ function node_library_info() {
  */
 function node_system_info_alter(&$info, $file, $type) {
   if ($type == 'module' && $file->name == 'translation') {
-    $info['hidden'] = !module_exists('translation') && Drupal::config('system.module.disabled')->get('translation') === NULL;
+    $info['hidden'] = !module_exists('translation');
   }
 }
diff --git a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.install b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.install
new file mode 100644
index 0000000..c8643a1
--- /dev/null
+++ b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.install
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the node_access_test_language
+ * module.
+ */
+
+/**
+ * Implements hook_install().
+ *
+ * Creates the 'private' field, which allows the node to be marked as private
+ * (restricted access) in a given translation.
+ */
+function node_access_test_language_install() {
+  $field_private = entity_create('field_entity', array(
+    'name' => 'field_private',
+    'entity_type' => 'node',
+    'type' => 'list_boolean',
+    'cardinality' => 1,
+    'translatable'  => TRUE,
+    'settings' => array(
+      'allowed_values' => array(0 => 'Not private', 1 => 'Private'),
+    ),
+  ));
+  $field_private->save();
+
+  entity_create('field_instance', array(
+    'field_name' => $field_private->name,
+    'entity_type' => 'node',
+    'bundle' => 'page',
+    'widget' => array(
+      'type' => 'options_buttons',
+    ),
+  ))->save();
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function node_access_test_language_uninstall() {
+  field_read_instance('node', 'field_private', 'page')->delete();
+}
diff --git a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module
index c285204..84a5fbe 100644
--- a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module
+++ b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module
@@ -42,39 +42,3 @@ function node_access_test_language_node_access_records(EntityInterface $node) {
   }
   return $grants;
 }
-
-/**
- * Implements hook_enable().
- *
- * Creates the 'private' field, which allows the node to be marked as private
- * (restricted access) in a given translation.
- */
-function node_access_test_language_enable() {
-  $field_private = entity_create('field_entity', array(
-    'name' => 'field_private',
-    'entity_type' => 'node',
-    'type' => 'list_boolean',
-    'cardinality' => 1,
-    'translatable'  => TRUE,
-    'settings' => array(
-      'allowed_values' => array(0 => 'Not private', 1 => 'Private'),
-    ),
-  ));
-  $field_private->save();
-
-  entity_create('field_instance', array(
-    'field_name' => $field_private->name,
-    'entity_type' => 'node',
-    'bundle' => 'page',
-    'widget' => array(
-      'type' => 'options_buttons',
-    ),
-  ))->save();
-}
-
-/**
- * Implements hook_disable().
- */
-function node_access_test_language_disable() {
-  field_read_instance('node', 'field_private', 'page')->delete();
-}
diff --git a/core/modules/overlay/overlay.install b/core/modules/overlay/overlay.install
index 29e6fa9..f3b78f3 100644
--- a/core/modules/overlay/overlay.install
+++ b/core/modules/overlay/overlay.install
@@ -6,12 +6,12 @@
  */
 
 /**
- * Implements hook_enable().
+ * Implements hook_install().
  *
  * If the module is being enabled through the admin UI, and not from an
  * installation profile, reopen the modules page in an overlay.
  */
-function overlay_enable() {
+function overlay_install() {
   if (strpos(current_path(), 'admin/modules') === 0) {
     // Flag for a redirect to <front>#overlay=admin/modules on hook_init().
     $_SESSION['overlay_enable_redirect'] = 1;
diff --git a/core/modules/php/php.install b/core/modules/php/php.install
index a88fe6a..8acf925 100644
--- a/core/modules/php/php.install
+++ b/core/modules/php/php.install
@@ -6,8 +6,8 @@
  */
 
 /**
- * Implements hook_disable().
+ * Implements hook_uninstall().
  */
-function php_disable() {
+function php_uninstall() {
   drupal_set_message(t('The PHP module has been disabled. Any existing content that was using the PHP filter will now be visible in plain text. This might pose a security risk by exposing sensitive information, if any, used in the PHP code.'));
 }
diff --git a/core/modules/rest/lib/Drupal/rest/Tests/NodeTest.php b/core/modules/rest/lib/Drupal/rest/Tests/NodeTest.php
index cd453e5..76773df 100644
--- a/core/modules/rest/lib/Drupal/rest/Tests/NodeTest.php
+++ b/core/modules/rest/lib/Drupal/rest/Tests/NodeTest.php
@@ -50,7 +50,7 @@ protected function enableNodeConfiguration($method, $operation) {
    */
   public function testNodes() {
     // Tests that the node resource works with comment module enabled.
-    $this->container->get('module_handler')->enable(array('comment'));
+    $this->container->get('module_handler')->install(array('comment'));
     $this->enableNodeConfiguration('GET', 'view');
 
     $node = $this->entityCreate('node');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index b55feee..9b40ce5 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -162,9 +162,9 @@ public function containerBuild(ContainerBuilder $container) {
       // away with a simple container holding the absolute bare minimum. When
       // a kernel is overridden then there's no need to re-register the keyvalue
       // service but when a test is happy with the superminimal container put
-      // together here, it still might a keyvalue storage for anything (for
-      // eg. module_enable) using \Drupal::state() -- that's why a memory
-      // service was added in the first place.
+      // together here, it still might a keyvalue storage for anything using
+      // \Drupal::state() -- that's why a memory service was added in the first
+      // place.
       $container
         ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory')
         ->addArgument(new Reference('service_container'));
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
index 505ff33..bd48b1c 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
@@ -89,7 +89,7 @@ function testEnableModulesInstall() {
     $this->assertFalse($schema, "'$table' table schema not found.");
 
     // Install the module.
-    module_enable(array($module));
+    \Drupal::moduleHandler()->install(array($module));
 
     // Verify that the enabled module exists.
     $this->assertTrue(module_exists($module), "$module module found.");
@@ -198,6 +198,9 @@ function testInstallConfig() {
    * Tests that the module list is retained after enabling/installing/disabling.
    */
   function testEnableModulesFixedList() {
+    // Install system module.
+    $this->container->get('module_handler')->install(array('system'));
+
     // entity_test is loaded via $modules; its entity type should exist.
     $this->assertEqual($this->container->get('module_handler')->moduleExists('entity_test'), TRUE);
     $this->assertTrue(TRUE == entity_get_info('entity_test'));
@@ -208,12 +211,12 @@ function testEnableModulesFixedList() {
     $this->assertTrue(TRUE == entity_get_info('entity_test'));
 
     // Install some other modules; entity_test should still exist.
-    module_enable(array('field', 'field_sql_storage', 'field_test'), FALSE);
+    $this->container->get('module_handler')->install(array('field', 'field_sql_storage', 'field_test'), FALSE);
     $this->assertEqual($this->container->get('module_handler')->moduleExists('entity_test'), TRUE);
     $this->assertTrue(TRUE == entity_get_info('entity_test'));
 
-    // Disable one of those modules; entity_test should still exist.
-    module_disable(array('field_test'));
+    // Uninstall one of those modules; entity_test should still exist.
+    $this->container->get('module_handler')->uninstall(array('field_test'));
     $this->assertEqual($this->container->get('module_handler')->moduleExists('entity_test'), TRUE);
     $this->assertTrue(TRUE == entity_get_info('entity_test'));
 
@@ -222,7 +225,7 @@ function testEnableModulesFixedList() {
     $this->assertEqual($this->container->get('module_handler')->moduleExists('entity_test'), TRUE);
     $this->assertTrue(TRUE == entity_get_info('entity_test'));
 
-    // Reactivate the disabled module without enabling it.
+    // Reactivate the previously uninstalled module.
     $this->enableModules(array('field_test'));
 
     // Create a field and an instance.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 7b9302a..cbaf3e0 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -811,7 +811,7 @@ protected function setUp() {
     }
     if ($modules) {
       $modules = array_unique($modules);
-      $success = module_enable($modules, TRUE);
+      $success = \Drupal::moduleHandler()->install($modules, TRUE);
       $this->assertTrue($success, t('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
       $this->rebuildContainer();
     }
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesListConfirmForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesListConfirmForm.php
index d674b18..be0ec46 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesListConfirmForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesListConfirmForm.php
@@ -115,18 +115,11 @@ public function buildForm(array $form, array &$form_state) {
     // were not manually selected.
     foreach ($this->modules['dependencies'] as $module => $dependencies) {
       $items[] = format_plural(count($dependencies), 'You must enable the @required module to install @module.', 'You must enable the @required modules to install @module.', array(
-        '@module' => $this->modules['enable'][$module],
+        '@module' => $this->modules['install'][$module],
         '@required' => implode(', ', $dependencies),
       ));
     }
 
-    foreach ($this->modules['missing'] as $name => $dependents) {
-      $items[] = format_plural(count($dependents), 'The @module module is missing, so the following module will be disabled: @depends.', 'The @module module is missing, so the following modules will be disabled: @depends.', array(
-        '@module' => $name,
-        '@depends' => implode(', ', $dependents),
-      ));
-    }
-
     $form['message'] = array(
       '#theme' => 'item_list',
       '#items' => $items,
@@ -146,12 +139,9 @@ public function submitForm(array &$form, array &$form_state) {
     // Gets list of modules prior to install process.
     $before = $this->moduleHandler->getModuleList();
 
-    // Installs, enables, and disables modules.
-    if (!empty($this->modules['enable'])) {
-      $this->moduleHandler->enable(array_keys($this->modules['enable']));
-    }
-    if (!empty($this->modules['disable'])) {
-      $this->moduleHandler->disable(array_keys($this->modules['disable']));
+    // Install the given modules.
+    if (!empty($this->modules['install'])) {
+      $this->moduleHandler->install(array_keys($this->modules['install']));
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
index 32d8db7..507df13 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
@@ -14,7 +14,7 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * Provides module enable/disable interface.
+ * Provides module installation interface.
  *
  * The list of modules gets populated by module.info.yml files, which contain
  * each module's name, description, and information about which modules it
@@ -117,7 +117,7 @@ public function buildForm(array $form, array &$form_state) {
         '#title' => $this->t($package),
         '#theme' => 'system_modules_details',
         '#header' => array(
-          array('data' => '<span class="visually-hidden">' . $this->t('Enabled') . '</span>', 'class' => array('checkbox')),
+          array('data' => '<span class="visually-hidden">' . $this->t('Installed') . '</span>', 'class' => array('checkbox')),
           array('data' => $this->t('Name'), 'class' => array('name')),
           array('data' => $this->t('Description'), 'class' => array('description', RESPONSIVE_PRIORITY_LOW)),
         ),
@@ -206,8 +206,9 @@ protected function buildRow(array $modules, $module, $distribution) {
     // Present a checkbox for installing and indicating the status of a module.
     $row['enable'] = array(
       '#type' => 'checkbox',
-      '#title' => $this->t('Enable'),
+      '#title' => $this->t('Install'),
       '#default_value' => (bool) $module->status,
+      '#disabled' => (bool) $module->status,
     );
 
     // Disable the checkbox for required modules.
@@ -301,67 +302,47 @@ protected function buildRow(array $modules, $module, $distribution) {
   }
 
   /**
-   * Helper function for building a list of modules to enable or disable.
+   * Helper function for building a list of modules to install.
    *
    * @param array $form_state
    *   The form state array.
    *
    * @return array
-   *   An array of modules to disable/enable and their dependencies.
+   *   An array of modules to install and their dependencies.
    */
   protected function buildModuleList(array $form_state) {
     $packages = $form_state['values']['modules'];
 
-    // Build a list of modules to enable or disable.
+    // Build a list of modules to install.
     $modules = array(
-      'enable' => array(),
-      'disable' => array(),
+      'install' => array(),
       'dependencies' => array(),
-      'missing' => array(),
     );
 
-    // Build a list of missing dependencies.
+    // Required modules have to be installed.
     // @todo This should really not be handled here.
     $data = system_rebuild_module_data();
     foreach ($data as $name => $module) {
-      // Modules with missing dependencies have to be disabled.
-      if ($this->moduleHandler->moduleExists($name)) {
-        foreach (array_keys($module->requires) as $dependency) {
-          if (!isset($data[$dependency])) {
-            $modules['missing'][$dependency][$name] = $module->info['name'];
-            $modules['disable'][$name] = $module->info['name'];
-          }
-        }
-      }
-      elseif (!empty($module->required)) {
-        $modules['enable'][$name] = $module->info['name'];
+      if (!empty($module->required) && !$this->moduleHandler->moduleExists($name)) {
+        $modules['install'][$name] = $module->info['name'];
       }
     }
 
     // First, build a list of all modules that were selected.
     foreach ($packages as $items) {
       foreach ($items as $name => $checkbox) {
-        // Do not override modules that are forced to be enabled/disabled.
-        if (isset($modules['enable'][$name]) || isset($modules['disable'][$name])) {
-          continue;
-        }
-
-        $enabled = $this->moduleHandler->moduleExists($name);
-        if (!$checkbox['enable'] && $enabled) {
-          $modules['disable'][$name] = $data[$name]->info['name'];
-        }
-        elseif ($checkbox['enable'] && !$enabled) {
-          $modules['enable'][$name] = $data[$name]->info['name'];
+        if ($checkbox['enable'] && !$this->moduleHandler->moduleExists($name)) {
+          $modules['install'][$name] = $data[$name]->info['name'];
         }
       }
     }
 
     // Add all dependencies to a list.
-    while (list($module) = each($modules['enable'])) {
+    while (list($module) = each($modules['install'])) {
       foreach (array_keys($data[$module]->requires) as $dependency) {
-        if (!isset($modules['enable'][$dependency]) && !$this->moduleHandler->moduleExists($dependency)) {
+        if (!isset($modules['install'][$dependency]) && !$this->moduleHandler->moduleExists($dependency)) {
           $modules['dependencies'][$module][$dependency] = $data[$dependency]->info['name'];
-          $modules['enable'][$dependency] = $data[$dependency]->info['name'];
+          $modules['install'][$dependency] = $data[$dependency]->info['name'];
         }
       }
     }
@@ -371,11 +352,11 @@ protected function buildModuleList(array $form_state) {
 
     // Invoke hook_requirements('install'). If failures are detected, make
     // sure the dependent modules aren't installed either.
-    foreach (array_keys($modules['enable']) as $module) {
-      if (drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED && !drupal_check_module($module)) {
-        unset($modules['enable'][$module]);
+    foreach (array_keys($modules['install']) as $module) {
+      if (!drupal_check_module($module)) {
+        unset($modules['install'][$module]);
         foreach (array_keys($data[$module]->required_by) as $dependent) {
-          unset($modules['enable'][$dependent]);
+          unset($modules['install'][$dependent]);
           unset($modules['dependencies'][$dependent]);
         }
       }
@@ -388,11 +369,12 @@ protected function buildModuleList(array $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
-    // Retrieve a list of modules to enable/disable and their dependencies.
+    // Retrieve a list of modules to install and their dependencies.
     $modules = $this->buildModuleList($form_state);
 
-    // Check if we have to enable any dependencies. If there is one or more
-    // dependencies that are not enabled yet, redirect to the confirmation form.
+    // Check if we have to install any dependencies. If there is one or more
+    // dependencies that are not installed yet, redirect to the confirmation
+    // form.
     if (!empty($modules['dependencies']) || !empty($modules['missing'])) {
       // Write the list of changed module states into a key value store.
       $account = $this->getCurrentUser()->id();
@@ -410,11 +392,8 @@ public function submitForm(array &$form, array &$form_state) {
     $before = $this->moduleHandler->getModuleList();
 
     // There seem to be no dependencies that would need approval.
-    if (!empty($modules['enable'])) {
-      $this->moduleHandler->enable(array_keys($modules['enable']));
-    }
-    if (!empty($modules['disable'])) {
-      $this->moduleHandler->disable(array_keys($modules['disable']));
+    if (!empty($modules['install'])) {
+      $this->moduleHandler->install(array_keys($modules['install']));
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
index 33e402b..af1fb21 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
@@ -70,15 +70,15 @@ public function buildForm(array $form, array &$form_state) {
 
     // Get a list of disabled, installed modules.
     $modules = system_rebuild_module_data();
-    $disabled = array_filter($modules, function ($module) {
-      return empty($module->status) && drupal_get_installed_schema_version($module->name) > SCHEMA_UNINSTALLED;
+    $uninstallable = array_filter($modules, function ($module) use ($modules) {
+      return empty($modules[$module->name]->info['required']) && drupal_get_installed_schema_version($module->name) > SCHEMA_UNINSTALLED;
     });
 
     $form['modules'] = array();
 
     // Only build the rest of the form if there are any modules available to
     // uninstall;
-    if (empty($disabled)) {
+    if (empty($uninstallable)) {
       return $form;
     }
 
@@ -86,10 +86,10 @@ public function buildForm(array $form, array &$form_state) {
 
     // Sort all modules by their name.
     $this->moduleHandler->loadInclude('system', 'inc', 'system.admin');
-    uasort($disabled, 'system_sort_modules_by_info_name');
+    uasort($uninstallable, 'system_sort_modules_by_info_name');
 
     $form['uninstall'] = array('#tree' => TRUE);
-    foreach ($disabled as $module) {
+    foreach ($uninstallable as $module) {
       $name = $module->info['name'] ?: $module->name;
       $form['modules'][$module->name]['#module_name'] = $name;
       $form['modules'][$module->name]['name']['#markup'] = $name;
@@ -107,7 +107,7 @@ public function buildForm(array $form, array &$form_state) {
       foreach (array_keys($module->required_by) as $dependent) {
         if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {
           $name = isset($modules[$dependent]->info['name']) ? $modules[$dependent]->info['name'] : $dependent;
-          $form['modules'][$module->name]['#dependents'][] = $name;
+          $form['modules'][$module->name]['#required_by'][] = $name;
           $form['uninstall'][$module->name]['#disabled'] = TRUE;
         }
       }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
index cf7d9cf..4e45336 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
@@ -26,7 +26,7 @@ public static function getInfo() {
    * Ensures entity info cache is updated after changes.
    */
   function testEntityInfoChanges() {
-    module_enable(array('entity_cache_test'));
+    \Drupal::moduleHandler()->install(array('entity_cache_test'));
     $entity_info = entity_get_info();
     $this->assertTrue(isset($entity_info['entity_cache_test']), 'Test entity type found.');
 
@@ -39,8 +39,8 @@ function testEntityInfoChanges() {
     $info = entity_get_info('entity_cache_test');
     $this->assertEqual($info['label'], 'New label.', 'New label appears in entity info.');
 
-    // Disable the providing module and make sure the entity type is gone.
-    module_disable(array('entity_cache_test', 'entity_cache_test_dependency'));
+    // Uninstall the providing module and make sure the entity type is gone.
+    module_uninstall(array('entity_cache_test', 'entity_cache_test_dependency'));
     $entity_info = entity_get_info();
     $this->assertFalse(isset($entity_info['entity_cache_test']), 'Entity type of the providing module is gone.');
   }
@@ -51,7 +51,7 @@ function testEntityInfoChanges() {
    * @see entity_cache_test_watchdog()
    */
   function testEntityInfoCacheWatchdog() {
-    module_enable(array('entity_cache_test'));
+    \Drupal::moduleHandler()->install(array('entity_cache_test'));
     $info = \Drupal::state()->get('entity_cache_test');
     $this->assertEqual($info['label'], 'Entity Cache Test', 'Entity info label is correct.');
     $this->assertEqual($info['controllers']['storage'], 'Drupal\Core\Entity\DatabaseStorageController', 'Entity controller class info is correct.');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/LanguageSelectElementTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/LanguageSelectElementTest.php
index 2705aed..e3510f6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/LanguageSelectElementTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/LanguageSelectElementTest.php
@@ -75,7 +75,7 @@ function testLanguageSelectElementOptions() {
   function testHiddenLanguageSelectElement() {
     // Disable the language module, so that the language select field will not
     // be rendered.
-    module_disable(array('language'));
+    module_uninstall(array('language'));
     $this->drupalGet('form-test/language_select');
     // Check that the language fields were rendered on the page.
     $ids = array('edit-languages-all', 'edit-languages-configurable', 'edit-languages-locked', 'edit-languages-config-and-locked');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
index 2fd8eb9..71f29d4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
@@ -34,7 +34,7 @@ public static function getInfo() {
    */
   function testClassLoading() {
     // Enable the module_test and module_autoload_test modules.
-    module_enable(array('module_test', 'module_autoload_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test', 'module_autoload_test'), FALSE);
     $this->resetAll();
     // Check twice to test an unprimed and primed system_list() cache.
     for ($i=0; $i<2; $i++) {
@@ -50,7 +50,7 @@ function testClassLoading() {
    */
   function testClassLoadingDisabledModules() {
     // Ensure that module_autoload_test is disabled.
-    module_disable(array('module_autoload_test'), FALSE);
+    module_uninstall(array('module_autoload_test'), FALSE);
     $this->resetAll();
     // Check twice to test an unprimed and primed system_list() cache.
     for ($i=0; $i<2; $i++) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
index 59dc6a2..83030e1 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
@@ -54,20 +54,6 @@ function testMissingModules() {
     $this->assertRaw(t('@module (<span class="admin-missing">missing</span>)', array('@module' => drupal_ucfirst('_missing_dependency'))), 'A module with missing dependencies is marked as such.');
     $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[Testing][system_dependencies_test][enable]"]');
     $this->assert(count($checkbox) == 1, 'Checkbox for the module is disabled.');
-
-    // Force enable the system_dependencies_test module.
-    module_enable(array('system_dependencies_test'), FALSE);
-
-    // Verify that the module is forced to be disabled when submitting
-    // the module page.
-    $this->drupalPost('admin/modules', array(), t('Save configuration'));
-    $this->assertText(t('The @module module is missing, so the following module will be disabled: @depends.', array('@module' => '_missing_dependency', '@depends' => 'System dependency test')), 'The module missing dependencies will be disabled.');
-
-    // Confirm.
-    $this->drupalPost(NULL, NULL, t('Continue'));
-
-    // Verify that the module has been disabled.
-    $this->assertModules(array('system_dependencies_test'), FALSE);
   }
 
   /**
@@ -103,7 +89,7 @@ function testIncompatibleCoreVersionDependency() {
    * Tests enabling a module that depends on a module which fails hook_requirements().
    */
   function testEnableRequirementsFailureDependency() {
-    module_enable(array('comment'));
+    \Drupal::moduleHandler()->install(array('comment'));
 
     $this->assertModules(array('requirements1_test'), FALSE);
     $this->assertModules(array('requirements2_test'), FALSE);
@@ -130,7 +116,7 @@ function testEnableRequirementsFailureDependency() {
    * UI. Dependencies should be enabled before their dependents.
    */
   function testModuleEnableOrder() {
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->resetAll();
     $this->assertModules(array('module_test'), TRUE);
     \Drupal::state()->set('module_test.dependency', 'dependency');
@@ -161,7 +147,7 @@ function testModuleEnableOrder() {
     $this->assertModules(array('forum', 'ban', 'php', 'datetime', 'comment', 'history', 'taxonomy', 'options', 'number'), TRUE);
 
     // Check the actual order which is saved by module_test_modules_enabled().
-    $module_order = \Drupal::state()->get('system_test.module_enable_order') ?: array();
+    $module_order = \Drupal::state()->get('module_test.install_order') ?: array();
     $this->assertIdentical($module_order, $expected_order);
   }
 
@@ -175,14 +161,6 @@ function testUninstallDependents() {
     $this->drupalPost(NULL, array(), t('Continue'));
     $this->assertModules(array('forum'), TRUE);
 
-    // Disable forum and comment. Both should now be installed but disabled.
-    $edit = array('modules[Core][forum][enable]' => FALSE);
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertModules(array('forum'), FALSE);
-    $edit = array('modules[Core][comment][enable]' => FALSE);
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertModules(array('comment'), FALSE);
-
     // Check that the taxonomy module cannot be uninstalled.
     $this->drupalGet('admin/modules/uninstall');
     $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="uninstall[comment]"]');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php
deleted file mode 100644
index 8458bc7..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php
+++ /dev/null
@@ -1,226 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Module\EnableDisableTest.
- */
-
-namespace Drupal\system\Tests\Module;
-
-/**
- * Tests functionality for enabling and disabling modules.
- */
-class EnableDisableTest extends ModuleTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Enable/disable modules',
-      'description' => 'Enable/disable core module and confirm table creation/deletion.',
-      'group' => 'Module',
-    );
-  }
-
-  /**
-   * Tests that all core modules can be enabled, disabled and uninstalled.
-   */
-  function testEnableDisable() {
-    $modules = system_rebuild_module_data();
-    foreach ($modules as $name => $module) {
-      // Filters all modules under core directory.
-      $in_core_path = (strpos($module->uri, 'core/modules') === 0);
-      // Filters test modules under Testing package.
-      $in_testing_package = ($module->info['package'] == 'Testing');
-      // Try to enable, disable and uninstall all core modules, unless they are
-      // hidden or required or system test modules.
-      if (!$in_core_path || !empty($module->info['hidden']) || !empty($module->info['required']) || $in_testing_package) {
-        unset($modules[$name]);
-      }
-    }
-
-    // Throughout this test, some modules may be automatically enabled (due to
-    // dependencies). We'll keep track of them in an array, so we can handle
-    // them separately.
-    $automatically_enabled = array();
-
-    // Remove already enabled modules (via installation profile).
-    // @todo Remove this after removing all dependencies from Testing profile.
-    foreach ($this->container->get('module_handler')->getModuleList() as $dependency => $filename) {
-      // Exclude required modules. Only installation profile "suggestions" can
-      // be disabled and uninstalled.
-      if (isset($modules[$dependency])) {
-        $automatically_enabled[$dependency] = TRUE;
-      }
-    }
-
-    $this->assertTrue(count($modules), format_string('Found @count modules that can be enabled: %modules', array(
-      '@count' => count($modules),
-      '%modules' => implode(', ', array_keys($modules)),
-    )));
-
-    // Enable the dblog module first, since we will be asserting the presence
-    // of log messages throughout the test.
-    if (isset($modules['dblog'])) {
-      $modules = array('dblog' => $modules['dblog']) + $modules;
-    }
-
-    // Set a variable so that the hook implementations in system_test.module
-    // will display messages via drupal_set_message().
-    \Drupal::state()->set('system_test.verbose_module_hooks', TRUE);
-
-    // Go through each module in the list and try to enable it (unless it was
-    // already enabled automatically due to a dependency).
-    foreach ($modules as $name => $module) {
-      if (empty($automatically_enabled[$name])) {
-        // Start a list of modules that we expect to be enabled this time.
-        $modules_to_enable = array($name);
-
-        // Find out if the module has any dependencies that aren't enabled yet;
-        // if so, add them to the list of modules we expect to be automatically
-        // enabled.
-        foreach (array_keys($module->requires) as $dependency) {
-          if (isset($modules[$dependency]) && empty($automatically_enabled[$dependency])) {
-            $modules_to_enable[] = $dependency;
-            $automatically_enabled[$dependency] = TRUE;
-          }
-        }
-
-        // Check that each module is not yet enabled and does not have any
-        // database tables yet.
-        foreach ($modules_to_enable as $module_to_enable) {
-          $this->assertModules(array($module_to_enable), FALSE);
-          $this->assertModuleTablesDoNotExist($module_to_enable);
-        }
-
-        // Install and enable the module.
-        $edit = array();
-        $package = $module->info['package'];
-        $edit['modules[' . $package . '][' . $name . '][enable]'] = $name;
-        $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-        // Handle the case where modules were installed along with this one and
-        // where we therefore hit a confirmation screen.
-        if (count($modules_to_enable) > 1) {
-          $this->drupalPost(NULL, array(), t('Continue'));
-        }
-        $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-
-        // Check that hook_modules_installed() and hook_modules_enabled() were
-        // invoked with the expected list of modules, that each module's
-        // database tables now exist, and that appropriate messages appear in
-        // the logs.
-        foreach ($modules_to_enable as $module_to_enable) {
-          $this->assertText(t('hook_modules_installed fired for @module', array('@module' => $module_to_enable)));
-          $this->assertText(t('hook_modules_enabled fired for @module', array('@module' => $module_to_enable)));
-          $this->assertModules(array($module_to_enable), TRUE);
-          $this->assertModuleTablesExist($module_to_enable);
-          $this->assertModuleConfig($module_to_enable);
-          $this->assertLogMessage('system', "%module module installed.", array('%module' => $module_to_enable), WATCHDOG_INFO);
-          $this->assertLogMessage('system', "%module module enabled.", array('%module' => $module_to_enable), WATCHDOG_INFO);
-        }
-
-        // Disable and uninstall the original module, and check appropriate
-        // hooks, tables, and log messages. (Later, we'll go back and do the
-        // same thing for modules that were enabled automatically.) Skip this
-        // for the dblog module, because that is needed for the test; we'll go
-        // back and do that one at the end also.
-        if ($name != 'dblog') {
-          $this->assertSuccessfulDisableAndUninstall($name, $package);
-        }
-      }
-    }
-
-    // Go through all modules that were automatically enabled, and try to
-    // disable and uninstall them one by one.
-    while (!empty($automatically_enabled)) {
-      $initial_count = count($automatically_enabled);
-      foreach (array_keys($automatically_enabled) as $name) {
-        $module = $modules[$name];
-        $package = $module->info['package'];
-        // If the module can't be disabled due to dependencies, skip it and try
-        // again the next time. Otherwise, try to disable it.
-        $this->drupalGet('admin/modules');
-        $disabled_checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[' . $package . '][' . $name . '][enable]"]');
-        if (empty($disabled_checkbox) && $name != 'dblog') {
-          unset($automatically_enabled[$name]);
-          $this->assertSuccessfulDisableAndUninstall($name, $package);
-        }
-      }
-      $final_count = count($automatically_enabled);
-      // If all checkboxes were disabled, something is really wrong with the
-      // test. Throw a failure and avoid an infinite loop.
-      if ($initial_count == $final_count) {
-        $this->fail(t('Remaining modules could not be disabled.'));
-        break;
-      }
-    }
-
-    // Disable and uninstall the dblog module last, since we needed it for
-    // assertions in all the above tests.
-    if (isset($modules['dblog'])) {
-      $this->assertSuccessfulDisableAndUninstall('dblog');
-    }
-
-    // Now that all modules have been tested, go back and try to enable them
-    // all again at once. This tests two things:
-    // - That each module can be successfully enabled again after being
-    //   uninstalled.
-    // - That enabling more than one module at the same time does not lead to
-    //   any errors.
-    $edit = array();
-    foreach ($modules as $name => $module) {
-      $edit['modules[' . $module->info['package'] . '][' . $name . '][enable]'] = $name;
-    }
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-  }
-
-  /**
-   * Disables and uninstalls a module and asserts that it was done correctly.
-   *
-   * @param string $module
-   *   The name of the module to disable and uninstall.
-   * @param string $package
-   *   (optional) The package of the module to disable and uninstall. Defaults
-   *   to 'Core'.
-   */
-  function assertSuccessfulDisableAndUninstall($module, $package = 'Core') {
-    // Disable the module.
-    $edit = array();
-    $edit['modules[' . $package . '][' . $module . '][enable]'] = FALSE;
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-    $this->assertModules(array($module), FALSE);
-
-    // Check that the appropriate hook was fired and the appropriate log
-    // message appears.
-    $this->assertText(t('hook_modules_disabled fired for @module', array('@module' => $module)));
-    if ($module != 'dblog') {
-      $this->assertLogMessage('system', "%module module disabled.", array('%module' => $module), WATCHDOG_INFO);
-    }
-
-    //  Check that the module's database tables still exist.
-    $this->assertModuleTablesExist($module);
-    //  Check that the module's config files still exist.
-    $this->assertModuleConfig($module);
-
-    // Uninstall the module.
-    $edit = array();
-    $edit['uninstall[' . $module . ']'] = $module;
-    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
-    $this->drupalPost(NULL, NULL, t('Uninstall'));
-    $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
-    $this->assertModules(array($module), FALSE);
-
-    // Check that the appropriate hook was fired and the appropriate log
-    // message appears. (But don't check for the log message if the dblog
-    // module was just uninstalled, since the {watchdog} table won't be there
-    // anymore.)
-    $this->assertText(t('hook_modules_uninstalled fired for @module', array('@module' => $module)));
-    if ($module != 'dblog') {
-      $this->assertLogMessage('system', "%module module uninstalled.", array('%module' => $module), WATCHDOG_INFO);
-    }
-
-    // Check that the module's database tables no longer exist.
-    $this->assertModuleTablesDoNotExist($module);
-    // Check that the module's config files no longer exist.
-    $this->assertNoModuleConfig($module);
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/InstallTest.php
index a141f00..91fe4ef 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/InstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/InstallTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Module;
 
+use Drupal\Core\Extension\ExtensionNameLengthException;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -46,6 +47,53 @@ function testDrupalWriteRecord() {
     // 'module_test' module was being installed and enabled.
     $data = db_query("SELECT data FROM {module_test}")->fetchCol();
     $this->assertTrue(in_array('Data inserted in hook_install()', $data), 'Data inserted using drupal_write_record() in hook_install() is correctly saved.');
-    $this->assertTrue(in_array('Data inserted in hook_enable()', $data), 'Data inserted using drupal_write_record() in hook_enable() is correctly saved.');
   }
+
+  /**
+   * Tests enabling User module once more.
+   *
+   * Regression: The installer might enable a module twice due to automatic
+   * dependency resolution. A bug caused the stored weight for User module to
+   * be an array.
+   */
+  function testEnableUserTwice() {
+    \Drupal::moduleHandler()->install(array('user'), FALSE);
+    $this->assertIdentical(config('system.module')->get('enabled.user'), '0');
+  }
+
+  /**
+   * Tests recorded schema versions of early installed modules in the installer.
+   */
+  function testRequiredModuleSchemaVersions() {
+    $version = drupal_get_installed_schema_version('system', TRUE);
+    $this->assertTrue($version > 0, 'System module version is > 0.');
+    $version = drupal_get_installed_schema_version('user', TRUE);
+    $this->assertTrue($version > 0, 'User module version is > 0.');
+  }
+
+  /**
+   * Tests that an exception is thrown when a module name is too long.
+   */
+  function testModuleNameLength() {
+    $module_name = 'invalid_module_name_over_the_maximum_allowed_character_length';
+    $message = format_string('Exception thrown when enabling module %name with a name length over the allowed maximum', array('%name' => $module_name));
+    try {
+      $this->container->get('module_handler')->install(array($module_name));
+      $this->fail($message);
+    }
+    catch (ExtensionNameLengthException $e) {
+      $this->pass($message);
+    }
+
+    // Since for the UI, the submit callback uses FALSE, test that too.
+    $message = format_string('Exception thrown when enabling as if via the UI the module %name with a name length over the allowed maximum', array('%name' => $module_name));
+    try {
+      $this->container->get('module_handler')->install(array($module_name), FALSE);
+      $this->fail($message);
+    }
+    catch (ExtensionNameLengthException $e) {
+      $this->pass($message);
+    }
+  }
+
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/InstallUninstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/InstallUninstallTest.php
new file mode 100644
index 0000000..b849f37
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/InstallUninstallTest.php
@@ -0,0 +1,187 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Module\EnableDisableTest.
+ */
+
+namespace Drupal\system\Tests\Module;
+
+/**
+ * Tests functionality for installing and uninstalling modules.
+ */
+class InstallUninstallTest extends ModuleTestBase {
+
+  public static $modules = array('system_test', 'dblog');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Install/uninstall modules',
+      'description' => 'Install/uninstall core module and confirm table creation/deletion.',
+      'group' => 'Module',
+    );
+  }
+
+  /**
+   * Tests that a fixed set of modules can be installed and uninstalled.
+   */
+  public function testInstallUninstall() {
+    // Set a variable so that the hook implementations in system_test.module
+    // will display messages via drupal_set_message().
+    $this->container->get('state')->set('system_test.verbose_module_hooks', TRUE);
+
+    // Install and uninstall module_test to ensure hook_preinstall_module and
+    // hook_preuninstall_module are fired as expected.
+    $this->container->get('module_handler')->install(array('module_test'));
+    $this->assertEqual($this->container->get('state')->get('system_test_preinstall_module'), 'module_test');
+    $this->container->get('module_handler')->uninstall(array('module_test'));
+    $this->assertEqual($this->container->get('state')->get('system_test_preuninstall_module'), 'module_test');
+
+    // Try to install and uninstall book, toolbar modules and its dependencies.
+    $all_modules = system_rebuild_module_data();
+
+    $all_modules = array_filter($all_modules, function ($module) {
+      // Filter hidden, required and already enabled modules.
+      if (!empty($module->info['hidden']) || !empty($module->info['required']) || $module->status == TRUE) {
+        return FALSE;
+      }
+      return TRUE;
+    });
+
+    foreach (array('book', 'ckeditor', 'toolbar') as $name) {
+      $modules[$name] = $all_modules[$name];
+      foreach ($modules[$name]->requires as $dependency) {
+        if (isset($all_modules[$dependency['name']])) {
+          $modules[$dependency['name']] = $all_modules[$dependency['name']];
+        }
+      }
+    }
+
+    // Go through each module in the list and try to install it (unless it was
+    // already installed automatically due to a dependency).
+    $automatically_installed = array();
+    while (list($name, $module) = each($modules)) {
+      // Skip modules that have been automatically installed.
+      if (in_array($name, $automatically_installed)) {
+        continue;
+      }
+
+      // Start a list of modules that we expect to be installed this time.
+      $modules_to_install = array($name);
+      foreach (array_keys($module->requires) as $dependency) {
+        if (isset($modules[$dependency]) && !in_array($dependency, $automatically_installed)) {
+          $modules_to_install[] = $dependency;
+
+          // Add any potential dependency of this module to the list of modules we
+          // expect to be automatically installed.
+          $automatically_installed[] = $dependency;
+        }
+      }
+
+      // Check that each module is not yet enabled and does not have any
+      // database tables yet.
+      foreach ($modules_to_install as $module_to_install) {
+        $this->assertModules(array($module_to_install), FALSE);
+        $this->assertModuleTablesDoNotExist($module_to_install);
+      }
+
+      // Install the module.
+      $edit = array();
+      $package = $module->info['package'];
+      $edit["modules[$package][$name][enable]"] = TRUE;
+      $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+
+      // Handle the case where modules were installed along with this one and
+      // where we therefore hit a confirmation screen.
+      if (count($modules_to_install) > 1) {
+        $this->drupalPost(NULL, array(), t('Continue'));
+      }
+
+      $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+
+      // Check that hook_modules_installed() was invoked with the expected list
+      // of modules, that each module's database tables now exist, and that
+      // appropriate messages appear in the logs.
+      foreach ($modules_to_install as $module_to_install) {
+        $this->assertText(t('hook_modules_installed fired for @module', array('@module' => $module_to_install)));
+        $this->assertModules(array($module_to_install), TRUE);
+        $this->assertModuleTablesExist($module_to_install);
+        $this->assertModuleConfig($module_to_install);
+        $this->assertLogMessage('system', "%module module installed.", array('%module' => $module_to_install), WATCHDOG_INFO);
+      }
+
+      // Uninstall the original module, and check appropriate
+      // hooks, tables, and log messages. (Later, we'll go back and do the
+      // same thing for modules that were enabled automatically.)
+      $this->assertSuccessfullUninstall($name, $package);
+    }
+
+    // Go through all modules that were automatically installed, and try to
+    // uninstall them one by one.
+    while ($automatically_installed) {
+      $initial_count = count($automatically_installed);
+      foreach ($automatically_installed as $name) {
+        $package = $modules[$name]->info['package'];
+        // If the module can't be uninstalled due to dependencies, skip it and
+        // try again the next time. Otherwise, try to uninstall it.
+        $this->drupalGet('admin/modules/uninstall');
+        $disabled_checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="uninstall[' . $name . ']"]');
+        if (empty($disabled_checkbox)) {
+          $automatically_installed = array_diff($automatically_installed, array($name));
+          $this->assertSuccessfullUninstall($name, $package);
+        }
+      }
+      $final_count = count($automatically_installed);
+      // If all checkboxes were disabled, something is really wrong with the
+      // test. Throw a failure and avoid an infinite loop.
+      if ($initial_count == $final_count) {
+        $this->fail('Remaining modules could not be disabled.');
+        break;
+      }
+    }
+
+    // Now that all modules have been tested, go back and try to enable them
+    // all again at once. This tests two things:
+    // - That each module can be successfully enabled again after being
+    //   uninstalled.
+    // - That enabling more than one module at the same time does not lead to
+    //   any errors.
+    $edit = array();
+    foreach ($modules as $name => $module) {
+      $edit['modules[' . $module->info['package'] . '][' . $name . '][enable]'] = TRUE;
+    }
+    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+  }
+
+  /**
+   * Uninstalls a module and asserts that it was done correctly.
+   *
+   * @param string $module
+   *   The name of the module to uninstall.
+   * @param string $package
+   *   (optional) The package of the module to uninstall. Defaults
+   *   to 'Core'.
+   */
+  protected function assertSuccessfullUninstall($module, $package = 'Core') {
+    $edit = array();
+    $edit['uninstall[' . $module . ']'] = TRUE;
+    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
+    $this->drupalPost(NULL, NULL, t('Uninstall'));
+    $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
+    $this->assertModules(array($module), FALSE);
+
+    // Check that the appropriate hook was fired and the appropriate log
+    // message appears. (But don't check for the log message if the dblog
+    // module was just uninstalled, since the {watchdog} table won't be there
+    // anymore.)
+    $this->assertText(t('hook_modules_uninstalled fired for @module', array('@module' => $module)));
+    $this->assertLogMessage('system', "%module module uninstalled.", array('%module' => $module), WATCHDOG_INFO);
+
+    // Check that the module's database tables no longer exist.
+    $this->assertModuleTablesDoNotExist($module);
+    // Check that the module's config files no longer exist.
+    $this->assertNoModuleConfig($module);
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
index d2d65bc..ee303e4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
@@ -43,7 +43,7 @@ function testModuleList() {
     $this->assertModuleList($module_list, t('Standard profile'));
 
     // Try to install a new module.
-    module_enable(array('ban'));
+    \Drupal::moduleHandler()->install(array('ban'));
     $module_list[] = 'ban';
     sort($module_list);
     $this->assertModuleList($module_list, t('After adding a module'));
@@ -98,18 +98,18 @@ function testModuleImplements() {
     $this->assertTrue(cache('bootstrap')->get('module_implements'), 'The module implements cache is populated after requesting a page.');
 
     // Prime ModuleHandler's hook implementation cache by invoking a random hook
-    // name. The subsequent module_enable() below will only call into
-    // setModuleList(), but will not explicitly reset the hook implementation
-    // cache, as that is expected to happen implicitly by setting the module
-    // list. This verifies that the hook implementation cache is cleared
-    // whenever setModuleList() is called.
+    // name. The subsequent \Drupal\Core\Extension\ModuleHandler::install()
+    // below will only call into setModuleList(), but will not explicitly reset
+    // the hook implementation cache, as that is expected to happen implicitly
+    // by setting the module list. This verifies that the hook implementation
+    // cache is cleared whenever setModuleList() is called.
     $module_handler = \Drupal::moduleHandler();
     $module_handler->invokeAll('test');
 
     // Make sure group include files are detected properly even when the file is
     // already loaded when the cache is rebuilt.
     // For that activate the module_test which provides the file to load.
-    module_enable(array('module_test'));
+    \Drupal::moduleHandler()->install(array('module_test'));
     $module_handler->loadAll();
     module_load_include('inc', 'module_test', 'module_test.file');
     $modules = $module_handler->getImplementations('test_hook');
@@ -120,7 +120,7 @@ function testModuleImplements() {
    * Test that module_invoke() can load a hook defined in hook_hook_info().
    */
   function testModuleInvoke() {
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->resetAll();
     $this->drupalGet('module-test/hook-dynamic-loading-invoke');
     $this->assertText('success!', 'module_invoke() dynamically loads a hook defined in hook_hook_info().');
@@ -130,7 +130,7 @@ function testModuleInvoke() {
    * Test that module_invoke_all() can load a hook defined in hook_hook_info().
    */
   function testModuleInvokeAll() {
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->resetAll();
     $this->drupalGet('module-test/hook-dynamic-loading-invoke-all');
     $this->assertText('success!', 'module_invoke_all() dynamically loads a hook defined in hook_hook_info().');
@@ -143,7 +143,7 @@ function testModuleInvokeAll() {
    * functions execute early in the request handling.
    */
   function testModuleInvokeAllDuringLoadFunction() {
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->resetAll();
     $this->drupalGet('module-test/hook-dynamic-loading-invoke-all-during-load/module_test');
     $this->assertText('success!', 'Menu item load function invokes a hook defined in hook_hook_info().');
@@ -156,7 +156,7 @@ function testDependencyResolution() {
     // Enable the test module, and make sure that other modules we are testing
     // are not already enabled. (If they were, the tests below would not work
     // correctly.)
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->assertTrue(module_exists('module_test'), 'Test module is enabled.');
     $this->assertFalse(module_exists('forum'), 'Forum module is disabled.');
     $this->assertFalse(module_exists('ban'), 'Ban module is disabled.');
@@ -166,53 +166,24 @@ function testDependencyResolution() {
     // depends on a made-up module, foo. Nothing should be installed.
     \Drupal::state()->set('module_test.dependency', 'missing dependency');
     drupal_static_reset('system_rebuild_module_data');
-    $result = module_enable(array('forum'));
-    $this->assertFalse($result, 'module_enable() returns FALSE if dependencies are missing.');
-    $this->assertFalse(module_exists('forum'), 'module_enable() aborts if dependencies are missing.');
+    $result = \Drupal::moduleHandler()->install(array('forum'));
+    $this->assertFalse($result, '\Drupal\Core\Extension\ModuleHandler::install() returns FALSE if dependencies are missing.');
+    $this->assertFalse(module_exists('forum'), '\Drupal\Core\Extension\ModuleHandler::install() aborts if dependencies are missing.');
 
     // Now, fix the missing dependency. Forum module depends on ban, but ban
-    // depends on the PHP module. module_enable() should work.
+    // depends on the PHP module.
+    // \Drupal\Core\Extension\ModuleHandler::install() should work.
     \Drupal::state()->set('module_test.dependency', 'dependency');
     drupal_static_reset('system_rebuild_module_data');
-    $result = module_enable(array('forum'));
-    $this->assertTrue($result, 'module_enable() returns the correct value.');
+    $result = \Drupal::moduleHandler()->install(array('forum'));
+    $this->assertTrue($result, '\Drupal\Core\Extension\ModuleHandler::install() returns the correct value.');
     // Verify that the fake dependency chain was installed.
-    $this->assertTrue(module_exists('ban') && module_exists('php'), 'Dependency chain was installed by module_enable().');
+    $this->assertTrue(module_exists('ban') && module_exists('php'), 'Dependency chain was installed by \Drupal\Core\Extension\ModuleHandler::install().');
     // Verify that the original module was installed.
     $this->assertTrue(module_exists('forum'), 'Module installation with unlisted dependencies succeeded.');
     // Finally, verify that the modules were enabled in the correct order.
-    $module_order = \Drupal::state()->get('system_test.module_enable_order') ?: array();
-    $this->assertEqual($module_order, array('php', 'ban', 'forum'), 'Modules were enabled in the correct order by module_enable().');
-
-    // Now, disable the PHP module. Both forum and ban should be disabled as
-    // well, in the correct order.
-    module_disable(array('php'));
-    $this->assertTrue(!module_exists('forum') && !module_exists('ban'), 'Depedency chain was disabled by module_disable().');
-    $this->assertFalse(module_exists('php'), 'Disabling a module with unlisted dependents succeeded.');
-    $disabled_modules = \Drupal::state()->get('module_test.disable_order') ?: array();
-    $this->assertEqual($disabled_modules, array('forum', 'ban', 'php'), 'Modules were disabled in the correct order by module_disable().');
-
-    // Disable a module that is listed as a dependency by the installation
-    // profile. Make sure that the profile itself is not on the list of
-    // dependent modules to be disabled.
-    $profile = drupal_get_profile();
-    $info = install_profile_info($profile);
-    $this->assertTrue(in_array('comment', $info['dependencies']), 'Comment module is listed as a dependency of the installation profile.');
-    $this->assertTrue(module_exists('comment'), 'Comment module is enabled.');
-    module_disable(array('comment'));
-    $this->assertFalse(module_exists('comment'), 'Comment module was disabled.');
-    $disabled_modules = \Drupal::state()->get('module_test.disable_order') ?: array();
-    $this->assertTrue(in_array('comment', $disabled_modules), 'Comment module is in the list of disabled modules.');
-    $this->assertFalse(in_array($profile, $disabled_modules), 'The installation profile is not in the list of disabled modules.');
-
-    // Try to uninstall the PHP module by itself. This should be rejected,
-    // since the modules which it depends on need to be uninstalled first, and
-    // that is too destructive to perform automatically.
-    $result = module_uninstall(array('php'));
-    $this->assertFalse($result, 'Calling module_uninstall() on a module whose dependents are not uninstalled fails.');
-    foreach (array('forum', 'ban', 'php') as $module) {
-      $this->assertNotEqual(drupal_get_installed_schema_version($module), SCHEMA_UNINSTALLED, format_string('The @module module was not uninstalled.', array('@module' => $module)));
-    }
+    $module_order = \Drupal::state()->get('module_test.install_order') ?: array();
+    $this->assertEqual($module_order, array('php', 'ban', 'forum'), 'Modules were enabled in the correct order by \Drupal\Core\Extension\ModuleHandler::install().');
 
     // Now uninstall all three modules explicitly, but in the incorrect order,
     // and make sure that drupal_uninstal_modules() uninstalled them in the
@@ -232,28 +203,28 @@ function testDependencyResolution() {
     $this->assertEqual(drupal_get_installed_schema_version('comment'), SCHEMA_UNINSTALLED, 'Comment module was uninstalled.');
     $uninstalled_modules = \Drupal::state()->get('module_test.uninstall_order') ?: array();
     $this->assertTrue(in_array('comment', $uninstalled_modules), 'Comment module is in the list of uninstalled modules.');
-    $this->assertFalse(in_array($profile, $uninstalled_modules), 'The installation profile is not in the list of uninstalled modules.');
+    $this->assertFalse(in_array($this->profile, $uninstalled_modules), 'The installation profile is not in the list of uninstalled modules.');
 
     // Enable forum module again, which should enable both the ban module and
     // php module. But, this time do it with ban module declaring a dependency
     // on a specific version of php module in its info file. Make sure that
-    // module_enable() still works.
+    // \Drupal\Core\Extension\ModuleHandler::install() still works.
     \Drupal::state()->set('module_test.dependency', 'version dependency');
     drupal_static_reset('system_rebuild_module_data');
-    $result = module_enable(array('forum'));
-    $this->assertTrue($result, 'module_enable() returns the correct value.');
+    $result = \Drupal::moduleHandler()->install(array('forum'));
+    $this->assertTrue($result, '\Drupal\Core\Extension\ModuleHandler::install() returns the correct value.');
     // Verify that the fake dependency chain was installed.
-    $this->assertTrue(module_exists('ban') && module_exists('php'), 'Dependency chain was installed by module_enable().');
+    $this->assertTrue(module_exists('ban') && module_exists('php'), 'Dependency chain was installed by \Drupal\Core\Extension\ModuleHandler::install().');
     // Verify that the original module was installed.
     $this->assertTrue(module_exists('forum'), 'Module installation with version dependencies succeeded.');
     // Finally, verify that the modules were enabled in the correct order.
-    $enable_order = \Drupal::state()->get('system_test.module_enable_order') ?: array();
+    $enable_order = \Drupal::state()->get('module_test.install_order') ?: array();
     $php_position = array_search('php', $enable_order);
     $ban_position = array_search('ban', $enable_order);
     $forum_position = array_search('forum', $enable_order);
     $php_before_ban = $php_position !== FALSE && $ban_position !== FALSE && $php_position < $ban_position;
     $ban_before_forum = $ban_position !== FALSE && $forum_position !== FALSE && $ban_position < $forum_position;
-    $this->assertTrue($php_before_ban && $ban_before_forum, 'Modules were enabled in the correct order by module_enable().');
+    $this->assertTrue($php_before_ban && $ban_before_forum, 'Modules were enabled in the correct order by \Drupal\Core\Extension\ModuleHandler::install().');
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnableTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnableTest.php
index d4967f8..e69de29 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnableTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnableTest.php
@@ -1,73 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\system\Tests\Module\ModuleEnableTest.
- */
-
-namespace Drupal\system\Tests\Module;
-
-use Drupal\Core\Extension\ExtensionNameLengthException;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests enabling modules.
- */
-class ModuleEnableTest extends WebTestBase {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Module enable',
-      'description' => 'Tests enabling modules.',
-      'group' => 'Module',
-    );
-  }
-
-  /**
-   * Tests enabling User module once more.
-   *
-   * Regression: The installer might enable a module twice due to automatic
-   * dependency resolution. A bug caused the stored weight for User module to
-   * be an array.
-   */
-  function testEnableUserTwice() {
-    $this->container->get('module_handler')->enable(array('user'), FALSE);
-    $this->assertIdentical(\Drupal::config('system.module')->get('enabled.user'), '0');
-  }
-
-  /**
-   * Tests recorded schema versions of early installed modules in the installer.
-   */
-  function testRequiredModuleSchemaVersions() {
-    $version = drupal_get_installed_schema_version('system', TRUE);
-    $this->assertTrue($version > 0, 'System module version is > 0.');
-    $version = drupal_get_installed_schema_version('user', TRUE);
-    $this->assertTrue($version > 0, 'User module version is > 0.');
-  }
-
-  /**
-   * Tests that an exception is thrown when a module name is too long.
-   */
-  function testModuleNameLength() {
-    $module_name = 'invalid_module_name_over_the_maximum_allowed_character_length';
-    $message = format_string('Exception thrown when enabling module %name with a name length over the allowed maximum', array('%name' => $module_name));
-    try {
-      $this->container->get('module_handler')->enable(array($module_name));
-      $this->fail($message);
-    }
-    catch (ExtensionNameLengthException $e) {
-      $this->pass($message);
-    }
-
-    // Since for the UI, the submit callback uses FALSE, test that too.
-    $message = format_string('Exception thrown when enabling as if via the UI the module %name with a name length over the allowed maximum', array('%name' => $module_name));
-    try {
-      $this->container->get('module_handler')->enable(array($module_name), FALSE);
-      $this->fail($message);
-    }
-    catch (ExtensionNameLengthException $e) {
-      $this->pass($message);
-    }
-  }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
index 78cecbf..de0e075 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
@@ -35,7 +35,6 @@ public static function getInfo() {
   function testUserPermsUninstalled() {
     // Uninstalls the module_test module, so hook_modules_uninstalled()
     // is executed.
-    module_disable(array('module_test'));
     module_uninstall(array('module_test'));
 
     // Are the perms defined by module_test removed?
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php
index 7998af1..c48e8a2 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php
@@ -12,13 +12,6 @@
  */
 class VersionTest extends ModuleTestBase {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('module_test');
-
   public static function getInfo() {
     return array(
       'name' => 'Module versions',
diff --git a/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php b/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php
index bffd0f0..ffe398f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php
@@ -46,12 +46,12 @@ function testServiceProviderRegistration() {
    * Tests that the DIC keeps up with module enable/disable in the same request.
    */
   function testServiceProviderRegistrationDynamic() {
-    // Disable the module and ensure the service provider's service is not registered.
-    module_disable(array('service_provider_test'));
+    // Uninstall the module and ensure the service provider's service is not registered.
+    \Drupal::moduleHandler()->uninstall(array('service_provider_test'));
     $this->assertFalse(drupal_container()->has('service_provider_test_class'), 'The service_provider_test_class service does not exist in the DIC.');
 
-    // Enable the module and ensure the service provider's service is registered.
-    module_enable(array('service_provider_test'));
+    // Install the module and ensure the service provider's service is registered.
+    \Drupal::moduleHandler()->install(array('service_provider_test'));
     $this->assertTrue(drupal_container()->has('service_provider_test_class'), 'The service_provider_test_class service exists in the DIC.');
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DefaultMobileMetaTagsTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DefaultMobileMetaTagsTest.php
index e5a3b98..ba0889f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/DefaultMobileMetaTagsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/DefaultMobileMetaTagsTest.php
@@ -42,7 +42,7 @@ public function testDefaultMetaTagsExist() {
    * Verifies that the default mobile meta tags can be removed.
    */
   public function testRemovingDefaultMetaTags() {
-    module_enable(array('system_module_test'));
+    \Drupal::moduleHandler()->install(array('system_module_test'));
     $this->drupalGet('');
     foreach ($this->default_metatags as $name => $metatag) {
       $this->assertNoRaw($metatag, String::format('Default Mobile meta tag "@name" removed properly.', array('@name' => $name)), 'System');
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
index aa2e1ae..c739dd9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
@@ -31,7 +31,7 @@ public static function getInfo() {
   function testSystemInfoAlter() {
     // Enable seven and the test module.
     theme_enable(array('seven'));
-    module_enable(array('module_test'), FALSE);
+    \Drupal::moduleHandler()->install(array('module_test'), FALSE);
     $this->assertTrue(module_exists('module_test'), 'Test module is enabled.');
 
     // Verify that the rebuilt and altered theme info is returned.
@@ -44,19 +44,5 @@ function testSystemInfoAlter() {
     $this->assertTrue(isset($info['regions']['test_region']), 'Altered theme info was returned by system_list().');
     $list_themes = list_themes();
     $this->assertTrue(isset($list_themes['seven']->info['regions']['test_region']), 'Altered theme info was returned by list_themes().');
-
-    // Disable the module and verify that rebuilt .info.yml does not contain it.
-    module_disable(array('module_test'), FALSE);
-    $this->assertFalse(module_exists('module_test'), 'Test module is disabled.');
-
-    $info = system_get_info('theme', 'seven');
-    $this->assertFalse(isset($info['regions']['test_region']), 'Altered theme info was not returned by system_get_info().');
-    $seven_regions = system_region_list('seven');
-    $this->assertFalse(isset($seven_regions['test_region']), 'Altered theme info was not returned by system_region_list().');
-    $system_list_themes = system_list('theme');
-    $info = $system_list_themes['seven']->info;
-    $this->assertFalse(isset($info['regions']['test_region']), 'Altered theme info was not returned by system_list().');
-    $list_themes = list_themes();
-    $this->assertFalse(isset($list_themes['seven']->info['regions']['test_region']), 'Altered theme info was not returned by list_themes().');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/MainContentFallbackTest.php b/core/modules/system/lib/Drupal/system/Tests/System/MainContentFallbackTest.php
index ae39a10..99af2dd 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/MainContentFallbackTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/MainContentFallbackTest.php
@@ -52,12 +52,13 @@ function setUp() {
    */
   function testMainContentFallback() {
     $edit = array();
-    // Disable the block module.
-    $edit['modules[Core][block][enable]'] = FALSE;
-    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+    // Uninstall the block module.
+    $edit['uninstall[block]'] = 'block';
+    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
+    $this->drupalPost(NULL, NULL, t('Uninstall'));
+    $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
     $this->rebuildContainer();
-    $this->assertFalse(module_exists('block'), 'Block module disabled.');
+    $this->assertFalse(module_exists('block'), 'Block module uninstall.');
 
     // At this point, no region is filled and fallback should be triggered.
     $this->drupalGet('admin/config/system/site-information');
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php
index d3476f7..b584a33 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php
@@ -254,7 +254,7 @@ function testSwitchDefaultTheme() {
    * Test that themes can't be enabled when the base theme or engine is missing.
    */
   function testInvalidTheme() {
-    module_enable(array('theme_page_test'));
+    \Drupal::moduleHandler()->install(array('theme_page_test'));
     $this->drupalGet('admin/appearance');
     $this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')), 'Invalid base theme check succeeded.');
     $this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')), 'Invalid theme engine check succeeded.');
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 a633558..5733ac3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
@@ -219,29 +219,6 @@ function testThemeGetSetting() {
   }
 
   /**
-   * Ensures the theme registry is rebuilt when modules are disabled/enabled.
-   */
-  function testRegistryRebuild() {
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', 'The theme registry contains theme_test_foo.');
-
-    module_disable(array('theme_test'), FALSE);
-    // After enabling/disabling a module during a test, we need to rebuild the
-    // container and ensure the extension handler is loaded, otherwise theme()
-    // throws an exception.
-    $this->rebuildContainer();
-    $this->container->get('module_handler')->loadAll();
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), FALSE, 'The theme registry does not contain theme_test_foo, because the module is disabled.');
-
-    module_enable(array('theme_test'), FALSE);
-    // After enabling/disabling a module during a test, we need to rebuild the
-    // container and ensure the extension handler is loaded, otherwise theme()
-    // throws an exception.
-    $this->rebuildContainer();
-    $this->container->get('module_handler')->loadAll();
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.');
-  }
-
-  /**
    * Tests child element rendering for 'render element' theme hooks.
    */
   function testDrupalRenderChildren() {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php
index 6aa50b2..64dc1ba 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php
@@ -47,7 +47,7 @@ public function testDisabledUpgrade() {
       }
     }
     $to_enable = array_diff_key($available, $enabled);
-    module_enable(array_keys($to_enable));
+    \Drupal::moduleHandler()->install(array_keys($to_enable));
     // Check for updates.
     require_once DRUPAL_ROOT . '/core/includes/update.inc';
     require_once DRUPAL_ROOT . '/core/includes/install.inc';
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index df7ef6f..8657ee6 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -663,11 +663,11 @@ function theme_system_modules_uninstall($variables) {
   // Display table.
   $rows = array();
   foreach (element_children($form['modules']) as $module) {
-    if (!empty($form['modules'][$module]['#dependents'])) {
-      $disabled_message = format_plural(count($form['modules'][$module]['#dependents']),
+    if (!empty($form['modules'][$module]['#required_by'])) {
+      $disabled_message = format_plural(count($form['modules'][$module]['#required_by']),
         'To uninstall @module, the following module must be uninstalled first: @required_modules',
         'To uninstall @module, the following modules must be uninstalled first: @required_modules',
-        array('@module' => $form['modules'][$module]['#module_name'], '@required_modules' => implode(', ', $form['modules'][$module]['#dependents'])));
+        array('@module' => $form['modules'][$module]['#module_name'], '@required_modules' => implode(', ', $form['modules'][$module]['#required_by'])));
       $disabled_message = '<div class="admin-requirements">' . $disabled_message . '</div>';
     }
     else {
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 49e87a0..2903d09 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1929,26 +1929,12 @@ function hook_rebuild() {
 }
 
 /**
- * Perform necessary actions before modules are installed.
+ * Perform necessary actions before a module is installed.
  *
- * This function allows all modules to react prior to a module being installed.
- *
- * @param $modules
- *   An array of modules about to be installed.
- */
-function hook_modules_preinstall($modules) {
-  mymodule_cache_clear();
-}
-
-/**
- * Perform necessary actions before modules are enabled.
- *
- * This function allows all modules to react prior to a module being enabled.
- *
- * @param $module
- *   An array of modules about to be enabled.
+ * @param string $module
+ *   The name of the module about to be installed.
  */
-function hook_modules_preenable($modules) {
+function hook_module_preinstall($module) {
   mymodule_cache_clear();
 }
 
@@ -1958,14 +1944,13 @@ function hook_modules_preenable($modules) {
  * This function differs from hook_install() in that it gives all other modules
  * a chance to perform actions when a module is installed, whereas
  * hook_install() is only called on the module actually being installed. See
- * module_enable() for a detailed description of the order in which install and
- * enable hooks are invoked.
+ * \Drupal\Core\Extension\ModuleHandler::install() for a detailed description of
+ * the order in which install and enable hooks are invoked.
  *
  * @param $modules
  *   An array of the modules that were installed.
  *
- * @see module_enable()
- * @see hook_modules_enabled()
+ * @see \Drupal\Core\Extension\ModuleHandler::install()
  * @see hook_install()
  */
 function hook_modules_installed($modules) {
@@ -1975,45 +1960,13 @@ function hook_modules_installed($modules) {
 }
 
 /**
- * Perform necessary actions after modules are enabled.
- *
- * This function differs from hook_enable() in that it gives all other modules a
- * chance to perform actions when modules are enabled, whereas hook_enable() is
- * only called on the module actually being enabled. See module_enable() for a
- * detailed description of the order in which install and enable hooks are
- * invoked.
- *
- * @param $modules
- *   An array of the modules that were enabled.
+ * Perform necessary actions before a module is uninstalled.
  *
- * @see hook_enable()
- * @see hook_modules_installed()
- * @see module_enable()
+ * @param string $modules
+ *   The name of the module about to be uninstalled.
  */
-function hook_modules_enabled($modules) {
-  if (in_array('lousy_module', $modules)) {
-    drupal_set_message(t('mymodule is not compatible with lousy_module'), 'error');
-    mymodule_disable_functionality();
-  }
-}
-
-/**
- * Perform necessary actions after modules are disabled.
- *
- * This function differs from hook_disable() in that it gives all other modules
- * a chance to perform actions when modules are disabled, whereas hook_disable()
- * is only called on the module actually being disabled.
- *
- * @param $modules
- *   An array of the modules that were disabled.
- *
- * @see hook_disable()
- * @see hook_modules_uninstalled()
- */
-function hook_modules_disabled($modules) {
-  if (in_array('lousy_module', $modules)) {
-    mymodule_enable_functionality();
-  }
+function hook_module_preuninstall($module) {
+  mymodule_cache_clear();
 }
 
 /**
@@ -2327,9 +2280,9 @@ function hook_requirements($phase) {
  * .module file is needed, it may be loaded with drupal_load().
  *
  * The tables declared by this hook will be automatically created when the
- * module is first enabled, and removed when the module is uninstalled. This
- * happens before hook_install() is invoked, and after hook_uninstall() is
- * invoked, respectively.
+ * module is installed, and removed when the module is uninstalled. This happens
+ * before hook_install() is invoked, and after hook_uninstall() is invoked,
+ * respectively.
  *
  * By declaring the tables used by your module via an implementation of
  * hook_schema(), these tables will be available on all supported database
@@ -2501,11 +2454,10 @@ function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $que
  *
  * Implementations of this hook are by convention declared in the module's
  * .install file. The implementation can rely on the .module file being loaded.
- * The hook will only be called the first time a module is enabled or after it
- * is re-enabled after being uninstalled. The module's schema version will be
- * set to the module's greatest numbered update hook. Because of this, any time
- * a hook_update_N() is added to the module, this function needs to be updated
- * to reflect the current version of the database schema.
+ * The hook will only be called when a module is installed. The module's schema
+ * version will be set to the module's greatest numbered update hook. Because of
+ * this, any time a hook_update_N() is added to the module, this function needs
+ * to be updated to reflect the current version of the database schema.
  *
  * See the @link http://drupal.org/node/146843 Schema API documentation @endlink
  * for details on hook_schema and how database tables are defined.
@@ -2519,9 +2471,7 @@ function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $que
  * be removed during uninstall should be removed with hook_uninstall().
  *
  * @see hook_schema()
- * @see module_enable()
- * @see hook_enable()
- * @see hook_disable()
+ * @see \Drupal\Core\Extension\ModuleHandler::install()
  * @see hook_uninstall()
  * @see hook_modules_installed()
  */
@@ -2765,35 +2715,6 @@ function hook_uninstall() {
 }
 
 /**
- * Perform necessary actions after module is enabled.
- *
- * The hook is called every time the module is enabled. It should be
- * implemented in the module's .install file. The implementation can
- * rely on the .module file being loaded.
- *
- * @see module_enable()
- * @see hook_install()
- * @see hook_modules_enabled()
- */
-function hook_enable() {
-  mymodule_cache_rebuild();
-}
-
-/**
- * Perform necessary actions before module is disabled.
- *
- * The hook is called every time the module is disabled. It should be
- * implemented in the module's .install file. The implementation can rely
- * on the .module file being loaded.
- *
- * @see hook_uninstall()
- * @see hook_modules_disabled()
- */
-function hook_disable() {
-  mymodule_cache_rebuild();
-}
-
-/**
  * Return an array of tasks to be performed by an installation profile.
  *
  * Any tasks you define here will be run, in order, after the installer has
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 7777e0c..298b2a3 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1529,7 +1529,7 @@ function system_update_8020() {
       ->condition('aid', 'system_block_ip_action')
       ->execute();
     // Enable the new Ban module.
-    module_enable(array('ban'));
+    Drupal::moduleHandler()->install(array('ban'));
   }
   else {
     // Drop old table.
@@ -1542,7 +1542,7 @@ function system_update_8020() {
  */
 function system_update_8021() {
   // Enable the module without re-installing the schema.
-  module_enable(array('action'));
+  Drupal::moduleHandler()->install(array('action'));
   // Rename former System module actions.
   $map = array(
     'system_message_action' => 'action_message_action',
@@ -1843,7 +1843,7 @@ function system_update_8041() {
  * Enable the new Entity module.
  */
 function system_update_8042() {
-  module_enable(array('entity'));
+  Drupal::moduleHandler()->install(array('entity'));
 }
 
 /**
@@ -1957,7 +1957,7 @@ function system_update_8047() {
  */
 function system_update_8048() {
   // Enable the module without re-installing the schema.
-  module_enable(array('menu_link'));
+  Drupal::moduleHandler()->install(array('menu_link'));
 
   // Add the langcode column if it doesn't exist.
   if (!db_field_exists('menu_inks', 'langcode')) {
@@ -2226,7 +2226,6 @@ function system_update_8058() {
     );
     db_change_field('menu_links', 'module', 'module', $spec);
   }
-
 }
 
 /**
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 94fbd21..3330e86 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2415,7 +2415,7 @@ function system_check_directory($form_element) {
 /**
  * Returns an array of information about enabled modules or themes.
  *
- * This function returns the contents of the .info.yml file for each enabled
+ * This function returns the contents of the .info.yml file for each installed
  * module or theme.
  *
  * @param $type
@@ -2570,13 +2570,11 @@ function system_rebuild_module_data() {
     $files = array();
     ksort($modules);
     // Add name, status, weight, and schema version.
-    $enabled_modules = (array) Drupal::config('system.module')->get('enabled');
-    $disabled_modules = (array) Drupal::config('system.module.disabled')->get();
-    $all_modules = $enabled_modules + $disabled_modules;
+    $all_modules = (array) Drupal::config('system.module')->get('enabled');
     foreach ($modules as $module => $record) {
       $record->name = $module;
       $record->weight = isset($all_modules[$module]) ? $all_modules[$module] : 0;
-      $record->status = (int) isset($enabled_modules[$module]);
+      $record->status = (int) isset($all_modules[$module]);
       $record->schema_version = SCHEMA_UNINSTALLED;
       $files[$module] = $record->filename;
     }
diff --git a/core/modules/system/tests/modules/entity_cache_test/entity_cache_test.module b/core/modules/system/tests/modules/entity_cache_test/entity_cache_test.module
index 962114c..19d4a55 100644
--- a/core/modules/system/tests/modules/entity_cache_test/entity_cache_test.module
+++ b/core/modules/system/tests/modules/entity_cache_test/entity_cache_test.module
@@ -8,11 +8,11 @@
 /**
  * Implements hook_watchdog().
  *
- * This hook is called during module_enable() and since this hook
- * implementation is invoked, we have to expect that this module and dependent
- * modules have been properly installed already. So we expect to be able to
- * retrieve the entity information that has been registered by the required
- * dependency module.
+ * This hook is called during \Drupal\Core\Extension\ModuleHandler::install()
+ * and since this hook implementation is invoked, we have to expect that this
+ * module and dependent modules have been properly installed already. So we
+ * expect to be able to retrieve the entity information that has been registered
+ * by the required dependency module.
  *
  * @see EnableDisableTestCase::testEntityCache()
  */
diff --git a/core/modules/system/tests/modules/module_test/module_test.install b/core/modules/system/tests/modules/module_test/module_test.install
index 4cc09df..f3b274a 100644
--- a/core/modules/system/tests/modules/module_test/module_test.install
+++ b/core/modules/system/tests/modules/module_test/module_test.install
@@ -31,12 +31,3 @@ function module_test_install() {
   $record = array('data' => 'Data inserted in hook_install()');
   drupal_write_record('module_test', $record);
 }
-
-/**
- * Implements hook_enable().
- */
-function module_test_enable() {
-  $record = array('data' => 'Data inserted in hook_enable()');
-  drupal_write_record('module_test', $record);
-}
-
diff --git a/core/modules/system/tests/modules/module_test/module_test.module b/core/modules/system/tests/modules/module_test/module_test.module
index fd1d2e6..bfbad0d 100644
--- a/core/modules/system/tests/modules/module_test/module_test.module
+++ b/core/modules/system/tests/modules/module_test/module_test.module
@@ -150,21 +150,12 @@ function module_test_class_loading() {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_modules_installed().
  */
-function module_test_modules_enabled($modules) {
+function module_test_modules_installed($modules) {
   // Record the ordered list of modules that were passed in to this hook so we
   // can check that the modules were enabled in the correct sequence.
-  Drupal::state()->set('system_test.module_enable_order', $modules);
-}
-
-/**
- * Implements hook_modules_disabled().
- */
-function module_test_modules_disabled($modules) {
-  // Record the ordered list of modules that were passed in to this hook so we
-  // can check that the modules were disabled in the correct sequence.
-  Drupal::state()->set('module_test.disable_order', $modules);
+  Drupal::state()->set('module_test.install_order', $modules);
 }
 
 /**
diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module
index ea10a04..2e749d9 100644
--- a/core/modules/system/tests/modules/system_test/system_test.module
+++ b/core/modules/system/tests/modules/system_test/system_test.module
@@ -98,28 +98,6 @@ function system_test_modules_installed($modules) {
 }
 
 /**
- * Implements hook_modules_enabled().
- */
-function system_test_modules_enabled($modules) {
-  if (Drupal::state()->get('system_test.verbose_module_hooks')) {
-    foreach ($modules as $module) {
-      drupal_set_message(t('hook_modules_enabled fired for @module', array('@module' => $module)));
-    }
-  }
-}
-
-/**
- * Implements hook_modules_disabled().
- */
-function system_test_modules_disabled($modules) {
-  if (Drupal::state()->get('system_test.verbose_module_hooks')) {
-    foreach ($modules as $module) {
-      drupal_set_message(t('hook_modules_disabled fired for @module', array('@module' => $module)));
-    }
-  }
-}
-
-/**
  * Implements hook_modules_uninstalled().
  */
 function system_test_modules_uninstalled($modules) {
@@ -280,3 +258,17 @@ function system_test_authorize_init_page($page_title) {
   system_authorized_init('system_test_authorize_run', drupal_get_path('module', 'system_test') . '/system_test.module', array(), $page_title);
   return new RedirectResponse($authorize_url);
 }
+
+/**
+ * Implements hook_module_preinstall().
+ */
+function system_test_module_preinstall($module) {
+  Drupal::state()->set('system_test_preinstall_module', $module);
+}
+
+/**
+ * Implements hook_module_preuninstall().
+ */
+function system_test_module_preuninstall($module) {
+  Drupal::state()->set('system_test_preuninstall_module', $module);
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php
index fe2bce0..33c49cd 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php
@@ -202,10 +202,9 @@ function testUninstallReinstall() {
     );
     entity_create('field_instance', $this->instance_definition)->save();
 
-    module_disable(array('taxonomy'));
     require_once DRUPAL_ROOT . '/core/includes/install.inc';
     module_uninstall(array('taxonomy'));
-    module_enable(array('taxonomy'));
+    \Drupal::moduleHandler()->install(array('taxonomy'));
 
     // Now create a vocabulary with the same name. All field instances
     // connected to this vocabulary name should have been removed when the
diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install
index 39835d6..f05e6e0 100644
--- a/core/modules/taxonomy/taxonomy.install
+++ b/core/modules/taxonomy/taxonomy.install
@@ -10,22 +10,6 @@
 use Drupal\field\Entity\Field;
 
 /**
- * Implements hook_uninstall().
- */
-function taxonomy_uninstall() {
-  Drupal::entityManager()->addNamespaces(new ArrayIterator(array(
-    'Drupal\taxonomy' => DRUPAL_ROOT . '/core/modules/taxonomy/lib',
-  )));
-  drupal_classloader_register('taxonomy', 'core/modules/taxonomy');
-  // Remove taxonomy_term bundles.
-  $config_names = config_get_storage_names_with_prefix('taxonomy.vocabulary.');
-  foreach ($config_names as $config_name) {
-    $vid = substr($config_name, strlen('taxonomy.vocabulary.'));
-    entity_invoke_bundle_hook('delete', 'taxonomy_term', $vid);
-  }
-}
-
-/**
  * Implements hook_schema().
  */
 function taxonomy_schema() {
diff --git a/core/modules/toolbar/toolbar.install b/core/modules/toolbar/toolbar.install
index 3d4f517..4b03662 100644
--- a/core/modules/toolbar/toolbar.install
+++ b/core/modules/toolbar/toolbar.install
@@ -18,7 +18,7 @@
  */
 function toolbar_update_8000() {
   // Enable the modules without re-installing the schema.
-  module_enable(array('breakpoint'));
+  Drupal::moduleHandler()->install(array('breakpoint'));
 }
 
 /**
diff --git a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerTest.php b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerTest.php
index b11df97..4020fd3 100644
--- a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerTest.php
+++ b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerTest.php
@@ -257,7 +257,7 @@ function testTrackerCronIndexing() {
    * Tests that publish/unpublish works at admin/content/node.
    */
   function testTrackerAdminUnpublish() {
-    module_enable(array('views'));
+    \Drupal::moduleHandler()->install(array('views'));
     $admin_user = $this->drupalCreateUser(array('access content overview', 'administer nodes', 'bypass node access'));
     $this->drupalLogin($admin_user);
 
diff --git a/core/modules/tracker/tracker.install b/core/modules/tracker/tracker.install
index 841d74a..6858a5d 100644
--- a/core/modules/tracker/tracker.install
+++ b/core/modules/tracker/tracker.install
@@ -13,9 +13,9 @@ function tracker_uninstall() {
 }
 
 /**
- * Implements hook_enable().
+ * Implements hook_install().
  */
-function tracker_enable() {
+function tracker_install() {
   $max_nid = db_query('SELECT MAX(nid) FROM {node}')->fetchField();
   if ($max_nid != 0) {
     Drupal::state()->set('tracker.index_nid', $max_nid);
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php b/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php
index af8d8c9..fd152ee 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php
@@ -67,7 +67,7 @@ function testUserCancelWithoutPermission() {
    * administer the site.
    */
   function testUserCancelUid1() {
-    module_enable(array('views'));
+    \Drupal::moduleHandler()->install(array('views'));
     // Update uid 1's name and password to we know it.
     $password = user_password();
     $account = array(
@@ -276,7 +276,7 @@ function testUserAnonymize() {
    */
   function testUserDelete() {
     \Drupal::config('user.settings')->set('cancel_method', 'user_cancel_delete')->save();
-    module_enable(array('comment'));
+    \Drupal::moduleHandler()->install(array('comment'));
     $this->resetAll();
 
     // Create a user.
@@ -392,7 +392,7 @@ function testUserWithoutEmailCancelByAdmin() {
    * Create an administrative user and mass-delete other users.
    */
   function testMassUserCancelByAdmin() {
-    module_enable(array('views'));
+    \Drupal::moduleHandler()->install(array('views'));
     \Drupal::config('user.settings')->set('cancel_method', 'user_cancel_reassign')->save();
     // Enable account cancellation notification.
     \Drupal::config('user.settings')->set('notify.status_canceled', TRUE)->save();
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserLoginTest.php b/core/modules/user/lib/Drupal/user/Tests/UserLoginTest.php
index fa657c9..4441df9 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserLoginTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserLoginTest.php
@@ -122,7 +122,7 @@ function testPasswordRehashOnLogin() {
     // containing the necessary container builder code and then verify that the
     // users password gets rehashed during the login.
     $overridden_count_log2 = 19;
-    module_enable(array('user_custom_phpass_params_test'));
+    \Drupal::moduleHandler()->install(array('user_custom_phpass_params_test'));
 
     $account->pass_raw = $password;
     $this->drupalLogin($account);
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index 6d15166..d72efc9 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -614,7 +614,7 @@ function user_update_8011() {
   // User pictures can only be migrated to the new user picture image field
   // if Image module is installed.
   if (!module_exists('image')) {
-    $old_schema = module_enable(array('image'));
+    $old_schema = Drupal::moduleHandler()->install(array('image'));
     if ($old_schema['image'] == SCHEMA_UNINSTALLED) {
       // Install image.module with schema version 8002 as a previous version
       // would have to create tables that would be removed again.
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
index a4c8567..67e84a6 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
@@ -52,7 +52,7 @@ protected function enableViewsTestModule() {
     \Drupal::state()->set('views_test_data_schema', $this->schemaDefinition());
     \Drupal::state()->set('views_test_data_views_data', $this->viewsData());
 
-    module_enable(array('views_test_data'));
+    \Drupal::moduleHandler()->install(array('views_test_data'));
     $this->resetAll();
     $this->rebuildContainer();
     $this->container->get('module_handler')->reload();
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayPath.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayPath.php
index 8f63b66..f8bc35a 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayPath.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayPath.php
@@ -59,7 +59,7 @@ public function testDeleteWithNoPath() {
    * Tests the menu and tab option form.
    */
   public function testMenuOptions() {
-    $this->container->get('module_handler')->enable(array('menu'));
+    $this->container->get('module_handler')->install(array('menu'));
     $this->drupalGet('admin/structure/views/view/test_view');
 
     // Add a new page display.
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/PreviewTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/PreviewTest.php
index 6ed0640..c9b019c 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/PreviewTest.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/PreviewTest.php
@@ -31,7 +31,7 @@ public static function getInfo() {
    * Tests contextual links in the preview form.
    */
   protected function testPreviewContextual() {
-    module_enable(array('contextual'));
+    \Drupal::moduleHandler()->install(array('contextual'));
     $this->drupalGet('admin/structure/views/view/test_preview/edit');
     $this->assertResponse(200);
     $this->drupalPost(NULL, $edit = array(), t('Update preview'));
