diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 539cce8..351cf07 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1065,6 +1065,8 @@ function comment_load($cid, $reset = FALSE) {
 /**
  * Gets the number of new comments for the current user and the specified node.
  *
+ * @deprecated Use \Drupal\comment\CommentManager::getCountNewComments()
+ *
  * @param int $entity_id
  *   Entity ID of the entity to which the comments are attached.
  * @param string $entity_type
@@ -1078,45 +1080,8 @@ function comment_load($cid, $reset = FALSE) {
  *   The number of new comments or FALSE if the user is not logged in.
  */
 function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestamp = 0) {
-  if (\Drupal::currentUser()->isAuthenticated() && \Drupal::moduleHandler()->moduleExists('history')) {
-    // Retrieve the timestamp at which the current user last viewed this entity.
-    if (!$timestamp) {
-      if ($entity_type == 'node') {
-        $timestamp = history_read($entity_id);
-      }
-      else {
-        $function = $entity_type . '_last_viewed';
-        if (function_exists($function)) {
-          $timestamp = $function($entity_id);
-        }
-        else {
-          // Default to 30 days ago.
-          // @todo Remove once http://drupal.org/node/1029708 lands.
-          $timestamp = COMMENT_NEW_LIMIT;
-        }
-      }
-    }
-    $timestamp = ($timestamp > HISTORY_READ_LIMIT ? $timestamp : HISTORY_READ_LIMIT);
-
-    // Use the timestamp to retrieve the number of new comments.
-    $query = db_select('comment', 'c');
-    $query->addExpression('COUNT(cid)');
-    $query->condition('c.entity_type', $entity_type)
-      ->condition('c.entity_id', $entity_id)
-      ->condition('c.status', CommentInterface::PUBLISHED)
-      ->condition('c.created', $timestamp, '>');
-    if ($field_name) {
-      // Limit to a particular field.
-      $query->condition('c.field_id', $entity_type . '__' . $field_name);
-    }
-
-    return $query->execute()
-      ->fetchField();
-  }
-  else {
-    return FALSE;
-  }
-
+  $entity = entity_load($entity_type, $entity_id);
+  return \Drupal::service('comment.manager')->getCountNewComments($entity, $field_name, $timestamp);
 }
 
 /**
diff --git a/core/modules/comment/comment.services.yml b/core/modules/comment/comment.services.yml
index 8524045..e4edfef 100644
--- a/core/modules/comment/comment.services.yml
+++ b/core/modules/comment/comment.services.yml
@@ -7,7 +7,7 @@ services:
 
   comment.manager:
     class: Drupal\comment\CommentManager
-    arguments: ['@field.info', '@entity.manager', '@current_user', '@config.factory', '@string_translation', '@url_generator']
+    arguments: ['@field.info', '@entity.manager', '@entity.query', '@current_user', '@config.factory', '@string_translation', '@url_generator', '@module_handler]
 
   comment.statistics:
     class: Drupal\comment\CommentStatistics
diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc
index f38f98b..2530a54 100644
--- a/core/modules/comment/comment.tokens.inc
+++ b/core/modules/comment/comment.tokens.inc
@@ -263,7 +263,7 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
           break;
 
         case 'comment-count-new':
-          $replacements[$original] = comment_num_new($entity->id(), $entity->getEntityTypeId());
+          $replacements[$original] = \Drupal::service('comment.manager')->getCountNewComments($entity);
           break;
       }
     }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentManager.php b/core/modules/comment/lib/Drupal/comment/CommentManager.php
index c522fd3..2f64cac 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentManager.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentManager.php
@@ -12,6 +12,8 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
@@ -37,6 +39,13 @@ class CommentManager implements CommentManagerInterface {
   protected $entityManager;
 
   /**
+   * The entity query factory.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
    * The current user.
    *
    * @var \Drupal\Core\Session\AccountInterface $current_user
@@ -72,12 +81,21 @@ class CommentManager implements CommentManagerInterface {
   protected $urlGenerator;
 
   /**
+   * The module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
    * Construct the CommentManager object.
    *
    * @param \Drupal\field\FieldInfo $field_info
    *   The field info service.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager service.
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query factory.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
@@ -86,14 +104,18 @@ class CommentManager implements CommentManagerInterface {
    *   The string translation service.
    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
    *   The url generator service.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler service.
    */
