diff --git a/core/modules/system/src/Tests/Theme/ThemeTest.php b/core/modules/system/src/Tests/Theme/ThemeTest.php
index 4eae7ae..f52b4ba 100644
--- a/core/modules/system/src/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/src/Tests/Theme/ThemeTest.php
@@ -216,7 +216,7 @@ function testListThemes() {
     // Check if ThemeHandlerInterface::listInfo() returns disabled themes.
     // Check for base theme and subtheme lists.
     $base_theme_list = array('test_basetheme' => 'Theme test base theme');
-    $sub_theme_list = array('test_subsubtheme' => 'Theme test subsubtheme', 'test_subtheme' => 'Theme test subtheme');
+    $sub_theme_list = array('test_subsubtheme' => 'Theme test subsubtheme', 'test_subtheme' => 'Theme test subtheme', 'test_theme_alter' => 'Theme test alter');
 
     $this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, 'Base theme\'s object includes list of subthemes.');
     $this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, 'Subtheme\'s object includes list of base themes.');
diff --git a/core/modules/system/src/Tests/Theme/ThemeTestCustomSettings.php b/core/modules/system/src/Tests/Theme/ThemeTestCustomSettings.php
new file mode 100644
index 0000000..6cd41d0
--- /dev/null
+++ b/core/modules/system/src/Tests/Theme/ThemeTestCustomSettings.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\file\Entity\File;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests custom theme settings.
+ *
+ * @group Theme
+ */
+class ThemeTestCustomSettings extends WebTestBase {
+
+  /**
+   * Modules to install.
+   *
+   * @var array
+   */
+  public static $modules = ['file'];
+
+  /**
+   * A user with administrative permissions.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $bigUser;
+
+  protected function setUp() {
+    parent::setUp();
+
+    // Create user.
+    $this->bigUser = $this->drupalCreateUser(['administer themes']);
+    // Install theme.
+    \Drupal::service('theme_handler')->install(['test_theme', 'test_theme_alter']);
+  }
+
+  /**
+   * Retrieves a sample file of the specified type.
+   *
+   * @return \Drupal\file\FileInterface
+   */
+  protected function getTestFile($type_name, $size = NULL) {
+    // Get a file to upload.
+    $file = current($this->drupalGetTestFiles($type_name, $size));
+
+    // Add a filesize property to files as would be read by
+    // \Drupal\file\Entity\File::load().
+    $file->filesize = filesize($file->uri);
+
+    return File::create((array) $file);
+  }
+
+  /**
+   * Retrieves the fid of the last inserted file.
+   */
+  protected function getLastFileId() {
+    return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
+  }
+
+  /**
+   * Tests extended theme settings with custom fields and custom submit handlers.
+   */
+  public function testCustomThemeSettings() {
+    $themes = ['test_theme', 'test_theme_alter'];
+
+    foreach ($themes AS $theme) {
+      $this->config('system.theme')
+        ->set('default', $theme)
+        ->save();
+
+      $settings_path = 'admin/appearance/settings/' . $theme;
+
+      $this->drupalLogin($this->bigUser);
+
+      $this->drupalGet($settings_path);
+      $this->assertResponse(200);
+
+      // Add a new managed file.
+      $image_file = $this->getTestFile('image');
+      $edit1['files[custom_logo]'] = drupal_realpath($image_file->getFileUri());
+      $this->drupalPostAjaxForm(NULL, $edit1, 'custom_logo_upload_button');
+      // Assert the new file is uploaded as temporary
+      $last_fid = $this->getLastFileId();
+      $file = File::load($last_fid);
+      if ($file) {
+        $this->assertFalse($file->isPermanent());
+      }
+
+      // Edit some options
+      $edit2 = [
+        'toggle_favicon' => FALSE,
+        'custom_flag' => TRUE,
+        'custom_text' => 'Tests text',
+      ];
+      $this->drupalPostForm($settings_path, $edit2, t('Save configuration'));
+
+      $this->assertFieldByName('toggle_favicon', $edit2['toggle_favicon']);
+      $this->assertFieldByName('custom_flag', $edit2['custom_flag']);
+      $this->assertFieldByName('custom_text', $edit2['custom_text']);
+      // Assert the uploaded file is saved as permanent
+      $file = File::load($last_fid);
+      if ($file) {
+        $this->assertTrue($file->isPermanent());
+      }
+      $this->assertFieldByName('files[custom_logo]', $edit1['files[custom_logo]']);
+    }
+
+  }
+
+}
diff --git a/core/modules/system/tests/themes/test_theme/test_theme.theme b/core/modules/system/tests/themes/test_theme/test_theme.theme
index aa399b6..bf980a1 100644
--- a/core/modules/system/tests/themes/test_theme/test_theme.theme
+++ b/core/modules/system/tests/themes/test_theme/test_theme.theme
@@ -154,3 +154,61 @@ function test_theme_preprocess_theme_test_preprocess_suggestions__kitten__flamin
 function test_theme_preprocess_theme_test_preprocess_suggestions__kitten__meerkat__tarsier__moose(&$variables) {
   $variables['bar'] = 'Moose';
 }
