diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml
index dabe16d4a344a40ef93769cd7700fff2ad0806e4..6dd6d3ea9d992df5b4907094abebd2127827a41a 100644
--- a/app/code/Magento/Backend/etc/adminhtml/system.xml
+++ b/app/code/Magento/Backend/etc/adminhtml/system.xml
@@ -179,6 +179,10 @@
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                     <comment>Warning! Enabling this feature is not recommended on production environments because it represents a potential security risk.</comment>
                 </field>
+                <field id="minify_html" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1">
+                    <label>Minify Html</label>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                </field>
             </group>
             <group id="translate_inline" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
                 <label>Translate Inline</label>
diff --git a/app/code/Magento/Backend/etc/config.xml b/app/code/Magento/Backend/etc/config.xml
index 0d4c5d7180513828a1fd452c6c17d3847b8910d3..ea2586bae427a78a76e1fe2eb2e36077c8683824 100644
--- a/app/code/Magento/Backend/etc/config.xml
+++ b/app/code/Magento/Backend/etc/config.xml
@@ -7,6 +7,11 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd">
     <default>
+        <dev>
+            <template>
+                <minify_html>1</minify_html>
+            </template>
+        </dev>
         <system>
             <media_storage_configuration>
                 <allowed_resources>
diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml
index bcc039467893ee6422bb34cb2a5ab8e326eca45d..930efcfb1c1aa92dc4278cbd19f997529a32d1b7 100644
--- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml
+++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml
@@ -30,7 +30,7 @@
     echo 'validate-one-required-by-name' ?>"
                     id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>"
                     type="checkbox"
