diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php
index 999f447..359ef13 100644
--- a/core/lib/Drupal/Core/Url.php
+++ b/core/lib/Drupal/Core/Url.php
@@ -196,9 +196,15 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) {
    * base://robots.txt. For URLs that have Drupal routes (that is, most pages
    * generated by Drupal), use Url::fromRoute().
    *
+   * For resolving URLs to an entity, you may use the
+   * entity://{entity_type}/{entity_id} scheme. For example entity://node/1
+   * would resolve to the entity.node.canonical route with a node parameter of
+   * one.
+   *
    * @param string $uri
    *   The URI of the external resource including the scheme. For Drupal paths
    *   that are not handled by the routing system, use base:// for the scheme.
+   *   For entity URLs you may use entity://{entity_type}/{entity_id}.
    * @param array $options
    *   (optional) An associative array of additional URL options, with the
    *   following elements:
@@ -217,7 +223,7 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) {
    *     respectively. TRUE enforces HTTPS and FALSE enforces HTTP.
    *
    * @return \Drupal\Core\Url
-   *   A new Url object for an unrouted (non-Drupal) URL.
+   *   A new Url object for an unrouted (non-Drupal) URL or a routed entity URI.
    *
    * @throws \InvalidArgumentException
    *   Thrown when the passed in path has no scheme.
@@ -225,10 +231,15 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) {
    * @see static::fromRoute()
    */
   public static function fromUri($uri, $options = array()) {
-    if (!parse_url($uri, PHP_URL_SCHEME)) {
+    if (!($scheme = parse_url($uri, PHP_URL_SCHEME))) {
       throw new \InvalidArgumentException(String::format('The URI "@uri" is invalid. You must use a valid URI scheme. Use base:// for a path, e.g., to a Drupal file that needs the base path. Do not use this for internal paths controlled by Drupal.', ['@uri' => $uri]));
     }
 
+    // Special case entity:// URIs. Map these to the canonical entity route.
+    if ($scheme === 'entity') {
+      return static::fromEntityUri($uri);
+    }
+
     $url = new static($uri, array(), $options);
     $url->setUnrouted();
 
@@ -236,6 +247,30 @@ public static function fromUri($uri, $options = array()) {
   }
 
   /**
+   * Create a new Url object for entity URIs.
+   *
+   * @param string $uri
+   *   An URI of the form entity://{entity_type}/{entity_id}.
+   *
+   * @return \Drupal\Core\Url
+   *   A new Url object for an entity's canonical route.
+   *
+   * @throws \InvalidArgumentException
+   *   Thrown if the entity URI is invalid.
+   */
+  protected static function fromEntityUri($uri) {
+    $uri_parts = parse_url($uri);
+    $entity_type_id = $uri_parts['host'];
+    $entity_id = trim($uri_parts['path'], '/');
+    if ($uri_parts['scheme'] != 'entity' || $entity_id === '') {
+      throw new \InvalidArgumentException(String::format('The entity URI "@uri" is invalid. You must specify the entity id in the URL. e.g., entity://node/1 for loading the canonical path to node entity with id 1.',
+        ['@uri' => $uri]));
+    }
+
+    return new static("entity.$entity_type_id.canonical", [$entity_type_id => $entity_id]);
+  }
+
+  /**
    * Returns the Url object matching a request.
    *
    * SECURITY NOTE: The request path is not checked to be valid and accessible
diff --git a/core/tests/Drupal/Tests/Core/UrlTest.php b/core/tests/Drupal/Tests/Core/UrlTest.php
index cea8770..849408b 100644
--- a/core/tests/Drupal/Tests/Core/UrlTest.php
+++ b/core/tests/Drupal/Tests/Core/UrlTest.php
@@ -9,13 +9,16 @@
 
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Entity\EntityType;
 use Drupal\Core\Routing\RouteMatch;
 use Drupal\Core\Url;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Exception\InvalidParameterException;
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
 use Symfony\Component\Routing\Route;
 
 /**
@@ -90,6 +93,7 @@ protected function setUp() {
       ->will($this->returnValueMap($alias_map));
 
     $this->router = $this->getMock('Drupal\Tests\Core\Routing\TestRouterInterface');
+
     $this->container = new ContainerBuilder();
     $this->container->set('router.no_access_checks', $this->router);
     $this->container->set('url_generator', $this->urlGenerator);
@@ -441,6 +445,33 @@ public function testFromRouteMatch() {
   }
 
   /**
+   * Tests the fromUri() method with an entity:// URI.
+   *
+   * @covers ::fromUri
+   */
+  public function testEntityUris() {
+    $url = Url::fromUri('entity://test_entity/1');
+    $this->assertSame('entity.test_entity.canonical', $url->getRouteName());
+    $this->assertEquals(['test_entity' => '1'], $url->getRouteParameters());
+  }
+
+  /**
+   * Tests the fromUri() method with an invalid entity:// URI.
+   *
+   * @covers ::fromUri
+   * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
+   */
+  public function testInvalidEntityUriParameter() {
+    // Make the mocked URL generator behave like the actual one.
+    $this->urlGenerator->expects($this->once())
+      ->method('generateFromRoute')
+      ->with('entity.test_entity.canonical', ['test_entity' => '1/blah'])
+      ->willThrowException(new InvalidParameterException('Parameter "test_entity" for route "/test_entity/{test_entity}" must match "[^/]++" ("1/blah" given) to generate a corresponding URL..'));
+
+    Url::fromUri('entity://test_entity/1/blah')->toString();
+  }
+
+  /**
    * Creates a mock access manager for the access tests.
    *
    * @param bool $access