+
+/**
+ * Implements hook_form_system_theme_settings_alter().
+ */
+function test_theme_form_system_theme_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  // Alter default field
+  $form['toggle_favicon']['#default_value'] = FALSE;
+
+  // Add custom fields
+  $form['extra_settings'] = array(
+    '#type' => 'vertical_tabs',
+  );
+  $form['extra'] = array(
+    '#type' => 'details',
+    '#title' => t('Extra'),
+    '#group' => 'extra_settings',
+  );
+  $form['extra']['custom_flag'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Custom flag.'),
+    '#default_value' => theme_get_setting('custom_flag'),
+  );
+  $form['extra']['custom_text'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Custom textfield.'),
+    '#default_value' => theme_get_setting('custom_text'),
+  );
+  $default_file_dir = 'public://template/logos';
+  $logo_folder = file_prepare_directory($default_file_dir, FILE_CREATE_DIRECTORY);
+  $form['extra']['custom_logo'] = array(
+    '#type' => 'managed_file',
+    '#title' => t('Secondary logo.'),
+    '#default_value' => theme_get_setting('custom_logo'),
+    '#progress_indicator' => 'bar',
+    '#progress_message'   => t('Please wait...'),
+    '#upload_location' => $logo_folder,
+    '#upload_validators'  => array(
+      'file_validate_extensions' => array('gif png jpg jpeg'),
+    ),
+  );
+  // Add a new submission handler.
+  $form['#submit'][] = 'test_theme_form_system_theme_settings_submit';
+}
+
+/**
+ * Test theme form settings submission handler.
+ */
+function test_theme_form_system_theme_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  if ($form_state->getValue('custom_logo')) {
+    $element = $form_state->getValue('custom_logo');
+    if (!empty($element[0])){
+      // Make submited files permanent.
+      $file = \Drupal\file\Entity\File::load($element[0]);
+      $file->setPermanent();
+      $file->save();
+    }
+  }
+}
diff --git a/core/modules/system/tests/themes/test_theme_alter/config/schema/test_theme_alter.schema.yml b/core/modules/system/tests/themes/test_theme_alter/config/schema/test_theme_alter.schema.yml
new file mode 100644
index 0000000..e68e3c3
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_alter/config/schema/test_theme_alter.schema.yml
@@ -0,0 +1,22 @@
+# Schema for the configuration files of the Test theme alter.
+
+test_theme_alter.settings:
+  type: theme_settings
+  label: 'Test theme alter settings'
+  mapping:
+    custom_flag:
+      type: boolean
+      label: 'Custom flag'
+    custom_text:
+      type: string
+      label: 'Custom text'
+    custom_logo:
+      type: mapping
+      label: 'Logo settings'
+      mapping:
+        path:
+          type: string
+          label: 'Logo path'
+        url:
+          type: uri
+          label: 'URL'
diff --git a/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.info.yml b/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.info.yml
new file mode 100644
index 0000000..d718e05
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.info.yml
@@ -0,0 +1,6 @@
+name: 'Theme test alter'
+type: theme
+description: 'Test theme alter that extends theme settings options'
+version: VERSION
+core: 8.x
+base theme: test_basetheme
diff --git a/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.theme b/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.theme
new file mode 100644
index 0000000..04628c8
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_alter/test_theme_alter.theme
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Add hooks for tests to use.
+ */
+
+/**
+ * Implements hook_preprocess_HOOK() for theme_test_template_test templates.
+ */
+function test_subsubtheme_preprocess_theme_test_template_test(&$variables) {
+}
diff --git a/core/modules/system/tests/themes/test_theme_alter/theme-settings.php b/core/modules/system/tests/themes/test_theme_alter/theme-settings.php
new file mode 100644
index 0000000..117ec4c
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_alter/theme-settings.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * Implements hook_form_system_theme_settings_alter().
+ */
+function test_theme_alter_form_system_theme_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  // Alter default field
+  $form['toggle_favicon']['#default_value'] = FALSE;
+
+  // Add custom fields
+  $form['extra_settings'] = array(
+    '#type' => 'vertical_tabs',
+  );
+  $form['extra'] = array(
+    '#type' => 'details',
+    '#title' => t('Extra'),
+    '#group' => 'extra_settings',
+  );
+  $form['extra']['custom_flag'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Custom flag.'),
+    '#default_value' => theme_get_setting('custom_flag'),
+  );
+  $form['extra']['custom_text'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Custom textfield.'),
+    '#default_value' => theme_get_setting('custom_text'),
+  );
+  $default_file_dir = 'public://template/logos';
+  $logo_folder = file_prepare_directory($default_file_dir, FILE_CREATE_DIRECTORY);
+  $form['extra']['custom_logo'] = array(
+    '#type' => 'managed_file',
+    '#title' => t('Secondary logo.'),
+    '#default_value' => theme_get_setting('custom_logo'),
+    '#progress_indicator' => 'bar',
+    '#progress_message'   => t('Please wait...'),
+    '#upload_location' => $logo_folder,
+    '#upload_validators'  => array(
+      'file_validate_extensions' => array('gif png jpg jpeg'),
+    ),
+  );
+  // Add a new submission handler.
+  $form['#submit'][] = 'test_theme_alter_form_system_theme_settings_submit';
+}
+
+/**
+ * Test theme form settings submission handler.
+ */
+function test_theme_alter_form_system_theme_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  if ($form_state->getValue('custom_logo')) {
+    $element = $form_state->getValue('custom_logo');
+    if (!empty($element[0])){
+      // Make submited files permanent.
+      $file = \Drupal\file\Entity\File::load($element[0]);
+      $file->setPermanent();
+      $file->save();
+    }
+  }
+}
