diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index a516836..efd4afb 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -52,14 +52,21 @@ function file_help($route_name, RouteMatchInterface $route_match) {
  * Implements hook_element_info().
  *
  * The managed file element may be used anywhere in Drupal.
+ *
+ * @todo Remove once https://www.drupal.org/node/2326409 is in.
  */
 function file_element_info() {
   $types['managed_file'] = array(
     '#input' => TRUE,
-    '#process' => array('file_managed_file_process'),
-    '#value_callback' => 'file_managed_file_value',
-    '#element_validate' => array('file_managed_file_validate'),
-    '#pre_render' => array('file_managed_file_pre_render'),
+    '#process' => array(
+      '\Drupal\file\Element\ManagedFile::processManagedFile',
+    ),
+    '#element_validate' => array(
+      '\Drupal\file\Element\ManagedFile::validateManagedFile',
+    ),
+    '#pre_render' => array(
+      '\Drupal\file\Element\ManagedFile::preRenderManagedFile',
+    ),
     '#theme' => 'file_managed_file',
     '#theme_wrappers' => array('form_element'),
     '#progress_indicator' => 'throbber',
@@ -1097,270 +1104,6 @@ function file_token_info() {
 }
 
 /**
- * Render API callback: Expands the managed_file element type.
- *
- * Expands the file type to include Upload and Remove buttons, as well as
- * support for a default value.
- *
- * This function is assigned as a #process callback in file_element_info().
- */
-function file_managed_file_process($element, FormStateInterface $form_state, $form) {
-  // Append the '-upload' to the #id so the field label's 'for' attribute
-  // corresponds with the file element.
-  $element['#id'] .= '-upload';
-
-  // This is used sometimes so let's implode it just once.
-  $parents_prefix = implode('_', $element['#parents']);
-
-  $fids = isset($element['#value']['fids']) ? $element['#value']['fids'] : array();
-
-  // Set some default element properties.
-  $element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator'];
-  $element['#files'] = !empty($fids) ? file_load_multiple($fids) : FALSE;
-  $element['#tree'] = TRUE;
-
-  $ajax_settings = array(
-    'path' => 'file/ajax',
-    'options' => array(
-      'query' => array(
-        'element_parents' => implode('/', $element['#array_parents']),
-        'form_build_id' => $form['form_build_id']['#value'],
-      ),
-    ),
-    'wrapper' => $element['#id'] . '-ajax-wrapper',
-    'effect' => 'fade',
-    'progress' => array(
-      'type' => $element['#progress_indicator'],
-      'message' => $element['#progress_message'],
-    ),
-  );
-
-  // Set up the buttons first since we need to check if they were clicked.
-  $element['upload_button'] = array(
-    '#name' => $parents_prefix . '_upload_button',
-    '#type' => 'submit',
-    '#value' => t('Upload'),
-    '#attributes' => array('class' => array('js-hide')),
-    '#validate' => array(),
-    '#submit' => array('file_managed_file_submit'),
-    '#limit_validation_errors' => array($element['#parents']),
-    '#ajax' => $ajax_settings,
-    '#weight' => -5,
-  );
-
-  // Force the progress indicator for the remove button to be either 'none' or
-  // 'throbber', even if the upload button is using something else.
-  $ajax_settings['progress']['type'] = ($element['#progress_indicator'] == 'none') ? 'none' : 'throbber';
-  $ajax_settings['progress']['message'] = NULL;
-  $ajax_settings['effect'] = 'none';
-  $element['remove_button'] = array(
-    '#name' => $parents_prefix . '_remove_button',
-    '#type' => 'submit',
-    '#value' => $element['#multiple'] ? t('Remove selected') : t('Remove'),
-    '#validate' => array(),
-    '#submit' => array('file_managed_file_submit'),
-    '#limit_validation_errors' => array($element['#parents']),
-    '#ajax' => $ajax_settings,
-    '#weight' => 1,
-  );
-
-  $element['fids'] = array(
-    '#type' => 'hidden',
-    '#value' => $fids,
-  );
-
-  // Add progress bar support to the upload if possible.
-  if ($element['#progress_indicator'] == 'bar' && $implementation = file_progress_implementation()) {
-    $upload_progress_key = mt_rand();
-
-    if ($implementation == 'uploadprogress') {
-      $element['UPLOAD_IDENTIFIER'] = array(
-        '#type' => 'hidden',
-        '#value' => $upload_progress_key,
-        '#attributes' => array('class' => array('file-progress')),
-        // Uploadprogress extension requires this field to be at the top of the
-        // form.
-        '#weight' => -20,
-      );
-    }
-    elseif ($implementation == 'apc') {
-      $element['APC_UPLOAD_PROGRESS'] = array(
-        '#type' => 'hidden',
-        '#value' => $upload_progress_key,
-        '#attributes' => array('class' => array('file-progress')),
-        // Uploadprogress extension requires this field to be at the top of the
-        // form.
-        '#weight' => -20,
-      );
-    }
-
-    // Add the upload progress callback.
-    $element['upload_button']['#ajax']['progress']['path'] = 'file/progress/' . $upload_progress_key;
-  }
-
-  // The file upload field itself.
-  $element['upload'] = array(
-    '#name' => 'files[' . $parents_prefix . ']',
-    '#type' => 'file',
-    '#title' => t('Choose a file'),
-    '#title_display' => 'invisible',
-    '#size' => $element['#size'],
-    '#multiple' => $element['#multiple'],
-    '#theme_wrappers' => array(),
-    '#weight' => -10,
-  );
-
-  if (!empty($fids) && $element['#files']) {
-    foreach ($element['#files'] as $delta => $file) {
-      $file_link = array(
-        '#theme' => 'file_link',
-        '#file' => $file,
-      );
-      if ($element['#multiple']) {
-        $element['file_' . $delta]['selected'] = array(
-          '#type' => 'checkbox',
-          '#title' => drupal_render($file_link),
-        );
-      }
-      else {
-        $element['file_' . $delta]['filename'] = $file_link += array('#weight' => -10);
-      }
-    }
-  }
-
-  // Add the extension list to the page as JavaScript settings.
-  if (isset($element['#upload_validators']['file_validate_extensions'][0])) {
-    $extension_list = implode(',', array_filter(explode(' ', $element['#upload_validators']['file_validate_extensions'][0])));
-    $element['upload']['#attached']['js'] = array(
-      array(
-        'type' => 'setting',
-        'data' => array('file' => array('elements' => array('#' . $element['#id'] => $extension_list)))
-      )
-    );
-  }
-
-  // Prefix and suffix used for Ajax replacement.
-  $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
-  $element['#suffix'] = '</div>';
-
-  return $element;
-}
-
-/**
- * Render API callback: Determines the value for a managed_file type element.
- *
- * This function is assigned as a #value_callback in file_element_info().
- */
-function file_managed_file_value(&$element, $input, FormStateInterface $form_state) {
-  // Find the current value of this field.
-  $fids = !empty($input['fids']) ? explode(' ', $input['fids']) : array();
-  foreach ($fids as $key => $fid) {
-    $fids[$key] = (int) $fid;
-  }
-
-  // Process any input and save new uploads.
-  if ($input !== FALSE) {
-    $input['fids'] = $fids;
-    $return = $input;
-
-    // Uploads take priority over all other values.
-    if ($files = file_managed_file_save_upload($element, $form_state)) {
-      if ($element['#multiple']) {
-        $fids = array_merge($fids, array_keys($files));
-      }
-      else {
-        $fids = array_keys($files);
-      }
-    }
-    else {
-      // Check for #filefield_value_callback values.
-      // Because FAPI does not allow multiple #value_callback values like it
-      // does for #element_validate and #process, this fills the missing
-      // functionality to allow File fields to be extended through FAPI.
-      if (isset($element['#file_value_callbacks'])) {
-        foreach ($element['#file_value_callbacks'] as $callback) {
-          $callback($element, $input, $form_state);
-        }
-      }
-
-      // Load files if the FIDs have changed to confirm they exist.
-      if (!empty($input['fids'])) {
-        $fids = array();
-        foreach ($input['fids'] as $fid) {
-          if ($file = file_load($fid)) {
-            $fids[] = $file->id();
-          }
-        }
-      }
-    }
-  }
-
-  // If there is no input, set the default value.
-  else {
-    if ($element['#extended']) {
-      $default_fids = isset($element['#default_value']['fids']) ? $element['#default_value']['fids'] : array();
-      $return = isset($element['#default_value']) ? $element['#default_value'] : array('fids' => array());
-    }
-    else {
-      $default_fids = isset($element['#default_value']) ? $element['#default_value'] : array();
-      $return = array('fids' => array());
-    }
-
-    // Confirm that the file exists when used as a default value.
-    if (!empty($default_fids)) {
-      $fids = array();
-      foreach ($default_fids as $fid) {
-        if ($file = file_load($fid)) {
-          $fids[] = $file->id();
-        }
-      }
-    }
-  }
-
-  $return['fids'] = $fids;
-  return $return;
-}
-
-/**
- * Render API callback: Validates the managed_file element.
- *
- * This function is assigned as a #element_validate callback in
- * file_element_info().
- */
-function file_managed_file_validate(&$element, FormStateInterface $form_state) {
-  // If referencing an existing file, only allow if there are existing
-  // references. This prevents unmanaged files from being deleted if this
-  // item were to be deleted.
-  $clicked_button = end($form_state->getTriggeringElement()['#parents']);
-  if ($clicked_button != 'remove_button' && !empty($element['fids']['#value'])) {
-    $fids = $element['fids']['#value'];
-    foreach ($fids as $fid) {
-      if ($file = file_load($fid)) {
-        if ($file->isPermanent()) {
-          $references = \Drupal::service('file.usage')->listUsage($file);
-          if (empty($references)) {
-            $form_state->setError($element, t('The file used in the !name field may not be referenced.', array('!name' => $element['#title'])));
-          }
-        }
-      }
-      else {
-        $form_state->setError($element, t('The file referenced by the !name field does not exist.', array('!name' => $element['#title'])));
-      }
-    }
-  }
-
-  // Check required property based on the FID.
-  if ($element['#required'] && empty($element['fids']['#value']) && !in_array($clicked_button, array('upload_button', 'remove_button'))) {
-    $form_state->setError($element['upload'], t('!name field is required.', array('!name' => $element['#title'])));
-  }
-
-  // Consolidate the array value of this field to array of FIDs.
-  if (!$element['#extended']) {
-    form_set_value($element, $element['fids']['#value'], $form_state);
-  }
-}
-
-/**
  * Form submission handler for upload / remove buttons of managed_file elements.
  *
  * @see file_managed_file_process()
@@ -1373,9 +1116,10 @@ function file_managed_file_submit($form, FormStateInterface $form_state) {
   $element = NestedArray::getValue($form, $parents);
 
   // No action is needed here for the upload button, because all file uploads on
-  // the form are processed by file_managed_file_value() regardless of which
-  // button was clicked. Action is needed here for the remove button, because we
-  // only remove a file in response to its remove button being clicked.
+  // the form are processed by \Drupal\file\Element\ManagedFile::valueCallback()
+  // regardless of which button was clicked. Action is needed here for the
+  // remove button, because we only remove a file in response to its remove
+  // button being clicked.
   if ($button_key == 'remove_button') {
     $fids = array_keys($element['#files']);
     // Get files that will be removed.
@@ -1409,8 +1153,9 @@ function file_managed_file_submit($form, FormStateInterface $form_state) {
     // $form_state->getValues() must be updated in case additional submit
     // handlers run, and for form building functions that run during the
     // rebuild, such as when the managed_file element is part of a field widget.
-    // FormState::$input must be updated so that file_managed_file_value()
-    // has correct information during the rebuild.
+    // FormState::$input must be updated so that
+    // \Drupal\file\Element\ManagedFile::valueCallback() has correct information
+    // during the rebuild.
     form_set_value($element['fids'], implode(' ', $fids), $form_state);
     NestedArray::setValue($form_state->getUserInput(), $element['fids']['#parents'], implode(' ', $fids));
   }
@@ -1493,41 +1238,6 @@ function template_preprocess_file_managed_file(&$variables) {
 }
 
 /**
- * Render API callback: Hides display of the upload or remove controls.
- *
- * Upload controls are hidden when a file is already uploaded. Remove controls
- * are hidden when there is no file attached. Controls are hidden here instead
- * of in file_managed_file_process(), because #access for these buttons depends
- * on the managed_file element's #value. See the documentation of form_builder()
- * for more detailed information about the relationship between #process,
- * #value, and #access.
- *
- * Because #access is set here, it affects display only and does not prevent
- * JavaScript or other untrusted code from submitting the form as though access
- * were enabled. The form processing functions for these elements should not
- * assume that the buttons can't be "clicked" just because they are not
- * displayed.
- *
- * This function is assigned as a #pre_render callback in file_element_info().
- *
- * @see file_managed_file_process()
- */
-function file_managed_file_pre_render($element) {
-  // If we already have a file, we don't want to show the upload controls.
-  if (!empty($element['#value']['fids'])) {
-    if (!$element['#multiple']) {
-      $element['upload']['#access'] = FALSE;
-      $element['upload_button']['#access'] = FALSE;
-    }
-  }
-  // If we don't already have a file, there is nothing to remove.
-  else {
-    $element['remove_button']['#access'] = FALSE;
-  }
-  return $element;
-}
-
-/**
  * Prepares variables for file link templates.
  *
  * Default template: file-link.html.twig.
diff --git a/core/modules/file/src/Element/ManagedFile.php b/core/modules/file/src/Element/ManagedFile.php
new file mode 100644
index 0000000..76a6857
--- /dev/null
+++ b/core/modules/file/src/Element/ManagedFile.php
@@ -0,0 +1,348 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Element\ManagedFile.
+ */
+
+namespace Drupal\file\Element;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element\FormElement;
+use Drupal\file\Entity\File;
+
+/**
+ * Provides an AJAX/progress aware widget for uploading and saving a file.
+ *
+ * @todo Annotate once https://www.drupal.org/node/2326409 is in.
+ *   FormElement("managed_file")
+ */
+class ManagedFile extends FormElement {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInfo() {
+    $class = get_class($this);
+    return [
+      '#input' => TRUE,
+      '#process' => [
+        [$class, 'processManagedFile'],
+      ],
+      '#element_validate' => [
+        [$class, 'validateManagedFile'],
+      ],
+      '#pre_render' => [
+        [$class, 'preRenderManagedFile'],
+      ],
+      '#theme' => 'file_managed_file',
+      '#theme_wrappers' => ['form_element'],
+      '#progress_indicator' => 'throbber',
+      '#progress_message' => NULL,
+      '#upload_validators' => [],
+      '#upload_location' => NULL,
+      '#size' => 22,
+      '#multiple' => FALSE,
+      '#extended' => FALSE,
+      '#attached' => [
+        'library' => ['file/drupal.file'],
+      ],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
+    // Find the current value of this field.
+    $fids = !empty($input['fids']) ? explode(' ', $input['fids']) : [];
+    foreach ($fids as $key => $fid) {
+      $fids[$key] = (int) $fid;
+    }
+
+    // Process any input and save new uploads.
+    if ($input !== FALSE) {
+      $input['fids'] = $fids;
+      $return = $input;
+
+      // Uploads take priority over all other values.
+      if ($files = file_managed_file_save_upload($element, $form_state)) {
+        if ($element['#multiple']) {
+          $fids = array_merge($fids, array_keys($files));
+        }
+        else {
+          $fids = array_keys($files);
+        }
+      }
+      else {
+        // Check for #filefield_value_callback values.
+        // Because FAPI does not allow multiple #value_callback values like it
+        // does for #element_validate and #process, this fills the missing
+        // functionality to allow File fields to be extended through FAPI.
+        if (isset($element['#file_value_callbacks'])) {
+          foreach ($element['#file_value_callbacks'] as $callback) {
+            $callback($element, $input, $form_state);
+          }
+        }
+
+        // Load files if the FIDs have changed to confirm they exist.
+        if (!empty($input['fids'])) {
+          $fids = [];
+          foreach ($input['fids'] as $fid) {
+            if ($file = File::load($fid)) {
+              $fids[] = $file->id();
+            }
+          }
+        }
+      }
+    }
+
+    // If there is no input, set the default value.
+    else {
+      if ($element['#extended']) {
+        $default_fids = isset($element['#default_value']['fids']) ? $element['#default_value']['fids'] : [];
+        $return = isset($element['#default_value']) ? $element['#default_value'] : ['fids' => []];
+      }
+      else {
+        $default_fids = isset($element['#default_value']) ? $element['#default_value'] : [];
+        $return = ['fids' => []];
+      }
+
+      // Confirm that the file exists when used as a default value.
+      if (!empty($default_fids)) {
+        $fids = [];
+        foreach ($default_fids as $fid) {
+          if ($file = File::load($fid)) {
+            $fids[] = $file->id();
+          }
+        }
+      }
+    }
+
+    $return['fids'] = $fids;
+    return $return;
+  }
+
+  /**
+   * Render API callback: Expands the managed_file element type.
+   *
+   * Expands the file type to include Upload and Remove buttons, as well as
+   * support for a default value.
+   */
+  public static function processManagedFile(&$element, FormStateInterface $form_state, &$complete_form) {
+    // Append the '-upload' to the #id so the field label's 'for' attribute
+    // corresponds with the file element.
+    $element['#id'] .= '-upload';
+
+    // This is used sometimes so let's implode it just once.
+    $parents_prefix = implode('_', $element['#parents']);
+
+    $fids = isset($element['#value']['fids']) ? $element['#value']['fids'] : [];
+
+    // Set some default element properties.
+    $element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator'];
+    $element['#files'] = !empty($fids) ? File::loadMultiple($fids) : FALSE;
+    $element['#tree'] = TRUE;
+
+    $ajax_settings = [
+      'path' => 'file/ajax',
+      'options' => [
+        'query' => [
+          'element_parents' => implode('/', $element['#array_parents']),
+          'form_build_id' => $complete_form['form_build_id']['#value'],
+        ],
+      ],
+      'wrapper' => $element['#id'] . '-ajax-wrapper',
+      'effect' => 'fade',
+      'progress' => [
+        'type' => $element['#progress_indicator'],
+        'message' => $element['#progress_message'],
+      ],
+    ];
+
+    // Set up the buttons first since we need to check if they were clicked.
+    $element['upload_button'] = [
+      '#name' => $parents_prefix . '_upload_button',
+      '#type' => 'submit',
+      '#value' => t('Upload'),
+      '#attributes' => ['class' => ['js-hide']],
+      '#validate' => [],
+      '#submit' => ['file_managed_file_submit'],
+      '#limit_validation_errors' => [$element['#parents']],
+      '#ajax' => $ajax_settings,
+      '#weight' => -5,
+    ];
+
+    // Force the progress indicator for the remove button to be either 'none' or
+    // 'throbber', even if the upload button is using something else.
+    $ajax_settings['progress']['type'] = ($element['#progress_indicator'] == 'none') ? 'none' : 'throbber';
+    $ajax_settings['progress']['message'] = NULL;
+    $ajax_settings['effect'] = 'none';
+    $element['remove_button'] = [
+      '#name' => $parents_prefix . '_remove_button',
+      '#type' => 'submit',
+      '#value' => $element['#multiple'] ? t('Remove selected') : t('Remove'),
+      '#validate' => [],
+      '#submit' => ['file_managed_file_submit'],
+      '#limit_validation_errors' => [$element['#parents']],
+      '#ajax' => $ajax_settings,
+      '#weight' => 1,
+    ];
+
+    $element['fids'] = [
+      '#type' => 'hidden',
+      '#value' => $fids,
+    ];
+
+    // Add progress bar support to the upload if possible.
+    if ($element['#progress_indicator'] == 'bar' && $implementation = file_progress_implementation()) {
+      $upload_progress_key = mt_rand();
+
+      if ($implementation == 'uploadprogress') {
+        $element['UPLOAD_IDENTIFIER'] = [
+          '#type' => 'hidden',
+          '#value' => $upload_progress_key,
+          '#attributes' => ['class' => ['file-progress']],
+          // Uploadprogress extension requires this field to be at the top of
+          // the form.
+          '#weight' => -20,
+        ];
+      }
+      elseif ($implementation == 'apc') {
+        $element['APC_UPLOAD_PROGRESS'] = [
+          '#type' => 'hidden',
+          '#value' => $upload_progress_key,
+          '#attributes' => ['class' => ['file-progress']],
+          // Uploadprogress extension requires this field to be at the top of
+          // the form.
+          '#weight' => -20,
+        ];
+      }
+
+      // Add the upload progress callback.
+      $element['upload_button']['#ajax']['progress']['path'] = 'file/progress/' . $upload_progress_key;
+    }
+
+    // The file upload field itself.
+    $element['upload'] = [
+      '#name' => 'files[' . $parents_prefix . ']',
+      '#type' => 'file',
+      '#title' => t('Choose a file'),
+      '#title_display' => 'invisible',
+      '#size' => $element['#size'],
+      '#multiple' => $element['#multiple'],
+      '#theme_wrappers' => [],
+      '#weight' => -10,
+    ];
+
+    if (!empty($fids) && $element['#files']) {
+      foreach ($element['#files'] as $delta => $file) {
+        $file_link = [
+          '#theme' => 'file_link',
+          '#file' => $file,
+        ];
+        if ($element['#multiple']) {
+          $element['file_' . $delta]['selected'] = [
+            '#type' => 'checkbox',
+            '#title' => drupal_render($file_link),
+          ];
+        }
+        else {
+          $element['file_' . $delta]['filename'] = $file_link + ['#weight' => -10];
+        }
+      }
+    }
+
+    // Add the extension list to the page as JavaScript settings.
+    if (isset($element['#upload_validators']['file_validate_extensions'][0])) {
+      $extension_list = implode(',', array_filter(explode(' ', $element['#upload_validators']['file_validate_extensions'][0])));
+      $element['upload']['#attached']['js'] = [[
+        'type' => 'setting',
+        'data' => ['file' => ['elements' => ['#' . $element['#id'] => $extension_list]]],
+      ]];
+    }
+
+    // Prefix and suffix used for Ajax replacement.
+    $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
+    $element['#suffix'] = '</div>';
+
+    return $element;
+  }
+
+  /**
+   * Render API callback: Hides display of the upload or remove controls.
+   *
+   * Upload controls are hidden when a file is already uploaded. Remove controls
+   * are hidden when there is no file attached. Controls are hidden here instead
+   * of in file_managed_file_process(), because #access for these buttons
+   * depends on the managed_file element's #value. See the documentation of
+   * form_builder() for more detailed information about the relationship between
+   * #process, #value, and #access.
+   *
+   * Because #access is set here, it affects display only and does not prevent
+   * JavaScript or other untrusted code from submitting the form as though
+   * access were enabled. The form processing functions for these elements
+   * should not assume that the buttons can't be "clicked" just because they are
+   * not displayed.
+   */
+  public static function preRenderManagedFile($element) {
+    // If we already have a file, we don't want to show the upload controls.
+    if (!empty($element['#value']['fids'])) {
+      if (!$element['#multiple']) {
+        $element['upload']['#access'] = FALSE;
+        $element['upload_button']['#access'] = FALSE;
+      }
+    }
+    // If we don't already have a file, there is nothing to remove.
+    else {
+      $element['remove_button']['#access'] = FALSE;
+    }
+    return $element;
+  }
+
+  /**
+   * Render API callback: Validates the managed_file element.
+   */
+  public static function validateManagedFile(&$element, FormStateInterface $form_state, &$complete_form) {
+    // If referencing an existing file, only allow if there are existing
+    // references. This prevents unmanaged files from being deleted if this
+    // item were to be deleted.
+    $clicked_button = end($form_state->getTriggeringElement()['#parents']);
+    if ($clicked_button != 'remove_button' && !empty($element['fids']['#value'])) {
+      $fids = $element['fids']['#value'];
+      foreach ($fids as $fid) {
+        if ($file = File::load($fid)) {
+          if ($file->isPermanent()) {
+            $references = static::fileUsage()->listUsage($file);
+            if (empty($references)) {
+              $form_state->setError($element, t('The file used in the !name field may not be referenced.', ['!name' => $element['#title']]));
+            }
+          }
+        }
+        else {
+          $form_state->setError($element, t('The file referenced by the !name field does not exist.', ['!name' => $element['#title']]));
+        }
+      }
+    }
+
+    // Check required property based on the FID.
+    if ($element['#required'] && empty($element['fids']['#value']) && !in_array($clicked_button, ['upload_button', 'remove_button'])) {
+      $form_state->setError($element['upload'], t('!name field is required.', ['!name' => $element['#title']]));
+    }
+
+    // Consolidate the array value of this field to array of FIDs.
+    if (!$element['#extended']) {
+      $form_state->setValueForElement($element, $element['fids']['#value']);
+    }
+  }
+
+  /**
+   * Wraps the file usage service.
+   *
+   * @return \Drupal\file\FileUsage\FileUsageInterface
+   */
+  protected static function fileUsage() {
+    return \Drupal::service('file.usage');
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
index f9becf4..ab0c6a8 100644
--- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -14,6 +14,7 @@
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
+use Drupal\file\Element\ManagedFile;
 
 /**
  * Plugin implementation of the 'file_generic' widget.
@@ -289,7 +290,7 @@ public static function value($element, $input = FALSE, FormStateInterface $form_
     }
 
     // We depend on the managed file element to handle uploads.
-    $return = file_managed_file_value($element, $input, $form_state);
+    $return = ManagedFile::valueCallback($element, $input, $form_state);
 
     // Ensure that all the required properties are returned even if empty.
     $return += array(
diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
index a8afbbb..07a567d 100644
--- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
@@ -402,7 +402,10 @@ protected function defaultImageForm(array &$element, array $settings) {
       '#description' => t('Image to be shown if no image is uploaded.'),
       '#default_value' => empty($settings['default_image']['fid']) ? array() : array($settings['default_image']['fid']),
       '#upload_location' => $settings['uri_scheme'] . '://default_images/',
-      '#element_validate' => array('file_managed_file_validate', array(get_class($this), 'validateDefaultImageForm')),
+      '#element_validate' => array(
+        '\Drupal\file\Element\ManagedFile::validateManagedFile',
+        array(get_class($this), 'validateDefaultImageForm'),
+      ),
       '#upload_validators' => $this->getUploadValidators(),
     );
     $element['default_image']['alt'] = array(
