diff --git a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php
index f09dd77..f9c8470 100644
--- a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php
+++ b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php
@@ -54,8 +54,9 @@ public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $co
     }
     $definition = $typed_config->getDefinition($config_name);
     $this->schema = $typed_config->create($definition, $config_data);
+    $errors = array();
     foreach ($config_data as $key => $value) {
-      $errors = $this->checkValue($key, $value);
+      $errors = array_merge($errors, $this->checkValue($key, $value));
     }
     if (empty($errors)) {
       return TRUE;
diff --git a/core/lib/Drupal/Core/Field/FormatterBase.php b/core/lib/Drupal/Core/Field/FormatterBase.php
index eeb94a3..bc3cdb6 100644
--- a/core/lib/Drupal/Core/Field/FormatterBase.php
+++ b/core/lib/Drupal/Core/Field/FormatterBase.php
@@ -55,14 +55,17 @@
    *   The formatter label display setting.
    * @param string $view_mode
    *   The view mode.
+   * @param array $third_party_settings
+   *   Any third party settings settings.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode) {
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
 
     $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
     $this->label = $label;
     $this->viewMode = $view_mode;
+    $this->thirdPartySettings = $third_party_settings;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Field/FormatterPluginManager.php b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
index 0d9e516..40be383 100644
--- a/core/lib/Drupal/Core/Field/FormatterPluginManager.php
+++ b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
@@ -68,7 +68,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
       return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition);
     }
 
-    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode']);
+    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode'], $configuration['third_party_settings']);
   }
 
   /**
@@ -123,6 +123,7 @@ public function getInstance(array $options) {
     $configuration += array(
       'field_definition' => $field_definition,
       'view_mode' => $options['view_mode'],
+      'third_party_settings' => array(),
     );
     return $this->createInstance($plugin_id, $configuration);
   }
@@ -143,6 +144,7 @@ public function prepareConfiguration($field_type, array $configuration) {
     $configuration += array(
       'label' => 'above',
       'settings' => array(),
+      'third_party_settings' => array(),
     );
     // If no formatter is specified, use the default formatter.
     if (!isset($configuration['type'])) {
diff --git a/core/lib/Drupal/Core/Field/PluginSettingsBase.php b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
index fb8e07b..8ed2cdd 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsBase.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
@@ -24,6 +24,15 @@
   protected $settings = array();
 
   /**
+   * The plugin settings injected by third party modules.
+   *
+   * @see hooks
+   *
+   * @var array
+   */
+  protected $thirdPartySettings = array();
+
+  /**
    * Whether default settings have been merged into the current $settings.
    *
    * @var bool
@@ -84,4 +93,22 @@ public function setSetting($key, $value) {
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getThirdPartySetting($module, $key) {
+    if (isset($this->thirdPartySettings[$module][$key])) {
+      return $this->thirdPartySettings[$module][$key];
+    }
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setThirdPartySetting($module, $key, $value) {
+    $this->thirdPartySettings[$module][$key] = $value;
+    return $this;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
index 9f9b7c6..c24a108 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
@@ -64,4 +64,31 @@ public function setSettings(array $settings);
    */
   public function setSetting($key, $value);
 
+  /**
+   * Returns the value of a third-party setting, or its default value if absent.
+   *
+   * @param string $module
+   *   The module providing the third-party setting.
+   * @param string $key
+   *   The setting name.
+   *
+   * @return mixed|NULL
+   *   The setting value. Returns NULL if the setting does not exist.
+   */
+  public function getThirdPartySetting($module, $key);
+
+  /**
+   * Sets the value of a third-party setting for the plugin.
+   *
+   * @param string $module
+   *   The module providing the third-party setting.
+   * @param string $key
+   *   The setting name.
+   * @param mixed $value
+   *   The setting value.
+   *
+   * @return $this
+   */
+  public function setThirdPartySetting($module, $key, $value);
+
 }
diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index ef04793..fa61dd2 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -43,11 +43,14 @@
    *   The definition of the field to which the widget is associated.
    * @param array $settings
    *   The widget settings.
+   * @param array $third_party_settings
+   *   Any third party settings settings.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
     $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
+    $this->thirdPartySettings = $third_party_settings;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Field/WidgetPluginManager.php b/core/lib/Drupal/Core/Field/WidgetPluginManager.php
index 55c1fc5..ae98361 100644
--- a/core/lib/Drupal/Core/Field/WidgetPluginManager.php
+++ b/core/lib/Drupal/Core/Field/WidgetPluginManager.php
@@ -108,6 +108,7 @@ public function getInstance(array $options) {
 
     $configuration += array(
       'field_definition' => $field_definition,
+      'third_party_settings' => array(),
     );
     return $this->createInstance($plugin_id, $configuration);
   }
