
 ckeditor/src/Plugin/CKEditorPlugin/DrupalMediaLibrary.php               |    4 
 ckeditor5/src/Plugin/CKEditor5Plugin/MediaLibrary.php                   |    4 
 media_library/config/schema/media_library.schema.yml                    |    3 
 media_library/src/Form/AddFormBase.php                                  |   38 +++-
 media_library/src/Form/FileUploadForm.php                               |   24 ++
 media_library/src/MediaLibraryState.php                                 |   33 +++
 media_library/src/MediaLibraryUiBuilder.php                             |   30 ++-
 media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php       |   89 ++++++++--
 media_library/tests/src/FunctionalJavascript/EmbeddedFormWidgetTest.php |    2 
 media_library/tests/src/FunctionalJavascript/WidgetAccessTest.php       |   22 +-
 media_library/tests/src/Kernel/MediaLibraryAccessTest.php               |   83 +++++++--
 media_library/tests/src/Kernel/MediaLibraryAddFormTest.php              |    4 
 media_library/tests/src/Kernel/MediaLibraryStateTest.php                |   19 +-
 13 files changed, 284 insertions(+), 71 deletions(-)

diff --git a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalMediaLibrary.php b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalMediaLibrary.php
index bfff786dbe..80ec6475e0 100644
--- a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalMediaLibrary.php
+++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalMediaLibrary.php
@@ -139,10 +139,14 @@ public function getConfig(Editor $editor) {
       $media_type_ids = array_unique($media_type_ids);
     }
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     $state = MediaLibraryState::create(
       'media_library.opener.editor',
       $media_type_ids,
       reset($media_type_ids),
+      $form_mode,
       1,
       ['filter_format_id' => $editor->getFilterFormat()->id()]
     );
diff --git a/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/MediaLibrary.php b/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/MediaLibrary.php
index 47cf823199..606d6c6e66 100644
--- a/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/MediaLibrary.php
+++ b/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/MediaLibrary.php
@@ -81,10 +81,14 @@ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterf
       $media_type_ids = array_unique($media_type_ids);
     }
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     $state = MediaLibraryState::create(
       'media_library.opener.editor',
       $media_type_ids,
       reset($media_type_ids),
+      $form_mode,
       1,
       ['filter_format_id' => $editor->getFilterFormat()->id()],
     );
diff --git a/core/modules/media_library/config/schema/media_library.schema.yml b/core/modules/media_library/config/schema/media_library.schema.yml
index 312f4ab607..bfc92b01e9 100644
--- a/core/modules/media_library/config/schema/media_library.schema.yml
+++ b/core/modules/media_library/config/schema/media_library.schema.yml
@@ -8,6 +8,9 @@ field.widget.settings.media_library_widget:
       sequence:
         type: string
         label: 'Media type ID'
+    form_mode:
+      type: string
+      label: 'Form mode'
 
 media_library.settings:
   type: config_object
diff --git a/core/modules/media_library/src/Form/AddFormBase.php b/core/modules/media_library/src/Form/AddFormBase.php
index 83742a3a17..7c897deb39 100644
--- a/core/modules/media_library/src/Form/AddFormBase.php
+++ b/core/modules/media_library/src/Form/AddFormBase.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\media_library\Form;
 
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\CloseDialogCommand;
 use Drupal\Core\Ajax\FocusFirstCommand;
@@ -117,7 +118,9 @@ protected function getMediaType(FormStateInterface $form_state) {
 
     $state = $this->getMediaLibraryState($form_state);
     $selected_type_id = $state->getSelectedTypeId();
-    $this->mediaType = $this->entityTypeManager->getStorage('media_type')->load($selected_type_id);
+    $this->mediaType = $this->entityTypeManager
+      ->getStorage('media_type')
+      ->load($selected_type_id);
 
     if (!$this->mediaType) {
       throw new \InvalidArgumentException("The '$selected_type_id' media type does not exist.");
@@ -135,13 +138,19 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['#prefix'] = '<div id="media-library-add-form-wrapper">';
     $form['#suffix'] = '</div>';
 
+    // The media library state includes the widget settings of the form.
+    $media_state = $this->getMediaLibraryState($form_state);
+
+    // The form mode used to render all available entity types.
+    $entity_add_form_mode = $media_state->getFormModeId();
+
     // The media library is loaded via AJAX, which means that the form action
     // URL defaults to the current URL. However, to add media, we always need to
     // submit the form to the media library URL, not whatever the current URL
     // may be.
-    $form['#action'] = Url::fromRoute('media_library.ui', [], [
-      'query' => $this->getMediaLibraryState($form_state)->all(),
-    ])->toString();
+    $form['#action'] = Url::fromRoute('media_library.ui', [],
+      ['query' => $media_state->all()])
+      ->toString();
 
     // The form is posted via AJAX. When there are messages set during the
     // validation or submission of the form, the messages need to be shown to
@@ -152,6 +161,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['#attributes']['class'] = [
       'js-media-library-add-form',
+      Html::getClass('media_library_form_mode--' . $entity_add_form_mode),
     ];
 
     $added_media = $this->getAddedMediaItems($form_state);
@@ -184,14 +194,15 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           'aria-label' => $this->t('Added media items'),
           // Add the tabindex '-1' to allow the focus to be shifted to the added
           // media wrapper when items are added. We set focus to the container
-          // because a media item does not necessarily have required fields and
+          // because a media item does not necessarily have required fields, and
           // we do not want to set focus to the remove button automatically.
           // @see ::updateFormCallback()
           'tabindex' => '-1',
         ],
       ];
       foreach ($added_media as $delta => $media) {
-        $form['media'][$delta] = $this->buildEntityFormElement($media, $form, $form_state, $delta);
+        $form['media'][$delta] = $this->buildEntityFormElement(
+          $media, $form, $form_state, $delta, $entity_add_form_mode);
       }
 
       $form['selection'] = $this->buildCurrentSelectionArea($form, $form_state);