-                    name="bundle_option[<?php echo $_option->getId() ?>][]"<?php if ($block->isSelected($_selection)) {
+                    name="bundle_option[<?php echo $_option->getId() ?>][<?php echo $_selection ?>]"<?php if ($block->isSelected($_selection)) {
     echo ' checked="checked"' ?><?php if (!$_selection->isSaleable() && !$_skipSaleableCheck) {
     echo ' disabled="disabled"' ?>
                     value="<?php echo $_selection->getSelectionId() ?>"
diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml
index d8b5d461196b9d55fe440083ac160a17315e9652..03922735e0c8ec34f66563eb556920916de57d5b 100644
--- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml
+++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml
@@ -21,7 +21,7 @@
                    price="<?php echo $block->getSelectionPrice($_selections[0]) ?>" />
         <?php else: ?>
             <select multiple="multiple" size="5" id="bundle-option-<?php echo $_option->getId() ?>"
-                    name="bundle_option[<?php echo $_option->getId() ?>][]"
+                    name="bundle_option[<?php echo $_option->getId() ?>]"
                     class="bundle-option-<?php echo $_option->getId() ?><?php if ($_option->getRequired()) echo ' required-entry' ?> multiselect change-container-classname"
                     onchange="ProductConfigure.bundleControl.changeSelection(this)">
             <?php if(!$_option->getRequired()): ?>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml
index 588184ee564d2d2d381250347d8f9fcce9034e1f..00938f3c70c0f58427e5b1302dc9c77f3ee6ed0c 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml
@@ -30,7 +30,7 @@
                                id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>"
                                type="checkbox"
                                <?php if ($_option->getRequired()) echo 'data-validate="{\'validate-one-required-by-name\':true}"'?>
-                               name="bundle_option[<?php echo $_option->getId() ?>][]"
+                               name="bundle_option[<?php echo $_option->getId() ?>][<?php echo $_selection->getId() ?>]"
                                <?php if ($block->isSelected($_selection)) echo ' checked="checked"' ?>
                                <?php if (!$_selection->isSaleable()) echo ' disabled="disabled"' ?>
                                value="<?php echo $_selection->getSelectionId() ?>"/>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml
index 81cb30bc6f7cf4e8a5eb0d624c72035809eb0ab5..5c32f9c42a23c300464df14ee8292b203755b8da 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml
@@ -24,7 +24,7 @@
             <select multiple="multiple"
                     size="5"
                     id="bundle-option-<?php echo $_option->getId() ?>"
-                    name="bundle_option[<?php echo $_option->getId() ?>][]"
+                    name="bundle_option[<?php echo $_option->getId() ?>]"
                     class="bundle-option-<?php echo $_option->getId() ?> multiselect product bundle option change-container-classname"
                     <?php if ($_option->getRequired()) echo 'data-validate={required:true}' ?>>
                 <?php if(!$_option->getRequired()): ?>
diff --git a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
index c14759cdc910ec6f5c14762f917359f872a5fa86..1865f71cd6b75e56cc0ddb0fa9a979079ca56ea9 100644
--- a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
+++ b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
@@ -15,7 +15,7 @@
     <?php if ($block->getDisplayLabel()): ?>
         <span class="price-label"><?php echo $block->getDisplayLabel(); ?></span>
     <?php endif; ?>
-    <span<?php if ($block->getPriceId()): ?> id="<?php echo $block->getPriceId() ?>"<?php endif;?>
+    <span <?php if ($block->getPriceId()): ?> id="<?php echo $block->getPriceId() ?>"<?php endif;?>
         <?php echo($block->getPriceDisplayLabel()) ? 'data-label="' . $block->getPriceDisplayLabel() . $block->getPriceDisplayInclExclTaxes() . '"' : '' ?>
         data-price-amount="<?php echo $block->getDisplayValue(); ?>"
         data-price-type="<?php echo $block->getPriceType(); ?>"
diff --git a/app/code/Magento/Checkout/Helper/Data.php b/app/code/Magento/Checkout/Helper/Data.php
index b3a064ad8163deff1357c9644694bea307e78900..44f5950b80be6b60230d9b008b56b33a5fab7f73 100644
--- a/app/code/Magento/Checkout/Helper/Data.php
+++ b/app/code/Magento/Checkout/Helper/Data.php
@@ -278,7 +278,11 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
                 [
                     'reason' => $message,
                     'checkoutType' => $checkoutType,
-                    'dateAndTime' => $this->_localeDate->date(),
+                    'dateAndTime' => $this->_localeDate->formatDateTime(
+                        new \DateTime(),
+                        \IntlDateFormatter::MEDIUM,
+                        \IntlDateFormatter::MEDIUM
+                    ),
                     'customer' => $checkout->getCustomerFirstname() . ' ' . $checkout->getCustomerLastname(),
                     'customerEmail' => $checkout->getCustomerEmail(),
                     'billingAddress' => $checkout->getBillingAddress(),
diff --git a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php
index bc5499166cd061f17548ab4fe1d1c8833c5f34fa..e844d62b7d840199cd200112a946810c1db01e6d 100644
--- a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php
@@ -123,8 +123,9 @@ class DataTest extends \PHPUnit_Framework_TestCase
             );
 
         $this->_checkoutSession = $arguments['checkoutSession'];
-        $localeDate = $arguments['localeDate'];
-        $localeDate->expects($this->any())->method('date')->will($this->returnValue('Oct 02, 2013'));
+        $arguments['localeDate']->expects($this->any())
+            ->method('formatDateTime')
+            ->willReturn('Oct 02, 2013');
 
         $this->_transportBuilder = $arguments['transportBuilder'];
 
diff --git a/app/code/Magento/Customer/Controller/Account/CreatePost.php b/app/code/Magento/Customer/Controller/Account/CreatePost.php
index 50824c3972cf7036d1d4230229c50cfe155748cb..fcefbfaa9fcd69123926b3b4160742ffc68f58fb 100644
--- a/app/code/Magento/Customer/Controller/Account/CreatePost.php
+++ b/app/code/Magento/Customer/Controller/Account/CreatePost.php
@@ -1,13 +1,14 @@
 <?php
 /**
- *
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
 namespace Magento\Customer\Controller\Account;
 
+use Magento\Customer\Model\Account\Redirect as AccountRedirect;
 use Magento\Customer\Api\Data\AddressInterface;
 use Magento\Customer\Model\Url;
+use Magento\Framework\Api\DataObjectHelper;
 use Magento\Framework\App\Action\Context;
 use Magento\Customer\Model\Session;
 use Magento\Framework\Controller\Result\RedirectFactory;
@@ -28,19 +29,12 @@ use Magento\Framework\Escaper;
 use Magento\Customer\Model\CustomerExtractor;
 use Magento\Framework\Exception\StateException;
 use Magento\Framework\Exception\InputException;
-use Magento\Store\Model\ScopeInterface;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class CreatePost extends \Magento\Customer\Controller\Account
 {
-    /** @var ScopeConfigInterface */
-    protected $scopeConfig;
-
-    /** @var StoreManagerInterface */
-    protected $storeManager;
-
     /** @var AccountManagementInterface */
     protected $accountManagement;
 
@@ -77,10 +71,13 @@ class CreatePost extends \Magento\Customer\Controller\Account
     /** @var \Magento\Framework\UrlInterface */
     protected $urlModel;
 
+    /** @var DataObjectHelper  */
+    protected $dataObjectHelper;
+
     /**
-     * @var \Magento\Framework\Api\DataObjectHelper
+     * @var AccountRedirect
      */
-    protected $dataObjectHelper;
+    private $accountRedirect;
 
     /**
      * @param Context $context
@@ -101,7 +98,8 @@ class CreatePost extends \Magento\Customer\Controller\Account
      * @param Registration $registration
      * @param Escaper $escaper
      * @param CustomerExtractor $customerExtractor
-     * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
+     * @param DataObjectHelper $dataObjectHelper
+     * @param AccountRedirect $accountRedirect
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -124,7 +122,8 @@ class CreatePost extends \Magento\Customer\Controller\Account
         Registration $registration,
         Escaper $escaper,
         CustomerExtractor $customerExtractor,
-        \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
+        DataObjectHelper $dataObjectHelper,
+        AccountRedirect $accountRedirect
     ) {
         $this->scopeConfig = $scopeConfig;
         $this->storeManager = $storeManager;
@@ -141,7 +140,13 @@ class CreatePost extends \Magento\Customer\Controller\Account
         $this->customerExtractor = $customerExtractor;
         $this->urlModel = $urlFactory->create();
         $this->dataObjectHelper = $dataObjectHelper;
-        parent::__construct($context, $customerSession, $resultRedirectFactory, $resultPageFactory);
+        $this->accountRedirect = $accountRedirect;
+        parent::__construct(
+            $context,
+            $customerSession,
+            $resultRedirectFactory,
+            $resultPageFactory
+        );
     }
 
     /**
@@ -257,9 +262,8 @@ class CreatePost extends \Magento\Customer\Controller\Account
                 $resultRedirect->setUrl($this->_redirect->success($url));
             } else {
                 $this->_getSession()->setCustomerDataAsLoggedIn($customer);
-
                 $this->messageManager->addSuccess($this->getSuccessMessage());
-                $resultRedirect->setUrl($this->getSuccessRedirect());
+                $resultRedirect = $this->accountRedirect->getRedirect();
             }
             return $resultRedirect;
         } catch (StateException $e) {
@@ -329,23 +333,4 @@ class CreatePost extends \Magento\Customer\Controller\Account
         }
         return $message;
     }
-
-    /**
-     * Retrieve success redirect URL
-     *
-     * @return string
-     */
-    protected function getSuccessRedirect()
-    {
-        $redirectToDashboard = $this->scopeConfig->isSetFlag(
-            Url::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD,
-            ScopeInterface::SCOPE_STORE
-        );
-        if (!$redirectToDashboard && $this->_getSession()->getBeforeAuthUrl()) {
-            $successUrl = $this->_getSession()->getBeforeAuthUrl(true);
-        } else {
-            $successUrl = $this->urlModel->getUrl('*/*/index', ['_secure' => true]);
-        }
-        return $this->_redirect->success($successUrl);
-    }
 }
diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php
index bf13ee5fcc4ef2c3cc611ef2ec2d4d5aa860e896..a3df334fbf83560dc676ee96e415ff842a88ac30 100644
--- a/app/code/Magento/Customer/Controller/Account/EditPost.php
+++ b/app/code/Magento/Customer/Controller/Account/EditPost.php
@@ -81,6 +81,9 @@ class EditPost extends \Magento\Customer\Controller\Account
             $customerId = $this->_getSession()->getCustomerId();
             $customer = $this->customerExtractor->extract('customer_account_edit', $this->_request);
             $customer->setId($customerId);
+            if ($customer->getAddresses() == null) {
+                $customer->setAddresses($this->customerRepository->getById($customerId)->getAddresses());
+            }
 
             if ($this->getRequest()->getParam('change_password')) {
                 $currPass = $this->getRequest()->getPost('current_password');
diff --git a/app/code/Magento/Customer/Controller/Account/LoginPost.php b/app/code/Magento/Customer/Controller/Account/LoginPost.php
index acc5eb614bba76d01c15f09c63269b2bd55bc8ea..1f05dff29314ebeca53856b305565dca6619aeb1 100644
--- a/app/code/Magento/Customer/Controller/Account/LoginPost.php
+++ b/app/code/Magento/Customer/Controller/Account/LoginPost.php
@@ -1,19 +1,16 @@
 <?php
 /**
- *
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
 namespace Magento\Customer\Controller\Account;
 
+use Magento\Customer\Model\Account\Redirect as AccountRedirect;
 use Magento\Framework\App\Action\Context;
 use Magento\Customer\Model\Session;
 use Magento\Framework\Controller\Result\RedirectFactory;
 use Magento\Framework\View\Result\PageFactory;
-use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\Store\Model\StoreManagerInterface;
 use Magento\Customer\Api\AccountManagementInterface;
-use Magento\Framework\Url\DecoderInterface;
 use Magento\Customer\Model\Url as CustomerUrl;
 use Magento\Framework\Exception\EmailNotConfirmedException;
 use Magento\Framework\Exception\AuthenticationException;
@@ -24,35 +21,26 @@ use Magento\Framework\Data\Form\FormKey\Validator;
  */
 class LoginPost extends \Magento\Customer\Controller\Account
 {
-    /** @var ScopeConfigInterface */
-    protected $scopeConfig;
-
-    /** @var StoreManagerInterface */
-    protected $storeManager;
-
     /** @var AccountManagementInterface */
     protected $customerAccountManagement;
 
-    /** @var DecoderInterface */
-    protected $urlDecoder;
-
-    /** @var CustomerUrl */
-    protected $customerUrl;
-
     /** @var Validator */
     protected $formKeyValidator;
 
+    /**
+     * @var AccountRedirect
+     */
+    private $accountRedirect;
+
     /**
      * @param Context $context
      * @param Session $customerSession
      * @param RedirectFactory $resultRedirectFactory
      * @param PageFactory $resultPageFactory
-     * @param ScopeConfigInterface $scopeConfig
-     * @param StoreManagerInterface $storeManager
      * @param AccountManagementInterface $customerAccountManagement
-     * @param DecoderInterface $urlDecoder
      * @param CustomerUrl $customerHelperData
-     * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator
+     * @param Validator $formKeyValidator
+     * @param AccountRedirect $accountRedirect
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -61,76 +49,21 @@ class LoginPost extends \Magento\Customer\Controller\Account
         Session $customerSession,
         RedirectFactory $resultRedirectFactory,
         PageFactory $resultPageFactory,
-        ScopeConfigInterface $scopeConfig,
-        StoreManagerInterface $storeManager,
         AccountManagementInterface $customerAccountManagement,
-        DecoderInterface $urlDecoder,
         CustomerUrl $customerHelperData,
-        Validator $formKeyValidator
+        Validator $formKeyValidator,
+        AccountRedirect $accountRedirect
     ) {
-        $this->scopeConfig = $scopeConfig;
-        $this->storeManager = $storeManager;
         $this->customerAccountManagement = $customerAccountManagement;
-        $this->urlDecoder = $urlDecoder;
         $this->customerUrl = $customerHelperData;
         $this->formKeyValidator = $formKeyValidator;
-        parent::__construct($context, $customerSession, $resultRedirectFactory, $resultPageFactory);
-    }
-
-    /**
-     * Define target URL and redirect customer after logging in
-     *
-     * @return \Magento\Framework\Controller\Result\Redirect
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
-     */
-    protected function loginPostRedirect()
-    {
-        $lastCustomerId = $this->_getSession()->getLastCustomerId();
-        if (isset(
-            $lastCustomerId
-            ) && $this->_getSession()->isLoggedIn() && $lastCustomerId != $this->_getSession()->getId()
-        ) {
-            $this->_getSession()->unsBeforeAuthUrl()->setLastCustomerId($this->_getSession()->getId());
-        }
-        if (!$this->_getSession()->getBeforeAuthUrl() ||
-            $this->_getSession()->getBeforeAuthUrl() == $this->storeManager->getStore()->getBaseUrl()
-        ) {
-            // Set default URL to redirect customer to
-            $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getAccountUrl());
-            // Redirect customer to the last page visited after logging in
-            if ($this->_getSession()->isLoggedIn()) {
-                if (!$this->scopeConfig->isSetFlag(
-                    CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD,
-                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-                )
-                ) {
-                    $referer = $this->getRequest()->getParam(CustomerUrl::REFERER_QUERY_PARAM_NAME);
-                    if ($referer) {
-                        $referer = $this->urlDecoder->decode($referer);
-                        if ($this->_url->isOwnOriginUrl()) {
-                            $this->_getSession()->setBeforeAuthUrl($referer);
-                        }
-                    }
-                } elseif ($this->_getSession()->getAfterAuthUrl()) {
-                    $this->_getSession()->setBeforeAuthUrl($this->_getSession()->getAfterAuthUrl(true));
-                }
-            } else {
-                $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getLoginUrl());
-            }
-        } elseif ($this->_getSession()->getBeforeAuthUrl() == $this->customerUrl->getLogoutUrl()) {
-            $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getDashboardUrl());
-        } else {
-            if (!$this->_getSession()->getAfterAuthUrl()) {
-                $this->_getSession()->setAfterAuthUrl($this->_getSession()->getBeforeAuthUrl());
-            }
-            if ($this->_getSession()->isLoggedIn()) {
-                $this->_getSession()->setBeforeAuthUrl($this->_getSession()->getAfterAuthUrl(true));
-            }
-        }
-        /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
-        $resultRedirect = $this->resultRedirectFactory->create();
-        $resultRedirect->setUrl($this->_getSession()->getBeforeAuthUrl(true));
-        return $resultRedirect;
+        $this->accountRedirect = $accountRedirect;
+        parent::__construct(
+            $context,
+            $customerSession,
+            $resultRedirectFactory,
+            $resultPageFactory
+        );
     }
 
     /**
@@ -177,6 +110,6 @@ class LoginPost extends \Magento\Customer\Controller\Account
             }
         }
 
-        return $this->loginPostRedirect();
+        return $this->accountRedirect->getRedirect();
     }
 }
diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..e230390fa2a991eaa6e3ff1da7e8a14c34c6fb07
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Account/Redirect.php
@@ -0,0 +1,199 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Account;
+
+use Magento\Customer\Model\Session;
+use Magento\Customer\Model\Url as CustomerUrl;
+use Magento\Framework\App\RequestInterface;
+use Magento\Framework\UrlInterface;
+use Magento\Store\Model\ScopeInterface;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\Controller\Result\Redirect as ResultRedirect;
+use Magento\Framework\Controller\Result\RedirectFactory;
+use Magento\Framework\Url\DecoderInterface;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class Redirect
+{
+    /**
+     * @var RequestInterface
+     */
+    protected $request;
+
+    /**
+     * @var ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var DecoderInterface
+     */
+    protected $urlDecoder;
+
+    /**
+     * @var CustomerUrl
+     */
+    protected $customerUrl;
+
+    /**
+     * @var UrlInterface
+     */
+    protected $url;
+
+    /**
+     * @var RedirectFactory
+     */
+    protected $resultRedirectFactory;
+
+    /**
+     * @param RequestInterface $request
+     * @param Session $customerSession
+     * @param ScopeConfigInterface $scopeConfig
+     * @param StoreManagerInterface $storeManager
+     * @param UrlInterface $url
+     * @param DecoderInterface $urlDecoder
+     * @param CustomerUrl $customerUrl
+     * @param RedirectFactory $resultRedirectFactory
+     */
+    public function __construct(
+        RequestInterface $request,
+        Session $customerSession,
+        ScopeConfigInterface $scopeConfig,
+        StoreManagerInterface $storeManager,
+        UrlInterface $url,
+        DecoderInterface $urlDecoder,
+        CustomerUrl $customerUrl,
+        RedirectFactory $resultRedirectFactory
+    ) {
+        $this->request = $request;
+        $this->session = $customerSession;
+        $this->scopeConfig = $scopeConfig;
+        $this->storeManager = $storeManager;
+        $this->url = $url;
+        $this->urlDecoder = $urlDecoder;
+        $this->customerUrl = $customerUrl;
+        $this->resultRedirectFactory = $resultRedirectFactory;
+    }
+
+    /**
+     * Retrieve redirect
+     *
+     * @return ResultRedirect
+     */
+    public function getRedirect()
+    {
+        $this->updateLastCustomerId();
+        $this->prepareRedirectUrl();
+
+        /** @var ResultRedirect $resultRedirect */
+        $resultRedirect = $this->resultRedirectFactory->create();
+        $resultRedirect->setUrl($this->session->getBeforeAuthUrl(true));
+        return $resultRedirect;
+    }
+
+    /**
+     * Update last customer id, if required
+     *
+     * @return void
+     */
+    protected function updateLastCustomerId()
+    {
+        $lastCustomerId = $this->session->getLastCustomerId();
+        if (isset($lastCustomerId)
+            && $this->session->isLoggedIn()
+            && $lastCustomerId != $this->session->getId()
+        ) {
+            $this->session->unsBeforeAuthUrl()
+                ->setLastCustomerId($this->session->getId());
+        }
+    }
+
+    /**
+     * Prepare redirect URL
+     *
+     * @return void
+     */
+    protected function prepareRedirectUrl()
+    {
+        $baseUrl = $this->storeManager->getStore()->getBaseUrl();
+
+        $url = $this->session->getBeforeAuthUrl();
+        if (!$url) {
+            $url = $baseUrl;
+        }
+
+        switch ($url) {
+            case $baseUrl:
+                if ($this->session->isLoggedIn()) {
+                    $this->processLoggedCustomer();
+                } else {
+                    $this->applyRedirect($this->customerUrl->getLoginUrl());
+                }
+                break;
+
+            case $this->customerUrl->getLogoutUrl():
+                $this->applyRedirect($this->customerUrl->getDashboardUrl());
+                break;
+
+            default:
+                if (!$this->session->getAfterAuthUrl()) {
+                    $this->session->setAfterAuthUrl($this->session->getBeforeAuthUrl());
+                }
+                if ($this->session->isLoggedIn()) {
+                    $this->applyRedirect($this->session->getAfterAuthUrl(true));
+                }
+                break;
+        }
+    }
+
+    /**
+     * Prepare redirect URL for logged in customer
+     *
+     * Redirect customer to the last page visited after logging in.
+     *
+     * @return void
+     */
+    protected function processLoggedCustomer()
+    {
+        // Set default redirect URL for logged in customer
+        $this->applyRedirect($this->customerUrl->getAccountUrl());
+
+        if (!$this->scopeConfig->isSetFlag(
+            CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD,
+            ScopeInterface::SCOPE_STORE
+        )
+        ) {
+            $referer = $this->request->getParam(CustomerUrl::REFERER_QUERY_PARAM_NAME);
+            if ($referer) {
+                $referer = $this->urlDecoder->decode($referer);
+                if ($this->url->isOwnOriginUrl()) {
+                    $this->applyRedirect($referer);
+                }
+            }
+        } elseif ($this->session->getAfterAuthUrl()) {
+            $this->applyRedirect($this->session->getAfterAuthUrl(true));
+        }
+    }
+
+    /**
+     * Prepare redirect URL
+     *
+     * @param string $url
+     * @return void
+     */
+    private function applyRedirect($url)
+    {
+        $this->session->setBeforeAuthUrl($url);
+    }
+}
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index c850e8c5a8e16b1f7a2fd8a7f176099b99b123d0..129f46990118ab34ef0bd442198d93f5a5d325c3 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -1077,7 +1077,7 @@ class AccountManagement implements AccountManagementInterface
      */
     public function sendPasswordResetConfirmationEmail($customer)
     {
-        $storeId = $customer->getStoreId();
+        $storeId = $this->storeManager->getStore()->getId();
         if (!$storeId) {
             $storeId = $this->getWebsiteStoreId($customer);
         }
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..86113cef969df40aa3c6f1f1f1603acca0f148b2
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php
@@ -0,0 +1,408 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Unit\Controller\Account;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class EditPostTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $context;
+
+    /**
+     * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerSession;
+
+    /**
+     * @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultRedirectFactory;
+
+    /**
+     * @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultPageFactory;
+
+    /**
+     * @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerAccountManagement;
+
+    /**
+     * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerRepository;
+
+    /**
+     * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $formKeyValidator;
+
+    /**
+     * @var \Magento\Customer\Model\CustomerExtractor|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerExtractor;
+
+    /**
+     * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $redirectResultMock;
+
+    /**
+     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $response;
+
+    /**
+     * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $request;
+
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customer;
+
+    /**
+     * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManager;
+
+    public function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->response = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false);
+        $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+
+        $this->messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false);
+
+        $this->context = $this->objectManager->getObject(
+            'Magento\Framework\App\Action\Context',
+            [
+                'request' => $this->request,
+                'response' => $this->response,
+                'messageManager' => $this->messageManager
+            ]
+        );
+
+        $this->redirectResultMock = $this->getMock('Magento\Framework\Controller\Result\Redirect', [], [], '', false);
+        $this->customerSession = $this->getMock('Magento\Customer\Model\Session', [], [], '', false);
+        $this->resultRedirectFactory = $this->getMock(
+            'Magento\Framework\Controller\Result\RedirectFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->resultPageFactory = $this->getMock('Magento\Framework\View\Result\PageFactory', [], [], '', false);
+        $this->customerAccountManagement = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\AccountManagementInterface',
+            [],
+            '',
+            false
+        );
+        $this->customerRepository = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\CustomerRepositoryInterface',
+            [],
+            '',
+            false
+        );
+        $this->formKeyValidator = $this->getMock('Magento\Framework\Data\Form\FormKey\Validator', [], [], '', false);
+        $this->customerExtractor = $this->getMock('Magento\Customer\Model\CustomerExtractor', [], [], '', false);
+        $this->customer = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\CustomerInterface',
+            [],
+            'dataCustomer',
+            false
+        );
+    }
+
+    /**
+     * @return \Magento\Customer\Controller\Account\EditPost
+     */
+    public function getController()
+    {
+        return $this->objectManager->getObject(
+            'Magento\Customer\Controller\Account\EditPost',
+            [
+                'context' => $this->context,
+                'customerSession' => $this->customerSession,
+                'resultRedirectFactory' => $this->resultRedirectFactory,
+                'resultPageFactory' => $this->resultPageFactory,
+                'customerAccountManagement' => $this->customerAccountManagement,
+                'customerRepository' => $this->customerRepository,
+                'formKeyValidator' => $this->formKeyValidator,
+                'customerExtractor' => $this->customerExtractor
+            ]
+        );
+    }
+
+    public function testEditPostActionWithInvalidFormKey()
+    {
+        $this->resultRedirectFactory
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($this->redirectResultMock);
+        $this->formKeyValidator
+            ->expects($this->once())
+            ->method('validate')
+            ->willReturn(false);
+        $this->redirectResultMock
+            ->expects($this->once())
+            ->method('setPath')
+            ->with('*/*/edit')
+            ->willReturn('http://test.com/customer/account/edit');
+
+        $this->assertSame($this->redirectResultMock, $this->getController()->execute());
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testEditPostActionWithAuthenticationExceptionWhenTryingChangePassword()
+    {
+        $customerId = 24;
+        $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false);
+        $loadedCustomer = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\CustomerInterface',
+            [],
+            'loadedCustomer',
+            false
+        );
+
+        $loadedCustomer
+            ->expects($this->once())
+            ->method('getAddresses')
+            ->willReturn([$address, $address]);
+
+        $this->resultRedirectFactory
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($this->redirectResultMock);
+        $this->formKeyValidator
+            ->expects($this->once())
+            ->method('validate')
+            ->willReturn(true);
+        $this->request
+            ->expects($this->once())
+            ->method('isPost')
+            ->willReturn(true);
+
+        $this->customerSession
+            ->expects($this->once())
+            ->method('getCustomerId')
+            ->willReturn($customerId);
+        $this->customerExtractor
+            ->expects($this->once())
+            ->method('extract')
+            ->willReturn($this->customer);
+        $this->customer
+            ->expects($this->once())
+            ->method('setId')
+            ->with($customerId);
+        $this->customer
+            ->expects($this->once())
+            ->method('getAddresses')
+            ->willReturn(null);
+        $this->customerRepository
+            ->expects($this->exactly(2))
+            ->method('getById')
+            ->with($customerId)
+            ->willReturn($loadedCustomer);
+        $this->customer
+            ->expects($this->once())
+            ->method('setAddresses')
+            ->with([$address, $address]);
+        $this->request
+            ->expects($this->once())
+            ->method('getParam')
+            ->with('change_password')
+            ->willReturn(true);
+
+        $this->request
+            ->expects($this->at(2))
+            ->method('getPost')
+            ->with('current_password', null)
+            ->willReturn(123);
+        $this->request
+            ->expects($this->at(3))
+            ->method('getPost')
+            ->with('password', null)
+            ->willReturn(321);
+        $this->request
+            ->expects($this->at(4))
+            ->method('getPost')
+            ->with('password_confirmation', null)
+            ->willReturn(321);
+
+        $this->customerAccountManagement
+            ->expects($this->once())
+            ->method('changePassword')
+            ->willThrowException(new \Magento\Framework\Exception\AuthenticationException(__('Error')));
+        $this->messageManager
+            ->expects($this->once())
+            ->method('addError')
+            ->with('Error');
+
+        $exception = new \Magento\Framework\Exception\InputException(__('Error'));
+        $this->customerRepository
+            ->expects($this->once())
+            ->method('save')
+            ->willThrowException($exception);
+        $this->messageManager
+            ->expects($this->once())
+            ->method('addException')
+            ->with($exception, 'Invalid input');
+        $this->request
+            ->expects($this->once())
+            ->method('getPostValue')
+            ->willReturn([]);
+
+        $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false);
+        $messageCollection
+            ->expects($this->once())
+            ->method('getCount')
+            ->willReturn(3);
+        $this->messageManager
+            ->expects($this->once())
+            ->method('getMessages')
+            ->willReturn($messageCollection);
+        $this->customerSession
+            ->expects($this->once())
+            ->method('__call')
+            ->with('setCustomerFormData', [[]]);
+
+        $this->redirectResultMock
+            ->expects($this->once())
+            ->method('setPath')
+            ->with('*/*/edit')
+            ->willReturn('http://test.com/customer/account/edit');
+
+        $this->assertSame($this->redirectResultMock, $this->getController()->execute());
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testEditPostActionWithoutErrors()
+    {
+        $customerId = 24;
+        $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false);
+        $loadedCustomer = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\CustomerInterface',
+            [],
+            'loadedCustomer',
+            false
+        );
+
+        $loadedCustomer
+            ->expects($this->once())
+            ->method('getAddresses')
+            ->willReturn([$address, $address]);
+
+        $this->resultRedirectFactory
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($this->redirectResultMock);
+        $this->formKeyValidator
+            ->expects($this->once())
+            ->method('validate')
+            ->willReturn(true);
+        $this->request
+            ->expects($this->once())
+            ->method('isPost')
+            ->willReturn(true);
+
+        $this->customerSession
+            ->expects($this->once())
+            ->method('getCustomerId')
+            ->willReturn($customerId);
+        $this->customerExtractor
+            ->expects($this->once())
+            ->method('extract')
+            ->willReturn($this->customer);
+        $this->customer
+            ->expects($this->once())
+            ->method('setId')
+            ->with($customerId);
+        $this->customer
+            ->expects($this->once())
+            ->method('getAddresses')
+            ->willReturn(null);
+        $this->customerRepository
+            ->expects($this->exactly(2))
+            ->method('getById')
+            ->with($customerId)
+            ->willReturn($loadedCustomer);
+        $this->customer
+            ->expects($this->once())
+            ->method('setAddresses')
+            ->with([$address, $address]);
+        $this->request
+            ->expects($this->once())
+            ->method('getParam')
+            ->with('change_password')
+            ->willReturn(true);
+
+        $this->request
+            ->expects($this->at(2))
+            ->method('getPost')
+            ->with('current_password', null)
+            ->willReturn(123);
+        $this->request
+            ->expects($this->at(3))
+            ->method('getPost')
+            ->with('password', null)
+            ->willReturn(321);
+        $this->request
+            ->expects($this->at(4))
+            ->method('getPost')
+            ->with('password_confirmation', null)
+            ->willReturn(321);
+
+        $this->customerAccountManagement
+            ->expects($this->once())
+            ->method('changePassword');
+
+        $this->customerRepository
+            ->expects($this->once())
+            ->method('save');
+
+        $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false);
+        $messageCollection
+            ->expects($this->once())
+            ->method('getCount')
+            ->willReturn(0);
+        $this->messageManager
+            ->expects($this->once())
+            ->method('getMessages')
+            ->willReturn($messageCollection);
+
+        $this->messageManager
+            ->expects($this->once())
+            ->method('addSuccess')
+            ->with('The account information has been saved.');
+
+        $this->redirectResultMock
+            ->expects($this->once())
+            ->method('setPath')
+            ->with('customer/account')
+            ->willReturn('http://test.com/customer/account/edit');
+
+        $this->assertSame($this->redirectResultMock, $this->getController()->execute());
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php
index 6f670e3e8ed8fdec1369ba50a78ef712cdec7713..7837c811df305141807f92c816cc06155298ee00 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php
@@ -96,6 +96,9 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase
      */
     protected $_formKeyValidator;
 
