 .../tests/modules/entity_test/entity_test.module   |  14 +++
 .../entity_test/EntityTestRenderController.php     |  38 +++++++
 .../Plugin/Core/Entity/EntityTestRender.php        |  33 ++++++
 .../lib/Drupal/views/Plugin/views/area/Entity.php  | 115 +++++++++++++++++++++
 .../Drupal/views/Tests/Handler/AreaEntityTest.php  | 114 ++++++++++++++++++++
 .../test_views/views.view.test_entity_area.yml     |  53 ++++++++++
 core/modules/views/views.views.inc                 |  16 +++
 7 files changed, 383 insertions(+)

diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 641083d..9f558b3 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -268,3 +268,17 @@ function entity_test_entity_test_insert($entity) {
 function entity_test_label_callback($entity_type, $entity, $langcode = NULL) {
   return 'label callback ' . $entity->name->value;
 }
+
+/**
+ * Implements hook_entity_view_mode_info().
+ */
+function entity_test_entity_view_mode_info() {
+  $view_modes['entity_test_render']['full'] = array(
+    'label' => t('Full'),
+  );
+  $view_modes['entity_test_render']['test'] = array(
+    'label' => t('Test'),
+  );
+
+  return $view_modes;
+}
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestRenderController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestRenderController.php
new file mode 100644
index 0000000..a333fa9
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestRenderController.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity_test\EntityTestRenderController.
+ */
+
+namespace Drupal\entity_test;
+
+use Drupal\Core\Entity\EntityRenderController;
+
+/**
+ * Defines an entity render controller for a test entity.
+ *
+ * @see \Drupal\entity_test\Plugin\Core\Entity\EntityTestRender
+ */
+class EntityTestRenderController extends EntityRenderController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityRenderController::buildContent().
+   */
+  public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
+    parent::buildContent($entities, $displays, $view_mode, $langcode);
+
+    foreach ($entities as $entity) {
+      $entity->content['label'] = array(
+        '#markup' => check_plain($entity->label()),
+      );
+      $entity->content['separator'] = array(
+        '#markup' => ' | ',
+      );
+      $entity->content['view_mode'] = array(
+        '#markup' => check_plain($view_mode),
+      );
+    }
+  }
+
+}
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestRender.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestRender.php
new file mode 100644
index 0000000..29b42d1
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestRender.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity_test\Plugin\Core\Entity\EntityTestRender.
+ */
+
+namespace Drupal\entity_test\Plugin\Core\Entity;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines a test entity class with a render controller.
+ *
+ * @Plugin(
+ *   id = "entity_test_render",
+ *   label = @Translation("Test render entity"),
+ *   module = "entity_test",
+ *   controller_class = "Drupal\entity_test\EntityTestStorageController",
+ *   render_controller_class = "Drupal\entity_test\EntityTestRenderController",
+ *   base_table = "entity_test",
+ *   fieldable = TRUE,
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid",
+ *     "label" = "name"
+ *   }
+ * )
+ */
+class EntityTestRender extends EntityTest {
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Entity.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Entity.php
new file mode 100644
index 0000000..db5a40c
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Entity.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Plugin\views\area\Entity.
+ */
+
+namespace Drupal\views\Plugin\views\area;
+
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\views\ViewExecutable;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\views\Plugin\views\area\AreaPluginBase;
+
+/**
+ * Provides an area handler which renders an entity in a certain view mode.
+ *
+ * @ingroup views_area_handlers
+ *
+ * @Plugin(
+ *   id = "entity",
+ *   module = "views"
+ * )
+ */
+class Entity extends AreaPluginBase {
+
+  /**
+   * Stores the entity type of the result entities.
+   *
+   * @var string
+   */
+  protected $entityType;
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\area\AreaPluginBase::init().
+   */
+  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
+    parent::init($view, $display, $options);
+    $this->entityType = $this->definition['entity_type'];
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\area\AreaPluginBase::defineOptions().
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+
+    $options['entity_id'] = array('default' => '');
+    $options['view_mode'] = array('default' => '');
+    $options['tokenize'] = array('default' => TRUE, 'bool' => TRUE);
+
+    return $options;
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\area\AreaPluginBase::buildOptionsForm().
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+
+    $options = $this->buildViewModeOptions();
+    $form['view_mode'] = array(
+      '#type' => 'select',
+      '#options' => $options,
+      '#title' => t('View mode'),
+      '#default_value' => $this->options['view_mode'],
+    );
+
+    $form['entity_id'] = array(
+      '#title' => t('ID'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['entity_id'],
+    );
+
+    // Add tokenization form elements.
+    $this->tokenForm($form, $form_state);
+  }
+
+  /**
+   * Return the main options, which are shown in the summary title.
+   *
+   * @return array
+   *   All view modes of the entity type.
+   */
+  protected function buildViewModeOptions() {
+    $options = array();
+    $view_modes = entity_get_view_modes($this->entityType);
+    foreach ($view_modes as $mode => $settings) {
+      $options[$mode] = $settings['label'];
+    }
+
+    return $options;
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\area\AreaPluginBase::render().
+   */
+  function render($empty = FALSE) {
+    if (!$empty || !empty($this->options['empty'])) {
+      $entity_id = $this->options['entity_id'];
+      if ($this->options['tokenize']) {
+        $entity_id = $this->view->style_plugin->tokenize_value($entity_id, 0);
+      }
+      $entity_id = $this->globalTokenReplace($entity_id);
+      if ($entity = entity_load($this->entityType, $entity_id)) {
+        $build = entity_view($entity, $this->options['view_mode']);
+        // @todo Support to just return a render array.
+        return drupal_render($build);
+      }
+    }
+
+    return '';
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/AreaEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/AreaEntityTest.php
new file mode 100644
index 0000000..d665661
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/AreaEntityTest.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Tests\Handler\AreaEntityTest.
+ */
+
+namespace Drupal\views\Tests\Handler;
+
+use Drupal\views\Tests\ViewTestBase;
+use Drupal\views\Tests\ViewUnitTestBase;
+
+/**
+ * Tests the generic entity area handler.
+ *
+ * @see \Drupal\views\Plugin\views\area\Entity
+ */
+class AreaEntityTest extends ViewTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('entity_test');
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_entity_area');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Area: Entity',
+      'description' => 'Tests the generic entity area handler.',
+      'group' => 'Views Handlers',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    $this->enableViewsTestModule();
+  }
+
+  /**
+   * Tests views data for entity area handlers.
+   */
+  public function testEntityAreaData() {
+    $data = $this->container->get('views.views_data')->get('views');
+    $entity_info = $this->container->get('plugin.manager.entity')->getDefinitions();
+
+    $expected_entities = array_filter($entity_info, function($info) {
+      return !empty($info['render_controller_class']);
+    });
+
+    // Test that all expected entity types have data.
+    foreach (array_keys($expected_entities) as $entity) {
+      $this->assertTrue(!empty($data['entity_' . $entity]), format_string('Views entity area data found for @entity', array('@entity' => $entity)));
+      // Test that entity_type is set correctly in the area data.
+      $this->assertEqual($entity, $data['entity_' . $entity]['area']['entity_type'], format_string('Correct entity_type set for @entity', array('@entity' => $entity)));
+    }
+
+    $expected_entities = array_filter($entity_info, function($info) {
+      return empty($info['render_controller_class']);
+    });
+
+    // Test that no configuration entity types have data.
+    foreach (array_keys($expected_entities) as $entity) {
+      $this->assertTrue(empty($data['entity_' . $entity]), format_string('Views config entity area data not found for @entity', array('@entity' => $entity)));
+    }
+  }
+
+  /**
+   * Tests the area handler.
+   */
+  public function testEntityArea() {
+
+    $entities = array();
+    for ($i = 0; $i < 2; $i++) {
+      $random_label = $this->randomName();
+      $data = array('bundle' => 'entity_test_render', 'name' => $random_label);
+      $entity_test = $this->container->get('plugin.manager.entity')->getStorageController('entity_test_render')->create($data);
+      $entity_test->save();
+      $entities[] = $entity_test;
+    }
+
+    $view = views_get_view('test_entity_area');
+    $this->drupalSetContent($view->preview('default', array($entities[1]->id())));
+
+    $result = $this->xpath('//div[@class = "view-header"]');
+    $this->assertTrue(strpos(trim((string) $result[0]), $entities[0]->label()) !== FALSE, 'The rendered entity appears in the header of the view.');
+    $this->assertTrue(strpos(trim((string) $result[0]), 'full') !== FALSE, 'The rendered entity appeared in the right view mode.');
+
+    $result = $this->xpath('//div[@class = "view-footer"]');
+    $this->assertTrue(strpos(trim((string) $result[0]), $entities[1]->label()) !== FALSE, 'The rendered entity appears in the header of the view.');
+    $this->assertTrue(strpos(trim((string) $result[0]), 'full') !== FALSE, 'The rendered entity appeared in the right view mode.');
+
+    // Change the view mode of the area handler.
+    $view = views_get_view('test_entity_area');
+    $item = $view->getItem('default', 'header', 'entity_entity_test_render');
+    $item['view_mode'] = 'test';
+    $view->setItem('default', 'header', 'entity_entity_test_render', $item);
+
+    $this->drupalSetContent($view->preview('default', array($entities[1]->id())));
+
+    $result = $this->xpath('//div[@class = "view-header"]');
+    $this->assertTrue(strpos(trim((string) $result[0]), $entities[0]->label()) !== FALSE, 'The rendered entity appears in the header of the view.');
+    $this->assertTrue(strpos(trim((string) $result[0]), 'test') !== FALSE, 'The rendered entity appeared in the right view mode.');
+  }
+
+}
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_area.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_area.yml
new file mode 100644
index 0000000..c836c82
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_area.yml
@@ -0,0 +1,53 @@
+base_table: views_test_data
+core: '8'
+description: ''
+status: '1'
+display:
+  default:
+    display_options:
+      defaults:
+        fields: '0'
+        pager: '0'
+        pager_options: '0'
+        sorts: '0'
+      header:
+        entity_entity_test_render:
+          field: entity_entity_test_render
+          id: entity_entity_test_render
+          table: views
+          entity_id: 1
+          view_mode: full
+          plugin_id: entity
+      footer:
+        entity_entity_test_render:
+          field: entity_entity_test_render
+          id: entity_entity_test_render
+          table: views
+          entity_id: !1
+          view_mode: full
+          plugin_id: entity
+      fields:
+        id:
+          field: id
+          id: id
+          relationship: none
+          table: views_test_data
+          plugin_id: numeric
+      arguments:
+        id:
+          id: id
+          table: views_test_data
+          field: id
+          plugin_id: numeric
+      pager:
+        options:
+          offset: '0'
+        type: none
+      pager_options: {  }
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: '0'
+human_name: ''
+id: test_entity_area
+tag: ''
diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc
index 3a145b2..f2178ab 100644
--- a/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc
@@ -106,5 +106,21 @@ function views_views_data() {
     ),
   );
 
+  // Registers an entity area handler per entity type.
+  foreach (entity_get_info() as $entity_type => $entity_info) {
+    // Exclude entity types, which cannot be rendered.
+    if (!empty($entity_info['render_controller_class'])) {
+      $label = $entity_info['label'];
+      $data['views']['entity_' . $entity_type] = array(
+        'title' => t('Rendered entity - @label', array('@label' => $label)),
+        'help' => t('Displays a rendered @label entity in an area.', array('@label' => $label)),
+        'area' => array(
+          'entity_type' => $entity_type,
+          'id' => 'entity',
+        ),
+      );
+    }
+  }
+
   return $data;
 }