@@ -124,7 +125,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
       return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition);
     }
 
-    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings']);
+    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings']);
   }
 
 
@@ -143,6 +144,7 @@ public function prepareConfiguration($field_type, array $configuration) {
     // Fill in defaults for missing properties.
     $configuration += array(
       'settings' => array(),
+      'third_party_settings' => array(),
     );
     // If no widget is specified, use the default widget.
     if (!isset($configuration['type'])) {
diff --git a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
index bb17d42..77681c9 100644
--- a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
+++ b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
@@ -75,6 +75,7 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration['settings'],
       $configuration['label'],
       $configuration['view_mode'],
+      $configuration['third_party_settings'],
       $container->get('current_user'),
       $container->get('entity.manager')->getStorage('comment'),
       $container->get('entity.manager')->getViewBuilder('comment')
@@ -96,6 +97,8 @@ public static function create(ContainerInterface $container, array $configuratio
    *   The formatter label display setting.
    * @param string $view_mode
    *   The view mode.
+   * @param array $third_party_settings
+   *   Third party settings.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
    * @param \Drupal\comment\CommentStorageInterface $comment_storage
@@ -103,8 +106,8 @@ public static function create(ContainerInterface $container, array $configuratio
    * @param \Drupal\Core\Entity\EntityViewBuilderInterface $comment_view_builder
    *   The comment view builder.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, AccountInterface $current_user, CommentStorageInterface $comment_storage, EntityViewBuilderInterface $comment_view_builder) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode);
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, CommentStorageInterface $comment_storage, EntityViewBuilderInterface $comment_view_builder) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
     $this->viewBuilder = $comment_view_builder;
     $this->storage = $comment_storage;
     $this->currentUser = $current_user;
diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
index 0285f02..239f454 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
@@ -67,13 +67,15 @@ public static function defaultSettings() {
    *   The formatter label display setting.
    * @param string $view_mode
    *   The view mode.
+   * @param array $third_party_settings
+   *   Third party settings.
    * @param \Drupal\Core\Datetime\Date $date_service
    *   The date service.
    * @param \Drupal\Core\Entity\EntityStorageInterface $date_storage
    *   The date storage.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, Date $date_service, EntityStorageInterface $date_storage) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode);
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, Date $date_service, EntityStorageInterface $date_storage) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
 
     $this->dateService = $date_service;
     $this->dateStorage = $date_storage;
@@ -90,6 +92,7 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration['settings'],
       $configuration['label'],
       $configuration['view_mode'],
+      $configuration['third_party_settings'],
       $container->get('date'),
       $container->get('entity.manager')->getStorage('date_format')
     );
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
index 161bada..9b2f3bd 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
@@ -34,8 +34,8 @@ class DateTimeDefaultWidget extends WidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
 
     // @todo Inject this once https://drupal.org/node/2035317 is in.
     $this->dateStorage = \Drupal::entityManager()->getStorage('date_format');
diff --git a/core/modules/entity/config/schema/entity.data_types.yml b/core/modules/entity/config/schema/entity.data_types.yml
index dcfd62c..cf8cf13 100644
--- a/core/modules/entity/config/schema/entity.data_types.yml
+++ b/core/modules/entity/config/schema/entity.data_types.yml
@@ -13,6 +13,11 @@ entity_field_view_display_base:
     weight:
       type: integer
       label: 'Weight'
+    third_party_settings:
+      type: sequence
+      label: 'Third party settings'
+      sequence:
+        - type: entity_view_display.third_party.[%key]
 
 # Schema for the base of the form mode display format settings.
 entity_field_form_display_base:
@@ -24,3 +29,8 @@ entity_field_form_display_base:
     weight:
       type: integer
       label: 'Weight'
+    third_party_settings:
+      type: sequence
+      label: 'Third party settings'
+      sequence:
+        - type: entity_form_display.third_party.[%key]
diff --git a/core/modules/entity/config/schema/entity.schema.yml b/core/modules/entity/config/schema/entity.schema.yml
index 074d82a..a924bad 100644
--- a/core/modules/entity/config/schema/entity.schema.yml
+++ b/core/modules/entity/config/schema/entity.schema.yml
@@ -115,27 +115,13 @@ entity.form_display.*.*.*:
 
 # Default schema for entity display field with undefined type.
 entity_view_display.field.*:
