diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/RevisionLinkTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/RevisionLinkTest.php
new file mode 100644
index 0000000..d034b07
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Tests/Views/RevisionLinkTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\node\Tests\Views\RevisionLink.
+ */
+
+namespace Drupal\node\Tests\Views;
+
+/**
+ * Tests the different revision link handlers.
+ *
+ * @see \Drupal\node\Plugin\views\field\Revision
+ * @see \Drupal\node\Plugin\views\field\RevisionLink
+ * @see \Drupal\node\Plugin\views\field\RevisionLinkDelete
+ * @see \Drupal\node\Plugin\views\field\RevisionLinkRevert
+ */
+class RevisionLinkTest extends NodeTestBase {
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_node_revision_links');
+
+  public $nodes = array();
+  public $revisions = array();
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node: Revision Links',
+      'description' => 'Tests the different revision link handlers.',
+      'group' => 'Views module integration',
+    );
+  }
+
+  /**
+   * Tests revision links.
+   */
+  public function testRevisionLinks() {
+    // Create one user which can view/revert and delete and one which can only
+    // one of them.
+    $this->drupalCreateContentType(array('name' => 'page', 'type' => 'page'));
+    $account = $this->drupalCreateUser(array('revert all revisions', 'view all revisions', 'delete all revisions', 'edit any page content', 'delete any page content'));
+    $this->drupalLogin($account);
+
+    // Create two nodes, one without an additional revision and one with a
+    // revision.
+    $this->nodes[] = $node = $this->drupalCreateNode();
+    $this->revisions[] = $node;
+
+    $this->nodes[] = $node = $this->drupalCreateNode();
+    $this->revisions[] = $node;
+    $node = clone $node;
+    $node->setNewRevision();
+    $this->revisions[] = $node;
+    $node->save();
+
+    $this->drupalGet('test-node-revision-links');
+    $this->assertResponse(200, 'Test view can be accessed in the path expected');
+
+    // The first node revision should link to the node directly as you get a
+    // access denied if you link to the revision.
+    $path = $this->nodes[0]->getSystemPath();
+    $this->assertLinkByHref($path);
+    $this->assertNoLinkByHref($path . '/revisions/' . $this->revisions[0]->getRevisionId() . '/delete');
+    $this->assertNoLinkByHref($path . '/revision/' . $this->revisions[0]->getRevisionId() . '/revert');
+
+    // For the second node the current revision got set to the last revision, so
+    // the first one should also link to the node page itself.
+    $path = $this->revisions[1]->getSystemPath();
+    $this->assertLinkByHref($path . '/revisions/' . $this->revisions[1]->getRevisionId() . '/view');
+    $this->assertLinkByHref($path . '/revisions/' . $this->revisions[1]->getRevisionId() . '/delete');
+    $this->assertLinkByHref($path . '/revisions/' . $this->revisions[1]->getRevisionId() . '/revert');
+
+    $path = $this->revisions[2]->getSystemPath();
+    $this->assertLinkByHref($path);
+    $this->assertNoLinkByHref($path . '/revisions/' . $this->revisions[2]->getRevisionId() . '/delete');
+    $this->assertNoLinkByHref($path . '/revisions/' . $this->revisions[2]->getRevisionId() . '/revert');
+
+    $accounts = array();
+    $accounts['view'] = $this->drupalCreateUser(array('view all revisions'));
+    $accounts['revert'] = $this->drupalCreateUser(array('revert all revisions', 'edit any page content'));
+    $accounts['delete'] = $this->drupalCreateUser(array('delete all revisions', 'delete any page content'));
+
+    $operations = array_keys($accounts);
+    array_shift($operations);
+    $path = $this->revisions[1]->getSystemPath();
+    // Render the view with users which can only delete/revert revisions.
+    foreach ($accounts as $op => $account) {
+      $this->drupalLogin($account);
+      $this->drupalGet('test-node-revision-links');
+
+      // Check expected links.
+      foreach ($operations as $operation) {
+        if ($operation == $op) {
+          $this->assertLinkByHref($path . '/revisions/' . $this->revisions[1]->getRevisionId() . '/' . $operation);
+        }
+        else {
+          $this->assertNoLinkByHref($path . '/revisions/' . $this->revisions[1]->getRevisionId() . '/' . $operation);
+        }
+      }
+    }
+  }
+}
diff --git a/core/modules/node/src/Plugin/views/field/Link.php b/core/modules/node/src/Plugin/views/field/Link.php
index d2a89a4..057c154 100644
--- a/core/modules/node/src/Plugin/views/field/Link.php
+++ b/core/modules/node/src/Plugin/views/field/Link.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\node\Plugin\views\field;
 
