diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 5372dc7..7962015 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -184,13 +184,6 @@
 define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);
 
 /**
- * Flag for drupal_set_title(); text has already been sanitized.
- *
- * @todo Move to the Title class.
- */
-const PASS_THROUGH = -1;
-
-/**
  * Regular expression to match PHP function names.
  *
  * @see http://php.net/manual/language.functions.php
@@ -1331,46 +1324,6 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
 }
 
 /**
- * Gets the title of the current page.
- *
- * The title is displayed on the page and in the title bar.
- *
- * @return
- *   The current page's title.
- */
-function drupal_get_title() {
-  return drupal_set_title() ?: '';
-}
-
-/**
- * Sets the title of the current page.
- *
- * The title is displayed on the page and in the title bar.
- *
- * @param $title
- *   Optional string value to assign to the page title; or if set to NULL
- *   (default), leaves the current title unchanged.
- * @param $output
- *   Optional flag - normally should be left as Title::CHECK_PLAIN. Only set to
- *   PASS_THROUGH if you have already removed any possibly dangerous code
- *   from $title using a function like
- *   \Drupal\Component\Utility\String::checkPlain() or filter_xss(). With this
- *   flag the string will be passed through unchanged.
- *
- * @return
- *   The updated title of the current page.
- */
-function drupal_set_title($title = NULL, $output = Title::CHECK_PLAIN) {
-  $stored_title = &drupal_static(__FUNCTION__);
-
-  if (isset($title)) {
-    $stored_title = ($output == PASS_THROUGH) ? $title : String::checkPlain($title);
-  }
-
-  return $stored_title;
-}
-
-/**
  * Generates a default anonymous $user object.
  *
  * @return \Drupal\Core\Session\AccountInterface
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index a58b59a..3298823 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2036,12 +2036,6 @@ function template_preprocess_html(&$variables) {
       'name' => String::checkPlain($site_config->get('name')),
     );
   }
-  elseif (drupal_get_title()) {
-    $head_title = array(
-      'title' => strip_tags(drupal_get_title()),
-      'name' => String::checkPlain($site_config->get('name')),
-    );
-  }
   // @todo Remove once views is not bypassing the view subscriber anymore.
   //   @see http://drupal.org/node/2068471
   elseif (drupal_is_front_page()) {
@@ -2124,6 +2118,7 @@ function template_preprocess_page(&$variables) {
 
   // Move some variables to the top level for themer convenience and template cleanliness.
   $variables['show_messages'] = $variables['page']['#show_messages'];
+  $variables['title'] = $variables['page']['#title'];
 
   foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
     if (!isset($variables['page'][$region_key])) {
@@ -2153,13 +2148,6 @@ function template_preprocess_page(&$variables) {
   $variables['site_slogan']       = (theme_get_setting('features.slogan') ? filter_xss_admin($site_config->get('slogan')) : '');
   $variables['tabs']              = menu_local_tabs();
 
-  if (isset($variables['page']['#title'])) {
-    $variables['title'] = $variables['page']['#title'];
-  }
-  else {
-    $variables['title'] = new RenderWrapper('drupal_get_title');
-  }
-
   // Pass the main menu and secondary menu to the template as render arrays.
   if (!empty($variables['main_menu'])) {
     $variables['main_menu'] = array(
@@ -2344,12 +2332,6 @@ function template_preprocess_maintenance_page(&$variables) {
       'name' => String::checkPlain($site_config->get('name')),
     );
   }
-  elseif (drupal_get_title()) {
-    $head_title = array(
-      'title' => strip_tags(drupal_get_title()),
-      'name' => String::checkPlain($site_config->get('name')),
-    );
-  }
   else {
     $head_title = array('name' => String::checkPlain($site_name));
     if ($site_slogan) {
@@ -2410,9 +2392,6 @@ function template_preprocess_maintenance_page(&$variables) {
   if (isset($variables['page']['#title'])) {
     $variables['title'] = $variables['page']['#title'];
   }
-  if (!isset($variables['title'])) {
-    $variables['title'] = drupal_get_title();
-  }
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Controller/DialogController.php b/core/lib/Drupal/Core/Controller/DialogController.php
index 5fda730..e86b9bd 100644
--- a/core/lib/Drupal/Core/Controller/DialogController.php
+++ b/core/lib/Drupal/Core/Controller/DialogController.php
@@ -93,14 +93,7 @@ public function dialog(Request $request, $_content, $modal = FALSE) {
     }
 
     $content = drupal_render($page_content);
-
-    // @todo Remove use of drupal_get_title() when
-    //  http://drupal.org/node/1871596 is in.
-    if (!$title = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT))) {
-      // @todo Remove use of drupal_get_title() when
-      //  http://drupal.org/node/1871596 is in.
-      $title = drupal_get_title();
-    }
+    $title = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
     $response = new AjaxResponse();
     // Fetch any modal options passed in from data-dialog-options.
     if (!($options = $request->request->get('dialogOptions'))) {
diff --git a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
index 0204bc0..9cc7651 100644
--- a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
+++ b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
@@ -80,7 +80,7 @@ protected function createHtmlFragment($page_content, Request $request) {
       $fragment->setTitle($page_content['#title'], Title::FILTER_XSS_ADMIN);
     }
     else if ($route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) {
-      $fragment->setTitle($this->titleResolver->getTitle($request, $route), PASS_THROUGH);
+      $fragment->setTitle($this->titleResolver->getTitle($request, $route), Title::PASS_THROUGH);
     }
 
     return $fragment;
diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
index 64aed01..6e0c509 100644
--- a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
+++ b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
@@ -74,14 +74,6 @@ public function render(HtmlFragment $fragment, $status_code = 200) {
    *   The modified page object.
    */
   public function preparePage(HtmlPage $page, &$page_array) {
-    // @todo Remove this one drupal_get_title() has been eliminated.
-    if (!$page->hasTitle()) {
-      $title = drupal_get_title();
-      // drupal_set_title() already ensured security, so not letting the
-      // title pass through would cause double escaping.
-      $page->setTitle($title, PASS_THROUGH);
-    }
-
     $page_array['#page'] = $page;
 
     // HTML element attributes.
diff --git a/core/lib/Drupal/Core/Page/HtmlFragment.php b/core/lib/Drupal/Core/Page/HtmlFragment.php
index cc5cac5..cf1ca4d 100644
--- a/core/lib/Drupal/Core/Page/HtmlFragment.php
+++ b/core/lib/Drupal/Core/Page/HtmlFragment.php
@@ -103,8 +103,8 @@ public function getContent() {
    *   Value to assign to the page title.
    * @param int $output
    *   (optional) normally should be left as Title::CHECK_PLAIN. Only set to
-   *   PASS_THROUGH if you have already removed any possibly dangerous code
-   *   from $title using a function like
+   *   Title::PASS_THROUGH if you have already removed any possibly dangerous
+   *   code from $title using a function like
    *   \Drupal\Component\Utility\String::checkPlain() or
    *   \Drupal\Component\Utility\Xss::filterAdmin(). With this flag the string
    *   will be passed through unchanged.
diff --git a/core/lib/Drupal/Core/Utility/Title.php b/core/lib/Drupal/Core/Utility/Title.php
index b6380b6..40a3a91 100644
--- a/core/lib/Drupal/Core/Utility/Title.php
+++ b/core/lib/Drupal/Core/Utility/Title.php
@@ -22,4 +22,9 @@ class Title {
    */
   const FILTER_XSS_ADMIN = 1;
 
+  /**
+   * For controller titles, text has already been sanitized.
+   */
+  const PASS_THROUGH = -1;
+
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
index daf2e77..001b807 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
@@ -161,21 +161,6 @@ function testMaintenancePage() {
     $html_attributes['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
 
     $site_config = \Drupal::config('system.site');
-    $site_name = $site_config->get('name');
-    $site_slogan = $site_config->get('slogan');
-    if ($title = drupal_get_title()) {
-      $head_title = array(
-        'title' => strip_tags($title),
-        'name' => String::checkPlain($site_config->get('name')),
-      );
-    }
-    else {
-      $head_title = array('name' => String::checkPlain($site_name));
-      if ($site_slogan) {
-        $head_title['slogan'] = strip_tags(Xss::filterAdmin($site_slogan));
-      }
-    }
-    $head_title = implode(' | ', $head_title);
 
     // Add favicon.
     $favicon = theme_get_setting('favicon.url');
@@ -229,14 +214,14 @@ function testMaintenancePage() {
     $placeholders = array(
       '!html_attributes' => $html_attributes->__toString(),
       '!head' => drupal_get_html_head(),
-      '!head_title' => $head_title,
+      '!head_title' => $site_config->get('name'),
       '!styles' => drupal_get_css($css),
       '!scripts' => drupal_get_js(),
       '!attributes.class' => 'maintenance-page in-maintenance no-sidebars',
       '!front_page' => url(),
       '!logo' => theme_get_setting('logo.url'),
       '!site_name' => $site_config->get('name'),
-      '!title' => $title ? '<h1>' . $title . '</h1>' : '',
+      '!title' => '',
       '!content' => '<span>foo</span>',
     );
 
@@ -244,6 +229,7 @@ function testMaintenancePage() {
     drupal_static_reset();
 
     // Test basic string for maintenance page content.
+    // No page title is set, so it should default to the site name.
     $elements = array(
       array(
         'name' => "#theme 'maintenance_page' with content of <span>foo</span>",
@@ -262,6 +248,11 @@ function testMaintenancePage() {
     drupal_static_reset();
     $elements[0]['name'] = "#theme 'maintenance_page' with content as a render array";
     $elements[0]['value']['#content'] = array('#markup' => '<span>foo</span>');
+    // Testing with a page title, which should be combined with the site name.
+    $title = t('A non-empty title');
+    $elements[0]['value']['#page']['#title'] = $title;
+    $elements[0]['placeholders']['!title'] = '<h1>' . $title . '</h1>';
+    $elements[0]['placeholders']['!head_title'] = strip_tags($title) . ' | ' . String::checkPlain($site_config->get('name'));
     $this->assertElements($elements);
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php b/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php
index 33f2f47..fdc511a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php
@@ -28,7 +28,7 @@ class PageTitleTest extends WebTestBase {
   public static function getInfo() {
     return array(
       'name' => 'Page titles',
-      'description' => 'Tests correct handling or conversion by drupal_set_title() and drupal_get_title() and checks the correct escaping of site name and slogan.',
+      'description' => 'Tests correct escaping of page title, site name and slogan.',
       'group' => 'System'
     );
   }
@@ -43,32 +43,13 @@ function setUp() {
 
     $this->content_user = $this->drupalCreateUser(array('create page content', 'access content', 'administer themes', 'administer site configuration'));
     $this->drupalLogin($this->content_user);
-    $this->saved_title = drupal_get_title();
   }
 
   /**
-   * Reset page title.
-   */
-  function tearDown() {
-    // Restore the page title.
-    drupal_set_title($this->saved_title, PASS_THROUGH);
-
-    parent::tearDown();
-  }
-
-  /**
-   * Tests the handling of HTML by drupal_set_title() and drupal_get_title()
+   * Tests the handling of HTML in node titles.
    */
   function testTitleTags() {
     $title = "string with <em>HTML</em>";
-    // drupal_set_title's $filter is Title::CHECK_PLAIN by default, so the title should be
-    // returned with check_plain().
-    drupal_set_title($title, Title::CHECK_PLAIN);
-    $this->assertTrue(strpos(drupal_get_title(), '<em>') === FALSE, 'Tags in title converted to entities when $output is Title::CHECK_PLAIN.');
-    // drupal_set_title's $filter is passed as PASS_THROUGH, so the title should be
-    // returned with HTML.
-    drupal_set_title($title, PASS_THROUGH);
-    $this->assertTrue(strpos(drupal_get_title(), '<em>') !== FALSE, 'Tags in title are not converted to entities when $output is PASS_THROUGH.');
     // Generate node content.
     $edit = array(
       'title[0][value]' => '!SimpleTest! ' . $title . $this->randomName(20),
@@ -82,6 +63,7 @@ function testTitleTags() {
     $this->drupalGet("node/" . $node->id());
     $this->assertText(check_plain($edit['title[0][value]']), 'Check to make sure tags in the node title are converted.');
   }
+
   /**
    * Test if the title of the site is XSS proof.
    */
@@ -113,9 +95,10 @@ function testTitleXSS() {
     $this->drupalGet('');
 
     // Test the title.
-    $this->assertNoRaw($title, 'Check for the unfiltered version of the title.');
-    // Adding </title> so we do not test the escaped version from drupal_set_title().
-    $this->assertRaw($title_filtered . '</title>', 'Check for the filtered version of the title.');
+    $this->assertNoRaw($title, 'Check for the lack of the unfiltered version of the title.');
+    // Add </title> to make sure we're checking the title tag, rather than the
+    // first 'heading' on the page.
+    $this->assertRaw($title_filtered . '</title>', 'Check for the filtered version of the title in a <title> tag.');
 
     // Test the slogan.
     $this->assertNoRaw($slogan, 'Check for the unfiltered version of the slogan.');
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 721bcf8..88cfc7e 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -284,6 +284,7 @@ function system_element_info() {
   $types['page'] = array(
     '#show_messages' => TRUE,
     '#theme' => 'page',
+    '#title' => '',
   );
   // By default, we don't want Ajax commands being rendered in the context of an
   // HTML page, so we don't provide defaults for #theme or #theme_wrappers.
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php
index 66f3495..bbc26ec 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\views\Plugin\views\area;
 
+use \Drupal\Core\Utility\Title as UtilityTitle;
+
 /**
  * Views area title override handler.
  *
@@ -51,7 +53,7 @@ public function preRender(array $results) {
     // If a title is provided, process it.
     if (!empty($this->options['title'])) {
       $value = $this->globalTokenReplace($this->options['title']);
-      $this->view->setTitle($this->sanitizeValue($value, 'xss_admin'), PASS_THROUGH);
+      $this->view->setTitle($this->sanitizeValue($value, 'xss_admin'), UtilityTitle::PASS_THROUGH);
     }
   }
 