-  type: mapping
+  type: entity_field_view_display_base
   label: 'Entity display default'
-  mapping:
-    visible:
-      type: boolean
-      label: 'Visibility'
-    weight:
-      type: integer
-      label: 'Weight'
 
 # Default schema for entity form display field with undefined type.
 entity_form_display.field.*:
-  type: mapping
+  type: entity_field_form_display_base
   label: 'Entity form display default'
-  mapping:
-    visible:
-      type: boolean
-      label: 'Visibility'
-    weight:
-      type: integer
-      label: 'Weight'
 
 entity_form_display.field.string:
   type: entity_field_form_display_base
diff --git a/core/modules/entity/src/EntityDisplayBase.php b/core/modules/entity/src/EntityDisplayBase.php
index a9b99d2..7b3033c 100644
--- a/core/modules/entity/src/EntityDisplayBase.php
+++ b/core/modules/entity/src/EntityDisplayBase.php
@@ -177,6 +177,12 @@ public function calculateDependencies() {
       if (isset($component['type']) && $definition = $this->pluginManager->getDefinition($component['type'], FALSE)) {
         $this->addDependency('module', $definition['provider']);
       }
+      // Create dependencies on any modules providing third party settings.
+      if (isset($component['third_party_settings'])) {
+        foreach($component['third_party_settings'] as $module => $settings) {
+          $this->addDependency('module', $module);
+        }
+      }
     }
     // Depend on configured modes.
     if ($this->mode != 'default') {
@@ -297,6 +303,11 @@ public function setComponent($name, array $options = array()) {
       $options = $this->pluginManager->prepareConfiguration($field_definition->getType(), $options);
     }
 
+    // Remove unnecessary empty third_party_settings.
+    if (empty($options['third_party_settings'])) {
+      unset($options['third_party_settings']);
+    }
+
     $this->content[$name] = $options;
     unset($this->hidden[$name]);
     unset($this->plugins[$name]);
diff --git a/core/modules/entity/src/Tests/EntityDisplayTest.php b/core/modules/entity/src/Tests/EntityDisplayTest.php
index 26e47d6..1254d8d 100644
--- a/core/modules/entity/src/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/src/Tests/EntityDisplayTest.php
@@ -69,6 +69,7 @@ public function testEntityDisplayCRUD() {
       'type' => 'string',
       'weight' => -5,
       'settings' => array(),
+      'third_party_settings' => array(),
     );
     $this->assertEqual($display->getComponents(), $expected);
 
@@ -221,12 +222,14 @@ public function testBaseFieldComponent() {
         'label' => 'above',
         'type' => 'text_default',
         'settings' => $formatter_settings,
+        'third_party_settings' => array(),
         'weight' => 10,
       ),
       'test_display_non_configurable' => array(
         'label' => 'above',
         'type' => 'text_default',
         'settings' => $formatter_settings,
+        'third_party_settings' => array(),
         'weight' => 11,
       ),
     );
diff --git a/core/modules/entity/src/Tests/EntityFormDisplayTest.php b/core/modules/entity/src/Tests/EntityFormDisplayTest.php
index aa47ca6..585a353 100644
--- a/core/modules/entity/src/Tests/EntityFormDisplayTest.php
+++ b/core/modules/entity/src/Tests/EntityFormDisplayTest.php
@@ -136,11 +136,13 @@ public function testBaseFieldComponent() {
       'test_display_configurable' => array(
         'type' => 'text_textfield',
         'settings' => $formatter_settings,
+        'third_party_settings' => array(),
         'weight' => 10,
       ),
       'test_display_non_configurable' => array(
         'type' => 'text_textfield',
         'settings' => $formatter_settings,
+        'third_party_settings' => array(),
         'weight' => 11,
       ),
     );
