diff --git a/core/includes/common.inc b/core/includes/common.inc
index fb0abac..e9c610d 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1420,6 +1420,10 @@ function drupal_set_time_limit($time_limit) {
 /**
  * Returns the path to a system item (module, theme, etc.).
  *
+ * This function should only be used when including a file containing PHP code;
+ * the 'module://', 'profile://' and 'theme://' stream wrappers should be used
+ * for other use cases.
+ *
  * @param $type
  *   The type of the item (i.e. theme, theme_engine, module, profile).
  * @param $name
diff --git a/core/lib/Drupal/Core/Routing/RouteBuilder.php b/core/lib/Drupal/Core/Routing/RouteBuilder.php
index 232e47e..04460ce 100644
--- a/core/lib/Drupal/Core/Routing/RouteBuilder.php
+++ b/core/lib/Drupal/Core/Routing/RouteBuilder.php
@@ -87,7 +87,7 @@ public function rebuild() {
     // a given item came from.
     foreach ($this->moduleHandler->getModuleList() as $module => $filename) {
       $collection = new RouteCollection();
-      $routing_file = DRUPAL_ROOT . '/' . dirname($filename) . '/' . $module . '.routing.yml';
+      $routing_file = "module://{$module}/{$module}.routing.yml";;
       if (file_exists($routing_file)) {
         $routes = $parser->parse(file_get_contents($routing_file));
         if (!empty($routes)) {
diff --git a/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php b/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php
new file mode 100644
index 0000000..0454b6a
--- /dev/null
+++ b/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StreamWrapper\ModuleStream.
+ */
+
+namespace Drupal\Core\StreamWrapper;
+
+/**
+ * Defines a read-only Drupal stream wrapper base class for modules.
+ *
+ * This class extends the complete stream wrapper implementation in LocalStream.
+ * URIs such as "module://system" are expanded to a normal filesystem path
+ * such as "modules/system" and then PHP filesystem functions are
+ * invoked.
+ */
+class ModuleStream extends SystemStream {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDirectoryPath() {
+    return drupal_get_path('module', $this->getSystemName());
+  }
+
+}
diff --git a/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php b/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php
new file mode 100644
index 0000000..809078f
--- /dev/null
+++ b/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StreamWrapper\ProfileStream.
+ */
+
+namespace Drupal\Core\StreamWrapper;
+
+/**
+ * Defines a read-only Drupal stream wrapper base class for profiles.
+ *
+ * This class extends the complete stream wrapper implementation in LocalStream.
+ * URIs such as "profile://default" are expanded to a normal filesystem path
+ * such as "profiles/default" and then PHP filesystem functions are
+ * invoked.
+ *
+ * Specifying "profile://current" will return a stream for the currently
+ * installed profile.
+ */
+class ProfileStream extends SystemStream {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSystemName($uri = NULL) {
+    $name = parent::getSystemName($uri);
+    if ($name == 'current') {
+      return drupal_get_profile();
+    }
+    else {
+      return $name;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDirectoryPath() {
+    return drupal_get_path('profile', $this->getSystemName());
+  }
+
+}
diff --git a/core/lib/Drupal/Core/StreamWrapper/SystemStream.php b/core/lib/Drupal/Core/StreamWrapper/SystemStream.php
new file mode 100644
index 0000000..2d0005d
--- /dev/null
+++ b/core/lib/Drupal/Core/StreamWrapper/SystemStream.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StreamWrapper\SystemStream.
+ */
+
+namespace Drupal\Core\StreamWrapper;
+
+/**
+ * Defines a base stream wrapper implementation.
+ *
+ * This class provides a read-only Drupal stream wrapper base class for system
+ * files such as modules, themes and profiles.
+ */
+abstract class SystemStream extends LocalReadOnlyStream {
+
+  /**
+   * Get the module, theme, or profile name of the current URI.
+   *
+   * @param string $uri
+   *   Optional URI.
+   *
+   * @return string
+   *   The extension name.
+   */
+  protected function getSystemName($uri = NULL) {
+    if (!isset($uri)) {
+      $uri = $this->uri;
+    }
+
+    $uri_parts = explode('://', $uri, 2);
+    if (count($uri_parts) === 1) {
+      // The delimiter ('://') was not found in $uri, malformed $uri passed.
+      throw new \InvalidArgumentException('Malformed $uri parameter passed: %s', $uri);
+    }
+    else {
+      list($scheme, $target) = $uri_parts;
+    }
+
+    $pos = strpos($target, '/');
+    return $pos === FALSE ? $target : substr($target, 0, $pos);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getTarget($uri = NULL) {
+    if (!isset($uri)) {
+      $uri = $this->uri;
+    }
+
+    $uri_parts = explode('://', $uri, 2);
+    if (count($uri_parts) === 1) {
+      // The delimiter ('://') was not found in $uri, malformed $uri passed.
+      throw new \InvalidArgumentException('Malformed $uri parameter passed: %s', $uri);
+    }
+    else {
+      list($scheme, $target) = $uri_parts;
+    }
+
+    // Remove erroneous leading or trailing, forward-slashes and backslashes.
+    $target = trim($target, '\/');
+
+    // Remove the module/theme/profile name form the file path.
+    $target = substr($target, strlen($this->getSystemName()));
+
+    // Trim again.
+    $target = trim($target, '\/');
+    return $target;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getExternalUrl() {
+    $dir = $this->getDirectoryPath();
+    if (empty($dir)) {
+      return FALSE;
+    }
+
+    $path = str_replace('\\', '/', $this->getTarget());
+    return $GLOBALS['base_url'] . '/' . $dir . '/' . drupal_encode_path($path);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php b/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php
new file mode 100644
index 0000000..79eeb53
--- /dev/null
+++ b/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StreamWrapper\ThemeStream.
+ */
+
+namespace Drupal\Core\StreamWrapper;
+
+/**
+ * Defines a read-only Drupal stream wrapper base class for themes.
+ *
+ * This class extends the complete stream wrapper implementation in LocalStream.
+ * URIs such as "theme://bartik" are expanded to a normal filesystem path
+ * such as "themes/default" and then PHP filesystem functions are
+ * invoked.
+ */
+class ThemeStream extends SystemStream {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDirectoryPath() {
+    return drupal_get_path('theme', $this->getSystemName());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSystemName($uri = NULL) {
+    global $theme_key;
+    $name = parent::getSystemName($uri);
+    if ($name == 'current') {
+      return $theme_key;
+    }
+    else if ($name == 'admin') {
+      return \Drupal::config('system.theme')->get('admin');
+    }
+    else {
+      return $name;
+    }
+  }
+
+}
diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchSimplifyTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchSimplifyTest.php
index 5b1e5d4..73efb55 100644
--- a/core/modules/search/lib/Drupal/search/Tests/SearchSimplifyTest.php
+++ b/core/modules/search/lib/Drupal/search/Tests/SearchSimplifyTest.php
@@ -30,7 +30,7 @@ function testSearchSimplifyUnicode() {
     // their own lines).  So the even-numbered lines should simplify to nothing,
     // and the odd-numbered lines we need to split into shorter chunks and
     // verify that simplification doesn't lose any characters.
-    $input = file_get_contents(DRUPAL_ROOT . '/core/modules/search/tests/UnicodeTest.txt');
+    $input = file_get_contents('module://search/tests/UnicodeTest.txt');
     $basestrings = explode(chr(10), $input);
     $strings = array();
     foreach ($basestrings as $key => $string) {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 87fe50d..9aad827 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2146,6 +2146,24 @@ function system_stream_wrappers() {
       'description' => t('Temporary local files for upload and previews.'),
       'type' => STREAM_WRAPPERS_LOCAL_HIDDEN,
     ),
+    'module' => array(
+      'name' => t('Module files'),
+      'class' => 'Drupal\Core\StreamWrapper\ModuleStream',
+      'description' => t('Local module files.'),
+      'type' => STREAM_WRAPPERS_READ,
+    ),
+    'theme' => array(
+      'name' => t('Theme files'),
+      'class' => 'Drupal\Core\StreamWrapper\ThemeStream',
+      'description' => t('Local theme files.'),
+      'type' => STREAM_WRAPPERS_READ,
+    ),
+    'profile' => array(
+      'name' => t('Profile files'),
+      'class' => 'Drupal\Core\StreamWrapper\ProfileStream',
+      'description' => t('Local profile files.'),
+      'type' => STREAM_WRAPPERS_READ,
+    ),
   );
 
   // Only register the private file stream wrapper if a file path has been set.
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
index b0cbb7b..7f140db 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
@@ -1943,7 +1943,7 @@ public function buildOptionsForm(&$form, &$form_state) {
 
         // Field templates aren't registered the normal way...and they're always
         // this one, anyhow.
-        $output .= '<pre>' . check_plain(file_get_contents(drupal_get_path('module', 'views') . '/templates/views-view-field.tpl.php')) . '</pre>';
+        $output .= '<pre>' . check_plain(file_get_contents("module://views/templates/views-view-field.tpl.php")) . '</pre>';
 
         $form['analysis'] = array(
           '#markup' => '<div class="form-item">' . $output . '</div>',
