Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 30050)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -196,6 +196,7 @@
 add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
 
 // Actions
+add_action( 'wp_head',             '_wp_render_title_tag',            1     );
 add_action( 'wp_head',             'wp_enqueue_scripts',              1     );
 add_action( 'wp_head',             'feed_links',                      2     );
 add_action( 'wp_head',             'feed_links_extra',                3     );
Index: src/wp-includes/general-template.php
===================================================================
--- src/wp-includes/general-template.php	(revision 30050)
+++ src/wp-includes/general-template.php	(working copy)
@@ -731,6 +731,25 @@
 }
 
 /**
+ * Display <title> tag with contents.
+ *
+ * @since 4.1.0
+ * @access private
+ */
+function _wp_render_title_tag() {
+	if ( ! current_theme_supports( 'title-tag' ) ) {
+		return;
+	}
+
+	// This can only work internally on wp_head.
+	if ( ! did_action( 'wp_head' ) && ! doing_action( 'wp_head' ) ) {
+		return;
+	}
+
+	echo "<title>" . wp_title( '|', false, 'right' ) . "</title>\n";
+}
+
+/**
  * Display or retrieve page title for all areas of blog.
  *
  * By default, the page title will display the separator before the page title,
@@ -853,6 +872,21 @@
 		$title = $prefix . implode( " $sep ", $title_array );
 	}
 
+	if ( current_theme_supports( 'title-tag' ) && ! is_feed() ) {
+		global $page, $paged;
+
+		$title .= get_bloginfo( 'name', 'display' );
+
+		$site_description = get_bloginfo( 'description', 'display' );
+		if ( $site_description && ( is_home() || is_front_page() ) ) {
+			$title .= " $sep $site_description";
+		}
+
+		if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) {
+			$title .= " $sep " . sprintf( __( 'Page %s' ), max( $paged, $page ) );
+		}
+	}
+
 	/**
 	 * Filter the text of the page title.
 	 *
Index: src/wp-includes/theme.php
===================================================================
--- src/wp-includes/theme.php	(revision 30050)
+++ src/wp-includes/theme.php	(working copy)
@@ -1611,6 +1611,15 @@
 				define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
 
 			break;
+
+		// Ensure that 'title-tag' is accessible in the admin.
+		case 'title-tag' :
+			// Can be called in functions.php but must happen before wp_loaded, i.e. not in header.php.
+			if ( did_action( 'wp_loaded' ) ) {
+				_doing_it_wrong( "add_theme_support( 'title-tag' )", sprintf( _x( 'You need to add theme support before %s.', 'action name' ), '<code>wp_loaded</code>' ), '4.1.0' );
+
+				return false;
+			}
 	}
 
 	$_wp_theme_features[ $feature ] = $args;
@@ -1763,6 +1772,14 @@
 	if ( !isset( $_wp_theme_features[$feature] ) )
 		return false;
 
+	if ( 'title-tag' == $feature ) {
+		// Don't confirm support unless called internally.
+		$trace = debug_backtrace();
+		if ( ! in_array( $trace[1]['function'], array( '_wp_render_title_tag', 'wp_title' ) ) ) {
+			return false;
+		}
+	}
+
 	// If no args passed then no extra checks need be performed
 	if ( func_num_args() <= 1 )
 		return true;