diff --git a/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml
new file mode 100644
index 0000000..f9ef7b7
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml
@@ -0,0 +1,23 @@
+entity_view_display.field.field_test_multiple:
+  type: entity_field_view_display_base
+  label: 'field_test display format settings'
+  mapping:
+    settings:
+      type: mapping
+      label: 'Settings'
+      mapping:
+        test_formatter_setting_multiple:
+          type: string
+          label: 'Test setting'
+
+entity_form_display.field.test_field_widget_multiple:
+  type: entity_field_form_display_base
+  label: 'field_test display format settings'
+  mapping:
+    settings:
+      type: mapping
+      label: 'Settings'
+      mapping:
+        test_widget_setting_multiple:
+          type: string
+          label: 'Test setting'
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 45a0c0d..6c9b7d4 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -156,44 +156,6 @@ function field_test_query_efq_metadata_test_alter(&$query) {
 }
 
 /**
- * Implements hook_field_widget_settings_form_alter().
- */
-function field_test_field_widget_settings_form_alter(&$element, &$form_state, $context) {
-  $element['field_test_widget_settings_form_alter'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Widget settings form alter'),
-    '#default_value' => $context['widget']->getSetting('field_test_widget_settings_form_alter'),
-  );
-}
-
-/**
- * Implements hook_field_widget_settings_summary_alter().
- */
-function field_test_field_widget_settings_summary_alter(&$summary, $context) {
-  $summary[] = 'field_test_field_widget_settings_summary_alter';
-  return $summary;
-}
-
-/**
- * Implements hook_field_formatter_settings_form_alter().
- */
-function field_test_field_formatter_settings_form_alter(&$element, &$form_state, $context) {
-  $element['field_test_formatter_settings_form_alter'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Formatter settings form alter'),
-    '#default_value' => $context['formatter']->getSetting('field_test_formatter_settings_form_alter'),
-  );
-}
-
-/**
- * Implements hook_field_formatter_settings_summary_alter().
- */
-function field_test_field_formatter_settings_summary_alter(&$summary, $context) {
-  $summary[] = 'field_test_field_formatter_settings_summary_alter';
-  return $summary;
-}
-
-/**
  * Implements hook_entity_extra_field_info_alter().
  */
 function field_test_entity_extra_field_info_alter(&$info) {
diff --git a/core/modules/field/tests/modules/field_third_party_test/config/schema/field_third_party_test.schema.yml b/core/modules/field/tests/modules/field_third_party_test/config/schema/field_third_party_test.schema.yml
new file mode 100644
index 0000000..c177f44
--- /dev/null
+++ b/core/modules/field/tests/modules/field_third_party_test/config/schema/field_third_party_test.schema.yml
@@ -0,0 +1,15 @@
+entity_view_display.third_party.field_third_party_test:
+  type: mapping
+  label: 'field_third_party_test entity display settings'
+  mapping:
+    field_test_field_formatter_third_party_settings_form:
+      type: string
+      label: field_test_field_formatter_third_party_settings_form
+
+entity_form_display.third_party.field_third_party_test:
+  type: mapping
+  label: 'field_third_party_test entity form display settings'
+  mapping:
+    field_test_widget_third_party_settings_form:
+      type: string
+      label: field_test_widget_third_party_settings_form
diff --git a/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.info.yml b/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.info.yml
new file mode 100644
index 0000000..6fd7f39
--- /dev/null
+++ b/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.info.yml
@@ -0,0 +1,9 @@
+name: 'Field Third Party Settings Test'
+type: module
+description: 'Support module for the Field API tests.'
+core: 8.x
+package: Testing
+version: VERSION
+dependencies:
+  - entity_test
+  - field_test
diff --git a/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.module b/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.module
new file mode 100644
index 0000000..c809842
--- /dev/null
+++ b/core/modules/field/tests/modules/field_third_party_test/field_third_party_test.module
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * Implements hook_field_widget_third_party_settings_form().
+ */
+function field_third_party_test_field_widget_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, $form, $form_state) {
+  $element['field_test_widget_third_party_settings_form'] = array(
+    '#type' => 'textfield',
+    '#title' => t('3rd party widget settings form'),
+    '#default_value' => $plugin->getThirdPartySetting('field_third_party_test', 'field_test_widget_third_party_settings_form'),
+  );
+  return $element;
+}
+
+/**
+ * Implements hook_field_widget_settings_summary_alter().
+ */
+function field_third_party_test_field_widget_settings_summary_alter(&$summary, $context) {
+  $summary[] = 'field_test_field_widget_settings_summary_alter';
+  return $summary;
+}
+
+/**
+ * Implements hook_field_formatter_third_party_settings_form().
+ */
+function field_third_party_test_field_formatter_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $view_mode, $form, $form_state) {
+  $element['field_test_field_formatter_third_party_settings_form'] = array(
+    '#type' => 'textfield',
+    '#title' => t('3rd party formatter settings form'),
+    '#default_value' => $plugin->getThirdPartySetting('field_third_party_test', 'field_test_field_formatter_third_party_settings_form'),
+  );
+  return $element;
+}
+
+/**
+ * Implements hook_field_formatter_settings_summary_alter().
+ */
+function field_third_party_test_field_formatter_settings_summary_alter(&$summary, $context) {
+  $summary[] = 'field_test_field_formatter_settings_summary_alter';
+  return $summary;
+}
+
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index 255ce85..6e6687a 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -11,65 +11,76 @@
  */
 
 /**
- * Alters the formatter settings form.
+ * Allow modules to add settings to field formatters provided by other modules.
  *
- * @param $element
- *   Form array.
- * @param $form_state
- *   The form state of the (entire) configuration form.
- * @param $context
- *   An associative array with the following elements:
- *   - formatter: The formatter object.
- *   - field_definition: The field definition.
- *   - view_mode: The view mode being configured.
- *   - form: The (entire) configuration form array.
+ * @param object $plugin
+ *   The field formatter.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ *   The field definition.
+ * @param $view_mode
+ *   The entity view mode.
+ * @param array $form
+ *   The The (entire) configuration form array.
+ * @param array $form_state
+ *   The form state.
+ *
+ * @return array
+ *   Returns the form array to be built.
  *
  * @see \Drupal\field_ui\DisplayOverView.
  */
