diff --git a/core/core.services.yml b/core/core.services.yml
index 0c038ec..d08541e 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -727,5 +727,8 @@ services:
     class: Drupal\Core\Asset\JsCollectionGrouper
   asset.js.dumper:
     class: Drupal\Core\Asset\AssetDumper
+  library.provider:
+    class: Drupal\Core\Asset\LibraryProvider
+    arguments: ['@cache.cache', '@module_handler']
   info_parser:
     class: Drupal\Core\Extension\InfoParser
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 1f2b74b..8816bc0 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2758,161 +2758,16 @@ function drupal_add_library($module, $name, $every_page = NULL) {
  *   requisite API functions; find and use a different name.
  */
 function drupal_get_library($extension, $name = NULL) {
-  $libraries = &drupal_static(__FUNCTION__, array());
-
-  if (!isset($libraries[$extension]) && ($cache = \Drupal::cache()->get('library:info:' . $extension))) {
-    $libraries[$extension] = $cache->data;
-  }
-
-  if (!isset($libraries[$extension])) {
-    $libraries[$extension] = array();
-    if ($extension === 'core') {
-      $path = 'core';
-      $extension_type = 'core';
-    }
-    else {
-      // @todo Add a $type argument OR automatically figure out the type based
-      //   on current extension data, possibly using a module->theme fallback.
-      $path = drupal_get_path('module', $extension);
-      $extension_type = 'module';
-      if (!$path) {
-        $path = drupal_get_path('theme', $extension);
-        $extension_type = 'theme';
-      }
-    }
-    $library_file = $path . '/' . $extension . '.libraries.yml';
-
-    if ($library_file && file_exists(DRUPAL_ROOT . '/' . $library_file)) {
-      $libraries[$extension] = array();
-      $parser = new Parser();
-      try {
-        $libraries[$extension] = $parser->parse(file_get_contents(DRUPAL_ROOT . '/' . $library_file));
-      }
-      catch (ParseException $e) {
-        // Rethrow a more helpful exception, since ParseException lacks context.
-        throw new \RuntimeException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
-      }
-      // Allow modules to alter the module's registered libraries.
-      \Drupal::moduleHandler()->alter('library_info', $libraries[$extension], $extension);
-    }
-
-    foreach ($libraries[$extension] as $id => &$library) {
-      if (!isset($library['js']) && !isset($library['css']) && !isset($library['settings'])) {
-        throw new \RuntimeException(sprintf("Incomplete library definition for '%s' in %s", $id, $library_file));
-      }
-      $library += array('dependencies' => array(), 'js' => array(), 'css' => array());
-
-      if (isset($library['version'])) {
-        // @todo Retrieve version of a non-core extension.
-        if ($library['version'] === 'VERSION') {
-          $library['version'] = \Drupal::VERSION;
-        }
-        // Remove 'v' prefix from external library versions.
-        elseif ($library['version'][0] === 'v') {
-          $library['version'] = substr($library['version'], 1);
-        }
-      }
-
-      foreach (array('js', 'css') as $type) {
-        // Prepare (flatten) the SMACSS-categorized definitions.
-        // @todo After Asset(ic) changes, retain the definitions as-is and
-        //   properly resolve dependencies for all (css) libraries per category,
-        //   and only once prior to rendering out an HTML page.
-        if ($type == 'css' && !empty($library[$type])) {
-          foreach ($library[$type] as $category => $files) {
-            foreach ($files as $source => $options) {
-              if (!isset($options['weight'])) {
-                $options['weight'] = 0;
-              }
-              // Apply the corresponding weight defined by CSS_* constants.
-              $options['weight'] += constant('CSS_' . strtoupper($category == 'theme' ? 'skin' : $category));
-              $library[$type][$source] = $options;
-            }
-            unset($library[$type][$category]);
-          }
-        }
-        foreach ($library[$type] as $source => $options) {
-          unset($library[$type][$source]);
-          // Allow to omit the options hashmap in YAML declarations.
-          if (!is_array($options)) {
-            $options = array();
-          }
-          if ($type == 'js' && isset($options['weight']) && $options['weight'] > 0) {
-            throw new \UnexpectedValueException("The $extension/$id library defines a positive weight for '$source'. Only negative weights are allowed (but should be avoided). Instead of a positive weight, specify accurate dependencies for this library.");
-          }
-          // Unconditionally apply default groups for the defined asset files.
-          // The library system is a dependency management system. Each library
-          // properly specifies its dependencies instead of relying on a custom
-          // processing order.
-          if ($type == 'js') {
-            $options['group'] = JS_LIBRARY;
-          }
-          elseif ($type == 'css') {
-            $options['group'] = $extension_type == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT;
-          }
-          // By default, all library assets are files.
-          if (!isset($options['type'])) {
-            $options['type'] = 'file';
-          }
-          if ($options['type'] == 'external') {
-            $options['data'] = $source;
-          }
-          // Determine the file asset URI.
-          else {
-            if ($source[0] === '/') {
-              // An absolute path maps to DRUPAL_ROOT / base_path().
-              if ($source[1] !== '/') {
-                $options['data'] = substr($source, 1);
-              }
-              // A protocol-free URI (e.g., //cdn.com/example.js) is external.
-              else {
-                $options['type'] = 'external';
-                $options['data'] = $source;
-              }
-            }
-            // A stream wrapper URI (e.g., public://generated_js/example.js).
-            elseif (file_valid_uri($source)) {
-              $options['data'] = $source;
-            }
-            // By default, file paths are relative to the registering extension.
-            else {
-              $options['data'] = $path . '/' . $source;
-            }
-          }
-          $options['version'] = $library['version'];
-
-          $library[$type][] = $options;
-        }
-      }
-      // @todo Introduce drupal_add_settings().
-      if (isset($library['settings'])) {
-        $library['js'][] = array(
-          'type' => 'setting',
-          'data' => $library['settings'],
-        );
-        unset($library['settings']);
-      }
-      // @todo Convert all uses of #attached[library][]=array('provider','name')
-      //   into #attached[library][]='provider/name' and remove this.
-      foreach ($library['dependencies'] as $i => $dependency) {
-        if (!is_array($dependency)) {
-          $library['dependencies'][$i] = explode('/', $dependency, 2);
-        }
-      }
-    }
-    \Drupal::cache()->set('library:info:' . $extension, $libraries[$extension], Cache::PERMANENT, array(
-      'extension' => array(TRUE, $extension),
-      'library_info' => array(TRUE),
-    ));
+  /**
+   * @var $provider \Drupal\Core\Asset\LibraryProviderInterface;
+   */
+  $provider = \Drupal::service('library.provider');
+  if ($name) {
+    return $provider->getLibraryByName($extension, $name);
   }
-
-  if (isset($name)) {
-    if (!isset($libraries[$extension][$name])) {
-      $libraries[$extension][$name] = FALSE;
-    }
-    return $libraries[$extension][$name];
+  else {
+    return $provider->getLibrariesByExtension($extension);
   }
-  return $libraries[$extension];
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Asset/LibraryProvider.php b/core/lib/Drupal/Core/Asset/LibraryProvider.php
new file mode 100644
index 0000000..cf69f3d
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/LibraryProvider.php
@@ -0,0 +1,268 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\LibraryProvider.
+ */
+
+namespace Drupal\Core\Asset;
+
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandler;
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Parser;
+
+/**
+ * Provides the libraries used in Drupal.
+ */
+class LibraryProvider implements LibraryProviderInterface {
+
+  /**
+   * Stores the library information keyed by extension
+   *
+   * @var array
+   */
+  protected $libraries;
+
+  /**
+   * The cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Constructs a new LibraryProvider instance.
+   *
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   The cache backend.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
+   */
+  public function __construct(CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
+    $this->cache = $cache_backend;
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLibrariesByExtension($extension) {
+    $this->ensureLibraryInformation($extension);
+    return $this->libraries[$extension];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLibraryByName($extension, $name) {
+    $this->ensureLibraryInformation($extension);
+    return isset($this->libraries[$extension][$name]) ? $this->libraries[$extension][$name] : FALSE;
+  }
+
+  protected function ensureLibraryInformation($extension) {
+    $this->retrieveFromCache($extension);
+    if (!isset($this->libraries[$extension])) {
+      if ($information = $this->buildLibrariesByExtension($extension)) {
+        $this->libraries[$extension] = $information;
+      }
+      else {
+        $this->libraries[$extension] = FALSE;
+      }
+    }
+  }
+
+  protected function retrieveFromCache($extension) {
+    if (!isset($this->libraries[$extension])) {
+      if ($cache = $this->cache->get('library:info:' . $extension)) {
+        $this->libraries[$extension] = $cache->data;
+      }
+    }
+  }
+
+  protected function setCache($extension, array $information) {
+    $this->cache->set('library:info:' . $extension, $information, Cache::PERMANENT, array(
+      'extension' => array(TRUE, $extension),
+      'library_info' => array(TRUE),
+    ));
+  }
+
+  protected function buildLibrariesByExtension($extension) {
+    $this->libraries[$extension] = array();
+    if ($extension === 'core') {
+      $path = 'core';
+      $extension_type = 'core';
+    }
+    else {
+      if ($this->moduleHandler->moduleExists($extension)) {
+        $extension_type = 'module';
+      }
+      else {
+        $extension_type = 'theme';
+      }
+      $path = $this->drupalGetPath($extension_type, $extension);
+    }
+    $library_file = $path . '/' . $extension . '.libraries.yml';
+
+    if ($library_file && file_exists(DRUPAL_ROOT . '/' . $library_file)) {
+      $this->libraries[$extension] = array();
+      $extension = $this->parseLibraryInfo($extension, $library_file);
+    }
+
+    foreach ($this->libraries[$extension] as $id => &$library) {
+      if (!isset($library['js']) && !isset($library['css']) && !isset($library['settings'])) {
+        throw new \RuntimeException(sprintf("Incomplete library definition for '%s' in %s", $id, $library_file));
+      }
+      $library += array('dependencies' => array(), 'js' => array(), 'css' => array());
+
+      if (isset($library['version'])) {
+        // @todo Retrieve version of a non-core extension.
+        if ($library['version'] === 'VERSION') {
+          $library['version'] = \Drupal::VERSION;
+        }
+        // Remove 'v' prefix from external library versions.
+        elseif ($library['version'][0] === 'v') {
+          $library['version'] = substr($library['version'], 1);
+        }
+      }
+
+      foreach (array('js', 'css') as $type) {
+        // Prepare (flatten) the SMACSS-categorized definitions.
+        // @todo After Asset(ic) changes, retain the definitions as-is and
+        //   properly resolve dependencies for all (css) libraries per category,
+        //   and only once prior to rendering out an HTML page.
+        if ($type == 'css' && !empty($library[$type])) {
+          foreach ($library[$type] as $category => $files) {
+            foreach ($files as $source => $options) {
+              if (!isset($options['weight'])) {
+                $options['weight'] = 0;
+              }
+              // Apply the corresponding weight defined by CSS_* constants.
+              $options['weight'] += constant('CSS_' . strtoupper($category == 'theme' ? 'skin' : $category));
+              $library[$type][$source] = $options;
+            }
+            unset($library[$type][$category]);
+          }
+        }
+        foreach ($library[$type] as $source => $options) {
+          unset($library[$type][$source]);
+          // Allow to omit the options hashmap in YAML declarations.
+          if (!is_array($options)) {
+            $options = array();
+          }
+          if ($type == 'js' && isset($options['weight']) && $options['weight'] > 0) {
+            throw new \UnexpectedValueException("The $extension/$id library defines a positive weight for '$source'. Only negative weights are allowed (but should be avoided). Instead of a positive weight, specify accurate dependencies for this library.");
+          }
+          // Unconditionally apply default groups for the defined asset files.
+          // The library system is a dependency management system. Each library
+          // properly specifies its dependencies instead of relying on a custom
+          // processing order.
+          if ($type == 'js') {
+            $options['group'] = JS_LIBRARY;
+          }
+          elseif ($type == 'css') {
+            $options['group'] = $extension_type == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT;
+          }
+          // By default, all library assets are files.
+          if (!isset($options['type'])) {
+            $options['type'] = 'file';
+          }
+          if ($options['type'] == 'external') {
+            $options['data'] = $source;
+          }
+          // Determine the file asset URI.
+          else {
+            if ($source[0] === '/') {
+              // An absolute path maps to DRUPAL_ROOT / base_path().
+              if ($source[1] !== '/') {
+                $options['data'] = substr($source, 1);
+              }
+              // A protocol-free URI (e.g., //cdn.com/example.js) is external.
+              else {
+                $options['type'] = 'external';
+                $options['data'] = $source;
+              }
+            }
+            // A stream wrapper URI (e.g., public://generated_js/example.js).
+            elseif ($this->fileValidUri($source)) {
+              $options['data'] = $source;
+            }
+            // By default, file paths are relative to the registering extension.
+            else {
+              $options['data'] = $path . '/' . $source;
+            }
+          }
+          $options['version'] = $library['version'];
+
+          $library[$type][] = $options;
+        }
+      }
+
+      // @todo Introduce drupal_add_settings().
+      if (isset($library['settings'])) {
+        $library['js'][] = array(
+          'type' => 'setting',
+          'data' => $library['settings'],
+        );
+        unset($library['settings']);
+      }
+      // @todo Convert all uses of #attached[library][]=array('provider','name')
+      //   into #attached[library][]='provider/name' and remove this.
+      foreach ($library['dependencies'] as $i => $dependency) {
+        if (!is_array($dependency)) {
+          $library['dependencies'][$i] = explode('/', $dependency, 2);
+        }
+      }
+    }
+    return $this->libraries[$extension];
+  }
+
+  /**
+   * Wraps drupal_get_path().
+   */
+  protected function drupalGetPath($string, $extension) {
+    return drupal_get_path($string, $extension);
+  }
+
+  /**
+   * @param $source
+   * @return bool
+   */
+  protected function fileValidUri($source) {
+    return file_valid_uri($source);
+  }
+
+  /**
+   * @param $extension
+   * @param $library_file
+   * @return mixed
+   * @throws \RuntimeException
+   */
+  protected function parseLibraryInfo($extension, $library_file) {
+    $parser = new Parser();
+    try {
+      $this->libraries[$extension] = $parser->parse(file_get_contents(DRUPAL_ROOT . '/' . $library_file));
+      return $extension;
+    } catch (ParseException $e) {
+      // Rethrow a more helpful exception, since ParseException lacks context.
+      throw new \RuntimeException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
+    }
+    return $extension;
+    // Allow modules to alter the module's registered libraries.
+    $this->moduleHandler->alter('library_info', $this->libraries[$extension], $extension);
+    return $extension;
+  }
+
+} 
diff --git a/core/lib/Drupal/Core/Asset/LibraryProviderInterface.php b/core/lib/Drupal/Core/Asset/LibraryProviderInterface.php
new file mode 100644
index 0000000..95af530
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/LibraryProviderInterface.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\LibraryProviderInterface.
+ */
+
+namespace Drupal\Core\Asset;
+
+/**
+ * Provides information for javascript/CSS libraries.
+ *
+ * Library information is statically cached. Libraries are keyed by module for
+ * several reasons:
+ * - Libraries are not unique. Multiple modules might ship with the same library
+ *   in a different version or variant. This registry cannot (and does not
+ *   attempt to) prevent library conflicts.
+ * - Modules implementing and thereby depending on a library that is registered
+ *   by another module can only rely on that module's library.
+ * - Two (or more) modules can still register the same library and use it
+ *   without conflicts in case the libraries are loaded on certain pages only.
+ */
+interface LibraryProviderInterface {
+
+  /**
+   * Gets all libraries defined by an extension.
+   *
+   * @param string $extension
+   *   The name of the extension that registered a library.
+   *
+   * @return array
+   *   An associative array of libraries registered by $extension is returned
+   *   (which may be empty).
+   *
+   * @see self::getLibraryByName
+   */
+  public function getLibrariesByExtension($extension);
+
+  /**
+   * Gets a single library defined by an extension by name.
+   *
+   * @param string $extension
+   *   The name of the extension that registered a library.
+   * @param string $name
+   *   The name of a registered library to retrieve.
+   *
+   * @return array|FALSE
+   *   The definition of the requested library, if $name was passed and it
+   *   exists, otherwise FALSE.
+   */
+  public function getLibraryByName($extension, $name);
+
+} 