-  public function __construct(FieldInfo $field_info, EntityManagerInterface $entity_manager, AccountInterface $current_user, ConfigFactoryInterface $config_factory, TranslationInterface $translation_manager, UrlGeneratorInterface $url_generator) {
+  public function __construct(FieldInfo $field_info, EntityManagerInterface $entity_manager, QueryFactory $query_factory, AccountInterface $current_user, ConfigFactoryInterface $config_factory, TranslationInterface $translation_manager, UrlGeneratorInterface $url_generator, ModuleHandlerInterface $module_handler) {
     $this->fieldInfo = $field_info;
     $this->entityManager = $entity_manager;
+    $this->queryFactory = $query_factory;
     $this->currentUser = $current_user;
     $this->userConfig = $config_factory->get('user.settings');
     $this->translationManager = $translation_manager;
     $this->urlGenerator = $url_generator;
+    $this->moduleHandler = $module_handler;
   }
 
   /**
@@ -316,6 +338,48 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function getCountNewComments(EntityInterface $entity, $field_name = NULL, $timestamp = 0) {
+    // @todo Replace module handler with optional history service injection
+    //   after http://drupal.org/node/2081585
+    if ($this->currentUser->isAuthenticated() && $this->moduleHandler->moduleExists('history')) {
+      // Retrieve the timestamp at which the current user last viewed this entity.
+      if (!$timestamp) {
+        if ($entity->getEntityTypeId() == 'node') {
+          $timestamp = history_read($entity->id());
+        }
+        else {
+          $function = $entity->getEntityTypeId() . '_last_viewed';
+          if (function_exists($function)) {
+            $timestamp = $function($entity->id());
+          }
+          else {
+            // Default to 30 days ago.
+            // @todo Remove once http://drupal.org/node/1029708 lands.
+            $timestamp = COMMENT_NEW_LIMIT;
+          }
+        }
+      }
+      $timestamp = ($timestamp > HISTORY_READ_LIMIT ? $timestamp : HISTORY_READ_LIMIT);
+
+      // Use the timestamp to retrieve the number of new comments.
+      $query = $this->queryFactory->get('comment')
+        ->condition('entity_type', $entity->getEntityTypeId())
+        ->condition('entity_id', $entity->id())
+        ->condition('created', $timestamp, '>')
+        ->condition('status', CommentInterface::PUBLISHED);
+      if ($field_name) {
+        // Limit to a particular field.
+        $query->condition('field_id', $entity->getEntityTypeId() . '__' . $field_name);
+      }
+
+      return $query->count()->execute();
+    }
+    return FALSE;
+  }
+
+  /**
    * Translates a string to the current language or to a given language.
    *
    * See the t() documentation for details.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
index 52de708..61c35f5 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
@@ -6,8 +6,8 @@
  */
 
 namespace Drupal\comment;
-use Drupal\Core\Entity\EntityInterface;
 
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
 
 /**
@@ -106,4 +106,19 @@ public function getFieldUIPageTitle($commented_entity_type, $field_name);
    */
   public function forbiddenMessage(EntityInterface $entity, $field_name);
 
+  /**
+   * Returns the number of new comments available on a given entity for a user.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity to which the comments are attached to.
+   * @param string $field_name
+   *   The field_name to count comments for. Defaults to any field.
+   * @param int $timestamp
+   *   Time to count from. Defaults to time of last user access the entity.
+   *
+   * @return int|false
+   *   The number of new comments or FALSE if the user is not authenticated.
+   */
+  public function getCountNewComments(EntityInterface $entity, $field_name = NULL, $timestamp = 0);
+
 }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
