diff --git a/core/modules/field/lib/Drupal/field/FieldInstance.php b/core/modules/field/lib/Drupal/field/FieldInstance.php
index d04146b..bd3e882 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstance.php
@@ -46,18 +46,18 @@ public function __construct(array $definition) {
   /**
    * Returns the Widget plugin for the instance.
    *
-   * @param bool $instance_settings_form
-   *   (optional) Whether we are getting the widget for the field instance
-   *   settings form. Defaults to FALSE.
+   * @param bool $allow_hidden
+   *   (optional) Whether we are allowed to return the 'field_hidden' widget.
+   *   Defaults to TRUE.
    *
    * @return \Drupal\field\Plugin\Type\Widget\WidgetInterface
    *   The Widget plugin to be used for the instance.
    */
-  public function getWidget($instance_settings_form = FALSE) {
+  public function getWidget($allow_hidden = TRUE) {
     // Skip the static cache if we are getting the widget for the field instance
     // settings form.
-    if (empty($this->widget) || $instance_settings_form) {
-      if ($instance_settings_form && $this->definition['widget']['type'] == 'field_hidden') {
+    if (empty($this->widget) || !$allow_hidden) {
+      if (!$allow_hidden && $this->definition['widget']['type'] == 'field_hidden') {
         $field = field_info_field_by_id($this->definition['field_id']);
         $field_type = field_info_field_types($field['type']);
         $default_widget = field_info_widget_types($field_type['default_widget']);
diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
index b11638f..f10b9d8 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
@@ -551,4 +551,62 @@ function testNestedFieldForm() {
     $this->assertFieldValues($entity_1, 'field_unlimited', LANGUAGE_NOT_SPECIFIED, array(3, 2));
     $this->assertFieldValues($entity_2, 'field_unlimited', LANGUAGE_NOT_SPECIFIED, array(13, 14, 15));
   }
+
+  /**
+   * Tests the Hidden widget.
+   */
+  function testFieldFormHiddenWidget() {
+    $this->field = $this->field_single;
+    $this->field_name = $this->field['field_name'];
+    $this->instance['field_name'] = $this->field_name;
+    $this->instance['widget']['type'] = 'field_hidden';
+    $this->instance['default_value'] = array(0 => array('value' => 99));
+    field_create_field($this->field);
+    field_create_instance($this->instance);
+    $langcode = LANGUAGE_NOT_SPECIFIED;
+
+    // Display creation form.
+    $this->drupalGet('test-entity/add/test_bundle');
+
+    // Create an entity.
+    $this->assertNoField("{$this->field_name}[$langcode][0][value]", 'The hidden widget is not displayed');
+    $this->drupalPost(NULL, array(), t('Save'));
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
+    $id = $match[1];
+    $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
+    $entity = field_test_entity_test_load($id);
+    $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], 99, 'Default value was saved');
+
+    // Update the instance to remove the default value and switch to the
+    // default widget.
+    $this->instance['default_value'] = NULL;
+    $this->instance['widget']['type'] = 'test_field_widget';
+    field_update_instance($this->instance);
+
+    // Display edit form.
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
+    $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", 99, 'Widget is displayed with the correct default value');
+
+    // Update the entity.
+    $value = mt_rand(1, 127);
+    $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
+    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
+    entity_get_controller('test_entity')->resetCache(array($id));
+    $entity = field_test_entity_test_load($id);
+    $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was updated');
+
+    // Update the instance and switch to the Hidden widget again.
+    $this->instance['widget']['type'] = 'field_hidden';
+    field_update_instance($this->instance);
+
+    // Create a new revision.
+    $edit = array('revision' => TRUE);
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
+
+    // Check that the expected value has been carried over to the new revision.
+    entity_get_controller('test_entity')->resetCache(array($id));
+    $entity = field_test_entity_test_load($id);
+    $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'New revision has the expected value for the field with the Hidden widget');
+  }
 }
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index f99a88a..3f455a7 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -446,7 +446,7 @@ function field_ui_field_type_options() {
  * If no field type is provided, returns a nested array of all widget types,
  * keyed by field type human name.
  */
-function field_ui_widget_type_options($field_type = NULL, $by_label = FALSE) {
+function field_ui_widget_type_options($field_type = NULL, $by_label = FALSE, $allow_hidden = TRUE) {
   $options = &drupal_static(__FUNCTION__);
 
   if (!isset($options)) {
@@ -454,6 +454,9 @@ function field_ui_widget_type_options($field_type = NULL, $by_label = FALSE) {
     $field_types = field_info_field_types();
     $widget_types = field_info_widget_types();
     uasort($widget_types, 'drupal_sort_weight');
+    if (!$allow_hidden) {
+      unset($widget_types['field_hidden']);
+    }
     foreach ($widget_types as $name => $widget_type) {
       foreach ($widget_type['field_types'] as $widget_field_type) {
         // Check that the field type exists.
@@ -722,7 +725,7 @@ function field_ui_widget_type_form($form, &$form_state, FieldInstance $instance)
     '#type' => 'select',
     '#title' => t('Widget type'),
     '#required' => TRUE,
-    '#options' => field_ui_widget_type_options($field['type']),
+    '#options' => field_ui_widget_type_options($field['type'], FALSE, (bool) !$instance['required']),
     '#default_value' => $instance->getWidget()->getPluginId(),
     '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)),
   );
@@ -914,10 +917,13 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
     '#weight' => -10,
   );
 
+  $allow_required = $instance['widget']['type'] != 'field_hidden' ? TRUE : FALSE;
   $form['instance']['required'] = array(
     '#type' => 'checkbox',
     '#title' => t('Required field'),
     '#default_value' => !empty($instance['required']),
+    '#description' => !$allow_required ? t('This field uses the <em>Hidden</em> widget so it cannot be required.') : NULL,
+    '#disabled' => !$allow_required,
     '#weight' => -5,
   );
 
@@ -1005,7 +1011,7 @@ function field_ui_default_value_widget($field, $instance, &$form, &$form_state)
   // Insert the widget. Since we do not use the "official" instance definition,
   // the whole flow cannot use field_invoke_method().
   $items = (array) $instance['default_value'];
-  $element += $instance->getWidget(TRUE)->form($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
+  $element += $instance->getWidget(FALSE)->form($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
 
   return $element;
 }
@@ -1027,7 +1033,7 @@ function field_ui_field_edit_form_validate($form, &$form_state) {
 
     // Extract the 'default value'.
     $items = array();
-    $instance->getWidget(TRUE)->submit($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
+    $instance->getWidget(FALSE)->submit($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
 
     // Grab the field definition from $form_state.
     $field_state = field_form_get_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state);
@@ -1047,7 +1053,7 @@ function field_ui_field_edit_form_validate($form, &$form_state) {
       field_form_set_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state, $field_state);
 
       // Assign reported errors to the correct form element.
-      $instance->getWidget(TRUE)->flagErrors($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
+      $instance->getWidget(FALSE)->flagErrors($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
     }
   }
 }
@@ -1068,7 +1074,7 @@ function field_ui_field_edit_form_submit($form, &$form_state) {
 
     // Extract field values.
     $items = array();
-    $instance->getWidget(TRUE)->submit($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
+    $instance->getWidget(FALSE)->submit($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state);
 
     $instance['default_value'] = $items ? $items : NULL;
   }