-function hook_field_formatter_settings_form_alter(&$element, &$form_state, $context) {
-  // Add a 'mysetting' checkbox to the settings form for 'foo_formatter'
-  // field formatters.
-  if ($context['formatter']->getPluginId() == 'foo_formatter') {
-    $element['mysetting'] = array(
+function hook_field_formatter_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $view_mode, $form, $form_state) {
+  $element = array();
+  // Add a 'my_setting' checkbox to the settings form for 'foo_formatter' field
+  // formatters.
+  if ($plugin->getPluginId() == 'foo_formatter') {
+    $element['my_setting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $plugin->getThirdPartySetting('my_module', 'my_setting'),
     );
   }
+  return $element;
 }
 
 /**
- * Alters the widget settings form.
+ * Allow modules to add settings to field widgets provided by other modules.
  *
- * @param array $element
- *   Form array.
+ * @param object $plugin
+ *   The field widget.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ *   The field definition.
+ * @param $form_mode
+ *   The entity form mode.
+ * @param array $form
+ *   The The (entire) configuration form array.
  * @param array $form_state
- *   The form state of the (entire) configuration form.
- * @param array $context
- *   An associative array with the following elements:
- *   - formatter: The formatter object.
- *   - field_definition: The field definition.
- *   - form_mode: The form mode being configured.
- *   - form: The (entire) configuration form array.
+ *   The form state.
+ *
+ * @return array
+ *   Returns the form array to be built.
  *
  * @see \Drupal\field_ui\FormDisplayOverView.
  */
-function hook_field_widget_settings_form_alter(&$element, &$form_state, $context) {
-  // Add a 'mysetting' checkbox to the settings form for 'foo_field' fields.
-  if ($context['field']['type'] == 'foo_field') {
-    $element['mysetting'] = array(
+function hook_field_widget_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, $form, $form_state) {
+  $element = array();
+  // Add a 'my_setting' checkbox to the settings form for 'foo_widget' field
+  // widgets.
+  if ($plugin->getPluginId() == 'foo_widget') {
+    $element['my_setting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $plugin->getThirdPartySetting('my_module', 'my_setting'),
     );
   }
+  return $element;
 }
 
 /**
  * Alters the field formatter settings summary.
  *
- * @param $summary
- *   The summary.
+ * @param array $summary
+ *   An array of summary messages.
  * @param $context
  *   An associative array with the following elements:
  *   - formatter: The formatter object.
@@ -82,7 +93,7 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
   // Append a message to the summary when an instance of foo_formatter has
   // mysetting set to TRUE for the current view mode.
   if ($context['formatter']->getPluginId() == 'foo_formatter') {
-    if ($context['formatter']->getSetting('mysetting')) {
+    if ($context['formatter']->getThirdPartySetting('my_module', 'my_setting')) {
       $summary[] = t('My setting enabled.');
     }
   }
@@ -92,7 +103,7 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
  * Alters the field widget settings summary.
  *
  * @param array $summary
- *   The summary.
+ *   An array of summary messages.
  * @param array $context
  *   An associative array with the following elements:
  *   - widget: The widget object.
@@ -102,10 +113,10 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
  * @see \Drupal\field_ui\FormDisplayOverView.
  */
 function hook_field_widget_settings_summary_alter(&$summary, $context) {
-  // Append a message to the summary when an instance of foo_field has
+  // Append a message to the summary when an instance of foo_widget has
   // mysetting set to TRUE for the current view mode.
-  if ($context['field']['type'] == 'foo_field') {
-    if ($context['widget']->getSetting('mysetting')) {
+  if ($context['widget']->getPluginId() == 'foo_widget') {
+    if ($context['widget']->getThirdPartySetting('my_module', 'my_setting')) {
       $summary[] = t('My setting enabled.');
     }
   }
diff --git a/core/modules/field_ui/src/DisplayOverview.php b/core/modules/field_ui/src/DisplayOverview.php
index 956d15f..43c73df 100644
--- a/core/modules/field_ui/src/DisplayOverview.php
+++ b/core/modules/field_ui/src/DisplayOverview.php
@@ -231,13 +231,18 @@ protected function getFieldLabelOptions() {
    * {@inheritdoc}
    */
   protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) {
-    $context = array(
-      'formatter' => $plugin,
-      'field_definition' => $field_definition,
-      'view_mode' => $this->mode,
-      'form' => $form,
-    );
-    $this->moduleHandler->alter('field_formatter_settings_form', $settings_form, $form_state, $context);
+    // Iterate through the modules calling their
+    // field_formatter_third_party_settings_form handlers (if any):
+    foreach ($this->moduleHandler->getImplementations('field_formatter_third_party_settings_form') as $module) {
+      // Index the settings form by module name.
+      $settings_form[$module] = $this->moduleHandler->invoke($module, 'field_formatter_third_party_settings_form', array(
+        $plugin,
+        $field_definition,
+        $this->mode,
+        $form,
+        $form_state,
+      ));
+    }
   }
 
   /**
diff --git a/core/modules/field_ui/src/DisplayOverviewBase.php b/core/modules/field_ui/src/DisplayOverviewBase.php
index 5fc7240..2787dc7 100644
--- a/core/modules/field_ui/src/DisplayOverviewBase.php
+++ b/core/modules/field_ui/src/DisplayOverviewBase.php
@@ -323,8 +323,11 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
     if (isset($form_state['values']['fields'][$field_name]['type'])) {
       $display_options['type'] = $form_state['values']['fields'][$field_name]['type'];
     }
-    if (isset($form_state['plugin_settings'][$field_name])) {
-      $display_options['settings'] = $form_state['plugin_settings'][$field_name];
+    if (isset($form_state['plugin_settings'][$field_name]['settings'])) {
+      $display_options['settings'] = $form_state['plugin_settings'][$field_name]['settings'];
+    }
+    if (isset($form_state['plugin_settings'][$field_name]['third_party_settings'])) {
+      $display_options['third_party_settings'] = $form_state['plugin_settings'][$field_name]['third_party_settings'];
     }
 
     // Get the corresponding plugin object.
@@ -349,9 +352,10 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
       if ($plugin) {
         // Generate the settings form and allow other modules to alter it.
         $settings_form = $plugin->settingsForm($form, $form_state);
-        $this->alterSettingsForm($settings_form, $plugin, $field_definition, $form, $form_state);
+        $third_party_settings_form = array();
+        $this->alterSettingsForm($third_party_settings_form, $plugin, $field_definition, $form, $form_state);
 
-        if ($settings_form) {
+        if ($settings_form || $third_party_settings_form) {
           $field_row['plugin']['#cell_attributes'] = array('colspan' => 3);
           $field_row['plugin']['settings_edit_form'] = array(
             '#type' => 'container',
@@ -361,6 +365,7 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
               '#markup' => $this->t('Plugin settings'),
             ),
             'settings' => $settings_form,
+            'third_party_settings' => $third_party_settings_form,
             'actions' => array(
               '#type' => 'actions',
               'save_settings' => $base_button + array(
@@ -405,7 +410,10 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
         }
 
         // Check selected plugin settings to display edit link or not.
-        if ($this->pluginManager->getDefaultSettings($display_options['type'])) {
+        $settings_form = $plugin->settingsForm($form, $form_state);
+        $third_party_settings_form = array();
+        $this->alterSettingsForm($third_party_settings_form, $plugin, $field_definition, $form, $form_state);
+        if (!empty($settings_form) || !empty($third_party_settings_form)) {
           $field_row['settings_edit'] = $base_button + array(
             '#type' => 'image_button',
             '#name' => $field_name . '_settings_edit',
@@ -516,12 +524,22 @@ public function submitForm(array &$form, array &$form_state) {
         if (isset($values['settings_edit_form']['settings'])) {
           $settings = $values['settings_edit_form']['settings'];
         }
-        elseif (isset($form_state['plugin_settings'][$field_name])) {
-          $settings = $form_state['plugin_settings'][$field_name];
+        elseif (isset($form_state['plugin_settings'][$field_name]['settings'])) {
+          $settings = $form_state['plugin_settings'][$field_name]['settings'];
         }
         elseif ($current_options = $display->getComponent($field_name)) {
           $settings = $current_options['settings'];
         }
+        $third_party_settings = array();
+        if (isset($values['settings_edit_form']['third_party_settings'])) {
+          $third_party_settings = $values['settings_edit_form']['third_party_settings'];
+        }
+        elseif (isset($form_state['plugin_settings'][$field_name]['third_party_settings'])) {
+          $third_party_settings = $form_state['plugin_settings'][$field_name]['third_party_settings'];
+        }
+        elseif (($current_options = $display->getComponent($field_name)) && isset($current_options['third_party_settings'])) {
+          $third_party_settings = $current_options['third_party_settings'];
+        }
 
         // Only save settings actually used by the selected plugin.
         $default_settings = $this->pluginManager->getDefaultSettings($values['type']);
@@ -531,7 +549,8 @@ public function submitForm(array &$form, array &$form_state) {
         $component_values = array(
           'type' => $values['type'],
           'weight' => $values['weight'],
-          'settings' => $settings
+          'settings' => $settings,
+          'third_party_settings' => $third_party_settings,
         );
 
         // Only formatters have configurable label visibility.
@@ -604,8 +623,8 @@ public function multistepSubmit($form, &$form_state) {
       case 'update':
         // Store the saved settings, and set the field back to 'non edit' mode.
         $field_name = $trigger['#field_name'];
-        $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
-        $form_state['plugin_settings'][$field_name] = $values;
+        $form_state['plugin_settings'][$field_name]['settings'] = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
+        $form_state['plugin_settings'][$field_name]['third_party_settings'] = $form_state['values']['fields'][$field_name]['settings_edit_form']['third_party_settings'];
         unset($form_state['plugin_settings_edit']);
         break;
 
diff --git a/core/modules/field_ui/src/FormDisplayOverview.php b/core/modules/field_ui/src/FormDisplayOverview.php
index 7c0a5ff..bdea751 100644
--- a/core/modules/field_ui/src/FormDisplayOverview.php
+++ b/core/modules/field_ui/src/FormDisplayOverview.php
@@ -183,13 +183,18 @@ protected function getOverviewRoute($mode) {
    * {@inheritdoc}
    */
   protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) {
-    $context = array(
-      'widget' => $plugin,
-      'field_definition' => $field_definition,
-      'form_mode' => $this->mode,
-      'form' => $form,
-    );
-    $this->moduleHandler->alter('field_widget_settings_form', $settings_form, $form_state, $context);
+    // Iterate through the modules calling their
+    // field_widget_third_party_settings_form handlers (if any):
+    foreach ($this->moduleHandler->getImplementations('field_widget_third_party_settings_form') as $module) {
+      // Index the settings form by module name.
+      $settings_form[$module] = $this->moduleHandler->invoke($module, 'field_widget_third_party_settings_form', array(
+        $plugin,
+        $field_definition,
+        $this->mode,
+        $form,
+        $form_state,
+      ));
+    }
   }
 
   /**
diff --git a/core/modules/field_ui/src/Tests/ManageDisplayTest.php b/core/modules/field_ui/src/Tests/ManageDisplayTest.php
index c98d52d..f138b0e 100644
--- a/core/modules/field_ui/src/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/src/Tests/ManageDisplayTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field_ui\Tests;
 
+use Drupal\config\Tests\SchemaCheckTestTrait;
 use Drupal\Core\Entity\EntityInterface;
 
 /**
@@ -14,12 +15,14 @@
  */
 class ManageDisplayTest extends FieldUiTestBase {
 
+  use SchemaCheckTestTrait;
+
   /**
    * Modules to enable.
    *
    * @var array
    */
-  public static $modules = array('search', 'field_test');
+  public static $modules = array('search', 'field_test', 'field_third_party_test');
 
   public static function getInfo() {
     return array(
@@ -100,13 +103,22 @@ function testFormatterUI() {
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
 
     // Assert that the field added in
-    // field_test_field_formatter_settings_form_alter() is present.
-    $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_formatter_settings_form_alter]';
-    $this->assertField($fieldname, 'The field added in hook_field_formatter_settings_form_alter() is present on the settings form.');
+    // field_test_field_formatter_third_party_settings_form() is present.
+    $fieldname = 'fields[field_test][settings_edit_form][third_party_settings][field_third_party_test][field_test_field_formatter_third_party_settings_form]';
+    $this->assertField($fieldname, 'The field added in hook_field_formatter_third_party_settings_form() is present on the settings form.');
     $edit = array($fieldname => 'foo');
     $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
 
-    // Confirm that the extra settings are not updated on the settings form.
+    // Save the form to save the third party settings.
+    $this->drupalPostForm(NULL, array(), t('Save'));
+
+    \Drupal::entityManager()->clearCachedFieldDefinitions();
+    $display = entity_load('entity_view_display', 'node.' . $this->type . '.default', TRUE);
+    $this->assertEqual($display->getRenderer('field_test')->getThirdPartySetting('field_third_party_test', 'field_test_field_formatter_third_party_settings_form'), 'foo');
+    $this->assertTrue(in_array('field_third_party_test', $display->calculateDependencies()['module']), 'The display has a dependency on field_third_party_test module.');
+    $this->assertConfigSchema(\Drupal::service('config.typed'), $display->getEntityType()->getConfigPrefix() . '.' . $display->id(), $display->toArray());
+
+    // Confirm that the third party settings are not updated on the settings form.
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
     $this->assertFieldByName($fieldname, '');
 
@@ -121,9 +133,15 @@ function testFormatterUI() {
     $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
     $this->assertText('Default empty setting now has a value.');
 
-    // Test the no settings form behavior.
+    // Test the settings form behavior. An edit button should be present since
+    // there are thrid party settings to configure.
     $edit = array('fields[field_test][type]' => 'field_no_settings', 'refresh_rows' => 'field_test');
     $this->drupalPostAjaxForm(NULL, $edit, array('op' => t('Refresh')));
+    $this->assertFieldByName('field_test_settings_edit');
+    // Uninstall the module providing third party settings and ensure the button
+    // is no longer there.
+    \Drupal::moduleHandler()->uninstall(array('field_third_party_test'));
+    $this->drupalGet($manage_display);
     $this->assertNoFieldByName('field_test_settings_edit');
   }
 
@@ -193,13 +211,21 @@ public function testWidgetUI() {
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
 
     // Assert that the field added in
-    // field_test_field_widget_settings_form_alter() is present.
-    $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_widget_settings_form_alter]';
-    $this->assertField($fieldname, 'The field added in hook_field_widget_settings_form_alter() is present on the settings form.');
+    // field_test_field_widget_third_party_settings_form() is present.
+    $fieldname = 'fields[field_test][settings_edit_form][third_party_settings][field_third_party_test][field_test_widget_third_party_settings_form]';
+    $this->assertField($fieldname, 'The field added in hook_field_widget_third_party_settings_form() is present on the settings form.');
     $edit = array($fieldname => 'foo');
     $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
 
-    // Confirm that the extra settings are not updated on the settings form.
+    // Save the form to save the third party settings.
+    $this->drupalPostForm(NULL, array(), t('Save'));
+    \Drupal::entityManager()->clearCachedFieldDefinitions();
+    $display = entity_load('entity_form_display', 'node.' . $this->type . '.default', TRUE);
+    $this->assertEqual($display->getRenderer('field_test')->getThirdPartySetting('field_third_party_test', 'field_test_widget_third_party_settings_form'), 'foo');
+    $this->assertTrue(in_array('field_third_party_test', $display->calculateDependencies()['module']), 'Form display does not have a dependency on field_third_party_test module.');
+    $this->assertConfigSchema(\Drupal::service('config.typed'), $display->getEntityType()->getConfigPrefix() . '.' . $display->id(), $display->toArray());
+
+    // Confirm that the third party settings are not updated on the settings form.
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
     $this->assertFieldByName($fieldname, '');
   }
diff --git a/core/modules/options/src/Plugin/Field/FieldWidget/OptionsWidgetBase.php b/core/modules/options/src/Plugin/Field/FieldWidget/OptionsWidgetBase.php
index 70f40ec..165bc92 100644
--- a/core/modules/options/src/Plugin/Field/FieldWidget/OptionsWidgetBase.php
+++ b/core/modules/options/src/Plugin/Field/FieldWidget/OptionsWidgetBase.php
@@ -45,8 +45,8 @@
   /**
    * {@inheritdoc}
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
     $property_names = $this->fieldDefinition->getPropertyNames();
     $this->column = $property_names[0];
   }
