diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 9a4f2ee..6b2da17 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2616,7 +2616,7 @@ function template_preprocess(&$variables, $hook) {
   static $count = array(), $default_attributes;
 
   // Track run count for each hook to provide zebra striping. See
-  // "template_preprocess_block()" which provides the same feature specific to
+  // "template_preprocess_block_wrapper()" which provides the same feature specific to
   // blocks.
   $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
   $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module
index 525cdc1..a7f794a 100644
--- a/core/modules/aggregator/aggregator.module
+++ b/core/modules/aggregator/aggregator.module
@@ -550,7 +550,7 @@ function aggregator_filter_xss($value) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function aggregator_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'aggregator') {
+  if ($variables['configuration']['module'] == 'aggregator') {
     $variables['attributes']['role'] = 'complementary';
   }
 }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorCategoryBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorCategoryBlock.php
index 10bc52e..acf8520 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorCategoryBlock.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorCategoryBlock.php
@@ -62,9 +62,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $id = $this->getPluginId();
     if ($category = db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchObject()) {
       $result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = :cid ORDER BY i.timestamp DESC, i.iid DESC', 0, $this->configuration['block_count'], array(':cid' => $category->cid));
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorFeedBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorFeedBlock.php
index afcef0e..335c370 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorFeedBlock.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/AggregatorFeedBlock.php
@@ -62,9 +62,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     // Plugin IDs look something like this: aggregator_feed_block:1.
     list(, $id) = explode(':', $this->getPluginId());
     if ($feed = db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE block <> 0 AND fid = :fid', array(':fid' => $id))->fetchObject()) {
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
index 1c6056d..b60dde4 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
@@ -50,7 +50,7 @@ public function testBlockLinks() {
     ));
     $this->drupalLogin($admin_user);
 
-    $block = $this->drupalPlaceBlock("aggregator_feed_block:{$feed->id()}", array('label' => 'feed-' . $feed->label()), array('block_count' => 2));
+    $block = $this->drupalPlaceBlock("aggregator_feed_block:{$feed->id()}", array('label' => 'feed-' . $feed->label(), 'block_count' => 2));
 
     // Confirm that the block is now being displayed on pages.
     $this->drupalGet('test-page');
diff --git a/core/modules/block/block.api.php b/core/modules/block/block.api.php
index c9b3b1f..3d3c4d1 100644
--- a/core/modules/block/block.api.php
+++ b/core/modules/block/block.api.php
@@ -11,25 +11,27 @@
  */
 
 /**
- * Perform alterations to the content of a block.
+ * Perform alterations to the content of a block entity.
  *
- * This hook allows you to modify any data returned by hook_block_view().
+ * This hook allows you to modify any data returned by
+ * \Drupal\block\BlockRenderController::view().
  *
- * Note that instead of hook_block_view_alter(), which is called for all blocks,
- * you can also use hook_block_view_ID_alter() to alter a specific block, or
- * hook_block_view_NAME_alter() to alter a specific block instance.
+ * Note that instead of hook_block_wrapper_view_alter(), which is called for all
+ * blocks, you can also use hook_block_wrapper_view_ID_alter() to alter a specific
+ * block, or hook_block_view_NAME_alter() to alter a specific block
+ * instance.
  *
  * @param array $build
  *   A renderable array of data, as returned from the build() implementation of
  *   the plugin that defined the block:
  *   - #title: The default localized title of the block.
- * @param \Drupal\block\BlockInterface $block
- *   The block instance.
+ * @param \Drupal\block\Plugin\Core\Entity\Block $block
+ *   The block entity.
  *
- * @see hook_block_view_ID_alter()
+ * @see hook_block_wrapper_view_ID_alter()
  * @see hook_block_view_NAME_alter()
  */
-function hook_block_view_alter(array &$build, \Drupal\block\Plugin\Core\Entity\Block $block) {
+function hook_block_wrapper_view_alter(array &$build, \Drupal\block\Plugin\Core\Entity\Block $block) {
   // Remove the contextual links on all blocks that provide them.
   if (is_array($build) && isset($build['#contextual_links'])) {
     unset($build['#contextual_links']);
@@ -42,25 +44,25 @@ function hook_block_view_alter(array &$build, \Drupal\block\Plugin\Core\Entity\B
 }
 
 /**
- * Perform alterations to a specific block.
+ * Perform alterations to the content of a specific block entity.
  *
- * Modules can implement hook_block_view_ID_alter() to modify a specific block,
- * rather than implementing hook_block_view_alter().
+ * Modules can implement hook_block_wrapper_view_ID_alter() to modify a specific block
+ * entity, rather than implementing hook_block_wrapper_view_alter().
  *
  * @param array $build
  *   A renderable array of data, as returned from the build() implementation of
  *   the plugin that defined the block:
  *   - #title: The default localized title of the block.
- * @param \Drupal\block\BlockInterface $block
- *   The block instance.
+ * @param \Drupal\block\Plugin\Core\Entity\Block $block
+ *   The block entity.
  *
  * @todo Add a more specific example of a block ID, and illustrate how this is
  *   different from hook_block_view_NAME_alter().
  *
- * @see hook_block_view_alter()
+ * @see hook_block_wrapper_view_alter()
  * @see hook_block_view_NAME_alter()
  */
-function hook_block_view_ID_alter(array &$build, \Drupal\block\BlockInterface $block) {
+function hook_block_wrapper_view_ID_alter(array &$build, \Drupal\block\Plugin\Core\Entity\Block $block) {
   // This code will only run for a specific block. For example, if ID
   // in the function definition above is set to "someid", the code
   // will only run on the "someid" block.
@@ -70,10 +72,27 @@ function hook_block_view_ID_alter(array &$build, \Drupal\block\BlockInterface $b
 }
 
 /**
- * Perform alterations to a specific block instance.
+ * Perform alterations to the content of a block plugin.
  *
- * Modules can implement hook_block_view_NAME_alter() to modify a specific block
- * instance, rather than implementing hook_block_view_alter().
+ * @param array $build
+ *   A renderable array, as returned by the plugin that defined the block.
+ * @param \Drupal\block\BlockInterface $block
+ *   The block plugin.
+ */
+function hook_block_view_alter(array &$build, \Drupal\block\BlockInterface $block) {
+  if (isset($build['#content'])) {
+    foreach (element_children($build['#content']) as $key) {
+      $build['#content']['#contextual_links']['my_module'] = array('admin/structure/mymodule', array($build['#content'][$key]['some_value']));
+    }
+  }
+}
+
+/**
+ * Perform alterations to the content of a specific block plugin.
+ *
+ * Modules can implement hook_block_view_NAME_alter() to modify a
+ * specific block plugin, rather than implementing
+ * hook_block_view_alter().
  *
  * @param array $build
  *   A renderable array of data, as returned from the build() implementation of
@@ -84,10 +103,11 @@ function hook_block_view_ID_alter(array &$build, \Drupal\block\BlockInterface $b
  *
  * @todo NAME is ambiguous, and so is the example here. Use a more specific
  *   example to illustrate what the block instance name will look like, and
- *   also illustrate how it is different from hook_block_view_ID().
+ *   also illustrate how it is different from hook_block_wrapper_view_ID().
  *
  * @see hook_block_view_alter()
- * @see hook_block_view_ID_alter()
+ * @see hook_block_wrapper_view_alter()
+ * @see hook_block_wrapper_view_ID_alter()
  */
 function hook_block_view_NAME_alter(array &$build, \Drupal\block\BlockInterface $block) {
   // This code will only run for a specific block instance. For example, if NAME
@@ -99,14 +119,20 @@ function hook_block_view_NAME_alter(array &$build, \Drupal\block\BlockInterface
 }
 
 /**
- * Define access for a specific block instance.
+ * Define access for a block entity.
  *
  * This hook is invoked by the access methods of the block plugin system and
  * should be used to alter the block access rules defined by a module from
  * another module.
  *
  * @param \Drupal\block\Plugin\Core\Entity\Block $block
- *   The block instance.
+ *   The block entity.
+ * @param string $operation
+ *   The operation to be performed, e.g., 'view', 'create', 'delete', 'update'.
+ * @param \Drupal\user\Plugin\Core\Entity\User $account
+ *   The user object to perform the access check operation on.
+ * @param string $langcode
+ *   The language code to perform the access check operation on.
  *
  * @return bool
  *   TRUE will allow access whereas FALSE will deny access to the block.
@@ -114,7 +140,7 @@ function hook_block_view_NAME_alter(array &$build, \Drupal\block\BlockInterface
  * @see \Drupal\block\BlockBase::access()
  * @see \Drupal\block\BlockBase::blockAccess()
  */
-function hook_block_access(\Drupal\block\Plugin\Core\Entity\Block $block) {
+function hook_block_access(\Drupal\block\Plugin\Core\Entity\Block $block, $operation, \Drupal\user\Plugin\Core\Entity\User $account, $langcode) {
   // Example code that would prevent displaying the 'Powered by Drupal' block in
   // a region different than the footer.
   if ($block->get('plugin') == 'system_powered_by_block' && $block->get('region') != 'footer') {
@@ -123,5 +149,20 @@ function hook_block_access(\Drupal\block\Plugin\Core\Entity\Block $block) {
 }
 
 /**
+ * Allow or deny access to a specific block plugin.
+ *
+ * @param \Drupal\block\BlockInterface $block
+ *   The block plugin.
+ *
+ * @return bool
+ *   TRUE will allow access whereas FALSE will deny access to the block.
+ */
+function hook_block_plugin_access(\Drupal\block\BlockInterface $block) {
+  if ($block->getPluginID() == 'my_plugin_id') {
+    return FALSE;
+  }
+}
+
+/**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index d9d2106..1a00013 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Utility\NestedArray;
 
 /**
  * Denotes that a block is not enabled in any region and should not be shown.
@@ -89,9 +90,17 @@ function block_help($path, $arg) {
 function block_theme() {
   return array(
     'block' => array(
-      'render element' => 'elements',
+      'variables' => array(
+        'content' => NULL,
+        'configuration' => NULL,
+        'plugin_id' => NULL,
+      ),
       'template' => 'block',
     ),
+    'block_wrapper' => array(
+      'render element' => 'elements',
+      'template' => 'block-wrapper',
+    ),
     'block_admin_display_form' => array(
       'template' => 'block-admin-display-form',
       'file' => 'block.admin.inc',
@@ -333,11 +342,10 @@ function _block_get_renderable_region($list = array()) {
       $id = array_pop($key_components);
       $build[$key] = array(
         '#block' => $block,
-        '#weight' => $block->get('weight'),
-        '#theme_wrappers' => array('block'),
+        '#theme_wrappers' => array('block_wrapper'),
         '#pre_render' => array('_block_get_renderable_block'),
         '#cache' => array(
-          'keys' => array($id, $block->get('module')),
+          'keys' => array($id, $settings['module']),
           'granularity' => $settings['cache'],
           'bin' => 'block',
           'tags' => array('content' => TRUE),
@@ -352,6 +360,12 @@ function _block_get_renderable_region($list = array()) {
     // draw attention on it.
     if (isset($build[$key]) && !in_array($block->get('plugin'), array('system_help_block', 'system_main_block'))) {
       $build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($key));
+
+      // If there are any nested contextual links, move them to the top level.
+      if (isset($build[$key]['content']['#content']['#contextual_links'])) {
+        $build[$key]['#contextual_links'] += $build[$key]['content']['#content']['#contextual_links'];
+        unset($build[$key]['content']['#content']['#contextual_links']);
+      }
     }
   }
   return $build;
@@ -496,7 +510,7 @@ function _block_get_renderable_block($element) {
   $block = $element['#block'];
   // Don't bother to build blocks that aren't accessible.
   if ($element['#access'] = $block->access()) {
-    $element += entity_view($block, 'block');
+    $element = NestedArray::mergeDeep($element, entity_view($block, 'block'));
   }
   return $element;
 }
@@ -513,50 +527,42 @@ function block_rebuild() {
 }
 
 /**
- * Processes variables for block.tpl.php.
+ * Processes variables for block-wrapper.tpl.php.
  *
  * Prepares the values passed to the theme_block function to be passed
  * into a pluggable template engine. Uses block properties to generate a
  * series of template file suggestions. If none are found, the default
- * block.tpl.php is used.
+ * block-wrapper.tpl.php is used.
  *
- * Most themes utilize their own copy of block.tpl.php. The default is located
- * inside "modules/block/block.tpl.php". Look in there for the full list of
- * variables.
+ * Most themes utilize their own copy of block-wrapper.tpl.php. The default is
+ * located inside "core/modules/block/templates/block-wrapper.tpl.php". Look in
+ * there for the full list of variables.
  *
- * The $variables array contains the following arguments:
- * - $block
- *
- * @see block.tpl.php
+ * @see block-wrapper.tpl.php
  */
-function template_preprocess_block(&$variables) {
+function template_preprocess_block_wrapper(&$variables) {
   $block_counter = &drupal_static(__FUNCTION__, array());
 
-  $variables['block'] = (object) $variables['elements']['#block_config'];
-  // If the block title is configured to be hidden, set it to an empty string.
-  if (empty($variables['elements']['#block']->label_display)) {
-    $variables['block']->label_hidden = $variables['block']->label;
-    $variables['block']->label = '';
-  }
-
   // All blocks get an independent counter for each region.
-  if (!isset($block_counter[$variables['block']->region])) {
-    $block_counter[$variables['block']->region] = 1;
+  $region = $variables['elements']['#block']->get('region');
+  if (!isset($block_counter[$region])) {
+    $block_counter[$region] = 1;
   }
   // Same with zebra striping.
-  $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even';
-  $variables['block_id'] = $block_counter[$variables['block']->region]++;
+  $variables['block_zebra'] = ($block_counter[$region] % 2) ? 'odd' : 'even';
+  $variables['block_id'] = $block_counter[$region]++;
 
   // Create the $content variable that templates expect.
   $variables['content'] = $variables['elements']['#children'];
 
-  $variables['attributes']['class'][] = drupal_html_class('block-' . $variables['block']->module);
+  $settings = $variables['elements']['#block']->get('settings');
+  $variables['attributes']['class'][] = drupal_html_class('block-' . $settings['module']);
 
   // Add default class for block content.
   $variables['content_attributes']['class'][] = 'content';
 
-  $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
-  $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
+  $variables['theme_hook_suggestions'][] = 'block_wrapper__' . $region;
+  $variables['theme_hook_suggestions'][] = 'block_wrapper__' . $settings['module'];
   // Hyphens (-) and underscores (_) play a special role in theme suggestions.
   // Theme suggestions should only contain underscores, because within
   // drupal_find_theme_templates(), underscores are converted to hyphens to
@@ -569,7 +575,7 @@ function template_preprocess_block(&$variables) {
   // We can safely explode on : because we know the Block plugin type manager
   // enforces that delimiter for all derivatives.
   $parts = explode(':', $variables['elements']['#block']->get('plugin'));
-  $suggestion = 'block';
+  $suggestion = 'block_wrapper';
   while ($part = array_shift($parts)) {
     $variables['theme_hook_suggestions'][] = $suggestion .= '__' . strtr($part, '-', '_');
   }
@@ -577,8 +583,24 @@ function template_preprocess_block(&$variables) {
   if ($id = $variables['elements']['#block']->id()) {
     $config_id = explode('.', $id);
     $machine_name = array_pop($config_id);
-    $variables['block_html_id'] = drupal_html_id('block-' . $machine_name);
-    $variables['theme_hook_suggestions'][] = 'block__' . $machine_name;
+    $variables['block_html_id'] = drupal_html_id('block-wrapper-' . $machine_name);
+    $variables['theme_hook_suggestions'][] = 'block_wrapper__' . $machine_name;
+  }
+}
+
+/**
+ * Processes variables for block.tpl.php.
+ */
+function template_preprocess_block(&$variables) {
+  $configuration = $variables['configuration'];
+
+  // Add default class for block content.
+  $variables['content_attributes']['class'][] = 'content';
+
+  $variables['label'] = check_plain($configuration['label']);
+  if ($configuration['label_display'] != BLOCK_LABEL_VISIBLE) {
+    $variables['label_hidden'] = $variables['label'];
+    $variables['label'] = '';
   }
 }
 
@@ -589,10 +611,11 @@ function template_preprocess_block(&$variables) {
  */
 function block_user_role_delete($role) {
   foreach (entity_load_multiple('block') as $block_id => $block) {
-    $visibility = $block->get('visibility');
+    $settings = $block->get('settings');
+    $visibility = $settings['visibility'];
     if (isset($visibility['roles']['roles'][$role->id()])) {
       unset($visibility['roles']['roles'][$role->id()]);
-      $block->set('visibility', $visibility);
+      $block->getPlugin()->setConfig('visibility', $visibility);
       $block->save();
     }
   }
@@ -629,10 +652,11 @@ function block_admin_paths() {
 function block_language_delete($language) {
   // Remove the block visibility settings for the deleted language.
   foreach (entity_load_multiple('block') as $block_id => $block) {
-    $visibility = $block->get('visibility');
+    $settings = $block->get('settings');
+    $visibility = $settings['visibility'];
     if (isset($visibility['language']['langcodes'][$language->langcode])) {
       unset($visibility['language']['langcodes'][$language->langcode]);
-      $block->set('visibility', $visibility);
+      $block->getPlugin()->setConfig('visibility', $visibility);
       $block->save();
     }
   }
diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module
index a3ce18c..4244f02 100644
--- a/core/modules/block/custom_block/custom_block.module
+++ b/core/modules/block/custom_block/custom_block.module
@@ -8,7 +8,7 @@
 use Drupal\custom_block\Plugin\Core\Entity\CustomBlockType;
 use Drupal\custom_block\Plugin\Core\Entity\CustomBlock;
 use Drupal\custom_block\Plugin\block\block\CustomBlockBlock;
-use Drupal\block\Plugin\Core\Entity\Block;
+use Drupal\block\BlockInterface;
 
 /**
  * Implements hook_menu_local_tasks().
@@ -288,15 +288,3 @@ function custom_block_admin_paths() {
   );
   return $paths;
 }
-
-/**
- * Implements hook_block_view_alter().
- */
-function custom_block_block_view_alter(array &$build, Block $block) {
-  // Add contextual links for custom blocks.
-  if ($block->getPlugin() instanceof CustomBlockBlock) {
-    // Move contextual links from inner content to outer wrapper.
-    $build['#contextual_links']['custom_block'] = $build['content']['#contextual_links']['custom_block'];
-    unset($build['content']['#contextual_links']['custom_block']);
-  }
-}
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php
index 592f150..71a50bd 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php
@@ -43,9 +43,6 @@ public function getDerivativeDefinitions(array $base_plugin_definition) {
     $custom_blocks = entity_load_multiple('custom_block');
     foreach ($custom_blocks as $custom_block) {
       $this->derivatives[$custom_block->uuid->value] = $base_plugin_definition;
-      $this->derivatives[$custom_block->uuid->value]['settings'] = array(
-        'info' => $custom_block->info->value,
-      ) + $base_plugin_definition['settings'];
       $this->derivatives[$custom_block->uuid->value]['admin_label'] = $custom_block->info->value;
     }
     return $this->derivatives;
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlockBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlockBlock.php
index 9219264..3ed308f 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlockBlock.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlockBlock.php
@@ -18,26 +18,20 @@
  *  id = "custom_block",
  *  admin_label = @Translation("Custom block"),
  *  module = "custom_block",
- *  derivative = "Drupal\custom_block\Plugin\Derivative\CustomBlock",
- *  settings = {
- *    "status" = TRUE,
- *    "info" = "",
- *    "view_mode" = "full"
- *   }
+ *  derivative = "Drupal\custom_block\Plugin\Derivative\CustomBlock"
  * )
  */
 class CustomBlockBlock extends BlockBase {
 
   /**
-   * Overrides \Drupal\block\BlockBase::getConfig().
+   * Overrides \Drupal\block\BlockBase::settings().
    */
-  public function getConfig() {
-    $definition = $this->getDefinition();
-    $this->configuration = parent::getConfig();
-    $this->configuration['status'] = $definition['settings']['status'];
-    $this->configuration['info'] = $definition['settings']['info'];
-    $this->configuration['view_mode'] = $definition['settings']['view_mode'];
-    return $this->configuration;
+  public function settings() {
+    return array(
+      'status' => TRUE,
+      'info' => '',
+      'view_mode' => 'full',
+    );
   }
 
   /**
@@ -73,9 +67,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     // @todo Clean up when http://drupal.org/node/1874498 lands.
     list(, $uuid) = explode(':', $this->getPluginId());
     if ($block = entity_load_by_uuid('custom_block', $uuid)) {
diff --git a/core/modules/block/lib/Drupal/block/BlockAccessController.php b/core/modules/block/lib/Drupal/block/BlockAccessController.php
index 8e8a563..253cbe4 100644
--- a/core/modules/block/lib/Drupal/block/BlockAccessController.php
+++ b/core/modules/block/lib/Drupal/block/BlockAccessController.php
@@ -20,7 +20,17 @@ class BlockAccessController extends EntityAccessController {
    * Overrides \Drupal\Core\Entity\EntityAccessController::viewAccess().
    */
   public function viewAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAULT, User $account = NULL) {
-    return $entity->getPlugin()->access();
+    // @todo \Drupal\Core\Entity\EntityAccessController::viewAccess() casts to a
+    //   Boolean, which incorrectly implies that access was always explicitly
+    //   granted or denied. To work around this call
+    //   \Drupal\Core\Entity\EntityAccessController::access() directly and check
+    //   the return type.
+    $access = $this->access($entity, 'view', $langcode, $account);
+    if ($access !== FALSE) {
+      // If entity access did not explicitly deny access, consult the plugin.
+      return $entity->getPlugin()->access();
+    }
+    return $access;
   }
 
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockBase.php b/core/modules/block/lib/Drupal/block/BlockBase.php
index 4de2a59..f1c41cb 100644
--- a/core/modules/block/lib/Drupal/block/BlockBase.php
+++ b/core/modules/block/lib/Drupal/block/BlockBase.php
@@ -8,7 +8,6 @@
 namespace Drupal\block;
 
 use Drupal\Component\Plugin\PluginBase;
-use Drupal\block\Plugin\Core\Entity\Block;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 
 /**
@@ -20,20 +19,19 @@
  */
 abstract class BlockBase extends PluginBase implements BlockInterface {
 
-  /**
-   * The entity using this plugin.
-   *
-   * @var \Drupal\block\Plugin\Core\Entity\Block
-   */
-  protected $entity;
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
-   */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, Block $entity) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
-    $this->entity = $entity;
+    $this->configuration += $this->settings() + array(
+      'label' => '',
+      'admin_label' => $plugin_definition['admin_label'],
+      'weight' => '',
+      'module' => $plugin_definition['module'],
+      'label_display' => BLOCK_LABEL_VISIBLE,
+      'visibility' => array(),
+      'cache' => DRUPAL_NO_CACHE,
+      'status' => TRUE,
+    );
   }
 
   /**
@@ -65,18 +63,6 @@ public function settings() {
    * @see \Drupal\Component\Plugin\PluginBase::$configuration
    */
   public function getConfig() {
-    if (empty($this->configuration)) {
-      // If the plugin configuration is not already set, initialize it with the
-      // default settings for the block plugin.
-      $this->configuration = $this->settings();
-
-      $definition = $this->getDefinition();
-      if (isset($definition['admin_label'])) {
-        $this->configuration += array('admin_label' => $definition['admin_label']);
-      }
-    }
-    // Ensure that the default cache mode is set.
-    $this->configuration += array('cache' => DRUPAL_NO_CACHE);
     return $this->configuration;
   }
 
@@ -142,7 +128,7 @@ public function access() {
     global $user;
 
     // Deny access to disabled blocks.
-    if (!$this->entity->get('status')) {
+    if (!$this->configuration['status']) {
       return FALSE;
     }
 
@@ -150,7 +136,7 @@ public function access() {
     // If a block has no roles associated, it is displayed for every role.
     // For blocks with roles associated, if none of the user's roles matches
     // the settings from this block, access is denied.
-    $visibility = $this->entity->get('visibility');
+    $visibility = $this->configuration['visibility'];
     if (!empty($visibility['role']['roles']) && !array_intersect(array_filter($visibility['role']['roles']), array_keys($user->roles))) {
       // No match.
       return FALSE;
@@ -201,8 +187,8 @@ public function access() {
     }
 
     // Check other modules for block access rules.
-    foreach (module_implements('block_access') as $module) {
-      if (module_invoke($module, 'block_access', $this->entity) === FALSE) {
+    foreach (module_implements('block_plugin_access') as $module) {
+      if (module_invoke($module, 'block_plugin_access', $this) === FALSE) {
         return FALSE;
       }
     }
@@ -222,12 +208,7 @@ public function access() {
    * @see \Drupal\block\BlockBase::blockForm()
    */
   public function form($form, &$form_state) {
-    $entity = $form_state['entity'];
     $definition = $this->getDefinition();
-    $form['id'] = array(
-      '#type' => 'value',
-      '#value' => $entity->id(),
-    );
     $form['module'] = array(
       '#type' => 'value',
       '#value' => $definition['module'],
@@ -237,38 +218,15 @@ public function form($form, &$form_state) {
       '#type' => 'textfield',
       '#title' => t('Title'),
       '#maxlength' => 255,
-      '#default_value' => !$entity->isNew() ? $entity->label() : $definition['admin_label'],
+      '#default_value' => !empty($this->configuration['label']) ? $this->configuration['label'] : $this->configuration['admin_label'],
       '#required' => TRUE,
     );
     $form['label_display'] = array(
       '#type' => 'checkbox',
       '#title' => t('Display title'),
-      '#default_value' => $entity->label_display == BLOCK_LABEL_VISIBLE ? TRUE : FALSE,
+      '#default_value' => $this->configuration['label_display'] == BLOCK_LABEL_VISIBLE,
       '#return_value' => BLOCK_LABEL_VISIBLE,
     );
-    $form['machine_name'] = array(
-      '#type' => 'machine_name',
-      '#title' => t('Machine name'),
-      '#maxlength' => 64,
-      '#description' => t('A unique name to save this block configuration. Must be alpha-numeric and be underscore separated.'),
-      '#default_value' => $entity->id(),
-      '#machine_name' => array(
-        'exists' => 'block_load',
-        'replace_pattern' => '[^a-z0-9_.]+',
-      ),
-      '#required' => TRUE,
-      '#disabled' => !$entity->isNew(),
-    );
-
-    // Region settings.
-    $form['region'] = array(
-      '#type' => 'select',
-      '#title' => t('Region'),
-      '#description' => t('Select the region where this block should be displayed.'),
-      '#default_value' => $entity->get('region'),
-      '#empty_value' => BLOCK_REGION_NONE,
-      '#options' => system_region_list($entity->get('theme'), REGIONS_VISIBLE),
-    );
 
     // Visibility settings.
     $form['visibility'] = array(
@@ -279,6 +237,7 @@ public function form($form, &$form_state) {
       ),
       '#tree' => TRUE,
       '#weight' => 10,
+      '#parents' => array('visibility'),
     );
 
     // Per-path visibility.
@@ -293,7 +252,7 @@ public function form($form, &$form_state) {
     // @todo remove this access check and inject it in some other way. In fact
     //   this entire visibility settings section probably needs a separate user
     //   interface in the near future.
-    $visibility = $entity->get('visibility');
+    $visibility = $this->configuration['visibility'];
     $access = user_access('use PHP for settings');
     if (!empty($visibility['path']['visibility']) && $visibility['path']['visibility'] == BLOCK_VISIBILITY_PHP && !$access) {
       $form['visibility']['path']['visibility'] = array(
@@ -394,7 +353,7 @@ public function form($form, &$form_state) {
     );
 
     // Add plugin-specific settings for this block type.
-    $form['settings'] = $this->blockForm(array(), $form_state);
+    $form += $this->blockForm($form, $form_state);
     return $form;
   }
 
@@ -429,14 +388,12 @@ public function blockForm($form, &$form_state) {
    * @see \Drupal\block\BlockBase::blockValidate()
    */
   public function validate($form, &$form_state) {
-    if (!empty($form['machine_name']['#disabled'])) {
-      $config_id = explode('.', $form_state['values']['machine_name']);
-      $form_state['values']['machine_name'] = array_pop($config_id);
-    }
-    $form_state['values']['visibility']['role']['roles'] = array_filter($form_state['values']['visibility']['role']['roles']);
-    if ($form_state['entity']->isNew()) {
-      form_set_value($form['id'], $form_state['entity']->get('theme') . '.' . $form_state['values']['machine_name'], $form_state);
-    }
+    // @todo The final location of visibility is unresolved. This moves the
+    //   values into the plugin settings, out of the entity values.
+    $form_state['values']['settings']['visibility'] = $form_state['values']['visibility'];
+    unset($form_state['values']['visibility']);
+
+    $form_state['values']['settings']['visibility']['role']['roles'] = array_filter($form_state['values']['settings']['visibility']['role']['roles']);
     $this->blockValidate($form, $form_state);
   }
 
@@ -471,10 +428,7 @@ public function blockValidate($form, &$form_state) {}
   public function submit($form, &$form_state) {
     if (!form_get_errors()) {
       $this->blockSubmit($form, $form_state);
-
-      drupal_set_message(t('The block configuration has been saved.'));
-      cache_invalidate_tags(array('content' => TRUE));
-      $form_state['redirect'] = 'admin/structure/block/list/block_plugin_ui:' . $form_state['entity']->get('theme');
+      $this->configuration = $form_state['values']['settings'] + $this->configuration;
     }
   }
 
@@ -496,4 +450,31 @@ public function submit($form, &$form_state) {
    */
   public function blockSubmit($form, &$form_state) {}
 
+  /**
+   * Implements \Drupal\block\BlockInterface::build().
+   */
+  public function build() {
+    $build = array();
+    $plugin_id = $this->getPluginId();
+    if ($content = $this->blockBuild()) {
+      $build = array(
+        '#theme' => 'block',
+        '#content' => $content,
+        '#configuration' => $this->configuration,
+        '#plugin_id' => $plugin_id,
+      );
+    }
+    list($name) = explode(':', $plugin_id . ':');
+    drupal_alter(array('block_view', "block_view_$name"), $build, $this);
+    return $build;
+  }
+
+  /**
+   * Adds block-type-specific render handling for the block plugin.
+   *
+   * @return array
+   *   A renderable array representing the content of this block.
+   */
+  abstract protected function blockBuild();
+
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockFormController.php b/core/modules/block/lib/Drupal/block/BlockFormController.php
index 8e95248..6f95259 100644
--- a/core/modules/block/lib/Drupal/block/BlockFormController.php
+++ b/core/modules/block/lib/Drupal/block/BlockFormController.php
@@ -19,7 +19,38 @@ class BlockFormController extends EntityFormController {
    * Overrides \Drupal\Core\Entity\EntityFormController::form().
    */
   public function form(array $form, array &$form_state, EntityInterface $entity) {
-    return $entity->getPlugin()->form($form, $form_state);
+    $form['#tree'] = TRUE;
+    $form['id'] = array(
+      '#type' => 'value',
+      '#value' => $entity->id(),
+    );
+    $form['settings'] = $entity->getPlugin()->form(array(), $form_state);
+
+    $form['machine_name'] = array(
+      '#type' => 'machine_name',
+      '#title' => t('Machine name'),
+      '#maxlength' => 64,
+      '#description' => t('A unique name to save this block configuration. Must be alpha-numeric and be underscore separated.'),
+      '#default_value' => $entity->id(),
+      '#machine_name' => array(
+        'exists' => 'block_load',
+        'replace_pattern' => '[^a-z0-9_.]+',
+        'source' => array('settings', 'label'),
+      ),
+      '#required' => TRUE,
+      '#disabled' => !$entity->isNew(),
+    );
+
+    // Region settings.
+    $form['region'] = array(
+      '#type' => 'select',
+      '#title' => t('Region'),
+      '#description' => t('Select the region where this block should be displayed.'),
+      '#default_value' => $entity->get('region'),
+      '#empty_value' => BLOCK_REGION_NONE,
+      '#options' => system_region_list($entity->get('theme'), REGIONS_VISIBLE),
+    );
+    return $form;
   }
 
   /**
@@ -38,6 +69,13 @@ public function validate(array $form, array &$form_state) {
     parent::validate($form, $form_state);
 
     $entity = $this->getEntity($form_state);
+    if ($entity->isNew()) {
+      form_set_value($form['id'], $entity->get('theme') . '.' . $form_state['values']['machine_name'], $form_state);
+    }
+    if (!empty($form['machine_name']['#disabled'])) {
+      $config_id = explode('.', $form_state['values']['machine_name']);
+      $form_state['values']['machine_name'] = array_pop($config_id);
+    }
     $entity->getPlugin()->validate($form, $form_state);
   }
 
@@ -52,8 +90,11 @@ public function submit(array $form, array &$form_state) {
     $entity->getPlugin()->submit($form, $form_state);
 
     // Save the settings of the plugin.
-    $entity->set('settings', $entity->getPlugin()->getConfig());
     $entity->save();
+
+    drupal_set_message(t('The block configuration has been saved.'));
+    cache_invalidate_tags(array('content' => TRUE));
+    $form_state['redirect'] = 'admin/structure/block/list/block_plugin_ui:' . $entity->get('theme');
   }
 
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockPluginBag.php b/core/modules/block/lib/Drupal/block/BlockPluginBag.php
new file mode 100644
index 0000000..73d50c0
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/BlockPluginBag.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\BlockPluginBag.
+ */
+
+namespace Drupal\block;
+
+use Drupal\block\Plugin\Core\Entity\Block;
+use Drupal\Component\Plugin\PluginBag;
+use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Component\Plugin\Exception\PluginException;
+
+/**
+ * Provides a collection of block plugins.
+ */
+class BlockPluginBag extends PluginBag {
+
+  /**
+   * The manager used to instantiate the plugins.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $manager;
+
+  /**
+   * Constructs a BlockPluginBag object.
+   *
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
+   *   The manager to be used for instantiating plugins.
+   * @param array $instance_ids
+   *   The ids of the plugin instances with which we are dealing.
+   * @param Plugin\Core\Entity\Block $entity
+   *   The Block entity that holds our configuration.
+   */
+  public function __construct(PluginManagerInterface $manager, array $instance_ids, Block $entity) {
+    $this->manager = $manager;
+    $this->entity = $entity;
+
+    $this->instanceIDs = drupal_map_assoc($instance_ids);
+  }
+
+  /**
+   * Overrides \Drupal\Component\Plugin\PluginBag::initializePlugin().
+   */
+  protected function initializePlugin($instance_id) {
+    if (!$instance_id) {
+      throw new PluginException(format_string("The block '@block' did not specify a plugin.", array('@block' => $this->entity->id())));
+    }
+    if (isset($this->pluginInstances[$instance_id])) {
+      return;
+    }
+
+    $settings = $this->entity->get('settings');
+    try {
+      $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $settings);
+    }
+    catch (PluginException $e) {
+      $module = $settings['module'];
+      // Ignore blocks belonging to disabled modules, but re-throw valid
+      // exceptions when the module is enabled and the plugin is misconfigured.
+      if (!$module || module_exists($module)) {
+        throw $e;
+      }
+    }
+  }
+
+}
diff --git a/core/modules/block/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php
index e1c560e..73cc4cd 100644
--- a/core/modules/block/lib/Drupal/block/BlockRenderController.php
+++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php
@@ -23,42 +23,6 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
   }
 
   /**
-   * Provides entity-specific defaults to the build process.
-   *
-   * @param Drupal\Core\Entity\EntityInterface $entity
-   *   The entity for which the defaults should be provided.
-   * @param string $view_mode
-   *   The view mode that should be used.
-   * @param string $langcode
-   *   (optional) For which language the entity should be prepared, defaults to
-   *   the current content language.
-   *
-   * @return array
-   *   An array of defaults to add into the entity render array.
-   */
-  protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) {
-    // @todo \Drupal\block\Tests\BlockTest::testCustomBlock() assuemes that a
-    //   block can be rendered without any of its wrappers. To do so, it uses a
-    //   custom view mode, and we choose to only add the wrappers on the default
-    //   view mode, 'block'.
-    if ($view_mode != 'block') {
-      return array();
-    }
-
-    return array(
-      '#block' => $entity,
-      '#weight' => $entity->get('weight'),
-      '#theme_wrappers' => array('block'),
-      '#block_config' => array(
-        'id' => $entity->get('plugin'),
-        'region' => $entity->get('region'),
-        'module' => $entity->get('module'),
-        'label' => check_plain($entity->label()),
-      ),
-    );
-  }
-
-  /**
    * Implements Drupal\Core\Entity\EntityRenderControllerInterface::view().
    */
   public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
@@ -73,15 +37,16 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
     $build = array();
     foreach ($entities as $entity_id => $entity) {
       // Allow blocks to be empty, do not add in the defaults.
-      if ($content = $entity->getPlugin()->build()) {
-        $build[$entity_id] = $this->getBuildDefaults($entity, $view_mode, $langcode);
+      $plugin = $entity->getPlugin();
+      if ($content = $plugin->build()) {
+        $build[$entity_id]['#block'] = $entity;
+        $build[$entity_id]['#theme_wrappers'][] = 'block_wrapper';
       }
       $build[$entity_id]['content'] = $content;
 
       // All blocks, even when empty, should be available for altering.
-      $id = str_replace(':', '__', $entity->get('plugin'));
       list(, $name) = $entity->id();
-      drupal_alter(array('block_view', "block_view_$id", "block_view_$name"), $build[$entity_id], $entity);
+      drupal_alter(array('block_wrapper_view', "block_wrapper_view_$name"), $build[$entity_id], $plugin);
 
     }
     return $build;
diff --git a/core/modules/block/lib/Drupal/block/BlockStorageController.php b/core/modules/block/lib/Drupal/block/BlockStorageController.php
index a873c5d..a59854c 100644
--- a/core/modules/block/lib/Drupal/block/BlockStorageController.php
+++ b/core/modules/block/lib/Drupal/block/BlockStorageController.php
@@ -16,20 +16,6 @@
 class BlockStorageController extends ConfigStorageController {
 
   /**
-   * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::create().
-   */
-  public function create(array $values) {
-    $entity = parent::create($values);
-
-    if (!$entity->get('module')) {
-      $definition = $entity->getPlugin()->getDefinition();
-      $entity->set('module', $definition['module']);
-    }
-
-    return $entity;
-  }
-
-  /**
    * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::load().
    */
   public function load(array $ids = NULL) {
@@ -53,4 +39,13 @@ public function loadByProperties(array $values = array()) {
     return $blocks;
   }
 
+  /**
+   * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::preSave().
+   */
+  protected function preSave(EntityInterface $entity) {
+    parent::preSave($entity);
+
+    $entity->set('settings', $entity->getPlugin()->getConfig());
+  }
+
 }
diff --git a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
index 077a81e..c5736c1 100644
--- a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
+++ b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
-use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\block\BlockPluginBag;
 
 /**
  * Defines a Block configuration entity class.
@@ -53,17 +53,6 @@ class Block extends ConfigEntityBase {
   public $label;
 
   /**
-   * Whether the block label is displayed to end users.
-   *
-   * When this is set to BLOCK_LABEL_VISIBLE (the default value), the label is
-   * rendered as header in the block markup. Otherwise, the label is passed
-   * to the block template as a separate $label_hidden variable.
-   *
-   * @var string
-   */
-  public $label_display = BLOCK_LABEL_VISIBLE;
-
-  /**
    * The block UUID.
    *
    * @var string
@@ -78,13 +67,6 @@ class Block extends ConfigEntityBase {
   protected $settings = array();
 
   /**
-   * The plugin instance.
-   *
-   * @var \Drupal\block\BlockInterface
-   */
-  protected $instance;
-
-  /**
    * The region this block is placed in.
    *
    * @var string
@@ -92,32 +74,27 @@ class Block extends ConfigEntityBase {
   protected $region = BLOCK_REGION_NONE;
 
   /**
-   * Settings to control the block visibility.
+   * The plugin instance ID.
    *
-   * @var array
+   * @var string
    */
-  protected $visibility = array();
+  protected $plugin;
 
   /**
-   * The weight of the block.
+   * The plugin bag that holds the block plugin for this entity.
    *
-   * @var int
+   * @var \Drupal\block\BlockPluginBag
    */
-  protected $weight;
+  protected $pluginBag;
 
   /**
-   * The module owning this plugin.
-   *
-   * @var string
+   * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::__construct();
    */
-  protected $module;
+  public function __construct(array $values, $entity_type) {
+    parent::__construct($values, $entity_type);
 
-  /**
-   * The plugin instance ID.
-   *
-   * @var string
-   */
-  protected $plugin;
+    $this->pluginBag = new BlockPluginBag(\Drupal::service('plugin.manager.block'), array($this->plugin), $this);
+  }
 
   /**
    * Returns the plugin instance.
@@ -126,26 +103,7 @@ class Block extends ConfigEntityBase {
    *   The plugin instance for this block.
    */
   public function getPlugin() {
-    if (!$this->instance) {
-      // Throw an exception if no plugin string was provided.
-      if (!$this->plugin) {
-        throw new PluginException(format_string("The block '@block' did not specify a plugin.", array('@block' => $this->id())));
-      }
-
-      // Create a plugin instance and store its configuration as settings.
-      try {
-        $this->instance = drupal_container()->get('plugin.manager.block')->createInstance($this->plugin, $this->settings, $this);
-        $this->settings += $this->instance->getConfig();
-      }
-      catch (PluginException $e) {
-        // Ignore blocks belonging to disabled modules, but re-throw valid
-        // exceptions when the module is enabled and the plugin is misconfigured.
-        if (empty($this->module) || module_exists($this->module)) {
-          throw $e;
-        }
-      }
-    }
-    return $this->instance;
+    return $this->pluginBag->get($this->plugin);
   }
 
   /**
@@ -162,6 +120,14 @@ public function uri() {
   }
 
   /**
+   * Overrides \Drupal\Core\Entity\Entity::label();
+   */
+  public function label($langcode = NULL) {
+    $settings = $this->get('settings');
+    return $settings['label'];
+  }
+
+  /**
    * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::get();
    */
   public function get($property_name, $langcode = NULL) {
@@ -177,21 +143,12 @@ public function get($property_name, $langcode = NULL) {
    * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::getExportProperties();
    */
   public function getExportProperties() {
+    $properties = parent::getExportProperties();
     $names = array(
-      'id',
-      'label',
-      'label_display',
-      'uuid',
       'region',
-      'weight',
-      'module',
-      'status',
-      'visibility',
       'plugin',
       'settings',
-      'langcode',
     );
-    $properties = array();
     foreach ($names as $name) {
       $properties[$name] = $this->get($name);
     }
diff --git a/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php b/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
index b102d4b..9ff342b 100644
--- a/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
+++ b/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
-use Drupal\block\Plugin\Core\Entity\Block;
 
 /**
  * Manages discovery and instantiation of block plugins.
@@ -35,15 +34,8 @@ public function __construct(array $namespaces) {
     $this->discovery = new DerivativeDiscoveryDecorator($this->discovery);
     $this->discovery = new AlterDecorator($this->discovery, 'block');
     $this->discovery = new CacheDecorator($this->discovery, 'block_plugins:' . language(LANGUAGE_TYPE_INTERFACE)->langcode, 'block', CacheBackendInterface::CACHE_PERMANENT, array('block'));
-  }
 
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginManagerBase::createInstance().
-   */
-  public function createInstance($plugin_id, array $configuration = array(), Block $entity = NULL) {
-    $plugin_definition = $this->discovery->getDefinition($plugin_id);
-    $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
-    return new $plugin_class($configuration, $plugin_id, $plugin_definition, $entity);
+    $this->factory = new DefaultFactory($this->discovery);
   }
 
 }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
index 96f9343..46454a6 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
@@ -192,9 +192,7 @@ function testCachePerPage() {
    * Private helper method to set the test block's cache mode.
    */
   private function setCacheMode($cache_mode) {
-    $settings = $this->block->get('settings');
-    $settings['cache'] = $cache_mode;
-    $this->block->set('settings', $settings);
+    $this->block->getPlugin()->setConfig('cache', $cache_mode);
     $this->block->save();
   }
 
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockHtmlIdTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockHtmlIdTest.php
index ed2f280..7d1aeb8 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockHtmlIdTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockHtmlIdTest.php
@@ -48,7 +48,7 @@ function setUp() {
    */
   function testHtmlId() {
     $this->drupalGet('');
-    $this->assertRaw('id="block-test-id-block"', 'HTML ID for test block is valid.');
+    $this->assertRaw('id="block-wrapper-test-id-block"', 'HTML ID for test block is valid.');
     $elements = $this->xpath('//div[contains(@class, :div-class)]/div/ul[contains(@class, :ul-class)]/li', array(':div-class' => 'block-system', ':ul-class' => 'menu'));
     $this->assertTrue(!empty($elements), 'The proper block markup was found.');
   }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php
new file mode 100644
index 0000000..ad4c9a3
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php
@@ -0,0 +1,175 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\Tests\BlockInterfaceTest.
+ */
+
+namespace Drupal\block\Tests;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Test BlockInterface methods to ensure no external dependencies exist.
+ */
+class BlockInterfaceTest extends DrupalUnitTestBase {
+  public static $modules = array('system', 'block', 'block_test', 'user');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Block Plugins Tests',
+      'description' => 'Tests that the block plugin can work properly without a supporting entity.',
+      'group' => 'Block',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+    $this->installSchema('user', 'role_permission');
+  }
+
+  /**
+   * Test configuration and subsequent form() and build() method calls.
+   *
+   * This test is attempting to test the existing block plugin api and all
+   * functionality that is expected to remain consistent. The arrays that are
+   * used for comparison can change, but only to include elements that are
+   * contained within BlockBase or the plugin being tested. Likely these
+   * comparison arrays should get smaller, not larger, as more form/build
+   * elements are moved into a more suitably responsible class.
+   *
+   * Instantiation of the plugin is the primary element being tested here. The
+   * subsequent method calls are just attempting to cause a failure if a
+   * dependency outside of the plugin configuration is required.
+   */
+  public function testBlockInterface() {
+    $manager = \Drupal::service('plugin.manager.block');
+    $configuration = array(
+      'label' => 'Custom Display Message',
+    );
+    $expected_configuration = array(
+      'label' => 'Custom Display Message',
+      'display_message' => 'no message set',
+      'admin_label' => 'Display message',
+      'weight' => '',
+      'module' => 'block_test',
+      'label_display' => BLOCK_LABEL_VISIBLE,
+      'visibility' =>
+      array (
+      ),
+      'cache' => DRUPAL_NO_CACHE,
+      'status' => TRUE,
+    );
+    // Initial configuration of the block at construction time.
+    $display_block = $manager->createInstance('test_block_instantiation', $configuration);
+    $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block was configured correctly.');
+
+    // Updating an element of the configuration.
+    $display_block->setConfig('display_message', 'My custom display message.');
+    $expected_configuration['display_message'] = 'My custom display message.';
+    $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block configuration was updated correctly.');
+
+    $expected_form = array(
+      'module' => array(
+        '#type' => 'value',
+        '#value' => 'block_test',
+      ),
+      'label' => array(
+        '#type' => 'textfield',
+        '#title' => 'Title',
+        '#maxlength' => 255,
+        '#default_value' => 'Custom Display Message',
+        '#required' => TRUE,
+      ),
+      'label_display' => array(
+        '#type' => 'checkbox',
+        '#title' => 'Display title',
+        '#default_value' => TRUE,
+        '#return_value' => 'visible',
+      ),
+      'visibility' => array(
+        '#type' => 'vertical_tabs',
+        '#title' => 'Visibility settings',
+        '#attached' => array(
+          'js' => array(
+            0 => 'core/modules/block/block.js',
+          ),
+        ),
+        '#tree' => TRUE,
+        '#weight' => 10,
+        '#parents' => array(
+          0 => 'visibility',
+        ),
+        'path' => array(
+          '#type' => 'details',
+          '#title' => 'Pages',
+          '#collapsed' => TRUE,
+          '#group' => 'visibility',
+          '#weight' => 0,
+          'visibility' => array(
+            '#type' => 'radios',
+            '#title' => 'Show block on specific pages',
+            '#options' => array(
+              0 => 'All pages except those listed',
+              1 => 'Only the listed pages',
+            ),
+            '#default_value' => 0,
+          ),
+          'pages' => array(
+            '#type' => 'textarea',
+            '#title' => '<span class="element-invisible">Pages</span>',
+            '#default_value' => '',
+            '#description' => 'Specify pages by using their paths. Enter one path per line. The \'*\' character is a wildcard. Example paths are <em class="placeholder">user</em> for the current user\'s page and <em class="placeholder">user/*</em> for every user page. <em class="placeholder">&lt;front&gt;</em> is the front page.',
+          ),
+        ),
+        'role' => array(
+          '#type' => 'details',
+          '#title' => 'Roles',
+          '#collapsed' => TRUE,
+          '#group' => 'visibility',
+          '#weight' => 10,
+          'roles' => array(
+            '#type' => 'checkboxes',
+            '#title' => 'Show block for specific roles',
+            '#default_value' => array(
+            ),
+            '#options' => array(
+            ),
+            '#description' => 'Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.',
+          ),
+        ),
+      ),
+      'display_message' => array(
+        '#type' => 'textfield',
+        '#title' => t('Display message'),
+        '#default_value' => 'My custom display message.',
+      ),
+    );
+    $form_state = array();
+    // Ensure there are no form elements that do not belong to the plugin.
+    $this->assertIdentical($display_block->form(array(), $form_state), $expected_form, 'Only the expected form elements were present.');
+
+    $expected_build = array(
+      '#theme' => 'block',
+      '#content' => array(
+        '#children' => 'My custom display message.',
+      ),
+      '#configuration' => array(
+        'label' => 'Custom Display Message',
+        'display_message' => 'My custom display message.',
+        'admin_label' => 'Display message',
+        'weight' => '',
+        'module' => 'block_test',
+        'label_display' => BLOCK_LABEL_VISIBLE,
+        'visibility' =>
+        array (
+        ),
+        'cache' => DRUPAL_NO_CACHE,
+        'status' => TRUE,
+      ),
+      '#plugin_id' => 'test_block_instantiation',
+    );
+    // Ensure the build array is proper.
+    $this->assertIdentical($display_block->build(), $expected_build, 'The plugin returned the appropriate build array.');
+  }
+}
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
index f247648..685448d 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
@@ -104,8 +104,8 @@ public function testLanguageBlockVisibilityLanguageDelete() {
     $block = $this->drupalPlaceBlock('system_powered_by_block', $edit);
 
     // Check that we have the language in config after saving the setting.
-    $visibility = $block->get('visibility');
-    $setting = $visibility['language']['langcodes']['fr'];
+    $settings = $block->get('settings');
+    $setting = $settings['visibility']['language']['langcodes']['fr'];
     $this->assertTrue('fr' === $setting, 'Language is set in the block configuration.');
 
     // Delete the language.
@@ -114,8 +114,8 @@ public function testLanguageBlockVisibilityLanguageDelete() {
     // Check that the language is no longer stored in the configuration after
     // it is deleted.
     $block = entity_load('block', $block->id());
-    $visibility = $block->get('visibility');
-    $this->assertTrue(empty($visibility['language']['langcodes']['fr']), 'Language is no longer not set in the block configuration after deleting the block.');
+    $settings = $block->get('settings');
+    $this->assertTrue(empty($settings['visibility']['language']['langcodes']['fr']), 'Language is no longer not set in the block configuration after deleting the block.');
   }
 
 }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
index 207f20b..99e2581 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
@@ -69,6 +69,7 @@ protected function createTests() {
     // Attempt to create a block without a plugin.
     try {
       $entity = $this->controller->create(array());
+      $entity->getPlugin();
       $this->fail('A block without a plugin was created with no exception thrown.');
     }
     catch (PluginException $e) {
@@ -93,18 +94,20 @@ protected function createTests() {
     $expected_properties = array(
       'id' => 'stark.test_block',
       'label' => '',
-      'label_display' => BLOCK_LABEL_VISIBLE,
-      'region' => '-1',
-      'weight' => '',
-      'module' => 'block_test',
       'status' => '1',
-      'visibility' => array(),
+      'langcode' => language_default()->langcode,
+      'region' => '-1',
       'plugin' => 'test_html_id',
       'settings' => array(
         'cache' => '1',
+        'label' => '',
         'admin_label' => t('Test block html id'),
+        'weight' => '',
+        'module' => 'block_test',
+        'label_display' => BLOCK_LABEL_VISIBLE,
+        'visibility' => array(),
+        'status' => '1',
       ),
-      'langcode' => language_default()->langcode,
     );
     $this->assertIdentical($actual_properties, $expected_properties, 'The block properties are exported correctly.');
 
@@ -124,7 +127,6 @@ protected function loadTests() {
     $this->assertEqual($entity->get('region'), '-1');
     $this->assertTrue($entity->get('status'));
     $this->assertEqual($entity->get('theme'), 'stark');
-    $this->assertEqual($entity->get('module'), 'block_test');
     $this->assertTrue($entity->uuid());
   }
 
@@ -132,19 +134,14 @@ protected function loadTests() {
    * Tests the rendering of blocks.
    */
   protected function renderTests() {
-    $entity = $this->controller->create(array(
-      'id' => 'stark.test_block',
-      'plugin' => 'test_html_id',
-    ));
-
     // Test the rendering of a block.
+    $entity = entity_load('block', 'stark.test_block');
     $output = entity_view($entity, 'block');
     $expected = array();
-    $expected[] = '  <div id="block-test-block"  class="block block-block-test">';
-    $expected[] = '';
-    $expected[] = '    ';
-    $expected[] = '  <div class="content">';
-    $expected[] = '      </div>';
+    $expected[] = '  <div id="block-wrapper-test-block"  class="block-wrapper block-block-test">';
+    $expected[] = '      ';
+    $expected[] = '<div class="content">';
+    $expected[] = '  </div>';
     $expected[] = '</div>';
     $expected[] = '';
     $expected_output = implode("\n", $expected);
@@ -154,19 +151,27 @@ protected function renderTests() {
     drupal_static_reset('drupal_html_id');
 
     // Test the rendering of a block with a given title.
-    $entity->set('label', 'Powered by Bananas');
+    $entity = $this->controller->create(array(
+      'id' => 'stark.test_block2',
+      'plugin' => 'test_html_id',
+      'settings' => array(
+        'label' => 'Powered by Bananas',
+      ),
+    ));
+    $entity->save();
     $output = entity_view($entity, 'block');
     $expected = array();
-    $expected[] = '  <div id="block-test-block"  class="block block-block-test">';
+    $expected[] = '  <div id="block-wrapper-test-block2"  class="block-wrapper block-block-test">';
+    $expected[] = '        <h2 class="">Powered by Bananas</h2>';
     $expected[] = '';
-    $expected[] = '    <h2 class="">Powered by Bananas</h2>';
-    $expected[] = '  ';
-    $expected[] = '  <div class="content">';
-    $expected[] = '      </div>';
+    $expected[] = '<div class="content">';
+    $expected[] = '  </div>';
     $expected[] = '</div>';
     $expected[] = '';
     $expected_output = implode("\n", $expected);
     $this->assertEqual(drupal_render($output), $expected_output, 'The block rendered correctly.');
+    // Clean up this entity.
+    $entity->delete();
   }
 
   /**
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
index d707c80..21b32a0 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
@@ -10,7 +10,7 @@
 use Drupal\simpletest\WebTestBase;
 
 /**
- * Unit tests for template_preprocess_block().
+ * Unit tests for template_preprocess_block_wrapper().
  */
 class BlockTemplateSuggestionsUnitTest extends WebTestBase {
 
@@ -24,13 +24,13 @@ class BlockTemplateSuggestionsUnitTest extends WebTestBase {
   public static function getInfo() {
     return array(
       'name' => 'Block template suggestions',
-      'description' => 'Test the template_preprocess_block() function.',
+      'description' => 'Test the template_preprocess_block_wrapper() function.',
       'group' => 'Block',
     );
   }
 
   /**
-   * Test if template_preprocess_block() handles the suggestions right.
+   * Test if template_preprocess_block_wrapper() handles the suggestions right.
    */
   function testBlockThemeHookSuggestions() {
     // Define a block with a derivative to be preprocessed, which includes both
@@ -42,19 +42,14 @@ function testBlockThemeHookSuggestions() {
       'region' => 'footer',
       'id' => config('system.theme')->get('default') . '.machinename',
     ));
+    $block->save();
 
-    $variables = array();
     $variables['elements']['#block'] = $block;
-    $variables['elements']['#block_config'] = $block->getPlugin()->getConfig() + array(
-      'id' => $block->get('plugin'),
-      'region' => $block->get('region'),
-      'module' => $block->get('module'),
-    );
     $variables['elements']['#children'] = '';
     // Test adding a class to the block content.
     $variables['content_attributes']['class'][] = 'test-class';
-    template_preprocess_block($variables);
-    $this->assertEqual($variables['theme_hook_suggestions'], array('block__footer', 'block__system', 'block__system_menu_block', 'block__system_menu_block__menu_admin', 'block__machinename'));
+    template_preprocess_block_wrapper($variables);
+    $this->assertEqual($variables['theme_hook_suggestions'], array('block_wrapper__footer', 'block_wrapper__system', 'block_wrapper__system_menu_block', 'block_wrapper__system_menu_block__menu_admin', 'block_wrapper__machinename'));
     $this->assertEqual($variables['content_attributes']['class'], array('test-class', 'content'), 'Default .content class added to block content_attributes_array');
   }
 
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
index 9020087..70675cf 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
@@ -34,7 +34,7 @@ function testBlockVisibility() {
     $edit = array(
       'machine_name' => strtolower($this->randomName(8)),
       'region' => 'sidebar_first',
-      'label' => $title,
+      'settings[label]' => $title,
     );
     // Set the block to be hidden on any user path, and to be shown only to
     // authenticated users.
@@ -75,7 +75,7 @@ function testBlockVisibilityListedEmpty() {
     $edit = array(
       'machine_name' => strtolower($this->randomName(8)),
       'region' => 'sidebar_first',
-      'label' => $title,
+      'settings[label]' => $title,
       'visibility[path][visibility]' => BLOCK_VISIBILITY_LISTED,
     );
     // Set the block to be hidden on any user path, and to be shown only to
@@ -102,18 +102,18 @@ function testBlock() {
     // Select the 'Powered by Drupal' block to be configured and moved.
     $block = array();
     $block['id'] = 'system_powered_by_block';
-    $block['label'] = $this->randomName(8);
+    $block['settings[label]'] = $this->randomName(8);
     $block['machine_name'] = strtolower($this->randomName(8));
     $block['theme'] = config('system.theme')->get('default');
     $block['region'] = 'header';
 
     // Set block title to confirm that interface works and override any custom titles.
-    $this->drupalPost('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], array('label' => $block['label'], 'machine_name' => $block['machine_name'], 'region' => $block['region']), t('Save block'));
+    $this->drupalPost('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], array('settings[label]' => $block['settings[label]'], 'machine_name' => $block['machine_name'], 'region' => $block['region']), t('Save block'));
     $this->assertText(t('The block configuration has been saved.'), 'Block title set.');
     // Check to see if the block was created by checking its configuration.
     $instance = entity_load('block', $block['theme'] . '.' . $block['machine_name']);
 
-    $this->assertEqual($instance->label(), $block['label'], 'Stored block title found.');
+    $this->assertEqual($instance->label(), $block['settings[label]'], 'Stored block title found.');
 
     // Check whether the block can be moved to all available regions.
     foreach ($this->regions as $region) {
@@ -130,10 +130,10 @@ function testBlock() {
 
     // Confirm that the block instance title and markup are not displayed.
     $this->drupalGet('node');
-    $this->assertNoText(t($block['label']));
+    $this->assertNoText(t($block['settings[label]']));
     // Check for <div id="block-my-block-instance-name"> if the machine name
     // is my_block_instance_name.
-    $xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-' . strtr(strtolower($block['machine_name']), '-', '_')));
+    $xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-wrapper-' . strtr(strtolower($block['machine_name']), '-', '_')));
     $this->assertNoFieldByXPath($xpath, FALSE, 'Block found in no regions.');
   }
 
@@ -150,7 +150,7 @@ function testHideBlockTitle() {
     $edit = array(
       'machine_name' => $machine_name,
       'region' => 'sidebar_first',
-      'label' => $title,
+      'settings[label]' => $title,
     );
     $this->drupalPost('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
     $this->assertText('The block configuration has been saved.', 'Block was saved');
@@ -159,7 +159,7 @@ function testHideBlockTitle() {
     $this->assertText($title, 'Block title was displayed by default.');
 
     $edit = array(
-      'label_display' => FALSE,
+      'settings[label_display]' => FALSE,
     );
     $this->drupalPost('admin/structure/block/manage/' . $default_theme . '.' . $machine_name . '/configure', $edit, t('Save block'));
     $this->assertText('The block configuration has been saved.', 'Block was saved');
@@ -192,12 +192,12 @@ function moveBlockToRegion(array $block, $region) {
 
     // Confirm that the block is being displayed.
     $this->drupalGet('');
-    $this->assertText(t($block['label']), 'Block successfully being displayed on the page.');
+    $this->assertText(t($block['settings[label]']), 'Block successfully being displayed on the page.');
 
     // Confirm that the custom block was found at the proper region.
     $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
       ':region-class' => 'region region-' . drupal_html_class($region),
-      ':block-id' => 'block-' . strtr(strtolower($block['machine_name']), '-', '_'),
+      ':block-id' => 'block-wrapper-' . strtr(strtolower($block['machine_name']), '-', '_'),
     ));
     $this->assertFieldByXPath($xpath, NULL, t('Block found in %region_name region.', array('%region_name' => drupal_html_class($region))));
   }
@@ -225,8 +225,7 @@ function testBlockRehash() {
     $this->assertEqual($settings['cache'], DRUPAL_CACHE_PER_ROLE, 'Test block cache mode defaults to DRUPAL_CACHE_PER_ROLE.');
 
     // Disable caching for this block.
-    $settings['cache'] = DRUPAL_NO_CACHE;
-    $block->set('settings', $settings);
+    $block->getPlugin()->setConfig('cache', DRUPAL_NO_CACHE);
     $block->save();
     // Flushing all caches should call _block_rehash().
     $this->resetAll();
@@ -290,13 +289,13 @@ function testBlockModuleDisable() {
     // Emulate a POST submission rather than using drupalPlaceBlock() to ensure
     // that the form still functions as expected.
     $edit = array(
-      'label' => $this->randomName(8),
+      'settings[label]' => $this->randomName(8),
       'machine_name' => strtolower($this->randomName(8)),
       'region' => 'sidebar_first',
     );
     $this->drupalPost('admin/structure/block/add/system_powered_by_block/stark', $edit, t('Save block'));
     $this->assertText(t('The block configuration has been saved.'));
-    $this->assertText($edit['label']);
+    $this->assertText($edit['settings[label]']);
 
     // Update the weight of a block.
     $edit = array('blocks[stark.' . $edit['machine_name'] . '][weight]' => -1);
@@ -323,7 +322,7 @@ function testBlockModuleDisable() {
       $machine_name = array_pop($name_pieces);
       $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
         ':region-class' => 'region region-' . drupal_html_class($region),
-        ':block-id' => 'block-' . strtr(strtolower($machine_name), '-', '_'),
+        ':block-id' => 'block-wrapper-' . strtr(strtolower($machine_name), '-', '_'),
     ));
       $this->assertFieldByXPath($xpath, NULL, format_string('Block %name found in the %region region.', array(
         '%name' => $blocks[$region]->label(),
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTestBase.php b/core/modules/block/lib/Drupal/block/Tests/BlockTestBase.php
index c950576..02b5a4d 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTestBase.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTestBase.php
@@ -103,7 +103,7 @@ function moveBlockToRegion(array $block, $region) {
     // Confirm that the custom block was found at the proper region.
     $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
      ':region-class' => 'region region-' . drupal_html_class($region),
-     ':block-id' => 'block-' . strtr(strtolower($block['machine_name']), '-', '_'),
+     ':block-id' => 'block-wrapper-' . strtr(strtolower($block['machine_name']), '-', '_'),
     ));
     $this->assertFieldByXPath($xpath, NULL, t('Block found in %region_name region.', array('%region_name' => drupal_html_class($region))));
   }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php
index b04f9fc..7ac3648 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php
@@ -32,10 +32,7 @@ public static function getInfo() {
   protected function setUp() {
     parent::setUp();
 
-    $this->drupalPlaceBlock('test_xss_title', array(
-      'label' => '<script>alert("XSS label");</script>',
-      'machine_name' => 'test_xss_block',
-    ));
+    $this->drupalPlaceBlock('test_xss_title', array('label' => '<script>alert("XSS label");</script>'));
   }
 
   /**
diff --git a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
index 5f3b776..9dec0a7 100644
--- a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
@@ -81,7 +81,7 @@ protected function assertNoBlockAppears(Block $block) {
   protected function findBlockInstance(Block $block) {
     $config_id = explode('.', $block->id());
     $machine_name = array_pop($config_id);
-    return $this->xpath('//div[@id = :id]', array(':id' => 'block-' . $machine_name));
+    return $this->xpath('//div[@id = :id]', array(':id' => 'block-wrapper-' . $machine_name));
   }
 
   /**
@@ -90,13 +90,13 @@ protected function findBlockInstance(Block $block) {
   protected function testDeleteBlockDisplay() {
     // To test all combinations possible we first place create two instances
     // of the block display of the first view.
-    $block_1 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array(), array('title' => 'test_view_block-block_1:1'));
-    $block_2 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array(), array('title' => 'test_view_block-block_1:2'));
+    $block_1 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array('title' => 'test_view_block-block_1:1'));
+    $block_2 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array('title' => 'test_view_block-block_1:2'));
 
     // Then we add one instance of blocks for each of the two displays of the
     // second view.
-    $block_3 = $this->drupalPlaceBlock('views_block:test_view_block2-block_1', array(), array('title' => 'test_view_block2-block_1'));
-    $block_4 = $this->drupalPlaceBlock('views_block:test_view_block2-block_2', array(), array('title' => 'test_view_block2-block_2'));
+    $block_3 = $this->drupalPlaceBlock('views_block:test_view_block2-block_1', array('title' => 'test_view_block2-block_1'));
+    $block_4 = $this->drupalPlaceBlock('views_block:test_view_block2-block_2', array('title' => 'test_view_block2-block_2'));
 
     $this->drupalGet('test-page');
     $this->assertBlockAppears($block_1);
diff --git a/core/modules/block/templates/block.tpl.php b/core/modules/block/templates/block-wrapper.tpl.php
similarity index 74%
copy from core/modules/block/templates/block.tpl.php
copy to core/modules/block/templates/block-wrapper.tpl.php
index 00b554a..a48e324 100644
--- a/core/modules/block/templates/block.tpl.php
+++ b/core/modules/block/templates/block-wrapper.tpl.php
@@ -5,13 +5,6 @@
  * Default theme implementation to display a block.
  *
  * Available variables:
- * - $block->label: Block title.
- * - $block->label_hidden: The hidden block title value if the block was
- *    configured to hide the title ($block->label is empty in this case).
- * - $content: Block content.
- * - $block->module: Module that generated the block.
- * - $block->delta: An ID for the block, unique within each module.
- * - $block->region: The block region embedding the current block.
  * - $attributes: An instance of Attributes class that can be manipulated as an
  *    array and printed as a string.
  *    It includes the 'class' information, which includes:
@@ -37,7 +30,7 @@
  * - $block_html_id: A valid HTML ID and guaranteed unique.
  *
  * @see template_preprocess()
- * @see template_preprocess_block()
+ * @see template_preprocess_block_wrapper()
  * @see template_process()
  *
  * @ingroup themeable
@@ -48,14 +41,7 @@
 <?php else: ?>
   <div <?php print $attributes; ?>>
 <?php endif; ?>
-
   <?php print render($title_prefix); ?>
-<?php if ($block->label): ?>
-  <h2<?php print $title_attributes; ?>><?php print $block->label; ?></h2>
-<?php endif;?>
   <?php print render($title_suffix); ?>
-
-  <div<?php print $content_attributes; ?>>
-    <?php print $content ?>
-  </div>
+  <?php print $content ?>
 </div>
diff --git a/core/modules/block/templates/block.tpl.php b/core/modules/block/templates/block.tpl.php
index 00b554a..5e4eb92 100644
--- a/core/modules/block/templates/block.tpl.php
+++ b/core/modules/block/templates/block.tpl.php
@@ -1,61 +1,9 @@
-<?php
-
-/**
- * @file
- * Default theme implementation to display a block.
- *
- * Available variables:
- * - $block->label: Block title.
- * - $block->label_hidden: The hidden block title value if the block was
- *    configured to hide the title ($block->label is empty in this case).
- * - $content: Block content.
- * - $block->module: Module that generated the block.
- * - $block->delta: An ID for the block, unique within each module.
- * - $block->region: The block region embedding the current block.
- * - $attributes: An instance of Attributes class that can be manipulated as an
- *    array and printed as a string.
- *    It includes the 'class' information, which includes:
- *   - block: The current template type, i.e., "theming hook".
- *   - block-[module]: The module generating the block. For example, the user
- *     module is responsible for handling the default user navigation block. In
- *     that case the class would be 'block-user'.
- * - $title_prefix (array): An array containing additional output populated by
- *   modules, intended to be displayed in front of the main title tag that
- *   appears in the template.
- * - $title_suffix (array): An array containing additional output populated by
- *   modules, intended to be displayed after the main title tag that appears in
- *   the template.
- *
- * Helper variables:
- * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
- * - $zebra: Same output as $block_zebra but independent of any block region.
- * - $block_id: Counter dependent on each block region.
- * - $id: Same output as $block_id but independent of any block region.
- * - $is_front: Flags true when presented in the front page.
- * - $logged_in: Flags true when the current user is a logged-in member.
- * - $is_admin: Flags true when the current user is an administrator.
- * - $block_html_id: A valid HTML ID and guaranteed unique.
- *
- * @see template_preprocess()
- * @see template_preprocess_block()
- * @see template_process()
- *
- * @ingroup themeable
- */
-?>
-<?php if (isset($block_html_id)): ?>
-  <div id="<?php print $block_html_id; ?>" <?php print $attributes; ?>>
-<?php else: ?>
-  <div <?php print $attributes; ?>>
-<?php endif; ?>
-
-  <?php print render($title_prefix); ?>
-<?php if ($block->label): ?>
-  <h2<?php print $title_attributes; ?>><?php print $block->label; ?></h2>
+<?php print render($title_prefix); ?>
+<?php if ($label): ?>
+  <h2<?php print $title_attributes; ?>><?php print $label; ?></h2>
 <?php endif;?>
-  <?php print render($title_suffix); ?>
+<?php print render($title_suffix); ?>
 
-  <div<?php print $content_attributes; ?>>
-    <?php print $content ?>
-  </div>
+<div<?php print $content_attributes; ?>>
+  <?php print render($content); ?>
 </div>
diff --git a/core/modules/block/tests/config/block.block.stark.test_block.yml b/core/modules/block/tests/config/block.block.stark.test_block.yml
index 59ba7b4..fb6856c 100644
--- a/core/modules/block/tests/config/block.block.stark.test_block.yml
+++ b/core/modules/block/tests/config/block.block.stark.test_block.yml
@@ -1,11 +1,11 @@
 id: stark.test_block
-label: ''
 region: '-1'
-weight: ''
-module: block_test
-status: '1'
-visibility: {  }
 plugin: test_html_id
 settings:
+  label: ''
+  weight: ''
+  module: block_test
+  status: '1'
+  visibility: {  }
   cache: '1'
   admin_label: 'Test block html id'
diff --git a/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestBlockInstantiation.php b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestBlockInstantiation.php
new file mode 100644
index 0000000..bd67c9b
--- /dev/null
+++ b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestBlockInstantiation.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_test\Plugin\block\block\TestBlockInstantiation.
+ */
+
+namespace Drupal\block_test\Plugin\block\block;
+
+use Drupal\block\BlockBase;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Provides a basic block for testing block instantiation and configuration.
+ *
+ * @Plugin(
+ *   id = "test_block_instantiation",
+ *   admin_label = @Translation("Display message"),
+ *   module = "block_test"
+ * )
+ */
+class TestBlockInstantiation extends BlockBase {
+
+  /**
+   * Overrides \Drupal\block\BlockBase::settings().
+   */
+  public function settings() {
+    return array(
+      'display_message' => 'no message set',
+    );
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockAccess().
+   */
+  public function blockAccess() {
+    return user_access('access content');
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockForm().
+   */
+  public function blockForm($form, &$form_state) {
+    $form['display_message'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Display message'),
+      '#default_value' => $this->configuration['display_message'],
+    );
+    return $form;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockSubmit().
+   */
+  public function blockSubmit($form, &$form_state) {
+    $this->configuration['display_message'] = $form_state['values']['display_message'];
+  }
+
+  /**
+   * Implements \Drupal\block\BlockBase::blockBuild().
+   */
+  protected function blockBuild() {
+    return array(
+      '#children' => $this->configuration['display_message'],
+    );
+  }
+
+}
diff --git a/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php
index dd7a423..14dfd9d 100644
--- a/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php
+++ b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php
@@ -34,9 +34,9 @@ public function settings() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       '#children' => state()->get('block_test.content'),
     );
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 26f324e..fe778f5 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -965,7 +965,7 @@ function _book_link_defaults($nid) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function book_preprocess_block(&$variables) {
-  if ($variables['block']-> module == 'book') {
+  if ($variables['configuration']['module'] == 'book') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php b/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php
index 165c798..e3b8162 100644
--- a/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php
+++ b/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php
@@ -59,9 +59,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $current_bid = 0;
     if ($node = menu_get_object()) {
       $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid'];
diff --git a/core/modules/book/lib/Drupal/book/Tests/BookTest.php b/core/modules/book/lib/Drupal/book/Tests/BookTest.php
index 4601342..1385126 100644
--- a/core/modules/book/lib/Drupal/book/Tests/BookTest.php
+++ b/core/modules/book/lib/Drupal/book/Tests/BookTest.php
@@ -338,7 +338,7 @@ function testBookNavigationBlock() {
    */
   function testNavigationBlockOnAccessModuleEnabled() {
     $this->drupalLogin($this->admin_user);
-    $block = $this->drupalPlaceBlock('book_navigation', array(), array('block_mode' => 'book pages'));
+    $block = $this->drupalPlaceBlock('book_navigation', array('block_mode' => 'book pages'));
 
     // Give anonymous users the permission 'node test view'.
     $edit = array();
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 8e9400f..835bde9 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1591,7 +1591,7 @@ function comment_preview(Comment $comment) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function comment_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'comment') {
+  if ($variables['configuration']['module'] == 'comment') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentCommentsBlock.php b/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentCommentsBlock.php
index bd7b49b..a55c8e1 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentCommentsBlock.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentCommentsBlock.php
@@ -59,9 +59,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       '#theme' => 'comment_block',
       '#number' => $this->configuration['block_count'],
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
index 901d325..89f81b1 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
@@ -46,7 +46,7 @@ public static function getInfo() {
    */
   function testRecentCommentBlock() {
     $this->drupalLogin($this->admin_user);
-    $block = $this->drupalPlaceBlock('recent_comments', array(), array('block_count' => 2));
+    $block = $this->drupalPlaceBlock('recent_comments', array('block_count' => 2));
 
     // Add some test comments, one without a subject.
     $comment1 = $this->postComment($this->node, $this->randomName(), $this->randomName());
@@ -78,7 +78,7 @@ function testRecentCommentBlock() {
     $this->assertTrue(strpos($this->drupalGetContent(), $comment3->comment_body->value) < strpos($this->drupalGetContent(), $comment2->subject->value), 'Comments were ordered correctly in block.');
 
     // Set the number of recent comments to show to 10.
-    $block->set('settings', array('block_count' => 10));
+    $block->getPlugin()->setConfig('block_count', 10);
     $block->save();
 
     // Post an additional comment.
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index eb2c1ec..a808f58 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -649,7 +649,8 @@ function forum_form_node_form_alter(&$form, &$form_state, $form_id) {
  *
  * This function can be used as a #pre_render callback.
  *
- * @see forum_block_view()
+ * @see \Drupal\forum\Plugin\block\block\NewTopicsBlock::blockBuild()
+ * @see \Drupal\forum\Plugin\block\block\ActiveTopicsBlock::blockBuild()
  */
 function forum_block_view_pre_render($elements) {
   $result = $elements['#query']->execute();
@@ -971,7 +972,7 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function forum_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'forum') {
+  if ($variables['configuration']['module'] == 'forum') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveTopicsBlock.php b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveTopicsBlock.php
index e3ff7dd..c4fab8c 100644
--- a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveTopicsBlock.php
+++ b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveTopicsBlock.php
@@ -22,9 +22,9 @@
 class ActiveTopicsBlock extends ForumBlockBase {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $query = db_select('forum_index', 'f')
       ->fields('f')
       ->addTag('node_access')
diff --git a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewTopicsBlock.php b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewTopicsBlock.php
index 71d4c3b..1ef7311 100644
--- a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewTopicsBlock.php
+++ b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewTopicsBlock.php
@@ -22,9 +22,9 @@
 class NewTopicsBlock extends ForumBlockBase {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $query = db_select('forum_index', 'f')
       ->fields('f')
       ->addTag('node_access')
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
index 02314e8..65dd7c2 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
@@ -71,7 +71,7 @@ public function testNewForumTopicsBlock() {
     }
 
     // Configure the new forum topics block to only show 2 topics.
-    $block->set('settings', array('block_count' => 2));
+    $block->getPlugin()->setConfig('block_count', 2);
     $block->save();
 
     $this->drupalGet('');
@@ -132,7 +132,7 @@ public function testActiveForumTopicsBlock() {
     }
 
     // Configure the active forum block to only show 2 topics.
-    $block->set('settings', array('block_count' => 2));
+    $block->getPlugin()->setConfig('block_count', 2);
     $block->save();
 
     $this->drupalGet('');
diff --git a/core/modules/help/help.module b/core/modules/help/help.module
index aac8636..77109d5 100644
--- a/core/modules/help/help.module
+++ b/core/modules/help/help.module
@@ -71,7 +71,7 @@ function help_help($path, $arg) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function help_preprocess_block(&$variables) {
-  if ($variables['block']->id == 'system_help_block') {
+  if ($variables['plugin_id'] == 'system_help_block') {
     $variables['attributes']['role'] = 'complementary';
   }
 }
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 6bbb5a7..53d6ffe 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -763,7 +763,7 @@ function language_language_delete($language) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function language_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'language') {
+  if ($variables['configuration']['module'] == 'language') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php b/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php
index 53c58e7..efe4b79 100644
--- a/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php
+++ b/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php
@@ -31,9 +31,9 @@ function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $build = array();
     $path = drupal_is_front_page() ? '<front>' : current_path();
     list($plugin_id, $type) = explode(':', $this->getPluginId());
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
index ac834d1..910c358 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
@@ -59,7 +59,7 @@ function testLanguageBlock() {
     $this->assertText($block->label(), 'Language switcher block found.');
 
     // Assert that only the current language is marked as active.
-    list($language_switcher) = $this->xpath('//div[@id=:id]/div[@class="content"]', array(':id' => 'block-test-language-block'));
+    list($language_switcher) = $this->xpath('//div[@id=:id]/div[@class="content"]', array(':id' => 'block-wrapper-test-language-block'));
     $links = array(
       'active' => array(),
       'inactive' => array(),
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
index a6c1dc7..f382ded 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
@@ -414,7 +414,7 @@ function testUrlLanguageFallback() {
 
     // Check that the language switcher active link matches the given browser
     // language.
-    $args = array(':id' => 'block-test-language-block', ':url' => base_path() . $GLOBALS['script_path'] . $langcode_browser_fallback);
+    $args = array(':id' => 'block-wrapper-test-language-block', ':url' => base_path() . $GLOBALS['script_path'] . $langcode_browser_fallback);
     $fields = $this->xpath('//div[@id=:id]//a[@class="language-link active" and starts-with(@href, :url)]', $args);
     $this->assertTrue($fields[0] == $languages[$langcode_browser_fallback]->name, 'The browser language is the URL active language');
 
diff --git a/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php b/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php
index c535fc6..2044087 100644
--- a/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php
+++ b/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php
@@ -24,9 +24,9 @@
 class MenuBlock extends SystemMenuBlock {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     list($plugin, $menu) = explode(':', $this->getPluginId());
     return menu_tree($menu);
   }
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index d13655e..fa6aa53 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -12,7 +12,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\block\Plugin\Core\Entity\Block;
+use Drupal\block\BlockInterface;
 use Drupal\system\Plugin\Core\Entity\Menu;
 use Drupal\system\Plugin\block\block\SystemMenuBlock;
 use Symfony\Component\HttpFoundation\JsonResponse;
@@ -399,13 +399,13 @@ function _menu_parents_recurse($tree, $menu_name, $indent, &$options, $exclude,
 }
 
 /**
- * Implements hook_block_view_alter().
+ * Implements hook_block_view_NAME_alter() for 'system_menu_block'.
  */
-function menu_block_view_alter(array &$build, Block $block) {
+function menu_block_view_system_menu_block_alter(array &$build, BlockInterface $block) {
   // Add contextual links for system menu blocks.
-  if ($block->getPlugin() instanceof SystemMenuBlock) {
-    foreach (element_children($build['content']) as $key) {
-      $build['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['content'][$key]['#original_link']['menu_name']));
+  if (isset($build['#content'])) {
+    foreach (element_children($build['#content']) as $key) {
+      $build['#content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['#content'][$key]['#original_link']['menu_name']));
     }
   }
 }
@@ -717,7 +717,7 @@ function menu_get_menus($all = TRUE) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function menu_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'menu') {
+  if ($variables['configuration']['module'] == 'menu') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentContentBlock.php b/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentContentBlock.php
index 083a096..1064461 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentContentBlock.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentContentBlock.php
@@ -59,9 +59,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     if ($nodes = node_get_recent($this->configuration['block_count'])) {
       return array(
         '#theme' => 'node_recent_block',
diff --git a/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php b/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php
index af627a2..49d0eb4 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php
@@ -39,9 +39,9 @@ public function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       '#theme' => 'feed_icon',
       '#url' => 'rss.xml',
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
index 3beb969..1836da6 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
@@ -61,7 +61,7 @@ public function testRecentNodeBlock() {
     ));
 
     // Enable the recent content block with two items.
-    $block = $this->drupalPlaceBlock('node_recent_block', array('machine_name' => 'test_block'), array('block_count' => 2));
+    $block = $this->drupalPlaceBlock('node_recent_block', array('machine_name' => 'test_block', 'block_count' => 2));
 
     // Test that block is not visible without nodes.
     $this->drupalGet('');
@@ -100,13 +100,13 @@ public function testRecentNodeBlock() {
     $this->assertText($node3->label(), 'Node found in block.');
 
     // Check to make sure nodes are in the right order.
-    $this->assertTrue($this->xpath('//div[@id="block-test-block"]/div/table/tbody/tr[position() = 1]/td/div/a[text() = "' . $node3->label() . '"]'), 'Nodes were ordered correctly in block.');
+    $this->assertTrue($this->xpath('//div[@id="block-wrapper-test-block"]/div/table/tbody/tr[position() = 1]/td/div/a[text() = "' . $node3->label() . '"]'), 'Nodes were ordered correctly in block.');
 
     $this->drupalLogout();
     $this->drupalLogin($this->adminUser);
 
     // Set the number of recent nodes to show to 10.
-    $block->set('settings', array('block_count' => 10));
+    $block->getPlugin()->setConfig('block_count', 10);
     $block->save();
 
     // Post an additional node.
@@ -132,8 +132,8 @@ public function testRecentNodeBlock() {
         ),
       ),
     ));
-    $visibility = $block->get('visibility');
-    $this->assertTrue(isset($visibility['node_type']['types']['article']), 'Visibility settings were saved to configuration');
+    $settings = $block->get('settings');
+    $this->assertTrue(isset($settings['visibility']['node_type']['types']['article']), 'Visibility settings were saved to configuration');
 
     // Create a page node.
     $node5 = $this->drupalCreateNode(array('uid' => $this->adminUser->uid, 'type' => 'page'));
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeSyndicateBlockTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeSyndicateBlockTest.php
index 887b7ea..3d23276 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeSyndicateBlockTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeSyndicateBlockTest.php
@@ -42,7 +42,7 @@ public function testSyndicateBlock() {
     // Place the "Syndicate" block and confirm that it is rendered.
     $this->drupalPlaceBlock('node_syndicate_block', array('machine_name' => 'test_syndicate_block'));
     $this->drupalGet('');
-    $this->assertFieldByXPath('//div[@id="block-test-syndicate-block"]/*', NULL, 'Syndicate block found.');
+    $this->assertFieldByXPath('//div[@id="block-wrapper-test-syndicate-block"]/*', NULL, 'Syndicate block found.');
   }
 
 }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 9bd3087..c3411c9 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1116,8 +1116,8 @@ function node_is_page(EntityInterface $node) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function node_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'node') {
-    switch ($variables['block']->id) {
+  if ($variables['configuration']['module'] == 'node') {
+    switch ($variables['plugin_id']) {
       case 'node_syndicate_block':
         $variables['attributes']['role'] = 'complementary';
         break;
@@ -1997,14 +1997,14 @@ function theme_node_recent_content($variables) {
 function node_form_block_form_alter(&$form, &$form_state) {
   $block = $form_state['entity'];
   $visibility = $block->get('visibility');
-  $form['visibility']['node_type'] = array(
+  $form['settings']['visibility']['node_type'] = array(
     '#type' => 'details',
     '#title' => t('Content types'),
     '#collapsed' => TRUE,
     '#group' => 'visibility',
     '#weight' => 5,
   );
-  $form['visibility']['node_type']['types'] = array(
+  $form['settings']['visibility']['node_type']['types'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Show block for specific content types'),
     '#default_value' => !empty($visibility['node_type']['types']) ? $visibility['node_type']['types'] : array(),
@@ -2020,7 +2020,8 @@ function node_form_block_form_alter(&$form, &$form_state) {
  * if the visibility conditions are not met.
  */
 function node_block_access($block) {
-  $visibility = $block->get('visibility');
+  $settings = $block->get('settings');
+  $visibility = $settings['visibility'];
   if (!empty($visibility)) {
     $allowed_types = array();
     $node = menu_get_object();
diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module
index 0f2e04f..67b7070 100644
--- a/core/modules/openid/openid.module
+++ b/core/modules/openid/openid.module
@@ -6,6 +6,7 @@
  */
 
 use Guzzle\Http\Exception\RequestException;
+use Drupal\block\BlockInterface;
 
 /**
  * Implements hook_menu().
@@ -160,23 +161,23 @@ function openid_user_logout($account) {
 }
 
 /**
- * Implements hook_block_view_MODULE_DELTA_alter().
+ * Implements hook_block_view_NAME_alter() for 'user_login_block'.
  *
  * Adds the OpenID login form to the user login block.
  *
  * @see \Drupal\user\Plugin\block\block\UserLoginBlock
  */
-function openid_block_view_user_login_block_alter(&$build, $block) {
+function openid_block_view_user_login_block_alter(array &$build, BlockInterface $block) {
   // Only alter the block when it is non-empty, i.e. when no user is logged in.
-  if (!isset($build['content']['user_login_form'])) {
+  if (!isset($build['#content']['user_login_form'])) {
     return;
   }
 
-  $build['content']['openid_login_form'] = drupal_get_form('openid_login_form');
-  $build['content']['openid_login_form']['openid_identifier']['#size'] = $build['content']['user_login_form']['name']['#size'];
+  $build['#content']['openid_login_form'] = drupal_get_form('openid_login_form');
+  $build['#content']['openid_login_form']['openid_identifier']['#size'] = $build['#content']['user_login_form']['name']['#size'];
 
   // Put an OpenID link as a first element.
-  $build['content']['user_links']['#items'] = array(
+  $build['#content']['user_links']['#items'] = array(
     l(t('Log in using OpenID'), 'user/login/openid', array(
       'attributes' => array(
         'title' => t('Log in using OpenID.'),
@@ -185,10 +186,10 @@ function openid_block_view_user_login_block_alter(&$build, $block) {
         'tabindex' => 0,
       ),
     ))
-  ) + $build['content']['user_links']['#items'];
+  ) + $build['#content']['user_links']['#items'];
 
   // Move links under the openid form.
-  $build['content']['user_links']['#weight'] = 10;
+  $build['#content']['user_links']['#weight'] = 10;
 }
 
 /**
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 446d56c..2e86a03 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -7,6 +7,8 @@
 
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Drupal\block\Plugin\Core\Entity\Block;
+use Drupal\user\Plugin\Core\Entity\User;
 
 /**
  * Implements hook_help().
@@ -479,7 +481,7 @@ function theme_overlay_disable_message($variables) {
 /**
  * Implements hook_block_access().
  */
-function overlay_block_access($block) {
+function overlay_block_access(Block $block, $operation, User $account, $langcode) {
   // If we are limiting rendering to a subset of page regions, hide all blocks
   // which appear in regions not on that list. Note that overlay_page_alter()
   // does a more comprehensive job of preventing unwanted regions from being
diff --git a/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php b/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php
index bb06d35..1076021 100644
--- a/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php
+++ b/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php
@@ -30,9 +30,9 @@ public function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(drupal_get_form('search_block_form'));
   }
 
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 6dd68d9..0d9ba4a 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -134,10 +134,10 @@ function search_permission() {
 }
 
 /**
- * Implements hook_preprocess_block().
+ * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function search_preprocess_block(&$variables) {
-  if ($variables['block']->id == 'search_form_block') {
+  if ($variables['plugin_id'] == 'search_form_block') {
     $variables['attributes']['role'] = 'search';
     $variables['content_attributes']['class'][] = 'container-inline';
   }
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php
index f610717..7a56d76 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php
@@ -23,9 +23,9 @@
 class ShortcutsBlock extends BlockBase {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       shortcut_renderable_links(shortcut_current_displayed_set()),
     );
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 25a04c7..137f0c3 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -488,7 +488,7 @@ function shortcut_renderable_links($shortcut_set = NULL) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function shortcut_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'shortcut') {
+  if ($variables['configuration']['module'] == 'shortcut') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 7b50b10..aeb75d2 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -341,8 +341,8 @@ protected function drupalCreateContentType($settings = array()) {
    *
    * @param string $plugin_id
    *   The plugin ID of the block type for this block instance.
-   * @param array $values
-   *   (optional) An associative array of values for the block entity.
+   * @param array $settings
+   *   (optional) An associative array of settings for the block entity.
    *   Override the defaults by specifying the key and value in the array, for
    *   example:
    *   @code
@@ -355,8 +355,6 @@ protected function drupalCreateContentType($settings = array()) {
    *   - machine_name: Random string.
    *   - region: 'sidebar_first'.
    *   - theme: The default theme.
-   * @param array $settings
-   *   (optional) An associative array of plugin-specific settings.
    *
    * @return \Drupal\block\Plugin\Core\Entity\Block
    *   The block entity.
@@ -364,15 +362,19 @@ protected function drupalCreateContentType($settings = array()) {
    * @todo
    *   Add support for creating custom block instances.
    */
-  protected function drupalPlaceBlock($plugin_id, array $values = array(), array $settings = array()) {
-    $values += array(
+  protected function drupalPlaceBlock($plugin_id, array $settings = array()) {
+    $settings += array(
       'plugin' => $plugin_id,
-      'label' => $this->randomName(8),
       'region' => 'sidebar_first',
-      'theme' => config('system.theme')->get('default'),
       'machine_name' => strtolower($this->randomName(8)),
-      'settings' => $settings,
+      'theme' => config('system.theme')->get('default'),
+      'label' => $this->randomName(8),
     );
+    foreach (array('region', 'machine_name', 'theme', 'plugin') as $key) {
+      $values[$key] = $settings[$key];
+      unset($settings[$key]);
+    }
+    $values['settings'] = $settings;
     // Build the ID out of the theme and machine_name.
     $values['id'] = $values['theme'] . '.' . $values['machine_name'];
     $block = entity_create('block', $values);
diff --git a/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php b/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php
index 7417bd8..9a740ac 100644
--- a/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php
+++ b/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php
@@ -116,9 +116,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $content = array();
 
     if ($this->day_list) {
diff --git a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsReportsTest.php b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsReportsTest.php
index ed14bb0..b897f99 100644
--- a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsReportsTest.php
+++ b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsReportsTest.php
@@ -41,7 +41,8 @@ function testPopularContentBlock() {
     $client->post($stats_path, $headers, $post)->send();
 
     // Configure and save the block.
-    $this->drupalPlaceBlock('statistics_popular_block', array('label' => 'Popular content'), array(
+    $this->drupalPlaceBlock('statistics_popular_block', array(
+      'label' => 'Popular content',
       'top_day_num' => 3,
       'top_all_num' => 3,
       'top_last_num' => 3,
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index 66842a5..9d0c19e 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -237,7 +237,7 @@ function statistics_update_index() {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function statistics_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'statistics') {
+  if ($variables['configuration']['module'] == 'statistics') {
     $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php
index a5476c3..140b092 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php
@@ -38,9 +38,9 @@ public function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       '#children' => $this->help,
     );
diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
index 80510b0..89e3a9c 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
@@ -23,9 +23,9 @@
 class SystemMainBlock extends BlockBase {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       drupal_set_page_content()
     );
diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMenuBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMenuBlock.php
index 01aa470..8a2e11f 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMenuBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMenuBlock.php
@@ -33,9 +33,9 @@ public function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     list($plugin, $derivative) = explode(':', $this->getPluginId());
     // Derivatives are prefixed with 'menu-'.
     $menu = substr($derivative, 5);
diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php
index 958edc0..9e29c1e 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php
@@ -23,9 +23,9 @@
 class SystemPoweredByBlock extends BlockBase {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     return array(
       '#children' => theme('system_powered_by'),
     );
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
index 07c38ae..a072e8b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
@@ -360,7 +360,7 @@ function testBreadCrumbs() {
       // ('taxonomy/term/%') should never be translated and appear in any menu
       // other than the breadcrumb trail.
       $elements = $this->xpath('//div[@id=:menu]/descendant::a[@href=:href]', array(
-        ':menu' => 'block-system-menu-tools',
+        ':menu' => 'block-wrapper-system-menu-tools',
         ':href' => url($link['link_path']),
       ));
       $this->assertTrue(count($elements) == 1, "Link to {$link['link_path']} appears only once.");
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php
index b9129e3..45f2efb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php
@@ -42,16 +42,16 @@ public function testBlockUpgradeTitleLength() {
     // Add a block instance with a 255-character title.
     // Confirm that the custom block has been created, and title matches input.
     $settings = array(
-      'label' => $this->randomName(255),
+      'settings[label]' => $this->randomName(255),
       'machine_name' => strtolower($this->randomName(8)),
       'region' => 'sidebar_first',
     );
     $this->drupalPost('admin/structure/block/add/system_powered_by_block/' . config('system.theme')->get('default'), $settings, t('Save block'));
-    $this->assertText($settings['label'], 'Block with title longer than 64 characters successfully created.');
+    $this->assertText($settings['settings[label]'], 'Block with title longer than 64 characters successfully created.');
 
     // Try to add a block with a title over 255 characters.
     $settings = array(
-      'label' => $this->randomName(256),
+      'settings[label]' => $this->randomName(256),
       'machine_name' => strtolower($this->randomName(8)),
       'region' => 'sidebar_first',
     );
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ebe5548..e5b428b 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2674,20 +2674,18 @@ function system_user_timezone(&$form, &$form_state) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function system_preprocess_block(&$variables) {
-  switch ($variables['block']->id) {
+  // Derive the base plugin ID.
+  list($plugin_id) = explode(':', $variables['plugin_id'] . ':');
+  switch ($plugin_id) {
     case 'system_powered_by_block':
       $variables['attributes_array']['role'] = 'complementary';
       break;
     case 'system_help_block':
       $variables['attributes_array']['role'] = 'complementary';
       break;
-
-    // System menu blocks should get the same class as menu module blocks.
-    default:
-      if ($variables['elements']['#block']->getPlugin() instanceof SystemMenuBlock) {
-        $variables['attributes_array']['role'] = 'navigation';
-        $variables['classes_array'][] = 'block-menu';
-      }
+    case 'system_menu_block':
+      $variables['attributes_array']['role'] = 'navigation';
+      $variables['classes_array'][] = 'block-menu';
   }
 }
 
diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php
index 716a315..4d57119 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php
@@ -30,9 +30,9 @@ public function blockAccess() {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $form = drupal_get_form('user_login_form');
     unset($form['name']['#attributes']['autofocus']);
     unset($form['name']['#description']);
diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php
index 5f88f7f..b32714a 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php
@@ -62,9 +62,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     // Retrieve a list of new users who have accessed the site successfully.
     $items = db_query_range('SELECT uid, name FROM {users} WHERE status <> 0 AND access <> 0 ORDER BY created DESC', 0, $this->configuration['whois_new_count'])->fetchAll();
     $build = array(
diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php
index d88568a..65dbe22 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php
@@ -76,9 +76,9 @@ public function blockSubmit($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     // Count users active within the defined period.
     $interval = REQUEST_TIME - $this->configuration['seconds_online'];
 
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index d41206f..4560cb3 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -671,8 +671,8 @@ function user_validate_current_pass(&$form, &$form_state) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function user_preprocess_block(&$variables) {
-  if ($variables['block']->module == 'user') {
-    switch ($variables['block']->id) {
+  if ($variables['configuration']['module'] == 'user') {
+    switch ($variables['plugin_id']) {
       case 'user_login_block':
         $variables['attributes']['role'] = 'form';
         break;
diff --git a/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsBlock.php b/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsBlock.php
index 8a77f18..19f6268 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsBlock.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsBlock.php
@@ -8,7 +8,6 @@
 namespace Drupal\views\Plugin\block\block;
 
 use Drupal\block\BlockBase;
-use Drupal\block\Plugin\Core\Entity\Block;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
 
@@ -41,8 +40,8 @@ class ViewsBlock extends BlockBase {
   /**
    * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, Block $entity) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity);
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     list($plugin, $delta) = explode(':', $this->getPluginId());
     list($name, $this->displayID) = explode('-', $delta, 2);
@@ -71,12 +70,12 @@ public function form($form, &$form_state) {
   }
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\Blockbase::blockBuild()().
    */
-  public function build() {
+  protected function blockBuild() {
     $output = $this->view->executeDisplay($this->displayID);
     // Set the label to the title configured in the view.
-    $this->entity->set('label', filter_xss_admin($this->view->getTitle()));
+    $this->configuration['label'] = filter_xss_admin($this->view->getTitle());
     // Before returning the block output, convert it to a renderable array
     // with contextual links.
     $this->addContextualLinks($output);
diff --git a/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsExposedFilterBlock.php b/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsExposedFilterBlock.php
index cb9d37c..97037bb 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsExposedFilterBlock.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/block/block/ViewsExposedFilterBlock.php
@@ -23,9 +23,9 @@
 class ViewsExposedFilterBlock extends ViewsBlock {
 
   /**
-   * Implements \Drupal\block\BlockBase::build().
+   * Implements \Drupal\block\BlockBase::blockBuild().
    */
-  public function build() {
+  protected function blockBuild() {
     $output = $this->view->display_handler->viewExposedFormBlocks();
     // Before returning the block output, convert it to a renderable array with
     // contextual links.
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 2907f1e..cbae5f1 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -560,7 +560,7 @@ function views_contextual_links_view_alter(&$element, $items) {
  * @param $display_id
  *   The ID of the display within $view whose contextual links will be added.
  *
- * @see views_block_view()
+ * @see \Drupal\views\Plugin\block\block\ViewsBlock::addContextualLinks()
  * @see views_page_alter()
  * @see template_preprocess_views_view()
  */
diff --git a/core/profiles/minimal/config/block.block.stark.admin.yml b/core/profiles/minimal/config/block.block.stark.admin.yml
index e84cdbe..d16ae8b 100644
--- a/core/profiles/minimal/config/block.block.stark.admin.yml
+++ b/core/profiles/minimal/config/block.block.stark.admin.yml
@@ -1,19 +1,19 @@
 id: stark.admin
-label: Administration
 region: sidebar_first
-weight: '1'
-module: system
-status: '1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types: {  }
-  visibility__active_tab: edit-visibility-path
 plugin: 'system_menu_block:menu-admin'
 settings:
+  label: Administration
+  weight: '1'
+  module: system
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types: {  }
+    visibility__active_tab: edit-visibility-path
   cache: '-1'
-label_display: visible
+  label_display: visible
diff --git a/core/profiles/minimal/config/block.block.stark.login.yml b/core/profiles/minimal/config/block.block.stark.login.yml
index ba8a66d..17a4e1d 100644
--- a/core/profiles/minimal/config/block.block.stark.login.yml
+++ b/core/profiles/minimal/config/block.block.stark.login.yml
@@ -1,19 +1,19 @@
 id: stark.login
-label: 'User login'
 region: sidebar_first
-weight: '0'
-module: user
-status: '1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types: {  }
-  visibility__active_tab: edit-visibility-path
 plugin: user_login_block
 settings:
+  label: 'User login'
+  weight: '0'
+  module: user
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types: {  }
+    visibility__active_tab: edit-visibility-path
   cache: '-1'
-label_display: visible
+  label_display: visible
diff --git a/core/profiles/minimal/config/block.block.stark.tools.yml b/core/profiles/minimal/config/block.block.stark.tools.yml
index dda5b98..cccbb5e 100644
--- a/core/profiles/minimal/config/block.block.stark.tools.yml
+++ b/core/profiles/minimal/config/block.block.stark.tools.yml
@@ -1,19 +1,19 @@
 id: stark.tools
-label: Tools
 region: sidebar_first
-weight: '0'
-module: system
-status: '1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types: {  }
-  visibility__active_tab: edit-visibility-path
 plugin: 'system_menu_block:menu-tools'
 settings:
+  label: Tools
+  weight: '0'
+  module: system
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types: {  }
+    visibility__active_tab: edit-visibility-path
   cache: '-1'
-label_display: visible
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.content.yml b/core/profiles/standard/config/block.block.bartik.content.yml
index 07c3cdd..c389bb4 100644
--- a/core/profiles/standard/config/block.block.bartik.content.yml
+++ b/core/profiles/standard/config/block.block.bartik.content.yml
@@ -1,22 +1,22 @@
 id: bartik.content
+region: content
+langcode: en
 plugin: system_main_block
-status: '1'
 settings:
+  status: '1'
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: ''
-module: system
-region: content
-weight: '0'
-langcode: en
-label_display: visible
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: ''
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.footer.yml b/core/profiles/standard/config/block.block.bartik.footer.yml
index 553edb7..c8ff530 100644
--- a/core/profiles/standard/config/block.block.bartik.footer.yml
+++ b/core/profiles/standard/config/block.block.bartik.footer.yml
@@ -1,22 +1,22 @@
 id: bartik.footer
+region: footer
 plugin: 'system_menu_block:menu-footer'
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-label: 'Footer menu'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-module: system
-region: footer
-weight: '0'
-langcode: en
-label_display: visible
+  label: 'Footer menu'
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.help.yml b/core/profiles/standard/config/block.block.bartik.help.yml
index 84395a6..bf8abb5 100644
--- a/core/profiles/standard/config/block.block.bartik.help.yml
+++ b/core/profiles/standard/config/block.block.bartik.help.yml
@@ -1,22 +1,22 @@
 id: bartik.help
+region: help
 plugin: system_help_block
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: ''
-module: system
-region: help
-weight: '0'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: ''
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.login.yml b/core/profiles/standard/config/block.block.bartik.login.yml
index aac6997..988234b 100644
--- a/core/profiles/standard/config/block.block.bartik.login.yml
+++ b/core/profiles/standard/config/block.block.bartik.login.yml
@@ -1,23 +1,23 @@
 id: bartik.login
-whois_new_count: '5'
-status: '1'
 settings:
+  whois_new_count: '5'
+  status: '1'
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: 'User login'
-module: user
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: 'User login'
+  module: user
+  weight: '0'
+  label_display: visible
 region: sidebar_first
-weight: '0'
 plugin: user_login_block
 langcode: en
-label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.powered.yml b/core/profiles/standard/config/block.block.bartik.powered.yml
index 48424f8..c6a3739 100644
--- a/core/profiles/standard/config/block.block.bartik.powered.yml
+++ b/core/profiles/standard/config/block.block.bartik.powered.yml
@@ -1,22 +1,22 @@
 id: bartik.powered
+region: footer
 plugin: system_powered_by_block
-status: '1'
+langcode: en
 settings:
+  status: '1'
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: ''
-module: system
-region: footer
-weight: '10'
-langcode: en
-label_display: visible
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: ''
+  module: system
+  weight: '10'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.search.yml b/core/profiles/standard/config/block.block.bartik.search.yml
index bcf0249..22f7c23 100644
--- a/core/profiles/standard/config/block.block.bartik.search.yml
+++ b/core/profiles/standard/config/block.block.bartik.search.yml
@@ -1,22 +1,22 @@
 id: bartik.search
+region: sidebar_first
 plugin: search_form_block
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: 'Search'
-module: search
-region: sidebar_first
-weight: '-1'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: 'Search'
+  module: search
+  weight: '-1'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.bartik.tools.yml b/core/profiles/standard/config/block.block.bartik.tools.yml
index 56c8ba4..c56d80f 100644
--- a/core/profiles/standard/config/block.block.bartik.tools.yml
+++ b/core/profiles/standard/config/block.block.bartik.tools.yml
@@ -1,22 +1,22 @@
 id: bartik.tools
+region: sidebar_first
 plugin: 'system_menu_block:menu-tools'
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: 'Tools'
-module: system
-region: sidebar_first
-weight: '0'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: 'Tools'
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.seven.content.yml b/core/profiles/standard/config/block.block.seven.content.yml
index f14f147..7c4b669 100644
--- a/core/profiles/standard/config/block.block.seven.content.yml
+++ b/core/profiles/standard/config/block.block.seven.content.yml
@@ -1,22 +1,22 @@
 id: seven.content
+region: content
 plugin: system_main_block
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: ''
-module: system
-region: content
-weight: '0'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: ''
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.seven.help.yml b/core/profiles/standard/config/block.block.seven.help.yml
index 075f518..b337339 100644
--- a/core/profiles/standard/config/block.block.seven.help.yml
+++ b/core/profiles/standard/config/block.block.seven.help.yml
@@ -1,22 +1,22 @@
 id: seven.help
+region: help
 plugin: system_help_block
-status: '1'
+langcode: en
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: ''
-module: system
-region: help
-weight: '0'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: ''
+  module: system
+  weight: '0'
+  label_display: visible
diff --git a/core/profiles/standard/config/block.block.seven.login.yml b/core/profiles/standard/config/block.block.seven.login.yml
index f0fb2b2..dd8d4d8 100644
--- a/core/profiles/standard/config/block.block.seven.login.yml
+++ b/core/profiles/standard/config/block.block.seven.login.yml
@@ -1,22 +1,22 @@
 id: seven.login
+region: content
 plugin: user_login_block
-status: '1'
 settings:
   cache: '-1'
-visibility:
-  path:
-    visibility: '0'
-    pages: ''
-  role:
-    roles: {  }
-  node_type:
-    types:
-      article: '0'
-      page: '0'
-  visibility__active_tab: edit-visibility-path
-label: 'User login'
-module: user
-region: content
-weight: '10'
-langcode: en
-label_display: visible
+  status: '1'
+  visibility:
+    path:
+      visibility: '0'
+      pages: ''
+    role:
+      roles: {  }
+    node_type:
+      types:
+        article: '0'
+        page: '0'
+    visibility__active_tab: edit-visibility-path
+  label: 'User login'
+  module: user
+  weight: '10'
+  langcode: en
+  label_display: visible
diff --git a/core/themes/bartik/bartik.theme b/core/themes/bartik/bartik.theme
index 9a6c8a9..8ce4b28 100644
--- a/core/themes/bartik/bartik.theme
+++ b/core/themes/bartik/bartik.theme
@@ -114,8 +114,10 @@ function bartik_process_maintenance_page(&$variables) {
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function bartik_preprocess_block(&$variables) {
+  // @todo A block plugin cannot not know what region it is in.
+  $region = '';
   // In the header and footer regions visually hide block titles.
-  if ($variables['block']->region == 'header' || $variables['block']->region == 'footer') {
+  if ($region == 'header' || $region == 'footer') {
     $variables['title_attributes']['class'][] = 'element-invisible';
   }
 }
diff --git a/core/themes/bartik/css/colors.css b/core/themes/bartik/css/colors.css
index f2a3249..f8b3db3 100644
--- a/core/themes/bartik/css/colors.css
+++ b/core/themes/bartik/css/colors.css
@@ -40,7 +40,7 @@ a:focus {
 a:active {
   color: #23aeff;
 }
-.sidebar .block {
+.sidebar .block-wrapper {
   background-color: #f6f6f2;
   border-color: #f9f9f9;
 }
diff --git a/core/themes/bartik/css/style-rtl.css b/core/themes/bartik/css/style-rtl.css
index dc7c2a4..97cae37 100644
--- a/core/themes/bartik/css/style-rtl.css
+++ b/core/themes/bartik/css/style-rtl.css
@@ -30,8 +30,8 @@ tr th {
 ul.tips {
   padding: 0 1.25em 0 0;
 }
-.block ol,
-.block ul {
+.block-wrapper ol,
+.block-wrapper ul {
   padding: 0 1em 0.25em 0;
 }
 
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index 7a6a376..33888c1 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -230,8 +230,8 @@ table ul.links li {
 
 /* ------------------ List Styles ------------------ */
 
-.block ol,
-.block ul {
+.block-wrapper ol,
+.block-wrapper ul {
   margin: 0;
   padding: 0 0 0.25em 1em; /* LTR */
 }
@@ -333,21 +333,21 @@ h1#site-name {
   font-style: italic;
 }
 /* Region header blocks. */
-.region-header .block {
+.region-header .block-wrapper {
   font-size: 0.857em;
   float: left; /* LTR */
   margin: 0 10px;
   padding: 0;
 }
-.region-header .block .content {
+.region-header .block-wrapper .content {
   margin: 0;
   padding: 0;
 }
-.region-header .block ul {
+.region-header .block-wrapper ul {
   margin: 0;
   padding: 0;
 }
-.region-header .block li {
+.region-header .block-wrapper li {
   list-style: none;
   list-style-image: none;
   padding: 0;
@@ -754,7 +754,7 @@ ul.links {
 .sidebar .section {
   padding-top: 10px;
 }
-.sidebar .block {
+.sidebar .block-wrapper {
   border: 1px solid;
   padding: 15px 20px;
   margin: 0 0 20px;
@@ -767,7 +767,7 @@ ul.links {
   font-size: 1.071em;
   line-height: 1.2;
 }
-.sidebar .block .content {
+.sidebar .block-wrapper .content {
   font-size: 0.914em;
   line-height: 1.4;
 }
@@ -795,7 +795,7 @@ ul.links {
   text-align: center;
   line-height: 1;
 }
-#triptych .block {
+#triptych .block-wrapper {
   margin-bottom: 1em;
   padding-bottom: 1em;
   border-bottom: 1px solid #dfdfdf;
@@ -804,12 +804,12 @@ ul.links {
 #triptych .block.last {
   border-bottom: none;
 }
-#triptych .block ul li,
-#triptych .block ol li {
+#triptych .block-wrapper ul li,
+#triptych .block-wrapper ol li {
   list-style: none;
 }
-#triptych .block ul,
-#triptych .block ol {
+#triptych .block-wrapper ul,
+#triptych .block-wrapper ol {
   padding-left: 0;
 }
 #triptych #block-user-login .form-text {
@@ -853,26 +853,26 @@ ul.links {
   color: rgba(255, 255, 255, 0.95);
   text-decoration: underline;
 }
-#footer-wrapper .block {
+#footer-wrapper .block-wrapper {
   margin: 20px 0;
   border: 1px solid #444;
   border-color: rgba(255, 255, 255, 0.1);
   padding: 10px;
 }
 #footer-columns .block-menu,
-#footer .block {
+#footer .block-wrapper {
   margin: 0;
   padding: 0;
   border: none;
 }
-#footer .block {
+#footer .block-wrapper {
   margin: 0.5em 0;
 }
-#footer .block .content {
+#footer .block-wrapper .content {
   padding: 0.5em 0;
   margin-top: 0;
 }
-#footer .block h2 {
+#footer .block-wrapper h2 {
   margin: 0;
 }
 #footer-columns h2 {
@@ -922,7 +922,7 @@ ul.links {
 #footer .region {
   margin-top: 20px;
 }
-#footer .block {
+#footer .block-wrapper {
   clear: both;
 }
 #footer ul,
@@ -1614,7 +1614,7 @@ div.admin-panel .description {
     font-size: 1.714em;
     margin-bottom: 0.9em;
   }
-  #triptych .block {
+  #triptych .block-wrapper {
     margin-bottom: 2em;
     padding-bottom: 2em;
   }
diff --git a/core/themes/seven/style-rtl.css b/core/themes/seven/style-rtl.css
index f4097d9..f16111d 100644
--- a/core/themes/seven/style-rtl.css
+++ b/core/themes/seven/style-rtl.css
@@ -6,7 +6,6 @@ dl dl {
   margin-right: 20px;
 }
 ul,
-.block ul,
 .item-list ul {
   margin: 0.25em 1.5em 0.25em 0;
 }
diff --git a/core/themes/stark/css/layout-rtl.css b/core/themes/stark/css/layout-rtl.css
index d5e9c6d..214bb38 100644
--- a/core/themes/stark/css/layout-rtl.css
+++ b/core/themes/stark/css/layout-rtl.css
@@ -18,7 +18,7 @@
     float: right;
     clear: right;
   }
-  body.two-sidebars #sidebar-second .block {
+  body.two-sidebars #sidebar-second .block-wrapper {
     float: right;
   }
 }
diff --git a/core/themes/stark/css/layout.css b/core/themes/stark/css/layout.css
index 39f533b..c303dea 100644
--- a/core/themes/stark/css/layout.css
+++ b/core/themes/stark/css/layout.css
@@ -52,7 +52,7 @@ img {
     width: 100%;
   }
 
-  body.two-sidebars #sidebar-second .block {
+  body.two-sidebars #sidebar-second .block-wrapper {
     float: left; /* LTR */
     width: 33%;
   }