@@ -218,8 +229,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
   /**
    * Builds the element for submitting source field value(s).
    *
-   * The input element needs to have a submit handler to create media items from
-   * the user input and store them in the form state using
+   * The input element needs to have a submit handler to create media
+   * items from the user input and store them in the form state using
    * ::processInputValues().
    *
    * @param array $form
@@ -245,11 +256,14 @@ abstract protected function buildInputElement(array $form, FormStateInterface $f
    *   The current form state.
    * @param int $delta
    *   The delta of the media item.
+   * @param string $add_form_mode
+   *   The form mode that each media item will be shown in when created.
    *
    * @return array
    *   The element containing the required fields sub-form.
    */
-  protected function buildEntityFormElement(MediaInterface $media, array $form, FormStateInterface $form_state, $delta) {
+  protected function buildEntityFormElement(MediaInterface $media, array $form,
+      FormStateInterface $form_state, int $delta, string $add_form_mode = 'media_library'): array {
     // We need to make sure each button has a unique name attribute. The default
     // name for button elements is 'op'. If the name is not unique, the
     // triggering element is not set correctly and the wrong media item is
@@ -263,7 +277,7 @@ protected function buildEntityFormElement(MediaInterface $media, array $form, Fo
         'aria-label' => $media->getName(),
         // Add the tabindex '-1' to allow the focus to be shifted to the next
         // media item when an item is removed. We set focus to the container
-        // because a media item does not necessarily have required fields and we
+        // because a media item does not necessarily have required fields, and we
         // do not want to set focus to the remove button automatically.
         // @see ::updateFormCallback()
         'tabindex' => '-1',
@@ -301,6 +315,7 @@ protected function buildEntityFormElement(MediaInterface $media, array $form, Fo
         '#limit_validation_errors' => [],
       ],
     ];
+
     // @todo Make the image style configurable in
     //   https://www.drupal.org/node/2988223
     $source = $media->getSource();
@@ -313,7 +328,8 @@ protected function buildEntityFormElement(MediaInterface $media, array $form, Fo
       ];
     }
 
-    $form_display = EntityFormDisplay::collectRenderDisplay($media, 'media_library');
+    $form_display = EntityFormDisplay::collectRenderDisplay($media, $add_form_mode);
+
     // When the name is not added to the form as an editable field, output
     // the name as a fixed element to confirm the right file was uploaded.
     if (!$form_display->getComponent('name')) {
diff --git a/core/modules/media_library/src/Form/FileUploadForm.php b/core/modules/media_library/src/Form/FileUploadForm.php
index 2c0a81976d..dc6742d819 100644
--- a/core/modules/media_library/src/Form/FileUploadForm.php
+++ b/core/modules/media_library/src/Form/FileUploadForm.php
@@ -257,13 +257,24 @@ public function processUploadElement(array $element, FormStateInterface $form_st
   }
 
   /**
+   * Build the sub form for media entities, but modify base to slim it down.
+   *
+   * @see hideExtraSourceFieldComponents()
+   *
    * {@inheritdoc}
    */
-  protected function buildEntityFormElement(MediaInterface $media, array $form, FormStateInterface $form_state, $delta) {
-    $element = parent::buildEntityFormElement($media, $form, $form_state, $delta);
+  protected function buildEntityFormElement(MediaInterface $media, array $form,
+      FormStateInterface $form_state, int $delta, string $add_form_mode = 'media_library'): array {
+
+    $element = parent::buildEntityFormElement($media, $form, $form_state, $delta, $add_form_mode);
+
+    // @todo $media->bundle is not part of MediaInterface.
     $source_field = $this->getSourceFieldName($media->bundle->entity);
     if (isset($element['fields'][$source_field])) {
-      $element['fields'][$source_field]['widget'][0]['#process'][] = [static::class, 'hideExtraSourceFieldComponents'];
+      $element['fields'][$source_field]['widget'][0]['#process'][] = [
+        static::class,
+        'hideExtraSourceFieldComponents',
+      ];
     }
     return $element;
   }
@@ -271,6 +282,9 @@ protected function buildEntityFormElement(MediaInterface $media, array $form, Fo
   /**
    * Processes an image or file source field element.
    *
+   * Removes the remove_button, preview, title, description and filename
+   * elements from the form.
+   *
    * @param array $element
    *   The entity form source field element.
    * @param \Drupal\Core\Form\FormStateInterface $form_state
@@ -282,10 +296,12 @@ protected function buildEntityFormElement(MediaInterface $media, array $form, Fo
    *   The processed form element.
    */
   public static function hideExtraSourceFieldComponents($element, FormStateInterface $form_state, $form) {
+
     // Remove original button added by ManagedFile::processManagedFile().
     if (!empty($element['remove_button'])) {
       $element['remove_button']['#access'] = FALSE;
     }
+
     // Remove preview added by ImageWidget::process().
     if (!empty($element['preview'])) {
       $element['preview']['#access'] = FALSE;
@@ -358,6 +374,7 @@ protected function createFileItem(MediaTypeInterface $media_type) {
    * {@inheritdoc}
    */
   protected function prepareMediaEntityForSave(MediaInterface $media) {
+    // @todo $media->bundle is not part of MediaInterface.
     /** @var \Drupal\file\FileInterface $file */
     $file = $media->get($this->getSourceFieldName($media->bundle->entity))->entity;
     $file->setPermanent();
@@ -381,6 +398,7 @@ public function removeButtonSubmit(array $form, FormStateInterface $form_state)
     /** @var \Drupal\media\MediaInterface $removed_media */
     $removed_media = $form_state->get(['media', $delta]);
 
+    // @todo $media->bundle is not part of MediaInterface.
     $file = $removed_media->get($this->getSourceFieldName($removed_media->bundle->entity))->entity;
     if ($file instanceof FileInterface && empty($this->fileUsage->listUsage($file))) {
       $file->delete();
diff --git a/core/modules/media_library/src/MediaLibraryState.php b/core/modules/media_library/src/MediaLibraryState.php
index 6e1773073c..123561b14b 100644
--- a/core/modules/media_library/src/MediaLibraryState.php
+++ b/core/modules/media_library/src/MediaLibraryState.php
@@ -27,6 +27,7 @@
  * - media_library_selected_type: The media library contains tabs to navigate
  *   between the different media types. The selected type contains the ID of the
  *   media type whose tab that should be opened.
+ * - media_library_form_mode: form mode machine name valid for this media type.
  * - media_library_remaining: When the opener wants to limit the amount of media
  *   items that can be selected, it can pass the number of remaining slots. When
  *   the number of remaining slots is a negative number, an unlimited amount of
@@ -45,7 +46,13 @@ class MediaLibraryState extends ParameterBag implements CacheableDependencyInter
    * {@inheritdoc}
    */
   public function __construct(array $parameters = []) {
-    $this->validateRequiredParameters($parameters['media_library_opener_id'], $parameters['media_library_allowed_types'], $parameters['media_library_selected_type'], $parameters['media_library_remaining']);
+    $this->validateRequiredParameters(
+      $parameters['media_library_opener_id'],
+      $parameters['media_library_allowed_types'],
+      $parameters['media_library_selected_type'],
+      $parameters['media_library_form_mode'],
+      $parameters['media_library_remaining']);
+
     $parameters += [
       'media_library_opener_parameters' => [],
     ];
@@ -62,6 +69,8 @@ public function __construct(array $parameters = []) {
    *   The allowed media type IDs.
    * @param string $selected_type_id
    *   The selected media type ID.
+   * @param string $form_mode
+   *   The form_mode machine name for the add media form.
    * @param int $remaining_slots
    *   The number of remaining items the user is allowed to select or add in the
    *   library.
@@ -71,11 +80,12 @@ public function __construct(array $parameters = []) {
    * @return static
    *   A state object.
    */
-  public static function create($opener_id, array $allowed_media_type_ids, $selected_type_id, $remaining_slots, array $opener_parameters = []) {
+  public static function create($opener_id, array $allowed_media_type_ids, $selected_type_id, $form_mode, $remaining_slots, array $opener_parameters = []) {
     $state = new static([
       'media_library_opener_id' => $opener_id,
       'media_library_allowed_types' => $allowed_media_type_ids,
       'media_library_selected_type' => $selected_type_id,
+      'media_library_form_mode' => $form_mode,
       'media_library_remaining' => $remaining_slots,
       'media_library_opener_parameters' => $opener_parameters,
     ]);
@@ -103,6 +113,7 @@ public static function fromRequest(Request $request) {
       $query->get('media_library_opener_id'),
       $query->all('media_library_allowed_types'),
       $query->get('media_library_selected_type'),
+      $query->get('media_library_form_mode'),
       $query->get('media_library_remaining'),
       $query->all('media_library_opener_parameters')
     );
@@ -137,7 +148,7 @@ public static function fromRequest(Request $request) {
    *   If one of the passed arguments is missing or does not pass the
    *   validation.
    */
-  protected function validateRequiredParameters($opener_id, array $allowed_media_type_ids, $selected_type_id, $remaining_slots) {
+  protected function validateRequiredParameters($opener_id, array $allowed_media_type_ids, $selected_type_id, $form_mode, $remaining_slots) {
     // The opener ID must be a non-empty string.
     if (!is_string($opener_id) || empty(trim($opener_id))) {
       throw new \InvalidArgumentException('The opener ID parameter is required and must be a string.');
@@ -157,6 +168,11 @@ protected function validateRequiredParameters($opener_id, array $allowed_media_t
     if (!is_string($selected_type_id) || empty(trim($selected_type_id))) {
       throw new \InvalidArgumentException('The selected type parameter is required and must be a string.');
     }
+    // The form mode must be a non-empty valid machine name string.
+    if (!is_string($form_mode) || empty(trim($form_mode)
+        || preg_match('@[^a-z0-9_]@', $form_mode))) {
+      throw new \InvalidArgumentException('The form mode parameter is required and must be a valid string.');
+    }
     // The selected type ID must be present in the list of allowed types.
     if (!in_array($selected_type_id, $allowed_media_type_ids, TRUE)) {
       throw new \InvalidArgumentException('The selected type parameter must be present in the list of allowed types.');
@@ -187,6 +203,7 @@ public function getHash() {
       $this->getOpenerId(),
       implode(':', $allowed_media_type_ids),
       $this->getSelectedTypeId(),
+      $this->getFormModeId(),
       $this->getAvailableSlots(),
       serialize($opener_parameters),
     ]);
@@ -237,6 +254,16 @@ public function getSelectedTypeId() {
     return $this->get('media_library_selected_type');
   }
 
+  /**
+   * Returns the form mode for the media's add media form.
+   *
+   * @return string
+   *   The form mode machine id.
+   */
+  public function getFormModeId() {
+    return $this->get('media_library_form_mode');
+  }
+
   /**
    * Determines if additional media items can be selected.
    *
diff --git a/core/modules/media_library/src/MediaLibraryUiBuilder.php b/core/modules/media_library/src/MediaLibraryUiBuilder.php
index fb5d5c41c0..05f8f66390 100644
--- a/core/modules/media_library/src/MediaLibraryUiBuilder.php
+++ b/core/modules/media_library/src/MediaLibraryUiBuilder.php
@@ -239,7 +239,14 @@ protected function buildMediaTypeMenu(MediaLibraryState $state) {
 
     $selected_type_id = $state->getSelectedTypeId();
     foreach ($allowed_types as $allowed_type_id => $allowed_type) {
-      $link_state = MediaLibraryState::create($state->getOpenerId(), $state->getAllowedTypeIds(), $allowed_type_id, $state->getAvailableSlots(), $state->getOpenerParameters());
+      $link_state = MediaLibraryState::create(
+        $state->getOpenerId(),
+        $state->getAllowedTypeIds(),
+        $allowed_type_id,
+        $state->getFormModeId(),
+        $state->getAvailableSlots(),
+        $state->getOpenerParameters());
+
       // Add the 'media_library_content' parameter so the response will contain
       // only the updated content for the tab.
       // @see self::buildUi()
@@ -247,11 +254,15 @@ protected function buildMediaTypeMenu(MediaLibraryState $state) {
 
       $title = $allowed_type->label();
       $display_title = [
-        '#markup' => $this->t('<span class="visually-hidden">Show </span>@title<span class="visually-hidden"> media</span>', ['@title' => $title]),
+        '#markup' => $this->t(
+          '<span class="visually-hidden">Show </span>@title<span class="visually-hidden"> media</span>',
+          ['@title' => $title]),
       ];
       if ($allowed_type_id === $selected_type_id) {
         $display_title = [
-          '#markup' => $this->t('<span class="visually-hidden">Show </span>@title<span class="visually-hidden"> media</span><span class="active-tab visually-hidden"> (selected)</span>', ['@title' => $title]),
+          '#markup' => $this->t(
+            '<span class="visually-hidden">Show </span>@title<span class="visually-hidden"> media</span><span class="active-tab visually-hidden"> (selected)</span>',
+            ['@title' => $title]),
         ];
       }
 
@@ -285,7 +296,9 @@ protected function buildMediaTypeMenu(MediaLibraryState $state) {
   protected function buildMediaTypeAddForm(MediaLibraryState $state) {
     $selected_type_id = $state->getSelectedTypeId();
 
-    $access_handler = $this->entityTypeManager->getAccessControlHandler('media');
+    $access_handler = $this->entityTypeManager
+      ->getAccessControlHandler('media');
+
     $context = [
       'media_library_state' => $state,
     ];
@@ -293,7 +306,10 @@ protected function buildMediaTypeAddForm(MediaLibraryState $state) {
       return [];
     }
 
-    $selected_type = $this->entityTypeManager->getStorage('media_type')->load($selected_type_id);
+    $selected_type = $this->entityTypeManager
+      ->getStorage('media_type')
+      ->load($selected_type_id);
+
     $plugin_definition = $selected_type->getSource()->getPluginDefinition();
 
     if (empty($plugin_definition['forms']['media_library_add'])) {
@@ -310,7 +326,9 @@ protected function buildMediaTypeAddForm(MediaLibraryState $state) {
       $state->remove('_media_library_form_rebuild');
     }
     $form_state->set('media_library_state', $state);
-    return $this->formBuilder->buildForm($plugin_definition['forms']['media_library_add'], $form_state);
+
+    $form_class = $plugin_definition['forms']['media_library_add'];
+    return $this->formBuilder->buildForm($form_class, $form_state);
   }
 
   /**
diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
index abecd54dc1..914319b0d3 100644
--- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
+++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
@@ -9,6 +9,7 @@
 use Drupal\Core\Ajax\InvokeCommand;
 use Drupal\Core\Ajax\OpenModalDialogCommand;
 use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
@@ -66,6 +67,13 @@ class MediaLibraryWidget extends WidgetBase implements TrustedCallbackInterface
    */
   protected $moduleHandler;
 
+  /**
+   * The entity display repository.
+   *
+   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
+   */
+  protected $entityDisplayRepository;
+
   /**
    * Constructs a MediaLibraryWidget widget.
    *
@@ -86,11 +94,12 @@ class MediaLibraryWidget extends WidgetBase implements TrustedCallbackInterface
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user, ModuleHandlerInterface $module_handler) {
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user, ModuleHandlerInterface $module_handler, EntityDisplayRepositoryInterface $entity_display_repository) {
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
     $this->entityTypeManager = $entity_type_manager;
     $this->currentUser = $current_user;
     $this->moduleHandler = $module_handler;
+    $this->entityDisplayRepository = $entity_display_repository;
   }
 
   /**
@@ -105,7 +114,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration['third_party_settings'],
       $container->get('entity_type.manager'),
       $container->get('current_user'),
-      $container->get('module_handler')
+      $container->get('module_handler'),
+      $container->get('entity_display.repository')
     );
   }
 
@@ -122,6 +132,7 @@ public static function isApplicable(FieldDefinitionInterface $field_definition)
   public static function defaultSettings() {
     return [
       'media_types' => [],
+      'form_mode' => 'media_library',
     ] + parent::defaultSettings();
   }
 
@@ -148,7 +159,9 @@ protected function getAllowedMediaTypeIdsSorted() {
 
     // When no target bundles are configured for the field, all are allowed.
     if ($allowed_media_type_ids === NULL) {
-      $allowed_media_type_ids = $this->entityTypeManager->getStorage('media_type')->getQuery()->execute();
+      $allowed_media_type_ids = $this->entityTypeManager
+        ->getStorage('media_type')
+        ->getQuery()->execute();
     }
 
     // When the user did not sort the media types, return the media type IDs
@@ -157,7 +170,7 @@ protected function getAllowedMediaTypeIdsSorted() {
       return $allowed_media_type_ids;
     }
 
-    // Some of the media types may no longer exist, and new media types may have
+    // Some media types may no longer exist, and new media types may have
     // been added that we don't yet know about. We need to make sure new media
     // types are added to the list and remove media types that are no longer
     // configured for the field.
@@ -198,7 +211,10 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#value_callback' => [static::class, 'setMediaTypesValue'],
     ];
 
-    $media_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple($media_type_ids);
+    $media_types = $this->entityTypeManager
+      ->getStorage('media_type')
+      ->loadMultiple($media_type_ids);
+
     $weight = 0;
     foreach ($media_types as $media_type_id => $media_type) {
       $label = $media_type->label();
@@ -217,6 +233,17 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       $weight++;
     }
 
+    $form_modes = $this->entityDisplayRepository
+      ->getFormModeOptions('media');
+
+    $elements['form_mode'] = [
+      '#type' => 'select',
+      '#options' => $form_modes,
+      '#title' => $this->t('New Media Form mode'),
+      '#default_value' => $this->getSetting('form_mode'),
+      '#required' => TRUE,
+    ];
+
     return $elements;
   }
 
@@ -263,13 +290,23 @@ public static function setMediaTypesValue(array &$element, $input, FormStateInte
   public function settingsSummary() {
     $summary = [];
     $media_type_labels = [];
-    $media_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple($this->getAllowedMediaTypeIdsSorted());
+    $media_types = $this->entityTypeManager
+      ->getStorage('media_type')
+      ->loadMultiple($this->getAllowedMediaTypeIdsSorted());
+
+    $form_modes = $this->entityDisplayRepository
+      ->getFormModeOptions('media');
+    $mode = $this->getSetting('form_mode');
+    $summary[] = $this->t('Form mode: @mode',
+      ['@mode' => $form_modes[$mode]]);
+
     if (count($media_types) !== 1) {
       foreach ($media_types as $media_type) {
         $media_type_labels[] = $media_type->label();
       }
       $summary[] = $this->t('Tab order: @order', ['@order' => implode(', ', $media_type_labels)]);
     }
+
     return $summary;
   }
 
@@ -452,13 +489,16 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       ];
     }
 
-    $cardinality_unlimited = ($element['#cardinality'] === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+    $cardinality_unlimited =
+      ($element['#cardinality'] === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
     $remaining = $element['#cardinality'] - count($referenced_entities);
 
     // Inform the user of how many items are remaining.
     if (!$cardinality_unlimited) {
       if ($remaining) {
-        $cardinality_message = $this->formatPlural($remaining, 'One media item remaining.', '@count media items remaining.');
+        $cardinality_message = $this->formatPlural($remaining,
+          'One media item remaining.',
+          '@count media items remaining.');
       }
       else {
         $cardinality_message = $this->t('The maximum number of media items have been selected.');
@@ -473,7 +513,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
 
     // Create a new media library URL with the correct state parameters.
     $selected_type_id = reset($allowed_media_type_ids);
-    $remaining = $cardinality_unlimited ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : $remaining;
+    $remaining = $cardinality_unlimited
+      ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
+      : $remaining;
+
     // This particular media library opener needs some extra metadata for its
     // \Drupal\media_library\MediaLibraryOpenerInterface::getSelectionResponse()
     // to be able to target the element whose 'data-media-library-widget-value'
@@ -496,7 +539,17 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
         $opener_parameters['revision_id'] = (string) $entity->getRevisionId();
       }
     }
-    $state = MediaLibraryState::create('media_library.opener.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining, $opener_parameters);
+
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = $this->getSetting('form_mode') ?? 'media_library';
+
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      $allowed_media_type_ids,
+      $selected_type_id,
+      $form_mode,
+      $remaining,
+      $opener_parameters);
 
     // Add a button that will load the Media library in a modal using AJAX.
     $element['open_button'] = [
@@ -530,8 +583,12 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     // JavaScript by adding the 'data-disabled-focus' attribute.
     // @see Drupal.behaviors.MediaLibraryWidgetDisableButton
     if (!$cardinality_unlimited && $remaining === 0) {
+
       $triggering_element = $form_state->getTriggeringElement();
-      if ($triggering_element && ($trigger_parents = $triggering_element['#array_parents']) && end($trigger_parents) === 'media_library_update_widget') {
+      if ($triggering_element
+        && ($trigger_parents = $triggering_element['#array_parents'])
+        && end($trigger_parents) === 'media_library_update_widget')
+      {
         // The widget is being rebuilt from a selection change.
         $element['open_button']['#attributes']['data-disabled-focus'] = 'true';
         $element['open_button']['#attributes']['class'][] = 'visually-hidden';
@@ -746,7 +803,9 @@ public static function updateWidget(array $form, FormStateInterface $form_state)
     // here.
     // @see Drupal.behaviors.MediaLibraryWidgetDisableButton
     elseif ($removed_last || (!$is_remove_button && !isset($element['open_button']['#attributes']['data-disabled-focus']))) {
-      $response->addCommand(new InvokeCommand("#$wrapper_id .js-media-library-open-button", 'focus'));
+      $response->addCommand(
+        new InvokeCommand("#$wrapper_id .js-media-library-open-button", 'focus')
+      );
     }
 
     return $response;
@@ -880,7 +939,8 @@ public static function addItems(array $form, FormStateInterface $form_state) {
     $parents[] = 'selection';
     NestedArray::setValue($form_state->getUserInput(), $parents, NULL);
 
-    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
+    $element = NestedArray::getValue($form,
+      array_slice($button['#array_parents'], 0, -1));
 
     $field_state = static::getFieldState($element, $form_state);
 
@@ -1001,7 +1061,8 @@ public static function validateRequired(array $element, FormStateInterface $form
     // the Form API's default validation would also catch this, the validation
     // error message is too vague, so a more precise one is provided here.
     if (count($field_state['items']) === 0) {
-      $form_state->setError($element, new TranslatableMarkup('@name field is required.', ['@name' => $element['#title']]));
+      $form_state->setError($element,
+        new TranslatableMarkup('@name field is required.', ['@name' => $element['#title']]));
     }
   }
 
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/EmbeddedFormWidgetTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/EmbeddedFormWidgetTest.php
index cb284610fa..dea5f4e24c 100644
--- a/core/modules/media_library/tests/src/FunctionalJavascript/EmbeddedFormWidgetTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/EmbeddedFormWidgetTest.php
@@ -70,6 +70,7 @@ protected function setUp(): void {
         'region' => 'content',
         'settings' => [
           'media_types' => ['type_three'],
+          'form_mode' => 'media_library',
         ],
       ])
       ->save();
@@ -103,6 +104,7 @@ public function testInsertionAndReselection($widget) {
         'region' => 'content',
         'settings' => [
           'media_types' => ['type_three'],
+          'form_mode' => 'media_library',
         ],
       ])
       ->save();
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/WidgetAccessTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/WidgetAccessTest.php
index c7a96e635b..541db80231 100644
--- a/core/modules/media_library/tests/src/FunctionalJavascript/WidgetAccessTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/WidgetAccessTest.php
@@ -58,15 +58,24 @@ public function testWidgetAccess() {
     $role->revokePermission('view media');
     $role->save();
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     // Create a working state.
     $allowed_types = ['type_one', 'type_two', 'type_three', 'type_four'];
     // The opener parameters are not relevant to the test, but the opener
     // expects them to be there or it will deny access.
-    $state = MediaLibraryState::create('media_library.opener.field_widget', $allowed_types, 'type_three', 2, [
-      'entity_type_id' => 'node',
-      'bundle' => 'basic_page',
-      'field_name' => 'field_unlimited_media',
-    ]);
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      $allowed_types, 'type_three',
+      $form_mode,
+      2,
+      [
+        'entity_type_id' => 'node',
+        'bundle' => 'basic_page',
+        'field_name' => 'field_unlimited_media',
+      ]
+    );
     $url_options = ['query' => $state->all()];
 
     // Verify that unprivileged users can't access the widget view.
@@ -125,6 +134,9 @@ public function testWidgetAccess() {
     $this->drupalGet('media-library', [
       'query' => array_merge($url_options['query'], ['media_library_selected_type' => 'type_one']),
     ]);
+    $this->drupalGet('media-library', [
+      'query' => array_merge($url_options['query'], ['media_library_form_mode' => '   ']),
+    ]);
     $assert_session->responseContains('Access denied');
     $this->drupalGet('media-library', [
       'query' => array_merge($url_options['query'], ['media_library_remaining' => 3]),
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
index 2b582a8263..cdcc3e9db5 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
@@ -108,12 +108,22 @@ public function testFieldWidgetEntityCreateAccess() {
     /** @var \Drupal\media_library\MediaLibraryUiBuilder $ui_builder */
     $ui_builder = $this->container->get('media_library.ui_builder');
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     // Create a media library state to test access.
-    $state = MediaLibraryState::create('media_library.opener.field_widget', ['file', 'image'], 'file', 2, [
-      'entity_type_id' => 'entity_test',
-      'bundle' => 'test',
-      'field_name' => 'field_test_media',
-    ]);
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      ['file', 'image'],
+      'file',
+      $form_mode,
+      2,
+      [
+        'entity_type_id' => 'entity_test',
+        'bundle' => 'test',
+        'field_name' => 'field_test_media',
+      ]
+    );
 
     $access_result = $ui_builder->checkAccess($this->createUser(), $state);
     $this->assertAccess($access_result, FALSE, "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create test entity_test_with_bundle entities'.", [], ['url.query_args', 'user.permissions']);
@@ -158,10 +168,14 @@ public function testEditorOpenerAccess($media_embed_enabled, $can_use_format) {
       $permissions[] = $format->getPermissionName();
     }
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     $state = MediaLibraryState::create(
       'media_library.opener.editor',
       ['image'],
       'image',
+      $form_mode,
       1,
       ['filter_format_id' => $format->id()]
     );
@@ -213,13 +227,23 @@ public function testFieldWidgetEntityEditAccess() {
     ]);
     $forbidden_entity->save();
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     // Create a media library state to test access.
-    $state = MediaLibraryState::create('media_library.opener.field_widget', ['file', 'image'], 'file', 2, [
-      'entity_type_id' => $forbidden_entity->getEntityTypeId(),
-      'bundle' => $forbidden_entity->bundle(),
-      'field_name' => 'field_test_media',
-      'entity_id' => $forbidden_entity->id(),
-    ]);
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      ['file', 'image'],
+      'file',
+      $form_mode,
+      2,
+      [
+        'entity_type_id' => $forbidden_entity->getEntityTypeId(),
+        'bundle' => $forbidden_entity->bundle(),
+        'field_name' => 'field_test_media',
+        'entity_id' => $forbidden_entity->id(),
+      ]
+    );
 
     $access_result = $ui_builder->checkAccess($this->createUser(), $state);
     $this->assertAccess($access_result, FALSE, NULL, [], ['url.query_args']);
@@ -238,6 +262,7 @@ public function testFieldWidgetEntityEditAccess() {
       $state->getOpenerId(),
       $state->getAllowedTypeIds(),
       $state->getSelectedTypeId(),
+      $state->getFormModeId(),
       $state->getAvailableSlots(),
       $parameters
     );
@@ -302,8 +327,17 @@ public function testFieldWidgetEntityFieldAccess(string $field_type) {
     // so that we can be certain that field access is checked.
     $account = $this->createUser(['administer entity_test content']);
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     // Test that access is denied even without an entity to work with.
-    $state = MediaLibraryState::create('media_library.opener.field_widget', ['file', 'image'], 'file', 2, [
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      ['file', 'image'],
+      'file',
+      $form_mode,
+      2,
+      [
       'entity_type_id' => 'entity_test',
       'bundle' => 'test',
       'field_name' => $field_storage->getName(),
@@ -325,6 +359,7 @@ public function testFieldWidgetEntityFieldAccess(string $field_type) {
       $state->getOpenerId(),
       $state->getAllowedTypeIds(),
       $state->getSelectedTypeId(),
+      $state->getFormModeId(),
       $state->getAvailableSlots(),
       $parameters
     );
@@ -339,11 +374,20 @@ public function testViewAccess() {
     /** @var \Drupal\media_library\MediaLibraryUiBuilder $ui_builder */
     $ui_builder = $this->container->get('media_library.ui_builder');
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     // Create a media library state to test access.
-    $state = MediaLibraryState::create('media_library.opener.field_widget', ['file', 'image'], 'file', 2, [
-      'entity_type_id' => 'entity_test',
-      'bundle' => 'test',
-      'field_name' => 'field_test_media',
+    $state = MediaLibraryState::create(
+      'media_library.opener.field_widget',
+      ['file', 'image'],
+      'file',
+      $form_mode,
+      2,
+      [
+        'entity_type_id' => 'entity_test',
+        'bundle' => 'test',
+        'field_name' => 'field_test_media',
     ]);
 
     // Create a clone of the view so we can reset the original later.
@@ -401,17 +445,20 @@ public function testAddFormAccess(): void {
       $this->createMediaType('image')->id(),
     ];
 
+    // @todo where should this be pulled from? The field widget specifies.
+    $form_mode = 'media_library';
+
     $account = $this->createUser(['create media']);
     $this->setCurrentUser($account);
 
     /** @var \Drupal\media_library\MediaLibraryUiBuilder $ui_builder */
     $ui_builder = $this->container->get('media_library.ui_builder');
 
-    $state = MediaLibraryState::create('test', $media_types, $media_types[0], 1);
+    $state = MediaLibraryState::create('test', $media_types, $media_types[0], $form_mode, 1);
     $build = $ui_builder->buildUi($state);
     $this->assertEmpty($build['content']['form']);
 
-    $state = MediaLibraryState::create('test', $media_types, $media_types[1], 1);
+    $state = MediaLibraryState::create('test', $media_types, $media_types[1], $form_mode, 1);
     $build = $ui_builder->buildUi($state);
     $this->assertNotEmpty($build['content']['form']);
   }
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
index 02628d22bc..9a60be53e5 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
@@ -112,7 +112,7 @@ public function testMediaTypeAddForm() {
    *   The render array for the media library.
    */
   protected function buildLibraryUi($selected_type_id) {
-    $state = MediaLibraryState::create('test', ['image', 'remote_video'], $selected_type_id, -1);
+    $state = MediaLibraryState::create('test', ['image', 'remote_video'], $selected_type_id, $form_mode, -1);
     return \Drupal::service('media_library.ui_builder')->buildUi($state);
   }
 
@@ -130,7 +130,7 @@ public function testFormStateValidation() {
    * Tests the validation of the selected type in the media library add form.
    */
   public function testSelectedTypeValidation() {
-    $state = MediaLibraryState::create('test', ['image', 'remote_video', 'header_image'], 'header_image', -1);
+    $state = MediaLibraryState::create('test', ['image', 'remote_video', 'header_image'], 'header_image', $form_mode, -1);
     $form_state = new FormState();
     $form_state->set('media_library_state', $state);
     $this->expectException(\InvalidArgumentException::class);
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryStateTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryStateTest.php
index bc4419a3b5..7a5ee89559 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryStateTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryStateTest.php
@@ -71,14 +71,14 @@ public function testMethods() {
     $selected_media_type_id = 'image';
     $remaining_slots = 2;
 
-    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_media_type_id, $remaining_slots);
+    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_media_type_id, $form_mode, $remaining_slots);
     $this->assertSame($opener_id, $state->getOpenerId());
     $this->assertSame($allowed_media_type_ids, $state->getAllowedTypeIds());
     $this->assertSame($selected_media_type_id, $state->getSelectedTypeId());
     $this->assertSame($remaining_slots, $state->getAvailableSlots());
     $this->assertTrue($state->hasSlotsAvailable());
 
-    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_media_type_id, 0);
+    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_media_type_id, $form_mode, 0);
     $this->assertFalse($state->hasSlotsAvailable());
   }
 
@@ -105,7 +105,7 @@ public function testCreate($opener_id, array $allowed_media_type_ids, $selected_
       $this->expectException(\InvalidArgumentException::class);
       $this->expectExceptionMessage($exception_message);
     }
-    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_type_id, $remaining_slots);
+    $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_type_id, $form_mode, $remaining_slots);
     $this->assertInstanceOf(MediaLibraryState::class, $state);
 
     // Ensure that the state object carries cache metadata.
@@ -281,7 +281,7 @@ public function providerCreate() {
   public function testFromRequest(array $query_overrides, $exception_expected) {
     // Override the query parameters and verify an exception is thrown when
     // required state parameters are changed.
-    $query = MediaLibraryState::create('test', ['file', 'image'], 'image', 2)->all();
+    $query = MediaLibraryState::create('test', ['file', 'image'], 'image', $form_mode, 2)->all();
     $query = array_merge($query, $query_overrides);
     if ($exception_expected) {
       $this->expectException(BadRequestHttpException::class);
@@ -329,6 +329,7 @@ public function providerFromRequest() {
         'media_library_opener_id' => 'test',
         'media_library_allowed_types' => ['file', 'image'],
         'media_library_selected_type' => 'image',
+        'media_library_form_mode' => 'media_library',
         'media_library_remaining' => 2,
       ],
       FALSE,
@@ -372,7 +373,7 @@ public function providerFromRequest() {
    * @covers ::getOpenerParameters
    */
   public function testOpenerParameters() {
-    $state = MediaLibraryState::create('test', ['file'], 'file', -1, [
+    $state = MediaLibraryState::create('test', ['file'], 'file', $form_mode, -1, [
       'foo' => 'baz',
     ]);
     $this->assertSame(['foo' => 'baz'], $state->getOpenerParameters());
@@ -382,8 +383,8 @@ public function testOpenerParameters() {
    * Tests that hash is unaffected by allowed media type order.
    */
   public function testHashUnaffectedByMediaTypeOrder() {
-    $state1 = MediaLibraryState::create('test', ['file', 'image'], 'image', 2);
-    $state2 = MediaLibraryState::create('test', ['image', 'file'], 'image', 2);
+    $state1 = MediaLibraryState::create('test', ['file', 'image'], 'image', $form_mode, 2);
+    $state2 = MediaLibraryState::create('test', ['image', 'file'], 'image', $form_mode, 2);
     $this->assertSame($state1->getHash(), $state2->getHash());
   }
 
@@ -391,11 +392,11 @@ public function testHashUnaffectedByMediaTypeOrder() {
    * Tests that hash is unaffected by opener parameter order.
    */
   public function testHashUnaffectedByOpenerParamOrder() {
-    $state1 = MediaLibraryState::create('test', ['file'], 'file', -1, [
+    $state1 = MediaLibraryState::create('test', ['file'], 'file', $form_mode, -1, [
       'foo' => 'baz',
       'baz' => 'foo',
     ]);
-    $state2 = MediaLibraryState::create('test', ['file'], 'file', -1, [
+    $state2 = MediaLibraryState::create('test', ['file'], 'file', $form_mode, -1, [
       'baz' => 'foo',
       'foo' => 'baz',
     ]);