+    /**
+     * @return void
+     */
     protected function setUp()
     {
         $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http')
@@ -170,6 +173,7 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase
 
     /**
      * covers \Magento\Customer\Controller\Account::getAllowedActions
+     * @return void
      */
     public function testGetAllowedActions()
     {
@@ -182,31 +186,4 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase
         $method->setAccessible(true);
         $this->assertEquals($this->openActions, $method->invoke($this->object));
     }
-
-    public function testLoginPostActionWhenRefererSetBeforeAuthUrl()
-    {
-        $this->_formKeyValidator->expects($this->once())->method('validate')->will($this->returnValue(true));
-        $this->customerSession->expects($this->at(0))->method('isLoggedIn')->with()->will($this->returnValue(0));
-        $this->customerSession->expects($this->at(4))->method('isLoggedIn')->with()->will($this->returnValue(1));
-        $this->request->expects(
-            $this->once()
-        )->method(
-            'getParam'
-        )->with(
-            Url::REFERER_QUERY_PARAM_NAME
-        )->will(
-            $this->returnValue('referer')
-        );
-        $this->url->expects($this->once())->method('isOwnOriginUrl')->with();
-
-        $this->redirectFactoryMock->expects($this->once())
-            ->method('create')
-            ->willReturn($this->redirectResultMock);
-
-        $this->redirectResultMock->expects($this->once())
-            ->method('setUrl')
-            ->willReturnSelf();
-
-        $this->object->execute();
-    }
 }
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..367865649d761cc77fddfdf9675218af3e943e81
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php
@@ -0,0 +1,265 @@
+<?php
+/**
+ * Unit test for Magento\Customer\Test\Unit\Model\Account\Redirect
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+// @codingStandardsIgnoreFile
+
+namespace Magento\Customer\Test\Unit\Model\Account;
+
+use Magento\Customer\Model\Account\Redirect;
+use Magento\Customer\Model\Url as CustomerUrl;
+use Magento\Store\Model\ScopeInterface;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class RedirectTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Redirect
+     */
+    protected $model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\RequestInterface
+     */
+    protected $request;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Session
+     */
+    protected $customerSession;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\Config\ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\Store
+     */
+    protected $store;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\UrlInterface
+     */
+    protected $url;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Url\DecoderInterface
+     */
+    protected $urlDecoder;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Url
+     */
+    protected $customerUrl;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\Redirect
+     */
+    protected $resultRedirect;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\RedirectFactory
+     */
+    protected $resultRedirectFactory;
+
+    public function setUp()
+    {
+        $this->request = $this->getMockForAbstractClass('Magento\Framework\App\RequestInterface');
+
+        $this->customerSession = $this->getMockBuilder('Magento\Customer\Model\Session')
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'getLastCustomerId',
+                'isLoggedIn',
+                'getId',
+                'setLastCustomerId',
+                'unsBeforeAuthUrl',
+                'getBeforeAuthUrl',
+                'setBeforeAuthUrl',
+                'getAfterAuthUrl',
+                'setAfterAuthUrl',
+            ])
+            ->getMock();
+
+        $this->scopeConfig = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface');
+
+        $this->store = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->storeManager = $this->getMockForAbstractClass('Magento\Store\Model\StoreManagerInterface');
+        $this->storeManager->expects($this->once())
+            ->method('getStore')
+            ->willReturn($this->store);
+
+        $this->url = $this->getMockForAbstractClass('Magento\Framework\UrlInterface');
+        $this->urlDecoder = $this->getMockForAbstractClass('Magento\Framework\Url\DecoderInterface');
+
+        $this->customerUrl = $this->getMockBuilder('Magento\Customer\Model\Url')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->resultRedirectFactory = $this->getMockBuilder('Magento\Framework\Controller\Result\RedirectFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->resultRedirectFactory->expects($this->once())
+            ->method('create')
+            ->willReturn($this->resultRedirect);
+
+        $objectManager = new ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            'Magento\Customer\Model\Account\Redirect',
+            [
+                'request'               => $this->request,
+                'customerSession'       => $this->customerSession,
+                'scopeConfig'           => $this->scopeConfig,
+                'storeManager'          => $this->storeManager,
+                'url'                   => $this->url,
+                'urlDecoder'            => $this->urlDecoder,
+                'customerUrl'           => $this->customerUrl,
+                'resultRedirectFactory' => $this->resultRedirectFactory
+            ]
+        );
+    }
+
+    /**
+     * @dataProvider getRedirectDataProvider
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function testGetRedirect(
+        $customerId,
+        $lastCustomerId,
+        $referer,
+        $baseUrl,
+        $beforeAuthUrl,
+        $afterAuthUrl,
+        $accountUrl,
+        $loginUrl,
+        $logoutUrl,
+        $dashboardUrl,
+        $customerLoggedIn,
+        $redirectToDashboard
+    ) {
+        // Preparations for method updateLastCustomerId()
+        $this->customerSession->expects($this->once())
+            ->method('getLastCustomerId')
+            ->willReturn($customerId);
+        $this->customerSession->expects($this->any())
+            ->method('isLoggedIn')
+            ->willReturn($customerLoggedIn);
+        $this->customerSession->expects($this->any())
+            ->method('getId')
+            ->willReturn($lastCustomerId);
+        $this->customerSession->expects($this->any())
+            ->method('unsBeforeAuthUrl')
+            ->willReturnSelf();
+        $this->customerSession->expects($this->any())
+            ->method('setLastCustomerId')
+            ->with($lastCustomerId)
+            ->willReturnSelf();
+
+        // Preparations for method prepareRedirectUrl()
+        $this->store->expects($this->once())
+            ->method('getBaseUrl')
+            ->willReturn($baseUrl);
+
+        $this->customerSession->expects($this->any())
+            ->method('getBeforeAuthUrl')
+            ->willReturn($beforeAuthUrl);
+        $this->customerSession->expects($this->any())
+            ->method('setBeforeAuthUrl')
+            ->willReturnSelf();
+        $this->customerSession->expects($this->any())
+            ->method('getAfterAuthUrl')
+            ->willReturn($afterAuthUrl);
+        $this->customerSession->expects($this->any())
+            ->method('setAfterAuthUrl')
+            ->with($beforeAuthUrl)
+            ->willReturnSelf();
+
+        $this->customerUrl->expects($this->any())
+            ->method('getAccountUrl')
+            ->willReturn($accountUrl);
+        $this->customerUrl->expects($this->any())
+            ->method('getLoginUrl')
+            ->willReturn($loginUrl);
+        $this->customerUrl->expects($this->any())
+            ->method('getLogoutUrl')
+            ->willReturn($logoutUrl);
+        $this->customerUrl->expects($this->any())
+            ->method('DashboardUrl')
+            ->willReturn($dashboardUrl);
+
+        $this->scopeConfig->expects($this->any())
+            ->method('isSetFlag')
+            ->with(CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD, ScopeInterface::SCOPE_STORE)
+            ->willReturn($redirectToDashboard);
+
+        $this->request->expects($this->any())
+            ->method('getParam')
+            ->with(CustomerUrl::REFERER_QUERY_PARAM_NAME)
+            ->willReturn($referer);
+
+        $this->urlDecoder->expects($this->any())
+            ->method('decode')
+            ->with($referer)
+            ->willReturn($referer);
+
+        $this->url->expects($this->any())
+            ->method('isOwnOriginUrl')
+            ->willReturn(true);
+
+        $this->resultRedirect->expects($this->once())
+            ->method('setUrl')
+            ->willReturnSelf();
+
+        $this->model->getRedirect();
+    }
+
+    /**
+     * @return array
+     */
+    public function getRedirectDataProvider()
+    {
+        /**
+         * Customer ID
+         * Last customer ID
+         * Referer
+         * Base URL
+         * BeforeAuth URL
+         * AfterAuth URL
+         * Account URL
+         * Login URL
+         * Logout URL
+         * Dashboard URL
+         * Is customer logged in flag
+         * Redirect to Dashboard flag
+         */
+        return [
+            // Loggend In, Redirect by Referer
+            [1, 2, 'referer', 'base', '', '', 'account', '', '', '', true, false],
+            // Loggend In, Redirect by AfterAuthUrl
+            [1, 2, 'referer', 'base', '', 'defined', 'account', '', '', '', true, true],
+            // Not logged In, Redirect by LoginUrl
+            [1, 2, 'referer', 'base', '', '', 'account', 'login', '', '', false, true],
+            // Logout, Redirect to Dashboard
+            [1, 2, 'referer', 'base', 'logout', '', 'account', 'login', 'logout', 'dashboard', false, true],
+            // Default redirect
+            [1, 2, 'referer', 'base', 'defined', '', 'account', 'login', 'logout', 'dashboard', true, true],
+        ];
+    }
+}
diff --git a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
index 2de8eaf41e183af60a117dd093ccc338adaba2a5..98537419a90f346fdf884520c90e00ace48ed54c 100644
--- a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
+++ b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
@@ -398,16 +398,21 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr
      * @param mixed $from
      * @param mixed $to
      * @return array
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     protected function _getTZOffsetTransitions($timezone, $from = null, $to = null)
     {
         $tzTransitions = [];
         try {
             if (!empty($from)) {
-                $from = (new \DateTime($from))->getTimestamp();
+                $from = $from instanceof \DateTime
+                    ? $from->getTimestamp()
+                    : (new \DateTime($from))->getTimestamp();
             }
 
-            $to = new \DateTime($to);
+            $to = $to instanceof \DateTime
+                ? $to
+                : new \DateTime($to);
             $nextPeriod = $this->_getWriteAdapter()->formatDate(
                 $to->format('Y-m-d H:i:s')
             );
diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php
index d160ec1223f6156cbc64109a68eb0e2a3a188c00..7141a1bed3a26f0aaac1b4889f8fd0517df050d0 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/Create.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php
@@ -1427,7 +1427,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode
             $saveInAddressBook = (int)(!empty($address['save_in_address_book']));
             $billingAddress->setData('save_in_address_book', $saveInAddressBook);
 
-            if ($this->getShippingAddress()->getSameAsBilling()) {
+            if (!$this->getQuote()->isVirtual() && $this->getShippingAddress()->getSameAsBilling()) {
                 $shippingAddress = clone $billingAddress;
                 $shippingAddress->setSameAsBilling(true);
                 $shippingAddress->setSaveInAddressBook(false);
diff --git a/app/code/Magento/Shipping/Model/Observer.php b/app/code/Magento/Shipping/Model/Observer.php
index c218e1d1d3f210b2d8b857ec732c7c254b71aa06..e29359060abb9170593593d4b2b50606c98ffdde 100644
--- a/app/code/Magento/Shipping/Model/Observer.php
+++ b/app/code/Magento/Shipping/Model/Observer.php
@@ -37,8 +37,8 @@ class Observer
     public function aggregateSalesReportShipmentData()
     {
         $this->_localeResolver->emulate(0);
-        $currentDate = $this->_coreLocale->date();
-        $date = $currentDate->subHour(25);
+        $currentDate = new \DateTime();
+        $date = $currentDate->modify('-25 hours');
         $this->_shippingFactory->create()->aggregate($date);
         $this->_localeResolver->revert();
         return $this;
diff --git a/app/code/Magento/Ui/view/base/web/js/form.js b/app/code/Magento/Ui/view/base/web/js/form.js
index 2fec472c353c64f7fdec3ecfbcbbfd470ee7b7d2..ef54b43da90399b6894c697e2f49cb46795af55a 100644
--- a/app/code/Magento/Ui/view/base/web/js/form.js
+++ b/app/code/Magento/Ui/view/base/web/js/form.js
@@ -3,20 +3,19 @@
  * See COPYING.txt for license details.
  */
 define([
+    'jquery',
     'underscore',
     'Magento_Ui/js/form/component',
     'Magento_Ui/js/lib/spinner',
     './form/adapter'
-], function (_, Component, loader, adapter) {
+], function ($, _, Component, loader, adapter) {
     'use strict';
 
-    function collectData(selector){
-        var items = document.querySelectorAll(selector),
+    function collectData(selector) {
+        var data = $(selector).serializeArray(),
             result = {};
 
-        items = Array.prototype.slice.call(items);
-
-        items.forEach(function(item){
+        data.forEach(function (item) {
             result[item.name] = item.value;
         });
 
diff --git a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js
index ffbdfe4c5fbe3774f1d46d1bce60f63adc317085..733448e77319ba27a2481791aac0217e6846456f 100644
--- a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js
+++ b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js
@@ -11,7 +11,7 @@ define([
     
     $.widget('mage.addToWishlist', {
         options: {
-            bundleInfo: '[id^=bundle-option-]:checked',
+            bundleInfo: 'div.control [name^=bundle_option]:not([name*=qty])',
             configurableInfo: '.super-attribute-select',
             groupedInfo: '#super-product-table input',
             downloadableInfo: '#downloadable-links-list input',
@@ -32,18 +32,55 @@ define([
             this._on(events);
         },
         _updateWishlistData: function(event) {
-            var dataToAdd = {};
+            var dataToAdd = {},
+                dataOrigin = {};
+            var self = this;
             $(event.handleObj.selector).each(function(index, element){
-                dataToAdd[$(element).attr('name')] = $(element).val();
+                dataOrigin = $.extend({}, dataOrigin, self._getElementData(element, 1));
+                if ($(element).is(':checked') || $(element).find(':checked').length) {
+                    dataToAdd = $.extend({}, dataToAdd, self._getElementData(element));
+                }
             });
-            var self = this;
             $('[data-action="add-to-wishlist"]').each(function(index, element) {
                 var params = $(element).data('post');
                 if (!params)
                     params = {};
+                self._removeExcessiveData(params, dataOrigin, dataToAdd);
                 params.data = $.extend({}, params.data, dataToAdd, {'qty': $(self.options.qtyInfo).val()});
                 $(element).data('post', params);
             });
+            event.stopPropagation();
+        },
+        _arrayDiffByKeys: function(array1, array2) {
+            var result = {};
+            $.each(array1, function(key, value) {
+                if (!array2[key])
+                    result[key] = value;
+            });
+            return result;
+        },
+        _getElementData: function(element, origin) {
+            var data = {},
+                elementName = $(element).attr('name'),
+                elementValue = $(element).val();
+            if (origin && $(element).is('select')) {
+                elementValue = $(element).find('option');
+            }
+            if ($(element).is('select[multiple]')) {
+                $.each(elementValue, function(key, option) {
+                    var value = origin ? option.value : option;
+                    data[elementName + '[' + value + ']'] = value;
+                });
+            } else {
+                data[elementName] = elementValue;
+            }
+            return data;
+        },
+        _removeExcessiveData: function(params, dataOrigin, dataToAdd) {
+            var dataToRemove = this._arrayDiffByKeys(dataOrigin, dataToAdd);
+            $.each(dataToRemove, function(key, value) {
+                delete params.data[key];
+            });
         }
     });
     
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
index 7f2caa27ef07634ab7d1e064a10daf54f17db648..f9e5c43acb695f35c3eca409b1d0c12b6b0bcf0d 100644
--- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml
@@ -39,14 +39,12 @@
     </variation>
     <variation name="AddProductToWishlistEntityTestVariation6" firstConstraint="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" method="test">
       <data name="product" xsi:type="string">bundleProduct::bundle_dynamic_product</data>
-      <data name="issue" xsi:type="string">Bug: MAGETWO-33952</data>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" next="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist" next="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage"/>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/>
     </variation>
     <variation name="AddProductToWishlistEntityTestVariation7" firstConstraint="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" method="test">
       <data name="product" xsi:type="string">bundleProduct::bundle_fixed_product</data>
-      <data name="issue" xsi:type="string">Bug: MAGETWO-33952</data>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" next="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist" next="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage"/>
       <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/>
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
index a267e9b299762a901b22dc3fc89715a6c0a6e637..63af5eeb61344361524d256fe3cf6f3fa627fc52 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
@@ -152,7 +152,7 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
             ->setPostValue('create_address', true);
 
         $this->dispatch('customer/account/createPost');
-        $this->assertRedirect($this->stringContains('customer/account/index/'));
+        $this->assertRedirect($this->stringContains('customer/account/'));
         $this->assertSessionMessages(
             $this->equalTo(['Thank you for registering with Main Website Store.']),
             MessageInterface::TYPE_SUCCESS
diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php b/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php
index 42abd3ab3f48ba49d5308f655fbb91b6b03d686a..e2fb6987724b6f2de342839679c2fafe2c728a8e 100644
--- a/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php
+++ b/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php
@@ -496,6 +496,8 @@ class Helper
             //       This block of the if should be removed leaving only the phtml condition when dev/tests is swept.
             // Skip all dev tests files
             $shouldFilter = true;
+        } elseif (preg_match('#(?:/|\\\\)Test(?:/|\\\\)Unit(?:/|\\\\)#', $filename)) {
+            $shouldFilter = true;
         } elseif (preg_match('/\\.phtml$/', $filename)) {
             // Skip all phtml files
             $shouldFilter = true;
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index e47cc2c1d2d314c6050365aeea5d2b1707bb36d0..e87c6a8441447b1c605e33196aae16c8a1d26b29 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -1905,7 +1905,7 @@ return [
     ['_isVatValidationEnabled', 'Magento\Customer\Controller\Account'],
     ['_createUrl', 'Magento\Customer\Controller\Account'],
     ['_extractAddress', 'Magento\Customer\Controller\Account\CreatePost', 'Magento\Customer\Controller\Account\CreatePost::extractAddress'],
-    ['_loginPostRedirect', 'Magento\Customer\Controller\Account\LoginPost', 'Magento\Customer\Controller\Account\LoginPost::loginPostRedirect'],
+    ['_loginPostRedirect', 'Magento\Customer\Controller\Account\LoginPost', 'Magento\Customer\Model\Account\Redirect::getRedirect'],
     ['_getAllowedActions', 'Magento\Customer\Controller\Account', 'Magento\Customer\Controller\Account::getAllowedActions'],
     ['isRegistrationAllowed', 'Magento\Customer\Controller\Account\CreatePost'],
     ['isRegistrationAllowed', 'Magento\Invitation\Controller\Customer\Account\CreatePost'],
@@ -2105,6 +2105,12 @@ return [
         'Magento\Integration\Helper\Validator',
         'Magento\Integration\Model\CredentialsValidator::validate'
     ],
+    ['getSuccessRedirect', 'Magento\Customer\Controller\Account\CreatePost'],
+    [
+        'loginPostRedirect',
+        'Magento\Customer\Controller\Account\LoginPost',
+        'Magento\Customer\Model\Account\Redirect::getRedirect'
+    ],
     ['isReviewOwner', 'Magento\Review\Block\Customer\View'],
     ['getRegistration', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getRegistration'],
     ['getCreateAccountUrl', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getCreateAccountUrl'],
diff --git a/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php b/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..1cfc89004602d9283017ba9e28c954b2950de7a0
--- /dev/null
+++ b/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Controller\Result;
+
+use Magento\Framework\ObjectManagerInterface;
+
+class RedirectFactory
+{
+    /**
+     * Object Manager instance
+     *
+     * @var ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * Instance name to create
+     *
+     * @var string
+     */
+    protected $instanceName;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param string $instanceName
+     */
+    public function __construct(
+        ObjectManagerInterface $objectManager,
+        $instanceName = 'Magento\Framework\Controller\Result\Redirect'
+    ) {
+        $this->objectManager = $objectManager;
+        $this->instanceName = $instanceName;
+    }
+
+    /**
+     * Create class instance with specified parameters
+     *
+     * @param array $data
+     * @return \Magento\Framework\Controller\Result\Redirect
+     */
+    public function create(array $data = [])
+    {
+        return $this->objectManager->create($this->instanceName, $data);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php b/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0fb551e749ac560fefe3ae3c3b4a6c71701d59ed
--- /dev/null
+++ b/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Unit test for Magento\Framework\ValidatorFactory
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+// @codingStandardsIgnoreFile
+
+namespace Magento\Framework\Controller\Test\Unit\Result;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class RedirectFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var  \Magento\Framework\ValidatorFactory */
+    private $model;
+
+    /** @var \Magento\Framework\ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject */
+    private $objectManagerMock;
+
+    public function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface');
+        $this->model = $objectManager->getObject('Magento\Framework\Controller\Result\RedirectFactory',
+            ['objectManager' => $this->objectManagerMock]
+        );
+    }
+
+    public function testCreate()
+    {
+        $redirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerMock->expects($this->once())->method('create')
+            ->willReturn($redirect);
+
+        $resultRedirect = $this->model->create();
+        $this->assertInstanceOf('Magento\Framework\Controller\Result\Redirect', $resultRedirect);
+        $this->assertSame($redirect, $resultRedirect);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php
index d50cf4fc4f534d79133eb308dc8c579ef07fb7bd..e053ca69564b780066f0d08a358a1d911f253cf8 100644
--- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php
+++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php
@@ -741,4 +741,30 @@ class File implements DriverInterface
     {
         return realpath($path);
     }
+
+    /**
+     * Return correct path for link
+     *
+     * @param string $path
+     * @return mixed
+     */
+    public function getRealPathSafety($path)
+    {
+        if (strpos($path, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) === false) {
+            return $path;
+        }
+        $pathParts = explode(DIRECTORY_SEPARATOR, $path);
+        $realPath = [];
+        foreach ($pathParts as $pathPart) {
+            if ($pathPart == '.') {
+                continue;
+            }
+            if ($pathPart == '..') {
+                array_pop($realPath);
+                continue;
+            }
+            $realPath[] = $pathPart;
+        }
+        return implode(DIRECTORY_SEPARATOR, $realPath);
+    }
 }
diff --git a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php
index aff29eefba7ce7e5f4892f353d7d2890d5f8a86d..c02447ee8c48f1ff0a0c8a065a023a28b535c79f 100644
--- a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php
+++ b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php
@@ -349,6 +349,14 @@ interface DriverInterface
      */
     public function getRealPath($path);
 
+    /**
+     * Return correct path for link
+     *
+     * @param string $path
+     * @return mixed
+     */
+    public function getRealPathSafety($path);
+
     /**
      * @param string $basePath
      * @param null $path
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
index 2bd6553b4fb725a8b848497acf89c92e646f6c50..ab75ed3fd336a7bbf4a5c9bbe8232828c24fd67d 100644
--- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
@@ -233,7 +233,7 @@ class Timezone implements TimezoneInterface
      * @param null $locale
      * @param null $timezone
      * @param string|null $pattern
-     * @return mixed
+     * @return string
      */
     public function formatDateTime(
         \DateTimeInterface $date,
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php
index 48bbbc73796dba44f8d925ac6e56a61641363d80..75c865b542a0ab78a4d77870f7de12308b2bdec8 100644
--- a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php
@@ -122,7 +122,7 @@ interface TimezoneInterface
      * @param null $locale
      * @param null $timezone
      * @param string|null $pattern
-     * @return mixed
+     * @return string
      */
     public function formatDateTime(
         \DateTimeInterface $date,
diff --git a/lib/internal/Magento/Framework/View/Asset/Config.php b/lib/internal/Magento/Framework/View/Asset/Config.php
index c18ffaeebabc07f72010e892213be61aac656ab7..1fa3bbde781383f5873c742fe0c358368fa61f46 100644
--- a/lib/internal/Magento/Framework/View/Asset/Config.php
+++ b/lib/internal/Magento/Framework/View/Asset/Config.php
@@ -4,11 +4,10 @@
  * See COPYING.txt for license details.
  */
 
-// @codingStandardsIgnoreFile
-
 namespace Magento\Framework\View\Asset;
 
 use Magento\Store\Model\ScopeInterface;
+use Magento\Framework\App\Config\ScopeConfigInterface;
 
 /**
  * View asset configuration interface
@@ -41,14 +40,19 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface
     const XML_PATH_JS_BUNDLING = 'dev/js/enable_js_bundling';
 
     /**
-     * @var \Magento\Framework\App\Config\ScopeConfigInterface
+     * XML path for HTML minification configuration
+     */
+    const XML_PATH_MINIFICATION_HTML = 'dev/template/minify_html';
+
+    /**
+     * @var ScopeConfigInterface
      */
     protected $scopeConfig;
 
     /**
-     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+     * @param ScopeConfigInterface $scopeConfig
      */
-    public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
+    public function __construct(ScopeConfigInterface $scopeConfig)
     {
         $this->scopeConfig = $scopeConfig;
     }
@@ -60,7 +64,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface
      */
     public function isMergeCssFiles()
     {
-        return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_MERGE_CSS_FILES, ScopeInterface::SCOPE_STORE);
+        return (bool)$this->scopeConfig->isSetFlag(
+            self::XML_PATH_MERGE_CSS_FILES,
+            ScopeInterface::SCOPE_STORE
+        );
     }
 
     /**
@@ -70,7 +77,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface
      */
     public function isBundlingJsFiles()
     {
-        return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_JS_BUNDLING, ScopeInterface::SCOPE_STORE);
+        return (bool)$this->scopeConfig->isSetFlag(
+            self::XML_PATH_JS_BUNDLING,
+            ScopeInterface::SCOPE_STORE
+        );
     }
 
     /**
@@ -80,7 +90,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface
      */
     public function isMergeJsFiles()
     {
-        return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_MERGE_JS_FILES, ScopeInterface::SCOPE_STORE);
+        return (bool)$this->scopeConfig->isSetFlag(
+            self::XML_PATH_MERGE_JS_FILES,
+            ScopeInterface::SCOPE_STORE
+        );
     }
 
     /**
@@ -110,4 +123,17 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface
             ScopeInterface::SCOPE_STORE
         );
     }
+
+    /**
+     * Check whether minify of HTML is on
+     *
+     * @return bool
+     */
+    public function isMinifyHtml()
+    {
+        return (bool)$this->scopeConfig->isSetFlag(
+            self::XML_PATH_MINIFICATION_HTML,
+            ScopeInterface::SCOPE_STORE
+        );
+    }
 }
diff --git a/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php b/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php
index b68e6f5fe54ae2bb36919c1e1c6912da5019243f..f099082ce4442631f9690cca216309906362fe81 100644
--- a/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php
+++ b/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php
@@ -46,4 +46,11 @@ interface ConfigInterface
      * @return string
      */
     public function getAssetMinificationAdapter($contentType);
+
+    /**
+     * Check whether minify of HTML is on
+     *
+     * @return bool
+     */
+    public function isMinifyHtml();
 }
diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php
index 656a021c8039db4e1238fa776ccde87c4a38d898..bbf4bcd58450fe37b4f36b6158e4625463cef3d4 100644
--- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php
+++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php
@@ -7,6 +7,7 @@
 namespace Magento\Framework\View\Design\FileResolution\Fallback;
 
 use Magento\Framework\App\State;
+use Magento\Framework\View\Asset\ConfigInterface;
 use Magento\Framework\View\Design\ThemeInterface;
 use Magento\Framework\View\Template\Html\MinifierInterface;
 
@@ -25,18 +26,26 @@ class TemplateFile extends File
      */
     protected $templateMinifier;
 
+    /**
+     * @var ConfigInterface
+     */
+    protected $assetConfig;
+
     /**
      * @param ResolverInterface $resolver
      * @param MinifierInterface $templateMinifier
      * @param State $appState
+     * @param ConfigInterface $assetConfig
      */
     public function __construct(
         ResolverInterface $resolver,
         MinifierInterface $templateMinifier,
-        State $appState
+        State $appState,
+        ConfigInterface $assetConfig
     ) {
         $this->appState = $appState;
         $this->templateMinifier = $templateMinifier;
+        $this->assetConfig = $assetConfig;
         parent::__construct($resolver);
     }
 
@@ -60,16 +69,18 @@ class TemplateFile extends File
     public function getFile($area, ThemeInterface $themeModel, $file, $module = null)
     {
         $template = parent::getFile($area, $themeModel, $file, $module);
-        switch ($this->appState->getMode()) {
-            case State::MODE_PRODUCTION:
-                return $this->templateMinifier->getPathToMinified($template);
-                break;
-            case State::MODE_DEFAULT:
-                return $this->templateMinifier->getMinified($template);
-                break;
-            case State::MODE_DEVELOPER:
-                return $template;
-                break;
+
+        if ($template && $this->assetConfig->isMinifyHtml()) {
+            switch ($this->appState->getMode()) {
+                case State::MODE_PRODUCTION:
+                    return $this->templateMinifier->getPathToMinified($template);
+                case State::MODE_DEFAULT:
+                    return $this->templateMinifier->getMinified($template);
+                case State::MODE_DEVELOPER:
+                default:
+                    return $template;
+            }
         }
+        return $template;
     }
 }
diff --git a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php
index 9af26b5705f77006a2e21bd33b0926c0d09478c5..9c3aba6b4ba08fc6d10bca11a1110256aea45fb9 100644
--- a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php
+++ b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php
@@ -52,15 +52,26 @@ class Minifier implements MinifierInterface
         'label',
         'select',
         'textarea',
+        '\?',
     ];
 
+    /**
+     * @var Filesystem\Directory\ReadInterface
+     */
+    protected $rootDirectory;
+
+    /**
+     * @var Filesystem\Directory\WriteInterface
+     */
+    protected $htmlDirectory;
+
     /**
      * @param Filesystem $filesystem
      */
     public function __construct(
         Filesystem $filesystem
     ) {
-        $this->appDirectory = $filesystem->getDirectoryRead(DirectoryList::APP);
+        $this->rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
         $this->htmlDirectory = $filesystem->getDirectoryWrite(DirectoryList::TEMPLATE_MINIFICATION_DIR);
     }
 
@@ -72,7 +83,8 @@ class Minifier implements MinifierInterface
      */
     public function getMinified($file)
     {
-        if (!$this->htmlDirectory->isExist($this->appDirectory->getRelativePath($file))) {
+        $file = $this->htmlDirectory->getDriver()->getRealPathSafety($file);
+        if (!$this->htmlDirectory->isExist($this->rootDirectory->getRelativePath($file))) {
             $this->minify($file);
         }
         return $this->getPathToMinified($file);
@@ -87,7 +99,7 @@ class Minifier implements MinifierInterface
     public function getPathToMinified($file)
     {
         return $this->htmlDirectory->getAbsolutePath(
-            $this->appDirectory->getRelativePath($file)
+            $this->rootDirectory->getRelativePath($file)
         );
     }
 
@@ -95,24 +107,33 @@ class Minifier implements MinifierInterface
      * Minify template file
      *
      * @param string $file
+     * @return void
      */
     public function minify($file)
     {
-        $file = $this->appDirectory->getRelativePath($file);
+        $file = $this->rootDirectory->getRelativePath($file);
         $content = preg_replace(
-            '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#',
-            '><',
+            '#(?<!]]>)\s+</#',
+            '</',
             preg_replace(
-                '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:textarea|pre|script)\b))*+)'
-                . '(?:<(?>textarea|pre|script)\b|\z))#',
-                ' ',
+                '#((?:<\?php\s+(?!echo)[^\?]*)\?>)\s+#',
+                '$1',
                 preg_replace(
-                    '#(?<!:)//(?!\<\!\[)(?!]]\>)[^\n\r]*#',
-                    '',
+                    '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#',
+                    '><',
                     preg_replace(
-                        '#(?<!:)//[^\n\r]*(\s\?\>)#',
-                        '$1',
-                        $this->appDirectory->readFile($file)
+                        '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:textarea|pre|script)\b))*+)'
+                        . '(?:<(?>textarea|pre|script)\b|\z))#',
+                        ' ',
+                        preg_replace(
+                            '#(?<!:)//(?!\s*\<\!\[)(?!\s*]]\>)[^\n\r]*#',
+                            '',
+                            preg_replace(
+                                '#(?<!:)//[^\n\r]*(\s\?\>)#',
+                                '$1',
+                                $this->rootDirectory->readFile($file)
+                            )
+                        )
                     )
                 )
             )
@@ -121,6 +142,6 @@ class Minifier implements MinifierInterface
         if (!$this->htmlDirectory->isExist()) {
             $this->htmlDirectory->create();
         }
-        $this->htmlDirectory->writeFile($file, $content);
+        $this->htmlDirectory->writeFile($file, rtrim($content));
     }
 }
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php
index 644876622074ed95b4da80934857c9c78c15d54a..359ea18c0f08e8c12c94cefbdf212bd14c415b40 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php
@@ -6,10 +6,10 @@
 
 namespace Magento\Framework\View\Test\Unit\Design\FileResolution\Fallback;
 
-use \Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile;
-
 use Magento\Framework\App\State;
 use Magento\Framework\View\Design\Fallback\RulePool;
+use Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile;
+use Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface;
 
 class TemplateFileTest extends \PHPUnit_Framework_TestCase
 {
@@ -33,12 +33,23 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase
      */
     protected $object;
 
+    /**
+     * @var \Magento\Framework\View\Asset\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $assetConfig;
+
     protected function setUp()
     {
         $this->resolver = $this->getMock('Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface');
         $this->minifier = $this->getMock('Magento\Framework\View\Template\Html\MinifierInterface');
         $this->state = $this->getMockBuilder('Magento\Framework\App\State')->disableOriginalConstructor()->getMock();
-        $this->object = new TemplateFile($this->resolver, $this->minifier, $this->state);
+        $this->assetConfig = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Asset\ConfigInterface',
+            [],
+            '',
+            false
+        );
+        $this->object = new TemplateFile($this->resolver, $this->minifier, $this->state, $this->assetConfig);
     }
 
     /**
@@ -46,6 +57,11 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetFileWhenStateDeveloper()
     {
+        $this->assetConfig
+            ->expects($this->once())
+            ->method('isMinifyHtml')
+            ->willReturn(true);
+
         $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface');
         $expected = 'some/file.ext';
 
@@ -63,10 +79,17 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase
 
     /**
      * Cover getFile when mode is default
+     * @param string $mode
+     * @param string $method
      * @dataProvider getMinifiedDataProvider
      */
     public function testGetFileWhenModifiedNeeded($mode, $method)
     {
+        $this->assetConfig
+            ->expects($this->once())
+            ->method('isMinifyHtml')
+            ->willReturn(true);
+
         $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface');
         $expected = 'some/file.ext';
         $expectedMinified = '/path/to/minified/some/file.ext';
@@ -87,6 +110,27 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase
         $this->assertSame($expectedMinified, $actual);
     }
 
+    public function testGetFileIfMinificationIsDisabled()
+    {
+        $this->assetConfig
+            ->expects($this->once())
+            ->method('isMinifyHtml')
+            ->willReturn(false);
+
+        $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface');
+        $expected = 'some/file.ext';
+
+        $this->resolver->expects($this->once())
+            ->method('resolve')
+            ->with(RulePool::TYPE_TEMPLATE_FILE, 'file.ext', 'frontend', $theme, null, 'Magento_Module')
+            ->will($this->returnValue($expected));
+
+        $this->state->expects($this->never())->method('getMode');
+
+        $actual = $this->object->getFile('frontend', $theme, 'file.ext', 'Magento_Module');
+        $this->assertSame($expected, $actual);
+    }
+
     /**
      * Contain different methods by mode for HTML minification
      *
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php
index 20c3d33358cd872d4f0904394478e750283ca990..a93962b3ae7e689f4ef943e5273b9da9afd8cffc 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php
@@ -6,9 +6,8 @@
 
 namespace Magento\Framework\View\Test\Unit\Template\Html;
 
-use \Magento\Framework\View\Template\Html\Minifier;
-
 use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\View\Template\Html\Minifier;
 
 class MinifierTest extends \PHPUnit_Framework_TestCase
 {
@@ -39,7 +38,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase
 
         $filesystem->expects($this->once())
             ->method('getDirectoryRead')
-            ->with(DirectoryList::APP)
+            ->with(DirectoryList::ROOT)
             ->willReturn($this->appDirectory);
         $filesystem->expects($this->once())
             ->method('getDirectoryWrite')
@@ -72,6 +71,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($absolutePath, $this->object->getPathToMinified($file));
     }
 
+    // @codingStandardsIgnoreStart
     /**
      * Covered method minify and test regular expressions
      * @test
@@ -115,8 +115,9 @@ class MinifierTest extends \PHPUnit_Framework_TestCase
     </body>
 </html>
 TEXT;
+
         $expectedContent = <<<TEXT
-<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?><div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script>
+<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script>
             //<![CDATA[
             var someVar = 123;
             testFunctionCall(function () {
@@ -128,7 +129,7 @@ TEXT;
                 }
             });
             //]]>
-        </script><?php echo "http://some.link.com/" ?><em>inline text</em> </body></html>
+</script><?php echo "http://some.link.com/" ?> <em>inline text</em></body></html>
 TEXT;
 
         $this->appDirectory->expects($this->once())
@@ -151,6 +152,7 @@ TEXT;
 
         $this->object->minify($file);
     }
+    // @codingStandardsIgnoreEnd
 
     /**
      * Contain method modify and getPathToModified
@@ -161,15 +163,28 @@ TEXT;
         $file = '/absolute/path/to/phtml/template/file';
         $relativePath = 'relative/path/to/phtml/template/file';
 
-        $this->appDirectory->expects($this->at(0))
+        $htmlDriver = $this->getMock('Magento\Framework\Filesystem\DriverInterface', [], [], '', false);
+        $htmlDriver
+            ->expects($this->once())
+            ->method('getRealPathSafety')
+            ->willReturn($file);
+
+        $this->appDirectory
+            ->expects($this->exactly(3))
             ->method('getRelativePath')
             ->with($file)
             ->willReturn($relativePath);
-        $this->htmlDirectory->expects($this->at(0))
+        $this->htmlDirectory
+            ->expects($this->at(1))
             ->method('isExist')
             ->with($relativePath)
             ->willReturn(false);
 
+        $this->htmlDirectory
+            ->expects($this->once())
+            ->method('getDriver')
+            ->willReturn($htmlDriver);
+
         $this->object->getMinified($file);
     }
 }