+use Drupal\node\NodeInterface;
 use Drupal\views\Plugin\views\field\FieldPluginBase;
 use Drupal\views\ResultRow;
 
@@ -49,6 +50,7 @@ public function buildOptionsForm(&$form, &$form_state) {
    * {@inheritdoc}
    */
   public function query() {
+    $this->ensureMyTable();
     $this->addAdditionalFields();
   }
 
@@ -76,7 +78,7 @@ protected function renderLink($node, ResultRow $values) {
     if ($node->access('view')) {
       $this->options['alter']['make_link'] = TRUE;
       $this->options['alter']['path'] = 'node/' . $node->id();
-      $text = !empty($this->options['text']) ? $this->options['text'] : t('View');
+      $text = !empty($this->options['text']) ? $this->sanitizeValue($this->options['text']) : t('View');
       return $text;
     }
   }
diff --git a/core/modules/node/src/Plugin/views/field/RevisionLink.php b/core/modules/node/src/Plugin/views/field/RevisionLink.php
index 5ea0835..360ae42 100644
--- a/core/modules/node/src/Plugin/views/field/RevisionLink.php
+++ b/core/modules/node/src/Plugin/views/field/RevisionLink.php
@@ -7,11 +7,15 @@
 
 namespace Drupal\node\Plugin\views\field;
 
-use Drupal\Core\Session\AccountInterface;
 use Drupal\node\Plugin\views\field\Link;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Field handler to present a link to a node revision.
@@ -20,22 +24,98 @@
  *
  * @ViewsField("node_revision_link")
  */
-class RevisionLink extends Link {
+class RevisionLink extends Link implements ContainerFactoryPluginInterface {
+
+  /**
+   * Database Service Object.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $database;
+
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
 
   /**
-   * Overrides Drupal\views\Plugin\views\field\FieldPluginBase::init().
+   * The current active user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * An array of revision count of a node keyed by nids.
+   *
+   * @var array
+   */
+  protected $countRevisions;
+
+  /**
+   * Constructs a Drupal\Component\Plugin\PluginBase object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database connection.
+   * @param \Drupal\Core\Entity\EntityManager $entity_manger
+   *   The entity manager service.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current active user.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, Connection $database, EntityManager $entity_manger, AccountInterface $current_user) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->database = $database;
+    $this->entityManager = $entity_manger;
+    $this->currentUser = $current_user;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('database'),
+      $container->get('entity.manager'),
+      $container->get('current_user')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     parent::init($view, $display, $options);
 
-    $this->additional_fields['node_vid'] = array('table' => 'node_revision', 'field' => 'vid');
+    $this->additional_fields[] = 'vid';
+    $this->additional_fields[] = 'nid';
   }
 
   /**
    * {@inheritdoc}
    */
-  public function access(AccountInterface $account) {
-    return $account->hasPermission('view revisions') || $account->hasPermission('administer nodes');
+  public function preRender(&$values) {
+    parent::preRender($values);
+
+    // Count the amount of revisions per node.
+    $nids = array();
+    foreach ($values as $row) {
+      $nids[] = $this->getValue($row, 'nid');
+    }
+
+    if (!empty($nids)) {
+      $this->countRevisions = $this->database->query("SELECT nid, COUNT(vid) as count FROM {node_field_revision} WHERE nid IN (:nids) GROUP BY nid", array(':nids' => array_unique($nids)))->fetchAllKeyed();
+    }
   }
 
   /**
@@ -50,14 +130,11 @@ public function access(AccountInterface $account) {
    *   Returns a string for the link text.
    */
   protected function renderLink($data, ResultRow $values) {
-    list($node, $vid) = $this->get_revision_entity($values, 'view');
-    if (!isset($vid)) {
-      return;
-    }
+    list($node, , $vid) = $this->getRevisionEntity($values, 'view');
 
     // Current revision uses the node view path.
-    $path = 'node/' . $node->nid;
-    if (!$node->isDefaultRevision()) {
+    $path = $node->getSystemPath();
+    if ($this->countRevisions[$node->id()] > 1 && $node->getRevisionId() != $vid) {
       $path .= "/revisions/$vid/view";
     }
 
@@ -71,25 +148,21 @@ protected function renderLink($data, ResultRow $values) {
   /**
    * Returns the revision values of a node.
    *
-   * @param object $values
+   * @param \Drupal\views\ResultRow $values
    *   An object containing all retrieved values.
    * @param string $op
    *   The operation being performed.
    *
    * @return array
-   *   A numerically indexed array containing the current node object and the
-   *   revision ID for this row.
+   *   Containing current node, node revision object and revision ID.
    */
-  function get_revision_entity($values, $op) {
-    $vid = $this->getValue($values, 'node_vid');
-    $node = $this->getEntity($values);
-    // Unpublished nodes ignore access control.
-    $node->setPublished(TRUE);
-    // Ensure user has access to perform the operation on this node.
-    if (!$node->access($op)) {
-      return array($node, NULL);
-    }
-    return array($node, $vid);
+  public function getRevisionEntity(ResultRow $values, $op) {
+    $storage_controller = $this->entityManager->getStorageController('node');
+    $vid = $this->getValue($values, 'vid');
+    $revision_node = $storage_controller->loadRevision($vid);
+    $node = $storage_controller->load($revision_node->id());
+
+    return array($node, $revision_node, $vid);
   }
 
 }
diff --git a/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php b/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php
index a09c00c..10c782d 100644
--- a/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php
+++ b/core/modules/node/src/Plugin/views/field/RevisionLinkDelete.php
@@ -23,9 +23,6 @@ class RevisionLinkDelete extends RevisionLink {
   /**
    * {@inheritdoc}
    */
-  public function access(AccountInterface $account) {
-    return $account->hasPermission('delete revisions') || $account->hasPermission('administer nodes');
-  }
 
   /**
    * Prepares the link to delete a node revision.
@@ -39,13 +36,15 @@ public function access(AccountInterface $account) {
    *   Returns a string for the link text.
    */
   protected function renderLink($data, ResultRow $values) {
-    list($node, $vid) = $this->get_revision_entity($values, 'delete');
-    if (!isset($vid)) {
+    list($node, $revision_node, $vid) = $this->getRevisionEntity($values, 'update');
+
+    $type = $node->getType();
+    if (!(($this->currentUser->hasPermission("delete $type revisions") || $this->currentUser->hasPermission('delete all revisions') || $this->currentUser->hasPermission('administer nodes')) && node_access('delete', $revision_node))) {
       return;
     }
 
     // Current revision cannot be deleted.
-    if ($node->isDefaultRevision()) {
+    if ($node->getRevisionId() == $vid) {
       return;
     }
 
@@ -53,7 +52,7 @@ protected function renderLink($data, ResultRow $values) {
     $this->options['alter']['path'] = 'node/' . $node->id() . "/revisions/$vid/delete";
     $this->options['alter']['query'] = drupal_get_destination();
 
-    return !empty($this->options['text']) ? $this->options['text'] : t('Delete');
+    return !empty($this->options['text']) ? $this->sanitizeValue($this->options['text']) : t('Delete');
   }
 
 }
diff --git a/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php b/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php
index f4f59ff..01ec53b 100644
--- a/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php
+++ b/core/modules/node/src/Plugin/views/field/RevisionLinkRevert.php
@@ -23,9 +23,6 @@ class RevisionLinkRevert extends RevisionLink {
   /**
    * {@inheritdoc}
    */
-  public function access(AccountInterface $account) {
-    return $account->hasPermission('revert revisions') || $account->hasPermission('administer nodes');
-  }
 
   /**
    * Prepares the link to revert node to a revision.
@@ -39,13 +36,15 @@ public function access(AccountInterface $account) {
    *   Returns a string for the link text.
    */
   protected function renderLink($data, ResultRow $values) {
-    list($node, $vid) = $this->get_revision_entity($values, 'update');
-    if (!isset($vid)) {
+    list($node, , $vid) = $this->getRevisionEntity($values, 'update');
+
+    $type = $node->bundle();
+    if (!($access = ($this->currentUser->hasPermission("revert $type revisions") || $this->currentUser->hasPermission('revert all revisions') || $this->currentUser->hasPermission('administer nodes')) && node_access('update', $node))) {
       return;
     }
 
     // Current revision cannot be reverted.
-    if ($node->isDefaultRevision()) {
+    if ($node->getRevisionId() == $vid) {
       return;
     }
 
@@ -53,7 +52,7 @@ protected function renderLink($data, ResultRow $values) {
     $this->options['alter']['path'] = 'node/' . $node->id() . "/revisions/$vid/revert";
     $this->options['alter']['query'] = drupal_get_destination();
 
-    return !empty($this->options['text']) ? $this->options['text'] : t('Revert');
+    return !empty($this->options['text']) ? $this->sanitizeValue($this->options['text']) : t('Revert');
   }
 
 }
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml
new file mode 100644
index 0000000..d387c3e
--- /dev/null
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml
@@ -0,0 +1,221 @@
+base_field: vid
+base_table: node_field_revision
+core: 8.x
+description: ''
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: '1'
+    display_options:
+      cache:
+        type: none
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: '0'
+          distinct: '0'
+          slave: '0'
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: '0'
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: '1'
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: none
+        options:
+          items_per_page: '0'
+          offset: '0'
+      style:
+        type: default
+      row:
+        type: fields
+      fields:
+        link_to_revision:
+          id: link_to_revision
+          table: node_field_revision
+          field: link_to_revision
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Link to revision'
+          exclude: '0'
+          alter:
+            alter_text: '0'
+            text: ''
+            make_link: '0'
+            path: ''
+            absolute: '0'
+            external: '0'
+            replace_spaces: '0'
+            path_case: none
+            trim_whitespace: '0'
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: '0'
+            max_length: ''
+            word_boundary: '1'
+            ellipsis: '1'
+            more_link: '0'
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: '0'
+            trim: '0'
+            preserve_tags: ''
+            html: '0'
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: '1'
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: '1'
+          empty: ''
+          hide_empty: '0'
+          empty_zero: '0'
+          hide_alter_empty: '1'
+          text: ''
+          plugin_id: node_revision_link
+        delete_revision:
+          id: delete_revision
+          table: node_field_revision
+          field: delete_revision
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Link to delete revision'
+          exclude: '0'
+          alter:
+            alter_text: '0'
+            text: ''
+            make_link: '0'
+            path: ''
+            absolute: '0'
+            external: '0'
+            replace_spaces: '0'
+            path_case: none
+            trim_whitespace: '0'
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: '0'
+            max_length: ''
+            word_boundary: '1'
+            ellipsis: '1'
+            more_link: '0'
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: '0'
+            trim: '0'
+            preserve_tags: ''
+            html: '0'
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: '1'
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: '1'
+          empty: ''
+          hide_empty: '0'
+          empty_zero: '0'
+          hide_alter_empty: '1'
+          text: ''
+          plugin_id: node_revision_link_delete
+        revert_revision:
+          id: revert_revision
+          table: node_field_revision
+          field: revert_revision
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Link to revert revision'
+          exclude: '0'
+          alter:
+            alter_text: '0'
+            text: ''
+            make_link: '0'
+            path: ''
+            absolute: '0'
+            external: '0'
+            replace_spaces: '0'
+            path_case: none
+            trim_whitespace: '0'
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: '0'
+            max_length: ''
+            word_boundary: '1'
+            ellipsis: '1'
+            more_link: '0'
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: '0'
+            trim: '0'
+            preserve_tags: ''
+            html: '0'
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: '1'
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: '1'
+          empty: ''
+          hide_empty: '0'
+          empty_zero: '0'
+          hide_alter_empty: '1'
+          text: ''
+          plugin_id: node_revision_link_revert
+      filters:
+        status:
+          value: '1'
+          table: node_field_revision
+          field: status
+          id: status
+          expose:
+            operator: '0'
+          group: '1'
+      sorts: {  }
+      title: test_node_revision_links
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: '1'
+    display_options:
+      path: test-node-revision-links
+label: test_node_revision_links
+module: views
+id: test_node_revision_links
+tag: ''
+uuid: c89579e2-be88-44e6-81f8-6d5e50b81a05
+langcode: en