index 3661080..9e6e68b 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
@@ -312,7 +312,8 @@ protected function alterBuild(array &$build, EntityInterface $comment, EntityVie
    */
   public static function attachNewCommentsLinkMetadata(array $element, array $context) {
     // Build "X new comments" link metadata.
-    $new = (int)comment_num_new($context['entity_id'], $context['entity_type']);
+    $new = \Drupal::service('comment.manager')
+      ->getCountNewComments(entity_load($context['entity_type'], $context['entity_id']));
     // Early-return if there are zero new comments for the current user.
     if ($new === 0) {
       return $element;
diff --git a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
index 7829950..c4a56ff 100644
--- a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
+++ b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
@@ -301,7 +301,7 @@ public function renderNewCommentsNodeLinks(Request $request) {
     $links = array();
     foreach ($nids as $nid) {
       $node = node_load($nid);
-      $new = comment_num_new($node->id(), 'node');
+      $new = $this->commentManager->getCountNewComments($node);
       $query = comment_new_page_count($node->{$field_name}->comment_count, $new, $node);
       $links[$nid] = array(
         'new_comment_count' => (int) $new,
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
index 24a20a9..e42998b 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
@@ -77,7 +77,7 @@ function testCommentInstallAfterContentModule() {
 
     // Drop default comment field added in CommentTestBase::setup().
     entity_load('field_config', 'node.comment')->delete();
-    if ($field = $this->container->get('field.info')->getField('node', 'comment_node_forum')) {
+    if ($field = $this->container->get('field.info')->getField('node', 'comment_forum')) {
       $field->delete();
     }
 
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
index 0d2a4b2..dcd3fb5 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
@@ -106,10 +106,12 @@ function testCommentTokenReplacement() {
     $tests['[entity:comment-count-new]'] = 2;
     // Also test the deprecated legacy token.
     $tests['[node:comment-count]'] = 2;
+    $tests['[node:comment-count-new]'] = 2;
 
     foreach ($tests as $input => $expected) {
       $output = $token_service->replace($input, array('entity' => $node, 'node' => $node), array('langcode' => $language_interface->id));
       $this->assertEqual($output, $expected, format_string('Node comment token %token replaced.', array('%token' => $input)));
     }
   }
+
 }
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 5facc3c..9184134 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -645,7 +645,7 @@ function template_preprocess_forums(&$variables) {
 
         if ($topic->new_replies) {
           $variables['topics'][$id]->new_text = format_plural($topic->new_replies, '1 new post<span class="visually-hidden"> in topic %title</span>', '@count new posts<span class="visually-hidden"> in topic %title</span>', array('%title' => $variables['topics'][$id]->label()));
-          $variables['topics'][$id]->new_url = url('node/' . $topic->id(), array('query' => comment_new_page_count($topic->comment_count, $topic->new_replies, $topic, 'comment_node_forum'), 'fragment' => 'new'));
+          $variables['topics'][$id]->new_url = url('node/' . $topic->id(), array('query' => comment_new_page_count($topic->comment_count, $topic->new_replies, $topic, 'comment_forum'), 'fragment' => 'new'));
         }
 
         // Build table rows from topics.
diff --git a/core/modules/forum/forum.services.yml b/core/modules/forum/forum.services.yml
index 3035062..cd4916d 100644
--- a/core/modules/forum/forum.services.yml
+++ b/core/modules/forum/forum.services.yml
@@ -1,7 +1,7 @@
 services:
   forum_manager:
     class: Drupal\forum\ForumManager
-    arguments: ['@config.factory', '@entity.manager', '@database', '@field.info', '@string_translation']
+    arguments: ['@config.factory', '@entity.manager', '@database', '@field.info', '@string_translation', '@comment.manager']
   forum.breadcrumb.node:
     class: Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder
     arguments: ['@entity.manager', '@config.factory', '@forum_manager']
diff --git a/core/modules/forum/lib/Drupal/forum/ForumManager.php b/core/modules/forum/lib/Drupal/forum/ForumManager.php
index 388dd4a..cababf8 100644
--- a/core/modules/forum/lib/Drupal/forum/ForumManager.php
+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -14,6 +14,7 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\comment\CommentInterface;
+use Drupal\comment\CommentManagerInterface;
 use Drupal\field\FieldInfo;
 use Drupal\node\NodeInterface;
 
@@ -64,6 +65,13 @@ class ForumManager extends DependencySerialization implements ForumManagerInterf
   protected $connection;
 
   /**
+   * The comment manager service.
+   *
+   * @var \Drupal\comment\CommentManagerInterface
+   */
+  protected $commentManager;
+
+  /**
    * Array of last post information keyed by forum (term) id.
    *
    * @var array
@@ -125,13 +133,16 @@ class ForumManager extends DependencySerialization implements ForumManagerInterf
    *   The field info service.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
    *   The translation manager service.
+   * @param \Drupal\comment\CommentManagerInterface $comment_manager
+   *   The comment manager service.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, EntityManagerInterface $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager) {
+  public function __construct(ConfigFactoryInterface $config_factory, EntityManagerInterface $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager, CommentManagerInterface $comment_manager) {
     $this->configFactory = $config_factory;
     $this->entityManager = $entity_manager;
     $this->connection = $connection;
     $this->fieldInfo = $field_info;
     $this->translationManager = $translation_manager;
+    $this->commentManager = $comment_manager;
   }
 
   /**
@@ -238,7 +249,7 @@ public function getTopics($tid, AccountInterface $account) {
         }
         else {
           $history = $this->lastVisit($topic->id(), $account);
-          $topic->new_replies = $this->numberNew($topic->id(), $history);
+          $topic->new_replies = $this->commentManager->getCountNewComments($topic, 'comment_forum', $history);
           $topic->new = $topic->new_replies || ($topic->last_comment_timestamp > $history);
         }
       }
@@ -302,21 +313,6 @@ protected function getTopicOrder($sortby) {
   }
 
   /**
-   * Wraps comment_num_new() in a method.
-   *
-   * @param int $nid
-   *   Node ID.
-   * @param int $timestamp
-   *   Timestamp of last read.
-   *
-   * @return int
-   *   Number of new comments.
-   */
-  protected function numberNew($nid, $timestamp) {
-    return comment_num_new($nid, $timestamp);
-  }
-
-  /**
    * Gets the last time the user viewed a node.
    *
    * @param int $nid
diff --git a/core/modules/forum/tests/Drupal/forum/Tests/ForumManagerTest.php b/core/modules/forum/tests/Drupal/forum/Tests/ForumManagerTest.php
index e1d4a0a..9429592 100644
--- a/core/modules/forum/tests/Drupal/forum/Tests/ForumManagerTest.php
+++ b/core/modules/forum/tests/Drupal/forum/Tests/ForumManagerTest.php
@@ -74,12 +74,17 @@ public function testGetIndex() {
       ->disableOriginalConstructor()
       ->getMock();
 
+    $comment_manager = $this->getMockBuilder('\Drupal\comment\CommentManagerInterface')
+      ->disableOriginalConstructor()
+      ->getMock();
+
     $manager = $this->getMock('\Drupal\forum\ForumManager', array('getChildren'), array(
       $config_factory,
       $entity_manager,
       $connection,
       $field_info,
       $translation_manager,
+      $comment_manager,
     ));
 
     $manager->expects($this->once())
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index 85fa119..450fe31 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -74,7 +74,7 @@ function tracker_page($account = NULL) {
       if ($node->comment_count) {
         $comments = $node->comment_count;
 
-        if ($new = comment_num_new($node->id(), 'node')) {
+        if ($new = \Drupal::service('comment.manager')->getCountNewComments($node)) {
           $comments .= '<br />';
           $comments .= l(format_plural($new, '1 new', '@count new'), 'node/' . $node->id(), array('fragment' => 'new'));
         }
