diff --git a/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php b/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php
index af1fb6ee37..aee2e23089 100644
--- a/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php
+++ b/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php
@@ -4,6 +4,11 @@
 
 use Drupal\Core\Block\BlockBase;
 use Drupal\Core\Block\TitleBlockPluginInterface;
+use Drupal\Core\Controller\TitleResolverInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Provides a block to display the page title.
@@ -16,17 +21,77 @@
  *   },
  * )
  */
-class PageTitleBlock extends BlockBase implements TitleBlockPluginInterface {
+class PageTitleBlock extends BlockBase implements TitleBlockPluginInterface, ContainerFactoryPluginInterface {
 
   /**
    * The page title: a string (plain title) or a render array (formatted title).
    *
-   * @var string|array
+   * @var string|array|null
    */
-  protected $title = '';
+  protected $title = NULL;
+
+  /**
+   * The request.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * The route match.
+   *
+   * @var \Drupal\Core\Routing\RouteMatchInterface
+   */
+  protected $routeMatch;
+
+  /**
+   * The title resolver.
+   *
+   * @var \Drupal\Core\Controller\TitleResolverInterface
+   */
+  protected $titleResolver;
+
+  /**
+   * Constructs a PageTitleBlock.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
+   * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
+   *   The title resolver.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, Request $request, RouteMatchInterface $route_match, TitleResolverInterface $title_resolver) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->request = $request;
+    $this->routeMatch = $route_match;
+    $this->titleResolver = $title_resolver;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('request_stack')->getCurrentRequest(),
+      $container->get('current_route_match'),
+      $container->get('title_resolver')
+    );
+  }
 
   /**
    * {@inheritdoc}
+   *
+   * @todo Deprecate this method in https://www.drupal.org/node/2359901.
    */
   public function setTitle($title) {
     $this->title = $title;
@@ -46,7 +111,9 @@ public function defaultConfiguration() {
   public function build() {
     return [
       '#type' => 'page_title',
-      '#title' => $this->title,
+      // @todo Always use the title resolver directly after
+      //   https://www.drupal.org/node/2359901 is resolved.
+      '#title' => !is_null($this->title) ? $this->title : $this->titleResolver->getTitle($this->request, $this->routeMatch->getRouteObject()),
     ];
   }
 
diff --git a/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.info.yml b/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.info.yml
new file mode 100644
index 0000000000..cc66e51c32
--- /dev/null
+++ b/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.info.yml
@@ -0,0 +1,6 @@
+name: Page Title Block Test
+type: module
+description: 'Test the Page Title Block.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.routing.yml b/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.routing.yml
new file mode 100644
index 0000000000..74cf4baf96
--- /dev/null
+++ b/core/modules/system/tests/modules/page_title_block_test/page_title_block_test.routing.yml
@@ -0,0 +1,7 @@
+page_title_block_test.test:
+  path: '/page-title-block-test-page'
+  defaults:
+    _title: 'Test page'
+    _controller: '\Drupal\page_title_block_test\Controller\PageBlockTitleTestController::testPage'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/page_title_block_test/src/Controller/PageBlockTitleTestController.php b/core/modules/system/tests/modules/page_title_block_test/src/Controller/PageBlockTitleTestController.php
new file mode 100644
index 0000000000..621eae4569
--- /dev/null
+++ b/core/modules/system/tests/modules/page_title_block_test/src/Controller/PageBlockTitleTestController.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Drupal\page_title_block_test\Controller;
+
+use Drupal\Component\Utility\Html;
+
+/**
+ * A test controller.
+ */
+class PageBlockTitleTestController {
+
+  /**
+   * Returns a page with the page title block embedded.
+   */
+  public function testPage() {
+    /** @var \Drupal\Core\Block\TitleBlockPluginInterface $block */
+    $block = \Drupal::service('plugin.manager.block')->createInstance('page_title_block');
+
+    if ($set_title = \Drupal::state()->get('page_title_block_test.set_title')) {
+      $block->setTitle($set_title);
+    }
+    if ($render_array_title = \Drupal::state()->get('page_title_block_test.render_array_title')) {
+      $build['#title'] = Html::escape($render_array_title);
+    }
+
+    // Nest the block lower than the top-level title.
+    $build[] = $block->build();
+    return $build;
+  }
+
+}
diff --git a/core/tests/Drupal/FunctionalTests/Core/Block/PageTitleBlockTest.php b/core/tests/Drupal/FunctionalTests/Core/Block/PageTitleBlockTest.php
new file mode 100644
index 0000000000..518c018a7c
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/Core/Block/PageTitleBlockTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Drupal\FunctionalTests\Core\Block;
+
+use Behat\Mink\Element\NodeElement;
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Block\Plugin\Block\PageTitleBlock
+ *
+ * @group block
+ */
+class PageTitleBlockTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['page_title_block_test'];
+
+  /**
+   * @covers ::build
+   * @dataProvider providerTestBuild
+   *
+   * @param array $expected
+   *   The expected page titles, in order.
+   * @param string $set_title
+   *   The value to call ::setTitle() with.
+   * @param string $render_array_title
+   *   The value for #title in the render array.
+   */
+  public function testBuild($expected, $set_title, $render_array_title) {
+    \Drupal::state()->set('page_title_block_test.set_title', $set_title);
+    \Drupal::state()->set('page_title_block_test.render_array_title', $render_array_title);
+
+    $this->drupalGet('page-title-block-test-page');
+    $page_titles = array_map(function (NodeElement $element) {
+      return $element->getText();
+    }, $this->getSession()->getPage()->findAll('css', '.page-title'));
+    $this->assertSame($expected, $page_titles);
+  }
+
+  /**
+   * Provides test data for ::testBuild().
+   */
+  public function providerTestBuild() {
+    // Data provider values are:
+    // - the expected page titles, in order
+    // - the value to call ::setTitle() with
+    // - the value for #title in the render array.
+    $data = [];
+    $data['no title manipulation'] = [
+      ['Test page', 'Test page'],
+      NULL,
+      NULL,
+    ];
+    $data['provide a top-level #title'] = [
+      ['render_array_title', 'Test page'],
+      NULL,
+      'render_array_title',
+    ];
+    $data['call setTitle() on the block'] = [
+      ['Test page', 'set_title'],
+      'set_title',
+      NULL,
+    ];
+    $data['call setTitle() on the block and provide a top-level #title'] = [
+      ['render_array_title', 'set_title'],
+      'set_title',
+      'render_array_title',
+    ];
+    return $data;
+  }
+
+}
