diff --git a/app/code/Magento/Backend/Block/Template/Context.php b/app/code/Magento/Backend/Block/Template/Context.php
index 035a909cb3b38c09284c3a1a1fc61ed0c6085b75..c25dc3c944c44e280e759e62381b5ae21d5ca5af 100644
--- a/app/code/Magento/Backend/Block/Template/Context.php
+++ b/app/code/Magento/Backend/Block/Template/Context.php
@@ -67,6 +67,8 @@ class Context extends \Magento\Framework\View\Element\Template\Context
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Framework\View\Page\Config $pageConfig
+     * @param \Magento\Framework\View\Element\Template\File\Resolver $resolver
+     * @param \Magento\Framework\View\Element\Template\File\Validator $validator
      * @param \Magento\Framework\AuthorizationInterface $authorization
      * @param \Magento\Backend\Model\Session $backendSession
      * @param \Magento\Framework\Math\Random $mathRandom
@@ -99,6 +101,8 @@ class Context extends \Magento\Framework\View\Element\Template\Context
         \Magento\Framework\App\State $appState,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\View\Page\Config $pageConfig,
+        \Magento\Framework\View\Element\Template\File\Resolver $resolver,
+        \Magento\Framework\View\Element\Template\File\Validator $validator,
         \Magento\Framework\AuthorizationInterface $authorization,
         \Magento\Backend\Model\Session $backendSession,
         \Magento\Framework\Math\Random $mathRandom,
@@ -133,7 +137,9 @@ class Context extends \Magento\Framework\View\Element\Template\Context
             $enginePool,
             $appState,
             $storeManager,
-            $pageConfig
+            $pageConfig,
+            $resolver,
+            $validator
         );
     }
 
diff --git a/app/code/Magento/Backend/Block/Widget/Context.php b/app/code/Magento/Backend/Block/Widget/Context.php
index dacc0fe3379c57233c5bdaf4a2c456d4c5544853..83c3f1827877b4e1c8b179f68068e5362d7eefea 100644
--- a/app/code/Magento/Backend/Block/Widget/Context.php
+++ b/app/code/Magento/Backend/Block/Widget/Context.php
@@ -49,6 +49,9 @@ class Context extends \Magento\Backend\Block\Template\Context
      * @param \Magento\Framework\View\TemplateEnginePool $enginePool
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Framework\View\Page\Config $pageConfig
+     * @param \Magento\Framework\View\Element\Template\File\Resolver $resolver
+     * @param \Magento\Framework\View\Element\Template\File\Validator $validator
      * @param \Magento\Framework\AuthorizationInterface $authorization
      * @param \Magento\Backend\Model\Session $backendSession
      * @param \Magento\Framework\Math\Random $mathRandom
@@ -56,7 +59,6 @@ class Context extends \Magento\Backend\Block\Template\Context
      * @param \Magento\Framework\Code\NameBuilder $nameBuilder
      * @param \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
      * @param Button\ToolbarInterface $toolbar
-     * @param \Magento\Framework\View\Page\Config $pageConfig
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -84,6 +86,8 @@ class Context extends \Magento\Backend\Block\Template\Context
         \Magento\Framework\App\State $appState,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\View\Page\Config $pageConfig,
+        \Magento\Framework\View\Element\Template\File\Resolver $resolver,
+        \Magento\Framework\View\Element\Template\File\Validator $validator,
         \Magento\Framework\AuthorizationInterface $authorization,
         \Magento\Backend\Model\Session $backendSession,
         \Magento\Framework\Math\Random $mathRandom,
@@ -116,6 +120,8 @@ class Context extends \Magento\Backend\Block\Template\Context
             $appState,
             $storeManager,
             $pageConfig,
+            $resolver,
+            $validator,
             $authorization,
             $backendSession,
             $mathRandom,
diff --git a/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php b/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..73046749a66bfae1f68a81376c9d2963ba995ae9
--- /dev/null
+++ b/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Captcha\Model\Cart;
+
+class ConfigPlugin
+{
+    /**
+     * @var \Magento\Captcha\Model\Checkout\ConfigProvider
+     */
+    protected $configProvider;
+
+    /**
+     * @param \Magento\Captcha\Model\Checkout\ConfigProvider $configProvider
+     */
+    public function __construct(
+        \Magento\Captcha\Model\Checkout\ConfigProvider $configProvider
+    ) {
+        $this->configProvider = $configProvider;
+    }
+
+    /**
+     * @param \Magento\Checkout\Block\Cart\Sidebar $subject
+     * @param array $result
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function afterGetConfig(\Magento\Checkout\Block\Cart\Sidebar $subject, array $result)
+    {
+        return array_merge_recursive($result, $this->configProvider->getConfig());
+    }
+}
diff --git a/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php b/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php
deleted file mode 100644
index eac1d7a74421e4994531d7cc71858d5690609fed..0000000000000000000000000000000000000000
--- a/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Captcha\Model\Checkout\Plugin;
-
-use Magento\Framework\Exception\NoSuchEntityException;
-use Magento\Framework\Exception\InputException;
-
-class Validation
-{
-    /**
-     * @var \Magento\Captcha\Helper\Data
-     */
-    protected $captchaHelper;
-
-    /**
-     * @var array
-     */
-    protected $formIds;
-
-    /**
-     * @param \Magento\Captcha\Helper\Data $captchaHelper
-     * @param array $formIds
-     */
-    public function __construct(
-        \Magento\Captcha\Helper\Data $captchaHelper,
-        array $formIds
-    ) {
-        $this->captchaHelper = $captchaHelper;
-        $this->formIds = $formIds;
-    }
-
-    /**
-     * @param \Magento\Quote\Model\AddressAdditionalDataProcessor $subject
-     * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData
-     * @throws \Magento\Framework\Exception\NoSuchEntityException
-     * @throws \Magento\Framework\Exception\InputException
-     * @return void
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     */
-    public function beforeProcess(
-        \Magento\Quote\Model\AddressAdditionalDataProcessor $subject,
-        \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData
-    ) {
-        $formId = $additionalData->getExtensionAttributes()->getCaptchaFormId();
-        $captchaText = $additionalData->getExtensionAttributes()->getCaptchaString();
-
-        if ($formId !== null && !in_array($formId, $this->formIds)) {
-            throw new NoSuchEntityException(__('Provided form does not exist'));
-        }
-        $captchaModel = $this->captchaHelper->getCaptcha($formId);
-        if ($captchaModel->isRequired()) {
-            if (!$captchaModel->isCorrect($captchaText)) {
-                throw new InputException(__('Incorrect CAPTCHA'));
-            }
-        }
-    }
-}
diff --git a/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php b/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php
index 39edd79861db2de45bc2f3c508c17afb9f3b3cd6..65cb2d8612abd20e6c3cf8a380de5a00f69cdd0c 100644
--- a/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php
+++ b/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php
@@ -26,53 +26,67 @@ class AjaxLogin
      */
     protected $resultJsonFactory;
 
+    /**
+     * @var array
+     */
+    protected $formIds;
+
     /**
      * @param CaptchaHelper $helper
      * @param SessionManagerInterface $sessionManager
      * @param JsonFactory $resultJsonFactory
+     * @param array $formIds
      */
     public function __construct(
         CaptchaHelper $helper,
         SessionManagerInterface $sessionManager,
-        JsonFactory $resultJsonFactory
+        JsonFactory $resultJsonFactory,
+        array $formIds
     ) {
         $this->helper = $helper;
         $this->sessionManager = $sessionManager;
         $this->resultJsonFactory = $resultJsonFactory;
+        $this->formIds = $formIds;
     }
 
     /**
      * @param \Magento\Customer\Controller\Ajax\Login $subject
      * @param callable $proceed
-     * @return \Magento\Framework\Controller\ResultInterface
+     * @return $this
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
      * @throws \Zend_Json_Exception
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function aroundExecute(
         \Magento\Customer\Controller\Ajax\Login $subject,
         \Closure $proceed
     ) {
-        $loginFormId = 'user_login';
+        $captchaFormIdField = 'captcha_form_id';
         $captchaInputName = 'captcha_string';
 
         /** @var \Magento\Framework\App\RequestInterface $request */
         $request = $subject->getRequest();
 
-        /** @var \Magento\Captcha\Model\ModelInterface $captchaModel */
-        $captchaModel = $this->helper->getCaptcha($loginFormId);
-
         $loginParams = \Zend_Json::decode($request->getContent());
         $username = isset($loginParams['username']) ? $loginParams['username'] : null;
-        $captchaString = isset($loginParams[$captchaInputName])
-            ? $loginParams[$captchaInputName]
-            : null;
+        $captchaString = isset($loginParams[$captchaInputName]) ? $loginParams[$captchaInputName] : null;
+        $loginFormId = isset($loginParams[$captchaFormIdField]) ? $loginParams[$captchaFormIdField] : null;
 
-        if ($captchaModel->isRequired($username)) {
-            $captchaModel->logAttempt($username);
-            if (!$captchaModel->isCorrect($captchaString)) {
-                $this->sessionManager->setUsername($username);
-                /** @var \Magento\Framework\Controller\Result\Json $resultJson */
+        foreach ($this->formIds as $formId) {
+            $captchaModel = $this->helper->getCaptcha($formId);
+            if ($captchaModel->isRequired($username) && !in_array($loginFormId, $this->formIds)) {
                 $resultJson = $this->resultJsonFactory->create();
-                return $resultJson->setData(['errors' => true, 'message' => __('Incorrect CAPTCHA')]);
+                return $resultJson->setData(['errors' => true, 'message' => __('Provided form does not exist')]);
+            }
+
+            if ($formId == $loginFormId) {
+                $captchaModel->logAttempt($username);
+                if (!$captchaModel->isCorrect($captchaString)) {
+                    $this->sessionManager->setUsername($username);
+                    /** @var \Magento\Framework\Controller\Result\Json $resultJson */
+                    $resultJson = $this->resultJsonFactory->create();
+                    return $resultJson->setData(['errors' => true, 'message' => __('Incorrect CAPTCHA')]);
+                }
             }
         }
         return $proceed();
diff --git a/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php b/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd47b19ea9038c553c8183b13066421b94236cfa
--- /dev/null
+++ b/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Captcha\Test\Unit\Controller\Refresh;
+
+class IndexTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $responseMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $viewMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $layoutMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $flagMock;
+
+    /**
+     * @var \Magento\Captcha\Controller\Refresh\Index
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false);
+        $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false);
+        $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+        $this->responseMock = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false);
+        $this->contextMock = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false);
+        $this->viewMock = $this->getMock('Magento\Framework\App\ViewInterface');
+        $this->layoutMock = $this->getMock('Magento\Framework\View\LayoutInterface');
+        $this->flagMock = $this->getMock('Magento\Framework\App\ActionFlag', [], [], '', false);
+
+        $this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->requestMock));
+        $this->contextMock->expects($this->any())->method('getView')->will($this->returnValue($this->viewMock));
+        $this->contextMock->expects($this->any())->method('getResponse')->will($this->returnValue($this->responseMock));
+        $this->contextMock->expects($this->any())->method('getActionFlag')->will($this->returnValue($this->flagMock));
+        $this->viewMock->expects($this->any())->method('getLayout')->will($this->returnValue($this->layoutMock));
+
+        $this->model = new \Magento\Captcha\Controller\Refresh\Index($this->contextMock, $this->captchaHelperMock);
+    }
+
+    /**
+     * @dataProvider executeDataProvider
+     * @param int $formId
+     * @param int $callsNumber
+     */
+    public function testExecute($formId, $callsNumber)
+    {
+        $content = ['formId' => $formId];
+
+        $blockMethods = ['setFormId', 'setIsAjax', 'toHtml'];
+        $blockMock = $this->getMock('Magento\Captcha\Block\Captcha', $blockMethods, [], '', false);
+
+        $this->requestMock->expects($this->any())->method('getPost')->with('formId')->will($this->returnValue($formId));
+        $this->requestMock->expects($this->exactly($callsNumber))->method('getContent')
+            ->will($this->returnValue(json_encode($content)));
+        $this->captchaHelperMock->expects($this->any())->method('getCaptcha')->with($formId)
+            ->will($this->returnValue($this->captchaMock));
+        $this->captchaMock->expects($this->once())->method('generate');
+        $this->captchaMock->expects($this->once())->method('getBlockName')->will($this->returnValue('block'));
+        $this->captchaMock->expects($this->once())->method('getImgSrc')->will($this->returnValue('source'));
+        $this->layoutMock->expects($this->once())->method('createBlock')->with('block')
+            ->will($this->returnValue($blockMock));
+        $blockMock->expects($this->any())->method('setFormId')->with($formId)->will($this->returnValue($blockMock));
+        $blockMock->expects($this->any())->method('setIsAjax')->with(true)->will($this->returnValue($blockMock));
+        $blockMock->expects($this->once())->method('toHtml');
+        $this->responseMock->expects($this->once())->method('representJson')->with(json_encode(['imgSrc' => 'source']));
+        $this->flagMock->expects($this->once())->method('set')->with('', 'no-postDispatch', true);
+
+        $this->model->execute();
+    }
+
+    /**
+     * @return array
+     */
+    public function executeDataProvider()
+    {
+        return [
+            [
+                'formId' => null,
+                'callsNumber' => 1,
+            ],
+            [
+                'formId' => 1,
+                'callsNumber' => 0,
+            ]
+        ];
+    }
+}
diff --git a/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php b/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..addc768e6c571efc38a2fa613195b6d6b791a5eb
--- /dev/null
+++ b/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Captcha\Test\Unit\Model\Checkout;
+
+class ConfigProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeMock;
+
+    /**
+     * @var integer
+     */
+    protected $formId = 1;
+
+    /**
+     * @var \Magento\Captcha\Model\Checkout\ConfigProvider
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface');
+        $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false);
+        $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false);
+        $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
+        $formIds = [$this->formId];
+
+        $this->model = new \Magento\Captcha\Model\Checkout\ConfigProvider(
+            $this->storeManagerMock,
+            $this->captchaHelperMock,
+            $formIds
+        );
+    }
+
+    /**
+     * @dataProvider getConfigDataProvider
+     * @param bool $isRequired
+     * @param integer $captchaGenerations
+     * @param array $expectedConfig
+     */
+    public function testGetConfig($isRequired, $captchaGenerations, $expectedConfig)
+    {
+        $this->captchaHelperMock->expects($this->any())->method('getCaptcha')->with($this->formId)
+            ->will($this->returnValue($this->captchaMock));
+
+        $this->captchaMock->expects($this->any())->method('isCaseSensitive')->will($this->returnValue(1));
+        $this->captchaMock->expects($this->any())->method('getHeight')->will($this->returnValue('12px'));
+        $this->captchaMock->expects($this->any())->method('isRequired')->will($this->returnValue($isRequired));
+
+        $this->captchaMock->expects($this->exactly($captchaGenerations))->method('generate');
+        $this->captchaMock->expects($this->exactly($captchaGenerations))->method('getImgSrc')
+            ->will($this->returnValue('source'));
+
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock));
+        $this->storeMock->expects($this->once())->method('isCurrentlySecure')->will($this->returnValue(true));
+        $this->storeMock->expects($this->once())->method('getUrl')->with('captcha/refresh', ['_secure' => true])
+            ->will($this->returnValue('https://magento.com/captcha'));
+
+        $config = $this->model->getConfig();
+        $this->assertEquals($config, $expectedConfig);
+    }
+
+    /**
+     * @return array
+     */
+    public function getConfigDataProvider()
+    {
+        return [
+            [
+                'isRequired' => true,
+                'captchaGenerations' => 1,
+                'expectedConfig' => [
+                    'captcha' => [
+                        $this->formId => [
+                            'isCaseSensitive' => true,
+                            'imageHeight' => '12px',
+                            'imageSrc' => 'source',
+                            'refreshUrl' => 'https://magento.com/captcha',
+                            'isRequired' => true
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'isRequired' => false,
+                'captchaGenerations' => 0,
+                'expectedConfig' => [
+                    'captcha' => [
+                        $this->formId => [
+                            'isCaseSensitive' => true,
+                            'imageHeight' => '12px',
+                            'imageSrc' => '',
+                            'refreshUrl' => 'https://magento.com/captcha',
+                            'isRequired' => false
+                        ],
+                    ],
+                ],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php b/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a79969f8ef4f17c760547f7b7496821b18e9fec
--- /dev/null
+++ b/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php
@@ -0,0 +1,173 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Captcha\Test\Unit\Model\Customer\Plugin;
+
+class AjaxLoginTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $sessionManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $jsonFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $captchaMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultJsonMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $loginControllerMock;
+
+    /**
+     * @var array
+     */
+    protected $formIds;
+
+    /**
+     * @var \Magento\Captcha\Model\Customer\Plugin\AjaxLogin
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->sessionManagerMock = $this->getMock('Magento\Checkout\Model\Session', ['setUsername'], [], '', false);
+        $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false);
+        $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false);
+        $this->jsonFactoryMock = $this->getMock(
+            'Magento\Framework\Controller\Result\JsonFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->resultJsonMock = $this->getMock('Magento\Framework\Controller\Result\Json', [], [], '', false);
+        $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+        $this->loginControllerMock = $this->getMock('Magento\Customer\Controller\Ajax\Login', [], [], '', false);
+
+        $this->loginControllerMock->expects($this->any())->method('getRequest')
+            ->will($this->returnValue($this->requestMock));
+        $this->captchaHelperMock->expects($this->once())->method('getCaptcha')
+            ->with('user_login')->will($this->returnValue($this->captchaMock));
+        $this->formIds = ['user_login'];
+
+        $this->model = new \Magento\Captcha\Model\Customer\Plugin\AjaxLogin(
+            $this->captchaHelperMock,
+            $this->sessionManagerMock,
+            $this->jsonFactoryMock,
+            $this->formIds
+        );
+    }
+
+    public function testAroundExecute()
+    {
+        $username = 'name';
+        $captchaString = 'string';
+        $requestContent = json_encode([
+            'username' => $username,
+            'captcha_string' => $captchaString,
+            'captcha_form_id' => $this->formIds[0]
+        ]);
+
+        $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent));
+        $this->captchaMock->expects($this->once())->method('isRequired')->with($username)
+            ->will($this->returnValue(true));
+        $this->captchaMock->expects($this->once())->method('logAttempt')->with($username);
+        $this->captchaMock->expects($this->once())->method('isCorrect')->with($captchaString)
+            ->will($this->returnValue(true));
+
+        $closure = function () {
+            return 'result';
+        };
+        $this->assertEquals('result', $this->model->aroundExecute($this->loginControllerMock, $closure));
+    }
+
+    public function testAroundExecuteIncorrectCaptcha()
+    {
+        $username = 'name';
+        $captchaString = 'string';
+        $requestContent = json_encode([
+            'username' => $username,
+            'captcha_string' => $captchaString,
+            'captcha_form_id' => $this->formIds[0]
+        ]);
+
+        $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent));
+        $this->captchaMock->expects($this->once())->method('isRequired')->with($username)
+            ->will($this->returnValue(true));
+        $this->captchaMock->expects($this->once())->method('logAttempt')->with($username);
+        $this->captchaMock->expects($this->once())->method('isCorrect')
+            ->with($captchaString)->will($this->returnValue(false));
+
+        $this->sessionManagerMock->expects($this->once())->method('setUsername')->with($username);
+        $this->jsonFactoryMock->expects($this->once())->method('create')
+            ->will($this->returnValue($this->resultJsonMock));
+
+        $this->resultJsonMock->expects($this->once())->method('setData')
+            ->with(['errors' => true, 'message' => __('Incorrect CAPTCHA')])->will($this->returnValue('response'));
+
+        $closure = function () {
+        };
+        $this->assertEquals('response', $this->model->aroundExecute($this->loginControllerMock, $closure));
+    }
+
+    /**
+     * @dataProvider aroundExecuteCaptchaIsNotRequired
+     * @param string $username
+     * @param array $requestContent
+     */
+    public function testAroundExecuteCaptchaIsNotRequired($username, $requestContent)
+    {
+        $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent));
+
+        $this->captchaMock->expects($this->once())->method('isRequired')->with($username)
+            ->will($this->returnValue(false));
+        $this->captchaMock->expects($this->never())->method('logAttempt')->with($username);
+        $this->captchaMock->expects($this->never())->method('isCorrect');
+
+        $closure = function () {
+            return 'result';
+        };
+        $this->assertEquals('result', $this->model->aroundExecute($this->loginControllerMock, $closure));
+    }
+
+    /**
+     * @return array
+     */
+    public function aroundExecuteCaptchaIsNotRequired()
+    {
+        return [
+            [
+                'username' => 'name',
+                'requestContent' => json_encode(['username' => 'name', 'captcha_string' => 'string']),
+            ],
+            [
+                'username' => null,
+                'requestContent' => json_encode(['captcha_string' => 'string']),
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json
index 987ef790dfd28fc18a1e0a87488a86213f350154..a52065c0e94a4ddbcde9e27a053311b619e9519d 100644
--- a/app/code/Magento/Captcha/composer.json
+++ b/app/code/Magento/Captcha/composer.json
@@ -6,7 +6,6 @@
         "magento/module-store": "0.74.0-beta15",
         "magento/module-customer": "0.74.0-beta15",
         "magento/module-checkout": "0.74.0-beta15",
-        "magento/module-quote": "0.74.0-beta15",
         "magento/module-backend": "0.74.0-beta15",
         "magento/framework": "0.74.0-beta15",
         "magento/magento-composer-installer": "*"
diff --git a/app/code/Magento/Captcha/etc/di.xml b/app/code/Magento/Captcha/etc/di.xml
index 2f150515f4ef38c3d2b14eb746aac1409d422dc6..6dfdcd70b2222544e04939b7eb1aa4404dd07083 100644
--- a/app/code/Magento/Captcha/etc/di.xml
+++ b/app/code/Magento/Captcha/etc/di.xml
@@ -19,16 +19,15 @@
     <type name="Magento\Customer\Controller\Ajax\Login">
         <plugin name="configurable_product" type="Magento\Captcha\Model\Customer\Plugin\AjaxLogin" sortOrder="50" />
     </type>
-    <type name="Magento\Quote\Model\AddressAdditionalDataProcessor">
-        <plugin name="captcha_validation" type="\Magento\Captcha\Model\Checkout\Plugin\Validation" />
-    </type>
-    <type name="Magento\Captcha\Model\Checkout\Plugin\Validation">
+    <type name="Magento\Captcha\Model\Customer\Plugin\AjaxLogin">
         <arguments>
             <argument name="formIds" xsi:type="array">
                 <item name="user_login" xsi:type="string">user_login</item>
                 <item name="guest_checkout" xsi:type="string">guest_checkout</item>
-                <item name="register_during_checkout" xsi:type="string">register_during_checkout</item>
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Checkout\Block\Cart\Sidebar">
+        <plugin name="login_captcha" type="\Magento\Captcha\Model\Cart\ConfigPlugin" sortOrder="50" />
+    </type>
 </config>
diff --git a/app/code/Magento/Captcha/etc/extension_attributes.xml b/app/code/Magento/Captcha/etc/extension_attributes.xml
deleted file mode 100644
index e99af65250102d4db36964850c3ee1d602f08b99..0000000000000000000000000000000000000000
--- a/app/code/Magento/Captcha/etc/extension_attributes.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0"?>
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd">
-    <extension_attributes for="Magento\Quote\Api\Data\AddressAdditionalDataInterface">
-        <attribute code="captcha_string" type="string" />
-        <attribute code="captcha_form_id" type="string" />
-    </extension_attributes>
-</config>
-
-
diff --git a/app/code/Magento/Captcha/etc/frontend/di.xml b/app/code/Magento/Captcha/etc/frontend/di.xml
index 4807eb77b726076246107bddfc1acbac299d83a6..a768ffac2f67e372ed36af36133105b7ca909f54 100644
--- a/app/code/Magento/Captcha/etc/frontend/di.xml
+++ b/app/code/Magento/Captcha/etc/frontend/di.xml
@@ -18,7 +18,6 @@
             <argument name="formIds" xsi:type="array">
                 <item name="user_login" xsi:type="string">user_login</item>
                 <item name="guest_checkout" xsi:type="string">guest_checkout</item>
-                <item name="register_during_checkout" xsi:type="string">register_during_checkout</item>
             </argument>
         </arguments>
     </type>
diff --git a/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml
index 3154d7f81876805131083c4912ab3e0fbf93cc87..d7d6fc551c5ff3f777effb8a6cf3b573c60113a1 100644
--- a/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>
         <referenceBlock name="checkout.root">
             <arguments>
@@ -13,30 +13,59 @@
                     <item name="components" xsi:type="array">
                         <item name="checkout" xsi:type="array">
                             <item name="children" xsi:type="array">
+                                <item name="authentication" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="captcha" xsi:type="array">
+                                            <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item>
+                                            <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                            <item name="formId" xsi:type="string">user_login</item>
+                                            <item name="configSource" xsi:type="string">checkoutConfig</item>
+                                        </item>
+                                    </item>
+                                </item>
                                 <item name="steps" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="authentication" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="captcha" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item>
-                                                    <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
-                                                    <item name="formId" xsi:type="string">user_login</item>
+                                                <item name="shippingAddress" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="customer-email" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="additional-login-form-fields" xsi:type="array">
+                                                                    <item name="children" xsi:type="array">
+                                                                        <item name="captcha" xsi:type="array">
+                                                                            <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item>
+                                                                            <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                                                            <item name="formId" xsi:type="string">guest_checkout</item>
+                                                                            <item name="configSource" xsi:type="string">checkoutConfig</item>
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
                                                 </item>
                                             </item>
                                         </item>
-                                        <item name="billingAddress" xsi:type="array">
+                                        <item name="billing-step" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="captcha_guest_checkout" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/guestCaptcha</item>
-                                                    <item name="displayArea" xsi:type="string">additional-fieldsets</item>
-                                                    <item name="formId" xsi:type="string">guest_checkout</item>
-                                                    <item name="dataScope" xsi:type="string">additionalAddressData</item>
-                                                </item>
-                                                <item name="captcha_register_during_checkout" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/registerCaptcha</item>
-                                                    <item name="displayArea" xsi:type="string">additional-fieldsets</item>
-                                                    <item name="formId" xsi:type="string">register_during_checkout</item>
-                                                    <item name="dataScope" xsi:type="string">additionalAddressData</item>
+                                                <item name="payment" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="customer-email" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="additional-login-form-fields" xsi:type="array">
+                                                                    <item name="children" xsi:type="array">
+                                                                        <item name="captcha" xsi:type="array">
+                                                                            <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item>
+                                                                            <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                                                            <item name="formId" xsi:type="string">guest_checkout</item>
+                                                                            <item name="configSource" xsi:type="string">checkoutConfig</item>
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
                                                 </item>
                                             </item>
                                         </item>
@@ -49,4 +78,4 @@
             </arguments>
         </referenceBlock>
     </body>
-</page>
\ No newline at end of file
+</page>
diff --git a/app/code/Magento/Captcha/view/frontend/layout/default.xml b/app/code/Magento/Captcha/view/frontend/layout/default.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9e0bf3cc751c5c0b9fad96ea62e3da31b26ed320
--- /dev/null
+++ b/app/code/Magento/Captcha/view/frontend/layout/default.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="minicart">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="minicart_content" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="sign-in-popup" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="captcha" xsi:type="array">
+                                            <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item>
+                                            <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                            <item name="formId" xsi:type="string">user_login</item>
+                                            <item name="configSource" xsi:type="string">checkout</item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js b/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js
index cc8b2119827216883b9330c5717d5cbf1d460337..b11ae9b1f144aee227da25267b86dd7cc7ed1681 100644
--- a/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js
+++ b/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js
@@ -9,9 +9,10 @@ define(
     function(storage) {
         "use strict";
         return function(refreshUrl, formId, imageSource) {
-            storage.post(
+            return storage.post(
                 refreshUrl,
-                JSON.stringify({'formId': formId})
+                JSON.stringify({'formId': formId}),
+                false
             ).done(
                 function (response) {
                     if (response.imgSrc) {
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js b/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js
index a8abae3cc8de7638c7c6414df11a646935e3e715..6a720a8cdeb91879729ecc3ca4aa85f3e497f3bd 100644
--- a/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js
+++ b/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js
@@ -6,10 +6,11 @@
 /*global alert*/
 define(
     [
+        'jquery',
         'ko',
         'Magento_Captcha/js/action/refresh'
     ],
-    function(ko, refreshAction) {
+    function($, ko, refreshAction) {
         return function (captchaData) {
             return {
                 formId: captchaData.formId,
@@ -20,6 +21,7 @@ define(
                 isCaseSensitive: captchaData.isCaseSensitive,
                 imageHeight: captchaData.imageHeight,
                 refreshUrl: captchaData.refreshUrl,
+                isLoading: ko.observable(false),
 
                 getFormId: function () {
                     return this.formId;
@@ -70,7 +72,14 @@ define(
                     this.captchaValue(value);
                 },
                 refresh: function() {
-                    refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource());
+                    var refresh,
+                        self = this;
+                    this.isLoading(true);
+
+                    refresh = refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource());
+                    $.when(refresh).done(function() {
+                        self.isLoading(false);
+                    });
                 }
             };
         }
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js
index 5039e6a56a4d254c1f3763c3ead7d62efc481f81..ddb4a6f84ae57bf22a0c9396a5843658813f0785 100644
--- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js
+++ b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js
@@ -7,15 +7,14 @@
 define(
     [
         'jquery',
-        'ko',
         'uiComponent',
-        'Magento_Customer/js/model/customer',
         'Magento_Captcha/js/model/captcha',
         'Magento_Captcha/js/model/captchaList'
     ],
-    function ($, ko, Component, customer, Captcha, captchaList) {
-        "use strict";
-        var captchaConfig = window.checkoutConfig.captcha;
+    function ($, Component, Captcha, captchaList) {
+        'use strict';
+        var captchaConfig;
+
         return Component.extend({
             defaults: {
                 template: 'Magento_Captcha/checkout/captcha'
@@ -26,11 +25,16 @@ define(
                 return this.currentCaptcha.getCaptchaValue();
             },
             initialize: function() {
+                this._super();
+                captchaConfig = window[this.configSource]['captcha'];
+
                 $.each(captchaConfig, function(formId, captchaData) {
                     captchaData.formId = formId;
                     captchaList.add(Captcha(captchaData));
                 });
-                this._super();
+            },
+            getIsLoading: function() {
+                return this.currentCaptcha.isLoading
             },
             getCurrentCaptcha: function() {
                 return this.currentCaptcha;
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js
deleted file mode 100644
index eb7e9c806e64bd94da1086bf4e92af253ce8027a..0000000000000000000000000000000000000000
--- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true jquery:true*/
-/*global define*/
-define(
-    [
-        'Magento_Captcha/js/view/checkout/defaultCaptcha',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Captcha/js/model/captchaList',
-        'Magento_Checkout/js/action/select-shipping-address',
-        'Magento_Checkout/js/action/select-billing-address',
-        'Magento_Checkout/js/model/step-navigator'
-    ],
-    function (defaultCaptcha, quote, captchaList, selectShippingAddress, selectBillingAddress, navigator) {
-        "use strict";
-        return defaultCaptcha.extend({
-            initialize: function() {
-                this._super();
-                var self = this;
-                var currentCaptcha = captchaList.getCaptchaByFormId(this.formId);
-                if (currentCaptcha != null) {
-                    this.setCurrentCaptcha(currentCaptcha);
-                    quote.getCheckoutMethod().subscribe(function(method) {
-                        if (method == 'guest') {
-                            self.setIsVisible(true);
-                            var callback = function(isSuccessful) {
-                                if (!isSuccessful) {
-                                    currentCaptcha.setCaptchaValue(null);
-                                    currentCaptcha.refresh();
-                                    navigator.goToStep('billingAddress');
-                                }
-                            };
-                            selectShippingAddress.setActionCallback(callback);
-                            selectBillingAddress.setActionCallback(callback);
-                        } else {
-                            self.setIsVisible(false);
-                        }
-                    });
-                }
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js
index e042e96e850e6558926cd6612a8a9d7526635c77..75f7c4f0071dc96da86f13112f3d8c04190e6a02 100644
--- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js
+++ b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js
@@ -7,26 +7,25 @@
 define(
     [
         'Magento_Captcha/js/view/checkout/defaultCaptcha',
-        'Magento_Customer/js/model/customer',
-        'Magento_Captcha/js/model/captchaList'
+        'Magento_Captcha/js/model/captchaList',
+        'Magento_Customer/js/action/login'
     ],
-    function (defaultCaptcha, customer, captchaList) {
-        "use strict";
+    function (defaultCaptcha, captchaList, loginAction) {
+        'use strict';
         return defaultCaptcha.extend({
             initialize: function() {
                 this._super();
-                var currentCaptcha = captchaList.getCaptchaByFormId(this.formId);
+                var currentCaptcha = captchaList.getCaptchaByFormId(this.formId),
+                    self = this;
+
                 if (currentCaptcha != null) {
                     currentCaptcha.setIsVisible(true);
                     this.setCurrentCaptcha(currentCaptcha);
-                    this.updateCaptchaOnFailedLogin();
-                }
-            },
-            updateCaptchaOnFailedLogin: function () {
-                if (this.formId == 'user_login') {
-                    var self = this;
-                    customer.getFailedLoginAttempts().subscribe(function() {
-                        self.refresh();
+
+                    loginAction.registerLoginCallback(function(loginData) {
+                        if (loginData.captcha_form_id && loginData.captcha_form_id == self.formId) {
+                            self.refresh();
+                        }
                     });
                 }
             }
diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js
deleted file mode 100644
index ea284b5fe562483669319af1c308409d4e137358..0000000000000000000000000000000000000000
--- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true jquery:true*/
-/*global define*/
-define(
-    [
-        'Magento_Captcha/js/view/checkout/defaultCaptcha',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Captcha/js/model/captchaList',
-        'Magento_Checkout/js/action/select-shipping-address',
-        'Magento_Checkout/js/action/select-billing-address',
-        'Magento_Checkout/js/model/step-navigator'
-    ],
-    function (defaultCaptcha, quote, captchaList, selectShippingAddress, selectBillingAddress, navigator) {
-        "use strict";
-        return defaultCaptcha.extend({
-            initialize: function() {
-                this._super();
-                var self = this;
-                var currentCaptcha = captchaList.getCaptchaByFormId(this.formId);
-                if (currentCaptcha != null) {
-                    this.setCurrentCaptcha(currentCaptcha);
-                    quote.getCheckoutMethod().subscribe(function(method) {
-                        if (method == 'register') {
-                            self.setIsVisible(true);
-                            var callback = function(isSuccessful) {
-                                if (!isSuccessful) {
-                                    currentCaptcha.setCaptchaValue(null);
-                                    currentCaptcha.refresh();
-                                    navigator.goToStep('billingAddress');
-                                }
-                            };
-                            selectShippingAddress.setActionCallback(callback);
-                            selectBillingAddress.setActionCallback(callback);
-                        } else {
-                            self.setIsVisible(false);
-                        }
-                    });
-                }
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html
index fd345b82386446b5553ef81f3ce56b5e1c70f158..3b294d904b2cbe877dd80763986aa7fa66ecf89b 100644
--- a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html
+++ b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html
@@ -5,7 +5,7 @@
  */
 -->
 <!-- ko if: (isRequired() && getIsVisible())-->
-<div class="field captcha required">
+<div class="field captcha required" data-bind="blockLoader: getIsLoading()">
     <label data-bind="attr: {for: 'captcha_' + formId}" class="label"><span data-bind="text: $t('Please type the letters below')"></span></label>
     <div class="control captcha">
         <input name="captcha_string" type="text" class="input-text required-entry" data-bind="value: captchaValue(), attr: {id: 'captcha_' + formId, 'data-scope': dataScope}" />
diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php
index a0d38f5d3c28a751df57aa7e44dbbfcde69847c3..b707ad5848b054ccf20039530499a588365facf7 100644
--- a/app/code/Magento/Catalog/Block/Product/Context.php
+++ b/app/code/Magento/Catalog/Block/Product/Context.php
@@ -94,6 +94,9 @@ class Context extends \Magento\Framework\View\Element\Template\Context
      * @param \Magento\Framework\View\TemplateEnginePool $enginePool
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Framework\View\Page\Config $pageConfig
+     * @param \Magento\Framework\View\Element\Template\File\Resolver $resolver
+     * @param \Magento\Framework\View\Element\Template\File\Validator $validator
      * @param \Magento\Catalog\Model\Config $catalogConfig
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Tax\Helper\Data $taxHelper
@@ -105,7 +108,6 @@ class Context extends \Magento\Framework\View\Element\Template\Context
      * @param \Magento\Catalog\Helper\Image $imageHelper
      * @param ReviewRendererInterface $reviewRenderer
      * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
-     * @param \Magento\Framework\View\Page\Config $pageConfig
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -133,6 +135,8 @@ class Context extends \Magento\Framework\View\Element\Template\Context
         \Magento\Framework\App\State $appState,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\View\Page\Config $pageConfig,
+        \Magento\Framework\View\Element\Template\File\Resolver $resolver,
+        \Magento\Framework\View\Element\Template\File\Validator $validator,
         \Magento\Catalog\Model\Config $catalogConfig,
         \Magento\Framework\Registry $registry,
         \Magento\Tax\Helper\Data $taxHelper,
@@ -179,7 +183,9 @@ class Context extends \Magento\Framework\View\Element\Template\Context
             $enginePool,
             $appState,
             $storeManager,
-            $pageConfig
+            $pageConfig,
+            $resolver,
+            $validator
         );
     }
 
diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b0f7dd0f9340b1c33eb6b1ec0d41b749243e620
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Test\Unit\Helper\Product;
+
+class ConfigurationPoolTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var array
+     */
+    protected $instancesType;
+
+    /**
+     * @var \Magento\Catalog\Helper\Product\ConfigurationPool
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->instancesType = ['simple' => 'simple', 'default' => 'default'];
+
+        $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface');
+        $this->model = new \Magento\Catalog\Helper\Product\ConfigurationPool($objectManagerMock, $this->instancesType);
+    }
+
+    /**
+     * @dataProvider getByProductTypeDataProvider
+     * @param string $productType
+     * @param string $expectedResult
+     */
+    public function testGetByProductType($productType, $expectedResult)
+    {
+        $this->assertEquals($expectedResult, $this->model->getByProductType($productType));
+    }
+
+    /**
+     * @return array
+     */
+    public function getByProductTypeDataProvider()
+    {
+        return [
+            [
+                'productType' => 'simple',
+                'expectedResult' => 'simple'
+            ],
+            [
+                'productType' => 'custom',
+                'expectedResult' => 'default'
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Actions.php b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Actions.php
index 7eac125efeaa9844f69f5def335f7eece0d5e7f6..ea19e1bee5c9874b40d0e484ff3d82157666961f 100644
--- a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Actions.php
+++ b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Actions.php
@@ -15,6 +15,7 @@ class Actions extends Generic implements TabInterface
      * Prepare content for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabLabel()
     {
@@ -25,6 +26,7 @@ class Actions extends Generic implements TabInterface
      * Prepare title for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabTitle()
     {
@@ -35,6 +37,7 @@ class Actions extends Generic implements TabInterface
      * Returns status flag about this tab can be showen or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function canShowTab()
     {
@@ -45,6 +48,7 @@ class Actions extends Generic implements TabInterface
      * Returns status flag about this tab hidden or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function isHidden()
     {
diff --git a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Conditions.php b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Conditions.php
index e52687c42cf0a92d72555376807378479b4cb05d..478a5556997cdd03d62195d3039ca35e3ae40f22 100644
--- a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Conditions.php
+++ b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Conditions.php
@@ -46,6 +46,7 @@ class Conditions extends Generic implements TabInterface
      * Prepare content for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabLabel()
     {
@@ -56,6 +57,7 @@ class Conditions extends Generic implements TabInterface
      * Prepare title for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabTitle()
     {
@@ -66,6 +68,7 @@ class Conditions extends Generic implements TabInterface
      * Returns status flag about this tab can be showen or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function canShowTab()
     {
@@ -76,6 +79,7 @@ class Conditions extends Generic implements TabInterface
      * Returns status flag about this tab hidden or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function isHidden()
     {
diff --git a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php
index 9b50207884c18ed1b9a124e751c4a485cf2c347b..c3da800a88d65759a74ea4414d4102a45a52a7d8 100644
--- a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php
+++ b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php
@@ -68,6 +68,7 @@ class Main extends Generic implements TabInterface
      * Prepare content for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabLabel()
     {
@@ -78,6 +79,7 @@ class Main extends Generic implements TabInterface
      * Prepare title for tab
      *
      * @return \Magento\Framework\Phrase
+     * @codeCoverageIgnore
      */
     public function getTabTitle()
     {
@@ -88,6 +90,7 @@ class Main extends Generic implements TabInterface
      * Returns status flag about this tab can be showed or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function canShowTab()
     {
@@ -98,6 +101,7 @@ class Main extends Generic implements TabInterface
      * Returns status flag about this tab hidden or not
      *
      * @return bool
+     * @codeCoverageIgnore
      */
     public function isHidden()
     {
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php
index f5c53227cf41c7587d110a9b50dab39aae37bd10..775d4ba8dfe6465c05a6a2a47d112a768197f709 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php
@@ -86,6 +86,7 @@ class Catalog extends Action
      *
      * @param string $dirtyRulesNoticeMessage
      * @return void
+     * @codeCoverageIgnore
      */
     public function setDirtyRulesNoticeMessage($dirtyRulesNoticeMessage)
     {
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
index dd32624a89912a5a3a8434f2975ed266bda2cb42..cef2b010b1d4070fe0cfc00db054890cb61a6033 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
@@ -60,6 +60,7 @@ abstract class AbstractIndexer implements IndexerActionInterface, MviewActionInt
      * Get affected cache tags
      *
      * @return array
+     * @codeCoverageIgnore
      */
     public function getIdentities()
     {
diff --git a/app/code/Magento/CatalogRule/Model/Resource/Rule.php b/app/code/Magento/CatalogRule/Model/Resource/Rule.php
index b20a93b2b6f15ee8904c2d8823b58fbd4ca1ef52..fe950295f0781e77ee525a65719883f19411dee2 100644
--- a/app/code/Magento/CatalogRule/Model/Resource/Rule.php
+++ b/app/code/Magento/CatalogRule/Model/Resource/Rule.php
@@ -135,6 +135,7 @@ class Rule extends \Magento\Rule\Model\Resource\AbstractResource
      * Initialize main table and table id field
      *
      * @return void
+     * @codeCoverageIgnore
      */
     protected function _construct()
     {
diff --git a/app/code/Magento/CatalogRule/Model/Resource/Rule/Collection.php b/app/code/Magento/CatalogRule/Model/Resource/Rule/Collection.php
index d23367451d26ce59315883d507e2cdb2c4fe8a1a..bda374dbafac623adce4a2c9bc7d122575ce9a98 100644
--- a/app/code/Magento/CatalogRule/Model/Resource/Rule/Collection.php
+++ b/app/code/Magento/CatalogRule/Model/Resource/Rule/Collection.php
@@ -24,6 +24,7 @@ class Collection extends \Magento\Rule\Model\Resource\Rule\Collection\AbstractCo
      * Set resource model
      *
      * @return void
+     * @codeCoverageIgnore
      */
     protected function _construct()
     {
diff --git a/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price.php b/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price.php
index 66f19d5c5234851cec5463701609323bfa382684..3f96fc0775c4bd0a4ec4b2b348520dce447b0bd1 100644
--- a/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price.php
+++ b/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price.php
@@ -17,6 +17,7 @@ class Price extends \Magento\Framework\Model\Resource\Db\AbstractDb
      * Initialize connection and define main table
      *
      * @return void
+     * @codeCoverageIgnore
      */
     protected function _construct()
     {
diff --git a/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price/Collection.php b/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price/Collection.php
index 8775a9b18f44a17d31493ef9ceb51d4d1237c00a..951b0e593c5407be37d0e356391c25256997750f 100644
--- a/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price/Collection.php
+++ b/app/code/Magento/CatalogRule/Model/Resource/Rule/Product/Price/Collection.php
@@ -9,6 +9,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 {
     /**
      * @return void
+     * @codeCoverageIgnore
      */
     protected function _construct()
     {
diff --git a/app/code/Magento/CatalogRule/Model/Rule.php b/app/code/Magento/CatalogRule/Model/Rule.php
index 84bfce2b0c8337189bcc4120e6a1b665b21dbb2c..1bdab229ba82a6d2b5aad2bbc72bf17fc46fa6ed 100644
--- a/app/code/Magento/CatalogRule/Model/Rule.php
+++ b/app/code/Magento/CatalogRule/Model/Rule.php
@@ -270,6 +270,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel
      *
      * @param string $now
      * @return void
+     * @codeCoverageIgnore
      */
     public function setNow($now)
     {
@@ -425,6 +426,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel
      *
      * @param  int|array $productIds
      * @return void
+     * @codeCoverageIgnore
      */
     public function setProductsFilter($productIds)
     {
@@ -435,6 +437,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel
      * Returns products filter
      *
      * @return array|int|null
+     * @codeCoverageIgnore
      */
     public function getProductsFilter()
     {
diff --git a/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php b/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea68c7aa5d85f7b00d7d3c96431c509e8b30388f
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api\Data;
+
+interface PaymentDetailsInterface
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const PAYMENT_METHODS = 'payment_methods';
+
+    const TOTALS = 'totals';
+
+    /**#@-*/
+
+    /**
+     * @return \Magento\Quote\Api\Data\PaymentMethodInterface[]
+     */
+    public function getPaymentMethods();
+
+    /**
+     * @param \Magento\Quote\Api\Data\PaymentMethodInterface[] $paymentMethods
+     * @return $this
+     */
+    public function setPaymentMethods($paymentMethods);
+
+    /**
+     * @return \Magento\Quote\Api\Data\TotalsInterface
+     */
+    public function getTotals();
+
+    /**
+     * @param \Magento\Quote\Api\Data\TotalsInterface $totals
+     * @return $this
+     */
+    public function setTotals($totals);
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php b/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b2b3710eb3ae4b521e96712312a2f2718cc53e6
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api\Data;
+
+interface ShippingInformationInterface extends \Magento\Framework\Api\CustomAttributesDataInterface
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const SHIPPING_ADDRESS = 'shipping_address';
+
+    const SHIPPING_METHOD_CODE = 'shipping_method_code';
+
+    const SHIPPING_CARRIER_CODE = 'shipping_carrier_code';
+
+    /**#@-*/
+
+    /**
+     * Returns shipping address
+     *
+     * @return \Magento\Quote\Api\Data\AddressInterface
+     */
+    public function getShippingAddress();
+
+    /**
+     * Set shipping address
+     *
+     * @param \Magento\Quote\Api\Data\AddressInterface $address
+     * @return $this
+     */
+    public function setShippingAddress(\Magento\Quote\Api\Data\AddressInterface $address);
+
+    /**
+     * Returns shipping method code
+     *
+     * @return string
+     */
+    public function getShippingMethodCode();
+
+    /**
+     * Set shipping method code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setShippingMethodCode($code);
+
+    /**
+     * Returns carrier code
+     *
+     * @return string
+     */
+    public function getShippingCarrierCode();
+
+    /**
+     * Set carrier code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setShippingCarrierCode($code);
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php b/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a2b178aa6691c64a9e00618c30f8717006a0220
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api;
+
+interface GuestPaymentInformationManagementInterface
+{
+    /**
+     * Set payment information and place order for a specified cart.
+     *
+     * @param string $cartId
+     * @param string $email
+     * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
+     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @return int Order ID.
+     */
+    public function savePaymentInformationAndPlaceOrder(
+        $cartId,
+        $email,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    );
+
+    /**
+     * Set payment information for a specified cart.
+     *
+     * @param string $cartId
+     * @param string $email
+     * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
+     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @return int Order ID.
+     */
+    public function savePaymentInformation(
+        $cartId,
+        $email,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    );
+}
diff --git a/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php b/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c52ee4a7766b8b8dfa6e6b55b76a16a4d2e8a786
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api;
+
+interface GuestShippingInformationManagementInterface
+{
+    /**
+     * @param string $cartId
+     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+     * @return \Magento\Checkout\Api\Data\PaymentDetailsInterface
+     */
+    public function saveAddressInformation(
+        $cartId,
+        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+    );
+}
diff --git a/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php b/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..bac301c7ab3695bc691aa74e5b9b764a366427a1
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api;
+
+interface PaymentInformationManagementInterface
+{
+    /**
+     * Set payment information and place order for a specified cart.
+     *
+     * @param int $cartId
+     * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
+     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @return int Order ID.
+     */
+    public function savePaymentInformationAndPlaceOrder(
+        $cartId,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    );
+
+    /**
+     * Set payment information for a specified cart.
+     *
+     * @param int $cartId
+     * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
+     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @return int Order ID.
+     */
+    public function savePaymentInformation(
+        $cartId,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    );
+}
diff --git a/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php b/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..4f39b764b35b9c3b7bbedbaf4914b7c6a732d77f
--- /dev/null
+++ b/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Api;
+
+interface ShippingInformationManagementInterface
+{
+    /**
+     * @param int $cartId
+     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+     * @return \Magento\Checkout\Api\Data\PaymentDetailsInterface
+     */
+    public function saveAddressInformation(
+        $cartId,
+        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+    );
+}
diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
index 593f1bd35806d975c41fba9806a6586c538a2950..a754a3c6582c58f3a1dcd4ec8f90f234a2ffaeff 100644
--- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php
+++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
@@ -52,6 +52,25 @@ class Sidebar extends AbstractCart
         $this->imageView = $imageView;
     }
 
+    /**
+     * Returns minicart config
+     *
+     * @return array
+     */
+    public function getConfig()
+    {
+        return [
+            'shoppingCartUrl' => $this->getShoppingCartUrl(),
+            'checkoutUrl' => $this->getCheckoutUrl(),
+            'updateItemQtyUrl' => $this->getUpdateItemQtyUrl(),
+            'removeItemUrl' => $this->getRemoveItemUrl(),
+            'imageTemplate' => $this->getImageHtmlTemplate(),
+            'customerRegisterUrl' => $this->getCustomerRegisterUrlUrl(),
+            'customerForgotPasswordUrl' => $this->getCustomerForgotPasswordUrl(),
+            'baseUrl' => $this->getBaseUrl()
+        ];
+    }
+
     /**
      * @return string
      */
@@ -139,4 +158,34 @@ class Sidebar extends AbstractCart
     {
         return $this->getLayout()->getBlock('checkout.cart.minicart.totals')->toHtml();
     }
+
+    /**
+     * Get customer register url
+     *
+     * @return string
+     */
+    public function getCustomerRegisterUrlUrl()
+    {
+        return $this->getUrl('customer/account/create');
+    }
+
+    /**
+     * Get customer forgot password url
+     *
+     * @return string
+     */
+    public function getCustomerForgotPasswordUrl()
+    {
+        return $this->getUrl('customer/account/forgotpassword');
+    }
+
+    /**
+     * Return base url.
+     *
+     * @return string
+     */
+    public function getBaseUrl()
+    {
+        return $this->_storeManager->getStore()->getBaseUrl();
+    }
 }
diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
index 224079faff6ff237b82ffa3ddf482d83d486a62f..32609252f0552023241063773f18a2f61c82fe02 100644
--- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
+++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
@@ -125,6 +125,9 @@ class AttributeMerger
                 'elementTmpl' => isset($additionalConfig['config']['elementTmpl'])
                     ? $additionalConfig['config']['elementTmpl']
                     : $elementTemplate,
+                'tooltip' => isset($additionalConfig['config']['tooltip'])
+                    ? $additionalConfig['config']['tooltip']
+                    : null
             ],
             'dataScope' => $dataScopePrefix . '.' . $attributeCode,
             'label' => $attributeConfig['label'],
@@ -141,7 +144,7 @@ class AttributeMerger
 
         $defaultValue = $this->getDefaultValue($attributeCode);
         if (null !== $defaultValue) {
-            $element['default'] = $defaultValue;
+            $element['value'] = $defaultValue;
         }
         return $element;
     }
diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php
index 9f5ffc3f6ef6dca215aaa6c100d57d4b4009dc8b..20332513a009f078db5fc7cd3468894ccaaac593 100644
--- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php
+++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php
@@ -60,26 +60,29 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso
         }
 
         // The following code is a workaround for custom address attributes
-        if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billingAddress']
-            ['children']['billing-address-fieldset']['children']
+        if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
+            ['payment']['children']
         )) {
-            $fields = $jsLayout['components']['checkout']['children']['steps']['children']['billingAddress']
-            ['children']['billing-address-fieldset']['children'];
-            $jsLayout['components']['checkout']['children']['steps']['children']['billingAddress']
-            ['children']['billing-address-fieldset']['children'] = $this->merger->merge(
-                $elements,
-                'checkoutProvider',
-                'billingAddress',
-                $fields
-            );
+            $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
+            ['payment']['children']['payments-list']['children'] =
+                array_merge_recursive(
+                    $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
+                    ['payment']['children']['payments-list']['children'],
+                    $this->processPaymentConfiguration(
+                        $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
+                        ['payment']['children']['renders']['children'],
+                        $elements
+                    )
+                );
         }
-        if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress']
-            ['children']['shipping-address-fieldset']['children']
+
+        if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
+            ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']
         )) {
-            $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress']
-            ['children']['shipping-address-fieldset']['children'];
-            $jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress']
-            ['children']['shipping-address-fieldset']['children'] = $this->merger->merge(
+            $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
+            ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];
+            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
+            ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] = $this->merger->merge(
                 $elements,
                 'checkoutProvider',
                 'shippingAddress',
@@ -88,4 +91,90 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso
         }
         return $jsLayout;
     }
+
+    /**
+     * Inject billing address component into every payment component
+     *
+     * @param array $configuration list of payment components
+     * @param array $elements attributes that must be displayed in address form
+     * @return array
+     */
+    private function processPaymentConfiguration(array &$configuration, array $elements)
+    {
+        $output = [];
+        foreach ($configuration as $paymentGroup => $groupConfig) {
+            foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
+                if (empty($paymentComponent['isBillingAddressRequired'])) {
+                    continue;
+                }
+                $output[$paymentCode . '-form'] = [
+                    'component' => 'Magento_Checkout/js/view/billing-address',
+                    'displayArea' => 'billing-address-form-' . $paymentCode,
+                    'provider' => 'checkoutProvider',
+                    'dataScopePrefix' => 'billingAddress' . $paymentCode,
+                    'sortOrder' => 1,
+                    'children' => [
+                        'form-fields' => [
+                            'component' => 'uiComponent',
+                            'displayArea' => 'additional-fieldsets',
+                            'children' => $this->merger->merge(
+                                $elements,
+                                'checkoutProvider',
+                                'billingAddress' . $paymentCode,
+                                [
+                                    'country_id' => [
+                                        'sortOrder' => 115,
+                                    ],
+                                    'region' => [
+                                        'visible' => false,
+                                    ],
+                                    'region_id' => [
+                                        'component' => 'Magento_Ui/js/form/element/region',
+                                        'config' => [
+                                            'template' => 'ui/form/field',
+                                            'elementTmpl' => 'ui/form/element/select',
+                                            'customEntry' => 'billingAddress' . $paymentCode . '.region',
+                                        ],
+                                        'validation' => [
+                                            'validate-select' => true,
+                                        ],
+                                        'filterBy' => [
+                                            'target' => '${ $.provider }:${ $.parentScope }.country_id',
+                                            'field' => 'country_id',
+                                        ],
+                                    ],
+                                    'postcode' => [
+                                        'component' => 'Magento_Ui/js/form/element/post-code',
+                                        'validation' => [
+                                            'required-entry' => true,
+                                        ],
+                                    ],
+                                    'company' => [
+                                        'validation' => [
+                                            'min_text_length' => 0,
+                                        ],
+                                    ],
+                                    'fax' => [
+                                        'validation' => [
+                                            'min_text_length' => 0,
+                                        ],
+                                    ],
+                                    'telephone' => [
+                                        'config' => [
+                                            'tooltip' => [
+                                                'description' => 'For delivery Questions',
+                                            ],
+                                        ],
+                                    ],
+                                ]
+                            ),
+                        ],
+                    ],
+                ];
+            }
+            unset($configuration[$paymentGroup]['methods']);
+        }
+
+        return $output;
+    }
 }
diff --git a/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php b/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php
new file mode 100644
index 0000000000000000000000000000000000000000..af5a8a51dd456490a1e1f66329cb1f83f94cc088
--- /dev/null
+++ b/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Block\Checkout;
+
+use Magento\Framework\App\Config\ScopeConfigInterface;
+
+class TotalsProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
+{
+    /**
+     * Core store config
+     *
+     * @var ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @param ScopeConfigInterface $scopeConfig
+     */
+    public function __construct(
+        ScopeConfigInterface $scopeConfig
+    ) {
+        $this->scopeConfig = $scopeConfig;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process($jsLayout)
+    {
+        $configData = $this->scopeConfig->getValue('sales/totals_sort');
+        $totals = $jsLayout['components']['checkout']['children']['summary']['children']['totals']['children'];
+        foreach ($totals as $code => &$total) {
+            //convert JS naming style to config naming style
+            $code = str_replace('-', '_', $code);
+            if (array_key_exists($code, $configData)) {
+                $total['sortOrder'] = $configData[$code];
+            }
+        }
+        $jsLayout['components']['checkout']['children']['summary']['children']['totals']['children'] = $totals;
+
+        return array_merge_recursive($jsLayout, $totals);
+    }
+}
diff --git a/app/code/Magento/Checkout/Block/Onepage/Success.php b/app/code/Magento/Checkout/Block/Onepage/Success.php
index 3f128226841f42e6526add15cb828d448359c047..46f85df2019ef53debf6b5583bffb9c7c264e6b0 100644
--- a/app/code/Magento/Checkout/Block/Onepage/Success.php
+++ b/app/code/Magento/Checkout/Block/Onepage/Success.php
@@ -104,9 +104,10 @@ class Success extends \Magento\Framework\View\Element\Template
     {
         $orderId = $this->_checkoutSession->getLastOrderId();
         if ($orderId) {
-            $order = $this->_orderFactory->create()->load($orderId);
-            if ($order->getId()) {
-                $isVisible = !in_array($order->getStatus(), $this->_orderConfig->getInvisibleOnFrontStatuses());
+            $incrementId = $this->_checkoutSession->getLastRealOrderId();
+            $status = $this->_checkoutSession->getLastOrderStatus();
+            if ($status && $incrementId) {
+                $isVisible = !in_array($status, $this->_orderConfig->getInvisibleOnFrontStatuses());
                 $canView = $this->httpContext->getValue(Context::CONTEXT_AUTH) && $isVisible;
                 $this->addData(
                     [
@@ -115,7 +116,7 @@ class Success extends \Magento\Framework\View\Element\Template
                         'print_url' => $this->getUrl('sales/order/print', ['order_id' => $orderId]),
                         'can_print_order' => $isVisible,
                         'can_view_order'  => $canView,
-                        'order_id'  => $order->getIncrementId(),
+                        'order_id'  => $incrementId,
                     ]
                 );
             }
diff --git a/app/code/Magento/Checkout/Controller/Onepage/Index.php b/app/code/Magento/Checkout/Controller/Onepage/Index.php
index 991511fc02267a4d6a250fb78576b0feaa08ad14..7fa9fa794c5fb5ab4441324cc716e26bec15c987 100644
--- a/app/code/Magento/Checkout/Controller/Onepage/Index.php
+++ b/app/code/Magento/Checkout/Controller/Onepage/Index.php
@@ -15,11 +15,19 @@ class Index extends \Magento\Checkout\Controller\Onepage
      */
     public function execute()
     {
-        if (!$this->_objectManager->get('Magento\Checkout\Helper\Data')->canOnepageCheckout()) {
+        $checkoutHelper = $this->_objectManager->get('Magento\Checkout\Helper\Data');
+        if (!$checkoutHelper->canOnepageCheckout()) {
             $this->messageManager->addError(__('One-page checkout is turned off.'));
             return $this->resultRedirectFactory->create()->setPath('checkout/cart');
         }
+
         $quote = $this->getOnepage()->getQuote();
+
+        if (!$this->_customerSession->isLoggedIn() && !$checkoutHelper->isAllowedGuestCheckout($quote)) {
+            $this->messageManager->addError(__('Guest checkout is disabled.'));
+            return $this->resultRedirectFactory->create()->setPath('checkout/cart');
+        }
+
         if (!$quote->hasItems() || $quote->getHasError() || !$quote->validateMinimumAmount()) {
             return $this->resultRedirectFactory->create()->setPath('checkout/cart');
         }
diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php
index ae306dc9439a26fedb5282ced36980fd55476887..55fd454db8aeb8d42bb6674d6ad0336f9e45c1ff 100644
--- a/app/code/Magento/Checkout/CustomerData/Cart.php
+++ b/app/code/Magento/Checkout/CustomerData/Cart.php
@@ -94,6 +94,7 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface
             'possible_onepage_checkout' => $this->isPossibleOnepageCheckout(),
             'items' => $this->getRecentItems(),
             'extra_actions' => $this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml(),
+            'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(),
         ];
     }
 
@@ -173,4 +174,14 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface
         }
         return $this->getQuote()->getAllVisibleItems();
     }
+
+    /**
+     * Check if guest checkout is allowed
+     *
+     * @return bool
+     */
+    public function isGuestCheckoutAllowed()
+    {
+        return $this->checkoutHelper->isAllowedGuestCheckout($this->checkoutSession->getQuote());
+    }
 }
diff --git a/app/code/Magento/Checkout/Model/Cart/ImageProvider.php b/app/code/Magento/Checkout/Model/Cart/ImageProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..f49b267b88a8ea7441b817fdb5a9fe42fe13b187
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/Cart/ImageProvider.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model\Cart;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ImageProvider
+{
+    /**
+     * @var \Magento\Quote\Api\CartItemRepositoryInterface
+     */
+    protected $itemRepository;
+
+    /**
+     * @var \Magento\Checkout\CustomerData\ItemPoolInterface
+     */
+    protected $itemPool;
+
+    /**
+     * @param \Magento\Quote\Api\CartItemRepositoryInterface $itemRepository
+     * @param \Magento\Checkout\CustomerData\ItemPoolInterface $itemPool
+     */
+    public function __construct(
+        \Magento\Quote\Api\CartItemRepositoryInterface $itemRepository,
+        \Magento\Checkout\CustomerData\ItemPoolInterface $itemPool
+    ) {
+        $this->itemRepository = $itemRepository;
+        $this->itemPool = $itemPool;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getImages($cartId)
+    {
+        $itemData = [];
+
+        /** @see code/Magento/Catalog/Helper/Product.php */
+        $items = $this->itemRepository->getList($cartId);
+        /** @var \Magento\Quote\Model\Quote\Item $cartItem */
+        foreach ($items as $cartItem) {
+            $allData = $this->itemPool->getItemData($cartItem);
+            $itemData[$cartItem->getItemId()] = $allData['product_image'];
+        }
+        return $itemData;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php
index 08de243b3a16294460af5e94807652592114ab90..21911aec850fcdc82c6163d2684fc10869fa8421 100644
--- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php
+++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php
@@ -6,7 +6,6 @@
 namespace Magento\Checkout\Model;
 
 use Magento\Checkout\Helper\Data as CheckoutHelper;
-use Magento\Checkout\Model\Type\Onepage as OnepageCheckout;
 use Magento\Checkout\Model\Session as CheckoutSession;
 use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository;
 use Magento\Customer\Model\Context as CustomerContext;
@@ -23,6 +22,9 @@ use Magento\Catalog\Helper\Product\ConfigurationPool;
 use Magento\Quote\Model\QuoteIdMaskFactory;
 use Magento\Framework\Locale\FormatInterface as LocaleFormat;
 use Magento\Framework\UrlInterface;
+use Magento\Quote\Api\CartTotalRepositoryInterface;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Store\Model\ScopeInterface;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -120,6 +122,53 @@ class DefaultConfigProvider implements ConfigProviderInterface
      */
     protected $viewConfig;
 
+    /**
+     * @var \Magento\Directory\Model\Country\Postcode\ConfigInterface
+     */
+    protected $postCodesConfig;
+
+    /**
+     * @var \Magento\Directory\Helper\Data
+     */
+    protected $directoryHelper;
+
+    /**
+     * @var Cart\ImageProvider
+     */
+    protected $imageProvider;
+
+    /**
+     * @var CartTotalRepositoryInterface
+     */
+    protected $cartTotalRepository;
+
+    /**
+     * Shipping method data factory.
+     *
+     * @var \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory
+     */
+    protected $estimatedAddressFactory;
+
+    /**
+     * @var ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @var \Magento\Shipping\Model\Config
+     */
+    protected $shippingMethodConfig;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \Magento\Quote\Api\PaymentMethodManagementInterface
+     */
+    protected $paymentMethodManagement;
+
     /**
      * @param CheckoutHelper $checkoutHelper
      * @param Session $checkoutSession
@@ -139,6 +188,15 @@ class DefaultConfigProvider implements ConfigProviderInterface
      * @param FormKey $formKey
      * @param \Magento\Catalog\Helper\Image $imageHelper
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
+     * @param \Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig
+     * @param Cart\ImageProvider $imageProvider
+     * @param \Magento\Directory\Helper\Data $directoryHelper
+     * @param CartTotalRepositoryInterface $cartTotalRepository
+     * @param \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory $estimatedAddressFactory
+     * @param ScopeConfigInterface $scopeConfig
+     * @param \Magento\Shipping\Model\Config $shippingMethodConfig
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -159,7 +217,16 @@ class DefaultConfigProvider implements ConfigProviderInterface
         \Magento\Customer\Model\Address\Config $addressConfig,
         FormKey $formKey,
         \Magento\Catalog\Helper\Image $imageHelper,
-        \Magento\Framework\View\ConfigInterface $viewConfig
+        \Magento\Framework\View\ConfigInterface $viewConfig,
+        \Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig,
+        Cart\ImageProvider $imageProvider,
+        \Magento\Directory\Helper\Data $directoryHelper,
+        CartTotalRepositoryInterface $cartTotalRepository,
+        \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory $estimatedAddressFactory,
+        ScopeConfigInterface $scopeConfig,
+        \Magento\Shipping\Model\Config $shippingMethodConfig,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
     ) {
         $this->checkoutHelper = $checkoutHelper;
         $this->checkoutSession = $checkoutSession;
@@ -179,6 +246,15 @@ class DefaultConfigProvider implements ConfigProviderInterface
         $this->formKey = $formKey;
         $this->imageHelper = $imageHelper;
         $this->viewConfig = $viewConfig;
+        $this->postCodesConfig = $postCodesConfig;
+        $this->imageProvider = $imageProvider;
+        $this->directoryHelper = $directoryHelper;
+        $this->cartTotalRepository = $cartTotalRepository;
+        $this->estimatedAddressFactory = $estimatedAddressFactory;
+        $this->scopeConfig = $scopeConfig;
+        $this->shippingMethodConfig = $shippingMethodConfig;
+        $this->storeManager = $storeManager;
+        $this->paymentMethodManagement = $paymentMethodManagement;
     }
 
     /**
@@ -186,6 +262,7 @@ class DefaultConfigProvider implements ConfigProviderInterface
      */
     public function getConfig()
     {
+        $quoteId = $this->checkoutSession->getQuote()->getId();
         return [
             'formKey' => $this->formKey->getFormKey(),
             'customerData' => $this->getCustomerData(),
@@ -207,10 +284,72 @@ class DefaultConfigProvider implements ConfigProviderInterface
             'basePriceFormat' => $this->localeFormat->getPriceFormat(
                 null,
                 $this->currencyManager->getDefaultCurrency()
-            )
+            ),
+            'postCodes' => $this->postCodesConfig->getPostCodes(),
+            'imageData' => $this->imageProvider->getImages($quoteId),
+            'countryData' => $this->getCountryData(),
+            'totalsData' => $this->getTotalsData(),
+            'shippingRates' => $this->getDefaultShippingRates(),
+            'shippingPolicy' => [
+                'isEnabled' => $this->scopeConfig->isSetFlag(
+                    'shipping/shipping_policy/enable_shipping_policy',
+                    ScopeInterface::SCOPE_STORE
+                ),
+                'shippingPolicyContent' => nl2br(
+                    $this->scopeConfig->getValue(
+                        'shipping/shipping_policy/shipping_policy_content',
+                        ScopeInterface::SCOPE_STORE
+                    )
+                )
+            ],
+            'activeCarriers' => $this->getActiveCarriers(),
+            'originCountryCode' => $this->getOriginCountryCode(),
+            'paymentMethods' => $this->getPaymentMethods()
         ];
     }
 
+    /**
+     * Get default shipping rates
+     *
+     * @return array
+     */
+    private function getDefaultShippingRates()
+    {
+        $output = [];
+        $addressKey = null;
+        if ($this->checkoutSession->getQuote()->getId()) {
+            $quote = $this->quoteRepository->get($this->checkoutSession->getQuote()->getId());
+            /** @var \Magento\Quote\Api\Data\EstimateAddressInterface $estimatedAddress */
+            $estimatedAddress = $this->estimatedAddressFactory->create();
+
+            $address = $quote->getShippingAddress();
+            if ($address &&
+                ($address->getCountryId()
+                    || $address->getPostcode()
+                    || $address->getRegion()
+                    || $address->getRegionId()
+                )
+            ) {
+                $estimatedAddress->setCountryId($address->getCountryId());
+                $estimatedAddress->setPostcode($address->getPostcode());
+                $estimatedAddress->setRegion($address->getRegion());
+                $estimatedAddress->setRegionId($address->getRegionId());
+            } else {
+                $estimatedAddress->setCountryId($this->directoryHelper->getDefaultCountry());
+            }
+            $rates = $this->shippingMethodManager->estimateByAddress($quote->getId(), $estimatedAddress);
+            foreach ($rates as $rate) {
+                $output[] = $rate->__toArray();
+            }
+
+            if ($address->getCustomerAddressId()) {
+                $addressKey = 'customer-address' . $address->getCustomerAddressId();
+            }
+        };
+        return ['key' => $addressKey, 'data' => $output];
+
+    }
+
     /**
      * Retrieve customer data
      *
@@ -270,13 +409,6 @@ class DefaultConfigProvider implements ConfigProviderInterface
         $quoteData = [];
         if ($this->checkoutSession->getQuote()->getId()) {
             $quote = $this->quoteRepository->get($this->checkoutSession->getQuote()->getId());
-            // the following condition is a legacy logic left here for compatibility
-            if (!$quote->getCustomer()->getId()) {
-                $this->quoteRepository->save($this->checkoutSession->getQuote()->setCheckoutMethod('guest'));
-            } else {
-                $this->quoteRepository->save($this->checkoutSession->getQuote()->setCheckoutMethod(null));
-            }
-
             $quoteData = $quote->toArray();
             $quoteData['is_virtual'] = $quote->getIsVirtual();
 
@@ -357,22 +489,21 @@ class DefaultConfigProvider implements ConfigProviderInterface
     /**
      * Retrieve selected shipping method
      *
-     * @return string
+     * @return array|null
      */
     private function getSelectedShippingMethod()
     {
-        // Shipping method ID contains carrier code and shipping method code
-        $shippingMethodId = '';
+        $shippingMethodData = null;
         try {
             $quoteId = $this->checkoutSession->getQuote()->getId();
             $shippingMethod = $this->shippingMethodManager->get($quoteId);
             if ($shippingMethod) {
-                $shippingMethodId = $shippingMethod->getCarrierCode() . '_' . $shippingMethod->getMethodCode();
+                $shippingMethodData = $shippingMethod->__toArray();
             }
         } catch (\Exception $exception) {
-            $shippingMethodId = '';
+            $shippingMethodData = null;
         }
-        return $shippingMethodId;
+        return $shippingMethodData;
     }
 
     /**
@@ -434,4 +565,97 @@ class DefaultConfigProvider implements ConfigProviderInterface
     {
         return $this->checkoutSession->getQuote()->getStore()->getBaseUrl(UrlInterface::URL_TYPE_STATIC);
     }
+
+    /**
+     * Return countries data
+     * @return array
+     */
+    private function getCountryData()
+    {
+        $country = [];
+        $regionsData = $this->directoryHelper->getRegionData();
+        foreach ($this->directoryHelper->getCountryCollection() as $code => $data) {
+            $country[$code]['name'] = $data->getName();
+            if (array_key_exists($code, $regionsData)) {
+                foreach ($regionsData[$code] as $key => $region) {
+                    $country[$code]['regions'][$key]['code'] = $region['code'];
+                    $country[$code]['regions'][$key]['name'] = $region['name'];
+                }
+            }
+
+        }
+        return $country;
+    }
+
+    /**
+     * Return quote totals data
+     * @return array
+     */
+    private function getTotalsData()
+    {
+        /** @var \Magento\Quote\Api\Data\TotalsInterface $totals */
+        $totals = $this->cartTotalRepository->get($this->checkoutSession->getQuote()->getId());
+        $items = [];
+        /** @var  \Magento\Quote\Model\Cart\Totals\Item $item */
+        foreach ($totals->getItems() as $item) {
+            $items[] = $item->__toArray();
+        }
+        $totalSegmentsData = [];
+        /** @var \Magento\Quote\Model\Cart\TotalSegment $totalSegment */
+        foreach ($totals->getTotalSegments() as $totalSegment) {
+            $totalSegmentsData[] = $totalSegment->toArray();
+        }
+        $totals->setItems($items);
+        $totals->setTotalSegments($totalSegmentsData);
+        $totalsArray = $totals->toArray();
+        if (is_object($totals->getExtensionAttributes())) {
+            $totalsArray['extension_attributes'] = $totals->getExtensionAttributes()->__toArray();
+        }
+        return $totalsArray;
+    }
+
+    /**
+     * Returns active carriers codes
+     * @return array
+     */
+    private function getActiveCarriers()
+    {
+        $activeCarriers = [];
+        foreach ($this->shippingMethodConfig->getActiveCarriers() as $carrier) {
+            $activeCarriers[] = $carrier->getCarrierCode();
+        }
+        return $activeCarriers;
+    }
+
+    /**
+     * Returns origin country code
+     * @return string
+     */
+    private function getOriginCountryCode()
+    {
+        return $this->scopeConfig->getValue(
+            \Magento\Shipping\Model\Config::XML_PATH_ORIGIN_COUNTRY_ID,
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->storeManager->getStore()
+        );
+    }
+
+    /**
+     * Returns array of payment methods
+     * @return array
+     */
+    private function getPaymentMethods()
+    {
+        $paymentMethods = [];
+        $quote = $this->checkoutSession->getQuote();
+        if ($quote->getIsVirtual()) {
+            foreach ($this->paymentMethodManagement->getList($quote->getId()) as $paymentMethod) {
+                $paymentMethods[] = [
+                    'code' => $paymentMethod->getCode(),
+                    'title' => $paymentMethod->getTitle()
+                ];
+            }
+        }
+        return $paymentMethods;
+    }
 }
diff --git a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..75e2539835e50cad7c7ff97d185044196423bf5d
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Model;
+
+class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPaymentInformationManagementInterface
+{
+
+    /**
+     * @var \Magento\Quote\Api\GuestBillingAddressManagementInterface
+     */
+    protected $billingAddressManagement;
+
+    /**
+     * @var \Magento\Quote\Api\GuestPaymentMethodManagementInterface
+     */
+    protected $paymentMethodManagement;
+
+    /**
+     * @var \Magento\Quote\Api\GuestCartManagementInterface
+     */
+    protected $cartManagement;
+
+    /**
+     * @param \Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement
+     * @param \Magento\Quote\Api\GuestPaymentMethodManagementInterface $paymentMethodManagement
+     * @param \Magento\Quote\Api\GuestCartManagementInterface $cartManagement
+     */
+    public function __construct(
+        \Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement,
+        \Magento\Quote\Api\GuestPaymentMethodManagementInterface $paymentMethodManagement,
+        \Magento\Quote\Api\GuestCartManagementInterface $cartManagement
+    ) {
+        $this->billingAddressManagement = $billingAddressManagement;
+        $this->paymentMethodManagement = $paymentMethodManagement;
+        $this->cartManagement = $cartManagement;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function savePaymentInformationAndPlaceOrder(
+        $cartId,
+        $email,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    ) {
+        $this->savePaymentInformation($cartId, $email, $paymentMethod, $billingAddress);
+        return $this->cartManagement->placeOrder($cartId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function savePaymentInformation(
+        $cartId,
+        $email,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    ) {
+        $billingAddress->setEmail($email);
+        $this->billingAddressManagement->assign($cartId, $billingAddress);
+        $this->paymentMethodManagement->set($cartId, $paymentMethod);
+        return true;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php b/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..475bc915bf90ce15e48972dcc03979a02abc3a55
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model;
+
+class GuestShippingInformationManagement implements \Magento\Checkout\Api\GuestShippingInformationManagementInterface
+{
+    /**
+     * @var \Magento\Quote\Model\QuoteIdMaskFactory
+     */
+    protected $quoteIdMaskFactory;
+
+    /**
+     * @var ShippingInformationManagement
+     */
+    protected $shippingInformationManagement;
+
+    /**
+     * @param \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory
+     * @param ShippingInformationManagement $shippingInformationManagement
+     */
+    public function __construct(
+        \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory,
+        \Magento\Checkout\Model\ShippingInformationManagement $shippingInformationManagement
+    ) {
+        $this->quoteIdMaskFactory = $quoteIdMaskFactory;
+        $this->shippingInformationManagement = $shippingInformationManagement;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function saveAddressInformation(
+        $cartId,
+        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+    ) {
+        /** @var $quoteIdMask \Magento\Quote\Model\QuoteIdMask */
+        $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
+        return $this->shippingInformationManagement->saveAddressInformation(
+            $quoteIdMask->getQuoteId(),
+            $addressInformation
+        );
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/PaymentDetails.php b/app/code/Magento/Checkout/Model/PaymentDetails.php
new file mode 100644
index 0000000000000000000000000000000000000000..add196487ae989ccc195e557ee3c6f5e3de7177e
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/PaymentDetails.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model;
+
+/**
+ * @codeCoverageIgnoreStart
+ */
+class PaymentDetails extends \Magento\Framework\Model\AbstractExtensibleModel implements
+    \Magento\Checkout\Api\Data\PaymentDetailsInterface
+{
+    /**
+     * @{inheritdoc}
+     */
+    public function getPaymentMethods()
+    {
+        return $this->getData(self::PAYMENT_METHODS);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    public function setPaymentMethods($paymentMethods)
+    {
+        return $this->setData(self::PAYMENT_METHODS, $paymentMethods);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    public function getTotals()
+    {
+        return $this->getData(self::TOTALS);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    public function setTotals($totals)
+    {
+        return $this->setData(self::TOTALS, $totals);
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @return \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface|null
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @param \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes
+    ) {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff4b973c6298e3b95265a2d121aa51bac501804f
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Model;
+
+class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInformationManagementInterface
+{
+
+    /**
+     * @var \Magento\Quote\Api\BillingAddressManagementInterface
+     */
+    protected $billingAddressManagement;
+
+    /**
+     * @var \Magento\Quote\Api\PaymentMethodManagementInterface
+     */
+    protected $paymentMethodManagement;
+
+    /**
+     * @var \Magento\Quote\Api\CartManagementInterface
+     */
+    protected $cartManagement;
+
+    /**
+     * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement
+     * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
+     * @param \Magento\Quote\Api\CartManagementInterface $cartManagement
+     */
+    public function __construct(
+        \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement,
+        \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement,
+        \Magento\Quote\Api\CartManagementInterface $cartManagement
+    ) {
+        $this->billingAddressManagement = $billingAddressManagement;
+        $this->paymentMethodManagement = $paymentMethodManagement;
+        $this->cartManagement = $cartManagement;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function savePaymentInformationAndPlaceOrder(
+        $cartId,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    ) {
+        $this->savePaymentInformation($cartId, $paymentMethod, $billingAddress);
+        return $this->cartManagement->placeOrder($cartId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function savePaymentInformation(
+        $cartId,
+        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
+        \Magento\Quote\Api\Data\AddressInterface $billingAddress
+    ) {
+        $this->billingAddressManagement->assign($cartId, $billingAddress);
+        $this->paymentMethodManagement->set($cartId, $paymentMethod);
+        return true;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/ShippingInformation.php b/app/code/Magento/Checkout/Model/ShippingInformation.php
new file mode 100644
index 0000000000000000000000000000000000000000..44d024c7171f587514efb03446cd2480f6b29364
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/ShippingInformation.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model;
+
+use Magento\Framework\Model\AbstractExtensibleModel;
+use Magento\Checkout\Api\Data\ShippingInformationInterface;
+
+/**
+ * @codeCoverageIgnoreStart
+ */
+class ShippingInformation extends AbstractExtensibleModel implements ShippingInformationInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getShippingAddress()
+    {
+        return $this->getData(self::SHIPPING_ADDRESS);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setShippingAddress(\Magento\Quote\Api\Data\AddressInterface $address)
+    {
+        return $this->setData(self::SHIPPING_ADDRESS, $address);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getShippingMethodCode()
+    {
+        return $this->getData(self::SHIPPING_METHOD_CODE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setShippingMethodCode($code)
+    {
+        return $this->setData(self::SHIPPING_METHOD_CODE, $code);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getShippingCarrierCode()
+    {
+        return $this->getData(self::SHIPPING_CARRIER_CODE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setShippingCarrierCode($code)
+    {
+        return $this->setData(self::SHIPPING_CARRIER_CODE, $code);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExtensionAttributes(
+        \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes
+    ) {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cf21372af8943caf46bafa3812898e5715c57d0
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php
@@ -0,0 +1,178 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model;
+
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\StateException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Psr\Log\LoggerInterface as Logger;
+use \Magento\Quote\Model\QuoteAddressValidator;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInformationManagementInterface
+{
+    /**
+     * @var \Magento\Quote\Api\PaymentMethodManagementInterface
+     */
+    protected $paymentMethodManagement;
+
+    /**
+     * @var PaymentDetailsFactory
+     */
+    protected $paymentDetailsFactory;
+
+    /**
+     * @var \Magento\Quote\Api\CartTotalRepositoryInterface
+     */
+    protected $cartTotalsRepository;
+
+    /**
+     * Quote repository.
+     *
+     * @var \Magento\Quote\Model\QuoteRepository
+     */
+    protected $quoteRepository;
+
+    /**
+     * Logger.
+     *
+     * @var Logger
+     */
+    protected $logger;
+
+    /**
+     * Validator.
+     *
+     * @var QuoteAddressValidator
+     */
+    protected $addressValidator;
+
+    /**
+     * @var \Magento\Customer\Api\AddressRepositoryInterface
+     */
+    protected $addressRepository;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
+     * @param \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory
+     * @param \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository
+     * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
+     * @param \Magento\Quote\Model\QuoteAddressValidator $addressValidator
+     * @param Logger $logger
+     * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository
+     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+     */
+    public function __construct(
+        \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement,
+        \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory,
+        \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository,
+        \Magento\Quote\Model\QuoteRepository $quoteRepository,
+        QuoteAddressValidator $addressValidator,
+        Logger $logger,
+        \Magento\Customer\Api\AddressRepositoryInterface $addressRepository,
+        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+    ) {
+        $this->paymentMethodManagement = $paymentMethodManagement;
+        $this->paymentDetailsFactory = $paymentDetailsFactory;
+        $this->cartTotalsRepository = $cartTotalsRepository;
+        $this->quoteRepository = $quoteRepository;
+        $this->addressValidator = $addressValidator;
+        $this->logger = $logger;
+        $this->addressRepository = $addressRepository;
+        $this->scopeConfig = $scopeConfig;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function saveAddressInformation(
+        $cartId,
+        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
+    ) {
+        $address = $addressInformation->getShippingAddress();
+        $carrierCode = $addressInformation->getShippingCarrierCode();
+        $methodCode = $addressInformation->getShippingMethodCode();
+
+        /** @var \Magento\Quote\Model\Quote $quote */
+        $quote = $this->quoteRepository->getActive($cartId);
+        if ($quote->isVirtual()) {
+            throw new NoSuchEntityException(
+                __('Cart contains virtual product(s) only. Shipping address is not applicable.')
+            );
+        }
+
+        if (0 == $quote->getItemsCount()) {
+            throw new InputException(__('Shipping method is not applicable for empty cart'));
+        }
+
+        $saveInAddressBook = $address->getSaveInAddressBook() ? 1 : 0;
+        $sameAsBilling = $address->getSameAsBilling() ? 1 : 0;
+        $customerAddressId = $address->getCustomerAddressId();
+        $this->addressValidator->validate($address);
+        $quote->setShippingAddress($address);
+        $address = $quote->getShippingAddress();
+
+        if ($customerAddressId) {
+            $addressData = $this->addressRepository->getById($customerAddressId);
+            $address = $quote->getShippingAddress()->importCustomerAddressData($addressData);
+        }
+        $address->setSameAsBilling($sameAsBilling);
+        $address->setSaveInAddressBook($saveInAddressBook);
+        $address->setCollectShippingRates(true);
+
+        if (!$address->getCountryId()) {
+            throw new StateException(__('Shipping address is not set'));
+        }
+
+        $address->setShippingMethod($carrierCode . '_' . $methodCode);
+
+        try {
+            $address->save();
+            $address->collectTotals();
+        } catch (\Exception $e) {
+            $this->logger->critical($e);
+            throw new InputException(__('Unable to save address. Please, check input data.'));
+        }
+
+        if (!$address->getShippingRateByCode($address->getShippingMethod())) {
+            throw new NoSuchEntityException(
+                __('Carrier with such method not found: %1, %2', $carrierCode, $methodCode)
+            );
+        }
+
+        if (!$quote->validateMinimumAmount($quote->getIsMultiShipping())) {
+            throw new InputException($this->scopeConfig->getValue(
+                'sales/minimum_order/error_message',
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                $quote->getStoreId()
+            ));
+        }
+
+        try {
+            $address->save();
+            $quote->collectTotals();
+            $this->quoteRepository->save($quote);
+        } catch (\Exception $e) {
+            $this->logger->critical($e);
+            throw new InputException(__('Unable to save shipping information. Please, check input data.'));
+        }
+
+        /** @var \Magento\Checkout\Api\Data\PaymentDetailsInterface $paymentDetails */
+        $paymentDetails = $this->paymentDetailsFactory->create();
+        $paymentDetails->setPaymentMethods($this->paymentMethodManagement->getList($cartId));
+        $paymentDetails->setTotals($this->cartTotalsRepository->get($cartId));
+        return $paymentDetails;
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/Type/Onepage.php b/app/code/Magento/Checkout/Model/Type/Onepage.php
index dae0433f518ad6d159a555a88a883ec78dc516cf..2f7b71dc698be94e4bb8a17ef81815e8611381d7 100644
--- a/app/code/Magento/Checkout/Model/Type/Onepage.php
+++ b/app/code/Magento/Checkout/Model/Type/Onepage.php
@@ -983,14 +983,18 @@ class Onepage
                 $redirectUrl
             )->setLastRealOrderId(
                 $order->getIncrementId()
+            )->setLastOrderStatus(
+                $order->getStatus()
             );
         }
 
         $this->_eventManager->dispatch(
             'checkout_submit_all_after',
-            ['order' => $order, 'quote' => $this->getQuote()]
+            [
+                'order' => $order,
+                'quote' => $this->getQuote()
+            ]
         );
-
         return $this;
     }
 
diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Onepage/SuccessTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Onepage/SuccessTest.php
index 919a4de1157f216db27acd8aa1b6f25520c3f956..54c8fee91f2c411fd470716906dc89087d403914 100644
--- a/app/code/Magento/Checkout/Test/Unit/Block/Onepage/SuccessTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Block/Onepage/SuccessTest.php
@@ -21,11 +21,6 @@ class SuccessTest extends \PHPUnit_Framework_TestCase
      */
     protected $orderConfig;
 
-    /**
-     * @var \Magento\Sales\Model\OrderFactory | \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $orderFactory;
-
     /**
      * @var \Magento\Checkout\Model\Session | \PHPUnit_Framework_MockObject_MockObject
      */
@@ -36,14 +31,19 @@ class SuccessTest extends \PHPUnit_Framework_TestCase
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
 
         $this->orderConfig = $this->getMock('Magento\Sales\Model\Order\Config', [], [], '', false);
-        $this->orderFactory = $this->getMock('Magento\Sales\Model\OrderFactory', ['create'], [], '', false);
-        $this->checkoutSession = $this->getMock('Magento\Checkout\Model\Session', ['getLastOrderId'], [], '', false);
+
+        $this->checkoutSession = $this->getMock(
+            'Magento\Checkout\Model\Session',
+            ['getLastOrderId', 'getLastRealOrderId', 'getLastOrderStatus'],
+            [],
+            '',
+            false
+        );
 
         $this->block = $objectManager->getObject(
             'Magento\Checkout\Block\Onepage\Success',
             [
                 'orderConfig' => $this->orderConfig,
-                'orderFactory' => $this->orderFactory,
                 'checkoutSession' => $this->checkoutSession
             ]
         );
@@ -74,28 +74,21 @@ class SuccessTest extends \PHPUnit_Framework_TestCase
     public function testToHtmlOrderVisibleOnFront(array $invisibleStatuses, $orderStatus, $expectedResult)
     {
         $orderId = 5;
-        $order = $this->getMock('Magento\Sales\Model\Order', ['getId', '__wakeup', 'load', 'getStatus'], [], '', false);
-
-        $order->expects($this->any())
-            ->method('load')
-            ->with($orderId)
-            ->will($this->returnValue($order));
-        $order->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue($orderId));
-        $order->expects($this->any())
-            ->method('getStatus')
-            ->will($this->returnValue($orderStatus));
+        $realOrderId = 100003332;
 
         $this->checkoutSession->expects($this->once())
             ->method('getLastOrderId')
             ->will($this->returnValue($orderId));
+        $this->checkoutSession->expects($this->once())
+            ->method('getLastRealOrderId')
+            ->will($this->returnValue($realOrderId));
+        $this->checkoutSession->expects($this->once())
+            ->method('getLastOrderStatus')
+            ->will($this->returnValue($orderStatus));
+
         $this->orderConfig->expects($this->any())
             ->method('getInvisibleOnFrontStatuses')
             ->will($this->returnValue($invisibleStatuses));
-        $this->orderFactory->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($order));
 
         $this->block->toHtml();
 
diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php
index f3a3f246ec1ee9acff0150dd74735d03a4be9dc5..5159d70026cbc5c902e6adc3c3b80d21e22ea64e 100644
--- a/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php
@@ -188,6 +188,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
         $this->basicStub($this->quoteMock, 'hasItems')->willReturn(true);
         $this->basicStub($this->quoteMock, 'getHasError')->willReturn(false);
         $this->basicStub($this->quoteMock, 'validateMinimumAmount')->willReturn(true);
+        $this->basicStub($this->sessionMock, 'isLoggedIn')->willReturn(true);
 
         //Expected outcomes
         $this->sessionMock->expects($this->once())->method('regenerateId');
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php b/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..29b91231adb10d532df997da73c74117859b5098
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Unit\Model\Cart;
+
+class ImageProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Checkout\Model\Cart\ImageProvider
+     */
+    public $model;
+
+    /**
+     * @var \PHPUnit_Framework_Mockobject_Mockobject | \Magento\Quote\Api\CartItemRepositoryInterface
+     */
+    protected $itemRepositoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_Mockobject_Mockobject | \Magento\Checkout\CustomerData\ItemPoolInterface
+     */
+    protected $itemPoolMock;
+
+    protected function setUp()
+    {
+        $this->itemRepositoryMock = $this->getMock('Magento\Quote\Api\CartItemRepositoryInterface', [], [], '', false);
+        $this->itemPoolMock = $this->getMock('Magento\Checkout\CustomerData\ItemPoolInterface', [], [], '', false);
+        $this->model = new \Magento\Checkout\Model\Cart\ImageProvider(
+            $this->itemRepositoryMock,
+            $this->itemPoolMock
+        );
+    }
+
+    public function testGetImages()
+    {
+        $cartId = 42;
+        $itemId = 74;
+        $itemData = ['product_image' => 'Magento.png', 'random' => '3.1415926535'];
+        $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false);
+        $itemMock->expects($this->once())->method('getItemId')->willReturn($itemId);
+
+        $expectedResult = [$itemId => $itemData['product_image']];
+
+        $this->itemRepositoryMock->expects($this->once())->method('getList')->with($cartId)->willReturn([$itemMock]);
+        $this->itemPoolMock->expects($this->once())->method('getItemData')->with($itemMock)->willReturn($itemData);
+
+        $this->assertEquals($expectedResult, $this->model->getImages($cartId));
+    }
+}
diff --git a/app/code/Magento/Checkout/etc/di.xml b/app/code/Magento/Checkout/etc/di.xml
index 42d589f77e2dc1d49c5bcfdb09b5f65c3fd331f3..085ff442d7f75790df42f626a68a4cc886154fb4 100644
--- a/app/code/Magento/Checkout/etc/di.xml
+++ b/app/code/Magento/Checkout/etc/di.xml
@@ -16,4 +16,10 @@
             <argument name="storage" xsi:type="object">Magento\Checkout\Model\Session\Storage</argument>
         </arguments>
     </type>
+    <preference for="Magento\Checkout\Api\GuestShippingInformationManagementInterface" type="Magento\Checkout\Model\GuestShippingInformationManagement" />
+    <preference for="Magento\Checkout\Api\ShippingInformationManagementInterface" type="Magento\Checkout\Model\ShippingInformationManagement" />
+    <preference for="Magento\Checkout\Api\Data\ShippingInformationInterface" type="Magento\Checkout\Model\ShippingInformation" />
+    <preference for="Magento\Checkout\Api\Data\PaymentDetailsInterface" type="Magento\Checkout\Model\PaymentDetails" />
+    <preference for="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" type="Magento\Checkout\Model\GuestPaymentInformationManagement" />
+    <preference for="Magento\Checkout\Api\PaymentInformationManagementInterface" type="Magento\Checkout\Model\PaymentInformationManagement" />
 </config>
diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml
index 3399782763bea132a2c807f956f6323ce84016c7..20f146cc353ce63add45e00f3fc083c28cdb2768 100644
--- a/app/code/Magento/Checkout/etc/frontend/di.xml
+++ b/app/code/Magento/Checkout/etc/frontend/di.xml
@@ -43,6 +43,7 @@
         <arguments>
             <argument name="layoutProcessors" xsi:type="array">
                 <item name="addressFormAttributes" xsi:type="object">Magento\Checkout\Block\Checkout\LayoutProcessor</item>
+                <item name="totalsSortOrder" xsi:type="object">Magento\Checkout\Block\Checkout\TotalsProcessor</item>
             </argument>
         </arguments>
     </type>
diff --git a/app/code/Magento/Checkout/etc/webapi.xml b/app/code/Magento/Checkout/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28598faec5913a1a3d30af16084b9a2ac0d64bf0
--- /dev/null
+++ b/app/code/Magento/Checkout/etc/webapi.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+
+    <!-- Managing shipping guest information -->
+    <route url="/V1/carts/:cartId/shipping-information" method="POST">
+        <service class="Magento\Checkout\Api\GuestShippingInformationManagementInterface" method="saveAddressInformation"/>
+        <resources>
+            <resource ref="anonymous" />
+        </resources>
+    </route>
+
+    <!-- Managing My shipping information -->
+    <route url="/V1/carts/mine/shipping-information" method="POST">
+        <service class="Magento\Checkout\Api\ShippingInformationManagementInterface" method="saveAddressInformation"/>
+        <resources>
+            <resource ref="self" />
+        </resources>
+        <data>
+            <parameter name="cartId" force="true">%cart_id%</parameter>
+        </data>
+    </route>
+    <!-- Guest place order with payment information saving -->
+    <route url="/V1/guest-carts/:cartId/payment-information" method="POST">
+        <service class="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" method="savePaymentInformationAndPlaceOrder"/>
+        <resources>
+            <resource ref="anonymous" />
+        </resources>
+    </route>
+    <!-- My place order with payment information saving -->
+    <route url="/V1/carts/mine/payment-information" method="POST">
+        <service class="Magento\Checkout\Api\PaymentInformationManagementInterface" method="savePaymentInformationAndPlaceOrder"/>
+        <resources>
+            <resource ref="self" />
+        </resources>
+        <data>
+            <parameter name="cartId" force="true">%cart_id%</parameter>
+        </data>
+    </route>
+
+    <!-- Managing payment guest information -->
+    <route url="/V1/guest-carts/:cartId/set-payment-information" method="POST">
+        <service class="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" method="savePaymentInformation"/>
+        <resources>
+            <resource ref="anonymous" />
+        </resources>
+    </route>
+    <!-- Managing My shipping information -->
+    <route url="/V1/carts/mine/set-payment-information" method="POST">
+        <service class="Magento\Checkout\Api\PaymentInformationManagementInterface" method="savePaymentInformation"/>
+        <resources>
+            <resource ref="self" />
+        </resources>
+        <data>
+            <parameter name="cartId" force="true">%cart_id%</parameter>
+        </data>
+    </route>
+</routes>
diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml
index 5db66984f7812e8bd62978befb585a2eaa8434f9..a40e65477410eef2cfebf8e9c39203ed88070605 100644
--- a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml
@@ -23,155 +23,233 @@
                         </item>
                         <item name="components" xsi:type="array">
                             <item name="checkout" xsi:type="array">
-                                <item name="component" xsi:type="string">Magento_Checkout/js/view/onepage</item>
+                                <item name="component" xsi:type="string">uiComponent</item>
+                                <item name="config" xsi:type="array">
+                                    <item name="template" xsi:type="string">Magento_Checkout/onepage</item>
+                                </item>
                                 <item name="children" xsi:type="array">
-                                    <item name="progress" xsi:type="array">
-                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/progress</item>
-                                        <item name="displayArea" xsi:type="string">progress</item>
+                                    <item name="errors" xsi:type="array">
+                                        <item name="sortOrder" xsi:type="string">0</item>
+                                        <item name="component" xsi:type="string">Magento_Ui/js/view/messages</item>
+                                        <item name="displayArea" xsi:type="string">messages</item>
+                                    </item>
+                                    <item name="authentication" xsi:type="array">
+                                        <item name="sortOrder" xsi:type="string">1</item>
+                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/authentication</item>
+                                        <item name="displayArea" xsi:type="string">authentication</item>
                                         <item name="children" xsi:type="array">
-                                            <item name="shipping" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item>
-                                                <item name="displayArea" xsi:type="string">shipping</item>
-                                            </item>
+                                        <!--Additional authentication fields-->
                                         </item>
                                     </item>
-                                    <item name="errors" xsi:type="array">
+                                    <item name="progressBar" xsi:type="array">
                                         <item name="sortOrder" xsi:type="string">0</item>
-                                        <item name="component" xsi:type="string">Magento_Ui/js/view/errors</item>
-                                        <item name="displayArea" xsi:type="string">errors</item>
+                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/progress-bar</item>
+                                        <item name="displayArea" xsi:type="string">progressBar</item>
                                     </item>
                                     <item name="steps" xsi:type="array">
                                         <item name="component" xsi:type="string">uiComponent</item>
                                         <item name="displayArea" xsi:type="string">steps</item>
                                         <item name="children" xsi:type="array">
-                                            <item name="authentication" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/authentication</item>
+                                            <item name="shipping-step" xsi:type="array">
+                                                <item name="component" xsi:type="string">uiComponent</item>
                                                 <item name="sortOrder" xsi:type="string">1</item>
                                                 <item name="children" xsi:type="array">
-                                                    <item name="before" xsi:type="array">
+                                                    <item name="step-config" xsi:type="array">
                                                         <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">before</item>
                                                         <item name="children" xsi:type="array">
-                                                            <!-- merge additional data before authentication here -->
+                                                            <item name="shipping-rates-validation" xsi:type="array">
+                                                                <item name="children" xsi:type="array">
+                                                                    <!--Step configuration components-->
+                                                                </item>
+                                                            </item>
                                                         </item>
                                                     </item>
-                                                </item>
-                                            </item>
-                                            <item name="billingAddress" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/billing-address</item>
-                                                <item name="provider" xsi:type="string">checkoutProvider</item>
-                                                <item name="sortOrder" xsi:type="string">2</item>
-                                                <item name="children" xsi:type="array">
-                                                    <item name="billing-address-fieldset" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">additional-fieldsets</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- The following items override configuration of corresponding address attributes -->
-                                                            <item name="region" xsi:type="array">
-                                                                <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field -->
-                                                                <item name="visible" xsi:type="boolean">false</item>
-                                                            </item>
-                                                            <item name="region_id" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="template" xsi:type="string">ui/form/field</item>
-                                                                    <item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
-                                                                    <item name="customEntry" xsi:type="string">billingAddress.region</item>
-                                                                </item>
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="validate-select" xsi:type="string">true</item>
-                                                                </item>
-                                                                <!-- Value of region_id field is filtered by the value of county_id attribute -->
-                                                                <item name="filterBy" xsi:type="array">
-                                                                    <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.country_id</item>
-                                                                    <item name="field" xsi:type="string">country_id</item>
+                                                    <item name="shippingAddress" xsi:type="array">
+                                                        <item name="config" xsi:type="array">
+                                                            <item name="deps" xsi:type="string">checkout.steps.shipping-step.step-config</item>
+                                                            <item name="popUpForm" xsi:type="array">
+                                                                <item name="element" xsi:type="string">#opc-new-shipping-address</item>
+                                                                <item name="options" xsi:type="array">
+                                                                    <item name="type" xsi:type="string">popup</item>
+                                                                    <item name="responsive" xsi:type="boolean">true</item>
+                                                                    <item name="innerScroll" xsi:type="boolean">true</item>
+                                                                    <item name="title" xsi:type="string">Shipping Address</item>
+                                                                    <item name="trigger" xsi:type="string">opc-new-shipping-address</item>
+                                                                    <item name="buttons" xsi:type="array">
+                                                                        <item name="save" xsi:type="array">
+                                                                            <item name="text" xsi:type="string">Save Address</item>
+                                                                            <item name="class" xsi:type="string">action primary action-save-address</item>
+                                                                        </item>
+                                                                        <item name="cancel" xsi:type="array">
+                                                                            <item name="text" xsi:type="string">Cancel</item>
+                                                                            <item name="class" xsi:type="string">action secondary action-hide-popup</item>
+                                                                        </item>
+                                                                    </item>
                                                                 </item>
                                                             </item>
-                                                            <item name="postcode" xsi:type="array">
-                                                                <!-- post-code field has custom UI component -->
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item>
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="required-entry" xsi:type="string">true</item>
+                                                        </item>
+                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping</item>
+                                                        <item name="provider" xsi:type="string">checkoutProvider</item>
+                                                        <item name="sortOrder" xsi:type="string">1</item>
+                                                        <item name="children" xsi:type="array">
+                                                            <item name="customer-email" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Customer/js/view/customer-email</item>
+                                                                <item name="displayArea" xsi:type="string">customer-email</item>
+                                                                <item name="tooltip" xsi:type="array">
+                                                                    <item name="description" xsi:type="string">We'll send your order confirmation here.</item>
+                                                                </item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <item name="before-login-form" xsi:type="array">
+                                                                        <item name="component" xsi:type="string">uiComponent</item>
+                                                                        <item name="displayArea" xsi:type="string">before-login-form</item>
+                                                                        <item name="children" xsi:type="array">
+                                                                            <!-- before login form fields -->
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="additional-login-form-fields" xsi:type="array">
+                                                                        <item name="component" xsi:type="string">uiComponent</item>
+                                                                        <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                                                        <item name="children" xsi:type="array">
+                                                                            <!-- additional login form fields -->
+                                                                        </item>
+                                                                    </item>
                                                                 </item>
                                                             </item>
-                                                            <item name="company" xsi:type="array">
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="min_text_length" xsi:type="number">0</item>
+                                                            <item name="before-form" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">before-form</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- before form fields -->
                                                                 </item>
                                                             </item>
-                                                            <item name="fax" xsi:type="array">
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="min_text_length" xsi:type="number">0</item>
+                                                            <item name="before-fields" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">before-fields</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- before fields -->
                                                                 </item>
                                                             </item>
-                                                            <item name="country_id" xsi:type="array">
-                                                                <item name="sortOrder" xsi:type="string">115</item>
+                                                            <item name="address-list" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-address/list</item>
+                                                                <item name="displayArea" xsi:type="string">address-list</item>
                                                             </item>
-                                                            <!-- The following items describe fields that are not directly related to address but must be shown in address form -->
-                                                            <item name="email" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="template" xsi:type="string">ui/form/field</item>
-                                                                    <item name="elementTmpl" xsi:type="string">ui/form/element/email</item>
-                                                                    <item name="customScope" xsi:type="string">customerDetails</item>
+                                                            <item name="address-list-additional-addresses" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">address-list-additional-addresses</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- address-list-additional-addresses -->
                                                                 </item>
-                                                                <item name="label" xsi:type="string">Email</item>
-                                                                <item name="dataScope" xsi:type="string">customerDetails.email</item>
-                                                                <item name="provider" xsi:type="string">checkoutProvider</item>
-                                                                <item name="sortOrder" xsi:type="string">45</item>
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="required-entry" xsi:type="boolean">true</item>
-                                                                    <item name="validate-email" xsi:type="boolean">true</item>
+                                                              </item>
+                                                            <item name="before-shipping-method-form" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">before-shipping-method-form</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- address-list-additional-addresses -->
                                                                 </item>
                                                             </item>
-                                                            <item name="save_in_address_book" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="template" xsi:type="string">ui/form/field</item>
-                                                                    <item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item>
+                                                            <item name="shipping-address-fieldset" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">additional-fieldsets</item>
+                                                                <item name="children" xsi:type="array">
+                                                                     <!-- The following items override configuration of corresponding address attributes -->
+                                                                    <item name="region" xsi:type="array">
+                                                                        <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field -->
+                                                                        <item name="visible" xsi:type="boolean">false</item>
+                                                                    </item>
+                                                                    <item name="region_id" xsi:type="array">
+                                                                        <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item>
+                                                                        <item name="config" xsi:type="array">
+                                                                            <item name="template" xsi:type="string">ui/form/field</item>
+                                                                            <item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
+                                                                            <item name="customEntry" xsi:type="string">shippingAddress.region</item>
+                                                                        </item>
+                                                                        <item name="validation" xsi:type="array">
+                                                                            <item name="validate-select" xsi:type="string">true</item>
+                                                                        </item>
+                                                                        <!-- Value of region_id field is filtered by the value of county_id attribute -->
+                                                                        <item name="filterBy" xsi:type="array">
+                                                                            <item name="target" xsi:type="string"><![CDATA[${ $.provider }:${ $.parentScope }.country_id]]></item>
+                                                                            <item name="field" xsi:type="string">country_id</item>
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="postcode" xsi:type="array">
+                                                                        <!-- post-code field has custom UI component -->
+                                                                        <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item>
+                                                                        <item name="validation" xsi:type="array">
+                                                                            <item name="required-entry" xsi:type="string">true</item>
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="company" xsi:type="array">
+                                                                        <item name="validation" xsi:type="array">
+                                                                            <item name="min_text_length" xsi:type="number">0</item>
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="fax" xsi:type="array">
+                                                                        <item name="validation" xsi:type="array">
+                                                                            <item name="min_text_length" xsi:type="number">0</item>
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="country_id" xsi:type="array">
+                                                                        <item name="sortOrder" xsi:type="string">115</item>
+                                                                    </item>
+                                                                    <item name="telephone" xsi:type="array">
+                                                                        <item name="config" xsi:type="array">
+                                                                            <item name="tooltip" xsi:type="array">
+                                                                                <item name="description" xsi:type="string">For delivery Questions</item>
+                                                                            </item>
+                                                                        </item>
+                                                                    </item>
                                                                 </item>
-                                                                <item name="description" xsi:type="string">Save in address book</item>
-                                                                <item name="provider" xsi:type="string">checkoutProvider</item>
-                                                                <item name="dataScope" xsi:type="string">billingAddress.save_in_address_book</item>
                                                             </item>
                                                         </item>
                                                     </item>
-                                                    <item name="billing-address-choice" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">additional-field-choice</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- this region for different choice -->
-                                                        </item>
-                                                    </item>
                                                 </item>
                                             </item>
-                                            <item name="shippingAddress" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-address</item>
-                                                <item name="provider" xsi:type="string">checkoutProvider</item>
-                                                <item name="sortOrder" xsi:type="string">3</item>
+                                            <item name="billing-step" xsi:type="array">
+                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                <item name="sortOrder" xsi:type="string">2</item>
                                                 <item name="children" xsi:type="array">
-                                                    <item name="before-fields" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">before-fields</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- before fields -->
+                                                    <item name="payment" xsi:type="array">
+                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/payment</item>
+                                                        <item name="config" xsi:type="array">
+                                                            <item name="title" xsi:type="string">Payment</item>
                                                         </item>
-                                                    </item>
-                                                    <item name="shipping-address-fieldset" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">additional-fieldsets</item>
                                                         <item name="children" xsi:type="array">
-                                                            <!-- The following items override configuration of corresponding address attributes -->
-                                                            <item name="region" xsi:type="array">
-                                                                <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field -->
-                                                                <item name="visible" xsi:type="boolean">false</item>
+                                                            <item name="renders" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- merge payment method renders here -->
+                                                                </item>
                                                             </item>
-                                                            <item name="region_id" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="template" xsi:type="string">ui/form/field</item>
-                                                                    <item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
-                                                                    <item name="customEntry" xsi:type="string">shippingAddress.region</item>
+                                                            <item name="customer-email" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Customer/js/view/customer-email</item>
+                                                                <item name="displayArea" xsi:type="string">customer-email</item>
+                                                                <item name="tooltip" xsi:type="array">
+                                                                    <item name="description" xsi:type="string">(You can create an account to track your order after checkout)</item>
+                                                                </item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <item name="before-login-form" xsi:type="array">
+                                                                        <item name="component" xsi:type="string">uiComponent</item>
+                                                                        <item name="displayArea" xsi:type="string">before-login-form</item>
+                                                                        <item name="children" xsi:type="array">
+                                                                            <!-- before login form fields -->
+                                                                        </item>
+                                                                    </item>
+                                                                    <item name="additional-login-form-fields" xsi:type="array">
+                                                                        <item name="component" xsi:type="string">uiComponent</item>
+                                                                        <item name="displayArea" xsi:type="string">additional-login-form-fields</item>
+                                                                        <item name="children" xsi:type="array">
+                                                                            <!-- additional login form fields -->
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
+                                                            </item>
+                                                            <!-- TODO: add billing address form -->
+                                                            <item name="beforeMethods" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">beforeMethods</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- merge additional data before payment methods here -->
                                                                 </item>
                                                                 <item name="validation" xsi:type="array">
                                                                     <item name="validate-select" xsi:type="string">true</item>
@@ -182,135 +260,107 @@
                                                                     <item name="field" xsi:type="string">country_id</item>
                                                                 </item>
                                                             </item>
-                                                            <item name="postcode" xsi:type="array">
-                                                                <!-- post-code field has custom UI component -->
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item>
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="required-entry" xsi:type="string">true</item>
-                                                                </item>
-                                                            </item>
-                                                            <item name="company" xsi:type="array">
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="min_text_length" xsi:type="number">0</item>
+                                                            <item name="payments-list" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/payment/list</item>
+                                                                <item name="displayArea" xsi:type="string">payment-methods-list</item>
+                                                                <item name="config" xsi:type="array">
+                                                                    <item name="deps" xsi:type="string">checkout.steps.billing-step.payment.renders</item>
                                                                 </item>
                                                             </item>
-                                                            <item name="fax" xsi:type="array">
-                                                                <item name="validation" xsi:type="array">
-                                                                    <item name="min_text_length" xsi:type="number">0</item>
+                                                            <!-- merge your payment methods here -->
+                                                            <item name="afterMethods" xsi:type="array">
+                                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                                <item name="displayArea" xsi:type="string">afterMethods</item>
+                                                                <item name="children" xsi:type="array">
+                                                                    <!-- merge additional data after payment methods here -->
                                                                 </item>
                                                             </item>
-                                                            <item name="country_id" xsi:type="array">
-                                                                <item name="sortOrder" xsi:type="string">115</item>
-                                                            </item>
-                                                            <item name="save_in_address_book" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="template" xsi:type="string">ui/form/field</item>
-                                                                    <item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item>
-                                                                </item>
-                                                                <item name="description" xsi:type="string">Save in address book</item>
-                                                                <item name="provider" xsi:type="string">checkoutProvider</item>
-                                                                <item name="dataScope" xsi:type="string">shippingAddress.save_in_address_book</item>
-                                                            </item>
                                                         </item>
                                                     </item>
                                                 </item>
                                             </item>
-                                            <item name="shipping" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-method</item>
-                                                <item name="sortOrder" xsi:type="string">4</item>
-                                                <item name="additional" xsi:type="array">
-                                                    <!-- merge your shipping methods here -->
+                                        </item>
+                                    </item>
+                                    <item name="summary" xsi:type="array">
+                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/summary</item>
+                                        <item name="displayArea" xsi:type="string">summary</item>
+                                        <item name="config" xsi:type="array">
+                                            <item name="template" xsi:type="string">Magento_Checkout/summary</item>
+                                        </item>
+                                        <item name="children" xsi:type="array">
+                                            <item name="totals" xsi:type="array">
+                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                <item name="displayArea" xsi:type="string">totals</item>
+                                                <item name="config" xsi:type="array">
+                                                    <item name="template" xsi:type="string">Magento_Checkout/summary/totals</item>
                                                 </item>
                                                 <item name="children" xsi:type="array">
-                                                    <item name="afterSelect" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">afterSelect</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge additional data after shipping methods here -->
+                                                    <!-- sort order for this totals is configured on admin panel-->
+                                                    <!-- Stores->Configuration->SALES->Sales->General->Checkout Totals Sort Order -->
+                                                    <item name="subtotal" xsi:type="array">
+                                                        <item name="component"  xsi:type="string">Magento_Checkout/js/view/summary/subtotal</item>
+                                                        <item name="config" xsi:type="array">
+                                                            <item name="title" xsi:type="string">Cart Subtotal</item>
                                                         </item>
                                                     </item>
-                                                </item>
-                                            </item>
-                                            <item name="payment" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/payment</item>
-                                                <item name="sortOrder" xsi:type="string">5</item>
-                                                <item name="children" xsi:type="array">
-                                                    <item name="beforeMethods" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">beforeMethods</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge additional data before payment methods here -->
+                                                    <item name="shipping" xsi:type="array">
+                                                        <item name="component"  xsi:type="string">Magento_Checkout/js/view/summary/shipping</item>
+                                                        <item name="config" xsi:type="array">
+                                                            <item name="title" xsi:type="string">Shipping</item>
+                                                            <item name="notCalculatedMessage" xsi:type="string">Not yet calculated</item>
                                                         </item>
                                                     </item>
-                                                    <!-- merge your payment methods here -->
-                                                    <item name="afterMethods" xsi:type="array">
-                                                        <item name="component" xsi:type="string">uiComponent</item>
-                                                        <item name="displayArea" xsi:type="string">afterMethods</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge additional data after payment methods here -->
+                                                    <item name="grand-total" xsi:type="array">
+                                                        <item name="component"  xsi:type="string">Magento_Checkout/js/view/summary/grand-total</item>
+                                                        <item name="config" xsi:type="array">
+                                                            <item name="title" xsi:type="string">Order Total</item>
                                                         </item>
                                                     </item>
                                                 </item>
                                             </item>
-                                            <item name="review" xsi:type="array">
-                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/review</item>
-                                                <item name="sortOrder" xsi:type="string">6</item>
+                                            <item name="itemsBefore" xsi:type="array">
+                                                <item name="component" xsi:type="string">uiComponent</item>
                                                 <item name="children" xsi:type="array">
-                                                    <item name="columns" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <item name="name" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/name</item></item>
-                                                            <item name="price" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/price</item></item>
-                                                            <item name="qty" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/qty</item></item>
-                                                            <item name="subtotal" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/subtotal</item></item>
-                                                        </item>
-                                                    </item>
-                                                    <item name="itemsBefore" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/itemsBefore</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge your components here -->
-                                                        </item>
-                                                    </item>
-                                                    <item name="itemsAfter" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/itemsAfter</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge your components here -->
-                                                        </item>
-                                                    </item>
-                                                    <item name="beforePlaceOrder" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/beforePlaceOrder</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <!-- merge your components here -->
-                                                        </item>
-                                                    </item>
-                                                    <item name="totals" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/totals</item>
+                                                    <!-- merge your components here -->
+                                                </item>
+                                            </item>
+                                            <item name="cart_items" xsi:type="array">
+                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/cart-items</item>
+                                                <item name="children" xsi:type="array">
+                                                    <item name="details" xsi:type="array">
+                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details</item>
                                                         <item name="children" xsi:type="array">
-                                                            <item name="subtotal" xsi:type="array">
-                                                                <item name="component"  xsi:type="string">Magento_Checkout/js/view/subtotal</item>
-                                                            </item>
-                                                            <item name="discount" xsi:type="array">
-                                                                <item name="component"  xsi:type="string">Magento_Checkout/js/view/discount</item>
+                                                            <item name="thumbnail" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/thumbnail</item>
+                                                                <item name="displayArea" xsi:type="string">before_details</item>
                                                             </item>
-                                                        </item>
-                                                    </item>
-                                                    <item name="actions" xsi:type="array">
-                                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/review/actions</item>
-                                                        <item name="children" xsi:type="array">
-                                                            <item name="@default" xsi:type="array">
-                                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/review/actions/default</item>
-                                                                <item name="config" xsi:type="array">
-                                                                    <item name="isDefault" xsi:type="boolean">true</item>
-                                                                </item>
+                                                            <item name="subtotal" xsi:type="array">
+                                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/subtotal</item>
+                                                                <item name="displayArea" xsi:type="string">after_details</item>
                                                             </item>
-                                                            <!-- merge your components here -->
                                                         </item>
                                                     </item>
+
+                                                </item>
+                                            </item>
+                                            <item name="itemsAfter" xsi:type="array">
+                                                <item name="component" xsi:type="string">uiComponent</item>
+                                                <item name="children" xsi:type="array">
+                                                    <!-- merge your components here -->
                                                 </item>
                                             </item>
                                         </item>
                                     </item>
+                                    <item name="shipping-information" xsi:type="array">
+                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-information</item>
+                                        <item name="displayArea" xsi:type="string">shipping-information</item>
+                                        <item name="children" xsi:type="array">
+                                            <item name="ship-to" xsi:type="array">
+                                                <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-information/list</item>
+                                                <item name="displayArea" xsi:type="string">ship-to</item>
+                                            </item>
+                                        </item>
+                                    </item>
                                 </item>
                             </item>
                             <item name="checkoutProvider" xsi:type="array">
@@ -321,5 +371,6 @@
                 </arguments>
             </block>
         </referenceContainer>
+        <remove name="page.messages" />
     </body>
 </page>
diff --git a/app/code/Magento/Checkout/view/frontend/layout/default.xml b/app/code/Magento/Checkout/view/frontend/layout/default.xml
index 2ac27890ca18a2a79b604c647abe24eb95f14625..da1007040f6a19ab02d2f794b2df8ac4e93df719 100644
--- a/app/code/Magento/Checkout/view/frontend/layout/default.xml
+++ b/app/code/Magento/Checkout/view/frontend/layout/default.xml
@@ -51,6 +51,19 @@
                                             <item name="displayArea" xsi:type="string">promotion</item>
                                         </item>
                                     </item>
+                                    <item name="sign-in-popup" xsi:type="array">
+                                        <item name="component" xsi:type="string">Magento_Checkout/js/view/cart/authentication</item>
+                                        <item name="config" xsi:type="array">
+                                            <item name="displayArea" xsi:type="string">sign-in-popup</item>
+                                            <item name="template" xsi:type="string">Magento_Checkout/cart/authentication</item>
+                                        </item>
+                                        <item name="children" xsi:type="array">
+                                            <item name="messages" xsi:type="array">
+                                                <item name="component" xsi:type="string">Magento_Ui/js/view/messages</item>
+                                                <item name="displayArea" xsi:type="string">messages</item>
+                                            </item>
+                                        </item>
+                                    </item>
                                 </item>
                             </item>
                         </item>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
index d515d34169278ca83c7d361c5e43fcd51f9840ae..6d08bcb4bbf500ef2f823c46e8074640099f07d6 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
@@ -42,18 +42,15 @@
         </div>
     <?php endif ?>
     <script>
-        window.checkout = {
-            shoppingCartUrl: '<?=$block->getShoppingCartUrl()?>',
-            checkoutUrl: '<?=$block->getCheckoutUrl()?>',
-            updateItemQtyUrl: '<?=$block->getUpdateItemQtyUrl()?>',
-            removeItemUrl: '<?=$block->getRemoveItemUrl()?>',
-            imageTemplate: '<?= $block->getImageHtmlTemplate()?>'
-        };
+        window.checkout = <?php echo \Zend_Json::encode($block->getConfig()); ?>;
     </script>
     <script type="text/x-magento-init">
     {
         "[data-block='minicart']": {
             "Magento_Ui/js/core/app": <?php echo $block->getJsLayout();?>
+        },
+        "*": {
+            "Magento_Ui/js/block-loader": "<?php echo $block->getViewFileUrl('images/loader-1.gif'); ?>"
         }
     }
     </script>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml
index 7e8fe0c43edb0dd18ac6ac63ceae182267a1de08..1f05ef68ff3a41b882e7342dc6c271ea2a9eb670 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 ?>
-    <div id="checkout" data-bind="scope:'checkout'">
+    <div id="checkout" data-bind="scope:'checkout'" class="checkout-container">
         <!-- ko template: getTemplate() --><!-- /ko -->
         <script type="text/x-magento-init">
             {
@@ -20,8 +20,13 @@
             window.customerData = window.checkoutConfig.customerData;
         </script>
         <script>
-            require(['mage/url', 'Magento_Checkout/js/model/step-loader'], function(url, loader) {
+            require([
+                'mage/url',
+                'Magento_Checkout/js/model/step-loader',
+                'Magento_Ui/js/block-loader'
+            ], function(url, loader, blockLoader) {
                 loader.registerLoader();
+                blockLoader("<?php echo $block->getViewFileUrl('images/loader-1.gif'); ?>");
                 return url.setBaseUrl('<?php echo $block->getBaseUrl();?>');
             })
         </script>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml
index 25d144d746d4a42020cce13217abb4b831e90d81..72b8a5bf5023ad578385467538fdb88299bce81e 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml
@@ -5,18 +5,14 @@
  */
 
 // @codingStandardsIgnoreFile
-
-/**
- * @deprecated
- * @removeCandidate
- */
 ?>
 <?php if ($block->isPossibleOnepageCheckout()):?>
     <button type="button"
+            data-role="proceed-to-checkout"
             title="<?php echo __('Proceed to Checkout') ?>"
+            data-mage-init='{"Magento_Checkout/js/proceed-to-checkout":{}}'
             class="action primary checkout<?php echo($block->isDisabled()) ? ' disabled' : ''; ?>"
-            <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?>
-            onclick="window.location='<?php echo $block->getCheckoutUrl() ?>';">
-                <span><?php echo __('Proceed to Checkout') ?></span>
+            <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?>>
+        <span><?php echo __('Proceed to Checkout') ?></span>
     </button>
 <?php endif?>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js
new file mode 100644
index 0000000000000000000000000000000000000000..a48f92659f46a3f0d2d8bb76d5cb2920182643be
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js
@@ -0,0 +1,17 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/model/address-converter'
+    ],
+    function(addressConverter) {
+        "use strict";
+        return function(addressData) {
+            var address = addressConverter.formAddressDataToQuoteAddress(addressData);
+            return address;
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js
new file mode 100644
index 0000000000000000000000000000000000000000..d4225a3166057fabbcc83ebf01530ffae7601167
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Customer/js/model/address-list',
+        'Magento_Checkout/js/model/address-converter'
+    ],
+    function(addressList, addressConverter) {
+        "use strict";
+        return function(addressData) {
+            var address = addressConverter.formAddressDataToQuoteAddress(addressData);
+            var isAddressUpdated = addressList().some(function(currentAddress, index, addresses) {
+                if (currentAddress.getKey() == address.getKey()) {
+                    addresses[index] = address;
+                    return true;
+                }
+                return false;
+            });
+            if (!isAddressUpdated) {
+                addressList.push(address);
+            } else {
+                addressList.valueHasMutated();
+            }
+            return address;
+        };
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js b/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js
new file mode 100644
index 0000000000000000000000000000000000000000..57524a7cb404576bc19da11b30b54452833f5ab9
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js
@@ -0,0 +1,47 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/*global define,alert*/
+define(
+    [
+        'jquery',
+        '../model/quote',
+        'Magento_Checkout/js/model/resource-url-manager',
+        'Magento_Ui/js/model/messageList',
+        'mage/storage',
+        'Magento_Checkout/js/model/totals'
+    ],
+    function ($, quote, resourceUrlManager, messageList, storage, totals) {
+        "use strict";
+        return function (callbacks, deferred) {
+            deferred = deferred || $.Deferred();
+            totals.isLoading(true);
+            return storage.get(
+                resourceUrlManager.getUrlForCartTotals(quote),
+                false
+            ).done(
+                function (response) {
+                    totals.isLoading(false);
+                    var proceed = true;
+                    $.each(callbacks, function(index, callback) {
+                        proceed = proceed && callback();
+                    });
+                    if (proceed) {
+                        quote.setTotals(response);
+                        deferred.resolve();
+                    }
+                }
+            ).error(
+                function (response) {
+                    totals.isLoading(false);
+                    var error = JSON.parse(response.responseText);
+                    messageList.addErrorMessage(error);
+                    deferred.reject();
+                }
+            );
+
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
index ee6bf6d67d3396bf764b2f39ac1c275ab464b1f5..eabe01078de5e0bbeb9a788c30c21f6e313977ec 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
@@ -2,48 +2,56 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*global define*/
 define(
     [
-        '../model/quote',
-        '../model/url-builder',
-        '../model/payment-service',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/url-builder',
         'mage/storage',
         'mage/url',
-        'Magento_Ui/js/model/errorlist',
+        'Magento_Ui/js/model/messageList',
         'Magento_Customer/js/model/customer',
         'underscore'
     ],
-    function(quote, urlBuilder, paymentService, storage, url, errorList, customer, _) {
-        "use strict";
-        return function(customParams, callback) {
-            var payload;
-            customParams = customParams || {
-                cartId: quote.getQuoteId(),
-                paymentMethod: paymentService.getSelectedPaymentData()
-            };
+    function (quote, urlBuilder, storage, url, messageList, customer, _) {
+        'use strict';
+
+        return function (paymentData, redirectOnSuccess) {
+            var serviceUrl, payload;
+
+            redirectOnSuccess = redirectOnSuccess === false ? false : true;
             /**
              * Checkout for guest and registered customer.
              */
-            var serviceUrl;
-            if (quote.getCheckoutMethod()() === 'guest') {
-                serviceUrl =  urlBuilder.createUrl('/guest-carts/:quoteId/order', {quoteId: quote.getQuoteId()});
+            if (!customer.isLoggedIn()) {
+                serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/payment-information', {
+                    quoteId: quote.getQuoteId()
+                });
+                payload = {
+                    cartId: quote.getQuoteId(),
+                    email: quote.guestEmail,
+                    paymentMethod: paymentData,
+                    billingAddress: quote.billingAddress()
+                };
             } else {
-                serviceUrl = urlBuilder.createUrl('/carts/mine/order', {});
+                serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {});
+                payload = {
+                    cartId: quote.getQuoteId(),
+                    paymentMethod: paymentData,
+                    billingAddress: quote.billingAddress()
+                };
             }
-            payload = customParams;
-            storage.put(
+            storage.post(
                 serviceUrl, JSON.stringify(payload)
             ).done(
-                function() {
-                    if (!_.isFunction(callback) || callback()) {
+                function () {
+                    if (redirectOnSuccess) {
                         window.location.replace(url.build('checkout/onepage/success/'));
                     }
                 }
             ).fail(
-                function(response) {
+                function (response) {
                     var error = JSON.parse(response.responseText);
-                    errorList.add(error);
+                    messageList.addErrorMessage(error);
                 }
             );
         };
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js
index 635f6797f40750b26511d8c686c4227b7420b433..da290fc1aa214d38d38deb8ca5b68805e66962f5 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js
@@ -2,88 +2,15 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true*/
-/*global define, alert*/
+/*global define*/
 define(
     [
-        '../model/quote',
-        '../model/addresslist',
-        '../model/step-navigator',
-        './select-shipping-address',
-        'uiRegistry',
-        '../model/url-builder',
-        'mage/storage',
-        '../model/payment-service',
-        'underscore'
+        '../model/quote'
     ],
-    function (quote, addressList, navigator, selectShippingAddress, registry, urlBuilder, storage, paymentService, _) {
+    function(quote) {
         "use strict";
-        var actionCallback;
-        var result = function (billingAddress, useForShipping, additionalData) {
-            var copyBillingToShipping = function() {
-                var shippingAddressSource = registry.get('checkoutProvider'),
-                    shippingAddress = shippingAddressSource.get('shippingAddress');
-                for (var property in billingAddress) {
-                    if (billingAddress.hasOwnProperty(property) && shippingAddress.hasOwnProperty(property)) {
-                        if (typeof billingAddress[property] === 'string') {
-                            shippingAddressSource.set('shippingAddress.' + property, billingAddress[property]);
-                        } else {
-                            shippingAddressSource.set('shippingAddress.' + property, _.clone(billingAddress[property]));
-                        }
-                    }
-                }
-            };
-            additionalData = additionalData || {};
-            quote.setBillingAddress(billingAddress);
-            if (useForShipping() === '1' && !quote.isVirtual()) {
-                if (!billingAddress.customerAddressId) {
-                    copyBillingToShipping();
-                }
-                selectShippingAddress(billingAddress, useForShipping, additionalData);
-            } else if (quote.isVirtual()) {
-                var serviceUrl;
-                if (quote.getCheckoutMethod()() === 'guest') {
-                    serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/addresses', {quoteId: quote.getQuoteId()});
-                } else {
-                    serviceUrl = urlBuilder.createUrl('/carts/mine/addresses', {});
-                }
-                storage.post(
-                    serviceUrl,
-                    JSON.stringify({
-                        billingAddress: quote.getBillingAddress()(),
-                        additionalData: {extensionAttributes : additionalData},
-                        checkoutMethod: quote.getCheckoutMethod()()
-                    })
-                ).done(
-                    function (result) {
-                        paymentService.setPaymentMethods(result.payment_methods);
-                        quote.setFormattedBillingAddress(result.formatted_billing_address);
-                        quote.setTotals(result.totals);
-                        navigator.setCurrent('billingAddress').goNext();
-                        if (typeof actionCallback == 'function') {
-                            actionCallback(true);
-                        }
-                    }
-                ).fail(
-                    function (response) {
-                        var error = JSON.parse(response.responseText);
-                        errorList.add(error);
-                        quote.setBillingAddress(null);
-                        if (typeof actionCallback == 'function') {
-                            actionCallback(false);
-                        }
-                    }
-                );
-            } else {
-                navigator.setCurrent('billingAddress').goNext();
-                if (addressList.isBillingSameAsShipping) {
-                    copyBillingToShipping();
-                }
-            }
+        return function(billingAddress) {
+            quote.billingAddress(billingAddress);
         };
-        result.setActionCallback = function (value) {
-            actionCallback = value;
-        };
-        return result;
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
index f0fe5a55aa3af0016a1a4e78dd15d7ae66295400..c6d9c56528efb47d0364a769b3a0a56d7d2d0016 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
@@ -5,96 +5,12 @@
 /*global define*/
 define(
     [
-        '../model/quote',
-        '../model/url-builder',
-        '../model/step-navigator',
-        '../model/payment-service',
-        'Magento_Ui/js/model/errorlist',
-        'mage/storage',
-        'underscore'
+        '../model/quote'
     ],
-    function(quote, urlBuilder, navigator, service, errorList, storage, _) {
-        "use strict";
-        return function (methodData, methodInfo, callbacks) {
-            var paymentMethodData = {
-                "cartId": quote.getQuoteId(),
-                "paymentMethod": methodData
-            };
-
-            var shippingMethodCode = quote.getSelectedShippingMethod()().slice(0).split("_"),
-                shippingMethodData = {
-                    "shippingCarrierCode" : shippingMethodCode.shift(),
-                    "shippingMethodCode" : shippingMethodCode.join('_')
-                },
-                serviceUrl;
-            if (quote.getCheckoutMethod()() === 'guest') {
-                serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/collect-totals', {quoteId: quote.getQuoteId()});
-            } else {
-                serviceUrl = urlBuilder.createUrl('/carts/mine/collect-totals', {});
-            }
-
-            if (quote.isVirtual()) {
-                return storage.put(
-                    serviceUrl,
-                    JSON.stringify(paymentMethodData)
-                ).done(
-                    function (response) {
-                        var proceed = true;
-                        _.each(callbacks, function(callback) {
-                            proceed = proceed && callback();
-                        });
-                        if (proceed) {
-                            quote.setPaymentMethod(methodData.method);
-                            service.setSelectedPaymentData(methodData);
-                            service.setSelectedPaymentInfo(methodInfo);
-                            quote.setTotals(response);
-                            navigator.setCurrent('paymentMethod').goNext();
-                        }
-                    }
-                ).error(
-                    function (response) {
-                        var error = JSON.parse(response.responseText);
-                        errorList.add(error);
-                        quote.setPaymentMethod(null);
-                    }
-                );
-            } else {
-                if (!_.isEmpty(quote.getShippingCustomOptions()())) {
-                    shippingMethodData = _.extend(
-                        shippingMethodData,
-                        {
-                            additionalData: {
-                                extension_attributes: quote.getShippingCustomOptions()()
-                            }
-                        }
-                    );
-                }
-                return storage.put(
-                    serviceUrl,
-                    JSON.stringify(_.extend(paymentMethodData, shippingMethodData))
-                ).done(
-                    function (response) {
-                        var proceed = true;
-                        _.each(callbacks, function(callback) {
-                            proceed = proceed && callback();
-                        });
-                        if (proceed) {
-                            quote.setPaymentMethod(methodData.method);
-                            //set the totals before setting PaymentData
-                            quote.setTotals(response);
-                            service.setSelectedPaymentData(methodData);
-                            service.setSelectedPaymentInfo(methodInfo);
-                            navigator.setCurrent('paymentMethod').goNext();
-                        }
-                    }
-                ).error(
-                    function (response) {
-                        var error = JSON.parse(response.responseText);
-                        errorList.add(error);
-                        quote.setPaymentMethod(null);
-                    }
-                );
-            }
-        };
+    function(quote) {
+        'use strict';
+        return function (paymentMethod) {
+            quote.paymentMethod(paymentMethod);
+        }
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js
index c9f87d1594b7aa201bee919e37ba79ca4c3d21a6..5247cef00fb03ac61bf36e29f7e6655fee7605cd 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js
@@ -4,69 +4,16 @@
  */
 /*global define*/
 define(
-    [
-        '../model/quote',
-        '../model/addresslist',
-        '../model/url-builder',
-        '../model/step-navigator',
-        '../model/shipping-service',
-        '../model/payment-service',
-        'mage/storage',
-        'Magento_Ui/js/model/errorlist'
+    ['../model/quote',
+     'Magento_Checkout/js/model/shipping-rate-service'
     ],
-    function(quote, addressList, urlBuilder, navigator, shippingService, paymentService, storage, errorList) {
+    function(quote, shippingRateService) {
         "use strict";
-        var actionCallback;
-        var result = function(shippingAddress, sameAsBilling, additionalData) {
-            var serviceUrl;
-            if (quote.getCheckoutMethod()() === 'guest') {
-                serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/addresses', {quoteId: quote.getQuoteId()});
-            } else {
-                serviceUrl =  urlBuilder.createUrl('/carts/mine/addresses', {});
-            }
-
-            errorList.clear();
-            additionalData = additionalData || {};
-            shippingAddress['same_as_billing'] = (sameAsBilling) ? 1 : 0;
-            quote.setShippingAddress(shippingAddress);
-
-            storage.post(
-                serviceUrl,
-                JSON.stringify({
-                    shippingAddress: quote.getShippingAddress()(),
-                    billingAddress: quote.getBillingAddress()(),
-                    additionalData: {extensionAttributes : additionalData},
-                    checkoutMethod: quote.getCheckoutMethod()()
-                })
-            ).done(
-                function(result) {
-                    shippingService.setShippingRates(result.shipping_methods);
-                    paymentService.setPaymentMethods(result.payment_methods);
-                    quote.setFormattedBillingAddress(result.formatted_billing_address);
-                    quote.setFormattedShippingAddress(result.formatted_shipping_address);
-                    quote.setTotals(result.totals);
-                    navigator.setCurrent('shippingAddress').goNext();
-                    if (typeof actionCallback == 'function') {
-                        actionCallback(true);
-                    }
-                }
-            ).fail(
-                function(response) {
-                    var error = JSON.parse(response.responseText);
-                    errorList.add(error);
-                    quote.setShippingAddress(null);
-                    quote.setBillingAddress(null);
-                    quote.setFormattedBillingAddress(null);
-                    quote.setFormattedShippingAddress(null);
-                    if (typeof actionCallback == 'function') {
-                        actionCallback(false);
-                    }
-                }
-            );
+        quote.shippingAddress.subscribe(function () {
+            shippingRateService.getRates(quote.shippingAddress())
+        });
+        return function(shippingAddress) {
+            quote.shippingAddress(shippingAddress);
         };
-        result.setActionCallback = function (value) {
-            actionCallback = value;
-        };
-        return result;
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js
index f00e2e86670c8e145fc67b33ec8a3fe7f1bcbf47..30f629cfc09e52343b5fe41343c8229f3e0e9abf 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js
@@ -5,36 +5,12 @@
 /*global define,alert*/
 define(
     [
-        '../model/quote',
-        '../model/url-builder',
-        '../model/step-navigator',
-        'Magento_Checkout/js/model/shipping-service',
-        'mage/translate',
-        'ko'
+        '../model/quote'
     ],
-    function (quote, urlBuilder, navigator, shippingService, $t, ko) {
+    function (quote) {
         "use strict";
-        return function (code, customOptions, callbacks) {
-            if (!code) {
-                alert($t('Please specify a shipping method'));
-                return;
-            }
-
-            var proceed = true;
-            _.each(callbacks, function (callback) {
-                proceed = proceed && callback();
-            });
-
-            if (proceed) {
-                var shippingMethodCode = code.split("_"),
-                    shippingRate = shippingService.getRateByCode(shippingMethodCode)[0];
-
-                quote.setShippingMethod(shippingMethodCode);
-                quote.setSelectedShippingMethod(code);
-                quote.setShippingCustomOptions(customOptions);
-                quote.setCollectedTotals('shipping', shippingRate.amount);
-                navigator.setCurrent('shippingMethod').goNext();
-            }
-        };
+        return function (shippingMethod) {
+            quote.shippingMethod(shippingMethod)
+        }
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js
new file mode 100644
index 0000000000000000000000000000000000000000..4f1167970a41e3af06ac108be3e60aa44d63ad20
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/url-builder',
+        'mage/storage',
+        'Magento_Ui/js/model/messageList',
+        'Magento_Customer/js/model/customer'
+    ],
+    function (quote, urlBuilder, storage, messageList, customer) {
+        'use strict';
+
+        return function () {
+            var serviceUrl,
+                payload,
+                paymentData = quote.paymentMethod();
+
+            /**
+             * Checkout for guest and registered customer.
+             */
+            if (!customer.isLoggedIn()) {
+                serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/set-payment-information', {
+                    quoteId: quote.getQuoteId()
+                });
+                payload = {
+                    cartId: quote.getQuoteId(),
+                    email: quote.guestEmail,
+                    paymentMethod: paymentData,
+                    billingAddress: quote.billingAddress()
+                };
+            } else {
+                serviceUrl = urlBuilder.createUrl('/carts/mine/set-payment-information', {});
+                payload = {
+                    cartId: quote.getQuoteId(),
+                    paymentMethod: paymentData,
+                    billingAddress: quote.billingAddress()
+                };
+            }
+            return storage.post(
+                serviceUrl, JSON.stringify(payload)
+            ).done(
+                function () {
+                    //do nothing
+                }
+            ).fail(
+                function (response) {
+                    var error = JSON.parse(response.responseText);
+                    messageList.addErrorMessage(error);
+                }
+            );
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js
new file mode 100644
index 0000000000000000000000000000000000000000..918f5201012f1eb933940b8a10e817b3a67387b4
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js
@@ -0,0 +1,17 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define,alert*/
+define(
+    [
+        '../model/quote',
+        'Magento_Checkout/js/model/shipping-save-processor'
+    ],
+    function (quote, shippingSaveProcessor) {
+        'use strict';
+        return function () {
+            return shippingSaveProcessor.saveShippingInformation(quote.shippingAddress().getType());
+        }
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
new file mode 100644
index 0000000000000000000000000000000000000000..896f38b9648aa27bee9050378c445d6a7e664ce5
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
@@ -0,0 +1,85 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'jquery',
+        'Magento_Checkout/js/model/new-customer-address',
+        'mage/utils/objects'
+    ],
+    function($, address, mageUtils) {
+        'use strict';
+        var countryData = window.checkoutConfig.countryData;
+
+        return {
+            /**
+             * Convert address form data to Address object
+             * @param {Object} formData
+             * @returns {Object}
+             */
+            formAddressDataToQuoteAddress: function(formData) {
+                // clone address form data to new object
+                var addressData = $.extend(true, {}, formData),
+                    region;
+
+                if (mageUtils.isObject(addressData.street)) {
+                    addressData.street = this.objectToArray(addressData.street);
+                }
+
+                addressData.region = {
+                    region_id: null,
+                    region_code: null,
+                    region: null
+                };
+
+                if (addressData.region_id) {
+                    region = countryData[addressData.country_id]['regions'][addressData.region_id];
+                    if (region) {
+                        addressData.region.region_id = addressData['region_id'];
+                        addressData.region.region_code = region['code'];
+                        addressData.region.region = region['name'];
+                    }
+                }
+                delete addressData.region_id;
+
+                return address(addressData);
+            },
+
+            formDataProviderToFlatData: function(formProviderData, formIndex) {
+                var addressData = {};
+                $.each(formProviderData, function(path, value) {
+                    var pathComponents = path.split('.');
+                    pathComponents.splice(pathComponents.indexOf(formIndex), 1);
+                    pathComponents.reverse();
+                    var dataObject = {};
+                    $.each(pathComponents, function(index, pathPart) {
+                        if (index == 0) {
+                            dataObject[pathPart] = value;
+                        } else {
+                            var parent = {};
+                            parent[pathPart] = dataObject;
+                            dataObject = parent;
+                        }
+                    });
+                    $.extend(true, addressData, dataObject);
+                });
+                return addressData;
+            },
+
+            /**
+             * Convert object to array
+             * @param {Object} object
+             * @returns {Array}
+             */
+            objectToArray: function (object) {
+                var convertedArray = [];
+                $.each(object, function (key) {
+                    return object[key].length ? convertedArray.push(object[key]) : false;
+                });
+
+                return convertedArray.slice(0);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js b/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js
deleted file mode 100644
index 62bc28d2527638c59a8f629f09448279187a74d4..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true*/
-/*global define*/
-define(['jquery'], function($) {
-    "use strict";
-    var addresses = [];
-    return {
-        add: function (address) {
-            addresses.push(address);
-        },
-        getAddressById: function(id) {
-            var address = null;
-            $.each(addresses, function(key, item) {
-                if (id === item.customerAddressId) {
-                    address = item;
-                    return false;
-                }
-            });
-            return address;
-        },
-        getAddresses: function() {
-            return addresses.slice(0);
-        },
-        isBillingSameAsShipping: false
-    };
-});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js
new file mode 100644
index 0000000000000000000000000000000000000000..e448a1c30b07da31ae1f26aaecb0477bade09b65
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'Magento_Ui/js/modal/modal'
+    ],
+    function ($, modal) {
+        'use strict';
+        return {
+            modalWindow: null,
+
+            /** Create popUp window for provided element */
+            createPopUp: function(element) {
+                this.modalWindow = element;
+                var options = {
+                    'type': 'popup',
+                    'modalClass': 'popup-authentication',
+                    'responsive': true,
+                    'innerScroll': true,
+                    'trigger': '.proceed-to-checkout',
+                    'buttons': []
+                };
+                modal(options, $(this.modalWindow));
+            },
+
+            /** Show login popup window */
+            showModal: function() {
+                $(this.modalWindow).modal('openModal');
+            }
+        }
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f64f87e3e4c6cb7308f6a441faed2e13a74589a
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
@@ -0,0 +1,58 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define([], function() {
+    /**
+     * @param addressData
+     * Returns new address object
+     */
+    return function (addressData) {
+        var identifier = Date.now();
+        return {
+            email: addressData.email,
+            countryId: addressData.country_id,
+            regionId: (addressData.region) ? addressData.region.region_id : null,
+            regionCode: (addressData.region) ? addressData.region.region_code : null,
+            region: (addressData.region) ? addressData.region.region : null,
+            customerId: addressData.customer_id,
+            street: addressData.street,
+            company: addressData.company,
+            telephone: addressData.telephone,
+            fax: addressData.fax,
+            postcode: addressData.postcode,
+            city: addressData.city,
+            firstname: addressData.firstname,
+            lastname: addressData.lastname,
+            middlename: addressData.middlename,
+            prefix: addressData.prefix,
+            suffix: addressData.suffix,
+            vatId: addressData.vat_id,
+            sameAsBilling: addressData.same_as_billing,
+            saveInAddressBook: addressData.save_in_address_book,
+            isDefaultShipping: function() {
+                return addressData.default_shipping;
+            },
+            isDefaultBilling: function() {
+                return addressData.default_billing;
+            },
+            getType: function() {
+                return 'new-customer-address'
+            },
+            getKey: function() {
+                return this.getType();
+            },
+            getCacheKey: function() {
+                return this.getType() + identifier;
+            },
+            isEditable: function() {
+                return true;
+            },
+            canUseForBilling: function() {
+                return true;
+            }
+        }
+    }
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js
index 9b6fc75a216c506964c20ee938f60ee1677de823..77841ad3b0632b0d155c7618039ea15fdc5776e9 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js
@@ -2,67 +2,72 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true jquery:true*/
-/*global alert*/
 define(
     [
-        'ko',
-        'jquery',
-        'Magento_Checkout/js/model/quote'
+        'underscore',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/payment/method-list',
+        'Magento_Checkout/js/action/select-payment-method'
     ],
-    function (ko, $, quote) {
+    function (_, quote, methodList, selectPaymentMethod) {
+        'use strict';
+        var freeMethodCode = 'free';
+
         return {
-            paymentMethods: ko.observableArray([]),
-            availablePaymentMethods: ko.observableArray([]),
-            selectedPaymentData: ko.observableArray(),
-            selectedPaymentInfo: ko.observableArray([]),
-            setPaymentMethods: function(methods) {
-                this.paymentMethods(methods);
+            isFreeAvailable: false,
+            /**
+             * Populate the list of payment methods
+             * @param {Array} methods
+             */
+            setPaymentMethods: function (methods) {
+                var self = this,
+                    freeMethod,
+                    filteredMethods,
+                    methodIsAvailable;
+
+                freeMethod = _.find(methods, function (method) {
+                    return method.method === freeMethodCode;
+                });
+                this.isFreeAvailable = freeMethod ? true : false;
+
+                if (self.isFreeAvailable && freeMethod && quote.totals().grand_total <= 0) {
+                    methods.splice(0, methods.length, freeMethod);
+                    selectPaymentMethod(freeMethod);
+                }
+                filteredMethods = _.without(methods, freeMethod);
+
+                if (filteredMethods.length === 1) {
+                    selectPaymentMethod(filteredMethods[0]);
+                } else if (quote.paymentMethod()) {
+                    methodIsAvailable = methods.some(function (item) {
+                        return item.method === quote.paymentMethod().method;
+                    });
+                    //Unset selected payment method if not available
+                    if (!methodIsAvailable) {
+                        selectPaymentMethod(null);
+                    }
+                }
+                methodList(methods);
             },
+            /**
+             * Get the list of available payment methods.
+             * @returns {Array}
+             */
             getAvailablePaymentMethods: function () {
                 var methods = [],
                     self = this;
-                $.each(this.paymentMethods(), function (key, method) {
-                    if (self.isFreeMethodActive() && (
-                        quote.getCalculatedTotal() <= 0 && method['code'] == 'free'
-                        || quote.getCalculatedTotal() > 0 && method['code'] != 'free'
-                        ) || !self.isFreeMethodActive()
+                _.each(methodList(), function (method) {
+                    if (self.isFreeAvailable && (
+                        quote.totals().grand_total <= 0 && method.method === freeMethodCode ||
+                        quote.totals().grand_total > 0 && method.method !== freeMethodCode
+                        ) || !self.isFreeAvailable
                     ) {
                         methods.push(method);
                     }
                 });
+
                 return methods;
-            },
-            isFreeMethodActive: function () {
-                var isAvailable = false;
-                $.each(this.paymentMethods(), function (key, method) {
-                    if (method['code'] == 'free') {
-                        isAvailable = true;
-                    }
-                });
-                return isAvailable;
-            },
-            setSelectedPaymentData: function(data) {
-                this.selectedPaymentData(data);
-            },
-            getSelectedPaymentData: function () {
-                return this.selectedPaymentData();
-            },
-            setSelectedPaymentInfo: function(data) {
-                this.selectedPaymentInfo(data);
-            },
-            getSelectedPaymentInfo: function () {
-                return this.selectedPaymentInfo();
-            },
-            getTitleByCode: function(code) {
-                var methodTitle = '';
-                $.each(this.getAvailablePaymentMethods(), function (key, entity) {
-                    if (entity['code'] == code) {
-                        methodTitle = entity['title'];
-                    }
-                });
-                return methodTitle;
             }
-        }
+        };
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js
new file mode 100644
index 0000000000000000000000000000000000000000..794f7d9a38b01fc043414adb8fdb2714f0aeac42
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'underscore'
+    ],
+    function (_) {
+        'use strict';
+
+        return function (methods) {
+            _.each(methods, function(method) {
+                if (method.hasOwnProperty('code')) {
+                    method.method = method.code;
+                    delete method.code;
+                }
+            });
+
+            return methods;
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js
new file mode 100644
index 0000000000000000000000000000000000000000..9b234d7572c8efdfafc4c71456491edfb811b71d
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js
@@ -0,0 +1,13 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'ko'
+    ],
+    function(ko) {
+        'use strict';
+        return ko.observableArray([]);
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js
similarity index 51%
rename from app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js
rename to app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js
index 44285074df09ad9fa0d14f8f94a69c8c8782ba11..1966d296a9ef06c2df54a5c22c6cbe1364e74655 100644
--- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js
@@ -2,14 +2,13 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*browser:true*/
 /*global define*/
 define(
     [
-        'Magento_Checkout/js/view/payment/method-info'
+        'ko'
     ],
-    function (method) {
-        return method.extend({
-        });
+    function(ko) {
+        'use strict';
+        return ko.observableArray([]);
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..1cc970630a39c7c4509450c921c98cab0886db7f
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(['mageUtils'], function (utils) {
+    'use strict';
+    return {
+        validatedPostCodeExample: [],
+        validate: function(postCode, countryId) {
+            var patterns = window.checkoutConfig.postCodes[countryId];
+            this.validatedPostCodeExample = [];
+
+            if (!utils.isEmpty(postCode) && !utils.isEmpty(patterns)) {
+                for (var pattern in patterns) {
+                    if (patterns.hasOwnProperty(pattern)) {
+                        this.validatedPostCodeExample.push(patterns[pattern]['example']);
+                        var regex = new RegExp(patterns[pattern]['pattern']);
+                        if (regex.test(postCode)) {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+            return true;
+        }
+    }
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
index 650a8b053f7a2c14d07cce94e578e3b1dde6c48f..2ba260a0495c1bd483b291d90988a68cffc48f8d 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
@@ -2,11 +2,10 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true jquery:true*/
-/*global alert*/
 define(
     ['ko'],
-    function(ko) {
+    function (ko) {
+        'use strict';
         var billingAddress = ko.observable(null);
         var shippingAddress = ko.observable(null);
         var shippingMethod = ko.observable(null);
@@ -14,15 +13,21 @@ define(
         var quoteData = window.checkoutConfig.quoteData;
         var basePriceFormat = window.checkoutConfig.basePriceFormat;
         var priceFormat = window.checkoutConfig.priceFormat;
-        var selectedShippingMethod = ko.observable(window.checkoutConfig.selectedShippingMethod);
         var storeCode = window.checkoutConfig.storeCode;
-        var totals = ko.observable({});
-        var checkoutMethod = ko.observable(null);
+        var totalsData = window.checkoutConfig.totalsData;
+        var totals = ko.observable(totalsData);
         var shippingCustomOptions = ko.observable(null);
         var formattedShippingAddress = ko.observable(null);
         var formattedBillingAddress = ko.observable(null);
         var collectedTotals = ko.observable({});
         return {
+            totals: totals,
+            shippingAddress: shippingAddress,
+            shippingMethod: shippingMethod,
+            billingAddress: billingAddress,
+            paymentMethod: paymentMethod,
+            guestEmail: null,
+
             getQuoteId: function() {
                 return quoteData.entity_id;
             },
@@ -39,7 +44,7 @@ define(
                 return window.checkoutConfig.quoteItemData;
             },
             getTotals: function() {
-                return totals
+                return totals;
             },
             setTotals: function(totalsData) {
                 if (_.isObject(totalsData.extension_attributes)) {
@@ -50,18 +55,6 @@ define(
                 totals(totalsData);
                 this.setCollectedTotals('subtotal_with_discount', parseFloat(totalsData.subtotal_with_discount));
             },
-            setBillingAddress: function (address) {
-                billingAddress(address);
-            },
-            getBillingAddress: function() {
-                return billingAddress;
-            },
-            setShippingAddress: function (address) {
-                shippingAddress(address);
-            },
-            getShippingAddress: function() {
-                return shippingAddress;
-            },
             setFormattedBillingAddress: function (address) {
                 formattedBillingAddress(address);
             },
@@ -80,27 +73,9 @@ define(
             getPaymentMethod: function() {
                 return paymentMethod;
             },
-            setShippingMethod: function(shippingMethodCode) {
-                shippingMethod(shippingMethodCode);
-            },
-            getShippingMethod: function() {
-                return shippingMethod;
-            },
-            getSelectedShippingMethod: function() {
-                return selectedShippingMethod;
-            },
-            setSelectedShippingMethod: function(shippingMethod) {
-                selectedShippingMethod(shippingMethod);
-            },
             getStoreCode: function() {
                 return storeCode;
             },
-            getCheckoutMethod: function() {
-                return checkoutMethod;
-            },
-            setCheckoutMethod: function(method) {
-                checkoutMethod(method);
-            },
             setShippingCustomOptions: function(customOptions) {
                 shippingCustomOptions(customOptions);
             },
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js
new file mode 100644
index 0000000000000000000000000000000000000000..b84e16a80bff26af12a7698631259f901cc5dd4f
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js
@@ -0,0 +1,90 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'Magento_Customer/js/model/customer',
+        'Magento_Checkout/js/model/url-builder',
+        'mageUtils'
+    ],
+    function(customer, urlBuilder, utils) {
+        "use strict";
+        return {
+            getUrlForEstimationShippingMethodsForNewAddress: function(quote) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {};
+                var urls = {
+                    'guest': '/guest-carts/:quoteId/estimate-shipping-methods',
+                    'customer': '/carts/mine/estimate-shipping-methods'
+                };
+                return this.getUrl(urls, params);
+            },
+
+            getUrlForEstimationShippingMethodsByAddressId: function(quote) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {};
+                var urls = {
+                    'default': '/carts/mine/estimate-shipping-methods-by-address-id'
+                };
+                return this.getUrl(urls, params);
+            },
+
+            getApplyCouponUrl: function(couponCode, quoteId) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quoteId} : {};
+                var urls = {
+                    'guest': '/guest-carts/' + quoteId + '/coupons/' + couponCode,
+                    'customer': '/carts/mine/coupons/' + couponCode
+                };
+                return this.getUrl(urls, params);
+            },
+
+            getCancelCouponUrl: function(quoteId) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quoteId} : {};
+                var urls = {
+                    'guest': '/guest-carts/' + quoteId + '/coupons/',
+                    'customer': '/carts/mine/coupons/'
+                };
+                return this.getUrl(urls, params);
+            },
+
+            getUrlForCartTotals: function(quote) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {};
+                var urls = {
+                    'guest': '/guest-carts/:quoteId/totals',
+                    'customer': '/carts/mine/totals'
+                };
+                return this.getUrl(urls, params);
+            },
+
+            getUrlForSetShippingInformation: function(quote) {
+                var params = (this.getCheckoutMethod() == 'guest') ? {cartId: quote.getQuoteId()} : {};
+                var urls = {
+                    'guest': '/carts/:cartId/shipping-information',
+                    'customer': '/carts/mine/shipping-information'
+                };
+                return this.getUrl(urls, params);
+            },
+
+            /** Get url for service */
+            getUrl: function(urls, urlParams) {
+                var url;
+
+                if (utils.isEmpty(urls)) {
+                    return 'Provided service call does not exist.';
+                }
+
+                if (!utils.isEmpty(urls['default'])) {
+                    url = urls['default'];
+                } else {
+                    url = urls[this.getCheckoutMethod()];
+                }
+                return urlBuilder.createUrl(url, urlParams);
+            },
+
+            getCheckoutMethod: function() {
+                return customer.isLoggedIn() ? 'customer' : 'guest';
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js
new file mode 100644
index 0000000000000000000000000000000000000000..d23e82ca703bab7e787a5f47b0027612b4111998
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'ko'
+    ],
+    function(ko) {
+        'use strict';
+        return {
+            isVisible: ko.observable(false)
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js
new file mode 100644
index 0000000000000000000000000000000000000000..068891a5286964d5dedb4b8812669e45a6f3b5ca
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/model/resource-url-manager',
+        'Magento_Checkout/js/model/quote',
+        'mage/storage',
+        'Magento_Checkout/js/model/shipping-service',
+        'Magento_Checkout/js/model/shipping-rate-registry',
+        'Magento_Ui/js/model/messageList'
+    ],
+    function (resourceUrlManager, quote, storage, shippingService, rateRegistry, messageList) {
+        "use strict";
+        return {
+            getRates: function(address) {
+                var cache = rateRegistry.get(address.getKey());
+                if (cache) {
+                    shippingService.setShippingRates(cache);
+                } else {
+                    shippingService.isLoading(true);
+                    storage.post(
+                        resourceUrlManager.getUrlForEstimationShippingMethodsByAddressId(),
+                        JSON.stringify({
+                            addressId: address.customerAddressId
+                        }),
+                        false
+                    ).done(
+                        function(result) {
+                            rateRegistry.set(address.getKey(), result);
+                            shippingService.setShippingRates(result);
+                        }
+
+                    ).fail(
+                        function(response) {
+                            var error = JSON.parse(response.responseText);
+                            messageList.addErrorMessage(error);
+                            shippingService.setShippingRates([])
+                        }
+                    ).always(
+                        function () {
+                            shippingService.isLoading(false);
+                        }
+                    );
+                }
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js
new file mode 100644
index 0000000000000000000000000000000000000000..db5052ca0c39f44ddf2ed115ac1d7d94631f2c34
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js
@@ -0,0 +1,61 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'Magento_Checkout/js/model/resource-url-manager',
+        'Magento_Checkout/js/model/quote',
+        'mage/storage',
+        'Magento_Checkout/js/model/shipping-service',
+        'Magento_Checkout/js/model/shipping-rate-registry',
+        'Magento_Ui/js/model/messageList'
+    ],
+    function (resourceUrlManager, quote, storage, shippingService, rateRegistry, messageList) {
+        'use strict';
+
+        return {
+            /**
+             * Get shipping rates for specified address.
+             * @param {Object} address
+             */
+            getRates: function (address) {
+                var cache = rateRegistry.get(address.getCacheKey()),
+                    serviceUrl = resourceUrlManager.getUrlForEstimationShippingMethodsForNewAddress(quote),
+                    payload = JSON.stringify({
+                            address: {
+                                country_id: address.countryId,
+                                region_id: address.regionId,
+                                region: address.region,
+                                postcode: address.postcode
+                            }
+                        }
+                    );
+
+                if (cache) {
+                    shippingService.setShippingRates(cache);
+                } else {
+                    shippingService.isLoading(true);
+                    storage.post(
+                        serviceUrl, payload, false
+                    ).done(
+                        function (result) {
+                            rateRegistry.set(address.getCacheKey(), result);
+                            shippingService.setShippingRates(result);
+                        }
+                    ).fail(
+                        function (response) {
+                            var error = JSON.parse(response.responseText);
+                            messageList.addErrorMessage(error);
+                            shippingService.setShippingRates([]);
+                        }
+                    ).always(
+                        function () {
+                            shippingService.isLoading(false);
+                        }
+                    );
+                }
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js
new file mode 100644
index 0000000000000000000000000000000000000000..e5bd1104b1714d89fa4db7bc2893e604e3ea633a
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function() {
+        "use strict";
+        var cache = [];
+        return {
+            get: function(addressKey) {
+                if (cache[addressKey]) {
+                    return cache[addressKey];
+                }
+                return false;
+            },
+            set: function(addressKey, data) {
+                cache[addressKey] = data;
+            }
+        };
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js
new file mode 100644
index 0000000000000000000000000000000000000000..68bc173215923fff08510790811e5270f4ef5328
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js
@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/model/shipping-rate-processor/new-address',
+        'Magento_Checkout/js/model/shipping-rate-processor/customer-address'
+    ],
+    function(defaultProcessor, customerAddressProcessor) {
+        "use strict";
+        var processors = [];
+        processors['default'] =  defaultProcessor;
+        processors['customer-address'] = customerAddressProcessor;
+
+        return {
+            registerProcessor: function(type, processor) {
+                processors[type] = processor;
+            },
+            getRates: function (address) {
+                var type = address.getType();
+                var rates = [];
+                if (processors[type]) {
+                    rates = processors[type].getRates(address);
+                } else {
+                    rates = processors['default'].getRates(address);
+                }
+                return rates;
+            }
+        }
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..e6eafeee848e544635b8bb1b97ac345b76b52854
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    ['jquery'],
+    function ($) {
+        "use strict";
+        var ratesRules = {};
+        var checkoutConfig = window.checkoutConfig;
+        return {
+            registerRules: function(carrier, rules) {
+                if (checkoutConfig.activeCarriers.indexOf(carrier) != -1) {
+                    ratesRules[carrier] = rules.getRules();
+                }
+            },
+            getRules: function() {
+                return ratesRules;
+            },
+            getObservableFields: function() {
+                var self = this;
+                var observableFields = [];
+                $.each(self.getRules(), function(carrier, fields) {
+                    $.each(fields, function(field, rules) {
+                        if (observableFields.indexOf(field) == -1) {
+                            observableFields.push(field);
+                        }
+                    });
+                });
+                return observableFields;
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..7bd072008705968c57080a089666f07968355fb8
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
@@ -0,0 +1,122 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'ko',
+        './shipping-rates-validation-rules',
+        '../model/address-converter',
+        '../action/select-shipping-address',
+        './postcode-validator',
+        'mage/translate'
+    ],
+    function ($, ko, shippingRatesValidationRules, addressConverter, selectShippingAddress, postcodeValidator, $t) {
+        'use strict';
+        var checkoutConfig = window.checkoutConfig;
+        var validators = [];
+        var observedElements = [];
+        var postcodeElement = null;
+
+        return {
+            validateAddressTimeout: 0,
+            validateDelay: 2000,
+
+            registerValidator: function(carrier, validator) {
+                if (checkoutConfig.activeCarriers.indexOf(carrier) != -1) {
+                    validators.push(validator);
+                }
+            },
+
+            validateAddressData: function(address) {
+                return validators.some(function(validator) {
+                    return validator.validate(address);
+                });
+            },
+
+            bindChangeHandlers: function(elements) {
+                var self = this;
+                var observableFields = shippingRatesValidationRules.getObservableFields();
+                $.each(elements, function(index, elem) {
+                    if (elem && observableFields.indexOf(elem.index) != -1) {
+                        if (elem.index !== 'postcode') {
+                            self.bindHandler(elem);
+                        }
+                    }
+
+                    if (elem.index === 'postcode') {
+                        self.bindHandler(elem);
+                        postcodeElement = elem;
+                    }
+                });
+            },
+
+            bindHandler: function(element) {
+                var self = this;
+                if (element.component.indexOf('/group') != -1) {
+                    $.each(element.elems(), function(index, elem) {
+                        self.bindHandler(elem);
+                    });
+                } else {
+                    element.on('value', function() {
+                        clearTimeout(self.validateAddressTimeout);
+                        self.validateAddressTimeout = setTimeout(function() {
+                            if (self.postcodeValidation()) {
+                                self.validateFields();
+                            }
+                        }, self.validateDelay);
+                    });
+                    observedElements.push(element);
+                }
+            },
+
+            postcodeValidation: function() {
+                if (postcodeElement == null || postcodeElement.value() == null) {
+                    return true;
+                }
+
+                var countryId = $('select[name="shippingAddress[country_id]"]').val();
+                var validationResult = postcodeValidator.validate(postcodeElement.value(), countryId);
+
+                postcodeElement.error(null);
+                if (!validationResult) {
+                    var errorMessage = $t('Invalid Zip/Postal code for current country!');
+                    if (postcodeValidator.validatedPostCodeExample.length) {
+                        errorMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; ');
+                    }
+                    postcodeElement.error(errorMessage);
+                }
+                return validationResult;
+            },
+
+            /**
+             * Convert form data to quote address and validate fields for shipping rates
+             */
+            validateFields: function() {
+                var addressFlat = addressConverter.formDataProviderToFlatData(
+                    this.collectObservedData(),
+                    'shippingAddress'
+                );
+                if (this.validateAddressData(addressFlat)) {
+                    var address = addressConverter.formAddressDataToQuoteAddress(addressFlat);
+                    selectShippingAddress(address);
+                }
+            },
+
+            /**
+             * Collect observed fields data to object
+             *
+             * @returns {*}
+             */
+            collectObservedData: function() {
+                var observedValues = {};
+                $.each(observedElements, function(index, field) {
+                    observedValues[field.dataScope] = field.value();
+                });
+                return observedValues;
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js
new file mode 100644
index 0000000000000000000000000000000000000000..8789ad0ccb38841da2fa7c900e1bee380fbc19e7
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/model/shipping-save-processor/default'
+    ],
+    function(defaultProcessor) {
+        'use strict';
+        var processors = [];
+        processors['default'] =  defaultProcessor;
+
+        return {
+            registerProcessor: function(type, processor) {
+                processors[type] = processor;
+            },
+            saveShippingInformation: function (type) {
+                var rates = [];
+                if (processors[type]) {
+                    rates = processors[type].saveShippingInformation();
+                } else {
+                    rates = processors['default'].saveShippingInformation();
+                }
+                return rates;
+            }
+        }
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..7233d429dc0691907a04b174452db883dbdc24df
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define,alert*/
+define(
+    [
+        'ko',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/resource-url-manager',
+        'mage/storage',
+        'Magento_Checkout/js/model/payment-service',
+        'Magento_Checkout/js/model/payment/method-converter',
+        'Magento_Ui/js/model/messageList'
+    ],
+    function (ko, quote, resourceUrlManager, storage, paymentService, methodConverter, messageList) {
+        'use strict';
+
+        return {
+            saveShippingInformation: function() {
+                var payload = {
+                    addressInformation: {
+                        shipping_address: quote.shippingAddress(),
+                        shipping_method_code: quote.shippingMethod().method_code,
+                        shipping_carrier_code: quote.shippingMethod().carrier_code
+                    }
+                };
+
+                return storage.post(
+                    resourceUrlManager.getUrlForSetShippingInformation(quote),
+                    JSON.stringify(payload)
+                ).done(
+                    function (response) {
+                        quote.setTotals(response.totals);
+                        paymentService.setPaymentMethods(methodConverter(response.payment_methods));
+                    }
+                ).fail(
+                    function (response) {
+                        var error = JSON.parse(response.responseText);
+                        messageList.addErrorMessage(error);
+                    }
+                );
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js
index 8bb0366111a7aa7002bf81a1932cbea8ec1582de..f03da90e2fade9119bbfb16dbcced239f13572c8 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js
@@ -4,46 +4,63 @@
  */
 /*global define*/
 define(
-    ['ko', 'jquery'],
-    function (ko, $) {
+    [
+        'ko',
+        'Magento_Checkout/js/action/select-shipping-method',
+        'Magento_Checkout/js/model/quote',
+        'jquery'
+    ],
+    function (ko, selectShippingMethodAction, quote, $) {
         "use strict";
-        var rates = ko.observable([]);
+        var shippingRates = ko.observableArray([]);
         return {
-            shippingRates: ko.observableArray([]),
+            isLoading: ko.observable(false),
+            /**
+             * Set shipping rates
+             *
+             * @param ratesData
+             */
             setShippingRates: function(ratesData) {
-                var self = this;
-                rates(ratesData);
-                self.shippingRates([]);
-                $.each(ratesData, function (key, entity) {
-                    var rateEntity = {};
-                    rateEntity.items = [];
-                    if (!ratesData.hasOwnProperty(entity.carrier_code)) {
-                        rateEntity['carrier_code'] = entity.carrier_code;
-                        rateEntity['carrier_title'] = entity.carrier_title;
-                    }
-                    rateEntity.items.push(entity);
-                    self.shippingRates.push(rateEntity);
-                });
+                shippingRates(ratesData);
+                shippingRates.valueHasMutated();
 
+                if (ratesData.length == 1) {
+                    //set shipping rate if we have only one available shipping rate
+                    selectShippingMethodAction(ratesData[0]);
+                } else if(quote.shippingMethod()) {
+                    var rateIsAvailable = ratesData.some(function (rate) {
+                        if (rate.carrier_code == quote.shippingMethod().carrier_code
+                            && rate.method_code == quote.shippingMethod().method_code) {
+                            return true;
+                        }
+                        return false;
+                    });
+                    //Unset selected shipping shipping method if not available
+                    if (!rateIsAvailable) {
+                        selectShippingMethodAction(null);
+                    }
+                }
             },
+
+            /**
+             * Get shipping rates
+             *
+             * @returns {*}
+             */
             getSippingRates: function() {
-                return this.shippingRates;
+                return shippingRates;
             },
-            getTitleByCode: function(methodCodeParts) {
-                var shippingMethodTitle = '', shippingMethodCode, carrierCode, methodCode;
-                if (!methodCodeParts) {
-                    return shippingMethodTitle;
-                }
-                shippingMethodCode = methodCodeParts.slice(0);
-                carrierCode = shippingMethodCode.shift();
-                methodCode = shippingMethodCode.join('_');
-                $.each(rates(), function (key, entity) {
-                    if (entity['carrier_code'] === carrierCode && entity['method_code'] === methodCode) {
-                        shippingMethodTitle = entity['carrier_title'] + " - " + entity['method_title'];
-                    }
-                });
-                return shippingMethodTitle;
+
+            /**
+             * Get shipping method title
+             *
+             * @param shippingMethod
+             * @returns {string}
+             */
+            getTitleByCode: function(shippingMethod) {
+                return shippingMethod ? shippingMethod.carrier_title + " - " + shippingMethod.method_title : '';
             },
+
             getRateByCode : function(methodCodeParts) {
                 var shippingRates = [],
                     shippingMethodCode = methodCodeParts.slice(0),
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js
index 44a48fa893285ea45161b23c6a402466921a1f06..0ce40c7999a80c32cfdb08b3c0ece8a261df3bdb 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js
@@ -7,198 +7,89 @@
 define(
     [
         'jquery',
-        'ko',
-        'Magento_Customer/js/model/customer',
-        'Magento_Ui/js/model/errorlist'
+        'ko'
     ],
-    function($, ko, customer, errorList) {
-        var customerIsLoggedIn = customer.isLoggedIn()();
-        var defaultStepClass = 'section';
-        var allowedStepClass = 'allow';
-        var activeStepClass = 'active';
+    function($, ko) {
+        var steps = ko.observableArray();
+
         return {
-            currentStep: null,
-            steps: [
-                {
-                    name: 'authentication',
-                    isVisible: ko.observable(!customerIsLoggedIn),
-                    isEnabled: true,
-                    number: ko.observable(1),
-                    classAttributes: ko.observable(defaultStepClass)
-                },
-                {
-                    name: 'billingAddress',
-                    isVisible: ko.observable(customerIsLoggedIn),
-                    isEnabled: true,
-                    number: ko.observable(2),
-                    classAttributes: ko.observable(defaultStepClass)
-                },
-                {
-                    name: 'shippingAddress',
-                    isVisible: ko.observable(false),
-                    isEnabled: true,
-                    number: ko.observable(3),
-                    classAttributes: ko.observable(defaultStepClass)
-                },
-                {
-                    name: 'shippingMethod',
-                    isVisible: ko.observable(false),
-                    isEnabled: true,
-                    number: ko.observable(4),
-                    classAttributes: ko.observable(defaultStepClass)
-                },
-                {
-                    name: 'paymentMethod',
-                    isVisible: ko.observable(false),
-                    isEnabled: true,
-                    number: ko.observable(5),
-                    classAttributes: ko.observable(defaultStepClass)
-                },
-                {
-                    name: 'review',
-                    isVisible: ko.observable(false),
-                    isEnabled: true,
-                    number: ko.observable(6),
-                    classAttributes: ko.observable(defaultStepClass)
-                }
-            ],
-            setCurrent: function(step) {
-                this.currentStep = step;
-                return this;
-            },
-            getCurrentStep: function() {
-                if (!this.currentStep) {
-                    alert('Current step not set.');
-                    return;
-                }
-                var self = this;
-                var currentStep = null;
-                $.each(this.steps, function(key, step) {
-                    if (self.currentStep == step.name) {
-                        currentStep = step;
-                    }
+            steps: steps,
+            stepCodes: [],
+            registerStep: function(code, title, isVisible, sortOrder) {
+                steps.push({
+                    code: code,
+                    title : title,
+                    isVisible: isVisible,
+                    sortOrder: sortOrder
                 });
-                return currentStep;
-            },
-            goNext: function() {
-                var currentStep = this.getCurrentStep();
-                var nextStepOrder = currentStep.number() + 1;
-                var nextStep = null;
-                $.each(this.steps, function(key, item) {
-                    if (nextStepOrder == item.number()) {
-                        nextStep = item;
-                        return false;
+                this.stepCodes.push(code);
+            },
+
+            sortItems: function(itemOne, itemTwo) {
+                return itemOne.sortOrder > itemTwo.sortOrder ? 1 : -1
+            },
+
+            getActiveItemIndex: function() {
+                var activeIndex = 0;
+                steps.sort(this.sortItems).forEach(function(element, index) {
+                    if (element.isVisible()) {
+                        activeIndex = index;
                     }
                 });
-                if (nextStep) {
-                    this.toStep(nextStep.name);
-                }
-            },
-            goBack: function() {
-                var currentStep = this.getCurrentStep();
-                var prevStepOrder = currentStep.number() - 1;
-                var previousStep = null;
-                $.each(this.steps, function(key, item) {
-                    if (prevStepOrder == item.number()) {
-                        previousStep = item;
-                        return false;
-                    }
-                });
-                if (previousStep) {
-                    this.toStep(previousStep.name);
-                }
-            },
-            getStepClassAttributes: function(name) {
-                return this.findStepByName(name).classAttributes;
-            },
-            setStepClassAttributes: function(name) {
-                var stepClass = defaultStepClass;
-                var step = this.findStepByName(name);
-                if (step.isVisible()) {
-                    stepClass += ' ' + activeStepClass;
-                }
-                if (this.isStepAvailable(step.name)) {
-                    stepClass += ' ' + allowedStepClass;
-                }
-                step.classAttributes(stepClass);
-            },
-            updateStepsClassAttributes: function() {
-                var self = this;
-                $.each(this.steps, function(key, step) {
-                    var stepClass = defaultStepClass;
-                    if (step.isVisible()) {
-                        stepClass += ' ' + activeStepClass;
-                    }
-                    if (self.isStepAvailable(step.name)) {
-                        stepClass += ' ' + allowedStepClass;
+                return activeIndex;
+            },
+
+            isProcessed: function(code) {
+                var activeItemIndex = this.getActiveItemIndex();
+                var sortedItems = steps.sort(this.sortItems);
+                var requestedItemIndex = -1;
+                sortedItems.forEach(function(element, index) {
+                    if (element.code == code) {
+                        requestedItemIndex = index;
                     }
-                    step.classAttributes(stepClass);
                 });
+                return activeItemIndex > requestedItemIndex;
             },
-            isStepAvailable: function(name) {
-                var visibleStep = this.getCurrentVisibleStep();
-                var step = this.findStepByName(name);
-                return (step.number() < visibleStep.number());
-            },
-            goToStep: function(name) {
-                if (this.isStepAvailable(name)) {
-                    this.toStep(name);
-                }
-            },
-            toStep: function(name) {
-                if (name) {
-                    $.each(this.steps, function(key, step) {
-                        step.isVisible(false);
-                    });
-                    this.findStepByName(name).isVisible(true);
-                    this.updateStepsClassAttributes();
-                    errorList.clear();
+
+            navigateTo: function(step) {
+                var sortedItems = steps.sort(this.sortItems);
+                if (!this.isProcessed(step.code)) {
+                    return;
                 }
-            },
-            findStepByName: function(name) {
-                var step = null;
-                $.each(this.steps, function(key, currentStep) {
-                    if (name == currentStep.name) {
-                        step = currentStep;
-                        return false;
+                sortedItems.forEach(function(element) {
+                    if (element.code == step.code) {
+                        element.isVisible(true);
+                    } else {
+                        element.isVisible(false);
                     }
+
                 });
-                return step;
             },
-            isStepVisible: function(step) {
-                this.setStepClassAttributes(step);
-                return this.findStepByName(step).isVisible;
-            },
-            setStepVisible: function(step, flag) {
-                this.findStepByName(step).isVisible(flag);
-            },
-            getCurrentVisibleStep: function() {
-                var step = null;
-                $.each(this.steps, function(key, currentStep) {
-                    if (currentStep.isVisible()) {
-                        step = currentStep;
-                        return false;
+
+            next: function() {
+                var activeIndex = 0;
+                steps.sort(this.sortItems).forEach(function(element, index) {
+                    if (element.isVisible()) {
+                        element.isVisible(false);
+                        activeIndex = index;
                     }
                 });
-                return step;
-            },
-            setStepEnabled: function(step, flag) {
-                this.findStepByName(step).isEnabled = flag;
-                this.refreshStepsNumbers();
+                if (steps().length > activeIndex + 1) {
+                    steps()[activeIndex + 1].isVisible(true);
+                }
             },
-            refreshStepsNumbers: function() {
-                var numb = 1;
-                $.each(this.steps, function(key, item) {
-                    if (item.isEnabled) {
-                        item.number(numb);
-                        numb++;
-                    } else {
-                        item.number(null);
+
+            back: function() {
+                var activeIndex = 0;
+                steps.sort(this.sortItems).forEach(function(element, index) {
+                    if (element.isVisible()) {
+                        element.isVisible(false);
+                        activeIndex = index;
                     }
                 });
-            },
-            getStepNumber: function(name) {
-                return this.findStepByName(name).number;
+                if (steps()[activeIndex - 1]) {
+                    steps()[activeIndex - 1].isVisible(true);
+                }
             }
         };
     }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js b/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js
new file mode 100644
index 0000000000000000000000000000000000000000..f32c0d2c15f3c40a2ea1468ac5c13d0e4b74da90
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'ko',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function(ko, quote) {
+
+        return {
+            totals: quote.totals,
+            isLoading: ko.observable(false),
+            getItems: function() {
+                if (!this.totals() || !this.totals().items) {
+                    return [];
+                }
+                return this.totals().items;
+            },
+            getSegment: function(code) {
+                if (!this.totals()) {
+                    return null;
+                }
+                for (var i in this.totals().total_segments) {
+                    var total = this.totals().total_segments[i];
+                    if (total.code == code) {
+                        return total;
+                    }
+                }
+                return null;
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js
new file mode 100644
index 0000000000000000000000000000000000000000..87794967ddff9501e2fba69a01fa8644decf056c
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+        'jquery',
+        'Magento_Checkout/js/model/cart/authentication-popup',
+        'Magento_Customer/js/customer-data'
+    ],
+    function($, authenticationPopup, customerData) {
+        return function (config, element) {
+            $(element).click(function(event) {
+                event.preventDefault();
+                var cart = customerData.get('cart'),
+                    customer = customerData.get('customer');
+
+                if (customer() == false && !cart().isGuestCheckoutAllowed) {
+                    authenticationPopup.showModal();
+                    return false;
+                }
+                location.href = window.checkout.checkoutUrl;
+            });
+
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
index 2455c3932eabaeee72ba2ec5997a0ed9a35b5732..5f93022da11a9089f3ef90ebef20ef2057529a56 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
@@ -6,9 +6,11 @@
 /*global confirm:true*/
 define([
     "jquery",
+    'Magento_Checkout/js/model/cart/authentication-popup',
+    'Magento_Customer/js/customer-data',
     "jquery/ui",
     "mage/decorate"
-], function($){
+], function($, authenticationPopup, customerData){
 
     $.widget('mage.sidebar', {
         options: {
@@ -32,6 +34,13 @@ define([
             });
 
             $(this.options.button.checkout).on('click', $.proxy(function() {
+                var cart = customerData.get('cart'),
+                    customer = customerData.get('customer');
+
+                if (customer() == false && !cart().isGuestCheckoutAllowed) {
+                    authenticationPopup.showModal();
+                    return false;
+                }
                 location.href = this.options.url.checkout;
             }, this));
 
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js
index 44018161f3eeabaf1969bd9e06558db266b13fd7..b921592e718ca5fc134113209f8a39e2624f68d3 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js
@@ -6,66 +6,43 @@
 /*global alert*/
 define(
     [
-        "jquery",
-        'ko',
+        'jquery',
         'Magento_Ui/js/form/form',
         'Magento_Customer/js/action/login',
         'Magento_Customer/js/model/customer',
-        'Magento_Checkout/js/model/step-navigator',
-        '../model/quote',
         'mage/validation'
     ],
-    function($, ko, Component, login, customer, navigator, quote) {
-        "use strict";
-        var stepName = 'authentication';
+    function($, Component, loginAction, customer) {
+        'use strict';
+        var checkoutConfig = window.checkoutConfig;
+
         return Component.extend({
-            stepNumber: navigator.getStepNumber(stepName),
-            isGuestCheckoutAllowed: window.checkoutConfig.isGuestCheckoutAllowed,
-            isCustomerLoginRequired: window.checkoutConfig.isCustomerLoginRequired,
-            registerUrl: window.checkoutConfig.registerUrl,
-            forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl,
-            username: '',
-            password: '',
-            isVisible: navigator.isStepVisible(stepName),
+            isGuestCheckoutAllowed: checkoutConfig.isGuestCheckoutAllowed,
+            isCustomerLoginRequired: checkoutConfig.isCustomerLoginRequired,
+            registerUrl: checkoutConfig.registerUrl,
+            forgotPasswordUrl: checkoutConfig.forgotPasswordUrl,
             defaults: {
                 template: 'Magento_Checkout/authentication'
             },
+
+            /** Is login form enabled for current customer */
+            isActive: function() {
+                return !customer.isLoggedIn();
+            },
+
+            /** Provide login action */
             login: function(loginForm) {
-                var loginData = {};
-                var formDataArray = $(loginForm).serializeArray();
-                var loginFormSelector = 'form[data-role=login]';
+                var loginData = {},
+                    formDataArray = $(loginForm).serializeArray();
+
                 formDataArray.forEach(function (entry) {
                     loginData[entry.name] = entry.value;
                 });
-                if($(loginFormSelector).validation() && $(loginFormSelector).validation('isValid')) {
-                    login(loginData);
-                }
-            },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            isActive: function() {
-                if (customer.isLoggedIn()()) {
-                    navigator.setStepEnabled(stepName, false);
-                }
-                return !customer.isLoggedIn()();
-            },
-            isChecked: function() {
-                if (!isGuestCheckoutAllowed) {
-                    return 'register';
-                }
-                return false;
-            },
-            setCheckoutMethod: function() {
-                quote.setCheckoutMethod('guest');
-                $('[name="customerDetails.password"]').hide();
-                $('[name="customerDetails.confirm_password"]').hide();
-                $('[name*=".save_in_address_book"]').hide();
-                navigator.setCurrent('authentication').goNext();
-            },
-            navigateToCurrentStep: function() {
-                if (!navigator.isStepVisible(stepName)()) {
-                    navigator.goToStep(stepName);
+
+                if($(loginForm).validation()
+                    && $(loginForm).validation('isValid')
+                ) {
+                    loginAction(loginData);
                 }
             }
         });
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js b/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js
index b84bed5619b32ec51ddd662dee71f4c65926f0c7..8424c7a9161db3a2eaefb81515920bc1d8202b9f 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js
@@ -9,7 +9,6 @@ define(
         "use strict";
         return Component.extend({
             defaults: {
-                template: 'Magento_Checkout/review/iterator',
                 displayArea: 'beforePlaceOrder'
             }
         });
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
index ebb20378def25789c4011acbd530a9b6e62da8ee..2ca86001d726002b81df9f2c6adc83bac7443080 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
@@ -6,127 +6,112 @@
 /*global define*/
 define(
     [
-        "jquery",
-        'Magento_Ui/js/form/form',
         'ko',
+        'Magento_Ui/js/form/form',
         'Magento_Customer/js/model/customer',
-        '../action/select-billing-address',
-        '../model/step-navigator',
-        '../model/quote',
-        '../model/addresslist'
+        'Magento_Customer/js/model/address-list',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/action/create-billing-address',
+        'Magento_Checkout/js/action/select-billing-address',
+        'mage/translate'
     ],
-    function ($, Component, ko, customer, selectBillingAddress, navigator, quote, addressList) {
+    function (ko, Component, customer, addressList, quote, createBillingAddress, selectBillingAddress, $t) {
         "use strict";
-        var stepName = 'billingAddress';
-        var newAddressSelected = ko.observable(false);
-        var billingFormSelector = '#co-billing-form';
+
+        var newAddressOption = {
+            getAddressInline: function() {
+                return $t('New Address');
+            },
+            customerAddressId: null
+        };
+        var addressOptions = addressList().filter(function(address, index, addresses) {
+            return address.getType() == 'customer-address';
+        });
+        addressOptions.push(newAddressOption);
 
         return Component.extend({
             defaults: {
                 template: 'Magento_Checkout/billing-address'
             },
+
             initObservable: function () {
-                this._super().observe('useForShipping');
+                this._super()
+                    .observe({
+                        selectedAddress: null,
+                        isAddressDetailsVisible: quote.shippingAddress() != null,
+                        isAddressFormVisible: !customer.isLoggedIn() || addressOptions.length == 1,
+                        isAddressSameAsShipping: false
+                    });
+                quote.billingAddress.subscribe(function(newAddress) {
+                    this.isAddressSameAsShipping(newAddress == quote.shippingAddress() && !quote.isVirtual());
+                    this.isAddressDetailsVisible(true);
+                }, this);
                 return this;
             },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            stepNumber: navigator.getStepNumber(stepName),
-            billingAddresses: function() {
-                var newAddress = {
-                        getAddressInline: function() {
-                            return $.mage.__('New address');
-                        },
-                        customerAddressId: null
-                    },
-                    addresses = addressList.getAddresses();
-                addresses.push(newAddress);
-                return addresses;
-            },
-            selectedBillingAddressId: ko.observable(
-                addressList.getAddresses().length ? addressList.getAddresses()[0].customerAddressId : null
-            ),
-            isVisible: navigator.isStepVisible(stepName),
-            useForShipping: "1",
-            quoteIsVirtual: quote.isVirtual(),
-            billingAddressesOptionsText: function(item) {
-                return item.getAddressInline();
+
+            canUseShippingAddress: ko.computed(function(){
+                return !quote.isVirtual() && quote.shippingAddress()
+                    && quote.shippingAddress().canUseForBilling();
+            }),
+
+            saveInAddressBook: true,
+
+            currentBillingAddress: quote.billingAddress,
+
+            addressOptions: addressOptions,
+
+            customerHasAddresses: addressOptions.length > 1,
+
+            addressOptionsText: function(address) {
+                return address.getAddressInline();
             },
-            checkUseForShipping: function(useForShipping) {
-                var additionalData = {};
-                if (useForShipping() instanceof Object) {
-                    additionalData = useForShipping().getAdditionalData();
-                    useForShipping('1');
+
+            useShippingAddress: function () {
+                if (this.isAddressSameAsShipping()) {
+                    selectBillingAddress(quote.shippingAddress());
+                    this.isAddressDetailsVisible(true);
+                } else {
+                    this.isAddressDetailsVisible(false);
                 }
-                return additionalData;
+                return true;
             },
-            submitBillingAddress: function() {
-                var additionalData = this.checkUseForShipping(this.useForShipping);
-                if (this.selectedBillingAddressId()) {
-                    selectBillingAddress(
-                        addressList.getAddressById(this.selectedBillingAddressId()),
-                        this.useForShipping,
-                        additionalData
-                    );
+
+            updateAddress: function () {
+                if (this.selectedAddress() && this.selectedAddress() != newAddressOption) {
+                    selectBillingAddress(this.selectedAddress());
                 } else {
-                    this.validate();
+                    this.source.set('params.invalid', false);
+                    this.source.trigger(this.dataScopePrefix + '.data.validate');
                     if (!this.source.get('params.invalid')) {
-                        var addressData = this.source.get('billingAddress');
-                        /**
-                         * All the the input fields that are not a part of the address (e. g. CAPTCHA) but need to be
-                         * submitted in the same request must have data-scope attribute set
-                         */
-                        var additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray();
-                        additionalFields.forEach(function (field) {
-                            additionalData[field.name] = field.value;
-                        });
-                        if (quote.getCheckoutMethod()() && !customer.isLoggedIn()()) {
-                            addressData.email = this.source.get('customerDetails.email');
-                        }
-                        if($(billingFormSelector).validation() && $(billingFormSelector).validation('isValid')) {
-                            selectBillingAddress(addressData, this.useForShipping, additionalData);
+                        var addressData = this.source.get(this.dataScopePrefix);
+
+                        if (this.isCustomerLoggedIn && !this.customerHasAddresses) {
+                            this.saveInAddressBook = true;
                         }
+                        addressData.save_in_address_book = this.saveInAddressBook;
+
+                        // New address must be selected as a billing address
+                        selectBillingAddress(createBillingAddress(addressData));
                     }
                 }
             },
-            navigateToCurrentStep: function() {
-                if (!navigator.isStepVisible(stepName)()) {
-                    navigator.goToStep(stepName);
-                }
-            },
-            isNewAddressSelected: function() {
-                if (!this.customerAddressCount) {
-                    return true;
-                }
-                return newAddressSelected();
-            },
-            onAddressChange: function (value) {
-                value() === null ? newAddressSelected(true) : newAddressSelected(false);
+
+            editAddress: function () {
+                this.isAddressDetailsVisible(false);
             },
-            validate: function() {
-                var fields = $(billingFormSelector).find('input, select');
-
-                this.source.set('params.invalid', false);
-                fields.trigger('change');
-                this.source.trigger('billingAddress.data.validate');
-                if (!customer.isLoggedIn()()) {
-                    this.source.trigger('customerDetails.data.validate');
+
+            cancelAddressEdit: function () {
+                if (quote.billingAddress()) {
+                    // restore 'Same As Shipping' checkbox state
+                    this.isAddressSameAsShipping(
+                        !quote.isVirtual() && (quote.shippingAddress() == quote.billingAddress())
+                    );
+                    this.isAddressDetailsVisible(true);
                 }
-                this.validateAdditionalAddressFields();
             },
-            validateAdditionalAddressFields: function() {
-                $(billingFormSelector).validation();
-                $(billingFormSelector + ' input[data-scope="additionalAddressData"]').each(function(key, item) {
-                    $(item).valid();
-                });
-            },
-            isCustomerLoggedIn: customer.isLoggedIn(),
-            customerAddressCount: window.checkoutConfig.customerAddressCount,
-            hideExtraFields: function() {
-                if (!quote.getCheckoutMethod()() && customer.isLoggedIn()()) {
-                    $('[name="customerDetails.email"]').hide();
-                }
+
+            onAddressChange: function (address) {
+                this.isAddressFormVisible(address == newAddressOption);
             }
         });
     }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js
new file mode 100644
index 0000000000000000000000000000000000000000..0985d990a697bde35a780beb7d318895548e9103
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js
@@ -0,0 +1,71 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'ko',
+        'Magento_Ui/js/form/form',
+        'Magento_Customer/js/action/login',
+        'Magento_Customer/js/customer-data',
+        'Magento_Checkout/js/model/cart/authentication-popup',
+        'mage/translate',
+        'mage/validation'
+    ],
+    function($, ko, Component, loginAction, customerData, authenticationPopup, $t) {
+        'use strict';
+        return Component.extend({
+            registerUrl: window.checkout.customerRegisterUrl,
+            forgotPasswordUrl: window.checkout.customerForgotPasswordUrl,
+            modalWindow: null,
+            isLoading: ko.observable(false),
+
+            initialize: function() {
+                var self = this;
+                this._super();
+                loginAction.registerLoginCallback(function() {
+                    self.isLoading(false);
+                });
+            },
+
+            /** Init popup login window */
+            setModalElement: function (element) {
+                authenticationPopup.createPopUp(element);
+            },
+
+            /** Is login form enabled for current customer */
+            isActive: function() {
+                var customer = customerData.get('customer');
+                return customer() == false;
+            },
+
+            /** Show login popup window */
+            showModal: function() {
+                if (this.modalWindow) {
+                    $(this.modalWindow).modal('openModal');
+                } else {
+                    alert($t('Guest checkout is disabled.'));
+                }
+            },
+
+            /** Provide login action */
+            login: function(loginForm) {
+                var loginData = {},
+                    formDataArray = $(loginForm).serializeArray();
+                formDataArray.forEach(function (entry) {
+                    loginData[entry.name] = entry.value;
+                });
+
+                if($(loginForm).validation()
+                    && $(loginForm).validation('isValid')
+                ) {
+                    this.isLoading(true);
+                    loginAction(loginData);
+                }
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js b/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js
deleted file mode 100644
index 85a2097532024573de71c8f0295bd0f6a2e8dc45..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/iterator',
-                displayArea: 'columns'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js b/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js
deleted file mode 100644
index f2a959dfcdb510885a209738efc74ef0b8372cf4..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(
-    [
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
-    ],
-    function (Component, quote, priceUtils) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/discount',
-                displayArea: 'totals'
-            },
-        colspan: 3,
-        style: '',
-        fieldName: 'Discount',
-        totals: quote.getTotals(),
-        getPureValue: function() {
-            var price = 0;
-            if (this.totals()) {
-                price = this.totals().discount_amount;
-            }
-            return price;
-        },
-        getValue: function() {
-            var price = 0;
-            if (this.totals()) {
-                price = this.totals().discount_amount;
-            }
-            return priceUtils.formatPrice(price, quote.getPriceFormat());
-        }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js b/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js
deleted file mode 100644
index ee96966658f05bc7ffb0bbe2aabd5cecb9decdb2..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/iterator',
-                displayArea: 'itemsAfter'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js b/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js
deleted file mode 100644
index 9d2e10ce0a87aeb5bb847e5eb83e11321d9d3c79..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/iterator',
-                displayArea: 'itemsBefore'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
index 373056b389e955be7f910313faf38af2e83cddbb..51e59d8ff6bb31bfb06222c8ef965cbdf19f835d 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
@@ -6,11 +6,13 @@ define([
     'uiComponent',
     'Magento_Customer/js/customer-data',
     'jquery',
-    'ko'
-], function (Component, customerData, $, ko) {
+    'ko',
+    'mage/url'
+], function (Component, customerData, $, ko, url) {
     'use strict';
 
     var sidebarInitialized = false;
+    url.setBaseUrl(window.checkout.baseUrl);
 
     function initSidebar() {
         var minicart = $("[data-block='minicart']");
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js
index 313ba3b923d06aa5caf03cef5330f719244471af..cde7e59dad6483cd2f2c95c55b1764403f80f035 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js
@@ -6,154 +6,35 @@
 /*global alert*/
 define(
     [
-        'jquery',
         'uiComponent',
-        '../model/quote',
-        '../action/select-payment-method',
+        'ko',
+        'Magento_Checkout/js/model/quote',
         'Magento_Checkout/js/model/step-navigator',
         'Magento_Checkout/js/model/payment-service',
-        'mage/translate',
-        'mageUtils'
+        'Magento_Checkout/js/model/payment/method-converter'
     ],
-    function ($, Component, quote, selectPaymentMethod, navigator, paymentService, $t, utils) {
-        var stepName = 'paymentMethod';
+    function (Component, ko, quote, stepNavigator, paymentService, methodConverter) {
+        'use strict';
+
+        /** Set payment methods to collection */
+        paymentService.setPaymentMethods(methodConverter(window.checkoutConfig.paymentMethods));
+
         return Component.extend({
             defaults: {
                 template: 'Magento_Checkout/payment',
                 activeMethod: ''
             },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            stepNumber: navigator.getStepNumber(stepName),
-            isVisible: navigator.isStepVisible(stepName),
-            paymentForm: '#co-payment-form',
-            initObservable: function () {
-                this._super()
-                    .observe('activeMethod');
-                return this;
-            },
-            quoteHasShippingMethod: function() {
-                return quote.isVirtual() || quote.getShippingMethod();
-            },
-            setPaymentMethod: function() {
-                if (!this.activeMethod()) {
-                    alert($t('Please choose a payment method.'));
-                    return;
-                }
-
-                if (this.isFormValid()) {
-                    selectPaymentMethod(
-                        this.getPaymentMethodData(),
-                        this.getPaymentMethodInfo(),
-                        this.getPaymentMethodCallbacks()
-                    );
-                }
-            },
-            getPaymentMethodData: function() {
-                var data = {
-                    "method": this.activeMethod(),
-                    "po_number": null,
-                    "cc_owner": null,
-                    "cc_number": null,
-                    "cc_type": null,
-                    "cc_exp_year": null,
-                    "cc_exp_month": null,
-                    "additional_data": null
-                };
-                utils.extend(data, this.getActiveMethodView().getData());
-
-                _.each(this.getAdditionalMethods(), function(elem) {
-                    if (elem.isActive()) {
-                        utils.extend(data, elem.getData());
-                    }
-                });
-
-                return data;
-            },
-            getPaymentMethodInfo: function() {
-                var info = this.getActiveMethodView().getInfo();
-
-                _.each(this.getAdditionalMethods(), function(elem) {
-                    if (elem.isActive()) {
-                        info = _.union(info, elem.getInfo());
-                    }
-                });
-
-                return info;
-            },
-            getPaymentMethodCallbacks: function() {
-                var callbacks = [this.getActiveMethodView().afterSave.bind(this.getActiveMethodView())];
-
-                _.each(this.getAdditionalMethods(), function(elem) {
-                    if (elem.isActive()) {
-                        callbacks = _.union(callbacks, [elem.afterSave.bind(elem)]);
-                    }
-                });
+            isVisible: ko.observable(quote.isVirtual()),
+            quoteIsVirtual: quote.isVirtual(),
 
-                return callbacks;
+            initialize: function () {
+                this._super();
+                stepNavigator.registerStep('billing', 'Review & Payments', this.isVisible, 20);
+                return this;
             },
-            getAvailableViews: function () {
-                var sortedElems = [],
-                    self = this;
-
-                _.each(this.getAvailableMethods(), function (originElem) {
-                    var method = self.getMethodViewByCode(originElem.code);
-                    if (method && method.isAvailable()) {
-                        sortedElems.push(method);
-                    }
-                });
 
-                if (sortedElems.length == 1) {
-                    this.activeMethod(sortedElems[0].getCode());
-                }
-
-                return sortedElems;
-            },
-            getAvailableMethods: function() {
-                return paymentService.getAvailablePaymentMethods();
-            },
-            getAvailableCodes: function() {
-                return _.pluck(this.getAvailableMethods(), 'code');
-            },
-            getMethodViewByCode: function(code) {
-                return _.find(this.getRegion('paymentMethods')(), function(elem) {
-                    return elem.getCode() == code;
-                });
-            },
-            getActiveMethodView: function() {
-                return this.getMethodViewByCode(this.activeMethod());
-            },
-            backToShippingMethod: function() {
-                navigator.setCurrent(stepName).goBack();
-            },
-            navigateToCurrentStep: function() {
-                if (!navigator.isStepVisible(stepName)()) {
-                    navigator.goToStep(stepName);
-                }
-            },
-            isMethodActive: function(code) {
-                return this.activeMethod() === code;
-            },
-            isFormValid: function() {
-                $(this.paymentForm).validation();
-                return $(this.paymentForm).validation('isValid');
-            },
             getFormKey: function() {
                 return window.checkoutConfig.formKey;
-            },
-            getAdditionalMethods: function() {
-                var methods = [];
-                _.each(this.getRegion('beforeMethods')(), function(elem) {
-                    methods = _.union(methods, elem.elems());
-                });
-                _.each(this.getRegion('afterMethods')(), function(elem) {
-                    methods = _.union(methods, elem.elems());
-                });
-                return methods;
-            },
-            getMethodControlAdditionalClass: function() {
-                return this.getAvailableViews().length == 1 ? ' hidden' : '';
             }
         });
     }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..7fa9e10b69a781d1f9afc86bc79ae7cc39c388d7
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js
@@ -0,0 +1,110 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'ko',
+        'jquery',
+        'uiComponent',
+        'Magento_Checkout/js/action/place-order',
+        'Magento_Checkout/js/action/select-payment-method',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Customer/js/model/customer',
+        'Magento_Checkout/js/model/payment-service'
+    ],
+    function (ko, $, Component, placeOrderAction, selectPaymentMethodAction, quote, customer, paymentService) {
+        'use strict';
+        return Component.extend({
+            redirectAfterPlaceOrder: true,
+            /**
+             * Initialize view.
+             *
+             * @returns {Component} Chainable.
+             */
+            initialize: function () {
+                this._super().initChildren();
+                return this;
+            },
+
+            /**
+             * Initialize child elements
+             *
+             * @returns {Component} Chainable.
+             */
+            initChildren: function () {
+                return this;
+            },
+
+            /**
+             * Place order.
+             */
+            placeOrder: function () {
+                var emailValidationResult = customer.isLoggedIn(),
+                    loginFormSelector = 'form[data-role=email-with-possible-login]';
+                if (!customer.isLoggedIn()) {
+                    $(loginFormSelector).validation();
+                    emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid());
+                }
+                if (emailValidationResult && this.validate()) {
+                    placeOrderAction(this.getData(), this.redirectAfterPlaceOrder);
+                }
+            },
+
+            selectPaymentMethod: function() {
+                selectPaymentMethodAction(this.getData());
+                return true;
+            },
+
+            isChecked: ko.computed(function () {
+                return quote.paymentMethod() ? quote.paymentMethod().method : null;
+            }),
+
+            isRadioButtonVisible: ko.computed(function () {
+                return paymentService.getAvailablePaymentMethods().length !== 1;
+            }),
+
+            /**
+             * Get payment method data
+             */
+            getData: function() {
+                return {
+                    "method": this.item.method,
+                    "po_number": null,
+                    "cc_owner": null,
+                    "cc_number": null,
+                    "cc_type": null,
+                    "cc_exp_year": null,
+                    "cc_exp_month": null,
+                    "additional_data": null
+                };
+            },
+
+            /**
+             * Get payment method type.
+             */
+            getTitle: function () {
+                return this.item.title;
+            },
+
+            /**
+             * Get payment method code.
+             */
+            getCode: function () {
+                return this.item.method;
+            },
+
+            validate: function () {
+                return true;
+            },
+
+            getBillingAddressFormName: function() {
+                return 'billing-address-form-' + this.item.method;
+            },
+
+            disposeSubscriptions: function () {
+                // dispose all active subscriptions
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js
deleted file mode 100644
index 64833500f70a1919a513cb7b6362bf5cc1655be6..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        return Component.extend({
-            getCode: function() {
-                return this.index;
-            },
-            isActive: function(parent) {
-                return false;
-            },
-            getData: function() {
-                return {};
-            },
-            getInfo: function() {
-                return [];
-            },
-            afterSave: function() {
-                return true;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js
new file mode 100644
index 0000000000000000000000000000000000000000..78faf6ba156658108f4820978fba27190f2cc9a3
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js
@@ -0,0 +1,119 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+    'underscore',
+    'ko',
+    'mageUtils',
+    'uiComponent',
+    'Magento_Checkout/js/model/payment/method-list',
+    'Magento_Checkout/js/model/payment/renderer-list',
+    'Magento_Ui/js/core/renderer/layout'
+], function (_, ko, utils, Component, paymentMethods, rendererList, layout) {
+    'use strict';
+
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Checkout/payment-methods/list',
+            visible: paymentMethods().length > 0
+        },
+
+        /**
+         * Initialize view.
+         *
+         * @returns {Component} Chainable.
+         */
+        initialize: function () {
+            this._super().initChildren();
+            paymentMethods.subscribe(
+                function (changes) {
+                    _.each(changes, function (change) {
+                        if (change.status === 'added') {
+                            this.createRenderer(change.value);
+                        } else if (change.status === 'deleted') {
+                            this.removeRenderer(change.value.method);
+                        }
+                    }, this);
+                }, this, 'arrayChange');
+
+            return this;
+        },
+
+        /**
+         * Create renders for child payment methods.
+         *
+         * @returns {Component} Chainable.
+         */
+        initChildren: function () {
+            var self = this;
+            _.each(paymentMethods(), function (paymentMethodData) {
+                self.createRenderer(paymentMethodData);
+            });
+
+            return this;
+        },
+
+        /**
+         * Create renderer.
+         *
+         * @param {Object} paymentMethodData
+         */
+        createRenderer: function (paymentMethodData) {
+            var renderer = this.getRendererByType(paymentMethodData.method),
+                rendererTemplate,
+                rendererComponent,
+                templateData;
+
+            if (renderer) {
+                templateData = {
+                    parentName: this.name,
+                    name: paymentMethodData.method
+                };
+                rendererTemplate = {
+                    parent: '${ $.$data.parentName }',
+                    name: '${ $.$data.name }',
+                    displayArea: 'payment-method-items',
+                    component: renderer.component
+                };
+                rendererComponent = utils.template(rendererTemplate, templateData);
+                utils.extend(rendererComponent, {
+                    item: paymentMethodData
+                });
+                layout([rendererComponent]);
+            }
+        },
+
+        /**
+         * Get renderer for payment method type.
+         *
+         * @param {String} paymentMethodCode
+         * @returns {Object}
+         */
+        getRendererByType: function (paymentMethodCode) {
+            var compatibleRenderer;
+            _.find(rendererList(), function (renderer) {
+                if (renderer.type === paymentMethodCode) {
+                    compatibleRenderer = renderer;
+                }
+            });
+
+            return compatibleRenderer;
+        },
+
+        /**
+         * Remove view renderer.
+         *
+         * @param {String} paymentMethodCode
+         */
+        removeRenderer: function (paymentMethodCode) {
+            var items = this.getRegion('payment-method-items');
+            _.find(items(), function (value) {
+                if (value.item.method === paymentMethodCode) {
+                    value.disposeSubscriptions();
+                    this.removeChild(value);
+                }
+            }, this);
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js
deleted file mode 100644
index c653d3f54111d7f52b031e3376bdc8db84c4dce0..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'Magento_Checkout/js/view/payment/generic',
-        '../../model/payment-service'
-    ],
-    function (generic, paymentService) {
-        return generic.extend({
-            defaults: {
-                titleTemplate: 'Magento_Checkout/payment/generic-title',
-                displayArea: 'paymentMethods',
-                isEnabled: true
-            },
-            initObservable: function () {
-                this._super()
-                    .observe('isEnabled');
-                return this;
-            },
-            getMethod: function() {
-                var paymentMethods = _.indexBy(paymentService.getAvailablePaymentMethods(), 'code');
-
-                return paymentMethods[this.getCode()];
-            },
-            isAvailable: function() {
-                return this.getMethod() != null;
-            },
-            getTitle: function() {
-                return this.isAvailable() ? this.getMethod()['title'] : '';
-            },
-            isActive: function(parent) {
-                return this.isAvailable() && parent.isMethodActive(this.getCode());
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js
deleted file mode 100644
index ec20c4d42179aeee395bec21babff8eda2849516..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true*/
-/*global define*/
-define(
-    [
-        'ko',
-        'Magento_Checkout/js/view/payment/generic',
-        'Magento_Checkout/js/model/quote'
-    ],
-    function (ko, generic, quote) {
-        return generic.extend({
-            defaults: {
-                isChecked: false
-            },
-            isAvailable: function() {
-                return false;
-            },
-            isOn: function() {
-                return false;
-            },
-            getBalance: function() {
-                return 0;
-            },
-            initObservable: function () {
-                this._super()
-                    .observe('isChecked');
-
-                var self = this;
-                this.isChecked.subscribe(
-                    function(isChecked) {
-                        if (isChecked) {
-                            quote.setCollectedTotals(self.getCode(), -parseFloat(self.getBalance()));
-                        } else {
-                            quote.setCollectedTotals(self.getCode(), 0);
-                        }
-                    }
-                );
-                this.isChecked(this.isOn());
-
-                return this;
-            },
-            isActive: function() {
-                return this.isChecked();
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js
new file mode 100644
index 0000000000000000000000000000000000000000..626171c589d3d3aaf6ab2a06e5b3b0884fd8322a
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'ko',
+        'uiComponent',
+        'Magento_Checkout/js/model/step-navigator'
+    ],
+    function (ko, Component, stepNavigator) {
+        var steps = stepNavigator.steps;
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/progress-bar',
+                visible: true
+            },
+            steps: steps,
+
+            sortItems: function(itemOne, itemTwo) {
+                return stepNavigator.sortItems(itemOne, itemTwo);
+            },
+
+            navigateTo: function(step) {
+                stepNavigator.navigateTo(step);
+            },
+
+            isProcessed: function(item) {
+                return stepNavigator.isProcessed(item.code);
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js
deleted file mode 100644
index 1017f9f160eeaa55c9c306bf42b1c98fd8f6d8f5..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'ko',
-        'uiComponent',
-        'Magento_Checkout/js/model/step-navigator',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Checkout/js/model/shipping-service',
-        'Magento_Checkout/js/model/payment-service'
-    ],
-    function (ko, Component, navigator, quote, shippingService, paymentService) {
-        var className = ko.observable();
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/progress'
-            },
-            getClassName: function()
-            {
-                className('opc-block-progress');
-                if(quote.getBillingAddress()() && (quote.getShippingAddress()()) || quote.isVirtual()) {
-                    className('opc-block-progress active')
-                }
-                if (quote.getPaymentMethod()()) {
-                    className('opc-block-progress order-review-step')
-                }
-                return className()
-            },
-
-            isShowStep: function (stepName) {
-                switch(stepName){
-                    case 'shippingAddress':
-                        if (quote.isVirtual()) {
-                            return false
-                        }
-                        return navigator.findStepByName(stepName).isEnabled;
-                        break;
-                    case 'shippingMethod':
-                        if (quote.isVirtual()) {
-                            return false
-                        }
-                        return navigator.findStepByName(stepName).isEnabled;
-                        break;
-                    default:
-                        return navigator.findStepByName(stepName).isEnabled;
-                }
-            },
-            isStepComplete: function(stepName) {
-                switch(stepName){
-                    case 'billingAddress':
-                        return quote.getFormattedBillingAddress()|| false;
-                    break;
-                    case 'shippingAddress':
-                        return quote.getFormattedShippingAddress()||false;
-                    break;
-                    case 'shippingMethod':
-                        return quote.getShippingMethod()||false;
-                    break;
-                    case 'paymentMethod':
-                        return quote.getPaymentMethod()||false;
-                        break;
-                    default:
-                        return false;
-                }
-            },
-            getBillingAddress: function() {
-                return quote.getFormattedBillingAddress()();
-            },
-            getShippingAddress: function() {
-                return quote.getFormattedShippingAddress();
-            },
-            getShippingMethod: function() {
-                return quote.getShippingMethod()
-            },
-            getPaymentMethod: function() {
-                return quote.getPaymentMethod();
-            },
-            getPaymentMethodTitle: function() {
-                var code = this.getPaymentMethod()();
-                return paymentService.getTitleByCode(code)
-            },
-            getPaymentMethodInfo: function() {
-                return paymentService.getSelectedPaymentInfo()
-            },
-            goToStep: function(stepName) {
-                navigator.goToStep(stepName);
-            },
-            getShippingMethodTitle: function() {
-                var code = this.getShippingMethod()();
-                return shippingService.getTitleByCode(code)
-            },
-            getShippingRates: function() {
-                var code = this.getShippingMethod()();
-                return shippingService.getRateByCode(code)
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review.js
deleted file mode 100644
index c2c9c58333f9f990073680f12e449cb67fd96471..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true jquery:true*/
-/*global define*/
-define(
-    [
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'mage/url',
-        'Magento_Checkout/js/model/step-navigator',
-        'Magento_Checkout/js/action/place-order',
-        'underscore'
-    ],
-    function (Component, quote, url, navigator, orderAction, _) {
-        "use strict";
-        var stepName = 'review';
-        var itemsBefore = [];
-        var itemsAfter = [];
-        var beforePlaceOrder = {};
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review'
-            },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            stepNumber: navigator.getStepNumber(stepName),
-            quoteHasPaymentMethod: quote.getPaymentMethod(),
-            itemsBefore: itemsBefore,
-            itemsAfter: itemsAfter,
-            beforePlaceOrder: beforePlaceOrder,
-            getItems: function() {
-                return quote.getTotals()().items;
-            },
-            getColHeaders: function() {
-                return ['name', 'price', 'qty', 'subtotal'];
-            },
-            isVisible: navigator.isStepVisible(stepName),
-            cartUrl: url.build('checkout/cart/'),
-            placeOrder: function(callback) {
-                var component,
-                    isValid = false;
-               if (_.isEmpty(this.beforePlaceOrder)) {
-                   orderAction(null, callback);
-               } else {
-                   for (component in this.beforePlaceOrder) {
-                       if (this.beforePlaceOrder.hasOwnProperty(component) && !this.beforePlaceOrder[component].validate()) {
-                           isValid = true;
-                       }
-                   }
-                   if (isValid) {
-                       orderAction(this.beforePlaceOrder[component].getSubmitParams(), callback);
-                   }
-               }
-            },
-            // get recalculated totals when all data set
-            getTotals: quote.getTotals()
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js
index e160151929985e6a859950e7c33141c7bead36a1..595871bc061e3c513341892fa5f83300e5a8836f 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js
@@ -17,7 +17,7 @@ define(
                 displayArea: 'actions'
             },
             getActiveView: function() {
-                var view = this.getViewByCode(quote.getPaymentMethod()());
+                var view = this.getViewByCode(quote.paymentMethod());
                 return view ? view : this.getDefaultView();
             },
             getViewByCode: function(code) {
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js
deleted file mode 100644
index 3c80b6595f9ef83703676ed7f2c5954da1fd4ac8..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent',
-        '../../../model/quote',
-        'Magento_Catalog/js/price-utils'
-    ],
-    function (Component, quote, priceUtils) {
-        "use strict";
-        var ownClass = '';
-        var columnTitle = '';
-        return Component.extend({
-            defaults: {
-                headerClass: null,
-                ownClass: ownClass,
-                columnTitle: columnTitle,
-                template: 'Magento_Checkout/review/item/column'
-            },
-            getClass: function() {
-                return 'col ' + this.ownClass;
-            },
-            getHeaderClass: function() {
-                if (this.headerClass) {
-                    return this.headerClass;
-                }
-                return 'col ' + this.ownClass;
-            },
-            getColName: function() {
-                return this.columnTitle;
-            },
-            getValue: function(quoteItem) {
-                return quoteItem.name;
-            },
-            getFormattedPrice: function (price) {
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js
deleted file mode 100644
index 0066f8cce1c0c39607ece39310b05a4226aba5a0..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        '../column'
-    ],
-    function (column) {
-        "use strict";
-        return column.extend({
-            defaults: {
-                ownClass: 'price',
-                columnTitle: 'Price',
-                template: 'Magento_Checkout/review/item/columns/price'
-            },
-            getValue: function(quoteItem) {
-                return this.getFormattedPrice(quoteItem.price);
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js
deleted file mode 100644
index c3352464d34e2e54cad7c2ed67b2bf314801915e..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        '../column'
-    ],
-    function (column) {
-        "use strict";
-        return column.extend({
-            defaults: {
-                ownClass: 'qty',
-                columnTitle: 'Qty',
-                template: 'Magento_Checkout/review/item/columns/qty'
-            },
-            getValue: function(quoteItem) {
-                return quoteItem.qty;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js
deleted file mode 100644
index aaa5529851d792e13ed91dcb28c29f66773efd24..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(
-    [
-        "jquery",
-        'Magento_Ui/js/form/form',
-        'ko',
-        'Magento_Checkout/js/action/select-shipping-address',
-        'Magento_Customer/js/model/customer',
-        '../model/quote',
-        'Magento_Checkout/js/model/step-navigator',
-        '../model/addresslist',
-        'underscore'
-    ],
-    function($, Component, ko, selectShippingAddress, customer, quote, navigator, addressList, _) {
-        'use strict';
-        var stepName = 'shippingAddress';
-        var newAddressSelected = ko.observable(false);
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/shipping-address',
-                visible: true,
-                formVisible: customer.getShippingAddressList().length === 0
-            },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            stepNumber: navigator.getStepNumber(stepName),
-            addresses: function() {
-                var newAddress = {
-                        getAddressInline: function() {
-                            return $.mage.__('New address');
-                        },
-                        customerAddressId: null
-                    },
-                    addresses = addressList.getAddresses();
-                addresses.push(newAddress);
-                return addresses;
-            },
-            selectedAddressId: ko.observable(
-                addressList.getAddresses().length ? addressList.getAddresses()[0].customerAddressId : null
-            ),
-            sameAsBilling: ko.observable(null),
-            quoteHasBillingAddress: quote.getBillingAddress(),
-            isVisible: navigator.isStepVisible(stepName),
-            initObservable: function () {
-                this._super()
-                    .observe('visible');
-                return this;
-            },
-            isActive: function() {
-                if (quote.isVirtual()) {
-                    navigator.setStepEnabled(stepName, false);
-                }
-                return !quote.isVirtual();
-            },
-            selectShippingAddress: function() {
-                var additionalFields,
-                    addressData,
-                    additionalData = {},
-                    billingAddress = quote.getBillingAddress()();
-
-                if (!billingAddress.customerAddressId || !this.visible()) {
-                    /**
-                     * All the the input fields that are not a part of the address but need to be submitted
-                     * in the same request must have data-scope attribute set
-                     */
-                    additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray();
-                    additionalFields.forEach(function (field) {
-                        additionalData[field.name] = field.value;
-                    });
-                }
-
-                if (!newAddressSelected()) {
-                    selectShippingAddress(
-                        addressList.getAddressById(this.selectedAddressId()),
-                        this.sameAsBilling(),
-                        additionalData
-                    );
-                } else {
-                    if (this.visible()) {
-                        this.validate();
-                    }
-
-                    if (!this.source.get('params.invalid')) {
-                        addressData = this.source.get('shippingAddress');
-                        selectShippingAddress(addressData, this.sameAsBilling(), additionalData);
-                    }
-                }
-            },
-            sameAsBillingClick: function() {
-                var billingAddress,
-                    shippingAddress,
-                    property;
-
-                addressList.isBillingSameAsShipping = !addressList.isBillingSameAsShipping;
-
-                if (this.sameAsBilling()) {
-                    billingAddress = quote.getBillingAddress()();
-
-                    if (billingAddress.customerAddressId) {
-                        this.selectedAddressId(billingAddress.customerAddressId);
-                        newAddressSelected(false);
-
-                    } else {
-                        // copy billing address data to shipping address form if customer uses new address for billing
-                        shippingAddress = this.source.get('shippingAddress');
-
-                        for (property in billingAddress) {
-                            if (billingAddress.hasOwnProperty(property) && shippingAddress.hasOwnProperty(property)) {
-                                if (typeof billingAddress[property] === 'string') {
-                                    this.source.set('shippingAddress.' + property, billingAddress[property]);
-                                } else {
-                                    this.source.set('shippingAddress.' + property, _.clone(billingAddress[property]));
-                                }
-                            }
-                        }
-
-                        this.selectedAddressId(null);
-                        newAddressSelected(true);
-                    }
-                }
-                return true;
-            },
-            onAddressChange: function() {
-                var billingAddress = quote.getBillingAddress();
-
-                if (this.selectedAddressId() !== billingAddress().customerAddressId) {
-                    this.sameAsBilling(false);
-                }
-
-                if (this.selectedAddressId() === null) {
-                    newAddressSelected(true);
-                } else {
-                    newAddressSelected(false);
-                }
-            },
-            // Checkout step navigation
-            backToBilling: function() {
-                navigator.setCurrent(stepName).goBack();
-            },
-            navigateToCurrentStep: function() {
-                if (!navigator.isStepVisible(stepName)()) {
-                    navigator.goToStep(stepName);
-                }
-            },
-            isNewAddressSelected: function() {
-                if (!this.customerAddressCount) {
-                    newAddressSelected(true);
-                    return true;
-                }
-                return newAddressSelected();
-            },
-            validate: function() {
-                this.source.set('params.invalid', false);
-                this.source.trigger('shippingAddress.data.validate');
-            },
-            isCustomerLoggedIn: customer.isLoggedIn(),
-            customerAddressCount: window.checkoutConfig.customerAddressCount
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..16ed0dbabc78b5ca4141a2c946b6dec97ed34c69
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js
@@ -0,0 +1,53 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define([
+    'jquery',
+    'ko',
+    'uiComponent',
+    'Magento_Checkout/js/action/select-shipping-address',
+    'Magento_Checkout/js/model/quote',
+    'Magento_Checkout/js/model/shipping-address/form-popup-state'
+], function($, ko, Component, selectShippingAddressAction, quote, formPopUpState) {
+    'use strict';
+    var countryData = window.checkoutConfig.countryData;
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Checkout/shipping-address/address-renderer/default'
+        },
+
+        initProperties: function () {
+            this._super();
+            this.isSelected = ko.computed(function() {
+                var isSelected = false;
+                var shippingAddress = quote.shippingAddress();
+                if (shippingAddress) {
+                    isSelected = shippingAddress.getKey() == this.address().getKey();
+                }
+                return isSelected;
+            }, this);
+
+            return this;
+        },
+
+        getCountryName: function(countryId) {
+            return (countryData[countryId] != undefined) ? countryData[countryId].name : "";
+        },
+
+        /** Set selected customer shipping address  */
+        selectAddress: function() {
+            selectShippingAddressAction(this.address());
+        },
+
+        editAddress: function() {
+            formPopUpState.isVisible(true);
+            this.showPopup();
+
+        },
+        showPopup: function() {
+            $('[data-open-modal="opc-new-shipping-address"]').trigger('click');
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js
new file mode 100644
index 0000000000000000000000000000000000000000..352d8e628e37f4a598115181c8a3c576e56b8ed2
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js
@@ -0,0 +1,84 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define([
+    'underscore',
+    'ko',
+    'mageUtils',
+    'uiComponent',
+    'Magento_Ui/js/core/renderer/layout',
+    'Magento_Customer/js/model/address-list'
+], function (_, ko, utils, Component, layout, addressList) {
+    'use strict';
+    var defaultRendererTemplate = {
+        parent: '${ $.$data.parentName }',
+        name: '${ $.$data.name }',
+        component: 'Magento_Checkout/js/view/shipping-address/address-renderer/default'
+    };
+
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Checkout/shipping-address/list',
+            visible: addressList().length > 0,
+            rendererTemplates: []
+        },
+
+        initialize: function () {
+            this._super()
+                .initChildren();
+
+            addressList.subscribe(
+                function(changes) {
+                    var self = this;
+                    changes.forEach(function(change) {
+                        if (change.status === 'added') {
+                           self.createRendererComponent(change.value, change.index);
+                        }
+                    });
+                },
+                this,
+                'arrayChange'
+            );
+            return this;
+        },
+
+        initProperties: function () {
+            this._super();
+            // the list of child components that are responsible for address rendering
+            this.rendererComponents = [];
+            return this;
+        },
+
+        initChildren: function () {
+            _.each(addressList(), this.createRendererComponent, this);
+            return this;
+        },
+
+        /**
+         * Create new component that will render given address in the address list
+         *
+         * @param address
+         * @param index
+         */
+        createRendererComponent: function (address, index) {
+            if (index in this.rendererComponents) {
+                this.rendererComponents[index].address(address);
+            } else {
+                // rendererTemplates are provided via layout
+                var rendererTemplate = (address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined)
+                    ? utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()])
+                    : defaultRendererTemplate;
+                var templateData = {
+                    parentName: this.name,
+                    name: index
+                };
+                var rendererComponent = utils.template(rendererTemplate, templateData);
+                utils.extend(rendererComponent, {address: ko.observable(address)});
+                layout([rendererComponent]);
+                this.rendererComponents[index] = rendererComponent;
+            }
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js
new file mode 100644
index 0000000000000000000000000000000000000000..d33dd69762f9ca3fab4c12c0ea05108d91e61764
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'uiComponent',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/shipping-service',
+        'Magento_Checkout/js/model/step-navigator'
+    ],
+    function($, Component, quote, shippingService, stepNavigator) {
+        'use strict';
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/shipping-information'
+            },
+
+            isVisible: function() {
+                return !quote.isVirtual() && stepNavigator.isProcessed('shipping');
+            },
+
+            getShippingMethodTitle: function() {
+                return shippingService.getTitleByCode(quote.shippingMethod())
+            },
+
+            back: function() {
+                // Temp solution for closing summary sliding panel on mobile MAGETWO-3864
+                $('#opc-sidebar').modal('toggleModal');
+                stepNavigator.back();
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..9df85f97d84c402e33a2dad71ad1e48bf5b643eb
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define([
+    'uiComponent'
+], function(Component) {
+    'use strict';
+    var countryData = window.checkoutConfig.countryData;
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Checkout/shipping-information/address-renderer/default'
+        },
+
+        getCountryName: function(countryId) {
+            return (countryData[countryId] != undefined) ? countryData[countryId].name : "";
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js
new file mode 100644
index 0000000000000000000000000000000000000000..36342149c66e6fcc140e5c1d6ab9316c45e26958
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js
@@ -0,0 +1,84 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define([
+    'jquery',
+    'ko',
+    'mageUtils',
+    'uiComponent',
+    'Magento_Ui/js/core/renderer/layout',
+    'Magento_Checkout/js/model/quote'
+], function ($, ko, utils, Component, layout, quote) {
+    'use strict';
+    var defaultRendererTemplate = {
+        parent: '${ $.$data.parentName }',
+        name: '${ $.$data.name }',
+        component: 'Magento_Checkout/js/view/shipping-information/address-renderer/default'
+    };
+
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Checkout/shipping-information/list',
+            rendererTemplates: {}
+        },
+
+        initialize: function () {
+            this._super()
+                .initChildren();
+
+            var self = this;
+            quote.shippingAddress.subscribe(function(address) {
+                self.createRendererComponent(address);
+            });
+            return this;
+        },
+
+        initProperties: function () {
+            this._super();
+            // the list of child components that are responsible for address rendering
+            this.rendererComponents = {};
+            return this;
+        },
+
+        initChildren: function () {
+            return this;
+        },
+
+        /**
+         * Create new component that will render given address in the address list
+         *
+         * @param address
+         */
+        createRendererComponent: function (address) {
+
+            $.each(this.rendererComponents, function(index, component) {
+                component.visible(false);
+            });
+
+            if (this.rendererComponents[address.getType()]) {
+                this.rendererComponents[address.getType()].address(address);
+                this.rendererComponents[address.getType()].visible(true);
+            } else {
+                // rendererTemplates are provided via layout
+                var rendererTemplate =
+                    (address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined)
+                    ? utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()])
+                    : defaultRendererTemplate;
+                var templateData = {
+                    parentName: this.name,
+                    name: address.getType()
+                };
+
+                var rendererComponent = utils.template(rendererTemplate, templateData);
+                utils.extend(
+                    rendererComponent,
+                    {address: ko.observable(address), visible: ko.observable(true)}
+                );
+                layout([rendererComponent]);
+                this.rendererComponents[address.getType()] = rendererComponent;
+            }
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js
deleted file mode 100644
index 29f4ebbca2a04b3d8d9eba738a9c734b3abd112b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'jquery',
-        'underscore',
-        'uiComponent',
-        '../model/quote',
-        '../model/shipping-service',
-        '../action/select-shipping-method',
-        'Magento_Catalog/js/price-utils',
-        'Magento_Checkout/js/model/step-navigator'
-    ],
-    function ($, _, Component, quote, shippingService, selectShippingMethod, priceUtils, navigator) {
-        var stepName = 'shippingMethod';
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/shipping-method'
-            },
-            stepClassAttributes: function() {
-                return navigator.getStepClassAttributes(stepName);
-            },
-            stepNumber: navigator.getStepNumber(stepName),
-            rates: shippingService.getSippingRates(),
-            // Checkout step navigation
-            isVisible: navigator.isStepVisible(stepName),
-            quoteHasShippingAddress: function() {
-                return quote.isVirtual() || quote.getShippingAddress();
-            },
-
-            selectedMethod: quote.getSelectedShippingMethod(),
-            verifySelectedMethodCode: function (data) {
-                if (this.selectedMethod() == data) {
-                    return data;
-                }
-                return false;
-            },
-
-            setShippingMethod: function (form) {
-                var item,
-                    customOptions = {};
-                for (item in this.elems()) {
-                    if ('submit' in this.elems()[item]) {
-                        customOptions = _.extend(customOptions, this.elems()[item].submit());
-                    }
-                }
-                form = $(form);
-                var code = form.find("input[name='shipping_method']:checked").val();
-                selectShippingMethod(code, customOptions, this.getAfterSelectCallbacks());
-            },
-            getAfterSelectCallbacks: function() {
-                var callbacks = [];
-                _.each(this.getAdditionalMethods(), function(view) {
-                    if (typeof view.afterSelect === 'function') {
-                        callbacks.push(view.afterSelect);
-                    }
-                });
-                return callbacks;
-            },
-            getAdditionalMethods: function() {
-                var methods = [];
-                _.each(this.getRegion('afterSelect')(), function(elem) {
-                    methods = _.union(methods, elem.elems());
-                });
-                return methods;
-            },
-            isActive: function() {
-                if (quote.isVirtual()) {
-                    navigator.setStepEnabled(stepName, false);
-                }
-                return !quote.isVirtual();
-            },
-            backToShippingAddress: function () {
-                navigator.setCurrent(stepName).goBack();
-            },
-            navigateToCurrentStep: function() {
-                if (!navigator.isStepVisible(stepName)()) {
-                    navigator.goToStep(stepName);
-                }
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..7a0b60c760956737ff6d178faaa8528a8754d470
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js
@@ -0,0 +1,241 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'Magento_Ui/js/form/form',
+        'ko',
+        'Magento_Customer/js/model/customer',
+        'Magento_Customer/js/model/address-list',
+        'Magento_Checkout/js/model/address-converter',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/action/create-shipping-address',
+        'Magento_Checkout/js/action/select-shipping-address',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-address/form-popup-state',
+        'Magento_Checkout/js/model/shipping-service',
+        'Magento_Checkout/js/action/select-shipping-method',
+        'Magento_Checkout/js/model/shipping-rate-registry',
+        'Magento_Checkout/js/action/set-shipping-information',
+        'Magento_Checkout/js/model/new-customer-address',
+        'Magento_Checkout/js/model/step-navigator',
+        'Magento_Ui/js/modal/modal',
+        'mage/translate'
+    ],
+    function(
+        $,
+        Component,
+        ko,
+        customer,
+        addressList,
+        addressConverter,
+        quote,
+        createShippingAddress,
+        selectShippingAddress,
+        shippingRatesValidator,
+        formPopUpState,
+        shippingService,
+        selectShippingMethodAction,
+        rateRegistry,
+        setShippingInformationAction,
+        newAddress,
+        stepNavigator,
+        modal,
+        $t
+    ) {
+        'use strict';
+        var rates = window.checkoutConfig.shippingRates.data,
+            rateKey = window.checkoutConfig.shippingRates.key;
+        var popUp = null;
+        if (addressList().length == 0) {
+            var address = new newAddress({});
+            rateRegistry.set(address.getCacheKey(), rates);
+            shippingService.setShippingRates(rates);
+            selectShippingAddress(address);
+        }
+
+        if (rateKey) {
+            rateRegistry.set(rateKey, rates);
+        }
+
+        selectShippingMethodAction(window.checkoutConfig.selectedShippingMethod);
+        shippingService.setShippingRates(rates);
+
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/shipping'
+            },
+            visible: ko.observable(!quote.isVirtual()),
+            isCustomerLoggedIn: customer.isLoggedIn,
+            isFormPopUpVisible: formPopUpState.isVisible,
+            isFormInline: addressList().length == 0,
+            isNewAddressAdded: ko.observable(false),
+            saveInAddressBook: true,
+            quoteIsVirtual: quote.isVirtual(),
+
+            initialize: function () {
+                var self = this;
+                this._super();
+                var shippingAddress = quote.shippingAddress();
+                if (!shippingAddress) {
+                    var isShippingAddressInitialized = addressList.some(function (address) {
+                        if (address.isDefaultShipping()) {
+                            selectShippingAddress(address);
+                            return true;
+                        }
+                        return false;
+                    });
+                    if (!isShippingAddressInitialized && addressList().length == 1) {
+                        selectShippingAddress(addressList()[0]);
+                    }
+                }
+                if (rates.length == 1) {
+                    selectShippingMethodAction(rates[0])
+                }
+
+                if (!quote.isVirtual()) {
+                    stepNavigator.registerStep('shipping', 'Shipping', this.visible, 10);
+                }
+
+                this.isFormPopUpVisible.subscribe(function(value) {
+                    if (value) {
+                        self.getPopUp().openModal();
+                    }
+                });
+
+                return this;
+            },
+
+            initElement: function(element) {
+                if (element.index === 'shipping-address-fieldset') {
+                    shippingRatesValidator.bindChangeHandlers(element.elems());
+                }
+            },
+
+            getPopUp: function() {
+                var self = this;
+                if (!popUp) {
+                    var buttons = this.popUpForm.options.buttons;
+                    this.popUpForm.options.buttons = [
+                        {
+                            text: buttons.save.text ? buttons.save.text : $t('Save Address'),
+                            class: buttons.save.class ? buttons.save.class : 'action primary action-save-address',
+                            click: self.saveNewAddress.bind(self)
+                        },
+                        {
+                            text: buttons.cancel.text ? buttons.cancel.text: $t('Cancel'),
+                            class: buttons.cancel.class ? buttons.cancel.class : 'action secondary action-hide-popup',
+                            click: function() {
+                                this.closeModal();
+                            }
+                        }
+                    ];
+                    this.popUpForm.options.closed = function() {
+                        self.isFormPopUpVisible(false);
+                    };
+                    popUp = modal(this.popUpForm.options, $(this.popUpForm.element));
+                }
+                return popUp;
+            },
+
+            /** Show address form popup */
+            showFormPopUp: function() {
+                this.isFormPopUpVisible(true);
+            },
+
+
+            /** Save new shipping address */
+            saveNewAddress: function() {
+                this.source.set('params.invalid', false);
+                this.source.trigger('shippingAddress.data.validate');
+
+                if (!this.source.get('params.invalid')) {
+                    var addressData = this.source.get('shippingAddress');
+                    addressData.save_in_address_book = this.saveInAddressBook;
+
+                    // New address must be selected as a shipping address
+                    selectShippingAddress(createShippingAddress(addressData));
+                    this.getPopUp().closeModal();
+                    this.isNewAddressAdded(true);
+                }
+            },
+
+            /** Shipping Method View **/
+            rates: shippingService.getSippingRates(),
+            isLoading: shippingService.isLoading,
+            isSelected: ko.computed(function () {
+                    return quote.shippingMethod()
+                        ? quote.shippingMethod().carrier_code + '_' + quote.shippingMethod().method_code
+                        : null;
+                }
+            ),
+
+            selectShippingMethod: function(shippingMethod) {
+                selectShippingMethodAction(shippingMethod);
+                return true;
+            },
+
+            setShippingInformation: function () {
+                if (this.validateShippingInformation()) {
+                    setShippingInformationAction().done(
+                        function() {
+                            stepNavigator.next();
+                        }
+                    );
+                }
+            },
+
+            validateShippingInformation: function() {
+                var shippingAddress,
+                    addressData,
+                    loginFormSelector = 'form[data-role=email-with-possible-login]',
+                    emailValidationResult = customer.isLoggedIn();
+
+                if (!quote.shippingMethod()) {
+                    alert($t('Please specify a shipping method'));
+                    return false;
+                }
+
+                if (!customer.isLoggedIn()) {
+                    $(loginFormSelector).validation();
+                    emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid());
+                }
+
+                if (this.isFormInline) {
+                    this.source.set('params.invalid', false);
+                    this.source.trigger('shippingAddress.data.validate');
+                    if (this.source.get('params.invalid')
+                        || !quote.shippingMethod().method_code
+                        || !quote.shippingMethod().carrier_code
+                        || !emailValidationResult
+                    ) {
+                        return false;
+                    }
+                    shippingAddress = quote.shippingAddress();
+                    addressData = addressConverter.formAddressDataToQuoteAddress(
+                        this.source.get('shippingAddress')
+                    );
+
+                    //Copy form data to quote shipping address object
+                    for (var field in addressData) {
+                        if (addressData.hasOwnProperty(field)
+                            && shippingAddress.hasOwnProperty(field)
+                            && typeof addressData[field] != 'function'
+                        ) {
+                            shippingAddress[field] = addressData[field];
+                        }
+                    }
+
+                    if (customer.isLoggedIn()) {
+                        shippingAddress.save_in_address_book = true;
+                    }
+                    selectShippingAddress(shippingAddress);
+                }
+                return true;
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js
deleted file mode 100644
index 227129562f0e58471263236a60dff85ce8a26b0b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(
-    ['uiComponent'],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/iterator',
-                displayArea: 'totals'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary.js
similarity index 53%
rename from app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js
rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary.js
index 1d8f713edc4c829a97086f3df4b7b69a150ec92a..7a97079de6bcdf291c0bddacdf8b9e77efed2ac6 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary.js
@@ -2,17 +2,16 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*browser:true jquery:true*/
 /*global define*/
 define(
     [
-        'uiComponent'
+        'uiComponent',
+        'Magento_Checkout/js/model/totals'
     ],
-    function (Component) {
+    function(Component, totals) {
+        'use strict';
         return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/onepage'
-            }
+            isLoading: totals.isLoading
         });
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js
new file mode 100644
index 0000000000000000000000000000000000000000..35a4b0071d724572aefb3cc1faaeee68123f3606
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Catalog/js/price-utils',
+        'Magento_Checkout/js/model/totals',
+        'Magento_Checkout/js/model/step-navigator'
+    ],
+    function (Component, quote, priceUtils, totals, stepNavigator) {
+        "use strict";
+        return Component.extend({
+            getFormattedPrice: function (price) {
+                return priceUtils.formatPrice(price, quote.getPriceFormat());
+            },
+            getTotals: function() {
+                return totals.totals();
+            },
+            isFullMode: function() {
+                if (!this.getTotals()) {
+                    return false;
+                }
+                return stepNavigator.isProcessed('shipping');
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js
new file mode 100644
index 0000000000000000000000000000000000000000..0a41d2b46f2bfe4ec67d75d470b261e7fe7f3626
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'ko',
+        'Magento_Checkout/js/model/totals',
+        'uiComponent',
+        'Magento_Checkout/js/model/step-navigator',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function (ko, totals, Component, stepNavigator, quote) {
+        'use strict';
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/summary/cart-items'
+            },
+            totals: totals.totals(),
+            getItems: totals.getItems(),
+            getItemsQty: function() {
+                return parseInt(this.totals.items_qty) || 0;
+            },
+            isItemsBlockExpanded: function () {
+                return quote.isVirtual() || stepNavigator.isProcessed('shipping');
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f341a847edc1f10af2ed256c115573212899d75
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js
@@ -0,0 +1,32 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function (Component, quote) {
+        "use strict";
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/summary/grand-total'
+            },
+            isDisplayed: function() {
+                return this.isFullMode();
+            },
+            getPureValue: function() {
+                var totals = quote.getTotals()();
+                if (totals) {
+                    return totals.grand_total;
+                }
+                return quote.grand_total;
+            },
+            getValue: function() {
+                return this.getFormattedPrice(this.getPureValue());
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js
similarity index 59%
rename from app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js
rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js
index 7e04d856621c69cb54018ea1aa937ddfad943163..1c965b0d5701be6269b412b9e825d1499531acca 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js
@@ -6,15 +6,15 @@
 /*global alert*/
 define(
     [
-        '../column'
+        'uiComponent',
+        '../../../model/quote',
+        'Magento_Catalog/js/price-utils'
     ],
-    function (column) {
+    function (Component, quote, priceUtils) {
         "use strict";
-        return column.extend({
+        return Component.extend({
             defaults: {
-                ownClass: 'name',
-                columnTitle: 'Product Name',
-                template: 'Magento_Checkout/review/item/columns/name'
+                template: 'Magento_Checkout/summary/item/details'
             },
             getValue: function(quoteItem) {
                 return quoteItem.name;
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js
similarity index 61%
rename from app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js
rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js
index f08fb4830a0db1ab8aa6e6e474fc0d83d90e03df..30d43f7369298743b79f1fb9d9d76e0de6c93044 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js
@@ -6,15 +6,14 @@
 /*global alert*/
 define(
     [
-        '../column'
+        'Magento_Checkout/js/view/summary/abstract-total'
     ],
-    function (column) {
+    function (viewModel) {
         "use strict";
-        return column.extend({
+        return viewModel.extend({
             defaults: {
-                ownClass: 'subtotal',
-                columnTitle: 'Subtotal',
-                template: 'Magento_Checkout/review/item/columns/price'
+                displayArea: 'after_details',
+                template: 'Magento_Checkout/summary/item/details/subtotal'
             },
             getValue: function(quoteItem) {
                 return this.getFormattedPrice(quoteItem.row_total);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js
new file mode 100644
index 0000000000000000000000000000000000000000..2efdc4f91f4b071b79cd916c5cc2e090981e5a29
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js
@@ -0,0 +1,52 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'uiComponent'
+    ],
+    function (Component) {
+        "use strict";
+        var imageData = window.checkoutConfig.imageData;
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/summary/item/details/thumbnail'
+            },
+            displayArea: 'before_details',
+            imageData: imageData,
+            getImageItem: function(item) {
+                if (this.imageData[item.item_id]) {
+                    return this.imageData[item.item_id];
+                }
+                return [];
+            },
+            getSrc: function(item) {
+                if (this.imageData[item.item_id]) {
+                    return this.imageData[item.item_id]['src'];
+                }
+                return null;
+            },
+            getWidth: function(item) {
+                if (this.imageData[item.item_id]) {
+                    return this.imageData[item.item_id]['width'];
+                }
+                return null;
+            },
+            getHeight: function(item) {
+                if (this.imageData[item.item_id]) {
+                    return this.imageData[item.item_id]['height'];
+                }
+                return null;
+            },
+            getAlt: function(item) {
+                if (this.imageData[item.item_id]) {
+                    return this.imageData[item.item_id]['alt'];
+                }
+                return null;
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..fdce6d6d37db2bb914517a0dfae21b31e63cdf0f
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js
@@ -0,0 +1,39 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/shipping-service'
+    ],
+    function ($, Component, quote, shippingService) {
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/summary/shipping'
+            },
+            quoteIsVirtual: quote.isVirtual(),
+            totals: quote.getTotals(),
+            getShippingMethodTitle: function() {
+                if (!this.isCalculated()) {
+                    return '';
+                }
+                return shippingService.getTitleByCode(quote.shippingMethod())
+            },
+            isCalculated: function() {
+                return this.totals() && this.isFullMode() && null != quote.shippingMethod();
+            },
+            getValue: function() {
+                if (!this.isCalculated()) {
+                    return this.notCalculatedMessage;
+                }
+                var price =  this.totals().shipping_amount;
+                return this.getFormattedPrice(price);
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js
new file mode 100644
index 0000000000000000000000000000000000000000..b5929a2b60562611adeac62ade8f95608d31ff32
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function (Component, quote) {
+        "use strict";
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Checkout/summary/subtotal'
+            },
+            getPureValue: function() {
+                var totals = quote.getTotals()();
+                if (totals) {
+                    return totals.subtotal;
+                }
+                return quote.subtotal;
+            },
+            getValue: function () {
+                return this.getFormattedPrice(this.getPureValue());
+            }
+
+        });
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js b/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js
deleted file mode 100644
index caca53e801396ac04e93ebbba53ebe2d4815bbfb..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Checkout/review/totals',
-                displayArea: 'totals'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html
index 263249c03824174fbc03630df6581d5e256b0909..f6a1e6e73a2bfcdb356a85b00747775a7d094ed4 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html
@@ -4,92 +4,81 @@
  * See COPYING.txt for license details.
  */
 -->
-<li id="opc-billing"
-    data-bind="visible: isActive(), attr: {'class': stepClassAttributes() }"
-    role="presentation"
-    data-collapsible="true">
-    <div class="step-title"
-         data-role="title"
-         data-bind="click: navigateToCurrentStep"
-         aria-controls="checkout-step-login"
-         role="tab">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Checkout Method')"></h2>
-    </div>
-    <div id="checkout-step-authentication" class="step-content" data-role="content" data-bind="fadeVisible: isVisible()" >
+<div class="authentication-wrapper" data-block="authentication" data-bind="visible: isActive()">
+    <button
+        type="button"
+        class="action action-auth-toggle"
+        data-trigger="authentication">
+        <span data-bind="text: $t('Sign In')"></span>
+    </button>
+    <div class="block-authentication"
+         style="display: none"
+         data-bind="mageInit: {
+            'Magento_Ui/js/modal/modal':{
+                'type': 'custom',
+                'modalClass': 'authentication-dropdown',
+                'trigger': '[data-trigger=authentication]',
+                'wrapperClass': 'authentication-wrapper',
+                'parentModalClass': '_has-modal-custom _has-auth-shown',
+                'responsive': true,
+                'responsiveClass': 'custom-slide',
+                'overlayClass': 'dropdown-overlay modal-custom-overlay',
+                'buttons': []
+            }}">
         <!-- ko foreach: getRegion('before') -->
         <!-- ko template: getTemplate() --><!-- /ko -->
         <!-- /ko -->
-        <div class="login-wrapper">
-            <!-- ko if: (isGuestCheckoutAllowed) -->
-            <div class="block block-guest">
-                <div class="block-title">
-                    <strong id="block-guest-heading" role="heading" aria-level="2">
-                    <!--ko text: $t('Check Out as a Guest')--><!--/ko-->
-                    </strong>
-                </div>
-                <div class="block-content" aria-labelledby="block-guest-heading">
+        <div class="block block-customer-login"
+             data-bind="attr: {'data-label': $t('or')}">
+            <div class="block-title">
+                <strong id="block-customer-login-heading"
+                        role="heading"
+                        aria-level="2"
+                        data-bind="text: $t('Sign In')"></strong>
+            </div>
+            <div class="block-content" aria-labelledby="block-customer-login-heading">
+                <form data-role="login"
+                      data-bind="submit:login"
+                      method="post">
+                    <div class="fieldset"
+                              data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
+                        <div class="field field-email required">
+                            <label class="label" for="login-email"><span data-bind="text: $t('Email Address')"></span></label>
+                            <div class="control">
+                                <input type="email"
+                                       class="input-text"
+                                       id="login-email"
+                                       name="username"
+                                       data-validate="{required:true, 'validate-email':true}" />
+                            </div>
+                        </div>
+                        <div class="field field-password required">
+                            <label for="login-password" class="label"><span data-bind="text: $t('Password')"></span></label>
+                            <div class="control">
+                                <input type="password"
+                                       class="input-text"
+                                       id="login-password"
+                                       name="password"
+                                       data-validate="{required:true, 'validate-password':true}"/>
+                            </div>
+                        </div>
+                        <!-- ko foreach: getRegion('additional-login-form-fields') -->
+                        <!-- ko template: getTemplate() --><!-- /ko -->
+                        <!-- /ko -->
+                    </div>
                     <div class="actions-toolbar">
+                        <input name="context" type="hidden" value="checkout" />
                         <div class="primary">
-                            <!-- ko if: (isGuestCheckoutAllowed)-->
-                            <button data-bind="visible: isGuestCheckoutAllowed, click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action continue primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span data-bind="text: $t('Continue')"></span></button>
-                            <!-- /ko -->
-                            <!-- ko ifnot: isGuestCheckoutAllowed -->
-                                <!-- ko if: isCustomerLoginRequired -->
-                                    <input type="checkbox" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register" checked="checked" style="display: none"/>
-                                    <button data-bind="click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":false, "registrationUrl":"registerUrl"}'><span data-bind="text: $t('Create an Account')"></span></button>
-                                <!-- /ko -->
-                                <!-- ko ifnot: isCustomerLoginRequired -->
-                                    <input type="checkbox" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register" checked="checked" style="display: none"/>
-                                    <button data-bind="click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span data-bind="text: $t('Create an Account')"></span></button>
-                                <!-- /ko -->
-                            <!-- /ko -->
+                            <button type="submit" class="action action-login secondary"><span data-bind="text: $t('Sign In')"></span></button>
+                        </div>
+                        <div class="secondary">
+                            <a class="action action-remind" data-bind="attr: { href: forgotPasswordUrl }">
+                                <span data-bind="text: $t('Forgot Password')"></span>
+                            </a>
                         </div>
                     </div>
-                </div>
-            </div>
-            <!-- /ko -->
-            <div class="block block-customer-login">
-                <div class="block-title">
-                    <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="text: $t('Login')"></strong>
-                </div>
-                <div class="block-content" aria-labelledby="block-customer-login-heading">
-                    <form class="form login" data-role="login"
-                          data-bind="submit:login"
-                          method="post"
-                          data-mage-init='{"validation":{}}'>
-                        <fieldset class="fieldset login" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
-                            <div class="field note" data-bind="text: $t('Already registered? Please sign in below:')"></div>
-                            <div class="field email required">
-                                <label class="label" for="login-email"><span data-bind="text: $t('Email')"></span></label>
-                                <div class="control">
-                                    <input type="email" class="input-text" id="login-email" name="username" data-validate="{required:true, 'validate-email':true}" data-bind="value: username" />
-                                </div>
-                            </div>
-                            <div class="field password required">
-                                <label for="login-password" class="label"><span data-bind="text: $t('Password')"></span></label>
-                                <div class="control">
-                                    <input type="password" class="input-text" id="login-password" name="password" data-bind="value:password" data-validate="{required:true, 'validate-password':true}"/>
-                                </div>
-                            </div>
-                            <!-- ko foreach: getRegion('additional-login-form-fields') -->
-                            <!-- ko template: getTemplate() --><!-- /ko -->
-                            <!-- /ko -->
-                            <div class="actions-toolbar">
-                                <input name="context" type="hidden" value="checkout" />
-                                <div class="primary">
-                                    <button type="submit" class="action login primary" data-action="checkout-method-login"><span data-bind="text: $t('Login')"></span></button>
-                                </div>
-                                <div class="secondary">
-                                    <a class="action remind" data-bind="attr: { href: forgotPasswordUrl }">
-                                        <span data-bind="text: $t('Forgot Your Password?')"></span>
-                                    </a>
-                                </div>
-                            </div>
-                        </fieldset>
-                    </form>
-                </div>
+                </form>
             </div>
         </div>
     </div>
-</li>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html
index baed4c7b53edbfb4715f8ddc7b3d9d8fe817074c..895f94e4cbd9404a667524f3e5cf29ba142371cd 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html
@@ -4,54 +4,23 @@
  * See COPYING.txt for license details.
  */
 -->
-<li id="opc-billing" data-bind="attr: {'class': stepClassAttributes() }" role="presentation">
-    <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Billing Information')"></h2>
-    </div>
-    <div id="checkout-step-billing" class="step-content" data-role="content" data-bind="fadeVisible: isVisible()">
-        <form class="form billing" id="co-billing-form" data-hasrequired="* Required Fields">
-            <!-- ko if: (customerAddressCount)-->
-            <div class="field addresses">
-                <label class="label" for="billing:address-select"><span data-bind="text: $t('Select a billing address from your address book or enter a new address.')"></span></label>
-                <div class="control">
-                    <select name="billing_address_id" id="billing:address-select" data-bind="
-                        options: billingAddresses(),
-                        optionsText: billingAddressesOptionsText,
-                        optionsValue: 'customerAddressId',
-                        value: selectedBillingAddressId,
-                        event: {change: onAddressChange(selectedBillingAddressId)};
-                    "></select>
-                </div>
-            </div>
-            <!--/ko-->
-            <fieldset id="billing-new-address-form" class="fieldset address"
-                      data-bind="fadeVisible: isNewAddressSelected(), event {change: hideExtraFields()}">
-
-            <!-- ko foreach: getRegion('additional-fieldsets') -->
-            <!-- ko template: getTemplate() --><!-- /ko -->
-            <!--/ko-->
-            </fieldset>
-            <!-- ko if: quoteIsVirtual == 0 -->
-            <div class="field choice">
-                <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_yes" value="1" checked="checked" class="radio" data-bind="checked: useForShipping" />
-                <label class="label" for="billing:use_for_shipping_yes"><span><!-- ko text: $t('Ship to this address')--><!-- /ko --> </span></label>
-            </div>
-            <div class="field choice">
-                <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_no" value="0" class="radio" data-bind="checked: useForShipping" />
-                <label class="label" for="billing:use_for_shipping_no"><span><!-- ko text: $t('Ship to different address')--><!-- /ko --></span></label>
-            </div>
-                <!-- ko foreach: getRegion('additional-field-choice') -->
-                    <!-- ko template: getTemplate() --><!-- /ko -->
-                <!-- /ko -->
-            <!-- /ko -->
+<div class="billing-address-same-as-shipping-block field choice" data-bind="visible: canUseShippingAddress()">
+    <input type="checkbox" name="billing-address-same-as-shipping" data-bind="checked: isAddressSameAsShipping, click: useShippingAddress, attr: {id: 'billing-address-same-as-shipping-' + $parent.getCode()}"/>
+    <label data-bind="text: $t('My billing and shipping address are the same'), attr: {for: 'billing-address-same-as-shipping-' + $parent.getCode()}"></label>
+</div>
 
-            <input type="hidden" name="billing[use_for_shipping]" value="1" />
-            <div class="actions" id="billing-buttons-container">
-                <div class="primary">
-                    <button data-role="opc-continue" type="button" class="action continue primary" data-bind="click: submitBillingAddress"><span><!-- ko text: $t('Continue')--><!-- /ko --></span></button>
-                </div>
-            </div>
-        </form>
+<!-- ko template: 'Magento_Checkout/billing-address/details' --><!-- /ko -->
+<fieldset class="fieldset" data-bind="visible: !isAddressDetailsVisible()">
+    <!-- ko template: 'Magento_Checkout/billing-address/list' --><!-- /ko -->
+    <!-- ko template: 'Magento_Checkout/billing-address/form' --><!-- /ko -->
+    <div class="actions-toolbar">
+        <div class="primary">
+            <button class="action action-update" type="button" data-bind="click: updateAddress">
+                <span data-bind="text: $t('Update')"></span>
+            </button>
+            <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit">
+                <span data-bind="text: $t('Cancel')"></span>
+            </button>
+        </div>
     </div>
-</li>
+</fieldset>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
new file mode 100644
index 0000000000000000000000000000000000000000..3d7d38a0f4aa80de63c750c37b0c489572300055
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
@@ -0,0 +1,18 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="billing-address-details" data-bind="if: isAddressDetailsVisible() && currentBillingAddress()">
+    <!-- ko text: currentBillingAddress().firstname --><!-- /ko --> <!-- ko text: currentBillingAddress().lastname --><!-- /ko --><br/>
+    <!-- ko text: currentBillingAddress().street --><!-- /ko --><br/>
+    <!-- ko text: currentBillingAddress().city --><!-- /ko -->, <!-- ko text: currentBillingAddress().region --><!-- /ko --> <!-- ko text: currentBillingAddress().postcode --><!-- /ko --><br/>
+
+    <!-- ko text: currentBillingAddress().telephone --><!-- /ko --><br/>
+    <button type="button"
+            class="action action-edit-address"
+            data-bind="visible: !isAddressSameAsShipping(), click: editAddress">
+        <span data-bind="text: $t('Edit')"></span>
+    </button>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html
new file mode 100644
index 0000000000000000000000000000000000000000..4174aa194d635afdd5220f2076a8ac71e985a0a7
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html
@@ -0,0 +1,26 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible">
+    <!-- ko foreach: getRegion('before-fields') -->
+    <!-- ko template: getTemplate() --><!-- /ko -->
+    <!--/ko-->
+    <form data-hasrequired="* Required Fields">
+        <fieldset id="billing-new-address-form" class="fieldset address">
+            <!-- ko foreach: getRegion('additional-fieldsets') -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+            <!-- ko if: (isCustomerLoggedIn && customerHasAddresses) -->
+            <div class="choice field">
+                <input type="checkbox" class="checkbox" id="billing-save-in-address-book" data-bind="checked: saveInAddressBook" />
+                <label class="label" for="billing-save-in-address-book">
+                    <span data-bind="text: $t('Save in address book')"></span>
+                </label>
+            </div>
+            <!-- /ko -->
+        </fieldset>
+    </form>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..f826ede448372134c8e7084dadbc973443492ed0
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html
@@ -0,0 +1,17 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="field field-select-billing">
+    <label class="label"><span data-bind="text: $t('My billing and shipping address are the same')"></span></label>
+    <div class="control" data-bind="if: (addressOptions.length > 1)">
+        <select class="select" name="billing_address_id" data-bind="
+        options: addressOptions,
+        optionsText: addressOptionsText,
+        value: selectedAddress,
+        event: {change: onAddressChange(selectedAddress())};
+    "></select>
+    </div>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html
new file mode 100644
index 0000000000000000000000000000000000000000..a2d2941754ff84e19bd81ff0acecce2056ee83d5
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html
@@ -0,0 +1,89 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<div class="block-authentication"
+     data-bind="afterRender: setModalElement, blockLoader: isLoading"
+     style="display: none">
+    <div class="block block-new-customer"
+         data-label="or">
+        <div class="block-title">
+            <strong id="block-new-customer-heading" role="heading" aria-level="2" data-bind="text: $t('Checkout out as a new customer')"></strong>
+        </div>
+        <div class="block-content" aria-labelledby="block-new-customer-heading">
+            <p data-bind="text: $t('Creating an account has many benefits:')"></p>
+            <ul>
+                <li data-bind="text: $t('See order and shipping status')"></li>
+                <li data-bind="text: $t('Track order history')"></li>
+                <li data-bind="text: $t('Check out faster')"></li>
+            </ul>
+            <div class="actions-toolbar">
+                <div class="primary">
+                    <a class="action action-register primary" data-bind="attr: {href: registerUrl}">
+                        <span data-bind="text: $t('Create Account')"></span>
+                    </a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="block block-customer-login"
+         data-label="or">
+        <div class="block-title">
+            <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="text:$t('Checkout out using your account')"></strong>
+        </div>
+        <!-- ko foreach: getRegion('messages') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+        <!-- ko foreach: getRegion('before') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- /ko -->
+        <div class="block-content" aria-labelledby="block-customer-login-heading">
+            <form class="form form-login"
+                  method="post"
+                  data-bind="submit:login"
+                  id="login-form">
+                <div class="fieldset login" data-hasrequired="* Required Fields">
+                    <div class="field email required">
+                        <label class="label" for="email"><span data-bind="text: $t('Email Address')"></span></label>
+                        <div class="control">
+                            <input name="username"
+                                   id="email"
+                                   type="email"
+                                   class="input-text"
+                                   data-validate="{required:true, 'validate-email':true}">
+                        </div>
+                    </div>
+                    <div class="field password required">
+                        <label for="pass" class="label"><span data-bind="text: $t('Password')"></span></label>
+                        <div class="control">
+                            <input name="password"
+                                   type="password"
+                                   class="input-text"
+                                   id="pass"
+                                   data-validate="{required:true, 'validate-password':true}">
+                        </div>
+                    </div>
+                    <!-- ko foreach: getRegion('additional-login-form-fields') -->
+                    <!-- ko template: getTemplate() --><!-- /ko -->
+                    <!-- /ko -->
+                    </div>
+                    <div class="actions-toolbar">
+                        <input name="context" type="hidden" value="checkout" />
+                        <div class="primary">
+                            <button type="submit" class="action action-login secondary" name="send" id="send2">
+                                <span data-bind="text: $t('Sign In')"></span>
+                            </button>
+                        </div>
+                        <div class="secondary">
+                            <a class="action" data-bind="attr: {href: forgotPasswordUrl}">
+                                <span data-bind="text: $t('Forgot Your Password?')"></span>
+                            </a>
+                        </div>
+                    </div>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html
index 82475d90a25234b62a37c5e8c73fd01e5d0d61b8..a2fe08baaa52a4265d71b256b2d675514a380047 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html
@@ -98,3 +98,6 @@
         <!-- /ko -->
     </div>
 </div>
+<!-- ko foreach: getRegion('sign-in-popup') -->
+<!-- ko template: getTemplate() --><!-- /ko -->
+<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html
index 7a5432c380b5579dff032a888203426d61ae03ea..ee9b97ccd8ab3441c0f7942baf948799ea2aba9c 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html
@@ -33,9 +33,9 @@
 
             <!-- ko if: options.length -->
             <div class="product options" data-mage-init='{"collapsible":{"openedState": "active", "saveState": false}}'>
-                <span data-role="title" class="more toggle"><!-- ko text: $t('See Details') --><!-- /ko --></span>
+                <span data-role="title" class="toggle"><!-- ko text: $t('See Details') --><!-- /ko --></span>
 
-                <div data-role="content" class="product options details content">
+                <div data-role="content" class="content">
                     <strong class="subtitle"><!-- ko text: $t('Options Details') --><!-- /ko --></strong>
                     <dl class="product options list">
                         <!-- ko foreach: { data: options, as: 'option' } -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/onepage.html b/app/code/Magento/Checkout/view/frontend/web/template/onepage.html
index b05de111621164ef6ff48603fa307eb087c49812..51b80426e5dd4a8fc930916241602f4d28da9681 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/onepage.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/onepage.html
@@ -4,19 +4,70 @@
  * See COPYING.txt for license details.
  */
 -->
+<!-- ko foreach: getRegion('authentication') -->
+<!-- ko template: getTemplate() --><!-- /ko -->
+<!--/ko-->
 
-<!-- ko foreach: getRegion('errors') -->
+<!-- ko foreach: getRegion('progressBar') -->
 <!-- ko template: getTemplate() --><!-- /ko -->
 <!--/ko-->
+
+<!-- Temp MAGETWO-36025 markup -->
+<div class="opc-estimated-wrapper">
+<!-- Markup for MAGETWO-38644 -->
+    <div class="estimated-block">
+        <span class="estimated-label" data-bind="text: $t('Estimated Total')"></span>
+        <span class="estimated-price">$100.00</span>
+    </div>
+    <div class="minicart-wrapper">
+        <button type="button" class="action showcart" data-toggle="opc-summary">
+            <span class="counter qty">
+                <span class="counter-number">6</span>
+            </span>
+        </button>
+    </div>
+    <!-- Temp MAGETWO-36025 markup
+    <button
+        type="button"
+        class="action showcart"
+        data-toggle="opc-summary">
+        <span data-bind="text: $t('View order summary')"></span>
+    </button>-->
+</div>
+<!-- /Temp MAGETWO-36025 markup -->
+
+<!-- ko foreach: getRegion('messages') -->
+    <!-- ko template: getTemplate() --><!-- /ko -->
+<!--/ko-->
 <div class="opc-wrapper">
     <ol class="opc" id="checkoutSteps">
     <!-- ko foreach: getRegion('steps') -->
-    <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
     <!--/ko-->
     </ol>
 </div>
-<div id="checkout-progress-wrapper" class="opc-block-progress-wrapper">
-    <!-- ko foreach: getRegion('progress') -->
-    <!-- ko template: getTemplate() --><!-- /ko -->
+
+<div id="opc-sidebar"
+    data-bind="mageInit: {
+    'Magento_Ui/js/modal/modal':{
+        'type': 'custom',
+        'modalClass': 'opc-sidebar opc-summary-wrapper',
+        'trigger': '[data-toggle=opc-summary]',
+        'wrapperClass': 'checkout-container',
+        'parentModalClass': '_has-modal-custom',
+        'responsive': true,
+        'responsiveClass': 'custom-slide',
+        'overlayClass': 'modal-custom-overlay',
+        'buttons': []
+    }}">
+
+    <!-- ko foreach: getRegion('summary') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
     <!--/ko-->
+
+    <div class="opc-block-shipping-information">
+        <!-- ko foreach: getRegion('shipping-information') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+    </div>
 </div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..386f34af57ecc0486acaca9b73b2f62cf4fe4f5e
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html
@@ -0,0 +1,12 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<div class="items payment-methods">
+    <!-- ko foreach: { data: getRegion('payment-method-items'), as: 'element'}  -->
+        <!-- ko template: element.getTemplate() --><!-- /ko -->
+    <!-- /ko -->
+</div>
+<!-- ko ifnot: getRegion('payment-method-items')().length > 0 --><div class="no-payments-block"><!-- ko text: $t('No Payment Methods')--><!-- /ko --></div><!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment.html b/app/code/Magento/Checkout/view/frontend/web/template/payment.html
index af29231586341e0e2f2cb46ab944a52f6823b77b..d289eacc124401c39893b337149972af7245254e 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/payment.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/payment.html
@@ -4,59 +4,33 @@
  * See COPYING.txt for license details.
  */
 -->
-<li id="opc-payment" data-bind=", attr: {'class': stepClassAttributes() }" role="presentation">
-    <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Payment Information')"></h2>
-    </div>
+<li id="opc-payment" role="presentation" class="checkout-payment-method" data-bind="fadeVisible: isVisible">
+    <div class="step-title" data-bind="text: $t(title)" data-role="title"></div>
     <div id="checkout-step-payment"
          class="step-content"
          data-role="content"
          role="tabpanel"
-         aria-hidden="false"
-         data-bind="fadeVisible: isVisible() && quoteHasShippingMethod()">
-        <form id="co-payment-form" class="form payments" novalidate="novalidate" data-bind="submit: setPaymentMethod">
+         aria-hidden="false">
+        <!-- ko if: (quoteIsVirtual) -->
+            <!-- ko foreach: getRegion('customer-email') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        <!--/ko-->
+        <form id="co-payment-form" class="form payments" novalidate="novalidate">
             <input data-bind='attr: {value: getFormKey()}' type="hidden" name="form_key"/>
             <fieldset class="fieldset">
-                <legend class="legend payments-title">
-                    <span><!-- ko text: $t('Payment Information')--><!-- /ko --></span>`
-                </legend>
-                <br>
                 <!-- ko foreach: getRegion('beforeMethods') -->
                     <!-- ko template: getTemplate() --><!-- /ko -->
                 <!-- /ko -->
                 <div id="checkout-payment-method-load" class="opc-payment">
-                    <dl class="items methods-payment">
-                        <!-- ko foreach: getAvailableViews() -->
-                        <dt data-bind='attr: {class: "item-title " + getCode()}'>
-                            <input data-bind='attr: {id: "p_method_" + getCode(), value: getCode(), title: getTitle(), class: "radio" + $parent.getMethodControlAdditionalClass()}, checked: $parent.activeMethod, enable: isEnabled' type="radio" name="payment[method]"/>
-                            <label data-bind='attr: {for: "p_method_" + getCode()}'><!-- ko template: titleTemplate --><!--/ko--></label>
-                        </dt>
-                        <!-- ko if: $data.formTemplate -->
-                        <dd data-bind='attr: {class: "item-content " + getCode()}, visible: $parent.isMethodActive(getCode()), enable: isEnabled'><!-- ko template: formTemplate --><!--/ko--></dd>
-                        <!-- /ko -->
-                        <!-- /ko -->
-                        <!-- ko ifnot: getAvailableViews().length > 0 -->
-                        <dt class="item-title"><!-- ko text: $t('No Payment Methods')--><!-- /ko --></dt>
-                        <!-- /ko -->
-                    </dl>
+                    <!-- ko foreach: getRegion('payment-methods-list') -->
+                        <!-- ko template: getTemplate() --><!-- /ko -->
+                    <!-- /ko -->
                 </div>
                 <!-- ko foreach: getRegion('afterMethods') -->
                     <!-- ko template: getTemplate() --><!-- /ko -->
                 <!-- /ko -->
             </fieldset>
-            <div class="actions-toolbar" id="payment-buttons-container">
-                <div class="primary">
-                    <button data-role="opc-continue"
-                            type="submit"
-                            class="button action continue primary">
-                        <span><!-- ko text: $t('Continue')--><!-- /ko --></span>
-                    </button>
-                </div>
-                <div class="secondary">
-                    <a class="action back" href="#" data-bind="click: backToShippingMethod"><span>Back</span></a>
-                </div>
-            </div>
         </form>
     </div>
 </li>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html
new file mode 100644
index 0000000000000000000000000000000000000000..6c13c80261d707b2e8b8930ff8e5642035231b11
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html
@@ -0,0 +1,13 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<ul class="opc-progress-bar">
+    <!-- ko foreach: { data: steps().sort(sortItems), as: 'item' } -->
+        <li class="opc-progress-bar-item" data-bind="css: item.isVisible() ? '_active' : ($parent.isProcessed(item) ? '_complete' : '')">
+            <span data-bind="text: $t(item.title), click: $parent.navigateTo"></span>
+        </li>
+    <!-- /ko -->
+</ul>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/progress.html b/app/code/Magento/Checkout/view/frontend/web/template/progress.html
deleted file mode 100644
index 2831a845897496816dd57d0fefadecd98b44390d..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/progress.html
+++ /dev/null
@@ -1,146 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-    <div data-bind = "attr: {'class': getClassName()}">
-    <div class="title">
-        <strong data-bind="text: $t('Your Checkout Progress')"></strong>
-    </div>
-    <div class="content">
-        <dl class="items">
-            <!-- ko if: isShowStep('billingAddress') -->
-            <!-- ko if: isStepComplete('billingAddress') -->
-            <dt class="item-title complete">
-                <span id="billing-address-label" data-bind="text: $t('Billing Address')"></span>
-                <a href="#billing"
-                   data-goto-section="billing"
-                   class="action billing"
-                   aria-describedby="billing-address-label" data-bind="text: $t('Change'), click: goToStep('billingAddress')">
-                </a>
-            </dt>
-            <dd class="item-content complete">
-                <address data-bind="html:getBillingAddress()"></address>
-            </dd>
-            <!--/ko-->
-            <!-- ko ifnot: isStepComplete('billingAddress') -->
-            <dt class="item-title" data-bind="text: $t('Billing Address')"></dt>
-            <!--/ko-->
-            <!--/ko-->
-
-            <!-- ko if: isShowStep('shippingAddress') -->
-            <!-- ko if: isStepComplete('shippingAddress') -->
-            <dt class="item-title complete">
-                <span id="shipping-address-label" data-bind="text: $t('Shipping Address')"></span>
-                <a href="#payment"
-                   data-goto-section="shipping"
-                   class="action shipping address"
-                   aria-describedby="shipping-address-label" data-bind="text:$t('Change'), click: goToStep('shippingAddress')">
-                </a>
-            </dt>
-            <dd class="item-content complete">
-                <address data-bind="html:getShippingAddress()"></address>
-            </dd>
-            <!--/ko-->
-            <!-- ko ifnot: isStepComplete('shippingAddress') -->
-            <dt class="item-title">
-                <span data-bind="text:$t('Shipping Address')"></span>
-            </dt>
-            <!--/ko-->
-            <!--/ko-->
-
-            <!-- ko if: isShowStep('shippingMethod') -->
-            <!-- ko if: isStepComplete('shippingMethod') -->
-            <dt class="item-title complete">
-                <span id="shipping-method-label" data-bind="text:$t('Shipping Method')"></span>
-                <a href="#shipping_method"
-                   data-goto-section="shipping_method"
-                   class="action shipping method"
-                   aria-describedby="shipping-method-label" data-bind="text:$t('Change'), click: goToStep('shippingMethod')">
-                </a>
-            </dt>
-            <dd class="item-content complete">
-                <!--<?php if ($block->getShippingMethod()): ?>-->
-
-                <!-- ko text: getShippingMethodTitle() --><!--/ko-->
-
-                <!--shipping method price rendering-->
-
-                <!-- ko foreach: {data: getShippingRates(), as: 'item'} -->
-                    <!-- ko foreach: $parent.getRegion('shipping') -->
-                        <!-- ko template: getTemplate() --><!-- /ko -->
-                    <!--/ko-->
-                <!--/ko-->
-
-                <!-- ko ifnot : (getShippingRates().length > 0) -->
-                <!-- ko text: $t('Please choose a shipping method.') --><!--/ko-->
-                <!--/ko-->
-            </dd>
-            <!--/ko-->
-            <!-- ko ifnot: isStepComplete('shippingMethod') -->
-            <dt class="item-title">
-                <span data-bind="text:$t('Shipping Method')"></span>
-            </dt>
-            <!--/ko-->
-            <!--/ko-->
-
-            <!-- ko if: isShowStep('paymentMethod') -->
-            <!-- ko if: isStepComplete('paymentMethod') -->
-            <dt class="item-title complete">
-                <span id="payment-method-label" data-bind="text:$t('Payment Method')"></span>
-                <a href="#payment"
-                   data-goto-section="payment"
-                   class="action payment method"
-                   aria-describedby="payment-method-label" data-bind="text:$t('Change'), click: goToStep('paymentMethod')">
-                </a>
-            </dt>
-            <dd class="item-content complete">
-                <dl class="payment-method">
-                    <dt class="title"><!-- ko text: getPaymentMethodTitle() --><!--/ko--></dt>
-                    <dd class="content">
-                        <!-- ko if: getPaymentMethodInfo().length > 0 -->
-                        <table class="data table">
-                            <tbody data-bind="foreach: {data: getPaymentMethodInfo(), as: 'item'}">
-                            <!-- ko if: item.name && (item.value || item.html) -->
-                            <tr>
-                                <th scope="row" data-bind="html: $t(item.name)"></th>
-                                <!-- ko if: item.value -->
-                                <td data-bind="text: $t(item.value)"></td>
-                                <!--/ko-->
-                                <!-- ko if: !item.value && item.html -->
-                                <td data-bind="html: $t(item.html)"></td>
-                                <!--/ko-->
-                            </tr>
-                            <!--/ko-->
-                            <!-- ko if: item.name && !item.value && !item.html -->
-                            <tr>
-                                <th colspan="2" scope="row"><!-- ko text: $t(item.name) --><!--/ko--></th>
-                            </tr>
-                            <!--/ko-->
-                            <!-- ko if: !item.name && (item.value || item.html) -->
-                            <tr>
-                                <!-- ko if: item.value -->
-                                <td colspan="2" data-bind="text: $t(item.value)"></td>
-                                <!--/ko-->
-                                <!-- ko if: !item.value && item.html -->
-                                <td colspan="2" data-bind="html: $t(item.html)"></td>
-                                <!--/ko-->
-                            </tr>
-                            <!--/ko-->
-                            </tbody>
-                        </table>
-                        <!--/ko-->
-                    </dd>
-                </dl>
-            </dd>
-            <!--/ko-->
-            <!-- ko ifnot: isStepComplete('paymentMethod') -->
-            <dt class="item-title">
-                <span data-bind="text:$t('Payment Method')"></span>
-            </dt>
-            <!--/ko-->
-            <!--/ko-->
-        </dl>
-    </div>
-</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review.html b/app/code/Magento/Checkout/view/frontend/web/template/review.html
deleted file mode 100644
index 2258e50fd37a2a127040dbc0f3595e80c280012b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<li id="opc-review" data-bind="attr: {'class': stepClassAttributes() }" role="presentation">
-    <div class="step-title" data-role="title">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Order Review')"></h2>
-    </div>
-    <div id="checkout-step-review"
-         class="step-content"
-         data-role="content"
-         role="tabpanel"
-         aria-hidden="false"
-         data-bind="fadeVisible: isVisible() && quoteHasPaymentMethod()">
-        <div class="order-review" id="checkout-review-load">
-            <!-- ko foreach: getRegion('itemsBefore') -->
-                <!-- ko template: getTemplate() --><!-- /ko -->
-            <!-- /ko -->
-            <div id="checkout-review-table-wrapper" class="order-review-wrapper table-wrapper">
-                <table class="data table table-order-review items" id="checkout-review-table">
-                    <caption class="table-caption" data-bind="text: $t('Order Review')"></caption>
-                    <thead>
-                        <tr>
-                            <!-- ko foreach: getRegion('columns') -->
-                                <!-- ko foreach: elems() -->
-                                    <th class="col" scope="col" data-bind=" text: $t(getColName()) , attr: { class: getHeaderClass() }" ></th>
-                                <!-- /ko -->
-                            <!-- /ko -->
-                        </tr>
-                    </thead>
-                    <tbody>
-                    <!-- ko foreach: {data: getItems(), as: 'item'} -->
-                        <tr>
-                            <!-- ko foreach: $parent.getRegion('columns') -->
-                                <!-- ko template: getTemplate() --><!-- /ko -->
-                            <!-- /ko -->
-                        </tr>
-                    <!-- /ko -->
-                    </tbody>
-                    <tfoot>
-                    <!-- ko foreach: getRegion('totals') -->
-                    <!-- ko template: getTemplate() --><!-- /ko -->
-                    <!-- /ko -->
-                    </tfoot>
-                </table>
-            </div>
-            <!-- ko foreach: getRegion('itemsAfter') -->
-                <!-- ko template: getTemplate() --><!-- /ko -->
-            <!-- /ko -->
-            <div id="checkout-review-submit" data-mage-init='{"paymentAuthentication":{}}' class="checkout-submit-order">
-                <!-- ko foreach: getRegion('beforePlaceOrder') -->
-                    <!-- ko template: getTemplate() --><!-- /ko -->
-                <!-- /ko -->
-                <!-- ko foreach: getRegion('actions') -->
-                    <!-- ko template: getTemplate() --><!-- /ko -->
-                <!-- /ko -->
-            </div>
-        </div>
-    </div>
-</li>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html b/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html
deleted file mode 100644
index 3123b421025ed575861d20ea2b6ebc5902df48dd..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: getPureValue() != 0 -->
-<tr class="totals">
-    <th data-bind="text: $t(fieldName) , attr: {'style':style, 'colspan': colspan}" class="mark" scope="row">
-    </th>
-    <td data-bind="text: getValue(), attr: {'style': style, 'data-th': $t(name) }" class="amount"></td>
-</tr>
-<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html
deleted file mode 100644
index c32d4991c36b0bcacca083ee241d5ca5149f1fa9..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<td data-bind="attr: { 'data-th': getColName(), class: getClass() }">
-    <span data-bind="text: getValue($parents[1])"></span>
-</td>
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html
deleted file mode 100644
index 54f6daf92fd94f087ab5c8aba02fe9b7d9585391..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<td class="col item" data-th="Product Name"><strong class="product name product-item-name" data-bind="text: $t(item.name)"></strong>
-    <!-- ko foreach: elems() -->
-        <!-- ko template: getTemplate() --><!-- /ko -->
-    <!-- /ko -->
-
-    <!-- ko if: (JSON.parse(item.options).length > 0)-->
-    <dl class="item-options">
-        <!--ko foreach: JSON.parse(item.options)-->
-        <dt data-bind="text: $t(label)"></dt>
-            <!-- ko if: ($data.full_view)-->
-            <dd data-bind="html: full_view"></dd>
-            <!-- /ko -->
-            <!-- ko ifnot: ($data.full_view)-->
-            <dd data-bind="html: value"></dd>
-            <!-- /ko -->
-        <!-- /ko -->
-    </dl>
-    <!-- /ko -->
-</td>
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html
deleted file mode 100644
index 25e9e79a35d89d2487140d9b3b5db518927be2e5..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<td data-bind="attr: { 'data-th': getColName(), class: getClass() }">
-    <span class="cart-price">
-        <span class="price" data-bind="text: getValue($parents[1])"></span>
-    </span>
-</td>
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html
deleted file mode 100644
index cc5e4d63f7890acb036bb3adb5a681e689df3743..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<td class="col qty" data-th="Qty"><span class="qty" data-bind="text: item.qty"></span></td>
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html b/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html
deleted file mode 100644
index 3e2032f2c631a6bebe2e29d02589aa44cae5c0dc..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-
-<!-- ko foreach: elems() -->
-    <!-- ko template: getTemplate() --><!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html
deleted file mode 100644
index acd04e1fca45cfca1ead82a33c4d7c34de5637f0..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<li id="opc-shipping" data-bind="fadeVisible: isActive(), attr: {'class': stepClassAttributes() }">
-    <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Shipping Information')"></h2>
-    </div>
-    <div id="checkout-step-shipping"
-         class="step-content"
-         data-role="content"
-         data-bind="fadeVisible: isVisible() && quoteHasBillingAddress()">
-        <form class="form shipping address" id="co-shipping-form" data-hasrequired="* Required Fields">
-            <!-- ko foreach: getRegion('before-fields') -->
-            <!-- ko template: getTemplate() --><!-- /ko -->
-            <!--/ko-->
-            <!-- ko if: (customerAddressCount)-->
-            <div class="field addresses" data-bind="visible: visible">
-                <label class="label" for="shipping:address-select"><span data-bind="text: $t('Select a shipping address from your address book or enter a new address.')"></span></label>
-                <div class="control">
-                    <select name="shipping_address_id" id="shipping:address-select" data-bind="
-                    options: addresses(),
-                    optionsText: function(item) { return item.getAddressInline(); },
-                    optionsValue: 'customerAddressId',
-                    value: selectedAddressId,
-                    event: {change: onAddressChange}
-                    ">
-                    </select>
-                </div>
-            </div>
-            <!-- /ko -->
-            <fieldset id="shipping-new-address-form" class="fieldset address"
-                      data-bind="fadeVisible: isNewAddressSelected(), visible: formVisible">
-            <!-- ko foreach: getRegion('additional-fieldsets') -->
-            <!-- ko template: getTemplate() --><!-- /ko -->
-            <!--/ko-->
-            </fieldset>
-
-            <div class="choice field" data-bind="visible: visible">
-                <input type="checkbox"
-                       name="shipping[same_as_billing]"
-                       id="shipping:same_as_billing"
-                       value="1"
-                       checked="checked"
-                       class="checkbox"
-                       data-bind="checked: sameAsBilling, click: sameAsBillingClick"/>
-                <label class="label" for="shipping:same_as_billing">
-                    <span data-bind="text: $t('Use Billing Address')"></span>
-                </label>
-            </div>
-            <div class="actions-toolbar" id="shipping-buttons-container">
-                <div class="primary">
-                    <button data-role="opc-continue" type="button" class="action continue primary" data-bind="click: selectShippingAddress"><span data-bind="text: $t('Continue')"></span></button>
-                </div>
-                <div class="secondary"><a href="#" class="action back" data-bind="click: backToBilling"><span data-bind="text: $t('Back')"></span></a></div>
-            </div>
-        </form>
-    </div>
-</li>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
new file mode 100644
index 0000000000000000000000000000000000000000..af87b5805b51e16afb0fec1d006c170325f1675c
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
@@ -0,0 +1,21 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="shipping-address-item" data-bind="css: isSelected() ? 'selected-item' : 'not-selected-item'">
+    <!-- ko text: address().firstname --><!-- /ko --> <!-- ko text: address().lastname --><!-- /ko --><br/>
+    <!-- ko text: address().street --><!-- /ko --><br/>
+    <!-- ko text: address().city --><!-- /ko -->, <!-- ko text: address().region --><!-- /ko --> <!-- ko text: address().postcode --><!-- /ko --><br/>
+    <!-- ko text: getCountryName(address().countryId) --><!-- /ko --><br/>
+    <!-- ko text: address().telephone --><!-- /ko --><br/>
+    <button type="button"
+            class="action edit-address-link"
+            data-bind="click: editAddress, visible: address().isEditable()">
+        <span data-bind="text: $t('Edit')"></span>
+    </button>
+    <button type="button" data-bind="click: selectAddress" class="action action-select-shipping-item">
+        <span data-bind="text: $t('Ship Here')"></span>
+    </button>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html
new file mode 100644
index 0000000000000000000000000000000000000000..e450ee3fd9c3d04ae0c99208a64b244f3811c055
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html
@@ -0,0 +1,24 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<form class="form form-shipping-address" id="co-shipping-form" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
+    <!-- ko foreach: getRegion('before-fields') -->
+    <!-- ko template: getTemplate() --><!-- /ko -->
+    <!--/ko-->
+    <fieldset id="shipping-new-address-form" class="fieldset address">
+        <!-- ko foreach: getRegion('additional-fieldsets') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+        <!-- ko if: (isCustomerLoggedIn) -->
+        <div class="field choice" data-bind="visible: !isFormInline">
+            <input type="checkbox" class="checkbox" id="shipping-save-in-address-book" data-bind="checked: saveInAddressBook" />
+            <label class="label" for="shipping-save-in-address-book">
+                <span data-bind="text: $t('Save in address book')"></span>
+            </label>
+        </div>
+        <!-- /ko -->
+    </fieldset>
+</form>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..84b0b3679c69f0b1d3efbf0cdf633bd0ca0519e0
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html
@@ -0,0 +1,18 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<!-- ko if: (visible)-->
+<div class="field addresses">
+    <div class="control">
+        <div class="shipping-address-items">
+            <!-- ko foreach: { data: elems, as: 'element' } -->
+            <!-- ko template: element.getTemplate() --><!-- /ko -->
+            <!-- /ko -->
+        </div>
+    </div>
+</div>
+<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html
new file mode 100644
index 0000000000000000000000000000000000000000..6d262c39d9f0cd0bf99259e870819e6ddc63dafe
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html
@@ -0,0 +1,35 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<!-- ko if: (isVisible()) -->
+<div class="shipping-information">
+    <div class="ship-to">
+        <div class="shipping-information-title">
+            <span data-bind="text: $t('Ship To')"></span>
+            <button class="action action-edit" data-bind="click: back">
+                <span data-bind="text: $t('edit')"></span>
+            </button>
+        </div>
+        <div class="shipping-information-content">
+            <!-- ko foreach: getRegion('ship-to') -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+    </div>
+    <div class="ship-via">
+        <div class="shipping-information-title">
+            <span data-bind="text: $t('Ship Via')"></span>
+            <button class="action action-edit" data-bind="click: back">
+                <span data-bind="text: $t('edit')"></span>
+            </button>
+        </div>
+        <div class="shipping-information-content">
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </div>
+    </div>
+</div>
+<!--/ko-->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
new file mode 100644
index 0000000000000000000000000000000000000000..32d832ca3092a32e8b8687325903880ce9274ee6
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
@@ -0,0 +1,13 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: (visible()) -->
+    <!-- ko text: address().firstname --><!-- /ko --> <!-- ko text: address().lastname --><!-- /ko --><br/>
+    <!-- ko text: address().street --><!-- /ko --><br/>
+    <!-- ko text: address().city --><!-- /ko -->, <!-- ko text: address().region --><!-- /ko --> <!-- ko text: address().postcode --><!-- /ko --><br/>
+    <!-- ko text: getCountryName(address().countryId) --><!-- /ko --><br/>
+    <!-- ko text: address().telephone --><!-- /ko --><br/>
+<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/totals.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html
similarity index 53%
rename from app/code/Magento/Checkout/view/frontend/web/template/review/totals.html
rename to app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html
index 3e2032f2c631a6bebe2e29d02589aa44cae5c0dc..c7a1eb499da7079fc81eaf82513fa59a3c3346de 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/review/totals.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html
@@ -5,6 +5,6 @@
  */
 -->
 
-<!-- ko foreach: elems() -->
-    <!-- ko template: getTemplate() --><!-- /ko -->
+<!-- ko foreach: { data: elems, as: 'element' } -->
+<!-- ko template: element.getTemplate() --><!-- /ko -->
 <!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html
deleted file mode 100644
index 523c1eb3b34f4c2c47d692b4401f945bbe422471..0000000000000000000000000000000000000000
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<li id="opc-shipping_method" data-bind="fadeVisible: isActive(), attr: {'class': stepClassAttributes() }" role="presentation">
-    <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep">
-        <span class="number" data-bind="text: stepNumber()"></span>
-        <h2 data-bind="text: $t('Shipping Method')"></h2>
-    </div>
-    <div id="checkout-step-shipping_method"
-         class="step-content"
-         data-role="content"
-         role="tabpanel"
-         aria-hidden="false"
-         data-bind="fadeVisible: isVisible() && quoteHasShippingAddress()">
-        <!-- ko if: rates().length == 0 -->
-        <!-- ko text: $t('Sorry, no quotes are available for this order right now.')--><!-- /ko -->
-        <!-- /ko -->
-        <!-- ko if: rates().length  -->
-        <form class="form methods-shipping" id="co-shipping-method-form" data-bind="submit: setShippingMethod" novalidate="novalidate">
-            <div id="checkout-shipping-method-load">
-                <dl class="items methods-shipping">
-                    <!--ko foreach: { data: rates(), as: 'method'}-->
-                    <dt data-bind="text: $t(method.carrier_title), attr: {'class': 'item-title ' + method.carrier_code}"></dt>
-                    <dd data-bind="attr: {'class': 'item-content ' + method.carrier_code}">
-                        <fieldset class="fieldset">
-                            <legend class="legend"><span data-bind="text: $t(method.carrier_title)"></span></legend>
-                            <br>
-                            <!--ko foreach: { data: items, as: 'item'}-->
-                            <div class="field choice">
-                                <!-- ko if:  item.error_message -->
-                                <div class="message error">
-                                    <div data-bind="text: $t(item.error_message)"></div>
-                                </div>
-                                <span class="no-display">
-                                    <input name="shipping_method" type="radio" data-bind="attr: {'value' : item.method_code, 'id': 's_method_' + item.method_code}"/>
-                                </span>
-                                <!-- /ko -->
-                                <!-- ko ifnot: item.error_message -->
-                                <!-- ko if: $parent.items.length && $parents[1].rates().length == 1 -->
-                                <span class="no-display">
-                                    <input data-bind="attr: {'value' : item.carrier_code + '_' + item.method_code, 'id': 's_method_' + item.method_code}"
-                                           name="shipping_method" class="radio" type="radio" checked="checked"/>
-                                    </span>
-                                <!-- /ko -->
-                                 <!--ko ifnot: ($parent.items.length && $parents[1].rates().length == 1)-->
-                                <div class="control">
-                                    <input name="shipping_method" type="radio"
-                                           data-bind="checked:$parents[1].verifySelectedMethodCode(item.carrier_code + '_' + item.method_code), attr: {'value': item.carrier_code + '_' + item.method_code, 'id': 's_method_' + item.carrier_code + '_' + item.method_code}"
-                                           class="radio"/>
-                                </div>
-                                 <!--/ko-->
-                                <label class="label" data-bind="attr: {'for': 's_method_' + item.carrier_code + '_' + item.method_code}">
-                                    <span>
-                                        <!-- ko text: $t(item.method_title) --><!-- /ko -->
-                                        <!-- ko foreach: $parents[1].getRegion('price') -->
-                                            <!-- ko template: getTemplate() --><!-- /ko -->
-                                    <!-- /ko -->
-                                    </span>
-                                </label>
-                                <!-- /ko -->
-                            </div>
-                            <!-- /ko -->
-                        </fieldset>
-                    </dd>
-
-                    <!-- /ko -->
-                </dl>
-
-            </div>
-
-            <div id="onepage-checkout-shipping-method-additional-load">
-                <!-- ko foreach: getRegion('shippingAdditional') -->
-                    <!-- ko template: getTemplate() --><!-- /ko -->
-                <!-- /ko -->
-            </div>
-            <div class="actions-toolbar" id="shipping-method-buttons-container">
-                <div class="primary">
-                    <button data-role="opc-continue" type="submit" class="button action continue primary">
-                        <span><!-- ko text: $t('Continue')--><!-- /ko --></span>
-                    </button>
-                </div>
-                <div class="secondary">
-                    <a class="action back" href="#" data-bind="click: backToShippingAddress">
-                        <span><!-- ko text: $t('Back')--><!-- /ko --></span>
-                    </a>
-                </div>
-            </div>
-        </form>
-        <!-- /ko -->
-        </div>
-</li>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html
new file mode 100644
index 0000000000000000000000000000000000000000..a62f3634547c53e3aa887261e137761c78394705
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html
@@ -0,0 +1,141 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<li id="opc-shipping" data-bind="fadeVisible: visible()">
+    <div class="step-title" data-bind="text: $t('Shipping Address')" data-role="title"></div>
+    <div id="checkout-step-shipping"
+         class="step-content"
+         data-role="content">
+
+        <!-- ko if: (!quoteIsVirtual) -->
+            <!-- ko foreach: getRegion('customer-email') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        <!--/ko-->
+
+        <!-- ko foreach: getRegion('address-list') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+
+        <!-- ko foreach: getRegion('address-list-additional-addresses') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+
+        <!-- Address form pop up -->
+        <!-- ko if: (!isFormInline) -->
+        <button type="button"
+                data-bind="click: showFormPopUp, visible: !isNewAddressAdded()"
+                class="action action-show-popup">
+            <span data-bind="text: $t('New Address')"></span></button>
+        <div id="opc-new-shipping-address" data-bind="visible: isFormPopUpVisible()">
+            <!-- ko template: 'Magento_Checkout/shipping-address/form' --><!-- /ko -->
+        </div>
+        <!-- /ko -->
+
+        <!-- ko foreach: getRegion('before-form') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!--/ko-->
+
+        <!-- Inline address form -->
+        <!-- ko if: (isFormInline) -->
+        <!-- ko template: 'Magento_Checkout/shipping-address/form' --><!-- /ko -->
+        <!-- /ko -->
+    </div>
+</li>
+
+
+<!--Shipping method template-->
+<li id="opc-shipping_method" data-bind="fadeVisible: visible(), blockLoader: isLoading" role="presentation">
+    <div class="checkout-shipping-method">
+        <div class="step-title" data-bind="text: $t('Shipping Method')" data-role="title"></div>
+        <!-- ko foreach: getRegion('before-shipping-method-form') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- /ko -->
+        <div id="checkout-step-shipping_method"
+             class="step-content"
+             data-role="content"
+             role="tabpanel"
+             aria-hidden="false">
+            <!-- ko if: rates().length  -->
+            <form class="form methods-shipping" id="co-shipping-method-form" data-bind="submit: setShippingInformation" novalidate="novalidate">
+                <div id="checkout-shipping-method-load">
+                    <table class="table-checkout-shipping-method">
+                        <thead>
+                            <tr class="row">
+                                <th class="col">&nbsp;</th>
+                                <th class="col col-price" data-bind="text: $t('Price')"></th>
+                                <th class="col col-method" data-bind="text: $t('Method Title')"></th>
+                                <th class="col col-carrier" data-bind="text: $t('Carrier Title')"></th>
+                            </tr>
+                        </thead>
+                        <tbody>
+
+                        <!--ko foreach: { data: rates(), as: 'method'}-->
+                        <tr class="row" data-bind="click: $parent.selectShippingMethod">
+                            <td class="col">
+                                <!-- ko ifnot: method.error_message -->
+                                <!-- ko if: $parent.rates().length == 1 -->
+                                <input name="shipping_method"
+                                       class="radio"
+                                       type="radio"
+                                       data-bind="attr: {checked: $parent.rates().length == 1, 'value' : method.carrier_code + '_' + method.method_code, 'id': 's_method_' + method.method_code}" />
+                                <!-- /ko -->
+                                <!--ko ifnot: ($parent.rates().length == 1)-->
+                                <input name="shipping_method" type="radio"
+                                       data-bind="
+                                                value: method.carrier_code + '_' + method.method_code,
+                                                checked: $parent.isSelected,
+                                                attr: {'id': 's_method_' + method.carrier_code + '_' + method.method_code},
+                                                click: $parent.selectShippingMethod"
+                                       class="radio"/>
+                                <!--/ko-->
+                                <!-- /ko -->
+                            </td>
+                            <td class="col col-price">
+                                <!-- ko foreach: $parent.getRegion('price') -->
+                                <!-- ko template: getTemplate() --><!-- /ko -->
+                                <!-- /ko -->
+                            </td>
+                            <td class="col col-method" data-bind="text: $t(method.method_title)"></td>
+                            <td class="col col-carrier" data-bind="text: $t(method.carrier_title)"></td>
+                        </tr>
+
+                        <!-- ko if:  method.error_message -->
+                        <tr class="row row-error">
+                            <td class="col col-error" colspan="4">
+                                <div class="message error">
+                                    <div data-bind="text: $t(method.error_message)"></div>
+                                </div>
+                                <span class="no-display">
+                                    <input name="shipping_method" type="radio" data-bind="attr: {'value' : method.method_code, 'id': 's_method_' + method.method_code}"/>
+                                </span>
+                            </td>
+                        </tr>
+                        <!-- /ko -->
+
+                        <!-- /ko -->
+                        </tbody>
+                    </table>
+                </div>
+
+                <div id="onepage-checkout-shipping-method-additional-load">
+                    <!-- ko foreach: getRegion('shippingAdditional') -->
+                    <!-- ko template: getTemplate() --><!-- /ko -->
+                    <!-- /ko -->
+                </div>
+                <div class="actions-toolbar" id="shipping-method-buttons-container">
+                    <div class="primary">
+                        <button data-role="opc-continue" type="submit" class="button action continue primary">
+                            <span><!-- ko text: $t('Next')--><!-- /ko --></span>
+                        </button>
+                    </div>
+                </div>
+            </form>
+            <!-- /ko -->
+            <!-- ko ifnot: rates().length > 0 --><div class="no-quotes-block"><!-- ko text: $t('Sorry, no quotes are available for this order at this time')--><!-- /ko --></div><!-- /ko -->
+        </div>
+    </div>
+</li>
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html b/app/code/Magento/Checkout/view/frontend/web/template/summary.html
similarity index 55%
rename from app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html
rename to app/code/Magento/Checkout/view/frontend/web/template/summary.html
index 7de21298dcc66e6e6d094e5be4d5b9163fb5830a..322ef76b8f053604505b4f054ceedde082c362e0 100644
--- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary.html
@@ -4,8 +4,9 @@
  * See COPYING.txt for license details.
  */
 -->
-<ol id="checkout-agreements" class="agreements checkout items">
+<div class="opc-block-summary" data-bind="blockLoader: isLoading">
+    <span data-bind="text: $t('Order Summary')" class="title"></span>
     <!-- ko foreach: elems() -->
         <!-- ko template: getTemplate() --><!-- /ko -->
-    <!--/ko-->
-</ol>
+    <!-- /ko -->
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html
new file mode 100644
index 0000000000000000000000000000000000000000..b262445e97dcaaf4972312823ea20b772a9cca7f
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html
@@ -0,0 +1,54 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko ifnot: isItemsBlockExpanded() -->
+<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}">
+    <div class="title" data-role="title">
+        <strong role="heading"><span data-bind="text: getItemsQty()"></span>
+            <!-- ko text: $t('Items in cart') --><!-- /ko -->
+        </strong>
+    </div>
+    <div class="content minicart-items" data-role="content">
+        <div class="minicart-items-wrapper overflowed">
+            <ol class="minicart-items">
+                <!-- ko foreach: getItems -->
+                <li class="product-item">
+                    <div class="product">
+                        <!-- ko foreach: $parent.elems() -->
+                        <!-- ko template: getTemplate() --><!-- /ko -->
+                        <!-- /ko -->
+                    </div>
+                </li>
+                <!-- /ko -->
+            </ol>
+        </div>
+    </div>
+</div>
+<!-- /ko -->
+<!-- ko if: isItemsBlockExpanded() -->
+<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': true}}">
+    <div class="title" data-role="title">
+        <strong role="heading"><span data-bind="text: getItemsQty()"></span>
+            <!-- ko text: $t('Items in cart') --><!-- /ko -->
+        </strong>
+    </div>
+    <div class="content minicart-items" data-role="content">
+        <div class="minicart-items-wrapper overflowed">
+            <ol class="minicart-items">
+                <!-- ko foreach: getItems -->
+                <li class="product-item">
+                    <div class="product">
+                        <!-- ko foreach: $parent.elems() -->
+                        <!-- ko template: getTemplate() --><!-- /ko -->
+                        <!-- /ko -->
+                    </div>
+                </li>
+                <!-- /ko -->
+            </ol>
+        </div>
+    </div>
+</div>
+<!-- /ko -->
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html
new file mode 100644
index 0000000000000000000000000000000000000000..78954c0a4feff1a869912afebbb6051c57f34922
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html
@@ -0,0 +1,17 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: isDisplayed() -->
+<tr>
+    <td colspan="2" data-bind="text: $t(title)"></td>
+    <td class="col grandtotal">
+        <span data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span>
+        <!-- ko foreach: elems() -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- /ko -->
+    </td>
+</tr>
+<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html
new file mode 100644
index 0000000000000000000000000000000000000000..dab4d8393326c266bbdff3cf1f54883b6b218c73
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html
@@ -0,0 +1,45 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<!-- ko foreach: getRegion('before_details') -->
+    <!-- ko template: getTemplate() --><!-- /ko -->
+<!-- /ko -->
+<div class="product-item-details">
+
+    <div class="product-item-inner">
+        <div class="product-item-name-block">
+            <strong class="product-item-name" data-bind="text: $t($parent.name)"></strong>
+            <div class="details-qty">
+                <span class="label"><!-- ko text: $t('Qty') --><!-- /ko --></span>
+                <span class="value" data-bind="text: $parent.qty"></span>
+            </div>
+        </div>
+        <!-- ko foreach: getRegion('after_details') -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- /ko -->
+    </div>
+
+    <!-- ko if: (JSON.parse($parent.options).length > 0)-->
+    <div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}">
+        <span data-role="title" class="toggle"><!-- ko text: $t('View Details') --><!-- /ko --></span>
+        <div data-role="content" class="content">
+            <strong class="subtitle"><!-- ko text: $t('Options Details') --><!-- /ko --></strong>
+            <dl class="item-options">
+                <!--ko foreach: JSON.parse($parent.options)-->
+                <dt class="label" data-bind="text: $t(label)"></dt>
+                    <!-- ko if: ($data.full_view)-->
+                    <dd class="values" data-bind="html: full_view"></dd>
+                    <!-- /ko -->
+                    <!-- ko ifnot: ($data.full_view)-->
+                    <dd class="values" data-bind="html: value"></dd>
+                    <!-- /ko -->
+                <!-- /ko -->
+            </dl>
+        </div>
+    </div>
+    <!-- /ko -->
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/item.js b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html
similarity index 54%
rename from app/code/Magento/Checkout/view/frontend/web/js/model/item.js
rename to app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html
index d1927d19e9288d2b244ff8f5761bc12556b605a2..f90013fcebbca354cb4ee7c7d3a0c756145ace6a 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/item.js
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html
@@ -1,9 +1,7 @@
+<!--
 /**
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define([], function() {
-
-});
+-->
+<span class="subtotal" data-bind="text: getValue($parents[1])"></span>
\ No newline at end of file
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html
new file mode 100644
index 0000000000000000000000000000000000000000..1b8cb1fada8c6d21332167f59d4a5cf68d342ca0
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html
@@ -0,0 +1,13 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<span class="product-image-container"
+      data-bind="attr: {'style': 'height: ' + getHeight($parents[1]) + 'px; width: ' + getWidth($parents[1]) + 'px;' }">
+    <span class="product-image-wrapper">
+        <img
+            data-bind="attr: {'src': getSrc($parents[1]), 'width': getWidth($parents[1]), 'height': getHeight($parents[1]), 'alt': getAlt($parents[1]) }"/>
+    </span>
+</span>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html
new file mode 100644
index 0000000000000000000000000000000000000000..34707698e61b6d43a73c743b908c3b4c8c246fbc
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html
@@ -0,0 +1,24 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: quoteIsVirtual == 0 -->
+    <tr class="totals shipping excl">
+        <th class="mark" scope="row">
+            <span class="label" data-bind="text: $t(title)"></span>
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </th>
+        <td class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+<!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html
new file mode 100644
index 0000000000000000000000000000000000000000..f241430924ac88f2a773699f978c33228d9beb9c
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html
@@ -0,0 +1,16 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<tr class="totals">
+    <th class="mark" scope="row" data-bind="text: $t(title)"></th>
+    <td class="amount">
+        <span class="price" data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span>
+        <!-- ko foreach: elems() -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+        <!-- /ko -->
+    </td>
+</tr>
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html
new file mode 100644
index 0000000000000000000000000000000000000000..074024dee00d9d0bdd55fef06c933f6df9d94330
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html
@@ -0,0 +1,14 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<table class="data table table-totals">
+    <caption class="table-caption" data-bind="text: $t('Order Summary')"></caption>
+    <tbody>
+    <!-- ko foreach: elems() -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+    <!-- /ko -->
+    </tbody>
+</table>
diff --git a/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php b/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php
index b13012ae47336a32c14f4f96ca9c22cdaa1a5914..ad8bdfc822cd6cf47021150f599f6e43320d709d 100644
--- a/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php
+++ b/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php
@@ -34,34 +34,22 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso
      */
     public function process($jsLayout)
     {
-        $form = [];
+        $agreementConfiguration = [];
         $agreementsList = $this->checkoutAgreementsRepository->getList();
+
         foreach ($agreementsList as $agreement) {
-            $name = $agreement->getAgreementId();
-            $form[$name] = [
-                'component' => 'Magento_Ui/js/form/element/abstract',
-                'config' => [
-                    'customScope' => 'checkoutAgreements',
-                    'customEntry' => 'checkoutAgreements.' . $name,
-                    'template' => 'Magento_CheckoutAgreements/form/element/agreement'
-                ],
-                'agreementConfiguration' => [
-                    'content' => $agreement->getIsHtml()
-                        ? $agreement->getContent()
-                        : nl2br($this->escaper->escapeHtml($agreement->getContent())),
-                    'height' => $agreement->getContentHeight(),
-                    'checkboxText' => $agreement->getCheckboxText()
-                ],
-                'dataScope' => $name,
-                'provider' => 'checkoutProvider',
-                'validation' => ['checked' => true],
-                'customEntry' => null,
-                'visible' => true
+            $agreementConfiguration[] = [
+                'content' => $agreement->getIsHtml()
+                    ? $agreement->getContent()
+                    : nl2br($this->escaper->escapeHtml($agreement->getContent())),
+                'height' => $agreement->getContentHeight(),
+                'checkboxText' => $agreement->getCheckboxText()
             ];
         }
-        $result['components']['checkout']['children']['steps']['children']['review']['children']
-        ['beforePlaceOrder']['children']['checkoutAgreements']['children'] = $form;
+        $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']
+        ['children']['payments-list']['children']['before-place-order']['children']['checkout-agreements-modal']
+        ['config']['agreementConfiguration'] = $agreementConfiguration;
 
-        return array_merge_recursive($jsLayout, $result);
+        return $jsLayout;
     }
 }
diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json
index 13f10a6560e989f70548019e6eb5b043740c431b..1c9182b3add4bac268176432b51c4704d97b8cd9 100644
--- a/app/code/Magento/CheckoutAgreements/composer.json
+++ b/app/code/Magento/CheckoutAgreements/composer.json
@@ -6,7 +6,6 @@
         "magento/module-checkout": "0.74.0-beta15",
         "magento/module-store": "0.74.0-beta15",
         "magento/module-backend": "0.74.0-beta15",
-        "magento/module-ui": "0.74.0-beta15",
         "magento/framework": "0.74.0-beta15",
         "magento/magento-composer-installer": "*"
     },
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml
index b80bfc39aef43beb4d75914c654e68171d66a546..5f883201ee2dc7a65fb206b071dea0216d7c8b3b 100644
--- a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml
@@ -15,16 +15,25 @@
                             <item name="children" xsi:type="array">
                                 <item name="steps" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="review" xsi:type="array">
+                                        <item name="billing-step" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="beforePlaceOrder" xsi:type="array">
+                                                <item name="payment" xsi:type="array">
                                                     <item name="children" xsi:type="array">
-                                                        <item name="checkoutAgreements" xsi:type="array">
-                                                            <item name="component"  xsi:type="string">Magento_CheckoutAgreements/js/view/checkoutAgreements</item>
-                                                            <item name="dataScope" xsi:type="string">checkoutAgreements</item>
-                                                            <item name="displayArea" xsi:type="string">checkoutAgreements</item>
-                                                            <item name="provider" xsi:type="string">checkoutProvider</item>
+                                                        <item name="payments-list" xsi:type="array">
                                                             <item name="children" xsi:type="array">
+                                                                <item name="before-place-order" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements-link</item>
+                                                                    <item name="displayArea" xsi:type="string">before-place-order</item>
+                                                                    <item name="dataScope" xsi:type="string">checkoutAgreements</item>
+                                                                    <item name="provider" xsi:type="string">checkoutProvider</item>
+                                                                    <item name="children" xsi:type="array">
+                                                                        <item name="checkout-agreements-modal" xsi:type="array">
+                                                                            <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements-modal</item>
+                                                                            <item name="dataScope" xsi:type="string">checkoutAgreements</item>
+                                                                            <item name="provider" xsi:type="string">checkoutProvider</item>
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
                                                             </item>
                                                         </item>
                                                     </item>
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml
new file mode 100644
index 0000000000000000000000000000000000000000..89eb6278a7646836ff461eb6955899faae9b5fb9
--- /dev/null
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- TODO remove this file as soon as enhanced checkout is implemented -->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="review" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="beforePlaceOrder" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="checkoutAgreements" xsi:type="array">
+                                                            <item name="component"  xsi:type="string">Magento_CheckoutAgreements/js/view/checkoutAgreements</item>
+                                                            <item name="dataScope" xsi:type="string">checkoutAgreements</item>
+                                                            <item name="displayArea" xsi:type="string">checkoutAgreements</item>
+                                                            <item name="provider" xsi:type="string">checkoutProvider</item>
+                                                            <item name="children" xsi:type="array">
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js
new file mode 100644
index 0000000000000000000000000000000000000000..071602c254c40f864b7654cfb56293d1c250d2dc
--- /dev/null
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js
@@ -0,0 +1,24 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+        'ko',
+        'uiComponent'
+    ], function (ko, Component) {
+        'use strict';
+
+        return Component.extend({
+            defaults: {
+                template: 'Magento_CheckoutAgreements/checkout/payment/checkout-agreements-link'
+            },
+            isVisible: window.checkoutConfig.checkoutAgreementsEnabled,
+            /**
+             * Opens modal window with Terms&Conditions
+             */
+            showAgreements: function () {
+                this.elems()[0].showAgreements();
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js
new file mode 100644
index 0000000000000000000000000000000000000000..e7762f7ea5b9f1c2448110c50be7ec42d28733a9
--- /dev/null
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+        'ko',
+        'uiComponent',
+        'Magento_Ui/js/modal/modal'
+    ], function (ko, Component, modal) {
+        'use strict';
+
+        /**
+         * Provides an empty div to force load template into.
+         * @todo MAGETWO-39170 Refactor this as soon as modal component is updated to support ko view models.
+         * @returns {HTMLElement}
+         */
+        function createTemporayContainer() {
+            var temporaryDiv = document.createElement('div');
+            temporaryDiv.style.display = 'none';
+            document.body.appendChild(temporaryDiv);
+
+            return temporaryDiv;
+        }
+
+        return Component.extend({
+            defaults: {
+                template: 'Magento_CheckoutAgreements/checkout/modal/agreements-modal'
+            },
+            /**
+             * Initialize view and render it's template to temporary div. This will be refactored as soon as
+             * modal component is integrated with uiComponent.
+             * @returns {*}
+             */
+            initialize: function () {
+                var temporaryContainer = createTemporayContainer();
+
+                this._super();
+                ko.renderTemplate(this.template, this, {}, temporaryContainer);
+                temporaryContainer.parentNode.removeChild(temporaryContainer);
+
+                return this;
+            },
+            modal: modal({
+                responsive: true,
+                innerScroll: true,
+                buttons: []
+            }),
+            /**
+             * Show Terms&Conditions pop-up
+             */
+            showAgreements: function () {
+                ko.renderTemplate(this.template, this, {}, this.modal.openModal(), 'replaceNode');
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js
deleted file mode 100644
index 094136c756467124a11a6c509263af55c8bd69c1..0000000000000000000000000000000000000000
--- a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(
-    ['Magento_Ui/js/form/form', 'Magento_Checkout/js/view/review', 'underscore'],
-    function (Component, review, _) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_CheckoutAgreements/checkout/review/agreements'
-            },
-            initialize: function() {
-                this._super();
-                if (window.checkoutConfig.checkoutAgreementsEnabled) {
-                    review.prototype.beforePlaceOrder.checkoutAgreements = this;
-                }
-            },
-            validate: function() {
-                this.source.set('params.invalid', false);
-                this.source.trigger('checkoutAgreements.data.validate');
-                return this.source.get('params.invalid');
-            },
-            getSubmitParams: function() {
-                return {
-                    agreements: _.keys(this.source.get('checkoutAgreements'))
-                };
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html
new file mode 100644
index 0000000000000000000000000000000000000000..0129cab3aebd3c2d9aaba585274e4bfc70413ccb
--- /dev/null
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html
@@ -0,0 +1,15 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<ol class="checkout-agreements-items">
+    <!-- ko foreach: agreementConfiguration -->
+    <li class="checkout-agreements-item">
+        <div class="checkout-agreements-item-title" data-bind="html: checkboxText"></div>
+        <div class="checkout-agreements-item-content"
+             data-bind="style: { height: height || null }, html: content"></div>
+    </li>
+    <!-- /ko -->
+</ol>
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html
new file mode 100644
index 0000000000000000000000000000000000000000..315bc47af7dac0607ace233f00b8dce7273a96db
--- /dev/null
+++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html
@@ -0,0 +1,14 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<div class="checkout-agreements" data-bind="visible: isVisible">
+    <!-- ko text: $t('You automatically accept') --><!-- /ko -->
+    <button type="button" class="action action-show" data-bind="click: showAgreements">
+        <span><!-- ko text: $t('terms and conditions') --><!-- /ko --></span>
+    </button>
+    <!-- ko text: $t('before placing the order') --><!-- /ko -->
+</div>
diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html
deleted file mode 100644
index 0f029cfe2f3b4113a83c4b7256f867ce8e5ca592..0000000000000000000000000000000000000000
--- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<li class="item">
-    <div class="agreement content" data-bind="style: { height: agreementConfiguration.height || null }, html: agreementConfiguration.content"></div>
-    <form class="field choice agree required" id="checkout-agreements">
-        <input type="checkbox" class="control-checkbox" data-bind="checked: value, attr: { id: uid, disabled: disabled, name: inputName }, hasFocus: focused">
-        <label class="field-label" data-bind="checked: value, attr: { for: uid }">
-            <span data-bind="html: agreementConfiguration.checkboxText"></span>
-        </label>
-    </form>
-    <!-- ko if: error() -->
-    <div class="mage-error" data-bind="attr: { for: uid }, text: error" generated="true"></div>
-    <!-- /ko -->
-</li>
diff --git a/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Edit/FormTest.php b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Edit/FormTest.php
index 9fd408462cfc6a5918fa511605c160c3ad05c7fd..d671e0b864fb54e5ffc82f9a5d317debb6d73015 100755
--- a/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Edit/FormTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Edit/FormTest.php
@@ -90,11 +90,6 @@ class FormTest extends \PHPUnit_Framework_TestCase
      */
     protected $appState;
 
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $viewFileSystem;
-
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
@@ -130,6 +125,16 @@ class FormTest extends \PHPUnit_Framework_TestCase
      */
     protected $block;
 
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Resolver|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_resolver;
+
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Validator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_validator;
+
     /**
      * Sets up the fixture, for example, open a network connection.
      * This method is called before a test is executed.
@@ -138,6 +143,22 @@ class FormTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
+        $this->_resolver = $this->getMock(
+            'Magento\Framework\View\Element\Template\File\Resolver',
+            [],
+            [],
+            '',
+            false
+        );
+
+        $this->_validator = $this->getMock(
+            'Magento\Framework\View\Element\Template\File\Validator',
+            [],
+            [],
+            '',
+            false
+        );
+
         $this->model = $this->getMock('Magento\Cms\Model\Block', ['getBlockId', 'setStoreId'], [], '', false);
 
         $this->registry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
@@ -158,7 +179,6 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
         $this->urlBuilder = $this->getMock('Magento\Framework\UrlInterface', [], [], '', false);
         $this->appState = $this->getMock('Magento\Framework\App\State', [], [], '', false);
-        $this->viewFileSystem = $this->getMock('Magento\Framework\View\FileSystem', [], [], '', false);
         $this->logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         $this->rootDirectory = $this->getMock(
             'Magento\Framework\Filesystem\Directory\ReadInterface',
@@ -193,10 +213,11 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->context->expects($this->once())->method('getStoreManager')->willReturn($this->storeManager);
         $this->context->expects($this->once())->method('getUrlBuilder')->willReturn($this->urlBuilder);
         $this->context->expects($this->once())->method('getAppState')->willReturn($this->appState);
-        $this->context->expects($this->once())->method('getViewFileSystem')->willReturn($this->viewFileSystem);
         $this->context->expects($this->once())->method('getFilesystem')->willReturn($this->fileSystem);
         $this->context->expects($this->once())->method('getLogger')->willReturn($this->logger);
         $this->context->expects($this->once())->method('getLayout')->willReturn($this->layout);
+        $this->context->expects($this->once())->method('getResolver')->willReturn($this->_resolver);
+        $this->context->expects($this->once())->method('getValidator')->willReturn($this->_validator);
 
         /** @var \Magento\Cms\Block\Adminhtml\Block\Edit\Form $block */
         $this->block = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php
index 5f381f0ddad0979e3efa4e6585a8ef09eedb7dd1..9f99ffd9339462f5692d169df9e2aeea0601f837 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -204,7 +204,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
      */
     public function getGridParentHtml()
     {
-        $templateName = $this->_viewFileSystem->getTemplateFileName($this->_parentTemplate, ['_relative' => true]);
+        $templateName = $this->resolver->getTemplateFileName($this->_parentTemplate, ['_relative' => true]);
         return $this->fetchView($templateName);
     }
 
diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php b/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php
index 992c63cf893f541fef9b1458542cd922b5a7e433..59d183ee6510eeba9fc301aeaec0417c464920e1 100644
--- a/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php
+++ b/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php
@@ -53,17 +53,8 @@ class Password extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBacke
                 );
             }
 
-            if ($this->string->substr(
-                $password,
-                0,
-                1
-            ) == ' ' || $this->string->substr(
-                $password,
-                $length - 1,
-                1
-            ) == ' '
-            ) {
-                throw new LocalizedException(__('The password can\'t begin or end with a space.'));
+            if (trim($password) != $password) {
+                throw new LocalizedException(__('The password can not begin or end with a space.'));
             }
 
             $object->setPasswordHash($object->hashPassword($password));
diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php
index 128ccedaf2b5277371680570b8e82fc88f95a2e2..777a78cb6fa05508712a9c07f4b8f7775ec45029 100644
--- a/app/code/Magento/Customer/Model/Customer/DataProvider.php
+++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php
@@ -9,7 +9,7 @@ use Magento\Eav\Model\Config;
 use Magento\Eav\Model\Entity\Type;
 use Magento\Customer\Model\Address;
 use Magento\Customer\Model\Customer;
-use Magento\Ui\DataProvider\EavValidationRul;
+use Magento\Ui\DataProvider\EavValidationRules;
 use Magento\Customer\Model\Resource\Customer\Collection;
 use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface;
 use Magento\Customer\Model\Resource\Customer\CollectionFactory as CustomerCollectionFactory;
@@ -75,7 +75,7 @@ class DataProvider implements DataProviderInterface
         'sortOrder' => 'sort_order',
         'notice' => 'note',
         'default' => 'default_value',
-        'size' => 'scope_multiline_count'
+        'size' => 'multiline_count'
     ];
 
     /**
@@ -90,9 +90,9 @@ class DataProvider implements DataProviderInterface
     ];
 
     /**
-     * @var EavValidationRul
+     * @var EavValidationRules
      */
-    protected $eavValidationRul;
+    protected $eavValidationRules;
 
     /**
      * Constructor
@@ -100,7 +100,7 @@ class DataProvider implements DataProviderInterface
      * @param string $name
      * @param string $primaryFieldName
      * @param string $requestFieldName
-     * @param EavValidationRul $eavValidationRul
+     * @param EavValidationRules $eavValidationRules
      * @param CustomerCollectionFactory $customerCollectionFactory
      * @param Config $eavConfig
      * @param array $meta
@@ -110,7 +110,7 @@ class DataProvider implements DataProviderInterface
         $name,
         $primaryFieldName,
         $requestFieldName,
-        EavValidationRul $eavValidationRul,
+        EavValidationRules $eavValidationRules,
         CustomerCollectionFactory $customerCollectionFactory,
         Config $eavConfig,
         array $meta = [],
@@ -119,7 +119,7 @@ class DataProvider implements DataProviderInterface
         $this->name = $name;
         $this->primaryFieldName = $primaryFieldName;
         $this->requestFieldName = $requestFieldName;
-        $this->eavValidationRul = $eavValidationRul;
+        $this->eavValidationRules = $eavValidationRules;
         $this->collection = $customerCollectionFactory->create();
         $this->collection->addAttributeToSelect('*');
         $this->eavConfig = $eavConfig;
@@ -223,6 +223,7 @@ class DataProvider implements DataProviderInterface
      * @param string|array $field
      * @param string|null $alias
      * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function addField($field, $alias = null)
     {
@@ -260,6 +261,7 @@ class DataProvider implements DataProviderInterface
      * @param string|null $field
      * @param bool $isAlias Alias identifier
      * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function removeField($field, $isAlias = false)
     {
@@ -369,7 +371,7 @@ class DataProvider implements DataProviderInterface
                 }
             }
 
-            $rules = $this->eavValidationRul->build($attribute, $meta[$code]);
+            $rules = $this->eavValidationRules->build($attribute, $meta[$code]);
             if (!empty($rules)) {
                 $meta[$code]['validation'] = $rules;
             }
diff --git a/app/code/Magento/Customer/Model/Resource/Address.php b/app/code/Magento/Customer/Model/Resource/Address.php
index 3b6ae0a28c8f9e812e762b72dbfe45d35681ebe9..d45f79f9a662574a3ca5c5db2cefadfe299c1274 100644
--- a/app/code/Magento/Customer/Model/Resource/Address.php
+++ b/app/code/Magento/Customer/Model/Resource/Address.php
@@ -9,7 +9,7 @@ namespace Magento\Customer\Model\Resource;
 
 use Magento\Framework\Exception\InputException;
 
-class Address extends \Magento\Eav\Model\Entity\AbstractEntity
+class Address extends \Magento\Eav\Model\Entity\VersionControl\AbstractEntity
 {
     /**
      * @var \Magento\Framework\Validator\Factory
@@ -23,19 +23,23 @@ class Address extends \Magento\Eav\Model\Entity\AbstractEntity
 
     /**
      * @param \Magento\Eav\Model\Entity\Context $context
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
      * @param \Magento\Framework\Validator\Factory $validatorFactory
      * @param \Magento\Customer\Model\CustomerFactory $customerFactory
      * @param array $data
      */
     public function __construct(
         \Magento\Eav\Model\Entity\Context $context,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Framework\Validator\Factory $validatorFactory,
         \Magento\Customer\Model\CustomerFactory $customerFactory,
         $data = []
     ) {
         $this->_validatorFactory = $validatorFactory;
         $this->_customerFactory = $customerFactory;
-        parent::__construct($context, $data);
+        parent::__construct($context, $entitySnapshot, $entityRelationComposite, $data);
     }
 
     /**
@@ -63,31 +67,6 @@ class Address extends \Magento\Eav\Model\Entity\AbstractEntity
         return parent::getEntityType();
     }
 
-    /**
-     * Set default shipping to address
-     *
-     * @param \Magento\Framework\Object $address
-     * @return $this
-     */
-    protected function _afterSave(\Magento\Framework\Object $address)
-    {
-        if ($address->getIsCustomerSaveTransaction()) {
-            return $this;
-        }
-        if ($address->getId() && ($address->getIsDefaultBilling() || $address->getIsDefaultShipping())) {
-            $customer = $this->_createCustomer()->load($address->getCustomerId());
-
-            if ($address->getIsDefaultBilling()) {
-                $customer->setDefaultBilling($address->getId());
-            }
-            if ($address->getIsDefaultShipping()) {
-                $customer->setDefaultShipping($address->getId());
-            }
-            $customer->save();
-        }
-        return $this;
-    }
-
     /**
      * Check customer address before saving
      *
diff --git a/app/code/Magento/Customer/Model/Resource/Address/Collection.php b/app/code/Magento/Customer/Model/Resource/Address/Collection.php
index 83018cb25c448d481bebc476493876d476ed9478..771db1c598ca9d09e88de1444bdcd30a27c57adc 100644
--- a/app/code/Magento/Customer/Model/Resource/Address/Collection.php
+++ b/app/code/Magento/Customer/Model/Resource/Address/Collection.php
@@ -10,7 +10,7 @@ namespace Magento\Customer\Model\Resource\Address;
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
+class Collection extends \Magento\Eav\Model\Entity\Collection\VersionControl\AbstractCollection
 {
     /**
      * Resource initialization
diff --git a/app/code/Magento/Customer/Model/Resource/Address/Relation.php b/app/code/Magento/Customer/Model/Resource/Address/Relation.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e10e2bb4612b3f55f4f9640264442608e6d9a41
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Resource/Address/Relation.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Customer address entity resource model
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Resource\Address;
+
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
+
+/**
+ * Class represents save operations for customer address relations
+ */
+class Relation implements RelationInterface
+{
+    /**
+     * @var \Magento\Customer\Model\CustomerFactory
+     */
+    protected $customerFactory;
+
+    /**
+     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
+     */
+    public function __construct(\Magento\Customer\Model\CustomerFactory $customerFactory)
+    {
+        $this->customerFactory = $customerFactory;
+    }
+
+    /**
+     * Process object relations
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return void
+     */
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
+    {
+        /**
+         * @var $object \Magento\Customer\Model\Address
+         */
+        if (!$object->getIsCustomerSaveTransaction() && $this->isAddressDefault($object)) {
+            $customer = $this->customerFactory->create()->load($object->getCustomerId());
+            $changedAddresses = [];
+
+            if ($object->getIsDefaultBilling()) {
+                $changedAddresses['default_billing'] = $object->getId();
+            }
+
+            if ($object->getIsDefaultShipping()) {
+                $changedAddresses['default_shipping'] = $object->getId();
+            }
+
+            if ($changedAddresses) {
+                $customer->getResource()->getWriteConnection()->update(
+                    $customer->getResource()->getTable('customer_entity'),
+                    $changedAddresses,
+                    $customer->getResource()->getWriteConnection()->quoteInto('entity_id = ?', $customer->getId())
+                );
+            }
+        }
+    }
+
+    /**
+     * Checks if address has chosen as default and has had an id
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return bool
+     */
+    protected function isAddressDefault(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $object->getId() && ($object->getIsDefaultBilling() || $object->getIsDefaultShipping());
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Resource/Customer.php b/app/code/Magento/Customer/Model/Resource/Customer.php
index 682e429411b7806b6c4695fcacaaecade20a7c88..16666b61689da0ccd4a50124c4128410b3bea0db 100644
--- a/app/code/Magento/Customer/Model/Resource/Customer.php
+++ b/app/code/Magento/Customer/Model/Resource/Customer.php
@@ -12,7 +12,7 @@ use Magento\Framework\Exception\AlreadyExistsException;
  * Customer entity resource model
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Customer extends \Magento\Eav\Model\Entity\AbstractEntity
+class Customer extends \Magento\Eav\Model\Entity\VersionControl\AbstractEntity
 {
     /**
      * @var \Magento\Framework\Validator\Factory
@@ -33,6 +33,8 @@ class Customer extends \Magento\Eav\Model\Entity\AbstractEntity
 
     /**
      * @param \Magento\Eav\Model\Entity\Context $context
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Framework\Validator\Factory $validatorFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -40,12 +42,14 @@ class Customer extends \Magento\Eav\Model\Entity\AbstractEntity
      */
     public function __construct(
         \Magento\Eav\Model\Entity\Context $context,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Framework\Validator\Factory $validatorFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
         $data = []
     ) {
-        parent::__construct($context, $data);
+        parent::__construct($context, $entitySnapshot, $entityRelationComposite, $data);
         $this->_scopeConfig = $scopeConfig;
         $this->_validatorFactory = $validatorFactory;
         $this->dateTime = $dateTime;
@@ -149,72 +153,14 @@ class Customer extends \Magento\Eav\Model\Entity\AbstractEntity
     /**
      * Save customer addresses and set default addresses in attributes backend
      *
-     * @param \Magento\Customer\Model\Customer $customer
+     * @param \Magento\Framework\Object $customer
      * @return $this
      */
     protected function _afterSave(\Magento\Framework\Object $customer)
     {
-        $this->_saveAddresses($customer);
         return parent::_afterSave($customer);
     }
 
-    /**
-     * Save/delete customer address
-     *
-     * @param \Magento\Customer\Model\Customer $customer
-     * @return $this
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
-     */
-    protected function _saveAddresses(\Magento\Customer\Model\Customer $customer)
-    {
-        $defaultBillingId = $customer->getData('default_billing');
-        $defaultShippingId = $customer->getData('default_shipping');
-        /** @var \Magento\Customer\Model\Address $address */
-        foreach ($customer->getAddresses() as $address) {
-            if ($address->getData('_deleted')) {
-                if ($address->getId() == $defaultBillingId) {
-                    $customer->setData('default_billing', null);
-                }
-                if ($address->getId() == $defaultShippingId) {
-                    $customer->setData('default_shipping', null);
-                }
-                $removedAddressId = $address->getId();
-                $address->delete();
-                // Remove deleted address from customer address collection
-                $customer->getAddressesCollection()->removeItemByKey($removedAddressId);
-            } else {
-                $address->setParentId(
-                    $customer->getId()
-                )->setStoreId(
-                    $customer->getStoreId()
-                )->setIsCustomerSaveTransaction(
-                    true
-                )->save();
-                if (($address->getIsPrimaryBilling() ||
-                    $address->getIsDefaultBilling()) && $address->getId() != $defaultBillingId
-                ) {
-                    $customer->setData('default_billing', $address->getId());
-                }
-                if (($address->getIsPrimaryShipping() ||
-                    $address->getIsDefaultShipping()) && $address->getId() != $defaultShippingId
-                ) {
-                    $customer->setData('default_shipping', $address->getId());
-                }
-            }
-        }
-        $changedAddresses = [];
-
-        $changedAddresses['default_billing'] = $customer->getData('default_billing');
-        $changedAddresses['default_shipping'] = $customer->getData('default_shipping');
-        $this->_getWriteAdapter()->update(
-            $this->getTable('customer_entity'),
-            $changedAddresses,
-            $this->_getWriteAdapter()->quoteInto('entity_id = ?', $customer->getId())
-        );
-
-        return $this;
-    }
-
     /**
      * Retrieve select object for loading base entity row
      *
diff --git a/app/code/Magento/Customer/Model/Resource/Customer/Collection.php b/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
index 6e0cdd7780452fed7563bd6df4de70d75ceb84f1..2353c59e91c5556f340720af805bbd512658d081 100644
--- a/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
+++ b/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
@@ -9,8 +9,9 @@ namespace Magento\Customer\Model\Resource\Customer;
  * Customers collection
  *
  * @author      Magento Core Team <core@magentocommerce.com>
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
+class Collection extends \Magento\Eav\Model\Entity\Collection\VersionControl\AbstractCollection
 {
     /**
      * Name of collection model
@@ -37,6 +38,7 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
      * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
      * @param \Magento\Eav\Model\Resource\Helper $resourceHelper
      * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\Object\Copy\Config $fieldsetConfig
      * @param \Zend_Db_Adapter_Abstract $connection
      * @param string $modelName
@@ -53,6 +55,7 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
         \Magento\Eav\Model\EntityFactory $eavEntityFactory,
         \Magento\Eav\Model\Resource\Helper $resourceHelper,
         \Magento\Framework\Validator\UniversalFactory $universalFactory,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Object\Copy\Config $fieldsetConfig,
         $connection = null,
         $modelName = self::CUSTOMER_MODEL_NAME
@@ -69,6 +72,7 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
             $eavEntityFactory,
             $resourceHelper,
             $universalFactory,
+            $entitySnapshot,
             $connection
         );
     }
diff --git a/app/code/Magento/Customer/Model/Resource/Customer/Relation.php b/app/code/Magento/Customer/Model/Resource/Customer/Relation.php
new file mode 100644
index 0000000000000000000000000000000000000000..3967a981b6e95cfb610febd4d5019f4c3ace74a8
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Resource/Customer/Relation.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Model\Resource\Customer;
+
+/**
+ * Class Relation
+ */
+class Relation implements \Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface
+{
+    /**
+     * Save relations for Customer
+     *
+     * @param \Magento\Framework\Model\AbstractModel $customer
+     * @return void
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     */
+    public function processRelation(\Magento\Framework\Model\AbstractModel $customer)
+    {
+        $defaultBillingId = $customer->getData('default_billing');
+        $defaultShippingId = $customer->getData('default_shipping');
+
+        /** @var \Magento\Customer\Model\Address $address */
+        foreach ($customer->getAddresses() as $address) {
+            if ($address->getData('_deleted')) {
+                if ($address->getId() == $defaultBillingId) {
+                    $customer->setData('default_billing', null);
+                }
+
+                if ($address->getId() == $defaultShippingId) {
+                    $customer->setData('default_shipping', null);
+                }
+
+                $removedAddressId = $address->getId();
+                $address->delete();
+
+                // Remove deleted address from customer address collection
+                $customer->getAddressesCollection()->removeItemByKey($removedAddressId);
+            } else {
+                $address->setParentId(
+                    $customer->getId()
+                )->setStoreId(
+                    $customer->getStoreId()
+                )->setIsCustomerSaveTransaction(
+                    true
+                )->save();
+
+                if (($address->getIsPrimaryBilling() ||
+                        $address->getIsDefaultBilling()) && $address->getId() != $defaultBillingId
+                ) {
+                    $customer->setData('default_billing', $address->getId());
+                }
+
+                if (($address->getIsPrimaryShipping() ||
+                        $address->getIsDefaultShipping()) && $address->getId() != $defaultShippingId
+                ) {
+                    $customer->setData('default_shipping', $address->getId());
+                }
+            }
+        }
+
+        $changedAddresses = [];
+
+        $changedAddresses['default_billing'] = $customer->getData('default_billing');
+        $changedAddresses['default_shipping'] = $customer->getData('default_shipping');
+
+        $customer->getResource()->getWriteConnection()->update(
+            $customer->getResource()->getTable('customer_entity'),
+            $changedAddresses,
+            $customer->getResource()->getWriteConnection()->quoteInto('entity_id = ?', $customer->getId())
+        );
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Resource/Group.php b/app/code/Magento/Customer/Model/Resource/Group.php
index 6dc9888d7715024c2edb1d84158b0407df5a79c5..145ec38181b851afea01714368c2dbbb48a4e1f3 100644
--- a/app/code/Magento/Customer/Model/Resource/Group.php
+++ b/app/code/Magento/Customer/Model/Resource/Group.php
@@ -5,12 +5,15 @@
  */
 namespace Magento\Customer\Model\Resource;
 
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+
 /**
  * Customer group resource model
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Group extends \Magento\Framework\Model\Resource\Db\AbstractDb
+class Group extends \Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb
 {
     /**
      * Group Management
@@ -26,19 +29,23 @@ class Group extends \Magento\Framework\Model\Resource\Db\AbstractDb
 
     /**
      * @param \Magento\Framework\Model\Resource\Db\Context $context
+     * @param Snapshot $entitySnapshot,
+     * @param RelationComposite $entityRelationComposite,
      * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement
      * @param Customer\CollectionFactory $customersFactory
      * @param string|null $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        RelationComposite $entityRelationComposite,
         \Magento\Customer\Api\GroupManagementInterface $groupManagement,
         \Magento\Customer\Model\Resource\Customer\CollectionFactory $customersFactory,
         $resourcePrefix = null
     ) {
         $this->_groupManagement = $groupManagement;
         $this->_customersFactory = $customersFactory;
-        parent::__construct($context, $resourcePrefix);
+        parent::__construct($context, $entitySnapshot, $entityRelationComposite, $resourcePrefix);
     }
 
     /**
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eab40c46f84bbc63098fe6222250db2ecd9ed2d7
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php
@@ -0,0 +1,249 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Customer;
+
+use Magento\Eav\Model\Config;
+use Magento\Eav\Model\Entity\Type;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Ui\DataProvider\EavValidationRules;
+use Magento\Customer\Model\Customer\DataProvider;
+use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Customer\Model\Resource\Customer\CollectionFactory;
+
+/**
+ * Class DataProviderTest
+ *
+ * Test for class \Magento\Customer\Model\Customer\DataProvider
+ */
+class DataProviderTest extends \PHPUnit_Framework_TestCase
+{
+    const ATTRIBUTE_CODE = 'test-code';
+    const OPTIONS_RESULT = 'test-options';
+
+    /**
+     * @var Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavConfigMock;
+
+    /**
+     * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionFactoryMock;
+
+    /**
+     * @var EavValidationRules|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavValidationRulesMock;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->eavConfigMock = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customerCollectionFactoryMock = $this->getMock(
+            'Magento\Customer\Model\Resource\Customer\CollectionFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->eavValidationRulesMock = $this
+            ->getMockBuilder('Magento\Ui\DataProvider\EavValidationRules')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    /**
+     * Run test getAttributesMeta method
+     *
+     * @param array $expected
+     * @return void
+     *
+     * @dataProvider getAttributesMetaDataProvider
+     */
+    public function testGetAttributesMetaWithOptions(array $expected)
+    {
+        $helper = new ObjectManager($this);
+        $dataProvider = $helper->getObject(
+            '\Magento\Customer\Model\Customer\DataProvider',
+            [
+                'name' => 'test-name',
+                'primaryFieldName' => 'primary-field-name',
+                'requestFieldName' => 'request-field-name',
+                'eavValidationRules' => $this->eavValidationRulesMock,
+                'customerCollectionFactory' => $this->getCustomerCollectionFactoryMock(),
+                'eavConfig' => $this->getEavConfigMock()
+            ]
+        );
+
+        $meta = $dataProvider->getMeta();
+        $this->assertNotEmpty($meta);
+        $this->assertEquals($expected, $meta);
+    }
+
+    /**
+     * Data provider for testGetAttributesMeta
+     *
+     * @return array
+     */
+    public function getAttributesMetaDataProvider()
+    {
+        return [
+            [
+                'expected' => [
+                    'customer' => [
+                        'fields' => [
+                            self::ATTRIBUTE_CODE => [
+                                'dataType' => 'frontend_input',
+                                'formElement' => 'frontend_input',
+                                'options' => 'test-options',
+                                'visible' => 'is_visible',
+                                'required' => 'is_required',
+                                'label' => 'frontend_label',
+                                'sortOrder' => 'sort_order',
+                                'notice' => 'note',
+                                'default' => 'default_value',
+                                'size' => 'multiline_count',
+                            ]
+                        ]
+                    ],
+                    'address' => [
+                        'fields' => [
+                            self::ATTRIBUTE_CODE => [
+                                'dataType' => 'frontend_input',
+                                'formElement' => 'frontend_input',
+                                'options' => 'test-options',
+                                'visible' => 'is_visible',
+                                'required' => 'is_required',
+                                'label' => 'frontend_label',
+                                'sortOrder' => 'sort_order',
+                                'notice' => 'note',
+                                'default' => 'default_value',
+                                'size' => 'multiline_count',
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * @return CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getCustomerCollectionFactoryMock()
+    {
+        $collectionMock = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $collectionMock->expects($this->once())
+            ->method('addAttributeToSelect')
+            ->with('*');
+
+        $this->customerCollectionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($collectionMock);
+
+        return $this->customerCollectionFactoryMock;
+    }
+
+    /**
+     * @return Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getEavConfigMock()
+    {
+        $this->eavConfigMock->expects($this->at(0))
+            ->method('getEntityType')
+            ->with('customer')
+            ->willReturn($this->getTypeCustomerMock());
+        $this->eavConfigMock->expects($this->at(1))
+            ->method('getEntityType')
+            ->with('customer_address')
+            ->willReturn($this->getTypeAddressMock());
+
+        return $this->eavConfigMock;
+    }
+
+    /**
+     * @return Type|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getTypeCustomerMock()
+    {
+        $typeCustomerMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $typeCustomerMock->expects($this->once())
+            ->method('getAttributeCollection')
+            ->willReturn($this->getAttributeMock());
+
+        return $typeCustomerMock;
+    }
+
+    /**
+     * @return Type|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getTypeAddressMock()
+    {
+        $typeAddressMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $typeAddressMock->expects($this->once())
+            ->method('getAttributeCollection')
+            ->willReturn($this->getAttributeMock());
+
+        return $typeAddressMock;
+    }
+
+    /**
+     * @return AbstractAttribute[]|\PHPUnit_Framework_MockObject_MockObject[]
+     */
+    protected function getAttributeMock()
+    {
+        $attributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->setMethods(['getAttributeCode', 'getDataUsingMethod', 'usesSource', 'getSource'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $sourceMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Source\AbstractSource')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $sourceMock->expects($this->any())
+            ->method('getAllOptions')
+            ->willReturn(self::OPTIONS_RESULT);
+
+        $attributeMock->expects($this->once())
+            ->method('getAttributeCode')
+            ->willReturn(self::ATTRIBUTE_CODE);
+
+        $attributeMock->expects($this->any())
+            ->method('getDataUsingMethod')
+            ->willReturnCallback(
+                function ($origName) {
+                    return $origName;
+                }
+            );
+        $attributeMock->expects($this->any())
+            ->method('usesSource')
+            ->willReturn(true);
+        $attributeMock->expects($this->any())
+            ->method('getSource')
+            ->willReturn($sourceMock);
+
+        $this->eavValidationRulesMock->expects($this->any())
+            ->method('build')
+            ->with($attributeMock, $this->logicalNot($this->isEmpty()));
+
+        return [$attributeMock];
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/Address/RelationTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/Address/RelationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d72b965ace153289868b83e6ff6bc507d936fe9
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/Address/RelationTest.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Resource\Address;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * Class AddressTest
+ */
+class RelationTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var  \Magento\Customer\Model\CustomerFactory | \PHPUnit_Framework_MockObject_MockObject */
+    protected $customerFactoryMock;
+
+    /** @var  \Magento\Customer\Model\Resource\Address\Relation */
+    protected $relation;
+
+    protected function setUp()
+    {
+        $this->customerFactoryMock = $this->getMock(
+            'Magento\Customer\Model\CustomerFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->relation = (new ObjectManagerHelper($this))->getObject(
+            'Magento\Customer\Model\Resource\Address\Relation',
+            [
+                'customerFactory' => $this->customerFactoryMock
+            ]
+        );
+    }
+
+    /**
+     * @param $addressId
+     * @param $isDefaultBilling
+     * @param $isDefaultShipping
+     * @dataProvider getRelationDataProvider
+     */
+    public function testProcessRelation($addressId, $isDefaultBilling, $isDefaultShipping)
+    {
+        $addressModel = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            [
+                '__wakeup',
+                'getId',
+                'getEntityTypeId',
+                'getIsDefaultBilling',
+                'getIsDefaultShipping',
+                'hasDataChanges',
+                'validateBeforeSave',
+                'beforeSave',
+                'afterSave',
+                'isSaveAllowed'
+            ],
+            [],
+            '',
+            false
+        );
+        $customerModel = $this->getMock(
+            'Magento\Customer\Model\Customer',
+            ['__wakeup', 'setDefaultBilling', 'setDefaultShipping', 'save', 'load', 'getResource', 'getId'],
+            [],
+            '',
+            false
+        );
+        $customerResource = $this->getMockForAbstractClass(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            [],
+            '',
+            false,
+            false,
+            true,
+            ['getWriteConnection', 'getTable']
+        );
+        $adapter = $this->getMockForAbstractClass(
+            'Magento\Framework\DB\Adapter\AdapterInterface',
+            [],
+            '',
+            false,
+            false,
+            true,
+            ['update', 'quoteInto']
+        );
+        $customerModel->expects($this->any())->method('getResource')->willReturn($customerResource);
+        $addressModel->expects($this->any())->method('getId')->willReturn($addressId);
+        $addressModel->expects($this->any())->method('getIsDefaultShipping')->willReturn($isDefaultShipping);
+        $addressModel->expects($this->any())->method('getIsDefaultBilling')->willReturn($isDefaultBilling);
+        $addressModel->expects($this->any())->method('getIsCustomerSaveTransaction')->willReturn(false);
+
+        $customerModel->expects($this->any())
+             ->method('load')
+             ->willReturnSelf();
+
+        $this->customerFactoryMock->expects($this->any())
+            ->method('create')
+            ->willReturn($customerModel);
+        if ($addressId && ($isDefaultBilling || $isDefaultShipping)) {
+            $customerId = 1;
+            $customerResource->expects($this->exactly(2))->method('getWriteConnection')->willReturn($adapter);
+            $customerModel->expects($this->any())->method('getId')->willReturn(1);
+            $conditionSql = "entity_id = $customerId";
+            $adapter->expects($this->once())->method('quoteInto')
+                ->with('entity_id = ?', $customerId)
+                ->willReturn($conditionSql);
+            $customerResource->expects($this->once())->method('getTable')
+                ->with('customer_entity')
+                ->willReturn('customer_entity');
+            $toUpdate = [];
+            if ($isDefaultBilling) {
+                $toUpdate['default_billing'] = $addressId;
+            }
+            if ($isDefaultShipping) {
+                $toUpdate['default_shipping'] = $addressId;
+            }
+            $adapter->expects($this->once())->method('update')->with(
+                'customer_entity',
+                $toUpdate,
+                $conditionSql
+            );
+        }
+        $this->relation->processRelation($addressModel);
+    }
+
+    /**
+     * Data provider for processRelation method
+     *
+     * @return array
+     */
+    public function getRelationDataProvider()
+    {
+        return [
+            [null, true, true],
+            [1, true, true],
+            [1, true, false],
+            [1, false, true],
+            [1, false, false],
+        ];
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php
index c15cf1596c8245fb30d8a79ba097923d545c26b0..11c8a8378e134a4eb9747d88c261421d9c8d41c1 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php
@@ -8,6 +8,8 @@
 
 namespace Magento\Customer\Test\Unit\Model\Resource;
 
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
 
 class AddressTest extends \PHPUnit_Framework_TestCase
@@ -21,12 +23,37 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Eav\Model\Entity\Type */
     protected $eavConfigType;
 
+    /** @var  Snapshot|\PHPUnit_Framework_MockObject_MockObject */
+    protected $entitySnapshotMock;
+
+    /** @var  RelationComposite|\PHPUnit_Framework_MockObject_MockObject */
+    protected $entityRelationCompositeMock;
+
     protected function setUp()
     {
+        $this->entitySnapshotMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            [],
+            [],
+            '',
+            false
+        );
+
+
+        $this->entityRelationCompositeMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite',
+            [],
+            [],
+            '',
+            false
+        );
+
         $this->addressResource = (new ObjectManagerHelper($this))->getObject(
             'Magento\Customer\Model\Resource\Address',
             [
                 'resource' => $this->prepareResource(),
+                'entitySnapshot' => $this->entitySnapshotMock,
+                'entityRelationComposite' => $this->entityRelationCompositeMock,
                 'eavConfig' => $this->prepareEavConfig(),
                 'validatorFactory' => $this->prepareValidatorFactory(),
                 'customerFactory' => $this->prepareCustomerFactory()
@@ -43,22 +70,6 @@ class AddressTest extends \PHPUnit_Framework_TestCase
      */
     public function testSave($addressId, $isDefaultBilling, $isDefaultShipping)
     {
-        /** @var $customer \Magento\Customer\Model\Address|\PHPUnit_Framework_MockObject_MockObject */
-        $customer = $this->getMock(
-            'Magento\Customer\Model\Customer',
-            ['__wakeup', 'setDefaultBilling', 'setDefaultShipping', 'save', 'load'],
-            [],
-            '',
-            false
-        );
-        $customer->expects($this->any())
-            ->method('load')
-            ->willReturnSelf();
-
-        $this->customerFactory->expects($this->any())
-            ->method('create')
-            ->willReturn($customer);
-
         /** @var $address \Magento\Customer\Model\Address|\PHPUnit_Framework_MockObject_MockObject */
         $address = $this->getMock(
             'Magento\Customer\Model\Address',
@@ -78,7 +89,8 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $address->expects($this->once())->method('hasDataChanges')->willReturn(true);
+        $this->entitySnapshotMock->expects($this->once())->method('isModified')->willReturn(true);
+        $this->entityRelationCompositeMock->expects($this->once())->method('processRelations');
         $address->expects($this->once())->method('isSaveAllowed')->willReturn(true);
         $address->expects($this->once())->method('validateBeforeSave');
         $address->expects($this->once())->method('beforeSave');
@@ -87,19 +99,6 @@ class AddressTest extends \PHPUnit_Framework_TestCase
         $address->expects($this->any())->method('getId')->willReturn($addressId);
         $address->expects($this->any())->method('getIsDefaultShipping')->willReturn($isDefaultShipping);
         $address->expects($this->any())->method('getIsDefaultBilling')->willReturn($isDefaultBilling);
-        if ($addressId && ($isDefaultBilling || $isDefaultShipping)) {
-            if ($isDefaultBilling) {
-                $customer->expects($this->once())->method('setDefaultBilling')->with($addressId);
-            }
-            if ($isDefaultShipping) {
-                $customer->expects($this->once())->method('setDefaultShipping')->with($addressId);
-            }
-            $customer->expects($this->once())->method('save');
-        } else {
-            $customer->expects($this->never())->method('setDefaultBilling');
-            $customer->expects($this->never())->method('setDefaultShipping');
-            $customer->expects($this->never())->method('save');
-        }
         $this->addressResource->setType('customer_address');
         $this->addressResource->save($address);
     }
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index 692eba9dc08461d96d0c449b7ef3e158c31f0c66..cc98e7676b3fa9f7825da52d2d647966661a0978 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -126,4 +126,45 @@
             </argument>
         </arguments>
     </type>
+    <virtualType name="EavVersionControlSnapshot" type="Magento\Framework\Model\Resource\Db\VersionControl\Snapshot">
+        <arguments>
+            <argument name="metadata" xsi:type="object">Magento\Eav\Model\Entity\VersionControl\Metadata</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="CustomerRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
+        <arguments>
+            <argument name="relationProcessors" xsi:type="array">
+                <item name="default" xsi:type="object">Magento\Customer\Model\Resource\Customer\Relation</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="CustomerAddressRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
+        <arguments>
+            <argument name="relationProcessors" xsi:type="array">
+                <item name="default" xsi:type="object">Magento\Customer\Model\Resource\Address\Relation</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Customer\Model\Resource\Customer">
+        <arguments>
+            <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument>
+            <argument name="entityRelationComposite" xsi:type="object">CustomerRelationsComposite</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Customer\Model\Resource\Customer\Collection">
+        <arguments>
+            <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Customer\Model\Resource\Address">
+        <arguments>
+            <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument>
+            <argument name="entityRelationComposite" xsi:type="object">CustomerAddressRelationsComposite</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Customer\Model\Resource\Address\Collection">
+        <arguments>
+            <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
index 21762022d84e565b42a9808389c03c6777d0d5ae..8bf281411f8b171dce5a5b627a8c3e9c3fbe4b77 100644
--- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
+++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
@@ -303,6 +303,9 @@
                     <item name="validation" xsi:type="array">
                         <item name="required-entry" xsi:type="boolean">true</item>
                     </item>
+                    <item name="imports" xsi:type="array">
+                        <item name="default" xsi:type="string">${ $.provider }:data.customer.firstname</item>
+                    </item>
                 </item>
             </argument>
         </field>
@@ -325,6 +328,9 @@
                     <item name="validation" xsi:type="array">
                         <item name="required-entry" xsi:type="boolean">true</item>
                     </item>
+                    <item name="imports" xsi:type="array">
+                        <item name="default" xsi:type="string">${ $.provider }:data.customer.lastname</item>
+                    </item>
                 </item>
             </argument>
         </field>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js b/app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js
similarity index 66%
rename from app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js
rename to app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js
index f25cd3f00ac28fb40a4a560426d5644e2f7855ba..6c658bace739f0f4343fe2b74836a7cab053febf 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js
@@ -2,22 +2,21 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true*/
-/*global define*/
 define(
     [
         'mage/storage',
-        '../model/url-builder',
-        'Magento_Customer/js/model/customer'
+        'Magento_Checkout/js/model/url-builder'
     ],
-    function(storage, urlBuilder, customer) {
-        "use strict";
-        return function(deferred) {
-            storage.post(
+    function (storage, urlBuilder) {
+        'use strict';
+
+        return function (deferred, email) {
+            return storage.post(
                 urlBuilder.createUrl('/customers/isEmailAvailable', {}),
                 JSON.stringify({
-                    customerEmail: customer.customerData.email
-                })
+                    customerEmail: email
+                }),
+                false
             ).done(
                 function (isEmailAvailable) {
                     if (isEmailAvailable) {
diff --git a/app/code/Magento/Customer/view/frontend/web/js/action/login.js b/app/code/Magento/Customer/view/frontend/web/js/action/login.js
index 11dcaeec5cb4b0943bd8b5d043bb59238a4df1c5..31d928825415b94304ca8b6f57fb912f6760a8cd 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/action/login.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/action/login.js
@@ -7,30 +7,45 @@ define(
     [
         'jquery',
         'mage/storage',
-        'Magento_Ui/js/model/errorlist',
-        'Magento_Customer/js/model/customer'
+        'Magento_Ui/js/model/messageList',
+        'Magento_Customer/js/customer-data'
     ],
-    function($, storage, errorlist, customer) {
-        "use strict";
-        return function(loginData, redirectUrl) {
-            return storage.post(
-                'customer/ajax/login',
-                JSON.stringify(loginData)
-            ).done(function (response) {
-                if (response.errors) {
-                    customer.increaseFailedLoginAttempt();
-                    errorlist.add(response);
-                } else {
-                    if (redirectUrl) {
-                        window.location.href = redirectUrl;
+    function($, storage, messageList, customerData) {
+        'use strict';
+        var callbacks = [],
+            action = function(loginData, redirectUrl) {
+                return storage.post(
+                    'customer/ajax/login',
+                    JSON.stringify(loginData)
+                ).done(function (response) {
+                    if (response.errors) {
+                        messageList.addErrorMessage(response);
+                        callbacks.forEach(function(callback) {
+                            callback(loginData);
+                        });
                     } else {
-                        location.reload();
+                        callbacks.forEach(function(callback) {
+                            callback(loginData);
+                        });
+                        customerData.invalidate(['customer']);
+                        if (redirectUrl) {
+                            window.location.href = redirectUrl;
+                        } else {
+                            location.reload();
+                        }
                     }
-                }
-            }).fail(function () {
-                customer.increaseFailedLoginAttempt();
-                errorlist.add({'message': 'Could not authenticate. Please try again later'});
-            });
+                }).fail(function () {
+                    messageList.addErrorMessage({'message': 'Could not authenticate. Please try again later'});
+                    callbacks.forEach(function(callback) {
+                        callback(loginData);
+                    });
+                });
+            };
+
+        action.registerLoginCallback = function(callback) {
+            callbacks.push(callback);
         };
+
+        return action;
     }
 );
diff --git a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
index 2f5c1181ea10d44c4a4e99294dac2ee068822387..bfb277c067d57bb85961c7824bdaf3919f1340b1 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
@@ -9,7 +9,6 @@ define([
     'Magento_Customer/js/section-config',
     'jquery/jquery-storageapi',
     'jquery/jquery.cookie'
-
 ], function ($, _, ko, sectionConfig) {
     'use strict';
 
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js b/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js
new file mode 100644
index 0000000000000000000000000000000000000000..a67a3e0b693973ad41af5205b6887abef0ffa797
--- /dev/null
+++ b/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js
@@ -0,0 +1,15 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'ko',
+        './customer-addresses'
+    ],
+    function(ko, defaultProvider) {
+        "use strict";
+        return ko.observableArray(defaultProvider.getAddressItems());
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js
new file mode 100644
index 0000000000000000000000000000000000000000..c14cffb2c59e3e8edb233a90f34e25a374688d65
--- /dev/null
+++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'ko',
+        './customer/address'
+    ],
+    function($, ko, address) {
+        "use strict";
+        var isLoggedIn = ko.observable(window.isCustomerLoggedIn);
+        return {
+            getAddressItems: function() {
+                var items = [];
+                if (isLoggedIn) {
+                    var customerData = window.customerData;
+                    if (Object.keys(customerData).length) {
+                        $.each(customerData.addresses, function (key, item) {
+                            items.push(new address(item));
+                        });
+                    }
+                }
+                return items;
+            }
+        }
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer.js
index 28a43254db2efdcf3e2e6e5d52b1eeca3841f9d4..25654444d6cc5ee783b134afdf41c44eaac28bdf 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/model/customer.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer.js
@@ -9,46 +9,31 @@ define(
         'ko',
         'underscore',
         'mage/storage',
-        'Magento_Checkout/js/model/addresslist',
-        './customer/address'
+        './address-list'
     ],
-    function($, ko, _, storage, addressList, address) {
+    function($, ko, _, storage, addressList) {
         "use strict";
         var isLoggedIn = ko.observable(window.isCustomerLoggedIn),
-            failedLoginAttempts = ko.observable(0),
             customerData = {};
 
         if (isLoggedIn()) {
             customerData = window.customerData;
-            if (Object.keys(customerData).length) {
-                $.each(customerData.addresses, function (key, item) {
-                    addressList.add(new address(item));
-                });
-            }
         } else {
             customerData = {};
         }
+
         return {
             customerData: customerData,
             customerDetails: {},
-            isLoggedIn: function() {
-                return isLoggedIn;
-            },
+            isLoggedIn: isLoggedIn,
             setIsLoggedIn: function (flag) {
                 isLoggedIn(flag);
             },
-            getFailedLoginAttempts: function() {
-                return failedLoginAttempts;
-            },
-            increaseFailedLoginAttempt: function() {
-                var oldAttempts = failedLoginAttempts();
-                failedLoginAttempts(++oldAttempts);
-            },
             getBillingAddressList: function () {
-                return addressList.getAddresses();
+                return addressList();
             },
             getShippingAddressList: function () {
-                return addressList.getAddresses();
+                return addressList();
             },
             setDetails: function (fieldName, value) {
                 if (fieldName) {
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
index 104655e0f2224625ceb03f07e78453fa9cfb9e14..c3f656411450d8f6a9603d7688a93d5e8f788fd7 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
@@ -5,6 +5,10 @@
 /*jshint browser:true jquery:true*/
 /*global alert*/
 define([], function() {
+    /**
+     * @param addressData
+     * Returns new address object
+     */
     return function (addressData) {
         return {
             customerAddressId: addressData.id,
@@ -26,9 +30,28 @@ define([], function() {
             prefix: addressData.prefix,
             suffix: addressData.suffix,
             vatId: addressData.vat_id,
-            sameAsBilling: null,
+            sameAsBilling: addressData.same_as_billing,
+            saveInAddressBook: addressData.save_in_address_book,
+            isDefaultShipping: function() {
+                return addressData.default_shipping;
+            },
+            isDefaultBilling: function() {
+                return addressData.default_billing;
+            },
             getAddressInline: function() {
                 return addressData.inline;
+            },
+            getType: function() {
+                return 'customer-address'
+            },
+            getKey: function() {
+                return this.getType() + this.customerAddressId;
+            },
+            isEditable: function() {
+                return false;
+            },
+            canUseForBilling: function() {
+                return true;
             }
         }
     }
diff --git a/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js b/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js
new file mode 100644
index 0000000000000000000000000000000000000000..ae864756661c84ffe7ab65d320d6b80d32822bca
--- /dev/null
+++ b/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js
@@ -0,0 +1,116 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'jquery',
+        'uiComponent',
+        'ko',
+        'Magento_Customer/js/model/customer',
+        'Magento_Customer/js/action/check-email-availability',
+        'Magento_Customer/js/action/login',
+        'Magento_Checkout/js/model/quote',
+        'mage/validation'
+    ],
+    function ($, Component, ko, customer, checkEmailAvailability, loginAction, quote) {
+        "use strict";
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Customer/customer-email',
+                email: '',
+                isLoading: false,
+                isPasswordVisible: false
+            },
+            checkDelay: 2000,
+            checkRequest: null,
+            isEmailCheckComplete: null,
+            isCustomerLoggedIn: customer.isLoggedIn,
+            forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl,
+            emailCheckTimeout: 0,
+
+            initialize: function() {
+                this._super();
+                var self = this;
+                this.email.subscribe(function() {
+                    self.emailHasChanged();
+                });
+            },
+
+            /** Initialize observable properties */
+            initObservable: function () {
+                this._super()
+                    .observe(['email', 'isLoading', 'isPasswordVisible']);
+                return this;
+            },
+
+            emailHasChanged: function () {
+                var self = this;
+                clearTimeout(this.emailCheckTimeout);
+                this.emailCheckTimeout = setTimeout(function () {
+                    if (self.validateEmail()) {
+                        self.checkEmailAvailability();
+                        quote.guestEmail = self.email();
+                    } else {
+                        self.isPasswordVisible(false);
+                    }
+                }, self.checkDelay);
+
+            },
+
+            checkEmailAvailability: function() {
+                var self = this;
+                this.validateRequest();
+                this.isEmailCheckComplete = $.Deferred();
+                this.isLoading(true);
+                this.checkRequest = checkEmailAvailability(this.isEmailCheckComplete, this.email());
+
+                $.when(this.isEmailCheckComplete).done(function() {
+                    self.isPasswordVisible(false);
+                }).fail( function() {
+                    self.isPasswordVisible(true);
+                }).always(function () {
+                    self.isLoading(false);
+                });
+            },
+
+            validateRequest: function() {
+                /*
+                 * If request has been sent -> abort it.
+                 * ReadyStates for request aborting:
+                 * 1 - The request has been set up
+                 * 2 - The request has been sent
+                 * 3 - The request is in process
+                 */
+                if (this.checkRequest != null && $.inArray(this.checkRequest.readyState, [1, 2, 3])) {
+                    this.checkRequest.abort();
+                    this.checkRequest = null;
+                }
+            },
+
+            validateEmail: function() {
+                var loginFormSelector = 'form[data-role=email-with-possible-login]';
+                $(loginFormSelector).validation();
+                var validationResult = $(loginFormSelector + ' input[name=username]').valid();
+                return Boolean(validationResult);
+            },
+
+            login: function(loginForm) {
+                var loginData = {},
+                    formDataArray = $(loginForm).serializeArray();
+
+                formDataArray.forEach(function (entry) {
+                    loginData[entry.name] = entry.value;
+                });
+                if (this.isPasswordVisible()
+                    && $(loginForm).validation()
+                    && $(loginForm).validation('isValid')
+                ) {
+                    loginAction(loginData);
+                }
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Customer/view/frontend/web/template/customer-email.html b/app/code/Magento/Customer/view/frontend/web/template/customer-email.html
new file mode 100644
index 0000000000000000000000000000000000000000..898a3300ed78e3e2262baaf6fbf040fef297620c
--- /dev/null
+++ b/app/code/Magento/Customer/view/frontend/web/template/customer-email.html
@@ -0,0 +1,67 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko ifnot: isCustomerLoggedIn() -->
+
+<!-- ko foreach: getRegion('before-login-form') -->
+<!-- ko template: getTemplate() --><!-- /ko -->
+<!-- /ko -->
+<form class="form form-login" data-role="email-with-possible-login"
+      data-bind="submit:login"
+      method="post">
+    <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading">
+        <div class="field required">
+            <label class="label" for="customer-email">
+                <span data-bind="text: $t('Email Address')"></span>
+            </label>
+            <div class="control _with-tooltip">
+                <input class="input-text"
+                       type="email"
+                       data-bind="textInput: email"
+                       name="username"
+                       data-validate="{required:true, 'validate-email':true}"
+                       id="customer-email" />
+                <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko -->
+                <span class="note"><!-- ko text: $t("(You can create an account after checkout)")--><!-- /ko --></span>
+            </div>
+        </div>
+
+        <!--Hidden fields -->
+        <fieldset class="fieldset hidden-fields" data-bind="fadeVisible: isPasswordVisible">
+            <div class="field">
+                <label class="label" for="customer-password">
+                    <span data-bind="text: $t('Password')"></span>
+                </label>
+                <div class="control">
+                    <input class="input-text"
+                           placeholder="optional"
+                           type="password"
+                           name="password"
+                           id="customer-password"
+                           data-validate="{required:true, 'validate-password':true}" />
+                    <span class="note" data-bind="text: $t('You already have an account with us. Sign in or continue as guest.')"></span>
+                </div>
+
+            </div>
+            <!-- ko foreach: getRegion('additional-login-form-fields') -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!-- /ko -->
+            <div class="actions-toolbar">
+                <input name="context" type="hidden" value="checkout" />
+                <div class="primary">
+                    <button type="submit" class="action login primary" data-action="checkout-method-login"><span data-bind="text: $t('Login')"></span></button>
+                </div>
+                <div class="secondary">
+                    <a class="action remind" data-bind="attr: { href: forgotPasswordUrl }">
+                        <span data-bind="text: $t('Forgot Your Password?')"></span>
+                    </a>
+                </div>
+            </div>
+        </fieldset>
+        <!--Hidden fields -->
+    </fieldset>
+</form>
+<!-- /ko -->
diff --git a/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ac3abe1cd6cb6fa38d82426add0139152f4b1e5b
--- /dev/null
+++ b/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="step-config" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="shipping-rates-validation" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="dhl-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Dhl/js/view/shipping-rates-validation</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557
--- /dev/null
+++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'postcode': {
+                        'required': true
+                    },
+                    'country_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1
--- /dev/null
+++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        './shipping-rates-validation-rules',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js
new file mode 100644
index 0000000000000000000000000000000000000000..de18ca91237cd6affd9e4f56b167bcdbcfd056ef
--- /dev/null
+++ b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../model/shipping-rates-validator',
+        '../model/shipping-rates-validation-rules'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        dhlShippingRatesValidator,
+        dhlShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('dhl', dhlShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('dhl', dhlShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/Directory/Helper/Data.php b/app/code/Magento/Directory/Helper/Data.php
index 1f7bae3fd00d0910f2c2c9589c180bd1be37cf16..fbd071c13824eb155d3adbd91b6ee9595beb8a5c 100644
--- a/app/code/Magento/Directory/Helper/Data.php
+++ b/app/code/Magento/Directory/Helper/Data.php
@@ -160,28 +160,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             $cacheKey = 'DIRECTORY_REGIONS_JSON_STORE' . $this->_storeManager->getStore()->getId();
             $json = $this->_configCacheType->load($cacheKey);
             if (empty($json)) {
-                $countryIds = [];
-                foreach ($this->getCountryCollection() as $country) {
-                    $countryIds[] = $country->getCountryId();
-                }
-                $collection = $this->_regCollectionFactory->create();
-                $collection->addCountryFilter($countryIds)->load();
-                $regions = [
-                    'config' => [
-                        'show_all_regions' => $this->isShowNonRequiredState(),
-                        'regions_required' => $this->getCountriesWithStatesRequired(),
-                    ],
-                ];
-                foreach ($collection as $region) {
-                    /** @var $region \Magento\Directory\Model\Region */
-                    if (!$region->getRegionId()) {
-                        continue;
-                    }
-                    $regions[$region->getCountryId()][$region->getRegionId()] = [
-                        'code' => $region->getCode(),
-                        'name' => (string)__($region->getName()),
-                    ];
-                }
+                $regions = $this->getRegionData();
                 $json = $this->jsonHelper->jsonEncode($regions);
                 if ($json === false) {
                     $json = 'false';
@@ -324,4 +303,36 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             $store
         );
     }
+
+    /**
+     * Retrieve regions data
+     *
+     * @return array
+     */
+    public function getRegionData()
+    {
+        $countryIds = [];
+        foreach ($this->getCountryCollection() as $country) {
+            $countryIds[] = $country->getCountryId();
+        }
+        $collection = $this->_regCollectionFactory->create();
+        $collection->addCountryFilter($countryIds)->load();
+        $regions = [
+            'config' => [
+                'show_all_regions' => $this->isShowNonRequiredState(),
+                'regions_required' => $this->getCountriesWithStatesRequired(),
+            ],
+        ];
+        foreach ($collection as $region) {
+            /** @var $region \Magento\Directory\Model\Region */
+            if (!$region->getRegionId()) {
+                continue;
+            }
+            $regions[$region->getCountryId()][$region->getRegionId()] = [
+                'code' => $region->getCode(),
+                'name' => (string)__($region->getName()),
+            ];
+        }
+        return $regions;
+    }
 }
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config.php b/app/code/Magento/Directory/Model/Country/Postcode/Config.php
new file mode 100644
index 0000000000000000000000000000000000000000..344938c4aaf54bc448544d2439235adddcd0700d
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode;
+
+class Config implements ConfigInterface
+{
+    /**
+     * @var Config\Data
+     */
+    protected $dataStorage;
+
+    /**
+     * @param Config\Data $dataStorage
+     */
+    public function __construct(\Magento\Directory\Model\Country\Postcode\Config\Data $dataStorage)
+    {
+        $this->dataStorage = $dataStorage;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPostCodes()
+    {
+        return $this->dataStorage->get();
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php
new file mode 100644
index 0000000000000000000000000000000000000000..be9ee4dca475c8be5b5be9364a3741f1b0cde6cd
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode\Config;
+
+class Converter implements \Magento\Framework\Config\ConverterInterface
+{
+    /**
+     * @var \Magento\Framework\Stdlib\BooleanUtils
+     */
+    protected $booleanUtils;
+
+    /**
+     * @param \Magento\Framework\Stdlib\BooleanUtils $booleanUtils
+     */
+    public function __construct(\Magento\Framework\Stdlib\BooleanUtils $booleanUtils)
+    {
+        $this->booleanUtils = $booleanUtils;
+    }
+
+    /**
+     * Convert dom node tree to array
+     *
+     * @param \DOMDocument $source
+     * @return array
+     */
+    public function convert($source)
+    {
+        $result = [];
+        /** @var \DOMNode $zipNode */
+        foreach ($source->documentElement->childNodes as $zipNode) {
+            if ($zipNode->nodeType != XML_ELEMENT_NODE) {
+                continue;
+            }
+            $groupName = $zipNode->attributes->getNamedItem('countryCode')->nodeValue;
+            /** @var \DOMNode $codesNode */
+            foreach ($zipNode->childNodes as $codesNode) {
+                if ($codesNode->nodeType != XML_ELEMENT_NODE) {
+                    continue;
+                }
+                /** @var \DOMNode $code */
+                foreach ($codesNode->childNodes as $code) {
+                    if ($code->nodeType != XML_ELEMENT_NODE
+                        || !$this->booleanUtils->toBoolean($code->attributes->getNamedItem('active')->nodeValue)
+                    ) {
+                        continue;
+                    }
+                    $result[$groupName][$code->attributes->getNamedItem('id')->nodeValue] = [
+                        'example' => $code->attributes->getNamedItem('example')->nodeValue,
+                        'pattern' => $code->nodeValue
+                    ];
+                }
+            }
+        }
+        return $result;
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3dc1a7a6c7a3c575172f6d2ddc8e87efff99488
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode\Config;
+
+class Data extends \Magento\Framework\Config\Data
+{
+    /**
+     * @param \Magento\Directory\Model\Country\Postcode\Config\Reader $reader
+     * @param \Magento\Framework\Config\CacheInterface $cache
+     */
+    public function __construct(
+        \Magento\Directory\Model\Country\Postcode\Config\Reader $reader,
+        \Magento\Framework\Config\CacheInterface $cache
+    ) {
+        parent::__construct($reader, $cache, 'country_postcodes');
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php
new file mode 100644
index 0000000000000000000000000000000000000000..7fb5878318dccc009756dc4feacf15ab015f22fd
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode\Config;
+
+class Reader extends \Magento\Framework\Config\Reader\Filesystem
+{
+    /**
+     * Construct the FileSystem Reader Class
+     *
+     * @param \Magento\Framework\Config\FileResolverInterface $fileResolver
+     * @param Converter $converter
+     * @param SchemaLocator $schemaLocator
+     * @param \Magento\Framework\Config\ValidationStateInterface $validationState
+     * @param string $fileName
+     * @param array $idAttributes
+     * @param string $domDocumentClass
+     * @param string $defaultScope
+     */
+    public function __construct(
+        \Magento\Framework\Config\FileResolverInterface $fileResolver,
+        Converter $converter,
+        \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator $schemaLocator,
+        \Magento\Framework\Config\ValidationStateInterface $validationState,
+        $fileName = 'zip_codes.xml',
+        $idAttributes = [],
+        $domDocumentClass = 'Magento\Framework\Config\Dom',
+        $defaultScope = 'global'
+    ) {
+        parent::__construct(
+            $fileResolver,
+            $converter,
+            $schemaLocator,
+            $validationState,
+            $fileName,
+            $idAttributes,
+            $domDocumentClass,
+            $defaultScope
+        );
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php
new file mode 100644
index 0000000000000000000000000000000000000000..5984a2e501b71983b6c9c6a00bdf546e7f81827a
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode\Config;
+
+class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface
+{
+    /**
+     * Path to corresponding XSD file with validation rules for both individual and merged configs
+     *
+     * @var string
+     */
+    private $schema;
+
+    /**
+     * @param \Magento\Framework\Module\Dir\Reader $moduleReader
+     */
+    public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader)
+    {
+        $this->schema = $moduleReader->getModuleDir('etc', 'Magento_Directory') . '/zip_codes.xsd';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSchema()
+    {
+        return $this->schema;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPerFileSchema()
+    {
+        return $this->schema;
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php b/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac1d487d47575c814c8c364f3e4d438494aaca87
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode;
+
+interface ConfigInterface
+{
+
+    /**
+     * Returns array of postcodes validation patterns
+     *
+     * @return array
+     */
+    public function getPostCodes();
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Validator.php b/app/code/Magento/Directory/Model/Country/Postcode/Validator.php
new file mode 100644
index 0000000000000000000000000000000000000000..a57d379683b3c802f1ac7060e5f8460a88416907
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/Validator.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode;
+
+class Validator implements ValidatorInterface
+{
+    /**
+     * @var ConfigInterface
+     */
+    protected $postCodesConfig;
+
+    /**
+     * @param ConfigInterface $postCodesConfig
+     */
+    public function __construct(\Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig)
+    {
+        $this->postCodesConfig = $postCodesConfig;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function validate($postcode, $countryId)
+    {
+        $postCodes = $this->postCodesConfig->getPostCodes();
+        if (isset($postCodes[$countryId]) && is_array($postCodes[$countryId])) {
+            $patterns = $postCodes[$countryId];
+            foreach ($patterns as $pattern) {
+                preg_match('/' . $pattern['pattern'] . '/', $postcode, $matches);
+                if (count($matches)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        throw new \InvalidArgumentException('Provided countryId does not exist.');
+    }
+}
diff --git a/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php b/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..b6517be656a31a4ace53ffec657867ae22360ace
--- /dev/null
+++ b/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode;
+
+interface ValidatorInterface
+{
+    /**
+     * Validate postcode for selected country by mask
+     *
+     * @param string $postcode
+     * @param string $countryId
+     * @return bool
+     * @throws \InvalidArgumentException
+     */
+    public function validate($postcode, $countryId);
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4f4d4b5bbd79536735e3a78a5b1b99bf0ef7893
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config;
+
+class ConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Model\Address\Config\Converter
+     */
+    protected $model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $booleanUtilsMock;
+
+    public function setUp()
+    {
+        $this->booleanUtilsMock = $this->getMock('Magento\Framework\Stdlib\BooleanUtils', [], [], '', false);
+        $this->model = new \Magento\Directory\Model\Country\Postcode\Config\Converter($this->booleanUtilsMock);
+    }
+
+    public function testConvert()
+    {
+        $inputData = new \DOMDocument();
+        $this->booleanUtilsMock->expects($this->any())->method('toBoolean')->willReturn(true);
+        $inputData->load(__DIR__ . '/../../../../_files/zip_codes.xml');
+        $expectedResult = require __DIR__ . '/../../../../_files/zip_codes.php';
+        $this->assertEquals($expectedResult, $this->model->convert($inputData));
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..18663e83e74f9c63b1a2ca9f51e9b84cc8d82882
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config;
+
+class DataTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $readerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $cacheMock;
+
+    protected function setUp()
+    {
+        $this->readerMock = $this->getMockBuilder(
+            'Magento\Directory\Model\Country\Postcode\Config\Reader'
+        )->disableOriginalConstructor()->getMock();
+        $this->cacheMock = $this->getMockBuilder(
+            'Magento\Framework\App\Cache\Type\Config'
+        )->disableOriginalConstructor()->getMock();
+    }
+
+    public function testGet()
+    {
+        $expected = ['someData' => ['someValue', 'someKey' => 'someValue']];
+        $this->cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize($expected)));
+        $configData = new \Magento\Directory\Model\Country\Postcode\Config\Data($this->readerMock, $this->cacheMock);
+
+        $this->assertEquals($expected, $configData->get());
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..066dcbcbd6668e319b1ea9c9e9b2a5c728f69064
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config;
+
+class ReaderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Sales\Model\Config\Reader
+     */
+    protected $reader;
+
+    /**
+     * Prepare parameters
+     */
+    public function setUp()
+    {
+        $fileResolver = $this->getMockBuilder(
+            'Magento\Framework\App\Config\FileResolver'
+        )->disableOriginalConstructor()->getMock();
+        $converter = $this->getMockBuilder(
+            'Magento\Directory\Model\Country\Postcode\Config\Converter'
+        )->disableOriginalConstructor()->getMock();
+        $schema = $this->getMockBuilder(
+            'Magento\Directory\Model\Country\Postcode\Config\SchemaLocator'
+        )->disableOriginalConstructor()->getMock();
+        $validator = $this->getMockBuilder(
+            'Magento\Framework\Config\ValidationStateInterface'
+        )->disableOriginalConstructor()->getMock();
+        $this->reader = new \Magento\Directory\Model\Country\Postcode\Config\Reader(
+            $fileResolver,
+            $converter,
+            $schema,
+            $validator
+        );
+    }
+
+    /**
+     * Test creating object
+     */
+    public function testInstanceof()
+    {
+        $this->assertInstanceOf('Magento\Directory\Model\Country\Postcode\Config\Reader', $this->reader);
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..794dc5a1ce9fe90129b8e8f47e8f73a004d1f2e6
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config;
+
+class SchemaLocatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $moduleReaderMock;
+
+    /**
+     * @var \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->moduleReaderMock = $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false);
+        $this->moduleReaderMock->expects(
+            $this->any()
+        )->method(
+            'getModuleDir'
+        )->with(
+            'etc',
+            'Magento_Directory'
+        )->will(
+            $this->returnValue('schema_dir')
+        );
+
+        $this->model = new \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator($this->moduleReaderMock);
+    }
+
+    public function testGetSchema()
+    {
+        $this->assertEquals('schema_dir/zip_codes.xsd', $this->model->getSchema());
+    }
+
+    public function testGetPerFileSchema()
+    {
+        $this->assertEquals('schema_dir/zip_codes.xsd', $this->model->getPerFileSchema());
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d24ead182cb394c290616125b3084a466eb8a385
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode;
+
+class ConfigTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dataStorageMock;
+
+    protected function setUp()
+    {
+        $this->dataStorageMock = $this->getMock(
+            '\Magento\Directory\Model\Country\Postcode\Config\Data',
+            [],
+            [],
+            '',
+            false
+        );
+    }
+
+    public function testGet()
+    {
+        $expected = ['US' => ['pattern_01' => 'pattern_01', 'pattern_02' => 'pattern_02']];
+        $this->dataStorageMock->expects($this->once())->method('get')->willReturn($expected);
+        $configData = new \Magento\Directory\Model\Country\Postcode\Config($this->dataStorageMock);
+        $this->assertEquals($expected, $configData->getPostCodes());
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7bf2562a6ed01b9f0d725a50ba9ce6eae6bf9c01
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Test\Unit\Model\Country\Postcode;
+
+class ValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $postcodesConfigMock;
+
+    /**
+     * @var \Magento\Directory\Model\Country\Postcode\Validator
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->postcodesConfigMock = $this->getMock(
+            '\Magento\Directory\Model\Country\Postcode\Config',
+            [],
+            [],
+            '',
+            false
+        );
+        $postCodes = [
+            'US' => [
+                'pattern_1' => ['pattern' => '^[0-9]{5}\-[0-9]{4}$'],
+                'pattern_2' => ['pattern' => '^[0-9]{5}$']
+            ]
+        ];
+        $this->postcodesConfigMock->expects($this->once())->method('getPostCodes')->willReturn($postCodes);
+        $this->model = new \Magento\Directory\Model\Country\Postcode\Validator($this->postcodesConfigMock);
+    }
+
+    public function testValidatePositive()
+    {
+        $postcode = '12345-6789';
+        $countryId = 'US';
+        $this->assertTrue($this->model->validate($postcode, $countryId));
+    }
+
+    public function testValidateNegative()
+    {
+        $postcode = 'POST-CODE';
+        $countryId = 'US';
+        $this->assertFalse($this->model->validate($postcode, $countryId));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Provided countryId does not exist.
+     */
+    public function testValidateThrowExceptionIfCountryDoesNotExist()
+    {
+        $postcode = '12345-6789';
+        $countryId = 'QQ';
+        $this->assertFalse($this->model->validate($postcode, $countryId));
+    }
+}
diff --git a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a151e73a3e72cd6b7c86874441aeaa2a1106c87
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+return [
+    'US' => [
+        'pattern_1' => [
+            'example' => 12345,
+            'pattern' => '^[0-9]{5}\-[0-9]{4}$'
+        ],
+        'pattern_2' => [
+            'example' => 12345,
+            'pattern' => '^[0-9]{5}$'
+        ]
+    ]
+];
diff --git a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bbe7582ea62c267702eb25b4415ea01ac9585e8f
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Directory/etc/zip_codes.xsd">
+    <zip countryCode="US">
+        <codes>
+            <code id="pattern_1" example="12345" active="true">^[0-9]{5}\-[0-9]{4}$</code>
+            <code id="pattern_2" example="12345" active="true">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+</config>
diff --git a/app/code/Magento/Directory/etc/di.xml b/app/code/Magento/Directory/etc/di.xml
index 36d16743f8363c39e4aa87e8019fcb0a51014af5..c1e11e69808025b7013f0e5837ec784ca0f40be3 100644
--- a/app/code/Magento/Directory/etc/di.xml
+++ b/app/code/Magento/Directory/etc/di.xml
@@ -27,4 +27,6 @@
             <argument name="helperData" xsi:type="object">DirectoryHelperDataProxy</argument>
         </arguments>
     </type>
+    <preference for="Magento\Directory\Model\Country\Postcode\ConfigInterface" type="Magento\Directory\Model\Country\Postcode\Config" />
+    <preference for="Magento\Directory\Model\Country\Postcode\ValidatorInterface" type="Magento\Directory\Model\Country\Postcode\Validator" />
 </config>
diff --git a/app/code/Magento/Directory/etc/zip_codes.xml b/app/code/Magento/Directory/etc/zip_codes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dfca9b740fa036ae66a94aaac0fc60154a79a626
--- /dev/null
+++ b/app/code/Magento/Directory/etc/zip_codes.xml
@@ -0,0 +1,487 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Directory/etc/zip_codes.xsd">
+    <zip countryCode="DZ">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AS">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AR">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AM">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AU">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AT">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="AZ">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+            <code id="pattern_2" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BD">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BY">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BE">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BA">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BR">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+            <code id="pattern_2" active="true" example="12345-678">^[0-9]{5}\-[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BN">
+        <codes>
+            <code id="pattern_1" active="true" example="AB1234">^[a-zA-z]{2}[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="BG">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CA">
+        <codes>
+            <code id="pattern_1" active="true" example="A1B 2C3">^[a-zA-z]{1}[0-9]{1}[a-zA-z]{1}\s[0-9]{1}[a-zA-z]{1}[0-9]{1}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="IC">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CN">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="HR">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CU">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CY">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CZ">
+        <codes>
+            <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="DK">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="EE">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="FI">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="FR">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GF">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GE">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="DE">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GR">
+        <codes>
+            <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GL">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GP">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GU">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GG">
+        <codes>
+            <code id="pattern_1" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="HU">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="IS">
+        <codes>
+            <code id="pattern_1" active="true" example="123">^[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="IN">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="ID">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="IL">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="IT">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="JP">
+        <codes>
+            <code id="pattern_1" active="true" example="123-4567">^[0-9]{3}-[0-9]{4}$</code>
+            <code id="pattern_2" active="true" example="123">^[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="JE">
+        <codes>
+            <code id="pattern_1" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="KZ">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="KE">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="KR">
+        <codes>
+            <code id="pattern_1" active="true" example="123-456">^[0-9]{3}-[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="KG">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="LV">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="LI">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="LT">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="LU">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MK">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MG">
+        <codes>
+            <code id="pattern_1" active="true" example="123">^[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MY">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MV">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+            <code id="pattern_2" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MT">
+        <codes>
+            <code id="pattern_1" active="true" example="ABC 123">^[a-zA-Z]{3}\s[0-9]{3}$</code>
+            <code id="pattern_2" active="true" example="ABC 12">^[a-zA-Z]{3}\s[0-9]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MH">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MQ">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MX">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MD">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MC">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MN">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MA">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="NL">
+        <codes>
+            <code id="pattern_1" active="true" example="1234 AB">^[0-9]{4}\s[a-zA-Z]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="NO">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="PK">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="PH">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="PL">
+        <codes>
+            <code id="pattern_1" active="true" example="12-345">^[0-9]{2}-[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="PT">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+            <code id="pattern_2" active="true" example="1234-567">^[0-9]{4}-[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="PR">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="RE">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="RO">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="RU">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="MP">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CS">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="SG">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="SK">
+        <codes>
+            <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="SI">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="ZA">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="ES">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="XY">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="SZ">
+        <codes>
+            <code id="pattern_1" active="true" example="A123">^[a-zA-Z]{1}[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="SE">
+        <codes>
+            <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="CH">
+        <codes>
+            <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="TW">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+            <code id="pattern_2" active="true" example="123">^[0-9]{3}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="TJ">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="TH">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="TR">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="TM">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="UA">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="GB">
+        <codes>
+            <code id="pattern_1" active="true" example="AB12 3CD">^[a-zA-Z]{2}[0-9]{2}\s[0-9]{1}[a-zA-Z]{2}$</code>
+            <code id="pattern_2" active="true" example="A1B 2CD">^[a-zA-Z]{1}[0-9]{1}[a-zA-Z]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+            <code id="pattern_3" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+            <code id="pattern_4" active="true" example="AB1C 2DF">^[a-zA-Z]{2}[0-9]{1}[a-zA-Z]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+            <code id="pattern_5" active="true" example="A12 3BC">^[a-zA-Z]{1}[0-9]{2}\s[0-9]{1}[a-zA-Z]{2}$</code>
+            <code id="pattern_6" active="true" example="A1 2BC">^[a-zA-Z]{1}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="US">
+        <codes>
+            <code id="pattern_1" active="true" example="12345-6789">^[0-9]{5}\-[0-9]{4}$</code>
+            <code id="pattern_2" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="UY">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="UZ">
+        <codes>
+            <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code>
+        </codes>
+    </zip>
+    <zip countryCode="VI">
+        <codes>
+            <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code>
+        </codes>
+    </zip>
+</config>
diff --git a/app/code/Magento/Directory/etc/zip_codes.xsd b/app/code/Magento/Directory/etc/zip_codes.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..5400633a0df327bc20546c074d4b5b89d6ccdd12
--- /dev/null
+++ b/app/code/Magento/Directory/etc/zip_codes.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="config" type="configType">
+    </xs:element>
+
+    <xs:complexType name="zipType">
+        <xs:sequence>
+            <xs:element type="codesType" name="codes"/>
+        </xs:sequence>
+        <xs:attribute type="xs:string" name="countryCode" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="codesType">
+        <xs:sequence>
+            <xs:element type="codeType" name="code" maxOccurs="unbounded" minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="configType">
+        <xs:sequence>
+            <xs:element type="zipType" name="zip" maxOccurs="unbounded" minOccurs="1"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="codeType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute type="xs:string" name="id" use="required"/>
+                <xs:attribute type="xs:string" name="example" use="required"/>
+                <xs:attribute type="xs:boolean" name="active" use="optional"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
index 96465ce1dfb580896dec931e5ee40ea2c7fec76a..0c36e420156d691b5a2cd7f1db7691117bc9ff7e 100755
--- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
+++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
@@ -896,6 +896,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Abs
         \Magento\Framework\Profiler::start('set_orig_data');
         foreach ($this->_items as $item) {
             $item->setOrigData();
+            $this->beforeAddLoadedItem($item);
         }
         \Magento\Framework\Profiler::stop('set_orig_data');
 
diff --git a/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..57e071e2f846dbfd51e1de43ba6c49ebdf0eb2b8
--- /dev/null
+++ b/app/code/Magento/Eav/Model/Entity/Collection/VersionControl/AbstractCollection.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Model\Entity\Collection\VersionControl;
+
+/**
+ * Class Abstract Collection
+ */
+abstract class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
+{
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot
+     */
+    protected $entitySnapshot;
+
+    /**
+     * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
+     * @param \Psr\Log\LoggerInterface $logger
+     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
+     * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param \Magento\Eav\Model\Config $eavConfig
+     * @param \Magento\Framework\App\Resource $resource
+     * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
+     * @param \Magento\Eav\Model\Resource\Helper $resourceHelper
+     * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+     * @param mixed $connection
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
+        \Psr\Log\LoggerInterface $logger,
+        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
+        \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Eav\Model\Config $eavConfig,
+        \Magento\Framework\App\Resource $resource,
+        \Magento\Eav\Model\EntityFactory $eavEntityFactory,
+        \Magento\Eav\Model\Resource\Helper $resourceHelper,
+        \Magento\Framework\Validator\UniversalFactory $universalFactory,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+        $connection = null
+    ) {
+        $this->entitySnapshot = $entitySnapshot;
+
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $eavConfig,
+            $resource,
+            $eavEntityFactory,
+            $resourceHelper,
+            $universalFactory,
+            $connection
+        );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function fetchItem()
+    {
+        $item = parent::fetchItem();
+        if ($item) {
+            $this->entitySnapshot->registerSnapshot($item);
+        }
+        return $item;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function beforeAddLoadedItem(\Magento\Framework\Object $item)
+    {
+        $this->entitySnapshot->registerSnapshot($item);
+        return $item;
+    }
+}
diff --git a/app/code/Magento/Eav/Model/Entity/VersionControl/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/VersionControl/AbstractEntity.php
new file mode 100644
index 0000000000000000000000000000000000000000..781c1baae9a6e564cdad284fe5d6e175489bb8f0
--- /dev/null
+++ b/app/code/Magento/Eav/Model/Entity/VersionControl/AbstractEntity.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Model\Entity\VersionControl;
+
+/**
+ * Class AbstractEntity
+ */
+abstract class AbstractEntity extends \Magento\Eav\Model\Entity\AbstractEntity
+{
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot
+     */
+    protected $entitySnapshot;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite
+     */
+    protected $entityRelationComposite;
+
+    /**
+     * @param \Magento\Eav\Model\Entity\Context $context
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Eav\Model\Entity\Context $context,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
+        $data = []
+    ) {
+        $this->entitySnapshot = $entitySnapshot;
+        $this->entityRelationComposite = $entityRelationComposite;
+
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function _afterLoad(\Magento\Framework\Object $object)
+    {
+        $this->entitySnapshot->registerSnapshot($object);
+        return parent::_afterLoad($object);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function save(\Magento\Framework\Model\AbstractModel $object)
+    {
+        /**
+         * Direct deleted items to delete method
+         */
+        if ($object->isDeleted()) {
+            return $this->delete($object);
+        }
+
+        $this->beginTransaction();
+
+        try {
+            if (!$this->isModified($object)) {
+                $this->entityRelationComposite->processRelations($object);
+                $this->commit();
+                return $this;
+            }
+
+            $object->validateBeforeSave();
+            $object->beforeSave();
+
+            if ($object->isSaveAllowed()) {
+                if (!$this->isPartialSave()) {
+                    $this->loadAllAttributes($object);
+                }
+
+                if ($this->getEntityTable() ==  \Magento\Eav\Model\Entity::DEFAULT_ENTITY_TABLE
+                    && !$object->getEntityTypeId()
+                ) {
+                    $object->setEntityTypeId($this->getTypeId());
+                }
+
+                $object->setParentId((int)$object->getParentId());
+
+                $this->objectRelationProcessor->validateDataIntegrity($this->getEntityTable(), $object->getData());
+
+                $this->_beforeSave($object);
+                $this->_processSaveData($this->_collectSaveData($object));
+                $this->_afterSave($object);
+                $this->entitySnapshot->registerSnapshot($object);
+                $object->afterSave();
+                $this->entityRelationComposite->processRelations($object);
+            }
+
+            $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
+            $object->setHasDataChanges(false);
+        } catch (\Exception $e) {
+            $this->rollBack();
+            $object->setHasDataChanges(true);
+            throw $e;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Checks if entity was modified
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return bool
+     */
+    protected function isModified(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $this->entitySnapshot->isModified($object);
+    }
+}
diff --git a/app/code/Magento/Eav/Model/Entity/VersionControl/Metadata.php b/app/code/Magento/Eav/Model/Entity/VersionControl/Metadata.php
new file mode 100644
index 0000000000000000000000000000000000000000..c628f450b7a18a2197c24756bec82c0a6801e8c0
--- /dev/null
+++ b/app/code/Magento/Eav/Model/Entity/VersionControl/Metadata.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Model\Entity\VersionControl;
+
+/**
+ * Class Metadata represents a list of entity fields that are applicable for persistence operations
+ */
+class Metadata extends \Magento\Framework\Model\Resource\Db\VersionControl\Metadata
+{
+    /**
+     * Returns list of entity fields that are applicable for persistence operations
+     *
+     * @param \Magento\Framework\Object $entity
+     * @return array
+     */
+    public function getFields(\Magento\Framework\Object $entity)
+    {
+        $entityClass = get_class($entity);
+        if (!isset($this->metadataInfo[$entityClass])) {
+            $fields = $entity->getResource()->getReadConnection()->describeTable(
+                $entity->getResource()->getEntityTable()
+            );
+
+            $fields = array_merge($fields, $entity->getAttributes());
+
+            $fields = array_fill_keys(
+                array_keys($fields),
+                null
+            );
+
+            $this->metadataInfo[$entityClass] = $fields;
+        }
+
+        return $this->metadataInfo[$entityClass];
+    }
+}
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
similarity index 99%
rename from app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php
rename to app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
index 3034b99b8714fa00a525568147f29c554be3db85..cce1b9d07a087bc140f09acb27b5c43b86570c0e 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
@@ -7,7 +7,7 @@ namespace Magento\Eav\Test\Unit\Model\Entity;
 
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
-class AbstractTest extends \PHPUnit_Framework_TestCase
+class AbstractEntityTest extends \PHPUnit_Framework_TestCase
 {
     /**
      * Entity model to be tested
@@ -115,7 +115,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase
      *
      * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\Pdo\Mysql
      */
-    private function _getAdapterMock()
+    protected function _getAdapterMock()
     {
         $adapter = $this->getMock(
             'Magento\Framework\DB\Adapter\Pdo\Mysql',
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php
index cd7b8d2bc528bc197164bbecd83e58920dfe76b8..4d89903528b32dafe7beebaf68028b6f62eb848a 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php
@@ -5,10 +5,17 @@
  */
 namespace Magento\Eav\Test\Unit\Model\Entity\Collection;
 
+use Magento\Eav\Test\Unit\Model\Entity\Collection\AbstractCollectionStub;
+
+/**
+ * AbstractCollection test
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Eav\Test\Unit\Model\Entity\Collection\AbstractCollectionStub|\PHPUnit_Framework_MockObject_MockObject
+     * @var AbstractCollectionStub|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $model;
 
@@ -57,6 +64,11 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorFactoryMock;
 
+    /**
+     * @var \Magento\Framework\DB\Statement\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $statementMock;
+
     public function setUp()
     {
         $this->coreEntityFactoryMock = $this->getMock(
@@ -100,6 +112,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
         $this->entityFactoryMock = $this->getMock('Magento\Eav\Model\EntityFactory', [], [], '', false);
         /** @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject */
         $connectionMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false);
+        $this->statementMock = $this->getMock('Magento\Framework\DB\Statement\Pdo\Mysql', ['fetch'], [], '', false);
         /** @var $selectMock \Zend_Db_Select|\PHPUnit_Framework_MockObject_MockObject */
         $selectMock = $this->getMock('Zend_Db_Select', [], [], '', false);
         $this->coreEntityFactoryMock->expects(
@@ -110,6 +123,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
             $this->returnCallback([$this, 'getMagentoObject'])
         );
         $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock));
+        $connectionMock->expects($this->any())->method('query')->willReturn($this->statementMock);
 
         $this->coreResourceMock->expects(
             $this->any()
@@ -119,11 +133,11 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
             $this->returnValue($connectionMock)
         );
         $entityMock = $this->getMock('Magento\Eav\Model\Entity\AbstractEntity', [], [], '', false);
-        $entityMock->expects($this->once())->method('getReadConnection')->will($this->returnValue($connectionMock));
-        $entityMock->expects($this->once())->method('getDefaultAttributes')->will($this->returnValue([]));
+        $entityMock->expects($this->any())->method('getReadConnection')->will($this->returnValue($connectionMock));
+        $entityMock->expects($this->any())->method('getDefaultAttributes')->will($this->returnValue([]));
 
         $this->validatorFactoryMock->expects(
-            $this->once()
+            $this->any()
         )->method(
             'create'
         )->with(
@@ -132,7 +146,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
             $this->returnValue($entityMock)
         );
 
-        $this->model = new \Magento\Eav\Test\Unit\Model\Entity\Collection\AbstractCollectionStub(
+        $this->model = new AbstractCollectionStub(
             $this->coreEntityFactoryMock,
             $this->loggerMock,
             $this->fetchStrategyMock,
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionStub.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionStub.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab2aa4dacd95e3f15d879205d09bf31dbd52bf9d
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionStub.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Test\Unit\Model\Entity\Collection\VersionControl;
+
+/**
+ * Stub for version control abstract collection model.
+ */
+class AbstractCollectionStub extends \Magento\Eav\Model\Entity\Collection\VersionControl\AbstractCollection
+{
+    /**
+     * Retrieve item by id
+     *
+     * @param   mixed $id
+     * @return  \Magento\Framework\Object
+     */
+    public function getItemById($id)
+    {
+        if (isset($this->_itemsById[$id])) {
+            return $this->_itemsById[$id];
+        }
+        return null;
+    }
+
+    /**
+     * Initialize collection
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        return $this->_init('Magento\Framework\Object', 'test_entity_model');
+    }
+}
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3c890c71a1c0aed698a56ce0ff652c23a9f5c2f
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/VersionControl/AbstractCollectionTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Test\Unit\Model\Entity\Collection\VersionControl;
+
+use Magento\Eav\Test\Unit\Model\Entity\Collection\VersionControl\AbstractCollectionStub;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+/**
+ * Test for version control abstract collection model.
+ */
+class AbstractCollectionTest extends \Magento\Eav\Test\Unit\Model\Entity\Collection\AbstractCollectionTest
+{
+    /**
+     * Subject of testing.
+     *
+     * @var AbstractCollectionStub|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $subject;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entitySnapshot;
+
+    public function setUp()
+    {
+        parent::setUp();
+
+        $objectManager = new ObjectManager($this);
+
+        $this->entitySnapshot = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            ['registerSnapshot'],
+            [],
+            '',
+            false
+        );
+
+        $this->subject = $objectManager->getObject(
+            'Magento\Eav\Test\Unit\Model\Entity\Collection\VersionControl\AbstractCollectionStub',
+            [
+                'entityFactory' => $this->coreEntityFactoryMock,
+                'universalFactory' => $this->validatorFactoryMock,
+                'entitySnapshot' => $this->entitySnapshot
+            ]
+        );
+    }
+
+    /**
+     * @param array $data
+     * @dataProvider fetchItemDataProvider
+     */
+    public function testFetchItem(array $data)
+    {
+        $item = $this->getMagentoObject()->setData($data);
+
+        $this->statementMock->expects($this->once())
+            ->method('fetch')
+            ->willReturn($data);
+
+        if (!$data) {
+            $this->entitySnapshot->expects($this->never())->method('registerSnapshot');
+
+            $this->assertEquals(false, $this->subject->fetchItem());
+        } else {
+            $this->entitySnapshot->expects($this->once())->method('registerSnapshot')->with($item);
+
+            $this->assertEquals($item, $this->subject->fetchItem());
+        }
+    }
+
+    public static function fetchItemDataProvider()
+    {
+        return [
+            [[]],
+            [['attribute' => 'test']]
+        ];
+    }
+}
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/AbstractEntityTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/AbstractEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9c1865c483f8f3e048b6e7815fe919fdbed82ad9
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/AbstractEntityTest.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Test\Unit\Model\Entity\VersionControl;
+
+use Magento\Eav\Model\Entity\VersionControl\AbstractEntity;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+/**
+ * Test for version control abstract entity model.
+ */
+class AbstractEntityTest extends \Magento\Eav\Test\Unit\Model\Entity\AbstractEntityTest
+{
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entitySnapshot;
+
+    /**
+     * @var RelationComposite|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entityRelationComposite;
+
+    protected function setUp()
+    {
+        $this->entitySnapshot = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            ['isModified', 'registerSnapshot'],
+            [],
+            '',
+            false
+        );
+
+        $this->entityRelationComposite = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite',
+            ['processRelations'],
+            [],
+            '',
+            false
+        );
+
+        parent::setUp();
+    }
+
+    /**
+     * @param string $attributeCode
+     * @param int $attributeSetId
+     * @param array $productData
+     * @param array $productOrigData
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     * @dataProvider productAttributesDataProvider
+     */
+    public function testSave($attributeCode, $attributeSetId, $productData, $productOrigData)
+    {
+        $object = $this->getMock(
+            'Magento\Catalog\Model\Product',
+            ['getOrigData', '__wakeup', 'beforeSave', 'afterSave', 'validateBeforeSave'],
+            [],
+            '',
+            false
+        );
+
+        $object->setEntityTypeId(1);
+        foreach ($productData as $key => $value) {
+            $object->setData($key, $value);
+        }
+        $object->expects($this->any())->method('getOrigData')->will($this->returnValue($productOrigData));
+
+        $entityType = new \Magento\Framework\Object();
+        $entityType->setEntityTypeCode('test');
+        $entityType->setEntityTypeId(0);
+        $entityType->setEntityTable('table');
+
+        $attributes = $this->_getAttributes();
+
+        $attribute = $this->_getAttributeMock($attributeCode, $attributeSetId);
+
+        /** @var $backendModel \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend */
+        $backendModel = $this->getMock(
+            'Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend',
+            [
+                'getBackend',
+                'getBackendTable',
+                'getAffectedFields',
+                'isStatic',
+                'getEntityValueId',
+                'getEntityIdField'
+            ]
+        );
+
+        $backendModel->expects(
+            $this->once()
+        )->method(
+            'getAffectedFields'
+        )->will(
+            $this->returnValue(['test_table' => [['value_id' => 0, 'attribute_id' => $attributeCode]]])
+        );
+
+        $backendModel->expects($this->any())->method('isStatic')->will($this->returnValue(false));
+        $backendModel->expects($this->never())->method('getEntityValueId');
+        $backendModel->expects(
+            isset($productData['entity_id']) ? $this->never() : $this->once()
+        )->method(
+            'getEntityIdField'
+        )->will(
+            $this->returnValue('entity_id')
+        );
+
+        $backendModel->setAttribute($attribute);
+
+        $attribute->expects($this->any())->method('getBackend')->will($this->returnValue($backendModel));
+        $attribute->setId(222);
+        $attributes[$attributeCode] = $attribute;
+        $eavConfig = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new ObjectManager($this);
+
+        $this->entitySnapshot->expects($this->once())->method('isModified')->willReturn(true);
+        $this->entitySnapshot->expects($this->once())->method('registerSnapshot')->with($object);
+
+        $this->entityRelationComposite->expects($this->once())->method('processRelations')->with($object);
+
+        $arguments =  $objectManager->getConstructArguments(
+            'Magento\Eav\Model\Entity\VersionControl\AbstractEntity',
+            [
+                'eavConfig' => $eavConfig,
+                'entitySnapshot' => $this->entitySnapshot,
+                'entityRelationComposite' => $this->entityRelationComposite,
+                'data' => [
+                    'type' => $entityType,
+                    'entityTable' => 'entityTable',
+                    'attributesByCode' => $attributes
+                ]
+            ]
+        );
+
+        /** @var $model AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */
+        $model = $this->getMockBuilder('Magento\Eav\Model\Entity\VersionControl\AbstractEntity')
+            ->setConstructorArgs($arguments)
+            ->setMethods(['_getValue', 'beginTransaction', 'commit', 'rollback'])
+            ->getMock();
+
+        $model->expects($this->any())->method('_getValue')->will($this->returnValue($eavConfig));
+
+        $eavConfig->expects($this->any())->method('getAttribute')->will(
+            $this->returnCallback(
+                function ($entityType, $attributeCode) use ($attributes) {
+                    return $entityType && isset($attributes[$attributeCode]) ? $attributes[$attributeCode] : null;
+                }
+            )
+        );
+
+        $model->setConnection($this->_getAdapterMock());
+        $model->isPartialSave(true);
+        $model->save($object);
+    }
+
+    public function testSaveNotModified()
+    {
+        $objectManager = new ObjectManager($this);
+
+        /** @var $object \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */
+        $object = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+
+        $arguments = $objectManager->getConstructArguments(
+            'Magento\Eav\Model\Entity\VersionControl\AbstractEntity',
+            [
+                'entitySnapshot' => $this->entitySnapshot,
+                'entityRelationComposite' => $this->entityRelationComposite,
+            ]
+        );
+
+        /** @var $model AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */
+        $model = $this->getMockBuilder('Magento\Eav\Model\Entity\VersionControl\AbstractEntity')
+            ->setConstructorArgs($arguments)
+            ->setMethods(['beginTransaction', 'commit'])
+            ->getMock();
+
+        $this->entitySnapshot->expects($this->once())->method('isModified')->willReturn(false);
+        $this->entitySnapshot->expects($this->never())->method('registerSnapshot');
+
+        $this->entityRelationComposite->expects($this->once())->method('processRelations')->with($object);
+
+        $model->save($object);
+    }
+}
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/MetadataTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/MetadataTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..77e00daf49c9b623a851c86b7fbf5679d8e39faf
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/VersionControl/MetadataTest.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Test\Unit\Model\Entity\VersionControl;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+/**
+ * Test for version control metadata model.
+ */
+class MetadataTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Eav\Model\Entity\VersionControl\Metadata
+     */
+    protected $metadata;
+
+    /**
+     * @var \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resource;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $connection;
+
+    protected function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+
+        $this->model = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ['getResource', 'getAttributes'],
+            [],
+            '',
+            false
+        );
+
+        $this->resource = $this->getMockForAbstractClass(
+            'Magento\Framework\DB\Adapter\AdapterInterface',
+            [],
+            '',
+            false,
+            false,
+            true,
+            ['getReadConnection', 'getEntityTable']
+        );
+
+        $this->connection = $this->getMockForAbstractClass(
+            'Magento\Framework\DB\Adapter\AdapterInterface',
+            [],
+            '',
+            false,
+            false
+        );
+
+        $this->model->expects($this->any())->method('getResource')->willReturn($this->resource);
+
+        $this->resource->expects($this->any())->method('getReadConnection')->willReturn($this->connection);
+
+        $this->metadata = $objectManager->getObject(
+            'Magento\Eav\Model\Entity\VersionControl\Metadata'
+        );
+    }
+
+    public function testGetFields()
+    {
+        $entityTable = 'entity_table';
+
+        $expectedDescribedTable = ['field1' => null, 'field2' => null];
+        $expectedAttributes = ['attribute1' => 'value1', 'attribute2' => 'value2'];
+
+        $expectedResults = array_merge($expectedDescribedTable, $expectedAttributes);
+
+        $this->resource->expects($this->any())->method('getEntityTable')->willReturn($entityTable);
+
+        $this->connection->expects($this->once())->method('describeTable')->with($entityTable)->willReturn(
+            $expectedDescribedTable
+        );
+
+        $this->model->expects($this->any())->method('getAttributes')->willReturn($expectedAttributes);
+        //check that fields load with null initial value
+        $this->assertEquals(
+            array_fill_keys(array_keys($expectedResults), null),
+            $this->metadata->getFields($this->model)
+        );
+
+        // Testing loading data from cache.
+        $this->connection->expects($this->never())->method('describeTable');
+
+        $this->assertEquals(
+            array_fill_keys(array_keys($expectedResults), null),
+            $this->metadata->getFields($this->model)
+        );
+    }
+}
diff --git a/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..541e46a36a627814c6989c5c8d237e7d1e83aaf5
--- /dev/null
+++ b/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="step-config" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="shipping-rates-validation" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="fedex-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Fedex/js/view/shipping-rates-validation</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557
--- /dev/null
+++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'postcode': {
+                        'required': true
+                    },
+                    'country_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1
--- /dev/null
+++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        './shipping-rates-validation-rules',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc9bc66b93e5ee503719ef80794bf1fb91a9acfe
--- /dev/null
+++ b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../model/shipping-rates-validator',
+        '../model/shipping-rates-validation-rules'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        fedexShippingRatesValidator,
+        fedexShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('fedex', fedexShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('fedex', fedexShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js
index 4896aeb00b5b87c57ad90cdcc86c26e68da0b794..51e72540458efd1cd3a3f8fe564f148e9357a0b7 100644
--- a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js
+++ b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js
@@ -7,10 +7,10 @@ define(
     [
         '../model/url-builder',
         'mage/storage',
-        'Magento_Ui/js/model/errorlist',
+        'Magento_Ui/js/model/messageList',
         'mage/url'
     ],
-    function(urlBuilder, storage, errorList, url) {
+    function(urlBuilder, storage, messageList, url) {
         "use strict";
         return function(giftMessage, remove) {
             url.setBaseUrl(giftMessage.getConfigValue('baseUrl'));
@@ -30,7 +30,7 @@ define(
                     );
                 }
             }
-            errorList.clear();
+            messageList.clear();
 
             storage.post(
                 serviceUrl,
@@ -49,7 +49,7 @@ define(
             ).fail(
                 function(response) {
                     var error = JSON.parse(response.responseText);
-                    errorList.add(error);
+                    messageList.addErrorMessage(error);
                 }
             );
         };
diff --git a/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml
index c6140255ab7f1141c453b557d25a282a92abc897..8e1eb709250e00164ef7c62f3dc6468334b0ef73 100644
--- a/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml
@@ -15,30 +15,34 @@
                             <item name="children" xsi:type="array">
                                 <item name="steps" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="payment" xsi:type="array">
+                                        <item name="billing-step" xsi:type="array">
+                                            <item name="component" xsi:type="string">uiComponent</item>
+                                            <item name="sortOrder" xsi:type="string">2</item>
                                             <item name="children" xsi:type="array">
-                                                <item name="checkmo" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/checkmo-method</item>
-                                                    <item name="config" xsi:type="array">
-                                                        <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/checkmo-form</item>
-                                                    </item>
-                                                </item>
-                                                <item name="cashondelivery" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/instructions-method</item>
-                                                    <item name="config" xsi:type="array">
-                                                        <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/instructions-form</item>
-                                                    </item>
-                                                </item>
-                                                <item name="banktransfer" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/instructions-method</item>
-                                                    <item name="config" xsi:type="array">
-                                                        <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/instructions-form</item>
-                                                    </item>
-                                                </item>
-                                                <item name="purchaseorder" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/purchaseorder-method</item>
-                                                    <item name="config" xsi:type="array">
-                                                        <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/purchaseorder-form</item>
+                                                <item name="payment" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="renders" xsi:type="array">
+                                                            <!-- merge payment method renders here -->
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="offline-payments" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/offline-payments</item>
+                                                                    <item name="methods" xsi:type="array">
+                                                                        <item name="checkmo" xsi:type="array">
+                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
+                                                                        </item>
+                                                                        <item name="banktransfer" xsi:type="array">
+                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
+                                                                        </item>
+                                                                        <item name="cashondelivery" xsi:type="array">
+                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
+                                                                        </item>
+                                                                        <item name="purchaseorder" xsi:type="array">
+                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
                                                     </item>
                                                 </item>
                                             </item>
@@ -52,4 +56,4 @@
             </arguments>
         </referenceBlock>
     </body>
-</page>
+</page>
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js
deleted file mode 100644
index 5093e525aaea7e12e2e138f33884d33217120b54..0000000000000000000000000000000000000000
--- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'Magento_Checkout/js/view/payment/method-info',
-        'mage/translate'
-    ],
-    function (methodInfo, $t) {
-        return methodInfo.extend({
-            getMailingAddress: function() {
-                return window.checkoutConfig.payment.checkmo.mailingAddress;
-            },
-            getPayableTo: function() {
-                return window.checkoutConfig.payment.checkmo.payableTo;
-            },
-            getInfo: function() {
-                var info = [];
-                if (this.getPayableTo()) {
-                    info.push({name: $t('Make Check payable to')});
-                    info.push({value: this.getPayableTo()});
-                }
-                if (this.getMailingAddress()) {
-                    info.push({name: $t('Send Check to')});
-                    info.push({html: this.getMailingAddress()});
-                }
-                return info;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js
deleted file mode 100644
index a3d9e9cdbae67265888a71dfe8aaae79fdbf778c..0000000000000000000000000000000000000000
--- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'Magento_Checkout/js/view/payment/method-info'
-    ],
-    function (methodInfo) {
-        return methodInfo.extend({
-            getInstructions: function() {
-                return window.checkoutConfig.payment.instructions[this.getCode()];
-            },
-            getInfo: function() {
-                var info = [];
-                if (this.getInstructions()) {
-                    info.push({html: this.getInstructions()});
-                }
-                return info;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js
new file mode 100644
index 0000000000000000000000000000000000000000..e139bbf2fa4b1d5148317167bc8d4a1ae2392bc9
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'ko',
+        'Magento_Checkout/js/view/payment/default'
+    ],
+    function (ko, Component) {
+        'use strict';
+
+        return Component.extend({
+            defaults: {
+                template: 'Magento_OfflinePayments/payment/banktransfer'
+            },
+            /**
+             * Get value of instruction field.
+             * @returns {String}
+             */
+            getInstructions: function () {
+                return window.checkoutConfig.payment.instructions[this.item.method];
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js
new file mode 100644
index 0000000000000000000000000000000000000000..9dea96883c3235d087e106bc20b728f9fc8315da
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js
@@ -0,0 +1,24 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/payment/default'
+    ],
+    function (Component) {
+        'use strict';
+        return Component.extend({
+            defaults: {
+                template: 'Magento_OfflinePayments/payment/cashondelivery'
+            },
+
+            /** Returns payment method instructions */
+            getInstructions: function() {
+                return window.checkoutConfig.payment.instructions[this.item.method];
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js
new file mode 100644
index 0000000000000000000000000000000000000000..6eb00662593f1e0a2213af36b50fc6ca29f271c7
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/payment/default'
+    ],
+    function (Component) {
+        'use strict';
+
+        return Component.extend({
+            defaults: {
+                template: 'Magento_OfflinePayments/payment/checkmo'
+            },
+
+            /** Returns send check to info */
+            getMailingAddress: function() {
+                return window.checkoutConfig.payment.checkmo.mailingAddress;
+            },
+
+            /** Returns payable to info */
+            getPayableTo: function() {
+                return window.checkoutConfig.payment.checkmo.payableTo;
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js
new file mode 100644
index 0000000000000000000000000000000000000000..a5d09084f5cb8c5fefdb256cfdf94079f2b9e9e6
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js
@@ -0,0 +1,44 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/payment/default',
+        'jquery',
+        "mage/validation"
+    ],
+    function (Component, $) {
+        'use strict';
+        return Component.extend({
+            defaults: {
+                template: 'Magento_OfflinePayments/payment/purchaseorder-form',
+                purchaseOrderNumber: ''
+            },
+            initObservable: function () {
+                this._super()
+                    .observe('purchaseOrderNumber');
+                return this;
+            },
+            getData: function () {
+                return {
+                    "method": this.item.method,
+                    'po_number': this.purchaseOrderNumber(),
+                    "cc_owner": null,
+                    "cc_number": null,
+                    "cc_type": null,
+                    "cc_exp_year": null,
+                    "cc_exp_month": null,
+                    "additional_data": null
+                };
+
+            },
+            validate: function () {
+                var form = '#purchaseorder';
+                return $(form).validation() && $(form).validation('isValid');
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js
new file mode 100644
index 0000000000000000000000000000000000000000..809df962245fb2c225f117b2866c6b3d4c70a5bd
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js
@@ -0,0 +1,38 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/payment/renderer-list'
+    ],
+    function (
+        Component,
+        rendererList
+    ) {
+        'use strict';
+        rendererList.push(
+            {
+                type: 'checkmo',
+                component: 'Magento_OfflinePayments/js/view/payment/method-renderer/checkmo-method'
+            },
+            {
+                type: 'banktransfer',
+                component: 'Magento_OfflinePayments/js/view/payment/method-renderer/banktransfer-method'
+            },
+            {
+                type: 'cashondelivery',
+                component: 'Magento_OfflinePayments/js/view/payment/method-renderer/cashondelivery-method'
+            },
+            {
+                type: 'purchaseorder',
+                component: 'Magento_OfflinePayments/js/view/payment/method-renderer/purchaseorder-method'
+            }
+        );
+        /** Add view logic here if needed */
+        return Component.extend({});
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js
deleted file mode 100644
index 1233199cc2d862f2048fb7bcf1f0f05e72502a2a..0000000000000000000000000000000000000000
--- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'jquery',
-        "mage/translate",
-        'Magento_Checkout/js/view/payment/method-info'
-    ],
-    function ($, $t, methodInfo) {
-        return methodInfo.extend({
-            defaults: {
-                purchaseOrderNumber: ''
-            },
-            initObservable: function () {
-                this._super()
-                    .observe('purchaseOrderNumber');
-                return this;
-            },
-            getData: function() {
-                return {'po_number': this.purchaseOrderNumber()};
-            },
-            getInfo: function() {
-                return [
-                    {'name': 'Purchase Order Number', value: this.purchaseOrderNumber()}
-                ];
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html
new file mode 100644
index 0000000000000000000000000000000000000000..dfcbf3131970749bfec9ab0537c3ef12f689fae7
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html
@@ -0,0 +1,40 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
+    <div class="payment-method-title field choice">
+        <input type="radio"
+               name="payment[method]"
+               class="radio"
+               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()" />
+        <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
+    </div>
+
+    <div class="payment-method-content">
+        <div class="payment-method-billing-address">
+            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <p data-bind="text: getInstructions()"></p>
+        <div class="checkout-agreements-block">
+            <!-- ko foreach: $parent.getRegion('before-place-order') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <div class="actions-toolbar">
+            <div class="primary">
+                <button class="action primary checkout"
+                        type="submit"
+                        data-bind="click: placeOrder, attr: {'title': $t('Place Order')}, enable: (getCode() == isChecked())"
+                        disabled>
+                    <span data-bind="text: $t('Place Order')"></span>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
+        
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html
new file mode 100644
index 0000000000000000000000000000000000000000..569d5b0a48eb368622fee51306a8d9c30b075cf7
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html
@@ -0,0 +1,41 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
+    <div class="payment-method-title field choice">
+        <input type="radio"
+               name="payment[method]"
+               class="radio"
+               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
+        <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
+    </div>
+
+    <div class="payment-method-content">
+        <div class="payment-method-billing-address">
+            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <p data-bind="text: getInstructions()"></p>
+        <div class="checkout-agreements-block">
+            <!-- ko foreach: $parent.getRegion('before-place-order') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <div class="actions-toolbar">
+            <div class="primary">
+                <button class="action primary checkout"
+                        type="submit"
+                        data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())"
+                        disabled>
+                    <span data-bind="text: $t('Place Order')"></span>
+                </button>
+            </div>
+        </div>
+
+    </div>
+</div>
+        
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html
deleted file mode 100644
index 92c84f0662ddda6acf0fdff41ed3233ff69fe447..0000000000000000000000000000000000000000
--- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: getMailingAddress() || getPayableTo() -->
-<dl class="items check payable" id="payment_form_<?php echo $block->getMethodCode() ?>">
-    <!-- ko if: getPayableTo() -->
-    <dt class="title"><!-- ko text: $t('Make Check payable to:') --><!-- /ko --></dt>
-    <dd class="content"><!-- ko text: $t(getPayableTo()) --><!-- /ko --></dd>
-    <!-- /ko -->
-    <!-- ko if: getMailingAddress() -->
-    <dt class="title"><!-- ko text: $t('Send Check to:') --><!-- /ko --></dt>
-    <dd class="content">
-        <address class="checkmo mailing address" data-bind="html: $t(getMailingAddress())"></address>
-    </dd>
-    <!-- /ko -->
-</dl>
-<!-- /ko -->
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html
new file mode 100644
index 0000000000000000000000000000000000000000..58f85845434792ab778b177461ac493a743d649d
--- /dev/null
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html
@@ -0,0 +1,52 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
+    <div class="payment-method-title field choice">
+        <input type="radio"
+               name="payment[method]"
+               class="radio"
+               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
+        <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
+    </div>
+    <div class="payment-method-content">
+        <div class="payment-method-billing-address">
+            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <!-- ko if: getMailingAddress() || getPayableTo() -->
+        <dl class="items check payable">
+            <!-- ko if: getPayableTo() -->
+            <dt class="title"><!-- ko text: $t('Make Check payable to:') --><!-- /ko --></dt>
+            <dd class="content"><!-- ko text: $t(getPayableTo()) --><!-- /ko --></dd>
+            <!-- /ko -->
+            <!-- ko if: getMailingAddress() -->
+            <dt class="title"><!-- ko text: $t('Send Check to:') --><!-- /ko --></dt>
+            <dd class="content">
+                <address class="checkmo mailing address" data-bind="html: $t(getMailingAddress())"></address>
+            </dd>
+            <!-- /ko -->
+        </dl>
+        <!-- /ko -->
+        <div class="checkout-agreements-block">
+            <!-- ko foreach: $parent.getRegion('before-place-order') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <div class="actions-toolbar">
+            <div class="primary">
+                <button class="action primary checkout"
+                        type="submit"
+                        data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())"
+                        disabled>
+                    <span data-bind="text: $t('Place Order')"></span>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
+        
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html
deleted file mode 100644
index 56f30d9cc42c14d7997f02c5c51b0dd22624fb21..0000000000000000000000000000000000000000
--- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: getInstructions() -->
-<div data-bind="attr: {class: 'items ' + getCode() + ' instructions agreement content', id: 'payment_form_' + getCode()}, html: $t(getInstructions())"></div>
-<!-- /ko -->
\ No newline at end of file
diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html
index 828045b5b7321a6893dc0493cb48d2e5ea14341e..585d61feae7d7c7423285c3db12f5351adc2d385 100644
--- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html
+++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html
@@ -4,19 +4,59 @@
  * See COPYING.txt for license details.
  */
 -->
-<fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'>
-    <div class="field field-number required">
-        <label for="po_number" class="label"><span><!-- ko text: $t('Purchase Order Number')--><!-- /ko --></span></label>
-        <div class="control">
-            <input type="text"
-                   id="po_number"
-                   name="payment[po_number]"
-                   data-validate="{required:true}"
-                   data-bind='
-                        attr: {title: $t("Purchase Order Number")},
-                        value: purchaseOrderNumber,
-                        enable: isActive($parent)'
-                   class="input-text"/>
+<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
+    <form id="purchaseorder-form" class="form form-purchase-order">
+
+        <div class="payment-method-title field choice">
+            <input type="radio"
+                   name="payment[method]"
+                   class="radio"
+                   data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
+            <label data-bind="attr: {'for': getCode()}" class="label">
+                <span data-bind="text: getTitle()"></span>
+            </label>
         </div>
-    </div>
-</fieldset>
\ No newline at end of file
+
+        <div class="payment-method-content">
+            <div class="payment-method-billing-address">
+                <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+                <!--/ko-->
+            </div>
+
+            <fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'>
+                <div class="field field-number required">
+                    <label for="po_number" class="label">
+                        <span><!-- ko text: $t('Purchase Order Number')--><!-- /ko --></span>
+                    </label>
+                    <div class="control">
+                        <input type="text"
+                               id="po_number"
+                               name="payment[po_number]"
+                               data-validate="{required:true}"
+                               data-bind='
+                                attr: {title: $t("Purchase Order Number")},
+                                value: purchaseOrderNumber'
+                               class="input-text"/>
+                    </div>
+                </div>
+                <div class="checkout-agreements-block">
+                    <!-- ko foreach: $parent.getRegion('before-place-order') -->
+                        <!-- ko template: getTemplate() --><!-- /ko -->
+                    <!--/ko-->
+                </div>
+                <div class="actions-toolbar" id="review-buttons-container">
+                    <div class="primary">
+                        <button class="action primary checkout"
+                                type="submit"
+                                data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())"
+                                data-role="review-save">
+                            <span data-bind="text: $t('Place Order')"></span>
+                        </button>
+                    </div>
+                </div>
+            </fieldset>
+        </div>
+    </form>
+</div>
+        
\ No newline at end of file
diff --git a/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f97709a21bd0aa5313a6bdc0f44ef0167205a1e1
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="step-config" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="shipping-rates-validation" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="freeshipping-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/freeshipping</item>
+                                                                </item>
+                                                                <item name="flatrate-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/flatrate</item>
+                                                                </item>
+                                                                <item name="tablerate-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/tablerate</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js
new file mode 100644
index 0000000000000000000000000000000000000000..f45450e5359e06c86e85badb235aa193797c3a48
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'country_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..f45450e5359e06c86e85badb235aa193797c3a48
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'country_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js
new file mode 100644
index 0000000000000000000000000000000000000000..174ca5d9b9506d9c7ea4d39d45b4bf1502ba6104
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'postcode': {
+                        'required': true
+                    },
+                    'country_id': {
+                        'required': true
+                    },
+                    'region_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js
new file mode 100644
index 0000000000000000000000000000000000000000..39faae263931600a6eec596c1e127ce6098b595d
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        '../shipping-rates-validation-rules/flatrate',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..d3e970cc8f7676a446ab94bc1c727cc7ad7a11cf
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        '../shipping-rates-validation-rules/freeshipping',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js
new file mode 100644
index 0000000000000000000000000000000000000000..3a04b4cf03756da06de7a377ef65df08fe8599de
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        '../shipping-rates-validation-rules/tablerate',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7cd3490469ad1b1c18a30fb1873ee7b2d9b9e2b
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../../model/shipping-rates-validator/flatrate',
+        '../../model/shipping-rates-validation-rules/flatrate'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        flatrateShippingRatesValidator,
+        flatrateShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('flatrate', flatrateShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('flatrate', flatrateShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..a58024dcff35edb777ec6f6da89a3707364ae75f
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../../model/shipping-rates-validator/freeshipping',
+        '../../model/shipping-rates-validation-rules/freeshipping'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        freeshippingShippingRatesValidator,
+        freeshippingShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('freeshipping', freeshippingShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('freeshipping', freeshippingShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f9754eedd202d1a8fb6c766d44de4e91f66bdd3
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../../model/shipping-rates-validator/tablerate',
+        '../../model/shipping-rates-validation-rules/tablerate'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        tablerateShippingRatesValidator,
+        tablerateShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('tablerate', tablerateShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('tablerate', tablerateShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/PageCache/Model/Observer/ProcessLayoutRenderElement.php b/app/code/Magento/PageCache/Model/Observer/ProcessLayoutRenderElement.php
index c95ad9995ef88ff4943fb0dbd5e0c3673776857b..ea4d21869bda7c09e933ded3f741ff297808f0d2 100644
--- a/app/code/Magento/PageCache/Model/Observer/ProcessLayoutRenderElement.php
+++ b/app/code/Magento/PageCache/Model/Observer/ProcessLayoutRenderElement.php
@@ -16,6 +16,22 @@ class ProcessLayoutRenderElement
     protected $_config;
 
     /**
+     * Is varnish enabled flag
+     *
+     * @var bool
+     */
+    protected $isVarnishEnabled;
+
+    /**
+     * Is full page cache enabled flag
+     *
+     * @var bool
+     */
+    protected $isFullPageCacheEnabled;
+
+    /**
+     * Class constructor
+     *
      * @param \Magento\PageCache\Model\Config $config
      */
     public function __construct(\Magento\PageCache\Model\Config $config)
@@ -44,6 +60,32 @@ class ProcessLayoutRenderElement
         return sprintf('<esi:include src="%s" />', $url);
     }
 
+    /**
+     * Is full page cache enabled
+     *
+     * @return bool
+     */
+    protected function isFullPageCacheEnabled()
+    {
+        if ($this->isFullPageCacheEnabled === null) {
+            $this->isFullPageCacheEnabled = $this->_config->isEnabled();
+        }
+        return $this->isFullPageCacheEnabled;
+    }
+
+    /**
+     * Is varnish cache engine enabled
+     *
+     * @return bool
+     */
+    protected function isVarnishEnabled()
+    {
+        if ($this->isVarnishEnabled === null) {
+            $this->isVarnishEnabled = ($this->_config->getType() == \Magento\PageCache\Model\Config::VARNISH);
+        }
+        return $this->isVarnishEnabled;
+    }
+
     /**
      * Add comment cache containers to private blocks
      * Blocks are wrapped only if page is cacheable
@@ -56,15 +98,15 @@ class ProcessLayoutRenderElement
         $event = $observer->getEvent();
         /** @var \Magento\Framework\View\Layout $layout */
         $layout = $event->getLayout();
-        if ($layout->isCacheable() && $this->_config->isEnabled()) {
+        if ($this->isFullPageCacheEnabled() && $layout->isCacheable()) {
             $name = $event->getElementName();
+            /** @var \Magento\Framework\View\Element\AbstractBlock $block */
             $block = $layout->getBlock($name);
             $transport = $event->getTransport();
             if ($block instanceof \Magento\Framework\View\Element\AbstractBlock) {
                 $blockTtl = $block->getTtl();
-                $varnishIsEnabledFlag = ($this->_config->getType() == \Magento\PageCache\Model\Config::VARNISH);
                 $output = $transport->getData('output');
-                if ($varnishIsEnabledFlag && isset($blockTtl)) {
+                if (isset($blockTtl) && $this->isVarnishEnabled()) {
                     $output = $this->_wrapEsi($block, $layout);
                 } elseif ($block->isScopePrivate()) {
                     $output = sprintf(
diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Observer/ProcessLayoutRenderElementTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Observer/ProcessLayoutRenderElementTest.php
index 370edc3a369e53f2f49de43de5e26a367fb3bd7c..1601b85f477494d942138fae8a8cbbcf8cc35c54 100644
--- a/app/code/Magento/PageCache/Test/Unit/Model/Observer/ProcessLayoutRenderElementTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Model/Observer/ProcessLayoutRenderElementTest.php
@@ -99,19 +99,29 @@ class ProcessLayoutRenderElementTest extends \PHPUnit_Framework_TestCase
         $this->_configMock->expects($this->any())->method('isEnabled')->will($this->returnValue($cacheState));
 
         if ($cacheState) {
-            $eventMock->expects($this->once())->method('getElementName')->will($this->returnValue('blockName'));
-            $eventMock->expects($this->once())->method('getTransport')->will($this->returnValue($this->_transport));
-            $this->_layoutMock->expects($this->once())->method('isCacheable')->will($this->returnValue(true));
-
-            $this->_layoutMock->expects($this->any())->method('getUpdate')->will($this->returnSelf());
-            $this->_layoutMock->expects($this->any())->method('getHandles')->will($this->returnValue([]));
-            $this->_layoutMock->expects(
-                $this->once()
-            )->method(
-                    'getBlock'
-                )->will(
-                    $this->returnValue($this->_blockMock)
-                );
+            $eventMock->expects($this->once())
+                ->method('getElementName')
+                ->will($this->returnValue('blockName'));
+
+            $eventMock->expects($this->once())
+                ->method('getTransport')
+                ->will($this->returnValue($this->_transport));
+
+            $this->_layoutMock->expects($this->once())
+                ->method('isCacheable')
+                ->will($this->returnValue(true));
+
+            $this->_layoutMock->expects($this->any())
+                ->method('getUpdate')
+                ->will($this->returnSelf());
+
+            $this->_layoutMock->expects($this->any())
+                ->method('getHandles')
+                ->will($this->returnValue([]));
+            
+            $this->_layoutMock->expects($this->once())
+                ->method('getBlock')
+                ->will($this->returnValue($this->_blockMock));
 
             if ($varnishIsEnabled) {
                 $this->_blockMock->expects($this->once())
@@ -123,20 +133,12 @@ class ProcessLayoutRenderElementTest extends \PHPUnit_Framework_TestCase
                     ->will($this->returnValue('page_cache/block/wrapesi/with/handles/and/other/stuff'));
             }
             if ($scopeIsPrivate) {
-                $this->_blockMock->expects(
-                    $this->once()
-                )->method(
-                        'getNameInLayout'
-                    )->will(
-                        $this->returnValue('testBlockName')
-                    );
-                $this->_blockMock->expects(
-                    $this->once()
-                )->method(
-                        'isScopePrivate'
-                    )->will(
-                        $this->returnValue($scopeIsPrivate)
-                    );
+                $this->_blockMock->expects($this->once())
+                    ->method('getNameInLayout')
+                    ->will($this->returnValue('testBlockName'));
+                $this->_blockMock->expects($this->once())
+                    ->method('isScopePrivate')
+                    ->will($this->returnValue($scopeIsPrivate));
             }
             $this->_configMock->expects($this->any())->method('getType')->will($this->returnValue($varnishIsEnabled));
         }
diff --git a/app/code/Magento/Payment/Gateway/Command/CommandException.php b/app/code/Magento/Payment/Gateway/Command/CommandException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c4409fb42e62ff9a8afc3a5356891e3ffd3172b
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/Command/CommandException.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Gateway\Command;
+
+use Magento\Framework\Exception\LocalizedException;
+
+class CommandException extends LocalizedException
+{
+
+}
diff --git a/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php b/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php
index a6044462cded037192b2ca675ba06ce32e89549c..b04491622d4ba58b1a54b257388e38f82ba1515b 100644
--- a/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php
+++ b/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php
@@ -52,8 +52,8 @@ class GatewayCommand implements CommandInterface
         BuilderInterface $requestBuilder,
         TransferFactoryInterface $transferFactory,
         ClientInterface $client,
-        HandlerInterface $handler,
-        ValidatorInterface $validator
+        HandlerInterface $handler = null,
+        ValidatorInterface $validator = null
     ) {
         $this->requestBuilder = $requestBuilder;
         $this->transferFactory = $transferFactory;
@@ -67,6 +67,7 @@ class GatewayCommand implements CommandInterface
      *
      * @param array $commandSubject
      * @return null
+     * @throws \Exception
      */
     public function execute(array $commandSubject)
     {
@@ -76,16 +77,22 @@ class GatewayCommand implements CommandInterface
         );
 
         $response = $this->client->placeRequest($transferO);
-
-        $result = $this->validator->validate(array_merge($commandSubject, ['response' => $response]));
-        if ($result !== null && !$result->isValid()) {
-            $commandSubject['payment']->getPayment()->setIsTransactionPending(true);
-            return;
+        if ($this->validator) {
+            $result = $this->validator->validate(
+                array_merge($commandSubject, ['response' => $response])
+            );
+            if (!$result->isValid()) {
+                throw new CommandException(
+                    __(implode("\n", $result->getFailsDescription()))
+                );
+            }
         }
 
-        $this->handler->handle(
-            $commandSubject,
-            $response
-        );
+        if ($this->handler) {
+            $this->handler->handle(
+                $commandSubject,
+                $response
+            );
+        }
     }
 }
diff --git a/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php b/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php
index 17566610aa29e171681ff4ade6829053e0a49c51..4811a6426816a538f702db7e0b1d9cfea0dd9a7c 100644
--- a/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php
+++ b/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php
@@ -6,6 +6,7 @@
 namespace Magento\Payment\Gateway\Config;
 
 use Magento\Payment\Gateway\ConfigInterface;
+use Magento\Payment\Gateway\Helper\SubjectReader;
 
 class ConfigValueHandler implements ValueHandlerInterface
 {
@@ -26,13 +27,13 @@ class ConfigValueHandler implements ValueHandlerInterface
     /**
      * Retrieve method configured value
      *
-     * @param string $field
+     * @param array $subject
      * @param int|null $storeId
      *
      * @return mixed
      */
-    public function handle($field, $storeId = null)
+    public function handle(array $subject, $storeId = null)
     {
-        return $this->configInterface->getValue($field, $storeId);
+        return $this->configInterface->getValue(SubjectReader::readField($subject), $storeId);
     }
 }
diff --git a/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php b/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php
index 5f857ea3cf539bceec121eb2af09120147774bb3..70e13466bfe30df92d45d4a8c8239819f497b0ea 100644
--- a/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php
+++ b/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php
@@ -10,10 +10,10 @@ interface ValueHandlerInterface
     /**
      * Retrieve method configured value
      *
-     * @param string $field
+     * @param array $subject
      * @param int|null $storeId
      *
      * @return mixed
      */
-    public function handle($field, $storeId = null);
+    public function handle(array $subject, $storeId = null);
 }
diff --git a/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php
index f01bee1d7c77ab2b4c695ea4f00229f165e29132..f9be150d4761af45d4214edc702771444b0e5a08 100644
--- a/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php
+++ b/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php
@@ -106,4 +106,14 @@ class OrderAdapter implements OrderAdapterInterface
     {
         return $this->order->getEntityId();
     }
+
+    /**
+     * Returns order grand total amount
+     *
+     * @return float|null
+     */
+    public function getGrandTotalAmount()
+    {
+        return $this->order->getBaseGrandTotal();
+    }
 }
diff --git a/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php b/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php
index 0d925d823a9906c6d1bedbe4f488338f33493d64..c15bf289b2bfeeb0657912aec5beea99d7e36b33 100644
--- a/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php
+++ b/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php
@@ -55,4 +55,11 @@ interface OrderAdapterInterface
      * @return int
      */
     public function getId();
+
+    /**
+     * Returns order grand total amount
+     *
+     * @return float
+     */
+    public function getGrandTotalAmount();
 }
diff --git a/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php b/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php
index 43a6a9ded86e61c539b5f64dfbbd89de57bc1c94..5e9ab098109729c78375d05cfbff6489e4cb1fb7 100644
--- a/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php
+++ b/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php
@@ -106,4 +106,14 @@ class QuoteAdapter implements OrderAdapterInterface
     {
         return $this->quote->getId();
     }
+
+    /**
+     * Returns order grand total amount
+     *
+     * @return null
+     */
+    public function getGrandTotalAmount()
+    {
+        return null;
+    }
 }
diff --git a/app/code/Magento/Payment/Gateway/Helper/SubjectReader.php b/app/code/Magento/Payment/Gateway/Helper/SubjectReader.php
new file mode 100644
index 0000000000000000000000000000000000000000..bef0a4e463301a4ddda60ce704ea817a85f5488a
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/Helper/SubjectReader.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Gateway\Helper;
+
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
+
+class SubjectReader
+{
+    /**
+     * Reads payment from subject
+     *
+     * @param array $subject
+     * @return PaymentDataObjectInterface
+     */
+    public static function readPayment(array $subject)
+    {
+        if (!isset($subject['payment'])
+            || !$subject['payment'] instanceof PaymentDataObjectInterface
+        ) {
+            throw new \InvalidArgumentException('Payment data object should be provided');
+        }
+
+        return $subject['payment'];
+    }
+
+    /**
+     * Reads amount from subject
+     *
+     * @param array $subject
+     * @return mixed
+     */
+    public static function readAmount(array $subject)
+    {
+        if (!isset($subject['amount']) || !is_numeric($subject['amount'])) {
+            throw new \InvalidArgumentException('Amount should be provided');
+        }
+
+        return $subject['amount'];
+    }
+
+    /**
+     * Reads field from subject
+     *
+     * @param array $subject
+     * @return string
+     */
+    public static function readField(array $subject)
+    {
+        if (!isset($subject['field']) || !is_string($subject['field'])) {
+            throw new \InvalidArgumentException();
+        }
+
+        return $subject['field'];
+    }
+}
diff --git a/app/code/Magento/Payment/Gateway/Http/Client/Soap.php b/app/code/Magento/Payment/Gateway/Http/Client/Soap.php
new file mode 100644
index 0000000000000000000000000000000000000000..80479f0b768b2eb618f71458678a027bb8a663e3
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/Http/Client/Soap.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Gateway\Http\Client;
+
+use Magento\Framework\Webapi\Soap\ClientFactory;
+use Magento\Payment\Gateway\Http\ClientInterface;
+use Magento\Payment\Gateway\Http\ConverterInterface;
+use Magento\Payment\Gateway\Http\TransferInterface;
+use Magento\Payment\Model\Method\Logger;
+
+class Soap implements ClientInterface
+{
+    /**
+     * @var Logger
+     */
+    private $logger;
+
+    /**
+     * @var ConverterInterface | null
+     */
+    private $converter;
+
+    /**
+     * @var ClientFactory
+     */
+    private $clientFactory;
+
+    /**
+     * @param Logger $logger
+     * @param ClientFactory $clientFactory
+     * @param ConverterInterface | null $converter
+     */
+    public function __construct(
+        Logger $logger,
+        ClientFactory $clientFactory,
+        ConverterInterface $converter = null
+    ) {
+        $this->logger = $logger;
+        $this->converter = $converter;
+        $this->clientFactory = $clientFactory;
+    }
+
+    /**
+     * Places request to gateway. Returns result as ENV array
+     *
+     * @param TransferInterface $transferObject
+     * @return array
+     * @throws \Magento\Payment\Gateway\Http\ClientException
+     * @throws \Magento\Payment\Gateway\Http\ConverterException
+     * @throws \Exception
+     */
+    public function placeRequest(TransferInterface $transferObject)
+    {
+        $this->logger->debug(['request' => $transferObject->getBody()]);
+
+        $client = $this->clientFactory->create(
+            $transferObject->getClientConfig()['wsdl'],
+            ['trace' => true]
+        );
+
+        try {
+            $client->__setSoapHeaders($transferObject->getHeaders());
+
+            $response = $client->__soapCall(
+                $transferObject->getMethod(),
+                [$transferObject->getBody()]
+            );
+
+            $result = $this->converter
+                ? $this->converter->convert(
+                    $response
+                )
+                : [$response];
+
+            $this->logger->debug(['response' => $result]);
+        } catch (\Exception $e) {
+            $this->logger->debug(['trace' => $client->__getLastRequest()]);
+            throw $e;
+        }
+
+        return $result;
+    }
+}
diff --git a/app/code/Magento/Payment/Gateway/Http/Client/Zend.php b/app/code/Magento/Payment/Gateway/Http/Client/Zend.php
index 0ea8ffbc871b8e49261c641a5bb71e3669e830d2..0415aab562b97e92f742315a48eca0ace2d56a9e 100644
--- a/app/code/Magento/Payment/Gateway/Http/Client/Zend.php
+++ b/app/code/Magento/Payment/Gateway/Http/Client/Zend.php
@@ -9,6 +9,7 @@ use Magento\Framework\HTTP\ZendClientFactory;
 use Magento\Framework\HTTP\ZendClient;
 use Magento\Payment\Gateway\Http\ClientInterface;
 use Magento\Payment\Gateway\Http\ConverterInterface;
+use Magento\Payment\Gateway\Http\TransferInterface;
 use Magento\Payment\Model\Method\Logger;
 
 class Zend implements ClientInterface
@@ -19,7 +20,7 @@ class Zend implements ClientInterface
     private $clientFactory;
 
     /**
-     * @var ConverterInterface
+     * @var ConverterInterface | null
      */
     private $converter;
 
@@ -30,13 +31,13 @@ class Zend implements ClientInterface
 
     /**
      * @param ZendClientFactory $clientFactory
-     * @param ConverterInterface $converter
      * @param Logger $logger
+     * @param ConverterInterface | null $converter
      */
     public function __construct(
         ZendClientFactory $clientFactory,
-        ConverterInterface $converter,
-        Logger $logger
+        Logger $logger,
+        ConverterInterface $converter = null
     ) {
         $this->clientFactory = $clientFactory;
         $this->converter = $converter;
@@ -46,10 +47,11 @@ class Zend implements ClientInterface
     /**
      * {inheritdoc}
      */
-    public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject)
+    public function placeRequest(TransferInterface $transferObject)
     {
         $log = [
-            'request' => $transferObject->getBody()
+            'request' => $transferObject->getBody(),
+            'request_uri' => $transferObject->getUri()
         ];
         $result = [];
         /** @var ZendClient $client */
@@ -66,7 +68,12 @@ class Zend implements ClientInterface
                 $client->setParameterPost($transferObject->getBody());
                 break;
             default:
-                throw new \LogicException(sprintf('Unsupported HTTP method %s', $transferObject->getMethod()));
+                throw new \LogicException(
+                    sprintf(
+                        'Unsupported HTTP method %s',
+                        $transferObject->getMethod()
+                    )
+                );
         }
 
         $client->setHeaders($transferObject->getHeaders());
@@ -76,10 +83,14 @@ class Zend implements ClientInterface
         try {
             $response = $client->request();
 
-            $result = $this->converter->convert($response->getBody());
+            $result = $this->converter
+                ? $this->converter->convert($response->getBody())
+                : [$response->getBody()];
             $log['response'] = $result;
         } catch (\Zend_Http_Client_Exception $e) {
-            throw new \Magento\Payment\Gateway\Http\ClientException(__($e->getMessage()));
+            throw new \Magento\Payment\Gateway\Http\ClientException(
+                __($e->getMessage())
+            );
         } catch (\Magento\Payment\Gateway\Http\ConverterException $e) {
             throw $e;
         } finally {
diff --git a/app/code/Magento/Payment/Gateway/Http/Converter/Soap/ObjectToArrayConverter.php b/app/code/Magento/Payment/Gateway/Http/Converter/Soap/ObjectToArrayConverter.php
new file mode 100644
index 0000000000000000000000000000000000000000..e0045085417715e81b6251b719b6a326c63dcdbb
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/Http/Converter/Soap/ObjectToArrayConverter.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Gateway\Http\Converter\Soap;
+
+use Magento\Payment\Gateway\Http\ConverterInterface;
+
+class ObjectToArrayConverter implements ConverterInterface
+{
+    /**
+     * Converts gateway response to ENV structure
+     *
+     * @param mixed $response
+     * @return array
+     * @throws \Magento\Payment\Gateway\Http\ConverterException
+     */
+    public function convert($response)
+    {
+        $response = (array) $response;
+        foreach ($response as $key => $value) {
+            if (is_object($value)) {
+                $response[$key] = $this->convert($value);
+            }
+        }
+
+        return $response;
+    }
+}
diff --git a/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php b/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php
index 776ea4b11673d8589dfca68b53c203da27986bda..673a0bbc847008af50b59bf41da2f0ed2f0f8af7 100644
--- a/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php
+++ b/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php
@@ -10,7 +10,7 @@ interface ConverterInterface
     /**
      * Converts gateway response to ENV structure
      *
-     * @param string $response
+     * @param mixed $response
      * @return array
      * @throws \Magento\Payment\Gateway\Http\ConverterException
      */
diff --git a/app/code/Magento/Payment/Gateway/Http/TransferInterface.php b/app/code/Magento/Payment/Gateway/Http/TransferInterface.php
index abd3d530b2ac59ff37b88ee738d29d79a864e8a8..f2150c8e083f23f8a9fa3f0440a52c884f9cfac3 100644
--- a/app/code/Magento/Payment/Gateway/Http/TransferInterface.php
+++ b/app/code/Magento/Payment/Gateway/Http/TransferInterface.php
@@ -38,7 +38,7 @@ interface TransferInterface
     /**
      * Returns request body
      *
-     * @return string
+     * @return array
      */
     public function getBody();
 
diff --git a/app/code/Magento/Payment/Gateway/Validator/AbstractValidator.php b/app/code/Magento/Payment/Gateway/Validator/AbstractValidator.php
index e82e0605445a367d1bbf528989c2081393f35c2c..b9e55ef57eca1d31ef32912e1457f8772c5520af 100644
--- a/app/code/Magento/Payment/Gateway/Validator/AbstractValidator.php
+++ b/app/code/Magento/Payment/Gateway/Validator/AbstractValidator.php
@@ -30,6 +30,11 @@ abstract class AbstractValidator implements ValidatorInterface
      */
     protected function createResult($isValid, array $fails = [])
     {
-        return $this->resultInterfaceFactory->create(['isValid' => (bool)$isValid, 'failsDescription' => $fails]);
+        return $this->resultInterfaceFactory->create(
+            [
+                'isValid' => (bool)$isValid,
+                'failsDescription' => $fails
+            ]
+        );
     }
 }
diff --git a/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php b/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php
index 3a0ff81186df3aff134f5e14c79d5a7f409a2e7b..0c65b09785040a45d402bed4653c4ab3b691db23 100644
--- a/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php
+++ b/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php
@@ -9,7 +9,7 @@ use Magento\Framework\Exception\NotFoundException;
 use Magento\Payment\Gateway\ConfigInterface;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
 
-class CountryValidator implements ValidatorInterface
+class CountryValidator extends AbstractValidator
 {
     /**
      * @var \Magento\Payment\Gateway\ConfigInterface
@@ -17,20 +17,15 @@ class CountryValidator implements ValidatorInterface
     private $config;
 
     /**
-     * @var ResultInterfaceFactory
-     */
-    private $resultFactory;
-
-    /**
-     * @param \Magento\Payment\Gateway\ConfigInterface $config
      * @param ResultInterfaceFactory $resultFactory
+     * @param \Magento\Payment\Gateway\ConfigInterface $config
      */
     public function __construct(
-        ConfigInterface $config,
-        ResultInterfaceFactory $resultFactory
+        ResultInterfaceFactory $resultFactory,
+        ConfigInterface $config
     ) {
         $this->config = $config;
-        $this->resultFactory = $resultFactory;
+        parent::__construct($resultFactory);
     }
 
     /**
@@ -55,10 +50,6 @@ class CountryValidator implements ValidatorInterface
             }
         }
 
-        return $this->resultFactory->create(
-            [
-                'isValid' => $isValid
-            ]
-        );
+        return $this->createResult($isValid);
     }
 }
diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php
index 05a476f9743c12a930052fe27c4dfcb057e54ae5..6e7c5c8c0ab5cecf0031ebc87519306289ea40e2 100644
--- a/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php
+++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php
@@ -9,18 +9,13 @@ use Magento\Framework\ObjectManager\TMap;
 use Magento\Framework\ObjectManager\TMapFactory;
 use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
 
-class ValidatorComposite implements ValidatorInterface
+class ValidatorComposite extends AbstractValidator
 {
     /**
      * @var ValidatorInterface[] | TMap
      */
     private $validators;
 
-    /**
-     * @var ResultInterfaceFactory
-     */
-    private $resultFactory;
-
     /**
      * @param ResultInterfaceFactory $resultFactory
      * @param array $validators
@@ -37,7 +32,7 @@ class ValidatorComposite implements ValidatorInterface
                 'type' => 'Magento\Payment\Gateway\Validator\ValidatorInterface'
             ]
         );
-        $this->resultFactory = $resultFactory;
+        parent::__construct($resultFactory);
     }
 
     /**
@@ -61,11 +56,6 @@ class ValidatorComposite implements ValidatorInterface
             }
         }
 
-        return $this->resultFactory->create(
-            [
-                'isValid' => $isValid,
-                'failsDescription' => $failsDescriptionAggregate
-            ]
-        );
+        return $this->createResult($isValid, $failsDescriptionAggregate);
     }
 }
diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php
index acb0e56809e30c3c677aebc4bffc5611ac7112f1..314a03d51550fedde3cd9b9e8c795eb25b4f5061 100644
--- a/app/code/Magento/Payment/Model/Method/Adapter.php
+++ b/app/code/Magento/Payment/Model/Method/Adapter.php
@@ -7,6 +7,9 @@ namespace Magento\Payment\Model\Method;
 
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\Exception\NotFoundException;
+use Magento\Payment\Gateway\Command\CommandPoolInterface;
+use Magento\Payment\Gateway\Config\ValueHandlerPoolInterface;
+use Magento\Payment\Gateway\Validator\ValidatorPoolInterface;
 use Magento\Payment\Model\InfoInterface;
 use Magento\Payment\Model\MethodInterface;
 
@@ -18,17 +21,17 @@ use Magento\Payment\Model\MethodInterface;
 class Adapter implements MethodInterface
 {
     /**
-     * @var \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface
+     * @var ValueHandlerPoolInterface
      */
     private $valueHandlerPool;
 
     /**
-     * @var \Magento\Payment\Gateway\Validator\ValidatorPoolInterface
+     * @var ValidatorPoolInterface
      */
     private $validatorPool;
 
     /**
-     * @var \Magento\Payment\Gateway\Command\CommandPoolInterface
+     * @var CommandPoolInterface
      */
     private $commandPool;
 
@@ -69,9 +72,9 @@ class Adapter implements MethodInterface
 
     /**
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface $valueHandlerPool
-     * @param \Magento\Payment\Gateway\Validator\ValidatorPoolInterface $validatorPool
-     * @param \Magento\Payment\Gateway\Command\CommandPoolInterface $commandPool
+     * @param ValueHandlerPoolInterface $valueHandlerPool
+     * @param ValidatorPoolInterface $validatorPool
+     * @param CommandPoolInterface $commandPool
      * @param \Magento\Payment\Gateway\Data\PaymentDataObjectFactory $paymentDataObjectFactory
      * @param string $code
      * @param string $formBlockType
@@ -79,9 +82,9 @@ class Adapter implements MethodInterface
      */
     public function __construct(
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface $valueHandlerPool,
-        \Magento\Payment\Gateway\Validator\ValidatorPoolInterface $validatorPool,
-        \Magento\Payment\Gateway\Command\CommandPoolInterface $commandPool,
+        ValueHandlerPoolInterface $valueHandlerPool,
+        ValidatorPoolInterface $validatorPool,
+        CommandPoolInterface $commandPool,
         \Magento\Payment\Gateway\Data\PaymentDataObjectFactory $paymentDataObjectFactory,
         $code,
         $formBlockType,
@@ -306,7 +309,15 @@ class Adapter implements MethodInterface
     private function getConfiguredValue($field)
     {
         $handler = $this->valueHandlerPool->get($field);
-        return $handler->handle($field, $this->getStore());
+        $subject = [
+            'field' => $field
+        ];
+
+        if ($this->getInfoInstance()) {
+            $subject['payment'] = $this->paymentDataObjectFactory->create($this->getInfoInstance());
+        }
+
+        return $handler->handle($subject, $this->getStore());
     }
 
     /**
@@ -522,12 +533,6 @@ class Adapter implements MethodInterface
      */
     public function getInfoInstance()
     {
-        if (!$this->infoInstance instanceof InfoInterface) {
-            throw new LocalizedException(
-                __('We cannot retrieve the payment information object instance.')
-            );
-        }
-
         return $this->infoInstance;
     }
 
@@ -548,8 +553,16 @@ class Adapter implements MethodInterface
             return $this->getConfiguredValue($field);
         }
 
+        $subject = [
+            'field' => $field
+        ];
+
+        if ($this->getInfoInstance()) {
+            $subject['payment'] = $this->paymentDataObjectFactory->create($this->getInfoInstance());
+        }
+
         $handler = $this->valueHandlerPool->get($field);
-        return $handler->handle($field, (int)$storeId);
+        return $handler->handle($subject, (int)$storeId);
     }
 
     /**
@@ -567,6 +580,7 @@ class Adapter implements MethodInterface
 
     /**
      * {inheritdoc}
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function initialize($paymentAction, $stateObject)
     {
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php
index 9872e20250bbe2d34c5375f22cbac5916e69cf3a..7a9d60d8acc18d9ce7fc373bdd14d56f0f0e26e6 100644
--- a/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php
@@ -5,50 +5,67 @@
  */
 namespace Magento\Payment\Test\Unit\Gateway\Command;
 
+use Magento\Payment\Gateway\Command\GatewayCommand;
+use Magento\Payment\Gateway\Http\ClientInterface;
+use Magento\Payment\Gateway\Http\TransferFactoryInterface;
+use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\Payment\Gateway\Response\HandlerInterface;
+use Magento\Payment\Gateway\Validator\ValidatorInterface;
+
 class GatewayCommandTest extends \PHPUnit_Framework_TestCase
 {
-    /** @var \Magento\Payment\Gateway\Command\GatewayCommand */
-    protected $model;
+    /** @var GatewayCommand */
+    protected $command;
 
     /**
-     * @var \Magento\Payment\Gateway\Request\BuilderInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var BuilderInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $requestBuilderMock;
 
     /**
-     * @var \Magento\Payment\Gateway\Http\TransferFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var TransferFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $transferFactoryMock;
 
     /**
-     * @var \Magento\Payment\Gateway\Http\ClientInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var ClientInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $clientMock;
 
     /**
-     * @var \Magento\Payment\Gateway\Response\HandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var HandlerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $responseHandlerMock;
 
     /**
-     * @var \Magento\Payment\Gateway\Validator\ValidatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var ValidatorInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $validatorMock;
 
     protected function setUp()
     {
-        $this->requestBuilderMock = $this->getMockBuilder('Magento\Payment\Gateway\Request\BuilderInterface')
+        $this->requestBuilderMock = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Request\BuilderInterface'
+        )
             ->getMockForAbstractClass();
-        $this->transferFactoryMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferFactoryInterface')
+        $this->transferFactoryMock = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\TransferFactoryInterface'
+        )
             ->getMockForAbstractClass();
-        $this->clientMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\ClientInterface')
+        $this->clientMock = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\ClientInterface'
+        )
             ->getMockForAbstractClass();
-        $this->responseHandlerMock = $this->getMockBuilder('Magento\Payment\Gateway\Response\HandlerInterface')
+        $this->responseHandlerMock = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Response\HandlerInterface'
+        )
             ->getMockForAbstractClass();
-        $this->validatorMock = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ValidatorInterface')
+        $this->validatorMock = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Validator\ValidatorInterface'
+        )
             ->getMockForAbstractClass();
 
-        $this->model = new \Magento\Payment\Gateway\Command\GatewayCommand(
+        $this->command = new GatewayCommand(
             $this->requestBuilderMock,
             $this->transferFactoryMock,
             $this->clientMock,
@@ -60,12 +77,19 @@ class GatewayCommandTest extends \PHPUnit_Framework_TestCase
     public function testExecute()
     {
         $commandSubject = ['authorize'];
-        $request = ['request_field1' => 'request_value1', 'request_field2' => 'request_value2'];
+        $request = [
+            'request_field1' => 'request_value1',
+            'request_field2' => 'request_value2'
+        ];
         $response = ['response_field1' => 'response_value1'];
-        $validationResult = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterface')
+        $validationResult = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Validator\ResultInterface'
+        )
             ->getMockForAbstractClass();
 
-        $transferO = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferInterface')
+        $transferO = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\TransferInterface'
+        )
             ->getMockForAbstractClass();
 
         $this->requestBuilderMock->expects(static::once())
@@ -94,6 +118,56 @@ class GatewayCommandTest extends \PHPUnit_Framework_TestCase
             ->method('handle')
             ->with($commandSubject, $response);
 
-        $this->model->execute($commandSubject);
+        $this->command->execute($commandSubject);
+    }
+
+    public function testExecuteValidationFail()
+    {
+        $this->setExpectedException(
+            'Magento\Payment\Gateway\Command\CommandException'
+        );
+
+        $commandSubject = ['authorize'];
+        $request = [
+            'request_field1' => 'request_value1',
+            'request_field2' => 'request_value2'
+        ];
+        $response = ['response_field1' => 'response_value1'];
+        $validationResult = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Validator\ResultInterface'
+        )
+            ->getMockForAbstractClass();
+
+        $transferO = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\TransferInterface'
+        )
+            ->getMockForAbstractClass();
+
+        $this->requestBuilderMock->expects(static::once())
+            ->method('build')
+            ->with($commandSubject)
+            ->willReturn($request);
+
+        $this->transferFactoryMock->expects(static::once())
+            ->method('create')
+            ->with($request)
+            ->willReturn($transferO);
+
+        $this->clientMock->expects(static::once())
+            ->method('placeRequest')
+            ->with($transferO)
+            ->willReturn($response);
+        $this->validatorMock->expects(static::once())
+            ->method('validate')
+            ->with(array_merge($commandSubject, ['response' =>$response]))
+            ->willReturn($validationResult);
+        $validationResult->expects(static::once())
+            ->method('isValid')
+            ->willReturn(false);
+        $validationResult->expects(static::once())
+            ->method('getFailsDescription')
+            ->willReturn([]);
+
+        $this->command->execute($commandSubject);
     }
 }
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php
index eebebfdadf275d0ae66013340594630543dce94e..3f1d4a280ef288d27e52458ecd3950bae936fc05 100644
--- a/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php
@@ -23,7 +23,8 @@ class ConfigValueHandlerTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->configMock = $this->getMockBuilder('Magento\Payment\Gateway\ConfigInterface')->getMockForAbstractClass();
+        $this->configMock = $this->getMockBuilder('Magento\Payment\Gateway\ConfigInterface')
+            ->getMockForAbstractClass();
         $this->model = new ConfigValueHandler($this->configMock);
     }
 
@@ -38,7 +39,7 @@ class ConfigValueHandlerTest extends \PHPUnit_Framework_TestCase
             ->with($field, $storeId)
             ->willReturn($expected);
 
-        $this->assertEquals($expected, $this->model->handle($field, $storeId));
+        $this->assertEquals($expected, $this->model->handle(['field' => $field], $storeId));
     }
 
     public function testHandleWithoutStoreId()
@@ -51,6 +52,6 @@ class ConfigValueHandlerTest extends \PHPUnit_Framework_TestCase
             ->with($field, null)
             ->willReturn($expected);
 
-        $this->assertEquals($expected, $this->model->handle($field));
+        $this->assertEquals($expected, $this->model->handle(['field' => $field]));
     }
 }
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/SoapTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/SoapTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef4dd5be64546681d9e328223dad5e9f57386d38
--- /dev/null
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/SoapTest.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Test\Unit\Gateway\Http\Client;
+
+use Magento\Payment\Gateway\Http\Client\Soap;
+
+class SoapTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $logger;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $clientFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $converter;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $client;
+
+    /**
+     * @var Soap
+     */
+    private $gatewayClient;
+
+    protected function setUp()
+    {
+        $this->logger = $this->getMockBuilder(
+            'Magento\Payment\Model\Method\Logger'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->clientFactory = $this->getMockBuilder(
+            'Magento\Framework\Webapi\Soap\ClientFactory'
+        )->getMock();
+        $this->converter = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\ConverterInterface'
+        )->getMockForAbstractClass();
+        $this->client = $this->getMockBuilder('\SoapClient')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->gatewayClient = new Soap(
+            $this->logger,
+            $this->clientFactory,
+            $this->converter
+        );
+    }
+
+    public function testPlaceRequest()
+    {
+        $expectedResult = [
+            'result' => []
+        ];
+        $soapResult = new \StdClass;
+
+        $this->logger->expects(static::at(0))
+            ->method('debug')
+            ->with(
+                ['request' => ['body']]
+            );
+        $this->clientFactory->expects(static::once())
+            ->method('create')
+            ->with('path_to_wsdl', ['trace' => true])
+            ->willReturn($this->client);
+        $transferObject = $this->getTransferObject();
+        $transferObject->expects(static::any())
+            ->method('__setSoapHeaders')
+            ->with(['headers']);
+        $this->client->expects(static::once())
+            ->method('__soapCall')
+            ->with('soapMethod', [['body']])
+            ->willReturn($soapResult);
+        $this->converter->expects(static::once())
+            ->method('convert')
+            ->with($soapResult)
+            ->willReturn($expectedResult);
+        $this->logger->expects(static::at(1))
+            ->method('debug')
+            ->with(['response' => $expectedResult]);
+
+        static::assertEquals(
+            $expectedResult,
+            $this->gatewayClient->placeRequest($transferObject)
+        );
+    }
+
+    public function testPlaceRequestSoapException()
+    {
+        $this->setExpectedException('Exception');
+
+        $this->logger->expects(static::at(0))
+            ->method('debug')
+            ->with(
+                ['request' => ['body']]
+            );
+        $this->clientFactory->expects(static::once())
+            ->method('create')
+            ->with('path_to_wsdl', ['trace' => true])
+            ->willReturn($this->client);
+        $transferObject = $this->getTransferObject();
+        $transferObject->expects(static::any())
+            ->method('__setSoapHeaders')
+            ->with(['headers']);
+        $this->client->expects(static::once())
+            ->method('__soapCall')
+            ->with('soapMethod', [['body']])
+            ->willThrowException(new \Exception);
+        $this->client->expects(static::once())
+            ->method('__getLastRequest')
+            ->willReturn('RequestTrace');
+        $this->logger->expects(static::at(1))
+            ->method('debug')
+            ->with(
+                ['trace' => 'RequestTrace']
+            );
+
+        $this->gatewayClient->placeRequest($transferObject);
+    }
+
+    /**
+     * Returns prepared transfer object
+     *
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getTransferObject()
+    {
+        $transferObject = $this->getMockBuilder(
+            'Magento\Payment\Gateway\Http\TransferInterface'
+        )->getMock();
+
+        $transferObject->expects(static::any())
+            ->method('getBody')
+            ->willReturn(['body']);
+        $transferObject->expects(static::any())
+            ->method('getClientConfig')
+            ->willReturn(['wsdl' => 'path_to_wsdl']);
+        $transferObject->expects(static::any())
+            ->method('getMethod')
+            ->willReturn('soapMethod');
+
+        return $transferObject;
+    }
+}
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php
index 43f2a400ccd77100161afbd5596ddf4fdbc7b8b1..e34cb00d5a24b4822ac6de12e6a406304fc5afcc 100644
--- a/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php
@@ -65,7 +65,11 @@ class ZendTest extends \PHPUnit_Framework_TestCase
         $this->transferObjectMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferInterface')
             ->getMockForAbstractClass();
 
-        $this->model = new Zend($this->zendClientFactoryMock, $this->converterMock, $this->loggerMock);
+        $this->model = new Zend(
+            $this->zendClientFactoryMock,
+            $this->loggerMock,
+            $this->converterMock
+        );
     }
 
     public function testPlaceRequest()
@@ -147,7 +151,7 @@ class ZendTest extends \PHPUnit_Framework_TestCase
         $this->transferObjectMock->expects($this->once())->method('getHeaders')->willReturn($headers);
         $this->transferObjectMock->expects($this->atLeastOnce())->method('getBody')->willReturn($body);
         $this->transferObjectMock->expects($this->once())->method('shouldEncode')->willReturn($shouldEncode);
-        $this->transferObjectMock->expects($this->once())->method('getUri')->willReturn($uri);
+        $this->transferObjectMock->expects(static::atLeastOnce())->method('getUri')->willReturn($uri);
 
         $this->clientMock->expects($this->once())->method('setConfig')->with($config)->willReturnSelf();
         $this->clientMock->expects($this->once())->method('setMethod')->with($method)->willReturnSelf();
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Http/Converter/Soap/ObjectToArrayConverterTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Converter/Soap/ObjectToArrayConverterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c39c6dcb1d8b2f8374ba9897b062dd16320479bf
--- /dev/null
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Converter/Soap/ObjectToArrayConverterTest.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Payment\Test\Unit\Gateway\Http\Converter\Soap;
+
+use Magento\Payment\Gateway\Http\Converter\Soap\ObjectToArrayConverter;
+
+class ObjectToArrayConverterTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConvert()
+    {
+        $input = new \stdClass();
+        $input->property = new \stdClass();
+        $input->property2 = 'bla';
+        $input->property->property3 = new \stdClass();
+        $input->property->property4 = 'bla';
+        $input->property->property3->property5 = 'bla';
+
+        $output = [
+            'property' => [
+                'property3' => [
+                    'property5' => 'bla'
+                ],
+                'property4' => 'bla'
+            ],
+            'property2' => 'bla'
+        ];
+
+        $converter = new ObjectToArrayConverter();
+        static::assertEquals($output, $converter->convert($input));
+
+    }
+}
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php
index 38ac5d69dd3d01176e8f53c8f45a1057dc5ed17c..554b13ef74646f8e1cd6a62f8ede96b1491352ae 100644
--- a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php
@@ -38,8 +38,8 @@ class CountryValidatorTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->model = new \Magento\Payment\Gateway\Validator\CountryValidator(
-            $this->configMock,
-            $this->resultFactoryMock
+            $this->resultFactoryMock,
+            $this->configMock
         );
     }
 
@@ -62,7 +62,7 @@ class CountryValidatorTest extends \PHPUnit_Framework_TestCase
 
         $this->resultFactoryMock->expects($this->once())
             ->method('create')
-            ->with(['isValid' => $isValid])
+            ->with(['isValid' => $isValid, 'failsDescription' => []])
             ->willReturn($this->resultMock);
 
         $this->assertSame($this->resultMock, $this->model->validate($validationSubject));
@@ -90,7 +90,7 @@ class CountryValidatorTest extends \PHPUnit_Framework_TestCase
 
         $this->resultFactoryMock->expects($this->once())
             ->method('create')
-            ->with(['isValid' => $isValid])
+            ->with(['isValid' => $isValid, 'failsDescription' => []])
             ->willReturn($this->resultMock);
 
         $this->assertSame($this->resultMock, $this->model->validate($validationSubject));
diff --git a/app/code/Magento/Payment/etc/payment.xml b/app/code/Magento/Payment/etc/payment.xml
index 5560a70f11b325ea8d12a85ec5fd2582b29593f1..1d52b718925cddf25f531b1b6d8ea9c941a9b901 100644
--- a/app/code/Magento/Payment/etc/payment.xml
+++ b/app/code/Magento/Payment/etc/payment.xml
@@ -35,9 +35,6 @@
         <type id="DN" order="60">
             <label>Diners</label>
         </type>
-        <type id="JC" order="70">
-            <label>JCB</label>
-        </type>
         <type id="MI" order="80">
             <label>Maestro International</label>
         </type>
diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml
index c6a429a0fbe08f624c53f03d7998879281dfde27..a2cf8e3a6383311ba7b2e20bd57c858fa88d368f 100644
--- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml
+++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml
@@ -7,14 +7,22 @@
 <?php
 // @codingStandardsIgnoreFile
 
-/** @var \Magento\Payment\Block\Transparent\Form $block*/
+/** @var \Magento\Payment\Block\Transparent\Form $block */
 $code = $block->getMethodCode();
 ?>
 
 <!-- IFRAME for request to Payment Gateway -->
-<iframe id="<?php echo $code ?>-transparent-iframe" data-container="<?php echo $code ?>-transparent-iframe" allowtransparency="true" frameborder="0"  name="iframeTransparent" style="display:none;width:100%;background-color:transparent" src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe>
-<div id="payment_form_<?php echo $code ?>"
-     data-mage-init='{
+<iframe id="<?php echo $code ?>-transparent-iframe"
+        data-container="<?php echo $code ?>-transparent-iframe"
+        allowtransparency="true"
+        frameborder="0"
+        name="iframeTransparent"
+        style="display: none; width: 100%; background-color: transparent;"
+        src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe>
+<fieldset
+    id="payment_form_<?php echo $code ?>"
+    class="admin__fieldset"
+    data-mage-init='{
      "transparent":{
         "controller":"<?php echo $block->getRequest()->getControllerName() ?>",
         "gateway":"<?php echo $block->getMethodCode() ?>",
@@ -25,71 +33,96 @@ $code = $block->getMethodCode();
         "expireYearLength":"<?php echo $block->getMethodConfigData('cc_year_length') ?>",
         "nativeAction":"<?php echo $block->getUrl('*/*/save', ['_secure' => $block->getRequest()->isSecure()]) ?>"
       }, "validation":[]}'
-     style="display:none;">
+    style="display: none;">
+    <div class="admin__field _required">
+        <label for="<?php echo $code ?>_cc_type" class="admin__field-label">
+            <span><?php echo __('Credit Card Type') ?></span>
+        </label>
 
-        <div class="field required type">
-            <label for="<?php echo $code ?>_cc_type" class="label"><span><?php echo __('Credit Card Type') ?></span></label>
-            <div class="control">
-                <select id="<?php echo $code ?>_cc_type" data-container="<?php echo $code ?>-cc-type" name="payment[cc_type]" data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}'>
-                    <option value=""><?php echo __('--Please Select--')?></option>
-                    <?php $_ccType = $block->getInfoData('cc_type') ?>
-                    <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?>
-                        <option value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option>
-                    <?php endforeach ?>
-                </select>
-            </div>
+        <div class="admin__field-control">
+            <select id="<?php echo $code ?>_cc_type"
+                    data-container="<?php echo $code ?>-cc-type"
+                    name="payment[cc_type]"
+                    data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}'
+                    class="admin__control-select">
+                <option value=""><?php echo __('Please Select') ?></option>
+                <?php $_ccType = $block->getInfoData('cc_type') ?>
+                <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?>
+                    <option
+                        value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option>
+                <?php endforeach ?>
+            </select>
         </div>
+    </div>
 
-        <div class="field required number">
-            <label for="<?php echo $code ?>_cc_number" class="label"><span><?php echo __('Credit Card Number') ?></span></label>
-            <div class="control">
-                <input type="number" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number" name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>" class="input-text" value="" data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/>
-            </div>
+    <div class="admin__field _required field-number">
+        <label for="<?php echo $code ?>_cc_number" class="admin__field-label">
+            <span><?php echo __('Credit Card Number') ?></span>
+        </label>
+
+        <div class="admin__field-control">
+            <input type="text" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number"
+                   name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>"
+                   class="admin__control-text"
+                   value=""
+                   data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}'
+                   autocomplete="off"/>
         </div>
+    </div>
 
-        <div class="field required date" id="<?php echo $code ?>_cc_type_exp_div">
-            <label for="<?php echo $code ?>_expiration" class="label"><span><?php echo __('Expiration Date') ?></span></label>
-            <div class="control">
-                <div class="fields group group-2">
-                    <div class="field no-label month">
-                        <div class="control">
-                            <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]" data-container="<?php echo $code ?>-cc-month" class="month" data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'>
-                                <?php $_ccExpMonth = $block->getInfoData('cc_exp_month') ?>
-                                <?php foreach ($block->getCcMonths() as $k => $v): ?>
-                                    <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
-                                <?php endforeach ?>
-                            </select>
-                        </div>
-                    </div>
-                    <div class="field no-label year">
-                        <div class="control">
-                            <?php $_ccExpYear = $block->getInfoData('cc_exp_year') ?>
-                            <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]" class="year" data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'>
-                                <?php foreach ($block->getCcYears() as $k => $v): ?>
-                                    <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
-                                <?php endforeach ?>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
+    <div class="admin__field _required field-date" id="<?php echo $code ?>_cc_type_exp_div">
+        <label for="<?php echo $code ?>_expiration" class="admin__field-label">
+            <span><?php echo __('Expiration Date') ?></span>
+        </label>
+
+        <div class="admin__field-control">
+            <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]"
+                    data-container="<?php echo $code ?>-cc-month"
+                    class="admin__control-select admin__control-select-month"
+                    data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'>
+                <?php $_ccExpMonth = $block->getInfoData('cc_exp_month') ?>
+                <?php foreach ($block->getCcMonths() as $k => $v): ?>
+                    <option
+                        value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
+                <?php endforeach ?>
+            </select>
+
+            <?php $_ccExpYear = $block->getInfoData('cc_exp_year') ?>
+            <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]"
+                    class="admin__control-select admin__control-select-year"
+                    data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'>
+                <?php foreach ($block->getCcYears() as $k => $v): ?>
+                    <option
+                        value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
+                <?php endforeach ?>
+            </select>
         </div>
-        <?php if ($block->hasVerification()): ?>
-            <div class="field required cvv" id="<?php echo $code ?>_cc_type_cvv_div">
-                <label for="<?php echo $code ?>_cc_cid" class="label"><span><?php echo __('Card Verification Number') ?></span></label>
-                <div class="control">
-                    <input type="number" title="<?php echo __('Card Verification Number') ?>" data-container="<?php echo $code ?>-cc-cvv" class="input-text cvv" id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]" value="" data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/>
-                </div>
+    </div>
+    <?php if ($block->hasVerification()): ?>
+        <div class="admin__field _required field-cvv" id="<?php echo $code ?>_cc_type_cvv_div">
+            <label for="<?php echo $code ?>_cc_cid" class="admin__field-label">
+                <span><?php echo __('Card Verification Number') ?></span>
+            </label>
+
+            <div class="admin__field-control">
+                <input type="text" title="<?php echo __('Card Verification Number') ?>"
+                       data-container="<?php echo $code ?>-cc-cvv"
+                       class="admin__control-text cvv"
+                       id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]"
+                       value=""
+                       data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}'
+                       autocomplete="off"/>
             </div>
-        <?php endif; ?>
-        <?php echo $block->getChildHtml() ?>
-</div>
+        </div>
+    <?php endif; ?>
+    <?php echo $block->getChildHtml() ?>
+</fieldset>
 
 <script>
     /**
      * Disable card server validation in admin
      */
-    require(["Magento_Sales/order/create/form"], function(){
+    require(["Magento_Sales/order/create/form"], function () {
         order.addExcludedPaymentMethod('<?php echo $code ?>');
     });
 </script>
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/ae.png b/app/code/Magento/Payment/view/base/web/images/cc/ae.png
new file mode 100644
index 0000000000000000000000000000000000000000..f72ae5c26c314ac95ebfabb5887f3a1daf4cdd22
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/ae.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/di.png b/app/code/Magento/Payment/view/base/web/images/cc/di.png
new file mode 100644
index 0000000000000000000000000000000000000000..130d5a4aec88e9eec99e435f94f75725bf5728c7
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/di.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/dn.png b/app/code/Magento/Payment/view/base/web/images/cc/dn.png
new file mode 100644
index 0000000000000000000000000000000000000000..3444db7ea5945a86ac9ca506a5ff25939bb49c6b
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/dn.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/jc.png b/app/code/Magento/Payment/view/base/web/images/cc/jc.png
new file mode 100644
index 0000000000000000000000000000000000000000..86df1caa5da6e869e462941402e1129213e9f05c
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/jc.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/mc.png b/app/code/Magento/Payment/view/base/web/images/cc/mc.png
new file mode 100644
index 0000000000000000000000000000000000000000..bf0a4c2b8727fa824f3e902e88ee31d4d144a474
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/mc.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/sm.png b/app/code/Magento/Payment/view/base/web/images/cc/sm.png
new file mode 100644
index 0000000000000000000000000000000000000000..d239695ab2a41091981b4f34732276281bf8c992
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/sm.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/un.png b/app/code/Magento/Payment/view/base/web/images/cc/un.png
new file mode 100644
index 0000000000000000000000000000000000000000..b60791a0900184b6aea16155e06777ea7646158c
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/un.png differ
diff --git a/app/code/Magento/Payment/view/base/web/images/cc/vi.png b/app/code/Magento/Payment/view/base/web/images/cc/vi.png
new file mode 100644
index 0000000000000000000000000000000000000000..0885f78a93765fa61e350c60641302b498b109c0
Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/vi.png differ
diff --git a/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml
index 3f89143cb971ba996a0a3298a3807bec96d2d958..979a1c039cfedda69eb2821b528ad9c246824b68 100644
--- a/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml
@@ -15,10 +15,26 @@
                             <item name="children" xsi:type="array">
                                 <item name="steps" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="payment" xsi:type="array">
+                                        <item name="billing-step" xsi:type="array">
+                                            <item name="component" xsi:type="string">uiComponent</item>
+                                            <item name="sortOrder" xsi:type="string">2</item>
                                             <item name="children" xsi:type="array">
-                                                <item name="free" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Payment/js/view/payment/free-method</item>
+                                                <item name="payment" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="renders" xsi:type="array">
+                                                            <!-- merge payment method renders here -->
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="free-payments" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Payment/js/view/payment/payments</item>
+                                                                    <item name="methods" xsi:type="array">
+                                                                        <item name="free" xsi:type="array">
+                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
+                                                                        </item>
+                                                                    </item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
                                                 </item>
                                             </item>
                                         </item>
@@ -31,4 +47,4 @@
             </arguments>
         </referenceBlock>
     </body>
-</page>
+</page>
\ No newline at end of file
diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml
index 93ac9970e145338451895c1d54d29a977e19f7bc..f71a9bdd9fa412d02330b38ad6cb347b409bfd19 100644
--- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml
+++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml
@@ -26,9 +26,15 @@ $params = $block->getParams();
             window.top.location = "<?php echo $params['order_success'] ?>";
         <?php else: ?>
             var require = window.top.require;
-            require(['jquery'], function($) {
-                $('#originalPlaceOrder').click();
-            });
+            require(
+                [
+                    'Magento_Checkout/js/model/quote',
+                    'Magento_Checkout/js/action/place-order'
+                ],
+                function(quote, placeOrderAction) {
+                    placeOrderAction(quote.paymentMethod(), true);
+                }
+            );
         <?php endif; ?>
         </script>
     </head>
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef6dd82c179b4591a89a43987f72ca91ca974478
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js
@@ -0,0 +1,19 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function() {
+        'use strict';
+        return {
+            creditCard: null,
+            creditCardNumber: null,
+            expirationMonth: null,
+            expirationYear: null,
+            cvvCode: null
+        }
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f13a5af7c60a297dd13867daa9e1ba4694fbe5d
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js
@@ -0,0 +1,72 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'mageUtils',
+        'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator',
+        'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type'
+    ],
+    function (utils, luhn10, creditCardTypes) {
+        'use strict';
+
+        function resultWrapper(card, isPotentiallyValid, isValid) {
+            return {
+                card: card,
+                isValid: isValid,
+                isPotentiallyValid: isPotentiallyValid
+            };
+        }
+
+        return function (value) {
+            var potentialTypes,
+                cardType,
+                valid,
+                i,
+                maxLength;
+
+            if (utils.isEmpty(value)) {
+                return resultWrapper(null, false, false);
+            }
+
+            value = value.replace(/\-|\s/g, '');
+
+            if (!/^\d*$/.test(value)) {
+                return resultWrapper(null, false, false);
+            }
+
+            potentialTypes = creditCardTypes.getCardTypes(value);
+
+            if (potentialTypes.length === 0) {
+                return resultWrapper(null, false, false);
+            } else if (potentialTypes.length !== 1) {
+                return resultWrapper(null, true, false);
+            }
+
+            cardType = potentialTypes[0];
+
+            if (cardType.type === 'unionpay') {  // UnionPay is not Luhn 10 compliant
+                valid = true;
+            } else {
+                valid = luhn10(value);
+            }
+
+            for (i = 0; i < cardType.lengths.length; i++) {
+                if (cardType.lengths[i] === value.length) {
+                    return resultWrapper(cardType, valid, valid);
+                }
+            }
+
+            maxLength = Math.max.apply(null, cardType.lengths);
+
+            if (value.length < maxLength) {
+                return resultWrapper(cardType, true, false);
+            }
+
+            return resultWrapper(cardType, false, false);
+        };
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js
new file mode 100644
index 0000000000000000000000000000000000000000..71e0e57c5c16e71a394d1fa948f35ed807c75495
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js
@@ -0,0 +1,144 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'mageUtils'
+    ],
+    function ($, utils) {
+        'use strict';
+        var types = [
+            {
+                title: 'Visa',
+                type: 'VI',
+                pattern: '^4\\d*$',
+                gaps: [4, 8, 12],
+                lengths: [16],
+                code: {
+                    name: 'CVV',
+                    size: 3
+                }
+            },
+            {
+                title: 'MasterCard',
+                type: 'MC',
+                pattern: '^5([1-5]\\d*)?$',
+                gaps: [4, 8, 12],
+                lengths: [16],
+                code: {
+                    name: 'CVC',
+                    size: 3
+                }
+            },
+            {
+                title: 'American Express',
+                type: 'AE',
+                pattern: '^3([47]\\d*)?$',
+                isAmex: true,
+                gaps: [4, 10],
+                lengths: [15],
+                code: {
+                    name: 'CID',
+                    size: 4
+                }
+            },
+            {
+                title: 'Diners',
+                type: 'DN',
+                pattern: '^3((0([0-5]\\d*)?)|[689]\\d*)?$',
+                gaps: [4, 10],
+                lengths: [14],
+                code: {
+                    name: 'CVV',
+                    size: 3
+                }
+            },
+            {
+                title: 'Discover',
+                type: 'DI',
+                pattern: '^6(0|01|011\\d*|5\\d*|4|4[4-9]\\d*)?$',
+                gaps: [4, 8, 12],
+                lengths: [16],
+                code: {
+                    name: 'CID',
+                    size: 3
+                }
+            },
+            {
+                title: 'JCB',
+                type: 'JC',
+                pattern: '^((2|21|213|2131\\d*)|(1|18|180|1800\\d*)|(3|35\\d*))$',
+                gaps: [4, 8, 12],
+                lengths: [16],
+                code: {
+                    name: 'CVV',
+                    size: 3
+                }
+            },
+            {
+                title: 'UnionPay',
+                type: 'UN',
+                pattern: '^6(2\\d*)?$',
+                gaps: [4, 8, 12],
+                lengths: [16, 17, 18, 19],
+                code: {
+                    name: 'CVN',
+                    size: 3
+                }
+            },
+            {
+                title: 'Maestro',
+                type: 'SM',
+                pattern: '(^(5[0678])[0-9]{11,18}$)' +
+                '|(^(6[^05])[0-9]{11,18}$)' +
+                '|(^(601)[^1][0-9]{9,16}$)' +
+                '|(^(6011)[0-9]{9,11}$)' +
+                '|(^(6011)[0-9]{13,16}$)' +
+                '|(^(65)[0-9]{11,13}$)' +
+                '|(^(65)[0-9]{15,18}$)' +
+                '|(^(49030)[2-9]([0-9]{10}$' +
+                '|[0-9]{12,13}$))' +
+                '|(^(49033)[5-9]([0-9]{10}$' +
+                '|[0-9]{12,13}$))' +
+                '|(^(49110)[1-2]([0-9]{10}$' +
+                '|[0-9]{12,13}$))' +
+                '|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))' +
+                '|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))' +
+                '|(^(4936)([0-9]{12}$|[0-9]{14,15}$))',
+                gaps: [4, 8, 12],
+                lengths: [12, 13, 14, 15, 16, 17, 18, 19],
+                code: {
+                    name: 'CVC',
+                    size: 3
+                }
+            }
+        ];
+        return {
+            getCardTypes: function (cardNumber) {
+                var i, value,
+                    result = [];
+
+                if (utils.isEmpty(cardNumber)) {
+                    return result;
+                }
+
+                if (cardNumber === '') {
+                    return $.extend(true, {}, types);
+                }
+
+                for (i = 0; i < types.length; i++) {
+                    value = types[i];
+
+                    if (new RegExp(value.pattern).test(cardNumber)) {
+                        result.push($.extend(true, {}, value));
+                    }
+                }
+                return result;
+            }
+        }
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..38e93f084a25c72c8be813e52fa4f75b44c46622
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js
@@ -0,0 +1,22 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function() {
+        'use strict';
+        /**
+         * Luhn algorithm verification
+         */
+        return function(a, b, c, d, e) {
+            for(d = +a[b = a.length-1], e = 0; b--;) {
+                c = +a[b];
+                d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;
+            }
+            return !(d%10)
+        };
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..45733c9f8ff4623727ba757c88f0cd92ad346f21
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js
@@ -0,0 +1,41 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function() {
+        'use strict';
+
+        function resultWrapper(isValid, isPotentiallyValid) {
+            return {
+                isValid: isValid,
+                isPotentiallyValid: isPotentiallyValid
+            };
+        }
+
+        /**
+         * CVV number validation
+         * validate digit count fot CVV code
+         */
+        return function(value, maxLength) {
+            var DEFAULT_LENGTH = 3;
+            maxLength = maxLength || DEFAULT_LENGTH;
+
+            if (!/^\d*$/.test(value)) {
+                return resultWrapper(false, false);
+            }
+            if (value.length === maxLength) {
+                return resultWrapper(true, true);
+            }
+            if (value.length < maxLength) {
+                return resultWrapper(false, true);
+            }
+            if (value.length > maxLength) {
+                return resultWrapper(false, false);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7266a282740c6eb258839a7746bf57dbb1b329b
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'mageUtils',
+        'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date',
+        'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',
+        'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator'
+    ],
+    function(utils, parseDate, expirationMonth, expirationYear) {
+        'use strict';
+
+        function resultWrapper(isValid, isPotentiallyValid, month, year) {
+            return {
+                isValid: isValid,
+                isPotentiallyValid: isPotentiallyValid,
+                month: month,
+                year: year
+            };
+        }
+
+        return function(value) {
+            var date,
+                monthValid,
+                yearValid;
+
+            if (utils.isEmpty(value)) {
+                return resultWrapper(false, false, null, null);
+            }
+
+            value = value.replace(/^(\d\d) (\d\d(\d\d)?)$/, '$1/$2');
+            date = parseDate(value);
+            monthValid = expirationMonth(date.month);
+            yearValid = expirationYear(date.year);
+
+            if (monthValid.isValid && yearValid.isValid) {
+                return resultWrapper(true, true, date.month, date.year);
+            }
+
+            if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) {
+                return resultWrapper(false, true, null, null);
+            }
+
+            return resultWrapper(false, false, null, null);
+        }
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..c41ad14a459dbe7f788b8b0e21dd07a62150561c
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js
@@ -0,0 +1,41 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function () {
+        'use strict';
+
+        function resultWrapper(isValid, isPotentiallyValid) {
+            return {
+                isValid: isValid,
+                isPotentiallyValid: isPotentiallyValid
+            };
+        }
+
+        return function (value) {
+            var month,
+                monthValid;
+
+            if ((value.replace(/\s/g, '') === '') || (value === '0')) {
+                return resultWrapper(false, true);
+            }
+
+            if (!/^\d*$/.test(value)) {
+                return resultWrapper(false, false);
+            }
+
+            if (isNaN(value)) {
+                return resultWrapper(false, false);
+            }
+
+            month = parseInt(value, 10);
+            monthValid = month > 0 && month < 13;
+
+            return resultWrapper(monthValid, monthValid);
+        };
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..132c8dc42e9f2675647eb4112d09100fae84f7dd
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js
@@ -0,0 +1,42 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function() {
+        'use strict';
+
+        function resultWrapper(isValid, isPotentiallyValid) {
+            return {
+                isValid: isValid,
+                isPotentiallyValid: isPotentiallyValid
+            };
+        }
+
+        return function(value) {
+            var currentYear = new Date().getFullYear(),
+                len = value.length,
+                valid,
+                expMaxLifetime = 19;
+
+            if (value.replace(/\s/g, '') === '') {
+                return resultWrapper(false, true);
+            }
+
+            if (!/^\d*$/.test(value)) {
+                return resultWrapper(false, false);
+            }
+
+            if (len !== 4) {
+                return resultWrapper(false, true);
+            }
+
+            value = parseInt(value, 10);
+            valid = value >= currentYear && value <= currentYear + expMaxLifetime;
+            return resultWrapper(valid, valid);
+        };
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js
new file mode 100644
index 0000000000000000000000000000000000000000..119bfa698732ecb0bf8895dad4ec75d8edeac063
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js
@@ -0,0 +1,32 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [],
+    function() {
+        'use strict';
+        return function(value) {
+            var month, len;
+
+            if (value.match('/')) {
+                value = value.split(/\s*\/\s*/g);
+
+                return {
+                    month: value[0],
+                    year: value.slice(1).join()
+                };
+            }
+
+            len = (value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3) ? 2 : 1;
+            month = value.substr(0, len);
+
+            return {
+                month: month,
+                year: value.substr(month.length, 4)
+            };
+        }
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..660f3e3c0471f40d168481723d316bfcf792c0ed
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js
@@ -0,0 +1,74 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define([
+            'jquery',
+            'Magento_Payment/js/model/credit-card-validation/cvv-validator',
+            'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',
+            'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator',
+            'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',
+            'Magento_Payment/js/model/credit-card-validation/credit-card-data'
+        ], factory);
+    } else {
+        factory(jQuery);
+    }
+}(function ($, cvvValidator, creditCardNumberValidator, expirationDateValidator, monthValidator, creditCardData) {
+    "use strict";
+
+    $.each({
+        'validate-card-number': [
+            /**
+             * Validate credit card number based on mod 10
+             * @param number - credit card number
+             * @return {boolean}
+             */
+            function (number) {
+                return creditCardNumberValidator(number).isValid;
+            },
+            'Please enter a valid credit card number.'
+        ],
+        'validate-card-date': [
+            /**
+             * Validate credit card number based on mod 10
+             * @param date - month
+             * @return {boolean}
+             */
+                function (date) {
+                return monthValidator(date).isValid;
+            },
+            'Incorrect credit card expiration month.'
+        ],
+        'validate-card-cvv': [
+            /**
+             * Validate credit card number based on mod 10
+             * @param cvv - month
+             * @return {boolean}
+             */
+                function (cvv) {
+                var maxLength = creditCardData.creditCard ? creditCardData.creditCard.code.size : 3;
+                return cvvValidator(cvv, maxLength).isValid;
+            },
+            'Please enter a valid credit card verification number.'
+        ],
+        'validate-card-year': [
+            /**
+             * Validate credit card number based on mod 10
+             * @param date - month
+             * @return {boolean}
+             */
+                function (date) {
+                return monthValidator(date).isValid;
+            },
+            'Incorrect credit card expiration year.'
+        ]
+
+    }, function (i, rule) {
+        rule.unshift(i);
+        $.validator.addMethod.apply($.validator, rule);
+    });
+}));
\ No newline at end of file
diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js
index 8e6e53f0ae7e5061322e0a525bc733c057d938e2..5c1abc1e3c75b1721a889badee6e364009bd448f 100644
--- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js
+++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js
@@ -7,21 +7,24 @@
 define(
     [
         'underscore',
-        'uiComponent',
+        'Magento_Checkout/js/view/payment/default',
+        'Magento_Payment/js/model/credit-card-validation/credit-card-data',
+        'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',
         'mage/translate'
     ],
-    function (_, component, $t) {
-        return component.extend({
+    function (_, Component, creditCardData, cardNumberValidator, $t) {
+        return Component.extend({
             defaults: {
-                template: 'Magento_Payment/payment/cc-form',
                 creditCardType: '',
                 creditCardExpYear: '',
                 creditCardExpMonth: '',
                 creditCardNumber: '',
                 creditCardSsStartMonth: '',
                 creditCardSsStartYear: '',
-                creditCardVerificationNumber: ''
+                creditCardVerificationNumber: '',
+                selectedCardType: null
             },
+
             initObservable: function () {
                 this._super()
                     .observe([
@@ -31,15 +34,62 @@ define(
                         'creditCardNumber',
                         'creditCardVerificationNumber',
                         'creditCardSsStartMonth',
-                        'creditCardSsStartYear'
+                        'creditCardSsStartYear',
+                        'selectedCardType'
                     ]);
                 return this;
             },
+
+            initialize: function() {
+                var self = this;
+                this._super();
+
+                //Set credit card number to credit card data object
+                this.creditCardNumber.subscribe(function(value) {
+                    var result;
+                    self.selectedCardType(null);
+
+                    if (value == '' || value == null) {
+                        return false;
+                    }
+                    result = cardNumberValidator(value);
+
+                    if (!result.isPotentiallyValid && !result.isValid) {
+                        return false;
+                    }
+                    if (result.card !== null) {
+                        self.selectedCardType(result.card.type);
+                        creditCardData.creditCard = result.card;
+                    }
+
+                    if (result.isValid) {
+                        creditCardData.creditCardNumber = value;
+                        self.creditCardType(result.card.type);
+                    }
+                });
+
+                //Set expiration year to credit card data object
+                this.creditCardExpYear.subscribe(function(value) {
+                    creditCardData.expirationYear = value;
+                });
+
+                //Set expiration month to credit card data object
+                this.creditCardExpMonth.subscribe(function(value) {
+                    creditCardData.expirationYear = value;
+                });
+
+                //Set cvv code to credit card data object
+                this.creditCardVerificationNumber.subscribe(function(value) {
+                    creditCardData.cvvCode = value;
+                });
+            },
+
             getCode: function() {
                 return 'cc';
             },
             getData: function() {
                 return {
+                    'method': this.item.method,
                     'cc_type': this.creditCardType(),
                     'cc_exp_year': this.creditCardExpYear(),
                     'cc_exp_month': this.creditCardExpMonth(),
diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js
similarity index 90%
rename from app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js
rename to app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js
index 5349dab7b4d93202a4dec1f9924de97d0c564645..83a229af3bfbea8019ea0897b206b91f768377ee 100644
--- a/app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js
+++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js
@@ -6,12 +6,12 @@
 /*global define*/
 define(
     [
-        'uiComponent'
+        'Magento_Payment/js/view/payment/cc-form'
     ],
     function (Component) {
         return Component.extend({
             defaults: {
-                template: 'Magento_Payment/review/actions/iframe'
+                template: 'Magento_Payment/payment/iframe'
             },
             getSource: function () {
                 return window.checkoutConfig.payment.iframe.source[this.getCode()];
@@ -34,9 +34,6 @@ define(
             getCardFieldsMap: function() {
                 return window.checkoutConfig.payment.iframe.cardFieldsMap[this.getCode()];
             },
-            getCode: function() {
-                return this.index;
-            },
             originalPlaceOrder: function(parent) {
                 return parent.placeOrder.bind(parent);
             },
diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js
new file mode 100644
index 0000000000000000000000000000000000000000..72c249027684b153892f992c3ce14cdd47aa84ad
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'Magento_Checkout/js/view/payment/default',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function (Component, quote) {
+        'use strict';
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Payment/payment/free'
+            },
+
+            /** Returns is method available */
+            isAvailable: function() {
+                return quote.totals().grand_total <= 0;
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js
new file mode 100644
index 0000000000000000000000000000000000000000..cff4f3810842e9ce77510d4b95da261e9475392b
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/payment/renderer-list'
+    ],
+    function (
+        Component,
+        rendererList
+    ) {
+        'use strict';
+        rendererList.push(
+            {
+                type: 'free',
+                component: 'Magento_Payment/js/view/payment/method-renderer/free-method'
+            }
+        );
+        /** Add view logic here if needed */
+        return Component.extend({});
+    }
+);
\ No newline at end of file
diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html
index 96fd1446d2cf33028c3f63f07d6400b1ef82a342..49d1d57f958bdd938284aaeaf11abf1ca926fb3d 100644
--- a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html
+++ b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html
@@ -4,20 +4,36 @@
  * See COPYING.txt for license details.
  */
 -->
+
 <fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}">
     <!-- ko if: (isShowLegend())-->
-    <legend class="legend"><span><!-- ko text: $t('Credit Card Information')--><!-- /ko --></span></legend><br />
+    <legend class="legend">
+        <span><!-- ko text: $t('Credit Card Information')--><!-- /ko --></span>
+    </legend><br />
     <!-- /ko -->
     <div class="field type required">
         <label data-bind="attr: {for: getCode() + '_cc_type'}" class="label">
             <span><!-- ko text: $t('Credit Card Type')--><!-- /ko --></span>
         </label>
         <div class="control">
-            <select name="payment[cc_type]" class="select"
-                data-bind="attr: {id: getCode() + '_cc_type', 'data-container': getCode() + '-cc-type', 'data-validate': JSON.stringify({required:true, 'validate-cc-type-select':'#' + getCode() + '_cc_number'})},
-                mageInit: {creditCardType:{creditCardTypeContainer:'#' + getCode() + '_cc_type_ss_div'}},
-                enable: isActive($parents), options: getCcAvailableTypesValues(), optionsValue: 'value', optionsText: 'type', optionsCaption: $t('--Please Select--'), value: creditCardType">
-            </select>
+            <ul class="credit-card-types">
+                <!-- ko foreach: {data: getCcAvailableTypesValues(), as: 'item'} -->
+                <li class="item" data-bind="css: {_active: $parent.selectedCardType() == item.value} ">
+                    <!-- if picture -->
+                    <img data-bind="attr: {
+                        'src': 'Magento_Payment::images/cc/'+ item.value + '.png',
+                        'alt': item.type
+                        }">
+                    <!-- if NOpicture -->
+                    <span><!-- ko text: item.type --><!-- /ko --></span>
+                </li>
+                <!--/ko-->
+            </ul>
+            <input type="hidden"
+                   name="payment[cc_number]"
+                   class="input-text"
+                   value=""
+                   data-bind="attr: {id: getCode() + '_cc_type'}, value: creditCardType">
         </div>
     </div>
     <div class="field number required">
@@ -25,9 +41,15 @@
             <span><!-- ko text: $t('Credit Card Number')--><!-- /ko --></span>
         </label>
         <div class="control">
-            <input type="number" name="payment[cc_number]" class="input-text" value=""
-                data-bind="attr: {id: getCode() + '_cc_number', title: $t('Credit Card Number'), 'data-container': getCode() + '-cc-number', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})},
-                enable: isActive($parents), value: creditCardNumber"/>
+            <input type="text" name="payment[cc_number]" class="input-text" value=""
+                   data-bind="attr: {
+                                    id: getCode() + '_cc_number',
+                                    title: $t('Credit Card Number'),
+                                    'data-container': getCode() + '-cc-number',
+                                    'data-validate': JSON.stringify({'required-number':true, 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})},
+                              enable: isActive($parents),
+                              value: creditCardNumber,
+                              valueUpdate: 'keyup' "/>
         </div>
     </div>
     <div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}">
@@ -38,17 +60,29 @@
             <div class="fields group group-2">
                 <div class="field no-label month">
                     <div class="control">
-                        <select  name="payment[cc_exp_month]" class="select month"
-                            data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})},
-                            enable: isActive($parents), options: getCcMonthsValues(), optionsValue: 'value', optionsText: 'month', optionsCaption: $t('Month'), value: creditCardExpMonth">
+                        <select  name="payment[cc_exp_month]"
+                                 class="select select-month"
+                                 data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})},
+                                            enable: isActive($parents),
+                                            options: getCcMonthsValues(),
+                                            optionsValue: 'value',
+                                            optionsText: 'month',
+                                            optionsCaption: $t('Month'),
+                                            value: creditCardExpMonth">
                         </select>
                     </div>
                 </div>
                 <div class="field no-label year">
                     <div class="control">
-                        <select name="payment[cc_exp_year]" class="select year"
-                            data-bind="attr: {id: getCode() + '_expiration_yr', 'data-container': getCode() + '-cc-year', 'data-validate': JSON.stringify({required:true})},
-                            enable: isActive($parents), options: getCcYearsValues(), optionsValue: 'value', optionsText: 'year', optionsCaption: $t('Year'), value: creditCardExpYear">
+                        <select name="payment[cc_exp_year]"
+                                class="select select-year"
+                                data-bind="attr: {id: getCode() + '_expiration_yr', 'data-container': getCode() + '-cc-year', 'data-validate': JSON.stringify({required:true})},
+                                           enable: isActive($parents),
+                                           options: getCcYearsValues(),
+                                           optionsValue: 'value',
+                                           optionsText: 'year',
+                                           optionsCaption: $t('Year'),
+                                           value: creditCardExpYear">
                         </select>
                     </div>
                 </div>
@@ -60,11 +94,16 @@
         <label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label">
             <span><!-- ko text: $t('Card Verification Number')--><!-- /ko --></span>
         </label>
-        <div class="control">
-            <input type="number" class="input-text cvv" name="payment[cc_cid]" value=""
-                    data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-cvn':'#' + getCode() + '_cc_type'})}, enable: isActive($parents), value: creditCardVerificationNumber"/>
-            <div class="note">
-                <a href="#" class="action cvv" data-bind="attr: {title: $t('What is this?')}, mageInit:{'tooltip': {'content': getCvvImageHtml()}}"><span><!-- ko text: $t('What is this?')--><!-- /ko --></span></a>
+        <div class="control _with-tooltip">
+            <input type="text" class="input-text cvv" name="payment[cc_cid]" value=""
+                   data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-card-cvv':'#' + getCode() + '_cc_type'})},
+                             enable: isActive($parents),
+                             value: creditCardVerificationNumber"/>
+            <div class="field-tooltip toggle">
+                <span class="field-tooltip-action action-cvv" data-bind="attr: {title: $t('What is this?')}">
+                    <span><!-- ko text: $t('What is this?')--><!-- /ko --></span>
+                </span>
+                <div class="field-tooltip-content" data-bind="html: getCvvImageHtml()"></div>
             </div>
         </div>
     </div>
@@ -72,33 +111,55 @@
     <!-- ko if: (hasSsCardType())-->
     <div class="field switch solo required" data-bind="attr: {id: getCode() + '_cc_type_ss_div'}">
         <div class="nested">
-            <div class="field switch solo required">
-                <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"><span><!-- ko text: $t('Switch/Solo/Maestro Only')--><!-- /ko --></span></label>
+            <div class="field switch-solo required">
+                <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label">
+                    <span><!-- ko text: $t('Switch/Solo/Maestro Only')--><!-- /ko --></span>
+                </label>
             </div>
             <div class="field number required">
-                <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"><span><!-- ko text: $t('Issue Number')--><!-- /ko --></span></label>
+                <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label">
+                    <span><!-- ko text: $t('Issue Number')--><!-- /ko --></span>
+                </label>
                 <div class="control">
-                    <input type="text" name="payment[cc_ss_issue]" value="" class="input-text cvv" data-bind="attr: {id: getCode() + '_cc_issue', title: $t('Issue Number'), 'data-container': getCode() + '-cc-issue', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, enable: isActive($parents)"/>
+                    <input type="text" name="payment[cc_ss_issue]"
+                           value=""
+                           class="input-text cvv"
+                           data-bind="attr: {id: getCode() + '_cc_issue', title: $t('Issue Number'), 'data-container': getCode() + '-cc-issue', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, enable: isActive($parents)"/>
                 </div>
             </div>
 
             <div class="field date required">
-                <label data-bind="attr: {for: getCode() + '_start_month'}" class="label"><span><!-- ko text: $t('Start Date')--><!-- /ko --></span></label>
+                <label data-bind="attr: {for: getCode() + '_start_month'}" class="label">
+                    <span><!-- ko text: $t('Start Date')--><!-- /ko --></span>
+                </label>
                 <div class="control">
                     <div class="fields group group-2">
-                        <div class="field no-label">
+                        <div class="field no-label month">
                             <div class="control">
-                                <select name="payment[cc_ss_start_month]" class="select month"
+                                <select name="payment[cc_ss_start_month]"
+                                        class="select select-month"
                                         data-bind="attr: {id: getCode() + '_start_month', 'data-container': getCode() + '-cc-start-month', 'data-validate': JSON.stringify({'validate-cc-ukss':true})},
-                                        enable: isActive($parents), options: getCcMonthsValues(), optionsValue: 'value', optionsText: 'month', optionsCaption: $t('Month'), value: creditCardSsStartMonth">
+                                                  enable: isActive($parents),
+                                                  options: getCcMonthsValues(),
+                                                  optionsValue: 'value',
+                                                  optionsText: 'month',
+                                                  optionsCaption: $t('Month'),
+                                                  value: creditCardSsStartMonth">
                                 </select>
                             </div>
                         </div>
-                        <div class="field no-label">
+                        <div class="field no-label year">
                             <div class="control">
-                                <select name="payment[cc_ss_start_year]" class="select year"
-                                        data-bind="attr: {id: getCode() + '_start_year', 'data-container': getCode() + '-cc-start-year', 'data-validate': JSON.stringify({'validate-cc-ukss':true})},
-                                        enable: isActive($parents), options: getSsStartYearsValues(), optionsValue: 'value', optionsText: 'year', optionsCaption: $t('Year'), value: creditCardSsStartYear">
+                                <select name="payment[cc_ss_start_year]"
+                                        class="select select-year"
+                                        data-bind="attr: {id: getCode() + '_start_year', 'data-container': getCode() + '-cc-start-year',
+                                        'data-validate': JSON.stringify({'validate-cc-ukss':true})},
+                                        enable: isActive($parents),
+                                        options: getSsStartYearsValues(),
+                                        optionsValue: 'value',
+                                        optionsText: 'year',
+                                        optionsCaption: $t('Year'),
+                                        value: creditCardSsStartYear">
                                 </select>
                             </div>
                         </div>
diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/free.html b/app/code/Magento/Payment/view/frontend/web/template/payment/free.html
new file mode 100644
index 0000000000000000000000000000000000000000..fb33eafd3cfbb59e8fffe9983692fe3d2fad1050
--- /dev/null
+++ b/app/code/Magento/Payment/view/frontend/web/template/payment/free.html
@@ -0,0 +1,36 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}, visible: isAvailable()">
+    <div class="payment-method-title field choice">
+        <input type="radio"
+               name="payment[method]"
+               class="radio"
+               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
+        <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
+    </div>
+    <div class="payment-method-content">
+        <div class="payment-method-billing-address">
+            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
+            <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <div class="checkout-agreements-block">
+            <!-- ko foreach: $parent.getRegion('before-place-order') -->
+                <!-- ko template: getTemplate() --><!-- /ko -->
+            <!--/ko-->
+        </div>
+        <div class="actions-toolbar">
+            <div class="primary">
+                <button class="action primary checkout"
+                        type="submit"
+                        data-bind="click: placeOrder, attr: {title: $t('Place Order')}">
+                    <span data-bind="text: $t('Place Order')"></span>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
diff --git a/app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html b/app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html
similarity index 91%
rename from app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html
rename to app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html
index df5212f51e03f9a2b54332ca117c38d7abb0d5ba..2fec488a491cb1787d622de53a3c4764c404c4c4 100644
--- a/app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html
+++ b/app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html
@@ -21,6 +21,11 @@
     <!-- ko template: getTemplate() --><!-- /ko -->
 <!-- /ko -->
 </form>
+<div class="checkout-agreements-block">
+    <!-- ko foreach: $parent.getRegion('before-place-order') -->
+        <!-- ko template: getTemplate() --><!-- /ko -->
+    <!--/ko-->
+</div>
 <div class="actions-toolbar" id="review-buttons-container">
     <div class="primary">
         <button data-role="review-save" type="submit"
diff --git a/app/code/Magento/Payment/view/frontend/web/transparent.js b/app/code/Magento/Payment/view/frontend/web/transparent.js
index 6394cf38fee739a4667b1845efc4e11f4582b913..2060ca7c8ea5e5a344329c0e48ad935859f77f8a 100644
--- a/app/code/Magento/Payment/view/frontend/web/transparent.js
+++ b/app/code/Magento/Payment/view/frontend/web/transparent.js
@@ -6,12 +6,14 @@
 define([
     "jquery",
     "mage/template",
-    "jquery/ui"
+    "jquery/ui",
+    "Magento_Payment/js/model/credit-card-validation/validator"
 ], function($, mageTemplate){
-    "use strict";
+    'use strict';
 
     $.widget('mage.transparent', {
         options: {
+            context: null,
             placeOrderSelector: '[data-role="review-save"]',
             paymentFormSelector: '#co-payment-form',
             updateSelectorPrefix: '#checkout-',
@@ -34,9 +36,24 @@ define([
 
         _create: function() {
             this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl);
-            $(this.options.placeOrderSelector)
-                .off('click')
-                .on('click', $.proxy(this._placeOrderHandler, this));
+
+            if (this.options.context) {
+                this.options.context.setPlaceOrderHandler($.proxy(this._orderSave, this));
+                this.options.context.setValidateHandler($.proxy(this._validateHandler, this));
+            } else {
+                $(this.options.placeOrderSelector)
+                    .off('click')
+                    .on('click', $.proxy(this._placeOrderHandler, this));
+            }
+        },
+
+        /**
+         * handler for credit card validation
+         * @return {Boolean}
+         * @private
+         */
+        _validateHandler: function() {
+            return (this.element.validation && this.element.validation('isValid'));
         },
 
         /**
@@ -45,7 +62,7 @@ define([
          * @private
          */
         _placeOrderHandler: function() {
-            if (this.element.validation && this.element.validation('isValid')) {
+            if (this._validateHandler()) {
                 this._orderSave();
             }
             return false;
@@ -65,7 +82,7 @@ define([
                 '[data-container="' + this.options.gateway + '-cc-type"]'
             ).val();
 
-            $.ajax({
+            return $.ajax({
                 url: this.options.orderSaveUrl,
                 type: 'post',
                 context: this,
@@ -110,7 +127,6 @@ define([
                     inputs: data
                 }
             });
-
             $(tmpl).appendTo($(iframeSelector)).submit();
         },
 
diff --git a/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml
similarity index 97%
rename from app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml
rename to app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml
index 80989653fc335a36a6ebf2298af1ebab84a33a53..6d8cd9506b3907770cbb9e49e44996503a4337bd 100644
--- a/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml
@@ -5,6 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
+<!-- TODO remove this file as soon as enhanced checkout is implemented -->
 <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>
         <referenceBlock name="checkout.root">
diff --git a/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php b/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php
deleted file mode 100644
index a721e539ddf505abedd92f68433c26e917833a75..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Api;
-
-interface AddressDetailsManagementInterface
-{
-    /**
-     * Save billing and shipping addresses
-     *
-     * @param int $cartId
-     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
-     * @param \Magento\Quote\Api\Data\AddressInterface $shippingAddress
-     * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface|null $additionalData
-     * @param string|null $checkoutMethod
-     * @return \Magento\Quote\Api\Data\AddressDetailsInterface
-     */
-    public function saveAddresses(
-        $cartId,
-        \Magento\Quote\Api\Data\AddressInterface $billingAddress,
-        \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null,
-        \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null,
-        $checkoutMethod = null
-    );
-}
diff --git a/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php b/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php
deleted file mode 100644
index 843d5faa1e38723531baed4c6f1ad6c564f6b674..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Api\Data;
-
-interface AddressDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
-{
-    /**#@+
-     * Constants defined for keys of array, makes typos less likely
-     */
-    const SHIPPING_METHODS = 'shipping_methods';
-
-    const PAYMENT_METHODS = 'payment_methods';
-
-    const FORMATTED_BILLING_ADDRESS = 'formatted_billing_address';
-
-    const FORMATTED_SHIPPING_ADDRESS = 'formatted_shipping_address';
-
-    const TOTALS = 'totals';
-
-    /**#@-*/
-
-    /**
-     * @return \Magento\Quote\Api\Data\ShippingMethodInterface[]
-     */
-    public function getShippingMethods();
-
-    /**
-     * @return \Magento\Quote\Api\Data\PaymentMethodInterface[]
-     */
-    public function getPaymentMethods();
-
-    /**
-     * @param \Magento\Quote\Api\Data\ShippingMethodInterface[] $shippingMethods
-     * @return $this
-     */
-    public function setShippingMethods($shippingMethods);
-
-    /**
-     * @param \Magento\Quote\Api\Data\PaymentMethodInterface[] $paymentMethods
-     * @return $this
-     */
-    public function setPaymentMethods($paymentMethods);
-
-    /**
-     * @return string|null
-     */
-    public function getFormattedShippingAddress();
-
-    /**
-     * @return string
-     */
-    public function getFormattedBillingAddress();
-
-    /**
-     * @param string $formattedBillingAddress
-     * @return $this
-     */
-    public function setFormattedBillingAddress($formattedBillingAddress);
-
-    /**
-     * @param string $formattedShippingAddress
-     * @return $this
-     */
-    public function setFormattedShippingAddress($formattedShippingAddress);
-
-
-    /**
-     * Retrieve existing extension attributes object or create a new one.
-     *
-     * @return \Magento\Quote\Api\Data\AddressDetailsExtensionInterface|null
-     */
-    public function getExtensionAttributes();
-
-    /**
-     * Set an extension attributes object.
-     *
-     * @param \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes
-    );
-
-    /**
-     * @return \Magento\Quote\Api\Data\TotalsInterface
-     */
-    public function getTotals();
-
-    /**
-     * @param \Magento\Quote\Api\Data\TotalsInterface $totals
-     * @return $this
-     */
-    public function setTotals($totals);
-}
diff --git a/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php b/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ab64d64cf93fe303ff96b15eccceeef0a898045
--- /dev/null
+++ b/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Api\Data;
+
+/**
+ * Interface TotalsInterface
+ * @api
+ */
+interface TotalSegmentInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const CODE  = 'code';
+    const TITLE = 'title';
+    const VALUE = 'value';
+    const AREA  = 'area';
+    /**#@-*/
+
+    /**
+     * Total code
+     *
+     * @return string
+     */
+    public function getCode();
+
+    /**
+     * Set total code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setCode($code);
+
+    /**
+     * Get total title
+     *
+     * @return string|null
+     */
+    public function getTitle();
+
+    /**
+     * Set total title
+     *
+     * @param string|null $title
+     * @return $this
+     */
+    public function setTitle($title = null);
+
+    /**
+     * Get total value
+     *
+     * @return float
+     */
+    public function getValue();
+
+    /**
+     * Set total value
+     *
+     * @param float $value
+     * @return $this
+     */
+    public function setValue($value);
+
+    /**
+     * Get display area code.
+     *
+     * @return string|null
+     */
+    public function getArea();
+
+    /**
+     * Set display area code
+     *
+     * @param string|null $area
+     * @return $this
+     */
+    public function setArea($area = null);
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Quote\Api\Data\TotalSegmentExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Quote/Api/Data/TotalsInterface.php b/app/code/Magento/Quote/Api/Data/TotalsInterface.php
index 5e8d5349ba1c13ee7c06603ba275131f570649fb..d11e5260c459ac3c706f5f347c91f236384785d9 100644
--- a/app/code/Magento/Quote/Api/Data/TotalsInterface.php
+++ b/app/code/Magento/Quote/Api/Data/TotalsInterface.php
@@ -42,6 +42,8 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
 
     const KEY_BASE_TAX_AMOUNT = 'base_tax_amount';
 
+    const KEY_WEEE_TAX_APPLIED_AMOUNT = 'weee_tax_applied_amount';
+
     const KEY_SHIPPING_TAX_AMOUNT = 'shipping_tax_amount';
 
     const KEY_BASE_SHIPPING_TAX_AMOUNT = 'base_shipping_tax_amount';
@@ -58,8 +60,14 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
 
     const KEY_QUOTE_CURRENCY_CODE = 'quote_currency_code';
 
+    const KEY_COUPON_CODE = 'coupon_code';
+
     const KEY_ITEMS = 'items';
 
+    const KEY_TOTAL_SEGMENTS = 'total_segments';
+
+    const KEY_ITEMS_QTY = 'items_qty';
+
     /**#@-*/
 
     /**
@@ -272,6 +280,21 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
      */
     public function setBaseTaxAmount($baseTaxAmount);
 
+    /**
+     * Returns the total weee tax applied amount in quote currency.
+     *
+     * @return float Item weee tax applied amount in quote currency.
+     */
+    public function getWeeeTaxAppliedAmount();
+
+    /**
+     * Sets the total weee tax applied amount in quote currency.
+     *
+     * @param float $weeeTaxAppliedAmount
+     * @return $this
+     */
+    public function setWeeeTaxAppliedAmount($weeeTaxAppliedAmount);
+
     /**
      * Get shipping tax amount in quote currency
      *
@@ -392,6 +415,36 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
      */
     public function setQuoteCurrencyCode($quoteCurrencyCode);
 
+    /**
+     * Get applied coupon code
+     *
+     * @return string|null
+     */
+    public function getCouponCode();
+
+    /**
+     * Set applied coupon code
+     *
+     * @param string $couponCode
+     * @return $this
+     */
+    public function setCouponCode($couponCode);
+
+    /**
+     * Get items qty
+     *
+     * @return int||null
+     */
+    public function getItemsQty();
+
+    /**
+     * Set items qty
+     *
+     * @param int $itemsQty
+     * @return $this
+     */
+    public function setItemsQty($itemsQty = null);
+
     /**
      * Get totals by items
      *
@@ -407,6 +460,21 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
      */
     public function setItems(array $items = null);
 
+    /**
+     * Get dynamically calculated totals
+     *
+     * @return \Magento\Quote\Api\Data\TotalSegmentInterface[]
+     */
+    public function getTotalSegments();
+
+    /**
+     * Set dynamically calculated totals
+     *
+     * @param \Magento\Quote\Api\Data\TotalSegmentInterface[] $totals
+     * @return $this
+     */
+    public function setTotalSegments($totals = []);
+
     /**
      * Retrieve existing extension attributes object or create a new one.
      *
diff --git a/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php b/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php
deleted file mode 100644
index a4eea1464145c613a5c06acdfb164bd9de819527..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Api;
-
-interface GuestAddressDetailsManagementInterface
-{
-    /**
-     * Save billing and shipping addresses for guest.
-     *
-     * @param string $cartId
-     * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
-     * @param \Magento\Quote\Api\Data\AddressInterface|null $shippingAddress
-     * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface|null $additionalData
-     * @return \Magento\Quote\Api\Data\AddressDetailsInterface
-     */
-    public function saveAddresses(
-        $cartId,
-        \Magento\Quote\Api\Data\AddressInterface $billingAddress,
-        \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null,
-        \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null
-    );
-}
diff --git a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php
index 10bd639cf93c5e30ddb57fde13595a67f2a5f945..29c4a07ca8d46c9d85d9f1a901c9303a86eaec3e 100644
--- a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php
+++ b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php
@@ -45,4 +45,13 @@ interface GuestShippingMethodManagementInterface
      * @throws \Magento\Framework\Exception\StateException The shipping address is not set.
      */
     public function getList($cartId);
+
+    /**
+     * Estimate shipping
+     *
+     * @param string $cartId The shopping cart ID.
+     * @param \Magento\Quote\Api\Data\EstimateAddressInterface $address The estimate address
+     * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods.
+     */
+    public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address);
 }
diff --git a/app/code/Magento/Quote/Model/AddressDetails.php b/app/code/Magento/Quote/Model/AddressDetails.php
deleted file mode 100644
index ba3e3bf697708ee8c0d9fc6c0b5c161c6adb3ab3..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Model/AddressDetails.php
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Model;
-
-/**
- * @codeCoverageIgnoreStart
- */
-class AddressDetails extends \Magento\Framework\Model\AbstractExtensibleModel implements
-    \Magento\Quote\Api\Data\AddressDetailsInterface
-{
-    //@codeCoverageIgnoreStart
-    /**
-     * @{inheritdoc}
-     */
-    public function getShippingMethods()
-    {
-        return $this->getData(self::SHIPPING_METHODS);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function setShippingMethods($shippingMethods)
-    {
-        return $this->setData(self::SHIPPING_METHODS, $shippingMethods);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function getPaymentMethods()
-    {
-        return $this->getData(self::PAYMENT_METHODS);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function setPaymentMethods($paymentMethods)
-    {
-        return $this->setData(self::PAYMENT_METHODS, $paymentMethods);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function getFormattedShippingAddress()
-    {
-        return $this->getData(self::FORMATTED_SHIPPING_ADDRESS);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function getFormattedBillingAddress()
-    {
-        return $this->getData(self::FORMATTED_BILLING_ADDRESS);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function setFormattedBillingAddress($formattedBillingAddress)
-    {
-        return $this->setData(self::FORMATTED_BILLING_ADDRESS, $formattedBillingAddress);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function setFormattedShippingAddress($formattedShippingAddress)
-    {
-        return $this->setData(self::FORMATTED_SHIPPING_ADDRESS, $formattedShippingAddress);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function getTotals()
-    {
-        return $this->getData(self::TOTALS);
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function setTotals($totals)
-    {
-        return $this->setData(self::TOTALS, $totals);
-    }
-    //@codeCoverageIgnoreEnd
-
-    /**
-     * {@inheritdoc}
-     *
-     * @return \Magento\Quote\Api\Data\AddressDetailsExtensionInterface|null
-     */
-    public function getExtensionAttributes()
-    {
-        return $this->_getExtensionAttributes();
-    }
-
-    /**
-     * {@inheritdoc}
-     *
-     * @param \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes
-    ) {
-        return $this->_setExtensionAttributes($extensionAttributes);
-    }
-}
diff --git a/app/code/Magento/Quote/Model/AddressDetailsManagement.php b/app/code/Magento/Quote/Model/AddressDetailsManagement.php
deleted file mode 100644
index 84c6492510a6d02f6b668612047585920dc1bb75..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Model/AddressDetailsManagement.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Model;
-
-use Magento\Quote\Api\CartTotalRepositoryInterface;
-use Magento\Quote\Model\AddressAdditionalDataProcessor;
-
-class AddressDetailsManagement implements \Magento\Quote\Api\AddressDetailsManagementInterface
-{
-    /**
-     * @var \Magento\Quote\Api\BillingAddressManagementInterface
-     */
-    protected $billingAddressManagement;
-
-    /**
-     * @var \Magento\Quote\Api\ShippingAddressManagementInterface
-     */
-    protected $shippingAddressManagement;
-
-    /**
-     * @var \Magento\Quote\Api\PaymentMethodManagementInterface
-     */
-    protected $paymentMethodManagement;
-
-    /**
-     * @var \Magento\Quote\Api\ShippingMethodManagementInterface
-     */
-    protected $shippingMethodManagement;
-
-    /**
-     * @var AddressDetailsFactory
-     */
-    protected $addressDetailsFactory;
-
-    /**
-     * @var AddressAdditionalDataProcessor
-     */
-    protected $dataProcessor;
-
-    /**
-     * @var QuoteRepository
-     */
-    protected $quoteRepository;
-
-    /**
-     * @var CartTotalRepositoryInterface
-     */
-    protected $cartTotalsRepository;
-
-    /**
-     * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement
-     * @param \Magento\Quote\Api\ShippingAddressManagementInterface $shippingAddressManagement
-     * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
-     * @param \Magento\Quote\Api\ShippingMethodManagementInterface $shippingMethodManagement
-     * @param AddressDetailsFactory $addressDetailsFactory
-     * @param AddressAdditionalDataProcessor $dataProcessor
-     * @param QuoteRepository $quoteRepository
-     * @param CartTotalRepositoryInterface $cartTotalsRepository
-     */
-    public function __construct(
-        \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement,
-        \Magento\Quote\Api\ShippingAddressManagementInterface $shippingAddressManagement,
-        \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement,
-        \Magento\Quote\Api\ShippingMethodManagementInterface $shippingMethodManagement,
-        \Magento\Quote\Model\AddressDetailsFactory $addressDetailsFactory,
-        AddressAdditionalDataProcessor $dataProcessor,
-        QuoteRepository $quoteRepository,
-        CartTotalRepositoryInterface $cartTotalsRepository
-    ) {
-        $this->billingAddressManagement = $billingAddressManagement;
-        $this->shippingAddressManagement = $shippingAddressManagement;
-        $this->paymentMethodManagement = $paymentMethodManagement;
-        $this->shippingMethodManagement = $shippingMethodManagement;
-        $this->addressDetailsFactory = $addressDetailsFactory;
-        $this->dataProcessor = $dataProcessor;
-        $this->quoteRepository = $quoteRepository;
-        $this->cartTotalsRepository = $cartTotalsRepository;
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function saveAddresses(
-        $cartId,
-        \Magento\Quote\Api\Data\AddressInterface $billingAddress,
-        \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null,
-        \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null,
-        $checkoutMethod = null
-    ) {
-        $this->billingAddressManagement->assign($cartId, $billingAddress);
-
-        /** @var \Magento\Quote\Api\Data\AddressDetailsInterface  $addressDetails */
-        $addressDetails = $this->addressDetailsFactory->create();
-        if ($shippingAddress) {
-            $this->shippingAddressManagement->assign($cartId, $shippingAddress);
-            $addressDetails->setFormattedShippingAddress(
-                $this->shippingAddressManagement->get($cartId)->format('html')
-            );
-            $addressDetails->setShippingMethods($this->shippingMethodManagement->getList($cartId));
-        }
-        $addressDetails->setPaymentMethods($this->paymentMethodManagement->getList($cartId));
-        if ($additionalData !== null) {
-            $this->dataProcessor->process($additionalData);
-        }
-        if ($checkoutMethod != null) {
-            $this->quoteRepository->save(
-                $this->quoteRepository->getActive($cartId)
-                    ->setCheckoutMethod($checkoutMethod)
-            );
-        }
-
-        $addressDetails->setFormattedBillingAddress(
-            $this->billingAddressManagement->get($cartId)->format('html')
-        );
-
-        $addressDetails->setTotals($this->cartTotalsRepository->get($cartId));
-        return $addressDetails;
-    }
-}
diff --git a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php
index 78bdf6da18569990d10fe5ac97330780b6bd14ed..88906928f9a72034da279a9d51c51e7f6944d1a3 100644
--- a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php
+++ b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php
@@ -11,6 +11,7 @@ use Magento\Quote\Api\CartTotalRepositoryInterface;
 use Magento\Catalog\Helper\Product\ConfigurationPool;
 use Magento\Framework\Api\DataObjectHelper;
 use Magento\Quote\Model\Cart\Totals\ItemConverter;
+use Magento\Quote\Api\CouponManagementInterface;
 
 /**
  * Cart totals data object.
@@ -39,24 +40,40 @@ class CartTotalRepository implements CartTotalRepositoryInterface
     /**
      * @var ConfigurationPool
      */
-    private $converter;
+    private $itemConverter;
+
+    /**
+     * @var CouponManagementInterface
+     */
+    protected $couponService;
+
+    /**
+     * @var TotalsConverter
+     */
+    protected $totalsConverter;
 
     /**
      * @param Api\Data\TotalsInterfaceFactory $totalsFactory
      * @param QuoteRepository $quoteRepository
      * @param DataObjectHelper $dataObjectHelper
+     * @param CouponManagementInterface $couponService
+     * @param TotalsConverter $totalsConverter
      * @param ItemConverter $converter
      */
     public function __construct(
         Api\Data\TotalsInterfaceFactory $totalsFactory,
         QuoteRepository $quoteRepository,
         DataObjectHelper $dataObjectHelper,
+        CouponManagementInterface $couponService,
+        TotalsConverter $totalsConverter,
         ItemConverter $converter
     ) {
         $this->totalsFactory = $totalsFactory;
         $this->quoteRepository = $quoteRepository;
         $this->dataObjectHelper = $dataObjectHelper;
-        $this->converter = $converter;
+        $this->couponService = $couponService;
+        $this->totalsConverter = $totalsConverter;
+        $this->itemConverter = $converter;
     }
 
     /**
@@ -82,11 +99,19 @@ class CartTotalRepository implements CartTotalRepositoryInterface
         $totals = $this->totalsFactory->create();
         $this->dataObjectHelper->populateWithArray($totals, $totalsData, '\Magento\Quote\Api\Data\TotalsInterface');
         $items = [];
+        $weeeTaxAppliedAmount = 0;
         foreach ($quote->getAllVisibleItems() as $index => $item) {
-            $items[$index] = $this->converter->modelToDataObject($item);
+            $items[$index] = $this->itemConverter->modelToDataObject($item);
+            $weeeTaxAppliedAmount += $item->getWeeeTaxAppliedAmount();
         }
+        $totals->setCouponCode($this->couponService->get($cartId));
+        $calculatedTotals = $this->totalsConverter->process($quote->getTotals());
+        $amount = $totals->getGrandTotal() - $totals->getTaxAmount();
+        $amount = $amount > 0 ? $amount : 0;
+        $totals->setGrandTotal($amount);
+        $totals->setTotalSegments($calculatedTotals);
         $totals->setItems($items);
-
+        $totals->setWeeeTaxAppliedAmount($weeeTaxAppliedAmount);
         return $totals;
     }
 }
diff --git a/app/code/Magento/Quote/Model/Cart/TotalSegment.php b/app/code/Magento/Quote/Model/Cart/TotalSegment.php
new file mode 100644
index 0000000000000000000000000000000000000000..203c8996f5fb2e55b92580cb86a41f93c0dba7e5
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Cart/TotalSegment.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Model\Cart;
+
+use Magento\Quote\Api\Data\TotalSegmentInterface;
+use Magento\Framework\Model\AbstractExtensibleModel;
+
+/**
+ * Extensible Cart Totals
+ *
+ * @codeCoverageIgnore
+ */
+class TotalSegment extends AbstractExtensibleModel implements TotalSegmentInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getCode()
+    {
+        return $this->getData(self::CODE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setCode($code)
+    {
+        return $this->setData(self::CODE, $code);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getValue()
+    {
+        return $this->getData(self::VALUE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setValue($value)
+    {
+        return $this->setData(self::VALUE, $value);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTitle()
+    {
+        return $this->getData(self::TITLE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setTitle($title = null)
+    {
+        return $this->setData(self::TITLE, $title);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArea()
+    {
+        return $this->getData(self::AREA);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setArea($area = null)
+    {
+        return $this->setData(self::AREA, $area);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExtensionAttributes(
+        \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes
+    ) {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Quote/Model/Cart/Totals.php b/app/code/Magento/Quote/Model/Cart/Totals.php
index 4612824f9cebb05dc6c4dedbb00bd8827e4019a3..742f27d4df5497d6adbafdf6e1dd7fd6ddb791c0 100644
--- a/app/code/Magento/Quote/Model/Cart/Totals.php
+++ b/app/code/Magento/Quote/Model/Cart/Totals.php
@@ -310,6 +310,27 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface
         return $this->setData(self::KEY_BASE_TAX_AMOUNT, $baseTaxAmount);
     }
 
+    /**
+     * Returns the total weee tax applied amount in quote currency.
+     *
+     * @return float Item weee tax applied amount in quote currency.
+     */
+    public function getWeeeTaxAppliedAmount()
+    {
+        return $this->getData(self::KEY_WEEE_TAX_APPLIED_AMOUNT);
+    }
+
+    /**
+     * Sets the total weee tax applied amount in quote currency.
+     *
+     * @param float $weeeTaxAppliedAmount
+     * @return $this
+     */
+    public function setWeeeTaxAppliedAmount($weeeTaxAppliedAmount)
+    {
+        return $this->setData(self::KEY_WEEE_TAX_APPLIED_AMOUNT, $weeeTaxAppliedAmount);
+    }
+
     /**
      * Get shipping tax amount in quote currency
      *
@@ -478,6 +499,43 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface
         return $this->setData(self::KEY_QUOTE_CURRENCY_CODE, $quoteCurrencyCode);
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function getCouponCode()
+    {
+        return $this->getData(self::KEY_COUPON_CODE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setCouponCode($couponCode)
+    {
+        return $this->setData(self::KEY_COUPON_CODE, $couponCode);
+    }
+
+    /**
+     * Get items qty
+     *
+     * @return int||null
+     */
+    public function getItemsQty()
+    {
+        return $this->getData(self::KEY_ITEMS_QTY);
+    }
+
+    /**
+     * Set items qty
+     *
+     * @param int $itemsQty
+     * @return $this
+     */
+    public function setItemsQty($itemsQty = null)
+    {
+        return $this->setData(self::KEY_ITEMS_QTY, $itemsQty);
+    }
+
     /**
      * Get totals by items
      *
@@ -499,6 +557,22 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface
         return $this->setData(self::KEY_ITEMS, $items);
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function getTotalSegments()
+    {
+        return $this->getData(self::KEY_TOTAL_SEGMENTS);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setTotalSegments($totals = [])
+    {
+        return $this->setData(self::KEY_TOTAL_SEGMENTS, $totals);
+    }
+
     /**
      * {@inheritdoc}
      *
diff --git a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php
index f569f8478b09d566bb3e65131436214d772a3b94..2b4792d2e44a2d884e8bf2f99b444abbc6a3ae43 100644
--- a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php
+++ b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php
@@ -86,10 +86,12 @@ class ItemConverter
     private function getFormattedOptionValue($item)
     {
         $optionsData = [];
+
+        /* @var $helper \Magento\Catalog\Helper\Product\Configuration */
+        $helper = $this->configurationPool->getByProductType('default');
+
         $options = $this->configurationPool->getByProductType($item->getProductType())->getOptions($item);
         foreach ($options as $index => $optionValue) {
-            /* @var $helper \Magento\Catalog\Helper\Product\Configuration */
-            $helper = $this->configurationPool->getByProductType('default');
             $params = [
                 'max_length' => 55,
                 'cut_replacer' => ' <a href="#" class="dots tooltip toggle" onclick="return false">...</a>'
diff --git a/app/code/Magento/Quote/Model/Cart/TotalsConverter.php b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php
new file mode 100644
index 0000000000000000000000000000000000000000..a041844c8ed5023dd4884459a0a95e222d3a882a
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Model\Cart;
+
+use Magento\Quote\Api\Data\TotalSegmentInterface;
+use Magento\Quote\Api\Data\TotalSegmentInterfaceFactory;
+
+/**
+ * Cart totals data objects converter.
+ */
+class TotalsConverter
+{
+    /**
+     * @var TotalSegmentInterfaceFactory
+     */
+    protected $factory;
+
+    /**
+     * @param TotalSegmentInterfaceFactory $factory
+     */
+    public function __construct(
+        TotalSegmentInterfaceFactory $factory
+    ) {
+        $this->factory = $factory;
+    }
+
+
+    /**
+     * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals
+     * @return \Magento\Quote\Api\Data\TotalSegmentInterface[]
+     */
+    public function process($addressTotals)
+    {
+        $data = [];
+        /** @var \Magento\Quote\Model\Quote\Address\Total $addressTotal */
+        foreach ($addressTotals as $addressTotal) {
+            $pureData = [
+                TotalSegmentInterface::CODE => $addressTotal->getCode(),
+                TotalSegmentInterface::TITLE => '',
+                TotalSegmentInterface::VALUE => $addressTotal->getValue(),
+                TotalSegmentInterface::AREA => $addressTotal->getArea(),
+            ];
+            if (is_object($addressTotal->getTitle())) {
+                $pureData[TotalSegmentInterface::TITLE] = $addressTotal->getTitle()->getText();
+            }
+            /** @var \Magento\Quote\Model\Cart\TotalSegment $total */
+            $total = $this->factory->create();
+            $total->setData($pureData);
+            $data[] = $total;
+        }
+        return $data;
+    }
+}
diff --git a/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php b/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php
deleted file mode 100644
index 2671a1ccb7665ebddf0b526f923090d6440c85f4..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Model\GuestCart;
-
-use Magento\Quote\Model\QuoteIdMaskFactory;
-
-class GuestAddressDetailsManagement implements \Magento\Quote\Api\GuestAddressDetailsManagementInterface
-{
-    /**
-     * @var \Magento\Quote\Api\AddressDetailsManagementInterface
-     */
-    protected $addressDetailsManagement;
-
-    /**
-     * @var QuoteIdMaskFactory
-     */
-    protected $quoteIdMaskFactory;
-
-    /**
-     * @param \Magento\Quote\Api\AddressDetailsManagementInterface $addressDetailsManagement
-     * @param QuoteIdMaskFactory $quoteIdMaskFactory
-     */
-    public function __construct(
-        \Magento\Quote\Api\AddressDetailsManagementInterface $addressDetailsManagement,
-        QuoteIdMaskFactory $quoteIdMaskFactory
-    ) {
-        $this->addressDetailsManagement = $addressDetailsManagement;
-        $this->quoteIdMaskFactory = $quoteIdMaskFactory;
-    }
-
-    /**
-     * @{inheritdoc}
-     */
-    public function saveAddresses(
-        $cartId,
-        \Magento\Quote\Api\Data\AddressInterface $billingAddress,
-        \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null,
-        \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null
-    ) {
-        $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
-        return $this->addressDetailsManagement->saveAddresses(
-            $quoteIdMask->getQuoteId(),
-            $billingAddress,
-            $shippingAddress,
-            $additionalData
-        );
-    }
-}
diff --git a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php
index 0687ca395de869030d97dbb780f474bf1ebc1733..6026ff8f8da0406a98dcc1beaf5212c816e81df6 100644
--- a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php
+++ b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php
@@ -69,4 +69,14 @@ class GuestShippingMethodManagement implements GuestShippingMethodManagementInte
         $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
         return $this->shippingMethodManagement->set($quoteIdMask->getQuoteId(), $carrierCode, $methodCode);
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address)
+    {
+        /** @var $quoteIdMask QuoteIdMask */
+        $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
+        return $this->shippingMethodManagement->estimateByAddress($quoteIdMask->getQuoteId(), $address);
+    }
 }
diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php
index 2dd5c4ca3add051bb7c518b939e8a1011e098a10..d55c9a70bb78a1fb496e4522c3639576dc935c62 100644
--- a/app/code/Magento/Quote/Model/Quote.php
+++ b/app/code/Magento/Quote/Model/Quote.php
@@ -801,33 +801,6 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C
         parent::beforeSave();
     }
 
-    /**
-     * Save related items
-     *
-     * @return $this
-     */
-    public function afterSave()
-    {
-        parent::afterSave();
-
-        if (null !== $this->_addresses) {
-            $this->getAddressesCollection()->save();
-        }
-
-        if (null !== $this->_items) {
-            $this->getItemsCollection()->save();
-        }
-
-        if (null !== $this->_payments) {
-            $this->getPaymentsCollection()->save();
-        }
-
-        if (null !== $this->_currentPayment) {
-            $this->getPayment()->save();
-        }
-        return $this;
-    }
-
     /**
      * Loading quote data by customer
      *
@@ -2496,6 +2469,46 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C
         return parent::_afterLoad();
     }
 
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function addressCollectionWasSet()
+    {
+        return null !== $this->_addresses;
+    }
+
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function itemsCollectionWasSet()
+    {
+        return null !== $this->_items;
+    }
+
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function paymentsCollectionWasSet()
+    {
+        return null !== $this->_payments;
+    }
+
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function currentPaymentWasSet()
+    {
+        return null !== $this->_currentPayment;
+    }
+
     /**
      * Return checkout method code
      *
diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php
index 2d091f08d1db37e3320f316540eaabce7d3895f9..1c525a5a80af525844fae490d2e4a6de55d9da47 100644
--- a/app/code/Magento/Quote/Model/Quote/Address.php
+++ b/app/code/Magento/Quote/Model/Quote/Address.php
@@ -423,23 +423,6 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements
             && $defaultBillingAddress == $defaultShippingAddress;
     }
 
-    /**
-     * Save child collections
-     *
-     * @return $this
-     */
-    public function afterSave()
-    {
-        parent::afterSave();
-        if (null !== $this->_items) {
-            $this->getItemsCollection()->save();
-        }
-        if (null !== $this->_rates) {
-            $this->getShippingRatesCollection()->save();
-        }
-        return $this;
-    }
-
     /**
      * Declare address quote model object
      *
@@ -538,7 +521,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements
     /**
      * Retrieve address items collection
      *
-     * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection
+     * @return \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
      */
     public function getItemsCollection()
     {
@@ -779,7 +762,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements
     /**
      * Retrieve collection of quote shipping rates
      *
-     * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection
+     * @return \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
      */
     public function getShippingRatesCollection()
     {
@@ -1114,6 +1097,26 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements
         $this->setId(null);
     }
 
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function itemsCollectionWasSet()
+    {
+        return null !== $this->_items;
+    }
+
+    /**
+     * Checks if it was set
+     *
+     * @return bool
+     */
+    public function shippingRatesCollectionWasSet()
+    {
+        return null !== $this->_rates;
+    }
+
     /**
      * Validate minimum amount
      *
@@ -1572,7 +1575,12 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements
      */
     public function getEmail()
     {
-        return $this->getData(self::KEY_EMAIL);
+        $email = $this->getData(self::KEY_EMAIL);
+        if (!$email) {
+            $email = $this->getQuote()->getCustomerEmail();
+            $this->setEmail($email);
+        }
+        return $email;
     }
 
     /**
diff --git a/app/code/Magento/Quote/Model/Quote/Address/Relation.php b/app/code/Magento/Quote/Model/Quote/Address/Relation.php
new file mode 100644
index 0000000000000000000000000000000000000000..f5e499d4dcd6f90c302aa27cf696ece18b630681
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Quote/Address/Relation.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Model\Quote\Address;
+
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
+
+class Relation implements RelationInterface
+{
+    /**
+     * Process object relations
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return void
+     */
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
+    {
+        /**
+         * @var $object \Magento\Quote\Model\Quote\Address
+         */
+        if ($object->itemsCollectionWasSet()) {
+            $object->getItemsCollection()->save();
+        }
+        if ($object->shippingRatesCollectionWasSet()) {
+            $object->getShippingRatesCollection()->save();
+        }
+    }
+}
diff --git a/app/code/Magento/Quote/Model/Quote/Item.php b/app/code/Magento/Quote/Model/Quote/Item.php
index 56ea708036533251670e39c59ed59569732de0b2..51694e5f68864efedb456e3628e2c0d66d2d557e 100644
--- a/app/code/Magento/Quote/Model/Quote/Item.php
+++ b/app/code/Magento/Quote/Model/Quote/Item.php
@@ -20,7 +20,6 @@ use Magento\Framework\Api\ExtensionAttributesFactory;
  * @method \Magento\Quote\Model\Quote\Item setCreatedAt(string $value)
  * @method string getUpdatedAt()
  * @method \Magento\Quote\Model\Quote\Item setUpdatedAt(string $value)
- * @method \Magento\Quote\Model\Quote\Item setProductId(int $value)
  * @method int getStoreId()
  * @method \Magento\Quote\Model\Quote\Item setStoreId(int $value)
  * @method int getParentItemId()
diff --git a/app/code/Magento/Quote/Model/Quote/Relation.php b/app/code/Magento/Quote/Model/Quote/Relation.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e131ae6b3b015bab21603b1b316a7d00d644337
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Quote/Relation.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Model\Quote;
+
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
+
+class Relation implements RelationInterface
+{
+    /**
+     * Process object relations
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return void
+     */
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
+    {
+        /**
+         * @var $object \Magento\Quote\Model\Quote
+         */
+        if ($object->addressCollectionWasSet()) {
+            $object->getAddressesCollection()->save();
+        }
+        if ($object->itemsCollectionWasSet()) {
+            $object->getItemsCollection()->save();
+        }
+        if ($object->paymentsCollectionWasSet()) {
+            $object->getPaymentsCollection()->save();
+        }
+        if ($object->currentPaymentWasSet()) {
+            $object->getPayment()->save();
+        }
+    }
+}
diff --git a/app/code/Magento/Quote/Model/QuoteAddressValidator.php b/app/code/Magento/Quote/Model/QuoteAddressValidator.php
index e92780f4056dba9f10a7158e9abd6cdae5470a4a..13df66e5f9f2513a5b176abb3c90d2b641a8ea88 100644
--- a/app/code/Magento/Quote/Model/QuoteAddressValidator.php
+++ b/app/code/Magento/Quote/Model/QuoteAddressValidator.php
@@ -13,7 +13,7 @@ class QuoteAddressValidator
      *
      * @var \Magento\Customer\Api\AddressRepositoryInterface
      */
-    protected $addressReporitory;
+    protected $addressRepository;
 
     /**
      * Customer repository.
@@ -39,7 +39,7 @@ class QuoteAddressValidator
         \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
         \Magento\Customer\Model\Session $customerSession
     ) {
-        $this->addressReporitory = $addressRepository;
+        $this->addressRepository = $addressRepository;
         $this->customerRepository = $customerRepository;
         $this->customerSession = $customerSession;
     }
@@ -67,7 +67,7 @@ class QuoteAddressValidator
         // validate address id
         if ($addressData->getId()) {
             try {
-                $address = $this->addressReporitory->getById($addressData->getId());
+                $address = $this->addressRepository->getById($addressData->getId());
             } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
                 throw new \Magento\Framework\Exception\NoSuchEntityException(
                     __('Invalid address id %1', $addressData->getId())
diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php
index f341b5894b9fb0a5a5da68f92c6a5b04e79fe2ca..3a75073c3960f5741e0e296ca212755b0021e4a5 100644
--- a/app/code/Magento/Quote/Model/QuoteManagement.php
+++ b/app/code/Magento/Quote/Model/QuoteManagement.php
@@ -297,11 +297,6 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
      */
     public function placeOrder($cartId, $agreements = null, PaymentInterface $paymentMethod = null)
     {
-        if (!$this->agreementsValidator->isValid($agreements)) {
-            throw new \Magento\Framework\Exception\CouldNotSaveException(
-                __('Please agree to all the terms and conditions before placing the order.')
-            );
-        }
         $quote = $this->quoteRepository->getActive($cartId);
         if ($paymentMethod) {
             $paymentMethod->setChecks([
@@ -333,6 +328,7 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
         $this->checkoutSession->setLastSuccessQuoteId($quote->getId());
         $this->checkoutSession->setLastOrderId($order->getId());
         $this->checkoutSession->setLastRealOrderId($order->getIncrementId());
+        $this->checkoutSession->setLastOrderStatus($order->getStatus());
 
         $this->eventManager->dispatch('checkout_submit_all_after', ['order' => $order, 'quote' => $quote]);
         return $order->getId();
diff --git a/app/code/Magento/Quote/Model/Resource/Quote.php b/app/code/Magento/Quote/Model/Resource/Quote.php
index c9ac55ba5414bb7a9368eb495b62bbdf952bad44..c942d9bd2f86a51a404b560f2be507413324d0e4 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote.php
@@ -8,7 +8,10 @@
 
 namespace Magento\Quote\Model\Resource;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
+use Magento\SalesSequence\Model\Manager;
 
 /**
  * Quote resource model
@@ -22,15 +25,19 @@ class Quote extends AbstractDb
 
     /**
      * @param \Magento\Framework\Model\Resource\Db\Context $context
+     * @param Snapshot $entitySnapshot,
+     * @param RelationComposite $entityRelationComposite,
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
      * @param null $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\SalesSequence\Model\Manager $sequenceManager,
+        Snapshot $entitySnapshot,
+        RelationComposite $entityRelationComposite,
+        Manager $sequenceManager,
         $resourcePrefix = null
     ) {
-        parent::__construct($context, $resourcePrefix);
+        parent::__construct($context, $entitySnapshot, $entityRelationComposite, $resourcePrefix);
         $this->sequenceManager = $sequenceManager;
     }
 
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address.php b/app/code/Magento/Quote/Model/Resource/Quote/Address.php
index 350193fc2e13f7e5e260a063ddd1e06539f8ebb8..56d71a651e18a430a6201716464b7dd6700a1b18 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Quote\Model\Resource\Quote;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
 
 /**
  * Quote address resource model
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Address/Collection.php
index 960d256ca93ab766ea243de3216b370a401ff6fc..521daa91741d3806d4a96575cd0d696ea7cebae1 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address/Collection.php
@@ -10,7 +10,7 @@ namespace Magento\Quote\Model\Resource\Quote\Address;
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * Event prefix
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address/Item.php b/app/code/Magento/Quote/Model/Resource/Quote/Address/Item.php
index 44365e28efd5339f851a5d9bf05d6dc06efd3a56..d156ba6804657d9bc20c62a117210bc5b7994dc0 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address/Item.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address/Item.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Quote\Model\Resource\Quote\Address;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
 
 /**
  * Quote address item resource model
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address/Item/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Address/Item/Collection.php
index 3ef5acacbbfae979a6f83a33a1b14d08d6e3eb67..03b381a572470fac7e1ff727ae76e71f129e9bce 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address/Item/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address/Item/Collection.php
@@ -10,7 +10,7 @@ namespace Magento\Quote\Model\Resource\Quote\Address\Item;
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * Resource initialization
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate.php b/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate.php
index 20177eb97cd48d36657ee22e8099d966caeaa250..221f1b42c5a1fe927e32fae8a3dac80e61b74ac7 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Quote\Model\Resource\Quote\Address;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
 
 /**
  * Quote address shipping rate resource model
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate/Collection.php
index f21945483c6873facccac4eb9efeebe611ba723c..94d13b94377aaec1409cb8aa97e191bcb78b1fdc 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Address/Rate/Collection.php
@@ -10,7 +10,7 @@ namespace Magento\Quote\Model\Resource\Quote\Address\Rate;
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * Whether to load fixed items only
@@ -24,8 +24,9 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Shipping\Model\CarrierFactoryInterface $carrierFactory
-     * @param \Zend_Db_Adapter_Abstract $connection
+     * @param \Zend_Db_Adapter_Abstract|null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
      */
     public function __construct(
@@ -33,11 +34,20 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Shipping\Model\CarrierFactoryInterface $carrierFactory,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $entitySnapshot,
+            $connection,
+            $resource
+        );
         $this->_carrierFactory = $carrierFactory;
     }
 
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Collection.php
index 426caa5d17fceb6b413de08d980edaeac59a611c..20e325fbf3678273365f9f20e185c1343cc0162d 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Collection.php
@@ -10,7 +10,7 @@ namespace Magento\Quote\Model\Resource\Quote;
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * Resource initialization
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Item.php b/app/code/Magento/Quote/Model/Resource/Quote/Item.php
index dbe8c0944870f21be9a933a361f33076e354080d..0f527977b5a8fd1228b469d844d9e34d7bb6381a 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Item.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Item.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Quote\Model\Resource\Quote;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
 
 /**
  * Quote resource model
@@ -29,7 +29,7 @@ class Item extends AbstractDb
      */
     public function save(\Magento\Framework\Model\AbstractModel $object)
     {
-        $hasDataChanges = $object->hasDataChanges();
+        $hasDataChanges = $this->isModified($object);
         $object->setIsOptionsSaved(false);
 
         $result = parent::save($object);
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Item/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Item/Collection.php
index 8f90d543450507681fd9e6678ce3390d37525eb1..56bbda864bc2cd501e68588e8582894708287169 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Item/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Item/Collection.php
@@ -8,7 +8,7 @@ namespace Magento\Quote\Model\Resource\Quote\Item;
 /**
  * Quote item resource collection
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * Collection quote instance
@@ -44,24 +44,35 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Quote\Model\Resource\Quote\Item\Option\CollectionFactory $itemOptionCollectionFactory
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
+     * @param Option\CollectionFactory $itemOptionCollectionFactory
      * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollectionFactory
      * @param \Magento\Quote\Model\Quote\Config $quoteConfig
-     * @param \Zend_Db_Adapter_Abstract $connection
+     * @param \Zend_Db_Adapter_Abstract|null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Quote\Model\Resource\Quote\Item\Option\CollectionFactory $itemOptionCollectionFactory,
         \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollectionFactory,
         \Magento\Quote\Model\Quote\Config $quoteConfig,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $entitySnapshot,
+            $connection,
+            $resource
+        );
         $this->_itemOptionCollectionFactory = $itemOptionCollectionFactory;
         $this->_productCollectionFactory = $productCollectionFactory;
         $this->_quoteConfig = $quoteConfig;
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Payment.php b/app/code/Magento/Quote/Model/Resource/Quote/Payment.php
index 3275211dbf876b0405ef96cd17fe1842fe7fbfe4..8fc4f3446e2b129a9019cc4ce8def5475e1cb587 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Payment.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Payment.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Quote\Model\Resource\Quote;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
 
 /**
  * Quote payment resource model
diff --git a/app/code/Magento/Quote/Model/Resource/Quote/Payment/Collection.php b/app/code/Magento/Quote/Model/Resource/Quote/Payment/Collection.php
index b1f14b76e7a53170de91a9f6ebe5e6ca5119291a..18b09bf83430939b3e4a3d508c9a602bea12bae7 100644
--- a/app/code/Magento/Quote/Model/Resource/Quote/Payment/Collection.php
+++ b/app/code/Magento/Quote/Model/Resource/Quote/Payment/Collection.php
@@ -8,14 +8,15 @@ namespace Magento\Quote\Model\Resource\Quote\Payment;
 /**
  * Quote payments collection
  */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Zend_Db_Adapter_Abstract $connection
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
+     * @param \Zend_Db_Adapter_Abstract|null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
      */
     public function __construct(
@@ -23,10 +24,19 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $entitySnapshot,
+            $connection,
+            $resource
+        );
     }
 
     /**
diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php
index f8a39533b4233cf77b9365821857ca0e973ada0c..f54ab223a9d55f23a7610bbd204064ac86c0ac97 100644
--- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php
+++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php
@@ -46,7 +46,6 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface
      * @param QuoteRepository $quoteRepository Quote repository.
      * @param \Magento\Quote\Model\Cart\ShippingMethodConverter $converter Shipping method converter.
      * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository Customer Address repository
-     *
      */
     public function __construct(
         QuoteRepository $quoteRepository,
@@ -80,6 +79,9 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface
         $shippingAddress->collectShippingRates();
         /** @var \Magento\Quote\Model\Quote\Address\Rate $shippingRate */
         $shippingRate = $shippingAddress->getShippingRateByCode($shippingMethod);
+        if (!$shippingRate) {
+            return null;
+        }
         return $this->converter->modelToDataObject($shippingRate, $quote->getQuoteCurrencyCode());
     }
 
@@ -140,10 +142,6 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface
         if (!$shippingAddress->getCountryId()) {
             throw new StateException(__('Shipping address is not set'));
         }
-        $billingAddress = $quote->getBillingAddress();
-        if (!$billingAddress->getCountryId()) {
-            throw new StateException(__('Billing address is not set'));
-        }
         $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode);
         if (!$shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod())) {
             throw new NoSuchEntityException(
@@ -222,7 +220,7 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface
         $shippingAddress->setRegionId($regionId);
         $shippingAddress->setRegion($region);
         $shippingAddress->setCollectShippingRates(true);
-        $shippingAddress->collectShippingRates();
+        $shippingAddress->collectTotals();
         $shippingRates = $shippingAddress->getGroupedAllShippingRates();
         foreach ($shippingRates as $carrierRates) {
             foreach ($carrierRates as $rate) {
diff --git a/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php
deleted file mode 100644
index ab1e0e6c18be2874a5fbc5f5af17ffd48452e028..0000000000000000000000000000000000000000
--- a/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php
+++ /dev/null
@@ -1,151 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Test\Unit\Model;
-
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
-
-class AddressDetailsManagementTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Quote\Model\AddressDetailsManagement
-     */
-    protected $model;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $billingAddressManagement;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $shippingAddressManagement;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $paymentMethodManagement;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $shippingMethodManagement;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $addressDetailsFactory;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $dataProcessor;
-
-    /** @var \Magento\Quote\Model\QuoteRepository|\PHPUnit_Framework_MockObject_MockObject */
-    protected $quoteRepository;
-
-    /**
-     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
-     */
-    protected $objectManager;
-
-    protected function setUp()
-    {
-        $this->objectManager = new ObjectManager($this);
-        $this->billingAddressManagement = $this->getMock('Magento\Quote\Api\BillingAddressManagementInterface');
-        $this->shippingAddressManagement = $this->getMock('Magento\Quote\Api\ShippingAddressManagementInterface');
-        $this->paymentMethodManagement = $this->getMock('Magento\Quote\Api\PaymentMethodManagementInterface');
-        $this->shippingMethodManagement = $this->getMock('Magento\Quote\Api\ShippingMethodManagementInterface');
-        $this->addressDetailsFactory = $this->getMock(
-            'Magento\Quote\Model\AddressDetailsFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $this->dataProcessor = $this->getMock('Magento\Quote\Model\AddressAdditionalDataProcessor', [], [], '', false);
-        $this->quoteRepository = $this->getMock('Magento\Quote\Model\QuoteRepository', [], [], '', false);
-
-        $this->model = $this->objectManager->getObject(
-            'Magento\Quote\Model\AddressDetailsManagement',
-            [
-                'billingAddressManagement' => $this->billingAddressManagement,
-                'shippingAddressManagement' => $this->shippingAddressManagement,
-                'paymentMethodManagement' => $this->paymentMethodManagement,
-                'shippingMethodManagement' => $this->shippingMethodManagement,
-                'addressDetailsFactory' => $this->addressDetailsFactory,
-                'dataProcessor' => $this->dataProcessor,
-                'quoteRepository' => $this->quoteRepository,
-            ]
-        );
-    }
-
-    public function testSaveAddresses()
-    {
-        $cartId = 100;
-        $additionalData = $this->getMock('\Magento\Quote\Api\Data\AddressAdditionalDataInterface');
-        $billingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', [], [], '', false);
-        $shippingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', [], [], '', false);
-
-        $this->billingAddressManagement->expects($this->once())
-            ->method('assign')
-            ->with($cartId, $billingAddressMock)
-            ->willReturn(1);
-
-        $billingAddressMock->expects($this->once())->method('format')->with('html');
-        $this->billingAddressManagement->expects($this->once())
-            ->method('get')
-            ->with($cartId)
-            ->willReturn($billingAddressMock);
-
-        $this->shippingAddressManagement->expects($this->once())
-            ->method('assign')
-            ->with($cartId, $shippingAddressMock)
-            ->willReturn(1);
-
-        $shippingAddressMock->expects($this->once())->method('format')->with('html');
-        $this->shippingAddressManagement->expects($this->once())
-            ->method('get')
-            ->with($cartId)
-            ->willReturn($shippingAddressMock);
-
-        $shippingMethodMock = $this->getMock('\Magento\Quote\Api\Data\ShippingMethodInterface');
-        $this->shippingMethodManagement->expects($this->once())
-            ->method('getList')
-            ->with($cartId)
-            ->willReturn([$shippingMethodMock]);
-        $paymentMethodMock = $this->getMock('\Magento\Quote\Api\Data\PaymentMethodInterface');
-        $this->paymentMethodManagement->expects($this->once())
-            ->method('getList')
-            ->with($cartId)
-            ->willReturn([$paymentMethodMock]);
-
-        $addressDetailsMock = $this->getMock('\Magento\Quote\Model\AddressDetails', [], [], '', false);
-        $this->addressDetailsFactory->expects($this->once())->method('create')->willReturn($addressDetailsMock);
-
-        $addressDetailsMock->expects($this->once())
-            ->method('setShippingMethods')
-            ->with([$shippingMethodMock])
-            ->willReturnSelf();
-        $addressDetailsMock->expects($this->once())
-            ->method('setPaymentMethods')
-            ->with([$paymentMethodMock])
-            ->willReturnSelf();
-        $this->dataProcessor->expects($this->once())->method('process')->with($additionalData);
-
-        $quote = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
-        $quote->expects($this->once())
-            ->method('setCheckoutMethod')
-            ->willReturnSelf();
-
-        $this->quoteRepository
-            ->expects($this->once())
-            ->method('getActive')
-            ->willReturn($quote);
-
-        $this->model->saveAddresses($cartId, $billingAddressMock, $shippingAddressMock, $additionalData, 'register');
-    }
-}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php b/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9770ab17fc4d02eb7d75838f4104acf4f41735b
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Cart\Totals;
+
+class ItemConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $configPoolMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $totalsFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dataObjectHelperMock;
+
+    /**
+     * @var \Magento\Quote\Model\Cart\Totals\ItemConverter
+     */
+    private $model;
+
+    public function setUp()
+    {
+        $this->configPoolMock = $this->getMock('Magento\Catalog\Helper\Product\ConfigurationPool', [], [], '', false);
+        $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
+        $this->dataObjectHelperMock = $this->getMock('Magento\Framework\Api\DataObjectHelper', [], [], '', false);
+        $this->totalsFactoryMock = $this->getMock(
+            'Magento\Quote\Api\Data\TotalsItemInterfaceFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+
+        $this->model = new \Magento\Quote\Model\Cart\Totals\ItemConverter(
+            $this->configPoolMock,
+            $this->eventManagerMock,
+            $this->totalsFactoryMock,
+            $this->dataObjectHelperMock
+        );
+    }
+
+    public function testModelToDataObject()
+    {
+        $productType = 'simple';
+
+        $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false);
+        $itemMock->expects($this->once())->method('toArray')->will($this->returnValue(['options' => []]));
+        $itemMock->expects($this->any())->method('getProductType')->will($this->returnValue($productType));
+
+        $simpleConfigMock = $this->getMock('Magento\Catalog\Helper\Product\Configuration', [], [], '', false);
+        $defaultConfigMock = $this->getMock('Magento\Catalog\Helper\Product\Configuration', [], [], '', false);
+
+        $this->configPoolMock->expects($this->any())->method('getByProductType')
+            ->will($this->returnValueMap([['simple', $simpleConfigMock], ['default', $defaultConfigMock]]));
+
+        $options = ['1' => ['label' => 'option1'], '2' => ['label' => 'option2']];
+        $simpleConfigMock->expects($this->once())->method('getOptions')->with($itemMock)
+            ->will($this->returnValue($options));
+
+        $option = ['data' => 'optionsData', 'label' => ''];
+        $defaultConfigMock->expects($this->any())->method('getFormattedOptionValue')->will($this->returnValue($option));
+
+        $this->eventManagerMock->expects($this->once())->method('dispatch')
+            ->with('items_additional_data', ['item' => $itemMock]);
+
+        $this->totalsFactoryMock->expects($this->once())->method('create');
+
+        $expectedData = [
+            'options' => '{"1":{"data":"optionsData","label":"option1"},"2":{"data":"optionsData","label":"option2"}}'
+        ];
+        $this->dataObjectHelperMock->expects($this->once())->method('populateWithArray')
+            ->with(null, $expectedData, '\Magento\Quote\Api\Data\TotalsItemInterface');
+
+        $this->model->modelToDataObject($itemMock);
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/RelationTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/RelationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8fa10e5ed63043809e17c2ee10bb39926e9bc08
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/RelationTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Quote\Address;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class RelationTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Model\AbstractModel | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $modelMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote\Address\Relation
+     */
+    private $relation;
+
+    protected function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->modelMock = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            [
+                'getItemsCollection',
+                'getShippingRatesCollection',
+                'itemsCollectionWasSet',
+                'shippingRatesCollectionWasSet'
+            ],
+            [],
+            '',
+            false
+        );
+        $this->relation = $objectManager->getObject('Magento\Quote\Model\Quote\Address\Relation', []);
+    }
+
+    public function testProcessRelation()
+    {
+        $itemsCollection = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\Collection\AbstractCollection',
+            [],
+            [],
+            '',
+            false
+        );
+        $shippingRatesCollection = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\Collection\AbstractCollection',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->modelMock->expects($this->once())->method('itemsCollectionWasSet')->willReturn(true);
+        $this->modelMock->expects($this->once())->method('getItemsCollection')->willReturn($itemsCollection);
+        $this->modelMock->expects($this->once())->method('shippingRatesCollectionWasSet')->willReturn(true);
+        $this->modelMock->expects($this->once())
+            ->method('getShippingRatesCollection')
+            ->willReturn($shippingRatesCollection);
+        $itemsCollection->expects($this->once())->method('save');
+        $shippingRatesCollection->expects($this->once())->method('save');
+        $this->relation->processRelation($this->modelMock);
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/AbstractItemTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/AbstractItemTest.php
index 2fd80d4588170a5594df523ff5586f5b6ef086d8..996d1d54955f38aee5c92e51030e5258497ef3a9 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/AbstractItemTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/AbstractItemTest.php
@@ -22,7 +22,7 @@ class AbstractItemTest extends \PHPUnit_Framework_TestCase
     public function testGetTotalDiscountAmount($expectedDiscountAmount, $children, $calculated, $myDiscountAmount)
     {
         $abstractItemMock = $this->getMockForAbstractClass(
-            '\Magento\Quote\Model\Quote\Item\AbstractItem',
+            'Magento\Quote\Model\Quote\Item\AbstractItem',
             [],
             '',
             false,
@@ -51,7 +51,7 @@ class AbstractItemTest extends \PHPUnit_Framework_TestCase
     {
         $childOneDiscountAmount = 1000;
         $childOneItemMock = $this->getMockForAbstractClass(
-            '\Magento\Quote\Model\Quote\Item\AbstractItem',
+            'Magento\Quote\Model\Quote\Item\AbstractItem',
             [],
             '',
             false,
@@ -65,7 +65,7 @@ class AbstractItemTest extends \PHPUnit_Framework_TestCase
 
         $childTwoDiscountAmount = 50;
         $childTwoItemMock = $this->getMockForAbstractClass(
-            '\Magento\Quote\Model\Quote\Item\AbstractItem',
+            'Magento\Quote\Model\Quote\Item\AbstractItem',
             [],
             '',
             false,
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/RelationTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/RelationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b0723b9273e046a59f667ad3b3b5526d4182bcd
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/RelationTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Quote;
+
+use Magento\Quote\Model\Quote\Relation;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class RelationTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Relation
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quoteMock;
+
+    /**
+     * Mock class dependencies
+     */
+    protected function setUp()
+    {
+        $this->quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
+
+        $objectManager = new ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            'Magento\Quote\Model\Quote\Relation'
+        );
+    }
+
+    /**
+     * Test for processRelation
+     */
+    public function testProcessRelation()
+    {
+        $addressCollectionMock = $this->getMock(
+            'Magento\Eav\Model\Entity\Collection\AbstractCollection',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->quoteMock->expects($this->once())->method('addressCollectionWasSet')->willReturn(true);
+        $this->quoteMock->expects($this->once())->method('getAddressesCollection')->willReturn($addressCollectionMock);
+        $addressCollectionMock->expects($this->once())->method('save');
+
+
+        $itemsCollectionMock = $this->getMock(
+            'Magento\Eav\Model\Entity\Collection\AbstractCollection',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->quoteMock->expects($this->once())->method('itemsCollectionWasSet')->willReturn(true);
+        $this->quoteMock->expects($this->once())->method('getItemsCollection')->willReturn($itemsCollectionMock);
+        $itemsCollectionMock->expects($this->once())->method('save');
+
+        $paymentCollectionMock = $this->getMock(
+            'Magento\Eav\Model\Entity\Collection\AbstractCollection',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->quoteMock->expects($this->once())->method('paymentsCollectionWasSet')->willReturn(true);
+        $this->quoteMock->expects($this->once())->method('getPaymentsCollection')->willReturn($paymentCollectionMock);
+        $paymentCollectionMock->expects($this->once())->method('save');
+
+        $paymentMock = $this->getMock('Magento\Quote\Model\Quote\Payment', [], [], '', false);
+        $this->quoteMock->expects($this->once())->method('currentPaymentWasSet')->willReturn(true);
+        $this->quoteMock->expects($this->once())->method('getPayment')->willReturn($paymentMock);
+        $paymentMock->expects($this->once())->method('save');
+
+        $this->model->processRelation($this->quoteMock);
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
index 56885a81d78648500927d8b77992e9cddea8a2ee..b6a44c587386f6c5fa0e885261ac30c06a7c83c6 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
@@ -211,7 +211,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $this->dataObjectHelperMock = $this->getMock('\Magento\Framework\Api\DataObjectHelper', [], [], '', false);
         $this->checkoutSessionMock = $this->getMock(
             'Magento\Checkout\Model\Session',
-            ['setLastQuoteId', 'setLastSuccessQuoteId', 'setLastOrderId', 'setLastRealOrderId'],
+            ['setLastQuoteId', 'setLastSuccessQuoteId', 'setLastOrderId', 'setLastRealOrderId', 'setLastOrderStatus'],
             [],
             '',
             false
@@ -652,6 +652,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $cartId = 100;
         $orderId = 332;
         $orderIncrementId = 100003332;
+        $orderStatus = 'status1';
         $email = 'email@mail.com';
 
         $this->quoteRepositoryMock->expects($this->once())
@@ -710,59 +711,26 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $service->expects($this->once())->method('submit')->willReturn($orderMock);
 
         $this->quoteMock->expects($this->atLeastOnce())->method('getId')->willReturn($cartId);
+
         $orderMock->expects($this->atLeastOnce())->method('getId')->willReturn($orderId);
         $orderMock->expects($this->atLeastOnce())->method('getIncrementId')->willReturn($orderIncrementId);
+        $orderMock->expects($this->atLeastOnce())->method('getStatus')->willReturn($orderStatus);
 
         $this->checkoutSessionMock->expects($this->once())->method('setLastQuoteId')->with($cartId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastSuccessQuoteId')->with($cartId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastOrderId')->with($orderId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastRealOrderId')->with($orderIncrementId);
-        $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(true);
-
+        $this->checkoutSessionMock->expects($this->once())->method('setLastOrderStatus')->with($orderStatus);
+ 
         $this->assertEquals($orderId, $service->placeOrder($cartId));
     }
 
-    /**
-     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
-     */
-    public function testPlaceOrderIfAgreementsIsNotValid()
-    {
-        $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(false);
-        
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\QuoteManagement $service */
-        $service = $this->getMock(
-            '\Magento\Quote\Model\QuoteManagement',
-            ['submit'],
-            [
-                'eventManager' => $this->eventManager,
-                'quoteValidator' => $this->quoteValidator,
-                'orderFactory' => $this->orderFactory,
-                'orderManagement' => $this->orderManagement,
-                'customerManagement' => $this->customerManagement,
-                'quoteAddressToOrder' => $this->quoteAddressToOrder,
-                'quoteAddressToOrderAddress' => $this->quoteAddressToOrderAddress,
-                'quoteItemToOrderItem' => $this->quoteItemToOrderItem,
-                'quotePaymentToOrderPayment' => $this->quotePaymentToOrderPayment,
-                'userContext' => $this->userContextMock,
-                'quoteRepository' => $this->quoteRepositoryMock,
-                'customerRepository' => $this->customerRepositoryMock,
-                'customerModelFactory' => $this->customerFactoryMock,
-                'dataObjectHelper' => $this->dataObjectHelperMock,
-                'storeManager' => $this->storeManagerMock,
-                'checkoutSession' => $this->checkoutSessionMock,
-                'customerSession' => $this->customerSessionMock,
-                'accountManagement' => $this->accountManagementMock,
-                'agreementsValidator' => $this->agreementsValidatorMock,
-            ]
-        );
-        $service->placeOrder(45);
-    }
-
     public function testPlaceOrder()
     {
         $cartId = 323;
         $orderId = 332;
         $orderIncrementId = 100003332;
+        $orderStatus = 'status1';
 
         /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\QuoteManagement $service */
         $service = $this->getMock(
@@ -822,14 +790,16 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $service->expects($this->once())->method('submit')->willReturn($orderMock);
 
         $this->quoteMock->expects($this->atLeastOnce())->method('getId')->willReturn($cartId);
+
         $orderMock->expects($this->atLeastOnce())->method('getId')->willReturn($orderId);
         $orderMock->expects($this->atLeastOnce())->method('getIncrementId')->willReturn($orderIncrementId);
+        $orderMock->expects($this->atLeastOnce())->method('getStatus')->willReturn($orderStatus);
 
         $this->checkoutSessionMock->expects($this->once())->method('setLastQuoteId')->with($cartId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastSuccessQuoteId')->with($cartId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastOrderId')->with($orderId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastRealOrderId')->with($orderIncrementId);
-        $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(true);
+        $this->checkoutSessionMock->expects($this->once())->method('setLastOrderStatus')->with($orderStatus);
 
         $paymentMethod = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false);
         $paymentMethod->expects($this->once())->method('setChecks');
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/Item/CollectionTest.php b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/Item/CollectionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..04b1ab4442d2ebf9ac3f3d089cecc34504e90555
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/Item/CollectionTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Resource\Quote\Item;
+
+use Magento\Quote\Model\Resource\Quote\Item\Collection;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+/**
+ * Class CollectionTest
+ */
+class CollectionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Collection
+     */
+    private $collection;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $connectionMock;
+
+    /**
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManagerMock;
+
+    /**
+     * @var \Zend_Db_Select|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $selectMock;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resourceMock;
+
+    /**
+     * @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fetchStrategyMock;
+
+    /**
+     * @var \Magento\Framework\Data\Collection\EntityFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entityFactoryMock;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entitySnapshotMock;
+
+    /**
+     * Mock class dependencies
+     */
+    protected function setUp()
+    {
+        $this->entityFactoryMock = $this->getMock('Magento\Framework\Data\Collection\EntityFactory', [], [], '', false);
+        $this->fetchStrategyMock = $this->getMockForAbstractClass(
+            'Magento\Framework\Data\Collection\Db\FetchStrategyInterface'
+        );
+        $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
+
+        $this->selectMock = $this->getMock('Zend_Db_Select', [], [], '', false);
+        $this->connectionMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false);
+        $this->connectionMock->expects($this->atLeastOnce())
+            ->method('select')
+            ->will($this->returnValue($this->selectMock));
+
+        $this->resourceMock = $this->getMock('Magento\Framework\Model\Resource\Db\AbstractDb', [], [], '', false);
+        $this->resourceMock->expects($this->any())->method('getReadConnection')->will(
+            $this->returnValue($this->connectionMock)
+        );
+
+        $objectManager = new ObjectManager($this);
+        $this->collection = $objectManager->getObject(
+            'Magento\Quote\Model\Resource\Quote\Item\Collection',
+            [
+                'entityFactory' => $this->entityFactoryMock,
+                'fetchStrategy' => $this->fetchStrategyMock,
+                'eventManager' => $this->eventManagerMock,
+                'resource' => $this->resourceMock
+            ]
+        );
+    }
+
+    public function testInstanceOf()
+    {
+        $this->assertInstanceOf('Magento\Framework\Model\Resource\Db\VersionControl\Collection', $this->collection);
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/ItemTest.php b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/ItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..60eb9d9eda57e978a5fd8c95a6f5de3cadfee183
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/ItemTest.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Resource\Quote;
+
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+use Magento\Quote\Model\Resource\Quote\Item;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * Class ItemTest
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ItemTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Item
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resourceMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote\Item|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quoteItemMock;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $adapterMock;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entitySnapshotMock;
+
+    /**
+     * @var RelationComposite|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $relationCompositeMock;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\ObjectRelationProcessor|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectRelationProcessorMock;
+
+    /**
+     * Mock class dependencies
+     */
+    public function setUp()
+    {
+        $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false);
+        $this->quoteItemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false);
+        $this->adapterMock = $this->getMock(
+            'Magento\Framework\DB\Adapter\Pdo\Mysql',
+            [
+                'describeTable',
+                'insert',
+                'lastInsertId',
+                'beginTransaction',
+                'rollback',
+                'commit',
+                'quoteInto',
+                'update'
+            ],
+            [],
+            '',
+            false
+        );
+        $this->entitySnapshotMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->relationCompositeMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->objectRelationProcessorMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\ObjectRelationProcessor',
+            [],
+            [],
+            '',
+            false
+        );
+        $contextMock = $this->getMock('\Magento\Framework\Model\Resource\Db\Context', [], [], '', false);
+        $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock);
+        $contextMock->expects($this->once())
+            ->method('getObjectRelationProcessor')
+            ->willReturn($this->objectRelationProcessorMock);
+
+        $objectManager = new ObjectManagerHelper($this);
+        $this->model = $objectManager->getObject(
+            'Magento\Quote\Model\Resource\Quote\Item',
+            [
+                'context' => $contextMock,
+                'entitySnapshot' => $this->entitySnapshotMock,
+                'entityRelationComposite' => $this->relationCompositeMock
+            ]
+        );
+    }
+
+    public function testInstanceOf()
+    {
+        $this->assertInstanceOf('Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb', $this->model);
+    }
+
+    public function testSaveNotModifiedItem()
+    {
+        $this->entitySnapshotMock->expects($this->exactly(2))
+            ->method('isModified')
+            ->with($this->quoteItemMock)
+            ->willReturn(false);
+
+        $this->quoteItemMock->expects($this->never())
+            ->method('isOptionsSaved');
+        $this->quoteItemMock->expects($this->never())
+            ->method('saveItemOptions');
+
+        $this->resourceMock->expects($this->any())
+            ->method('getConnection')
+            ->willReturn($this->adapterMock);
+
+        $this->assertEquals($this->model, $this->model->save($this->quoteItemMock));
+    }
+
+    public function testSaveSavedBeforeItem()
+    {
+        $this->entitySnapshotMock->expects($this->exactly(2))
+            ->method('isModified')
+            ->with($this->quoteItemMock)
+            ->willReturn(true);
+
+        $this->quoteItemMock->expects($this->once())
+            ->method('isOptionsSaved')
+            ->willReturn(true);
+        $this->quoteItemMock->expects($this->never())
+            ->method('saveItemOptions');
+
+        $this->resourceMock->expects($this->any())
+            ->method('getConnection')
+            ->willReturn($this->adapterMock);
+
+        $this->assertEquals($this->model, $this->model->save($this->quoteItemMock));
+    }
+
+    public function testSaveModifiedItem()
+    {
+        $this->entitySnapshotMock->expects($this->exactly(2))
+            ->method('isModified')
+            ->with($this->quoteItemMock)
+            ->willReturn(true);
+
+        $this->quoteItemMock->expects($this->once())
+            ->method('isOptionsSaved')
+            ->willReturn(false);
+        $this->quoteItemMock->expects($this->once())
+            ->method('saveItemOptions');
+
+        $this->resourceMock->expects($this->any())
+            ->method('getConnection')
+            ->willReturn($this->adapterMock);
+
+        $this->assertEquals($this->model, $this->model->save($this->quoteItemMock));
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/QuoteAddressTest.php b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/QuoteAddressTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7713ff991ba28f6d17e7d13547abc6a8640ea83
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Resource/Quote/QuoteAddressTest.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Quote\Test\Unit\Model\Resource\Quote;
+
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+
+/**
+ * Class QuoteAddressTest
+ */
+class QuoteAddressTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Quote\Model\Resource\Quote\Address
+     */
+    protected $addressResource;
+
+    /**
+     * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $appResourceMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote\Address|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $addressMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quoteMock;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $adapterMock;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $entitySnapshotMock;
+
+    /**
+     * @var RelationComposite|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $relationCompositeMock;
+
+    /**
+     * Init
+     */
+    public function setUp()
+    {
+        $this->addressMock = $this->getMock(
+            'Magento\Quote\Model\Quote\Address',
+            ['__wakeup', 'getOrderId', 'hasDataChanges', 'beforeSave', 'afterSave', 'validateBeforeSave', 'getOrder'],
+            [],
+            '',
+            false
+        );
+        $this->quoteMock = $this->getMock(
+            'Magento\Quote\Model\Quote',
+            ['__wakeup', 'getId'],
+            [],
+            '',
+            false
+        );
+        $this->appResourceMock = $this->getMock(
+            'Magento\Framework\App\Resource',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->adapterMock = $this->getMock(
+            'Magento\Framework\DB\Adapter\Pdo\Mysql',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->entitySnapshotMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->relationCompositeMock = $this->getMock(
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->appResourceMock->expects($this->any())
+                              ->method('getConnection')
+                              ->will($this->returnValue($this->adapterMock));
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->adapterMock->expects($this->any())
+                          ->method('describeTable')
+                          ->will($this->returnValue([]));
+        $this->adapterMock->expects($this->any())
+                          ->method('insert');
+        $this->adapterMock->expects($this->any())
+                          ->method('lastInsertId');
+        $this->addressResource = $objectManager->getObject(
+            'Magento\Quote\Model\Resource\Quote\Address',
+            [
+                'resource' => $this->appResourceMock,
+                'entitySnapshot' => $this->entitySnapshotMock,
+                'entityRelationComposite' => $this->relationCompositeMock
+            ]
+        );
+    }
+
+    public function testSave()
+    {
+        $this->entitySnapshotMock->expects($this->once())
+                                 ->method('isModified')
+                                 ->with($this->addressMock)
+                                 ->willReturn(true);
+        $this->entitySnapshotMock->expects($this->once())
+                                 ->method('registerSnapshot')
+                                 ->with($this->addressMock);
+        $this->relationCompositeMock->expects($this->once())
+                                 ->method('processRelations')
+                                 ->with($this->addressMock);
+        $this->addressResource->save($this->addressMock);
+    }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
index 4c5bffe80077615734f94e7df2f3cee0f0c61f4d..2fea9a5b9a15c1c67d7bcf85e49814f90162f5f6 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
@@ -32,6 +32,11 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorMock;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $scopeConfigMock;
+
     /**
      * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
      */
@@ -41,6 +46,7 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase
     {
         $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->quoteRepositoryMock = $this->getMock('\Magento\Quote\Model\QuoteRepository', [], [], '', false);
+        $this->scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
 
         $this->quoteAddressMock = $this->getMock(
             '\Magento\Quote\Model\Quote\Address',
@@ -66,7 +72,8 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'addressValidator' => $this->validatorMock,
-                'logger' => $this->getMock('\Psr\Log\LoggerInterface')
+                'logger' => $this->getMock('\Psr\Log\LoggerInterface'),
+                'scopeConfig' => $this->scopeConfigMock
             ]
         );
     }
@@ -167,6 +174,28 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase
         $this->service->assign('cart867', $this->quoteAddressMock);
     }
 
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testSetAddressWithViolationOfMinimumAmount()
+    {
+        $storeId = 12;
+        $this->quoteAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf();
+        $this->quoteAddressMock->expects($this->once())->method('save');
+
+        $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false);
+        $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with('cart123')
+            ->will($this->returnValue($quoteMock));
+        $quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false));
+        $quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($this->quoteAddressMock);
+        $quoteMock->expects($this->any())->method('getStoreId')->will($this->returnValue($storeId));
+
+        $this->scopeConfigMock->expects($this->once())->method('getValue')
+            ->with('sales/minimum_order/error_message', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId);
+
+        $this->service->assign('cart123', $this->quoteAddressMock);
+    }
+
     public function testGetAddress()
     {
         $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false);
diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php
index ef5992e11f7af3c0dbedf4f7b8d263a12cf1804e..fd760977a6c89f57308b2142d4acd827af06bfa4 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php
@@ -316,39 +316,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase
         $this->model->set($cartId, $carrierCode, $methodCode);
     }
 
-    /**
-     * @expectedException \Magento\Framework\Exception\StateException
-     * @expectedExceptionMessage Billing address is not set
-     */
-    public function testSetMethodWithoutBillingAddress()
-    {
-        $cartId = 12;
-        $carrierCode = 34;
-        $methodCode = 56;
-        $countryId = 1;
-
-        $this->quoteRepositoryMock->expects($this->once())
-            ->method('getActive')->with($cartId)->will($this->returnValue($this->quoteMock));
-        $this->quoteMock->expects($this->once())->method('getItemsCount')->will($this->returnValue(1));
-        $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false));
-        $this->quoteMock->expects($this->once())
-            ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock));
-        $this->shippingAddressMock->expects($this->once())
-            ->method('getCountryId')->will($this->returnValue($countryId));
-        $billingAddressMock = $this->getMock(
-            '\Magento\Quote\Model\Quote\Address',
-            ['getCountryId', '__wakeup'],
-            [],
-            '',
-            false
-        );
-        $this->quoteMock->expects($this->once())
-            ->method('getBillingAddress')->will($this->returnValue($billingAddressMock));
-        $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(null));
-
-        $this->model->set($cartId, $carrierCode, $methodCode);
-    }
-
     /**
      * @expectedException \Magento\Framework\Exception\NoSuchEntityException
      * @expectedExceptionMessage Carrier with such method not found: 34, 56
@@ -365,16 +332,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase
         $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false));
         $this->quoteMock->expects($this->once())
             ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock));
-        $billingAddressMock = $this->getMock(
-            '\Magento\Quote\Model\Quote\Address',
-            ['getCountryId', '__wakeup'],
-            [],
-            '',
-            false
-        );
-        $this->quoteMock->expects($this->once())
-            ->method('getBillingAddress')->will($this->returnValue($billingAddressMock));
-        $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23));
         $this->shippingAddressMock->expects($this->once())
             ->method('getCountryId')->will($this->returnValue($countryId));
         $this->shippingAddressMock->expects($this->once())
@@ -405,19 +362,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase
             ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock));
         $this->shippingAddressMock->expects($this->once())
             ->method('getCountryId')->will($this->returnValue($countryId));
-        $billingAddressMock = $this->getMock(
-            '\Magento\Quote\Model\Quote\Address',
-            [
-                'getCountryId',
-                '__wakeup'
-            ],
-            [],
-            '',
-            false
-        );
-        $this->quoteMock->expects($this->once())
-            ->method('getBillingAddress')->will($this->returnValue($billingAddressMock));
-        $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23));
         $this->shippingAddressMock->expects($this->once())
             ->method('setShippingMethod')->with($carrierCode . '_' . $methodCode);
         $this->shippingAddressMock->expects($this->once())
@@ -464,19 +408,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase
         $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false));
         $this->quoteMock->expects($this->once())
             ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock));
-        $billingAddressMock = $this->getMock(
-            '\Magento\Quote\Model\Quote\Address',
-            [
-                'getCountryId',
-                '__wakeup'
-            ],
-            [],
-            '',
-            false
-        );
-        $this->quoteMock->expects($this->once())
-            ->method('getBillingAddress')->will($this->returnValue($billingAddressMock));
-        $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23));
         $this->shippingAddressMock->expects($this->once())
             ->method('getCountryId')->will($this->returnValue($countryId));
         $this->shippingAddressMock->expects($this->once())
diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml
index 66cae592e21018589902a907529cbcc87007c8e4..8766552b2bca3a3ee0743e672a0335d4c5c858d2 100644
--- a/app/code/Magento/Quote/etc/di.xml
+++ b/app/code/Magento/Quote/etc/di.xml
@@ -24,6 +24,7 @@
     <preference for="Magento\Quote\Api\CartTotalRepositoryInterface" type="\Magento\Quote\Model\Cart\CartTotalRepository" />
     <preference for="Magento\Quote\Api\CartTotalManagementInterface" type="\Magento\Quote\Model\Cart\CartTotalManagement" />
     <preference for="Magento\Quote\Api\Data\TotalsInterface" type="\Magento\Quote\Model\Cart\Totals" />
+    <preference for="Magento\Quote\Api\Data\TotalSegmentInterface" type="\Magento\Quote\Model\Cart\TotalSegment" />
     <preference for="Magento\Quote\Api\Data\TotalsItemInterface" type="\Magento\Quote\Model\Cart\Totals\Item" />
     <preference for="Magento\Quote\Api\Data\CurrencyInterface" type="\Magento\Quote\Model\Cart\Currency" />
     <preference for="Magento\Quote\Api\GuestCartManagementInterface" type="Magento\Quote\Model\GuestCart\GuestCartManagement" />
@@ -35,7 +36,6 @@
     <preference for="Magento\Quote\Api\GuestShippingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingAddressManagement" />
     <preference for="Magento\Quote\Api\GuestShippingMethodManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingMethodManagement" />
     <preference for="Magento\Quote\Api\GuestBillingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestBillingAddressManagement" />
-    <preference for="Magento\Quote\Api\GuestAddressDetailsManagementInterface" type="Magento\Quote\Model\GuestCart\GuestAddressDetailsManagement" />
     <preference for="Magento\Quote\Api\GuestCartTotalManagementInterface" type="\Magento\Quote\Model\GuestCart\GuestCartTotalManagement" />
     <preference for="Magento\Quote\Api\Data\EstimateAddressInterface" type="Magento\Quote\Model\EstimateAddress" />
     <type name="Magento\Webapi\Controller\Rest\ParamsOverrider">
@@ -55,8 +55,30 @@
             <argument name="addressConfig" xsi:type="object">Magento\Customer\Model\Address\Config\Proxy</argument>
         </arguments>
     </type>
-    <preference for="Magento\Quote\Api\AddressDetailsManagementInterface" type="Magento\Quote\Model\AddressDetailsManagement" />
-    <preference for="Magento\Quote\Api\Data\AddressDetailsInterface" type="Magento\Quote\Model\AddressDetails" />
+    <virtualType name="QuoteAddressRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
+        <arguments>
+            <argument name="relationProcessors" xsi:type="array">
+                <item name="default" xsi:type="object">Magento\Quote\Model\Quote\Address\Relation</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Quote\Model\Resource\Quote\Address">
+        <arguments>
+            <argument name="entityRelationComposite" xsi:type="object">QuoteAddressRelationsComposite</argument>
+        </arguments>
+    </type>
+    <virtualType name="QuoteRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
+        <arguments>
+            <argument name="relationProcessors" xsi:type="array">
+                <item name="default" xsi:type="object">Magento\Quote\Model\Quote\Relation</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Quote\Model\Resource\Quote">
+        <arguments>
+            <argument name="entityRelationComposite" xsi:type="object">QuoteRelationsComposite</argument>
+        </arguments>
+    </type>
     <preference for="Magento\Quote\Api\Data\AddressAdditionalDataInterface" type="Magento\Quote\Model\AddressAdditionalData" />
     <preference for="Magento\Quote\Api\Data\TotalsAdditionalDataInterface" type="Magento\Quote\Model\Cart\TotalsAdditionalData" />
     <preference for="\Magento\Quote\Model\Quote\Address\CustomAttributeListInterface" type="\Magento\Quote\Model\Quote\Address\CustomAttributeList" />
diff --git a/app/code/Magento/Quote/etc/webapi.xml b/app/code/Magento/Quote/etc/webapi.xml
index 9b6ca15468d654d70622b0dba27d47a02f5f806d..8e5e097a995cd6aa38aa77f568f2c0ba97f1d9cd 100644
--- a/app/code/Magento/Quote/etc/webapi.xml
+++ b/app/code/Magento/Quote/etc/webapi.xml
@@ -145,6 +145,24 @@
             <parameter name="cartId" force="true">%cart_id%</parameter>
         </data>
     </route>
+    <route url="/V1/carts/mine/estimate-shipping-methods" method="POST">
+        <service class="Magento\Quote\Api\ShippingMethodManagementInterface" method="estimateByAddress"/>
+        <resources>
+            <resource ref="self" />
+        </resources>
+        <data>
+            <parameter name="cartId" force="true">%cart_id%</parameter>
+        </data>
+    </route>
+    <route url="/V1/carts/mine/estimate-shipping-methods-by-address-id" method="POST">
+        <service class="Magento\Quote\Api\ShippingMethodManagementInterface" method="estimateByAddressId"/>
+        <resources>
+            <resource ref="self" />
+        </resources>
+        <data>
+            <parameter name="cartId" force="true">%cart_id%</parameter>
+        </data>
+    </route>
 
     <!-- Managing Guest Cart Shipment Method -->
     <route url="/V1/guest-carts/:cartId/selected-shipping-method" method="PUT">
@@ -165,6 +183,12 @@
             <resource ref="anonymous" />
         </resources>
     </route>
+    <route url="/V1/guest-carts/:cartId/estimate-shipping-methods" method="POST">
+        <service class="Magento\Quote\Api\GuestShippingMethodManagementInterface" method="estimateByAddress"/>
+        <resources>
+            <resource ref="anonymous" />
+        </resources>
+    </route>
 
     <!-- Managing Cart Items -->
     <route url="/V1/carts/:cartId/items" method="GET">
@@ -352,12 +376,6 @@
             <resource ref="anonymous" />
         </resources>
     </route>
-    <route url="/V1/guest-carts/:cartId/addresses" method="POST">
-        <service class="Magento\Quote\Api\GuestAddressDetailsManagementInterface" method="saveAddresses"/>
-        <resources>
-            <resource ref="anonymous" />
-        </resources>
-    </route>
 
     <!-- Managing My Cart Billing address -->
     <route url="/V1/carts/mine/billing-address" method="GET">
@@ -495,15 +513,6 @@
             <parameter name="cartId" force="true">%cart_id%</parameter>
         </data>
     </route>
-    <route url="/V1/carts/mine/addresses" method="POST">
-        <service class="Magento\Quote\Api\AddressDetailsManagementInterface" method="saveAddresses"/>
-        <resources>
-            <resource ref="self" />
-        </resources>
-        <data>
-            <parameter name="cartId" force="true">%cart_id%</parameter>
-        </data>
-    </route>
 
     <!-- Managing Cart Order -->
     <route url="/V1/carts/:cartId/order" method="PUT">
diff --git a/app/code/Magento/Reports/Block/Adminhtml/Sales/Grid/Column/Renderer/Date.php b/app/code/Magento/Reports/Block/Adminhtml/Sales/Grid/Column/Renderer/Date.php
index 30b6fccb13435e396ce06d6383768b301f0f399c..8b325bb2a0ad1b0a5695bf54864496effbed60ba 100644
--- a/app/code/Magento/Reports/Block/Adminhtml/Sales/Grid/Column/Renderer/Date.php
+++ b/app/code/Magento/Reports/Block/Adminhtml/Sales/Grid/Column/Renderer/Date.php
@@ -37,31 +37,20 @@ class Date extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Date
     {
         $format = $this->getColumn()->getFormat();
         if (!$format) {
-            if (self::$_format === null) {
-                try {
-                    $formats = (new DataBundle())->get(
-                        $this->_localeResolver->getLocale()
-                    )['calendar']['gregorian']['availableFormats'];
-
-                    switch ($this->getColumn()->getPeriodType()) {
-                        case 'month':
-                            self::$_format = $formats['yM'];
-                            break;
-
-                        case 'year':
-                            self::$_format = $formats['y'];
-                            break;
-
-                        default:
-                            self::$_format = $this->_localeDate->getDateFormat(
-                                \IntlDateFormatter::MEDIUM
-                            );
-                            break;
-                    }
-                } catch (\Exception $e) {
-                }
+            $dataBundle = new DataBundle();
+            $resourceBundle = $dataBundle->get($this->_localeResolver->getLocale());
+            $formats = $resourceBundle['calendar']['gregorian']['availableFormats'];
+            switch ($this->getColumn()->getPeriodType()) {
+                case 'month':
+                    $format = $formats['yM'];
+                    break;
+                case 'year':
+                    $format = $formats['y'];
+                    break;
+                default:
+                    $format = $this->_localeDate->getDateFormat(\IntlDateFormatter::MEDIUM);
+                    break;
             }
-            $format = self::$_format;
         }
         return $format;
     }
@@ -74,51 +63,22 @@ class Date extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Date
      */
     public function render(\Magento\Framework\Object $row)
     {
-        //@todo: check this logic manually
         if ($data = $row->getData($this->getColumn()->getIndex())) {
             switch ($this->getColumn()->getPeriodType()) {
                 case 'month':
-                    $dateFormat = 'yyyy-MM';
+                    $data = $data . '-01';
                     break;
                 case 'year':
-                    $dateFormat = 'yyyy';
-                    break;
-                default:
-                    $dateFormat = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT;
+                    $data = $data . '-01-01';
                     break;
             }
-
             $format = $this->_getFormat();
-            try {
-                $data = $this->getColumn()->getGmtoffset()
-                    ? \IntlDateFormatter::formatObject(
-                        $this->_localeDate->date(new \DateTime($data)),
-                        $format
-                    )
-                    : \IntlDateFormatter::formatObject(
-                        $this->_localeDate->date(
-                            new \DateTime($data),
-                            null,
-                            false
-                        ),
-                        $format
-                    );
-            } catch (\Exception $e) {
-                $data = $this->getColumn()->getTimezone()
-                    ? \IntlDateFormatter::formatObject(
-                        $this->_localeDate->date(new \DateTime($data)),
-                        $format
-                    )
-                    : \IntlDateFormatter::formatObject(
-                        $this->_localeDate->date(
-                            new \DateTime($data),
-                            null,
-                            false
-                        ),
-                        $format
-                    );
+            if ($this->getColumn()->getGmtoffset() || $this->getColumn()->getTimezone()) {
+                $date = $this->_localeDate->date(new \DateTime($data));
+            } else {
+                $date = $this->_localeDate->date(new \DateTime($data), null, false);
             }
-            return $data;
+            return \IntlDateFormatter::formatObject($date, $format);
         }
         return $this->getColumn()->getDefault();
     }
diff --git a/app/code/Magento/Reports/Model/Resource/Customer/Collection.php b/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
index c602eb91ae9b4284b289204770089483d4879ffe..637f593308083813a3e0f89cac78e612279d76a1 100644
--- a/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
@@ -81,6 +81,7 @@ class Collection extends \Magento\Customer\Model\Resource\Customer\Collection
      * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
      * @param \Magento\Eav\Model\Resource\Helper $resourceHelper
      * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\Object\Copy\Config $fieldsetConfig
      * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
      * @param \Magento\Quote\Model\Resource\Quote\Item\CollectionFactory $quoteItemFactory
@@ -100,6 +101,7 @@ class Collection extends \Magento\Customer\Model\Resource\Customer\Collection
         \Magento\Eav\Model\EntityFactory $eavEntityFactory,
         \Magento\Eav\Model\Resource\Helper $resourceHelper,
         \Magento\Framework\Validator\UniversalFactory $universalFactory,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Object\Copy\Config $fieldsetConfig,
         \Magento\Quote\Model\QuoteRepository $quoteRepository,
         \Magento\Quote\Model\Resource\Quote\Item\CollectionFactory $quoteItemFactory,
@@ -117,6 +119,7 @@ class Collection extends \Magento\Customer\Model\Resource\Customer\Collection
             $eavEntityFactory,
             $resourceHelper,
             $universalFactory,
+            $entitySnapshot,
             $fieldsetConfig,
             $connection,
             $modelName
diff --git a/app/code/Magento/Reports/Model/Resource/Order/Collection.php b/app/code/Magento/Reports/Model/Resource/Order/Collection.php
index 07c2e2aa8c4a76d1d262f38904d52b00ea622f99..97294fb8ddd9371e270a9dde67709910fbe56696 100644
--- a/app/code/Magento/Reports/Model/Resource/Order/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Order/Collection.php
@@ -72,7 +72,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Collection
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\DB\Helper $coreResourceHelper
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -89,7 +89,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Collection
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\DB\Helper $coreResourceHelper,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Reports/Model/Resource/Quote/Collection.php b/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
index c83ab61da03371c03db533b27a46a4ad88c82205..ccad3cf8f4e8c37eabe56bc75897674dc820dd2c 100644
--- a/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
@@ -17,6 +17,7 @@ class Collection extends \Magento\Quote\Model\Resource\Quote\Collection
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Customer\Model\Resource\Customer $customerResource
      * @param \Zend_Db_Adapter_Abstract $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
@@ -26,11 +27,20 @@ class Collection extends \Magento\Quote\Model\Resource\Quote\Collection
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Customer\Model\Resource\Customer $customerResource,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $entitySnapshot,
+            $connection,
+            $resource
+        );
         $this->customerResource = $customerResource;
     }
 
diff --git a/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Grid/Column/Renderer/DateTest.php b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Grid/Column/Renderer/DateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6252d53d0382924f42e5af294791de18e333c88a
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Grid/Column/Renderer/DateTest.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Block\Adminhtml\Sales\Grid\Column\Renderer;
+
+use Magento\Reports\Block\Adminhtml\Sales\Grid\Column\Renderer\Date;
+
+class DateTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Reports\Block\Adminhtml\Sales\Grid\Column\Renderer\Date
+     */
+    protected $date;
+
+    /**
+     * @var \Magento\Backend\Block\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resolverMock;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $localeDate;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        $this->localeDate = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\TimezoneInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->localeDate
+            ->expects($this->once())
+            ->method('date')
+            ->will($this->returnArgument(0));
+
+        $this->contextMock = $this->getMockBuilder('Magento\Backend\Block\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->contextMock
+            ->expects($this->once())
+            ->method('getLocaleDate')
+            ->will($this->returnValue($this->localeDate));
+
+        $this->resolverMock = $this->getMockBuilder('Magento\Framework\Locale\ResolverInterface')
+            ->getMock();
+
+        $this->date = new Date(
+            $this->contextMock,
+            $this->resolverMock
+        );
+    }
+
+    /**
+     * @param string $data
+     * @param string $index
+     * @param string $locale
+     * @param string $period
+     * @param string $result
+     * @dataProvider datesDataProvider
+     * @return void
+     */
+    public function testRender($data, $index, $locale, $period, $result)
+    {
+        $this->resolverMock->expects($this->any())->method('getLocale')->will($this->returnValue($locale));
+        $this->localeDate->expects($this->any())->method('getDateFormat')->willReturnCallback(
+            function ($value) use ($locale) {
+                return (new \IntlDateFormatter(
+                    $locale,
+                    $value,
+                    \IntlDateFormatter::NONE
+                ))->getPattern();
+            }
+        );
+
+        $objectMock = $this->getMockBuilder('Magento\Framework\Object')
+            ->setMethods(['getData'])
+            ->getMock();
+        $objectMock->expects($this->once())->method('getData')->will($this->returnValue($data));
+
+        $columnMock = $this->getMockBuilder('Magento\Backend\Block\Widget\Grid\Column')
+            ->disableOriginalConstructor()
+            ->setMethods(['getIndex', 'getPeriodType'])
+            ->getMock();
+        $columnMock->expects($this->once())->method('getIndex')->will($this->returnValue($index));
+        $columnMock->expects($this->atLeastOnce())->method('getPeriodType')->will($this->returnValue($period));
+
+        $this->date->setColumn($columnMock);
+
+        $this->assertEquals($result, $this->date->render($objectMock));
+    }
+
+    /**
+     * @return array
+     */
+    public function datesDataProvider()
+    {
+        return [
+            [
+                'data' => '2000',
+                'index' => 'period',
+                'locale' => 'en_US',
+                'period' => 'year',
+                'result' => '2000'
+            ],
+            [
+                'data' => '2030',
+                'index' => 'period',
+                'locale' => 'en_US',
+                'period' => 'year',
+                'result' => '2030'
+            ],
+            [
+                'data' => '2000-01',
+                'index' => 'period',
+                'locale' => 'en_US',
+                'period' => 'month',
+                'result' => '1/2000'
+            ],
+            [
+                'data' => '2030-12',
+                'index' => 'period',
+                'locale' => 'en_US',
+                'period' => 'month',
+                'result' => '12/2030'
+            ],
+            [
+                'data' => '2014-06-25',
+                'index' => 'period',
+                'locale' => 'en_US',
+                'period' => 'day',
+                'result' => 'Jun 25, 2014'
+            ]
+        ];
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/AbstractControllerTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/AbstractControllerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a15c7a139132cb978a52ca934612c946427bb8aa
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/AbstractControllerTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report;
+
+/**
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
+ */
+abstract class AbstractControllerTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Framework\App\Response\Http\FileFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileFactoryMock;
+
+    /**
+     * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\App\ViewInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $viewMock;
+
+    /**
+     * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $layoutMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $breadcrumbsBlockMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $menuBlockMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $switcherBlockMock;
+
+    /**
+     * @var \Magento\Backend\Model\Menu|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $menuModelMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\AbstractBlock|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $abstractBlockMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        $this->requestMock = $this->getMockForAbstractClassBuilder(
+            'Magento\Framework\App\RequestInterface',
+            ['isDispatched', 'initForward', 'setDispatched', 'isForwarded']
+        );
+        $this->breadcrumbsBlockMock = $this->getMockForAbstractClassBuilder(
+            'Magento\Framework\View\Element\BlockInterface',
+            ['addLink']
+        );
+        $this->menuBlockMock = $this->getMockForAbstractClassBuilder(
+            'Magento\Framework\View\Element\BlockInterface',
+            ['setActive', 'getMenuModel']
+        );
+        $this->viewMock = $this->getMockForAbstractClassBuilder(
+            'Magento\Framework\App\ViewInterface'
+        );
+
+        $this->layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->switcherBlockMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->contextMock = $this->getMockBuilder('Magento\Backend\App\Action\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->fileFactoryMock = $this->getMockBuilder('Magento\Framework\App\Response\Http\FileFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->menuModelMock = $this->getMockBuilder('Magento\Backend\Model\Menu')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->abstractBlockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->setMethods(['getCsvFile', 'getExcelFile', 'setSaveParametersInSession', 'getCsv', 'getExcel'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->menuModelMock->expects($this->any())->method('getParentItems')->willReturn([]);
+        $this->menuBlockMock->expects($this->any())->method('getMenuModel')->willReturn($this->menuModelMock);
+        $this->viewMock->expects($this->any())->method('getLayout')->willReturn($this->layoutMock);
+        $this->contextMock->expects($this->any())->method('getRequest')->willReturn($this->requestMock);
+        $this->contextMock->expects($this->any())->method('getView')->willReturn($this->viewMock);
+
+        $this->layoutMock->expects($this->any())->method('getBlock')->will(
+            $this->returnValueMap(
+                [
+                    ['breadcrumbs', $this->breadcrumbsBlockMock],
+                    ['menu', $this->menuBlockMock],
+                    ['store_switcher', $this->switcherBlockMock]
+                ]
+            )
+        );
+        $this->layoutMock->expects($this->any())->method('getChildBlock')->willReturn($this->abstractBlockMock);
+    }
+
+    /**
+     * Custom mock for abstract class
+     * @param string $className
+     * @param array $mockedMethods
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getMockForAbstractClassBuilder($className, $mockedMethods = [])
+    {
+        return $this->getMockForAbstractClass($className, [], '', false, false, true, $mockedMethods);
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/AccountsTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/AccountsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c6267c7192f74a912a2ba6be23c7b5e3108fe473
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/AccountsTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\Accounts;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class AccountsTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\Accounts
+     */
+    protected $accounts;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->accounts = new Accounts(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('New Accounts Report'));
+
+        $this->viewMock
+            ->expects($this->any())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_customers_accounts');
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(0))
+            ->method('addLink')
+            ->with(new Phrase('Reports'), new Phrase('Reports'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(1))
+            ->method('addLink')
+            ->with(new Phrase('Customers'), new Phrase('Customers'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(2))
+            ->method('addLink')
+            ->with(new Phrase('New Accounts'), new Phrase('New Accounts'));
+        $this->accounts->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5e9ccccf6d933966c1802fe34a2c0fdf2c6c885
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsCsvTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportAccountsCsv;
+
+class ExportAccountsCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportAccountsCsv
+     */
+    protected $exportAccountsCsv;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportAccountsCsv = new ExportAccountsCsv(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('new_accounts.csv', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportAccountsCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..98134d20ccd9edc52fa27958a60c437657c1756c
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportAccountsExcelTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportAccountsExcel;
+
+class ExportAccountsExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportAccountsExcel
+     */
+    protected $exportAccountsExcel;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportAccountsExcel = new ExportAccountsExcel(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('new_accounts.xml', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportAccountsExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..573720a1859cd759ca99ba03f9ec0b93252904f4
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersCsvTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportOrdersCsv;
+
+class ExportOrdersCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportOrdersCsv
+     */
+    protected $exportOrdersCsv;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportOrdersCsv = new ExportOrdersCsv(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('customers_orders.csv', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportOrdersCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8273becb2d66d0a3636e6514a37f77c599e87d9
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportOrdersExcelTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportOrdersExcel;
+
+class ExportOrdersExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportOrdersExcel
+     */
+    protected $exportOrdersExcel;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportOrdersExcel = new ExportOrdersExcel(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('customers_orders.xml', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportOrdersExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4a7a0c68e2d2872f7e04a4a655eb614c5d72893
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsCsvTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportTotalsCsv;
+
+class ExportTotalsCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportTotalsCsv
+     */
+    protected $exportTotalsCsv;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportTotalsCsv = new ExportTotalsCsv(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('customer_totals.csv', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportTotalsCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..33177c27a183fbd6aa03e6e8f208190dc43a433d
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/ExportTotalsExcelTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\ExportTotalsExcel;
+
+class ExportTotalsExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\ExportTotalsExcel
+     */
+    protected $exportTotalsExcel;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->exportTotalsExcel = new ExportTotalsExcel(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->willReturn(['export']);
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('customer_totals.xml', ['export'], \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+        $this->exportTotalsExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/OrdersTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/OrdersTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e58897f7458dc46882a9e5b1aa5288e71f60748
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/OrdersTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\Orders;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class OrdersTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\Orders
+     */
+    protected $orders;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->orders = new Orders(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Order Count Report'));
+
+        $this->viewMock
+            ->expects($this->any())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_customers_orders');
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(0))
+            ->method('addLink')
+            ->with(new Phrase('Reports'), new Phrase('Reports'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(1))
+            ->method('addLink')
+            ->with(new Phrase('Customers'), new Phrase('Customers'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(2))
+            ->method('addLink')
+            ->with(new Phrase('Customers by Number of Orders'), new Phrase('Customers by Number of Orders'));
+        $this->orders->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/TotalsTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/TotalsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf63f966292f16cd203897e72f8abb7b672593f6
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Customer/TotalsTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Customer;
+
+use Magento\Reports\Controller\Adminhtml\Report\Customer\Totals;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class TotalsTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Customer\Totals
+     */
+    protected $totals;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->totals = new Totals(
+            $this->contextMock,
+            $this->fileFactoryMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Order Total Report'));
+
+        $this->viewMock
+            ->expects($this->any())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_customers_totals');
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(0))
+            ->method('addLink')
+            ->with(new Phrase('Reports'), new Phrase('Reports'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(1))
+            ->method('addLink')
+            ->with(new Phrase('Customers'), new Phrase('Customers'));
+        $this->breadcrumbsBlockMock
+            ->expects($this->at(2))
+            ->method('addLink')
+            ->with(new Phrase('Customers by Orders Total'), new Phrase('Customers by Orders Total'));
+        $this->totals->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/DownloadsTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/DownloadsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7e1ada266c5a9545c4b965a12c8604c0d446257
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/DownloadsTest.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\Downloads;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class DownloadsTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\Downloads
+     */
+    protected $downloads;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->downloads = new Downloads(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Downloads Report'));
+
+        $this->viewMock
+            ->expects($this->once())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Downloadable::report_products_downloads');
+
+        $this->breadcrumbsBlockMock
+            ->expects($this->exactly(3))
+            ->method('addLink')
+            ->withConsecutive(
+                [new Phrase('Reports'), new Phrase('Reports')],
+                [new Phrase('Products'), new Phrase('Products')],
+                [new Phrase('Downloads'), new Phrase('Downloads')]
+            );
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('createBlock')
+            ->with('Magento\Reports\Block\Adminhtml\Product\Downloads')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->downloads->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d693599b8f92dd48c21f8be673ff7a5efc16001
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsCsvTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportDownloadsCsv;
+
+class ExportDownloadsCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportDownloadsCsv
+     */
+    protected $exportDownloadsCsv;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportDownloadsCsv = new ExportDownloadsCsv(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('setSaveParametersInSession')
+            ->willReturnSelf();
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsv')
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('createBlock')
+            ->with('Magento\Reports\Block\Adminhtml\Product\Downloads\Grid')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('products_downloads.csv', $content);
+
+        $this->exportDownloadsCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b10f29b369590a8e2d154bb59abb2007fe34aa7
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportDownloadsExcelTest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportDownloadsExcel;
+
+class ExportDownloadsExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportDownloadsExcel
+     */
+    protected $exportDownloadsExcel;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportDownloadsExcel = new ExportDownloadsExcel(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+        $fileName = 'products_downloads.xml';
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('setSaveParametersInSession')
+            ->willReturnSelf();
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcel')
+            ->with($fileName)
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('createBlock')
+            ->with('Magento\Reports\Block\Adminhtml\Product\Downloads\Grid')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with($fileName, $content);
+
+        $this->exportDownloadsExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..010a123afc7e3e61d5ac8c541f0292bd94dd7cdf
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockCsvTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportLowstockCsv;
+
+class ExportLowstockCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportLowstockCsv
+     */
+    protected $exportLowstockCsv;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportLowstockCsv = new ExportLowstockCsv(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.block.report.product.lowstock.grid', 'grid.export')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('products_lowstock.csv', $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportLowstockCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..257b08e7bcbf44e47b5a855985482908b593af1d
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportLowstockExcelTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportLowstockExcel;
+
+class ExportLowstockExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportLowstockExcel
+     */
+    protected $exportLowstockExcel;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportLowstockExcel = new ExportLowstockExcel(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.block.report.product.lowstock.grid', 'grid.export')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('products_lowstock.xml', $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportLowstockExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..54d5303ad317e706fa733fe13c7208a8d09d6a7d
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldCsvTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportSoldCsv;
+
+class ExportSoldCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportSoldCsv
+     */
+    protected $exportSoldCsv;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportSoldCsv = new ExportSoldCsv(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('products_ordered.csv', $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportSoldCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cec703d778b347b536444ac4dafa1fa1937feb4f
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportSoldExcelTest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportSoldExcel;
+
+class ExportSoldExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportSoldExcel
+     */
+    protected $exportSoldExcel;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->exportSoldExcel = new ExportSoldExcel(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+        $fileName = 'products_ordered.xml';
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->with($fileName)
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('getChildBlock')
+            ->with('adminhtml.report.grid', 'grid.export')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with($fileName, $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportSoldExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedCsvTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1e4cafbf627af407b1470049d4b81a76c510009
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedCsvTest.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportViewedCsv;
+
+class ExportViewedCsvTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportViewedCsv
+     */
+    protected $exportViewedCsv;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $helperMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->helperMock = $this->getMockBuilder('Magento\Backend\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('get')
+            ->willReturn($this->helperMock);
+
+        $this->contextMock->expects($this->any())->method('getObjectManager')->willReturn($this->objectManagerMock);
+
+        $this->exportViewedCsv = new ExportViewedCsv(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+        $fileName = 'products_mostviewed.csv';
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('createBlock')
+            ->with('Magento\Reports\Block\Adminhtml\Product\Viewed\Grid')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with($fileName, $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportViewedCsv->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedExcelTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedExcelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..93c68d3ff695049a73d6f7df11a93d2c6ce2092f
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ExportViewedExcelTest.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\ExportViewedExcel;
+
+class ExportViewedExcelTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\ExportViewedExcel
+     */
+    protected $exportViewedExcel;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $helperMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->helperMock = $this->getMockBuilder('Magento\Backend\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('get')
+            ->willReturn($this->helperMock);
+
+        $this->contextMock->expects($this->any())->method('getObjectManager')->willReturn($this->objectManagerMock);
+
+        $this->exportViewedExcel = new ExportViewedExcel(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $content = ['export'];
+        $fileName = 'products_mostviewed.xml';
+
+        $this->abstractBlockMock
+            ->expects($this->once())
+            ->method('getExcelFile')
+            ->with($fileName)
+            ->willReturn($content);
+
+        $this->layoutMock
+            ->expects($this->once())
+            ->method('createBlock')
+            ->with('Magento\Reports\Block\Adminhtml\Product\Viewed\Grid')
+            ->willReturn($this->abstractBlockMock);
+
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with($fileName, $content, \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR);
+
+        $this->exportViewedExcel->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/LowstockTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/LowstockTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6120128d828fb902d8a10c9cc5956dd14d67e33d
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/LowstockTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\Lowstock;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class LowstockTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\Lowstock
+     */
+    protected $lowstock;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->lowstock = new Lowstock(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Low Stock Report'));
+
+        $this->viewMock
+            ->expects($this->once())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_products_lowstock');
+
+        $this->breadcrumbsBlockMock
+            ->expects($this->exactly(3))
+            ->method('addLink')
+            ->withConsecutive(
+                [new Phrase('Reports'), new Phrase('Reports')],
+                [new Phrase('Products'), new Phrase('Products')],
+                [new Phrase('Low Stock'), new Phrase('Low Stock')]
+            );
+
+        $this->lowstock->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/SoldTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/SoldTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b1b27e748e88f47ade203433a846b7360566c4b
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/SoldTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\Sold;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class SoldTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\Sold
+     */
+    protected $sold;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->sold = new Sold(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Ordered Products Report'));
+
+        $this->viewMock
+            ->expects($this->once())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_products_sold');
+
+        $this->breadcrumbsBlockMock
+            ->expects($this->exactly(3))
+            ->method('addLink')
+            ->withConsecutive(
+                [new Phrase('Reports'), new Phrase('Reports')],
+                [new Phrase('Products'), new Phrase('Products')],
+                [new Phrase('Products Ordered'), new Phrase('Products Ordered')]
+            );
+
+        $this->sold->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ViewedTest.php b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ViewedTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d87c428b3933a214d1d16fb68058e37007a5728
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Unit/Controller/Adminhtml/Report/Product/ViewedTest.php
@@ -0,0 +1,223 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Reports\Test\Unit\Controller\Adminhtml\Report\Product;
+
+use Magento\Reports\Controller\Adminhtml\Report\Product\Viewed;
+use Magento\Framework\Object;
+use Magento\Framework\Phrase;
+
+class ViewedTest extends \Magento\Reports\Test\Unit\Controller\Adminhtml\Report\AbstractControllerTest
+{
+    /**
+     * @var \Magento\Reports\Controller\Adminhtml\Report\Product\Viewed
+     */
+    protected $viewed;
+
+    /**
+     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $dateMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $helperMock;
+
+    /**
+     * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManagerMock;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->dateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\Filter\Date')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $flagMock = $this->getMockBuilder('Magento\Reports\Model\Flag')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $flagMock
+            ->expects($this->any())
+            ->method('setReportFlagCode')
+            ->willReturnSelf();
+        $flagMock
+            ->expects($this->any())
+            ->method('loadSelf')
+            ->willReturnSelf();
+
+        $this->helperMock = $this->getMockBuilder('Magento\Backend\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('create')
+            ->with('Magento\Reports\Model\Flag')
+            ->willReturn($flagMock);
+
+        $this->messageManagerMock = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $flagMock = $this->getMockBuilder('Magento\Framework\App\ActionFlag')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $responseMock = $this->getMockBuilder('Magento\Framework\App\ResponseInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['setRedirect', 'sendResponse'])
+            ->getMock();
+
+        $this->contextMock->expects($this->any())->method('getObjectManager')->willReturn($this->objectManagerMock);
+        $this->contextMock->expects($this->any())->method('getHelper')->willReturn($this->helperMock);
+        $this->contextMock->expects($this->any())->method('getMessageManager')->willReturn($this->messageManagerMock);
+        $this->contextMock->expects($this->any())->method('getActionFlag')->willReturn($flagMock);
+        $this->contextMock->expects($this->any())->method('getResponse')->willReturn($responseMock);
+
+        $this->viewed = new Viewed(
+            $this->contextMock,
+            $this->fileFactoryMock,
+            $this->dateMock
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('get')
+            ->willReturn($this->helperMock);
+
+        $titleMock = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $titleMock
+            ->expects($this->once())
+            ->method('prepend')
+            ->with(new Phrase('Product Views Report'));
+
+        $this->viewMock
+            ->expects($this->once())
+            ->method('getPage')
+            ->willReturn(
+                new Object(
+                    ['config' => new Object(
+                        ['title' => $titleMock]
+                    )]
+                )
+            );
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->with('Magento_Reports::report_products_viewed');
+
+        $this->breadcrumbsBlockMock
+            ->expects($this->exactly(3))
+            ->method('addLink')
+            ->withConsecutive(
+                [new Phrase('Reports'), new Phrase('Reports')],
+                [new Phrase('Products'), new Phrase('Products')],
+                [new Phrase('Products Most Viewed Report'), new Phrase('Products Most Viewed Report')]
+            );
+
+        $this->viewMock
+            ->expects($this->once())
+            ->method('renderLayout');
+
+        $this->viewed->execute();
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecuteWithException()
+    {
+        $errorText = new Phrase(
+            'An error occurred while showing the product views report. ' .
+            'Please review the log and try again.'
+        );
+
+        $logMock = $this->getMockBuilder('Psr\Log\LoggerInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $sessionMock = $this->getMockBuilder('Magento\Backend\Model\Session')
+            ->setMethods(['setIsUrlNotice'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('get')
+            ->will(
+                $this->returnValueMap(
+                    [
+                        ['Psr\Log\LoggerInterface', $logMock],
+                        ['Magento\Backend\Model\Auth\Session', $sessionMock]
+                    ]
+                )
+            );
+
+        $this->messageManagerMock
+            ->expects($this->once())
+            ->method('addError')
+            ->with($errorText);
+
+        $logMock
+            ->expects($this->once())
+            ->method('critical');
+        $sessionMock
+            ->expects($this->once())
+            ->method('setIsUrlNotice');
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->willThrowException(new \Exception());
+
+        $this->viewed->execute();
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecuteWithLocalizedException()
+    {
+        $errorText = new Phrase('Error');
+
+        $this->messageManagerMock
+            ->expects($this->once())
+            ->method('addError')
+            ->with($errorText);
+
+        $this->menuBlockMock
+            ->expects($this->once())
+            ->method('setActive')
+            ->willThrowException(new \Magento\Framework\Exception\LocalizedException($errorText));
+
+        $this->viewed->execute();
+    }
+}
diff --git a/app/code/Magento/Reports/Test/Unit/Model/Resource/Order/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/Resource/Order/CollectionTest.php
index 22a6bb1be49c2719d81af2339c7feef95295a195..b2414a6b388de779cec6e34ce0a06527085f9996 100644
--- a/app/code/Magento/Reports/Test/Unit/Model/Resource/Order/CollectionTest.php
+++ b/app/code/Magento/Reports/Test/Unit/Model/Resource/Order/CollectionTest.php
@@ -102,7 +102,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ->getMock();
         $this->managerMock = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface')
             ->getMock();
-        $this->entitySnapshotMock = $this->getMockBuilder('Magento\Sales\Model\Resource\EntitySnapshot')
+        $this->entitySnapshotMock = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\VersionControl\Snapshot')
             ->disableOriginalConstructor()
             ->getMock();
         $this->helperMock = $this->getMockBuilder('Magento\Framework\DB\Helper')
diff --git a/app/code/Magento/Reports/Test/Unit/Model/Resource/Quote/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/Resource/Quote/CollectionTest.php
index a8bea7e05133cba46c465b46f3d6e9f170559d3c..3f24f1a6d7e7be362ab20453647af0c9dd6c7952 100644
--- a/app/code/Magento/Reports/Test/Unit/Model/Resource/Quote/CollectionTest.php
+++ b/app/code/Magento/Reports/Test/Unit/Model/Resource/Quote/CollectionTest.php
@@ -42,6 +42,11 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
      */
     protected $entityFactoryMock;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot
+     */
+    protected $entitySnapshotMock;
+
     protected function setUp()
     {
         $this->selectMock = $this->getMockBuilder('Magento\Framework\DB\Select')
@@ -81,6 +86,10 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         $this->entityFactoryMock = $this->getMockBuilder('Magento\Framework\Data\Collection\EntityFactory')
             ->disableOriginalConstructor()
             ->getMock();
+        $this->entitySnapshotMock = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\VersionControl\Snapshot')
+            ->disableOriginalConstructor()
+            ->setMethods(['registerSnapshot'])
+            ->getMock();
 
         $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->model = $helper->getObject(
@@ -89,7 +98,8 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'customerResource' => $this->customerResourceMock,
                 'resource' => $this->resourceMock,
                 'fetchStrategy' => $this->fetchStrategyMock,
-                'entityFactory' => $this->entityFactoryMock
+                'entityFactory' => $this->entityFactoryMock,
+                'entitySnapshot' => $this->entitySnapshotMock
             ]
         );
     }
@@ -154,7 +164,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ->withAnyParameters()
             ->willReturn($customerId);
 
-        $itemMock = $this->getMockBuilder('Magento\Framework\Object')
+        $itemMock = $this->getMockBuilder('Magento\Framework\Model\AbstractModel')
             ->disableOriginalConstructor()
             ->getMock();
         $itemMock->expects($this->once())
diff --git a/app/code/Magento/Sales/Model/AbstractModel.php b/app/code/Magento/Sales/Model/AbstractModel.php
index 9f409bcbd76bb2dfacf96116b06584e6c70d12b3..e018d84d95c2d6b3674ea63b5961d925b08d91e2 100644
--- a/app/code/Magento/Sales/Model/AbstractModel.php
+++ b/app/code/Magento/Sales/Model/AbstractModel.php
@@ -45,16 +45,6 @@ abstract class AbstractModel extends AbstractExtensibleModel
         );
     }
 
-    /**
-     * Returns _eventPrefix
-     *
-     * @return string
-     */
-    public function getEventPrefix()
-    {
-        return $this->_eventPrefix;
-    }
-
     /**
      * Returns _eventObject
      *
diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php
index d0c564c01bf619a5babab63eefe194733eb8242c..56d1c892985da5d8423381fa5d9080be6de2564c 100644
--- a/app/code/Magento/Sales/Model/Order/Creditmemo.php
+++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php
@@ -373,6 +373,28 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt
         return false;
     }
 
+    /**
+     * Returns assigned invoice
+     *
+     * @return Invoice|null
+     */
+    public function getInvoice()
+    {
+        return $this->getData('invoice');
+    }
+
+    /**
+     * Sets invoice
+     *
+     * @param Invoice $invoice
+     * @return $this
+     */
+    public function setInvoice(Invoice $invoice)
+    {
+        $this->setData('invoice', $invoice);
+        return $this;
+    }
+
     /**
      * Check creditmemo cancel action availability
      *
diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php
index 6ecf8a298cd1a663af73808e5c79eb6b664d458a..269f9e0187798ed74eb919d31c88b6aada5a6bd5 100644
--- a/app/code/Magento/Sales/Model/Order/Payment.php
+++ b/app/code/Magento/Sales/Model/Order/Payment.php
@@ -186,6 +186,40 @@ class Payment extends Info implements OrderPaymentInterface
         return $this->_order;
     }
 
+    /**
+     * Sets transaction id for current payment
+     *
+     * @param string $transactionId
+     * @return $this
+     */
+    public function setTransactionId($transactionId)
+    {
+        $this->setData('transaction_id', $transactionId);
+        return $this;
+    }
+
+    /**
+     * Sets transaction close flag
+     *
+     * @param bool $isClosed
+     * @return $this
+     */
+    public function setIsTransactionClosed($isClosed)
+    {
+        $this->setData('is_transaction_closed', (bool)$isClosed);
+        return $this;
+    }
+
+    /**
+     * Returns transaction parent
+     *
+     * @return string
+     */
+    public function getParentTransactionId()
+    {
+        return $this->getData('parent_transaction_id');
+    }
+
     /**
      * Check order payment capture action availability
      *
@@ -655,6 +689,30 @@ class Payment extends Info implements OrderPaymentInterface
         return $this->_void(false, $amount);
     }
 
+    /**
+     * Sets creditmemo for current payment
+     *
+     * @param Creditmemo $creditmemo
+     * @return $this
+     */
+    public function setCreditmemo(Creditmemo $creditmemo)
+    {
+        $this->setData('creditmemo', $creditmemo);
+        return $this;
+    }
+
+    /**
+     * Returns Creditmemo assigned for this payment
+     *
+     * @return Creditmemo|null
+     */
+    public function getCreditmemo()
+    {
+        return $this->getData('creditmemo') instanceof Creditmemo
+            ? $this->getData('creditmemo')
+            : null;
+    }
+
     /**
      * Refund payment online or offline, depending on whether there is invoice set in the creditmemo instance
      * Updates transactions hierarchy, if required
diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
index 5d7a2efedd93f35bca87d852441edc3c1ac5e07a..40d528fbeb8d5fec707f059b6cb5e7a77c0c6bcc 100644
--- a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
+++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
@@ -614,8 +614,12 @@ class Transaction extends AbstractModel implements TransactionInterface
     {
         $this->_verifyThisTransactionExists();
         if (null === $this->_paymentObject && $shouldLoad) {
+            /** @var \Magento\Sales\Model\Order\Payment $payment */
             $payment = $this->_paymentFactory->create()->load($this->getPaymentId());
             if ($payment->getId()) {
+                if (!$payment->getOrder()) {
+                    $payment->setOrder($this->getOrder());
+                }
                 $this->setOrderPaymentObject($payment);
             }
         }
diff --git a/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php b/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php
index b0e4edf8dd32d65c367b71a823f16dca05c47219..d32dc6ee981c70f1d498d27d15ac04fb7f507d87 100644
--- a/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php
+++ b/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php
@@ -9,41 +9,13 @@ namespace Magento\Sales\Model\Resource\Collection;
  * Flat sales abstract collection
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-abstract class AbstractCollection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+abstract class AbstractCollection extends \Magento\Framework\Model\Resource\Db\VersionControl\Collection
 {
     /**
      * @var \Zend_Db_Select
      */
     protected $_countSelect;
 
-    /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot
-     */
-    protected $entitySnapshot;
-
-    /**
-     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Psr\Log\LoggerInterface $logger
-     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
-     * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
-     * @param string|null $connection
-     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
-     * @throws \Zend_Exception
-     */
-    public function __construct(
-        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Psr\Log\LoggerInterface $logger,
-        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
-        \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
-        $connection = null,
-        \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
-    ) {
-        $this->entitySnapshot = $entitySnapshot;
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
-    }
-
     /**
      * Set select count sql
      *
@@ -233,63 +205,4 @@ abstract class AbstractCollection extends \Magento\Framework\Model\Resource\Db\C
     {
         return $this;
     }
-
-    /**
-     * Returns a collection item that corresponds to the fetched row
-     * and moves the internal data pointer ahead
-     * All returned rows marked as non changed to prevent unnecessary persistence operations
-     *
-     * @return  \Magento\Framework\Object|bool
-     */
-    public function fetchItem()
-    {
-        if (null === $this->_fetchStmt) {
-            $this->_renderOrders()->_renderLimit();
-
-            $this->_fetchStmt = $this->getConnection()->query($this->getSelect());
-        }
-        $data = $this->_fetchStmt->fetch();
-        if (!empty($data) && is_array($data)) {
-            /**@var \Magento\Sales\Model\AbstractModel $item */
-            $item = $this->getNewEmptyItem();
-            if ($this->getIdFieldName()) {
-                $item->setIdFieldName($this->getIdFieldName());
-            }
-            $item->setData($data);
-            $this->entitySnapshot->registerSnapshot($item);
-            return $item;
-        }
-        return false;
-    }
-
-    /**
-     * Load data with filter in place
-     * All returned rows marked as non changed to prevent unnecessary persistence operations
-     *
-     * @param   bool $printQuery
-     * @param   bool $logQuery
-     * @return  $this
-     */
-    public function loadWithFilter($printQuery = false, $logQuery = false)
-    {
-        $this->_beforeLoad();
-        $this->_renderFilters()->_renderOrders()->_renderLimit();
-        $this->printLogQuery($printQuery, $logQuery);
-        $data = $this->getData();
-        $this->resetData();
-        if (is_array($data)) {
-            foreach ($data as $row) {
-                $item = $this->getNewEmptyItem();
-                if ($this->getIdFieldName()) {
-                    $item->setIdFieldName($this->getIdFieldName());
-                }
-                $item->setData($row);
-                $this->entitySnapshot->registerSnapshot($item);
-                $this->addItem($item);
-            }
-        }
-        $this->_setIsLoaded();
-        $this->_afterLoad();
-        return $this;
-    }
 }
diff --git a/app/code/Magento/Sales/Model/Resource/EntityAbstract.php b/app/code/Magento/Sales/Model/Resource/EntityAbstract.php
index 44989d28a214cc6f2531e7313591ac3d9bf27d68..b095ebf88a3ae1d73b0e28d07b9eceabc06d3d3b 100644
--- a/app/code/Magento/Sales/Model/Resource/EntityAbstract.php
+++ b/app/code/Magento/Sales/Model/Resource/EntityAbstract.php
@@ -5,9 +5,11 @@
  */
 namespace Magento\Sales\Model\Resource;
 
-use Magento\Framework\Model\Resource\Db\AbstractDb;
-use Magento\Sales\Model\EntityInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\SalesSequence\Model\Manager;
+use Magento\Sales\Model\EntityInterface;
 
 /**
  * Abstract sales entity provides to its children knowledge about eventPrefix and eventObject
@@ -47,46 +49,33 @@ abstract class EntityAbstract extends AbstractDb
      */
     protected $attribute;
 
-
     /**
      * @var Manager
      */
     protected $sequenceManager;
 
-    /**
-     * @var EntitySnapshot
-     */
-    protected $entitySnapshot;
-
-    /**
-     * @var EntityRelationComposite
-     */
-    protected $entityRelationComposite;
-
     /**
      * @param \Magento\Framework\Model\Resource\Db\Context $context
+     * @param Snapshot $entitySnapshot
+     * @param RelationComposite $entityRelationComposite
      * @param Attribute $attribute
      * @param Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param EntityRelationComposite $entityRelationComposite
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        EntityRelationComposite $entityRelationComposite,
         $resourcePrefix = null
     ) {
         $this->attribute = $attribute;
         $this->sequenceManager = $sequenceManager;
-        $this->entitySnapshot = $entitySnapshot;
-        $this->entityRelationComposite = $entityRelationComposite;
         if ($resourcePrefix === null) {
             $resourcePrefix = 'sales';
         }
-        parent::__construct($context, $resourcePrefix);
+        parent::__construct($context, $entitySnapshot, $entityRelationComposite, $resourcePrefix);
     }
 
     /**
@@ -171,83 +160,39 @@ abstract class EntityAbstract extends AbstractDb
     }
 
     /**
-     * Perform actions after object delete
-     *
-     * @param \Magento\Framework\Model\AbstractModel $object
-     * @return $this
+     * @inheritdoc
      */
-    protected function _afterDelete(\Magento\Framework\Model\AbstractModel $object)
+    protected function updateObject(\Magento\Framework\Model\AbstractModel $object)
     {
-        parent::_afterDelete($object);
-        return $this;
+        $condition = $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $object->getId());
+        $data = $this->_prepareDataForSave($object);
+        unset($data[$this->getIdFieldName()]);
+        $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
     }
 
     /**
-     * Perform actions after object load, mark loaded data as data without changes
-     *
-     * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\Object $object
-     * @return $this
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     * @inheritdoc
      */
-    protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
+    protected function saveNewObject(\Magento\Framework\Model\AbstractModel $object)
     {
-        $this->entitySnapshot->registerSnapshot($object);
-        return $this;
+        $bind = $this->_prepareDataForSave($object);
+        unset($bind[$this->getIdFieldName()]);
+        $this->_getWriteAdapter()->insert($this->getMainTable(), $bind);
+        $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));
+        if ($this->_useIsObjectNew) {
+            $object->isObjectNew(false);
+        }
     }
 
     /**
-     * Save entity
+     * Perform actions after object delete
      *
      * @param \Magento\Framework\Model\AbstractModel $object
      * @return $this
-     * @throws \Exception
      */
-    public function save(\Magento\Framework\Model\AbstractModel $object)
+    protected function _afterDelete(\Magento\Framework\Model\AbstractModel $object)
     {
-        if ($object->isDeleted()) {
-            return $this->delete($object);
-        }
-        if (!$this->entitySnapshot->isModified($object)) {
-            $this->entityRelationComposite->processRelations($object);
-            return $this;
-        }
-        $this->beginTransaction();
-
-        try {
-            $object->validateBeforeSave();
-            $object->beforeSave();
-            if ($object->isSaveAllowed()) {
-                $this->_serializeFields($object);
-                $this->_beforeSave($object);
-                $this->_checkUnique($object);
-                $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
-                if ($object->getId() !== null && (!$this->_useIsObjectNew || !$object->isObjectNew())) {
-                    $condition = $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $object->getId());
-                    $data = $this->_prepareDataForSave($object);
-                    unset($data[$this->getIdFieldName()]);
-                    $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
-                } else {
-                    $bind = $this->_prepareDataForSave($object);
-                    unset($bind[$this->getIdFieldName()]);
-                    $this->_getWriteAdapter()->insert($this->getMainTable(), $bind);
-                    $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));
-                    if ($this->_useIsObjectNew) {
-                        $object->isObjectNew(false);
-                    }
-                }
-                $this->unserializeFields($object);
-                $this->_afterSave($object);
-                $this->entitySnapshot->registerSnapshot($object);
-                $object->afterSave();
-                $this->entityRelationComposite->processRelations($object);
-            }
-            $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
-            $object->setHasDataChanges(false);
-        } catch (\Exception $e) {
-            $this->rollBack();
-            $object->setHasDataChanges(true);
-            throw $e;
-        }
+        parent::_afterDelete($object);
         return $this;
     }
 }
diff --git a/app/code/Magento/Sales/Model/Resource/EntityMetadata.php b/app/code/Magento/Sales/Model/Resource/EntityMetadata.php
deleted file mode 100644
index d39a9a63cb5ab9b25dd11321a01a4dbdbb8560ab..0000000000000000000000000000000000000000
--- a/app/code/Magento/Sales/Model/Resource/EntityMetadata.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Sales\Model\Resource;
-
-use Magento\Sales\Model\AbstractModel;
-
-/**
- * Class EntityMetadata represents a list of entity fields that are applicable for persistence operations
- */
-class EntityMetadata
-{
-    /**
-     * @var array
-     */
-    protected $metadataInfo = [];
-
-    /**
-     * Returns list of entity fields that are applicable for persistence operations
-     *
-     * @param AbstractModel $entity
-     * @return array
-     * @throws \Magento\Framework\Exception\LocalizedException
-     */
-    public function getFields(AbstractModel $entity)
-    {
-        if (!isset($this->metadataInfo[get_class($entity)])) {
-            $this->metadataInfo[get_class($entity)] =
-                $entity->getResource()->getReadConnection()->describeTable(
-                    $entity->getResource()->getMainTable()
-                );
-        }
-        return $this->metadataInfo[get_class($entity)];
-    }
-}
diff --git a/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php b/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php
deleted file mode 100644
index 72d26e580e8dff1b8940b82ca4433c5cfa27e69f..0000000000000000000000000000000000000000
--- a/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Sales\Model\Resource;
-
-/**
- * Interface EntityRelationInterface
- */
-interface EntityRelationInterface
-{
-    /**
-     * Process object relations
-     *
-     * @param \Magento\Sales\Model\AbstractModel $object
-     * @return void
-     */
-    public function processRelation(\Magento\Sales\Model\AbstractModel $object);
-}
diff --git a/app/code/Magento/Sales/Model/Resource/EntitySnapshot.php b/app/code/Magento/Sales/Model/Resource/EntitySnapshot.php
deleted file mode 100644
index 47a008445ebf5f3807944a1115a39d5d72f86c87..0000000000000000000000000000000000000000
--- a/app/code/Magento/Sales/Model/Resource/EntitySnapshot.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Sales\Model\Resource;
-
-use Magento\Framework\Model\AbstractModel;
-
-/**
- * Class EntitySnapshot register snapshot of entity data, for tracking changes
- */
-class EntitySnapshot
-{
-    /**
-     * Array of snapshots of entities data
-     *
-     * @var array
-     */
-    protected $snapshotData = [];
-
-    /**
-     * @var EntityMetadata
-     */
-    protected $entityMetadata;
-
-    /**
-     * Initialization
-     *
-     * @param EntityMetadata $entityMetadata
-     */
-    public function __construct(
-        EntityMetadata $entityMetadata
-    ) {
-        $this->entityMetadata = $entityMetadata;
-    }
-
-    /**
-     * Register snapshot of entity data, for tracking changes
-     *
-     * @param AbstractModel $entity
-     * @return void
-     */
-    public function registerSnapshot(AbstractModel $entity)
-    {
-        $data = array_intersect_key($entity->getData(), $this->entityMetadata->getFields($entity));
-        $this->snapshotData[get_class($entity)][$entity->getId()] = $data;
-    }
-
-    /**
-     * Check is current entity has changes, by comparing current object state with stored snapshot
-     *
-     * @param AbstractModel $entity
-     * @return bool
-     */
-    public function isModified(AbstractModel $entity)
-    {
-        if (!$entity->getId()) {
-            return true;
-        }
-        if (!isset($this->snapshotData[get_class($entity)][$entity->getId()])) {
-            return true;
-        }
-        $data = array_intersect_key($entity->getData(), $this->entityMetadata->getFields($entity));
-        if ($data !== $this->snapshotData[get_class($entity)][$entity->getId()]) {
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/app/code/Magento/Sales/Model/Resource/Order.php b/app/code/Magento/Sales/Model/Resource/Order.php
index 24b205c079d7266f3f010806d039466e25f2b25c..f44ca611da317a9068111add4782c16dec481591 100644
--- a/app/code/Magento/Sales/Model/Resource/Order.php
+++ b/app/code/Magento/Sales/Model/Resource/Order.php
@@ -11,6 +11,8 @@ use Magento\SalesSequence\Model\Manager;
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
 use Magento\Sales\Model\Resource\Order\Handler\State as StateHandler;
 use Magento\Sales\Model\Spi\OrderResourceInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
 
 /**
  * Flat sales order resource
@@ -53,27 +55,27 @@ class Order extends SalesResource implements OrderResourceInterface
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param Attribute $attribute
      * @param Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param RelationComposite $entityRelationComposite
      * @param StateHandler $stateHandler
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        RelationComposite $entityRelationComposite,
         Attribute $attribute,
         Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        EntityRelationComposite $entityRelationComposite,
         StateHandler $stateHandler,
         $resourcePrefix = null
     ) {
         $this->stateHandler = $stateHandler;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
@@ -138,8 +140,6 @@ class Order extends SalesResource implements OrderResourceInterface
      */
     protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
     {
-        /** @var \Magento\Sales\Model\Order $object */
-        $this->stateHandler->check($object);
         if (!$object->getId()) {
             /** @var \Magento\Store\Model\Store $store */
             $store = $object->getStore();
@@ -161,4 +161,14 @@ class Order extends SalesResource implements OrderResourceInterface
         }
         return parent::_beforeSave($object);
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save(\Magento\Framework\Model\AbstractModel $object)
+    {
+        /** @var \Magento\Sales\Model\Order $object */
+        $this->stateHandler->check($object);
+        return parent::save($object);
+    }
 }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Address.php b/app/code/Magento/Sales/Model/Resource/Order/Address.php
index 878bfdf6a8ad9fd6bbf30f71642c3f6fe8bf64d1..760895576385ec3fd42c8598f2f34e9e590bba1a 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Address.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Address.php
@@ -7,7 +7,7 @@ namespace Magento\Sales\Model\Resource\Order;
 
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
 use Magento\Sales\Model\Spi\OrderAddressResourceInterface;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 
 /**
  * Flat sales order address resource
@@ -35,18 +35,18 @@ class Address extends SalesResource implements OrderAddressResourceInterface
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Sales\Model\Order\Address\Validator $validator
      * @param \Magento\Sales\Model\Resource\GridPool $gridPool
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Order\Address\Validator $validator,
         \Magento\Sales\Model\Resource\GridPool $gridPool,
         $resourcePrefix = null
@@ -55,10 +55,10 @@ class Address extends SalesResource implements OrderAddressResourceInterface
         $this->gridPool = $gridPool;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Collection.php
index 4254242321fa2c11b6bf60fb819bc2c74a6ce615..2e68417ba67ee7523c848d233c6634f4101d51b8 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Collection.php
@@ -39,7 +39,7 @@ class Collection extends AbstractCollection implements OrderSearchResultInterfac
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\DB\Helper $coreResourceHelper
      * @param string|null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
@@ -49,7 +49,7 @@ class Collection extends AbstractCollection implements OrderSearchResultInterfac
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\DB\Helper $coreResourceHelper,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php
index f0a5c4d693428efed1a537f29db22df1af9758cb..255d4cd4388f1c67652a252c1737b57bd23f6890 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php
@@ -9,7 +9,7 @@ use Magento\Framework\App\Resource as AppResource;
 use Magento\SalesSequence\Model\Manager;
 use Magento\Sales\Model\Resource\Attribute;
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\CreditmemoResourceInterface;
 
 /**
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php
index 3056759346691ebb39edfbd90f0cbb5adb160382..304677688895668a68a1650f1a24ef9dbec0bfdd 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php
@@ -6,7 +6,7 @@
 namespace Magento\Sales\Model\Resource\Order\Creditmemo;
 
 use Magento\Sales\Model\Resource\EntityAbstract;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\CreditmemoCommentResourceInterface;
 
 /**
@@ -34,27 +34,27 @@ class Comment extends EntityAbstract implements CreditmemoCommentResourceInterfa
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Sales\Model\Order\Creditmemo\Comment\Validator $validator
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Order\Creditmemo\Comment\Validator $validator,
         $resourcePrefix = null
     ) {
         $this->validator = $validator;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
index 85eeb520f00038005fc02d39303e096723775948..c24cfddac98ab0f1e998c390ed099e04a8518234 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
@@ -23,7 +23,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Creditmemo\Grid\Col
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
      */
@@ -32,7 +32,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Creditmemo\Grid\Col
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Registry $registryManager,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php
index 674e9552b7ae54cc956fa539c09ed3fef49e1933..6aabb91138517a7696271fc16063a1fea8876789 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php
@@ -6,12 +6,12 @@
 
 namespace Magento\Sales\Model\Resource\Order\Creditmemo;
 
-use Magento\Sales\Model\Resource\EntityRelationInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
 
 /**
  * Class Relation
  */
-class Relation implements EntityRelationInterface
+class Relation implements RelationInterface
 {
     /**
      * @var Item
@@ -38,11 +38,11 @@ class Relation implements EntityRelationInterface
     /**
      * Process relations for CreditMemo
      *
-     * @param \Magento\Sales\Model\AbstractModel $object
+     * @param \Magento\Framework\Model\AbstractModel $object
      * @throws \Exception
      * @return void
      */
-    public function processRelation(\Magento\Sales\Model\AbstractModel $object)
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
     {
         /** @var \Magento\Sales\Model\Order\Creditmemo $object */
         if (null !== $object->getItems()) {
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice.php
index 6fb7504394cf8f3c813089146dbeb577b19cb448..33a095ce60c66d85b5ff05d8e4c4c8ec4568f7ed 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Invoice.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice.php
@@ -9,7 +9,7 @@ use Magento\Framework\App\Resource;
 use Magento\SalesSequence\Model\Manager;
 use Magento\Sales\Model\Resource\Attribute;
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\InvoiceResourceInterface;
 
 /**
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php
index f54208f1e5d5d11edc3ea35408223a2423752ea0..ad15a0a99dfd38d804ad68c407a63726512d4d75 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php
@@ -6,7 +6,7 @@
 namespace Magento\Sales\Model\Resource\Order\Invoice;
 
 use Magento\Sales\Model\Resource\EntityAbstract;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\InvoiceCommentResourceInterface;
 
 /**
@@ -34,27 +34,27 @@ class Comment extends EntityAbstract implements InvoiceCommentResourceInterface
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Sales\Model\Order\Invoice\Comment\Validator $validator
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Order\Invoice\Comment\Validator $validator,
         $resourcePrefix = null
     ) {
         $this->validator = $validator;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
index 6f6d71c655ebb10c595db011e3f5777c6e1a1754..2a79e1c08d2575123511f230b5270453baec11da 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
@@ -17,7 +17,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Invoice\Grid\Collec
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\Registry $registryManager
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
@@ -27,7 +27,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Invoice\Grid\Collec
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Registry $registryManager,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php
index 80f10e6adbaad2b6d2a61cdbfd17d9f2223ca2ec..b2da74d1d74333752376e0e0df64f2f99ad75a24 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php
@@ -6,14 +6,14 @@
 
 namespace Magento\Sales\Model\Resource\Order\Invoice;
 
-use Magento\Sales\Model\Resource\EntityRelationInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
 use Magento\Sales\Model\Resource\Order\Invoice\Item as InvoiceItemResource;
 use Magento\Sales\Model\Resource\Order\Invoice\Comment as InvoiceCommentResource;
 
 /**
  * Class Relation
  */
-class Relation implements EntityRelationInterface
+class Relation implements RelationInterface
 {
     /**
      * @var InvoiceItemResource
@@ -40,11 +40,11 @@ class Relation implements EntityRelationInterface
     /**
      * Process relations for Shipment
      *
-     * @param \Magento\Sales\Model\AbstractModel $object
+     * @param \Magento\Framework\Model\AbstractModel $object
      * @return void
      * @throws \Exception
      */
-    public function processRelation(\Magento\Sales\Model\AbstractModel $object)
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
     {
         /** @var $object \Magento\Sales\Model\Order\Invoice */
         if (null !== $object->getItems()) {
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
index 8f73ee346165a646e8e8939bcdae16d6d64256b4..284dd3dc81937a4b7da960ff0a90abb074481e4b 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
@@ -32,7 +32,7 @@ class Collection extends AbstractCollection implements OrderPaymentSearchResultI
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
      */
@@ -41,7 +41,7 @@ class Collection extends AbstractCollection implements OrderPaymentSearchResultI
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Relation.php
index 749de294fe06d4057c2a990d875821bc5e45840c..f832d285383280a67360c2ea6e28066beac0e6b9 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Relation.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Relation.php
@@ -6,9 +6,8 @@
 
 namespace Magento\Sales\Model\Resource\Order;
 
-use Magento\Sales\Model\AbstractModel;
 use Magento\Sales\Model\Resource\Order\Handler\Address as AddressHandler;
-use Magento\Sales\Model\Resource\EntityRelationInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
 use Magento\Sales\Model\Resource\Order\Item as OrderItemResource;
 use Magento\Sales\Model\Resource\Order\Payment as OrderPaymentResource;
 use Magento\Sales\Model\Resource\Order\Status\History as OrderStatusHistoryResource;
@@ -16,7 +15,7 @@ use Magento\Sales\Model\Resource\Order\Status\History as OrderStatusHistoryResou
 /**
  * Class Relation
  */
-class Relation implements EntityRelationInterface
+class Relation implements RelationInterface
 {
     /**
      * @var AddressHandler
@@ -59,11 +58,11 @@ class Relation implements EntityRelationInterface
     /**
      * Save relations for Order
      *
-     * @param AbstractModel $object
+     * @param \Magento\Framework\Model\AbstractModel $object
      * @return void
      * @throws \Exception
      */
-    public function processRelation(AbstractModel $object)
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
     {
         /** @var \Magento\Sales\Model\Order $object */
         $this->addressHandler->removeEmptyAddresses($object);
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment.php
index 8fe7b8afa972e655edfcaed864336d697ef0791f..32293e81802cc33e1a738ce2acd867b88117d82b 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment.php
@@ -9,7 +9,7 @@ use Magento\Framework\App\Resource as AppResource;
 use Magento\SalesSequence\Model\Manager;
 use Magento\Sales\Model\Resource\Attribute;
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Resource\Order\Shipment\Grid as ShipmentGrid;
 use Magento\Sales\Model\Spi\ShipmentResourceInterface;
 
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php
index 0379873ee76fb01c21ce4b02d95cec43c174406d..f77505a9fe208524ac4ffe094226b3f528ecf1cd 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php
@@ -6,7 +6,7 @@
 namespace Magento\Sales\Model\Resource\Order\Shipment;
 
 use Magento\Sales\Model\Resource\EntityAbstract;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\ShipmentCommentResourceInterface;
 
 /**
@@ -34,27 +34,27 @@ class Comment extends EntityAbstract implements ShipmentCommentResourceInterface
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Sales\Model\Order\Shipment\Comment\Validator $validator
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Order\Shipment\Comment\Validator $validator,
         $resourcePrefix = null
     ) {
         $this->validator = $validator;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
index ae31f67f65deb94365871772b991d45ebcebf9f0..d61ea0fbd7c82fb0455ffe6d5c502be45f0a4afe 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
@@ -22,7 +22,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Shipment\Grid\Colle
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\Registry $registryManager
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
@@ -32,7 +32,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Shipment\Grid\Colle
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Registry $registryManager,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php
index 8d25d48c40e2195d5dcb1c14e82c3b1e050eba28..32efe9ad52732e700ddb73b33e6968e75c7a7f4a 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php
@@ -6,7 +6,7 @@
 
 namespace Magento\Sales\Model\Resource\Order\Shipment;
 
-use Magento\Sales\Model\Resource\EntityRelationInterface;
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface;
 use Magento\Sales\Model\Resource\Order\Shipment\Item as ShipmentItemResource;
 use Magento\Sales\Model\Resource\Order\Shipment\Comment as ShipmentCommentResource;
 use Magento\Sales\Model\Resource\Order\Shipment\Track as ShipmentTrackResource;
@@ -14,7 +14,7 @@ use Magento\Sales\Model\Resource\Order\Shipment\Track as ShipmentTrackResource;
 /**
  * Class Relation
  */
-class Relation implements EntityRelationInterface
+class Relation implements RelationInterface
 {
     /**
      * @var ShipmentItemResource
@@ -49,11 +49,11 @@ class Relation implements EntityRelationInterface
     /**
      * Process relations for Shipment
      *
-     * @param \Magento\Sales\Model\AbstractModel $object
+     * @param \Magento\Framework\Model\AbstractModel $object
      * @return void
      * @throws \Exception
      */
-    public function processRelation(\Magento\Sales\Model\AbstractModel $object)
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object)
     {
         /** @var \Magento\Sales\Model\Order\Shipment $object */
         if (null !== $object->getItems()) {
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php
index 07dfa2beb992ecc46df47024df476e44e5ab70bd..6db8bf2ee10496a2716e0cbd707dc46b5d040911 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php
@@ -6,7 +6,7 @@
 namespace Magento\Sales\Model\Resource\Order\Shipment;
 
 use Magento\Sales\Model\Resource\EntityAbstract as SalesResource;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\ShipmentTrackResourceInterface;
 
 /**
@@ -34,27 +34,27 @@ class Track extends SalesResource implements ShipmentTrackResourceInterface
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param \Magento\Sales\Model\Order\Shipment\Track\Validator $validator
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Order\Shipment\Track\Validator $validator,
         $resourcePrefix = null
     ) {
         $this->validator = $validator;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Status.php b/app/code/Magento/Sales/Model/Resource/Order/Status.php
index 6ebf0702bb9eb87d96a082a47c702619052edcfc..b28a95f490823a288fb89a33ee0eb5d045e33b51 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Status.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Status.php
@@ -10,14 +10,14 @@ use Psr\Log\LoggerInterface as LogWriter;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\SalesSequence\Model\Manager;
 use \Magento\Sales\Model\Resource\EntityAbstract;
-use \Magento\Sales\Model\Resource\EntitySnapshot;
+use \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 
 /**
  * Order status resource model
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Status extends \Magento\Framework\Model\Resource\Db\AbstractDb
+class Status extends \Magento\Framework\Model\Resource\Db\VersionControl\AbstractDb
 {
     /**
      * Status labels table
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Status/History.php b/app/code/Magento/Sales/Model/Resource/Order/Status/History.php
index 8c13fdef8880954947e7c6c6f26f0d7b98b6cc22..2dbf7cc79946d97159b0dc71f069007f353196c7 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Status/History.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Status/History.php
@@ -7,7 +7,7 @@ namespace Magento\Sales\Model\Resource\Order\Status;
 
 use Magento\Sales\Model\Order\Status\History\Validator;
 use Magento\Sales\Model\Resource\EntityAbstract;
-use Magento\Sales\Model\Resource\EntitySnapshot;
+use Magento\Framework\Model\Resource\Db\VersionControl\Snapshot;
 use Magento\Sales\Model\Spi\OrderStatusHistoryResourceInterface;
 
 /**
@@ -26,27 +26,27 @@ class History extends EntityAbstract implements OrderStatusHistoryResourceInterf
      * @param \Magento\Framework\Model\Resource\Db\Context $context
      * @param \Magento\Sales\Model\Resource\Attribute $attribute
      * @param \Magento\SalesSequence\Model\Manager $sequenceManager
-     * @param EntitySnapshot $entitySnapshot
-     * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite
+     * @param Snapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite
      * @param Validator $validator
      * @param string $resourcePrefix
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite $entityRelationComposite,
         \Magento\Sales\Model\Resource\Attribute $attribute,
         \Magento\SalesSequence\Model\Manager $sequenceManager,
-        EntitySnapshot $entitySnapshot,
-        \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite,
         Validator $validator,
         $resourcePrefix = null
     ) {
         $this->validator = $validator;
         parent::__construct(
             $context,
-            $attribute,
-            $sequenceManager,
             $entitySnapshot,
             $entityRelationComposite,
+            $attribute,
+            $sequenceManager,
             $resourcePrefix
         );
     }
diff --git a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
index 9bd3c5d4aac539ad12d462d2d4c3100be3328703..f58c41554af1cde9e63f7597945889fd9313aebd 100644
--- a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
@@ -20,7 +20,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Payment\Transaction
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot
+     * @param \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot
      * @param \Magento\Framework\Registry $registryManager
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
@@ -30,7 +30,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Payment\Transaction
         \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Sales\Model\Resource\EntitySnapshot $entitySnapshot,
+        \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot $entitySnapshot,
         \Magento\Framework\Registry $registryManager,
         $connection = null,
         \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/AddressTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/AddressTest.php
index 85d167520a3bbdff1809a69a82a284f79c76be32..fd9d023735b57c1bcdccb2f6d4b1deba2829b12f 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/AddressTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/AddressTest.php
@@ -46,7 +46,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     protected $gridPoolMock;
 
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -95,7 +95,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/CommentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/CommentTest.php
index cb90e1429574daec837ab14470e58f5685eb192f..f5f43992bf9bfbd7ec5ab2cb15b7dd15edeab04b 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/CommentTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/CommentTest.php
@@ -35,7 +35,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -73,7 +73,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/CommentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/CommentTest.php
index 307b36d867efaf5e2d92b2b1c2bd54fb00147493..5348b94492ff3539e979d7ba852719aad2c52407 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/CommentTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/CommentTest.php
@@ -35,7 +35,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -73,7 +73,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/CommentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/CommentTest.php
index bc6d3793a0621a69cc068d564fb0c267c1bdee8c..d397e2d7b79c109b19f2932c51c5905a48ba8e4f 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/CommentTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/CommentTest.php
@@ -35,7 +35,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -73,7 +73,7 @@ class CommentTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/TrackTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/TrackTest.php
index d9c4b184b6c3812fa386c4489fc7e13f4504f55d..6a10d12526840f0147931793c476602254b646f4 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/TrackTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/TrackTest.php
@@ -35,7 +35,7 @@ class TrackTest extends \PHPUnit_Framework_TestCase
      */
     protected $validatorMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -73,7 +73,7 @@ class TrackTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/History/CollectionTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/History/CollectionTest.php
index 7d0dc3b50ec512812807269d2ef8ae59763f95a1..e3222511a2389b3cd7fe4d56621ca4d346d16c0f 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/History/CollectionTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/History/CollectionTest.php
@@ -48,7 +48,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
      */
     protected $entityFactoryMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -59,7 +59,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         $this->selectMock = $this->getMock('Zend_Db_Select', [], [], '', false);
         $this->historyItemMock = $this->getMock(
             'Magento\Sales\Model\Order\Status\History',
-            ['__wakeup', 'setData'],
+            ['__wakeup', 'addData'],
             [],
             '',
             false
@@ -74,7 +74,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ['getReadConnection', 'getMainTable', 'getTable', '__wakeup']
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
@@ -97,7 +97,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
 
         $data = [['data']];
         $this->historyItemMock->expects($this->once())
-            ->method('setData')
+            ->method('addData')
             ->with($this->equalTo($data[0]))
             ->will($this->returnValue($this->historyItemMock));
 
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/HistoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/HistoryTest.php
index eced486c174c08fccd775c5540d6f16a6b34c624..0dfcf1e512a5ad94cc26535d148777901b1a42b5 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/HistoryTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Status/HistoryTest.php
@@ -37,7 +37,7 @@ class HistoryTest extends \PHPUnit_Framework_TestCase
     protected $validatorMock;
 
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
@@ -65,7 +65,7 @@ class HistoryTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php
index 397e6b0374502cd78ccc7084e3ac7ddc8fd20dfa..647427af5956808ff1eb5505bf46ceadb7d1b23d 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Sales\Test\Unit\Model\Resource;
 
+use Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite;
 use \Magento\Sales\Model\Resource\Order;
 
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
@@ -50,12 +51,12 @@ class OrderTest extends \PHPUnit_Framework_TestCase
      */
     protected $adapterMock;
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $entitySnapshotMock;
 
     /**
-     * @var \Magento\Sales\Model\Resource\EntityRelationComposite|\PHPUnit_Framework_MockObject_MockObject
+     * @var RelationComposite|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $relationCompositeMock;
 
@@ -97,14 +98,14 @@ class OrderTest extends \PHPUnit_Framework_TestCase
         );
         $this->salesSequenceMock = $this->getMock('Magento\SalesSequence\Model\Sequence', [], [], '', false);
         $this->entitySnapshotMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
             [],
             [],
             '',
             false
         );
         $this->relationCompositeMock = $this->getMock(
-            'Magento\Sales\Model\Resource\EntityRelationComposite',
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite',
             [],
             [],
             '',
diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml
index c0aec4a0857a24fdc363ad679fc38b3a44bc7408..28ea25b9dcf30f4db415e56c8f90753867ff14be 100644
--- a/app/code/Magento/Sales/etc/di.xml
+++ b/app/code/Magento/Sales/etc/di.xml
@@ -220,7 +220,7 @@
             <argument name="resourcePrefix" xsi:type="string">sales</argument>
         </arguments>
     </type>
-    <virtualType name="OrderRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite">
+    <virtualType name="OrderRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
         <arguments>
             <argument name="relationProcessors" xsi:type="array">
                 <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Relation</item>
@@ -232,7 +232,7 @@
             <argument name="entityRelationComposite" xsi:type="object">OrderRelationsComposite</argument>
         </arguments>
     </type>
-    <virtualType name="InvoiceRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite">
+    <virtualType name="InvoiceRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
         <arguments>
             <argument name="relationProcessors" xsi:type="array">
                 <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Invoice\Relation</item>
@@ -244,7 +244,7 @@
             <argument name="entityRelationComposite" xsi:type="object">InvoiceRelationsComposite</argument>
         </arguments>
     </type>
-    <virtualType name="ShipmentRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite">
+    <virtualType name="ShipmentRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
         <arguments>
             <argument name="relationProcessors" xsi:type="array">
                 <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Shipment\Relation</item>
@@ -256,7 +256,7 @@
             <argument name="entityRelationComposite" xsi:type="object">ShipmentRelationsComposite</argument>
         </arguments>
     </type>
-    <virtualType name="CreditmemoRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite">
+    <virtualType name="CreditmemoRelationsComposite" type="Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite">
         <arguments>
             <argument name="relationProcessors" xsi:type="array">
                 <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Creditmemo\Relation</item>
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/details.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/details.phtml
index 196c1d42977c1482a4793ee9fe3c320e63983286..8a4bc2971760994b04dbf9b18b4ff0a804d89130 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/details.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/details.phtml
@@ -14,8 +14,8 @@ store name = $_order->getStore()->getGroup()->getName()
 ?>
 <?php $_order = $block->getOrder() ?>
 <div>
-<?php echo __('Customer Name: %1', $_order->getCustomerFirstname() ? $_order->getCustomerName() : $_order->getBillingAddress()->getName()) ?><br />
-<?php echo __('Purchased From: %1', $_order->getStore()->getGroup()->getName()) ?><br />
+<?php echo __('Customer Name: %1', $block->escapeHtml($_order->getCustomerFirstname() ? $_order->getCustomerName() : $_order->getBillingAddress()->getName())) ?><br />
+<?php echo __('Purchased From: %1', $block->escapeHtml($_order->getStore()->getGroup()->getName())) ?><br />
 </div>
 <table cellpadding="0" border="0" width="100%" style="border:1px solid #bebcb7; background:#f8f7f5;">
     <thead>
diff --git a/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b9ba81bfaa8ec98f6f906d86cc704b184ee417ff
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="billing-step" xsi:type="array">
+                                            <item name="component" xsi:type="string">uiComponent</item>
+                                            <item name="children" xsi:type="array">
+                                                <item name="payment" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="afterMethods" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="store-credit" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_SalesRule/js/view/payment/discount</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                                <item name="summary" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="totals" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="discount" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">Magento_SalesRule/js/view/summary/discount</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="title" xsi:type="string">Discount</item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
\ No newline at end of file
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js
new file mode 100644
index 0000000000000000000000000000000000000000..80a6488fb285a34fcf91dc07693843ce731ed85f
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/**
+ * Customer store credit(balance) application
+ */
+/*global define,alert*/
+define(
+    [
+        'ko',
+        'jquery',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/resource-url-manager',
+        'Magento_Checkout/js/model/payment-service',
+        'Magento_Ui/js/model/messageList',
+        'mage/storage',
+        'Magento_Checkout/js/action/get-totals'
+    ],
+    function (ko, $, quote, urlManager, paymentService, messageList, storage, getTotalsAction) {
+        'use strict';
+        return function (isApplied, isLoading) {
+            var quoteId = quote.getQuoteId();
+            var url = urlManager.getCancelCouponUrl(quoteId);
+            return storage.delete(
+                url,
+                false
+            ).done(
+                function (response) {
+                    isLoading(false);
+                    var deferred = $.Deferred();
+
+                    getTotalsAction([], deferred);
+                    $.when(deferred).done(function() {
+                        isApplied(false);
+                        paymentService.setPaymentMethods(
+                            paymentService.getAvailablePaymentMethods()
+                        );
+                    });
+                }
+            ).error(
+                function (response) {
+                    isLoading(false);
+                    var error = JSON.parse(response.responseText);
+                    messageList.addErrorMessage(error);
+                }
+            );
+        };
+    }
+);
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
new file mode 100644
index 0000000000000000000000000000000000000000..a76500e4517208b0a166af5a7162b17ddcad9099
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
@@ -0,0 +1,54 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/**
+ * Customer store credit(balance) application
+ */
+/*global define,alert*/
+define(
+    [
+        'ko',
+        'jquery',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/resource-url-manager',
+        'Magento_Checkout/js/model/payment-service',
+        'Magento_Ui/js/model/messageList',
+        'mage/storage',
+        'Magento_Checkout/js/action/get-totals'
+    ],
+    function (ko, $, quote, urlManager, paymentService, messageList, storage, getTotalsAction) {
+        'use strict';
+        return function (couponCode, isApplied, isLoading) {
+            var quoteId = quote.getQuoteId();
+            var url = urlManager.getApplyCouponUrl(couponCode, quoteId);
+            return storage.put(
+                url,
+                {},
+                false
+            ).done(
+                function (response) {
+                    if (response) {
+                        isLoading(false);
+                        isApplied(true);
+                        var deferred = $.Deferred();
+
+                        getTotalsAction([], deferred);
+                        $.when(deferred).done(function() {
+                            paymentService.setPaymentMethods(
+                                paymentService.getAvailablePaymentMethods()
+                            );
+                        });
+                    }
+                }
+            ).error(
+                function (response) {
+                    isLoading(false);
+                    var error = JSON.parse(response.responseText);
+                    messageList.addErrorMessage(error);
+                }
+            );
+        };
+    }
+);
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js
new file mode 100644
index 0000000000000000000000000000000000000000..ddbce5003a402df4de8db9b23a181beed36c7a59
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js
@@ -0,0 +1,63 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'jquery',
+        'ko',
+        'uiComponent',
+        'Magento_Checkout/js/model/quote',
+        'Magento_SalesRule/js/action/set-coupon-code',
+        'Magento_SalesRule/js/action/cancel-coupon'
+    ],
+    function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction) {
+        'use strict';
+        var totals = quote.getTotals();
+        var couponCode = ko.observable(null);
+        if (totals()) {
+            couponCode(totals()['coupon_code']);
+        }
+        var isApplied = ko.observable(couponCode() != null);
+        var isLoading = ko.observable(false);
+        return Component.extend({
+            defaults: {
+                template: 'Magento_SalesRule/payment/discount'
+            },
+            couponCode: couponCode,
+            /**
+             * Applied flag
+             */
+            isApplied: isApplied,
+            isLoading: isLoading,
+            /**
+             * Coupon code application procedure
+             */
+            apply: function() {
+                if (this.validate()) {
+                    isLoading(true);
+                    setCouponCodeAction(couponCode(), isApplied, isLoading);
+                }
+            },
+            /**
+             * Cancel using coupon
+             */
+            cancel: function() {
+                if (this.validate()) {
+                    isLoading(true);
+                    couponCode('');
+                    cancelCouponAction(isApplied, isLoading);
+                }
+            },
+            /**
+             * Coupon form validation
+             *
+             * @returns {boolean}
+             */
+            validate: function() {
+                var form = '#discount-form';
+                return $(form).validation() && $(form).validation('isValid');
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js
new file mode 100644
index 0000000000000000000000000000000000000000..8558966cd71e5aa7af00dc70ba339179ce9d4917
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js
@@ -0,0 +1,39 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote',
+    ],
+    function (Component, quote) {
+        "use strict";
+        return Component.extend({
+            defaults: {
+                template: 'Magento_SalesRule/summary/discount'
+            },
+            totals: quote.getTotals(),
+            isDisplayed: function() {
+                return this.isFullMode() && this.getPureValue() != 0;
+            },
+            getCouponCode: function() {
+                if (!this.totals()) {
+                    return null;
+                }
+                return this.totals()['coupon_code'];
+            },
+            getPureValue: function() {
+                var price = 0;
+                if (this.totals() && this.totals().discount_amount) {
+                    price = parseFloat(this.totals().discount_amount);
+                }
+                return price;
+            },
+            getValue: function() {
+                return this.getFormattedPrice(this.getPureValue());
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html
new file mode 100644
index 0000000000000000000000000000000000000000..92041308eada737fc81f6ab15b7bad6e0e041e8f
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html
@@ -0,0 +1,47 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="payment-option _collapsible opc-payment-additional discount-code"
+     data-bind="mageInit: {'collapsible':{'openedState': '_active'}}">
+    <div class="payment-option-title field choice" data-role="title">
+        <span class="action action-toggle" id="block-discount-heading" role="heading" aria-level="2">
+            <!-- ko text: $t('Apply promo code')--><!-- /ko -->
+        </span>
+    </div>
+    <div class="payment-option-content" data-role="content">
+        <form class="form form-discount" id="discount-form" data-bind="blockLoader: isLoading">
+            <div class="payment-option-inner">
+                <div class="field">
+                    <label class="label" for="discount-code">
+                        <span data-bind="text: $t('Enter promo code')"></span>
+                    </label>
+                    <div class="control">
+                        <input class="input-text"
+                               type="text"
+                               id="discount-code"
+                               name="discount_code"
+                               data-validate="{'required-entry':true}"
+                               data-bind="value: couponCode, attr:{placeholder: $t('Enter promo code')} " />
+                    </div>
+                </div>
+            </div>
+            <div class="actions-toolbar">
+                <div class="primary">
+                    <!-- ko ifnot: isApplied() -->
+                        <button class="action action-apply" type="submit" data-bind="'value': $t('Apply'), click: apply">
+                            <span><!-- ko text: $t('Apply')--><!-- /ko --></span>
+                        </button>
+                    <!-- /ko -->
+                    <!-- ko if: isApplied() -->
+                        <button class="action action-cancel" type="submit" data-bind="'value': $t('Cancel'), click: cancel">
+                            <span><!-- ko text: $t('Cancel coupon')--><!-- /ko --></span>
+                        </button>
+                    <!-- /ko -->
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html
new file mode 100644
index 0000000000000000000000000000000000000000..60ac9c7982a5f6a0a510abd25fb67e4ee11dc13a
--- /dev/null
+++ b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html
@@ -0,0 +1,17 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: isDisplayed() -->
+<tr class="totals discount">
+    <th class="mark" scope="row">
+        <span class="title" data-bind="text: title"></span>
+        <span class="discount coupon" data-bind="text: getCouponCode()"></span>
+    </th>
+    <td class="amount">
+        <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(name) }"></span>
+    </td>
+</tr>
+<!-- /ko -->
diff --git a/app/code/Magento/Shipping/etc/acl.xml b/app/code/Magento/Shipping/etc/acl.xml
index 74811607f3d06fbc8d002fa03dc27d47a0be0f59..feacd4d501dc3da36c629f277754c456eb7f6762 100644
--- a/app/code/Magento/Shipping/etc/acl.xml
+++ b/app/code/Magento/Shipping/etc/acl.xml
@@ -13,6 +13,7 @@
                     <resource id="Magento_Backend::stores_settings">
                         <resource id="Magento_Config::config">
                             <resource id="Magento_Shipping::config_shipping" title="Shipping Settings Section" sortOrder="5" />
+                            <resource id="Magento_Shipping::shipping_policy" title="Shipping Policy Parameters Section" sortOrder="5" />
                             <resource id="Magento_Shipping::carriers" title="Shipping Methods Section" sortOrder="5" />
                         </resource>
                     </resource>
diff --git a/app/code/Magento/Shipping/etc/adminhtml/system.xml b/app/code/Magento/Shipping/etc/adminhtml/system.xml
index 40e4568907c17aa71bd790790b3ea912932eb260..5b56b96f719b7fbd3270e7b253dab0b1f862205d 100644
--- a/app/code/Magento/Shipping/etc/adminhtml/system.xml
+++ b/app/code/Magento/Shipping/etc/adminhtml/system.xml
@@ -7,7 +7,7 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd">
     <system>
-        <section id="shipping" translate="label" type="text" sortOrder="310" showInDefault="1" showInWebsite="1" showInStore="0">
+        <section id="shipping" translate="label" type="text" sortOrder="310" showInDefault="1" showInWebsite="1" showInStore="1">
             <label>Shipping Settings</label>
             <tab>sales</tab>
             <resource>Magento_Shipping::config_shipping</resource>
@@ -34,6 +34,19 @@
                     <label>Street Address Line 2</label>
                 </field>
             </group>
+            <group id="shipping_policy" translate="label" type="text" sortOrder="120" showInDefault="1" showInWebsite="1" showInStore="1">
+                <label>Shipping Policy Parameters</label>
+                <field id="enable_shipping_policy" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Apply custom Shipping Policy</label>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                </field>
+                <field id="shipping_policy_content" translate="label" type="textarea" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
+                    <label>Shipping Policy</label>
+                    <depends>
+                        <field id="enable_shipping_policy">1</field>
+                    </depends>
+                </field>
+            </group>
         </section>
         <section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1">
             <label>Shipping Methods</label>
diff --git a/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14a25393667d7b7bfe54cce7ba0b750f65b0cfd6
--- /dev/null
+++ b/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="shippingAddress" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="before-shipping-method-form" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="shipping_policy" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Shipping/js/view/checkout/shipping/shipping-policy</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Shipping/view/frontend/web/js/model/config.js b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d69bd10ae7c674ea543ddd0cb30d97b567ef3056
--- /dev/null
+++ b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js
@@ -0,0 +1,13 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define([], function () {
+        "use strict";
+        return function () {
+            return window.checkoutConfig.shippingPolicy
+        }
+    }
+);
diff --git a/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a41b1ae5770388c85fa13b76b3fa4abdf2689a7
--- /dev/null
+++ b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js
@@ -0,0 +1,18 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+    'uiComponent',
+    'Magento_Shipping/js/model/config'
+
+], function (Component, config) {
+    'use strict';
+
+    return Component.extend({
+        defaults: {
+            template: 'Magento_Shipping/checkout/shipping/shipping-policy'
+        },
+        config: config()
+    });
+});
diff --git a/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html
new file mode 100644
index 0000000000000000000000000000000000000000..1c0cc5c80e2efc4a25ad4c7f9e52266b569bbb82
--- /dev/null
+++ b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html
@@ -0,0 +1,14 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="shipping-policy-block field-tooltip" data-bind="visible: config.isEnabled">
+    <span class="field-tooltip-action">
+        <!-- ko text: $t('See our shipping policy') --><!-- /ko -->
+    </span>
+    <div class="field-tooltip-content">
+        <span data-bind="html: config.shippingPolicyContent"></span>
+    </div>
+</div>
diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml
index c47f73ec9012bd91e4218009b662d754d6905645..1bc032018f7c8a1ff22c9c0863f1c5aaac1d62b0 100644
--- a/app/code/Magento/Store/etc/di.xml
+++ b/app/code/Magento/Store/etc/di.xml
@@ -23,6 +23,11 @@
         <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\View\Element\Template\File\Validator">
+        <arguments>
+            <argument name="scope" xsi:type="string">store</argument>
+        </arguments>
+    </type>
     <type name="Magento\Store\Model\Config\Reader\Website">
         <arguments>
             <argument name="scopePool" xsi:type="object">Magento\Framework\App\Config\ScopePool\Proxy</argument>
diff --git a/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php b/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php
index 3fb1e6fd5b28ea248de75a35a11bf4336d10684c..e36af22d214c62161943940fd4e7439596ca4b56 100644
--- a/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php
+++ b/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php
@@ -3,11 +3,9 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\Tax\Api\Data;
 
-
-interface GrandTotalDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+interface GrandTotalDetailsInterface
 {
     /**
      * Get tax amount value
@@ -47,21 +45,4 @@ interface GrandTotalDetailsInterface extends \Magento\Framework\Api\ExtensibleDa
      * @return $this
      */
     public function setGroupId($id);
-
-    /**
-     * {@inheritdoc}
-     *
-     * @return \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface|null
-     */
-    public function getExtensionAttributes();
-
-    /**
-     * {@inheritdoc}
-     *
-     * @param \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes
-    );
 }
diff --git a/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php b/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php
index f6d39a9d385d5add5389df19846d273fd42f31c9..39dda8c3536fc456bf9ac4d9d22dd9c46d9d2d22 100644
--- a/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php
+++ b/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php
@@ -3,11 +3,9 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\Tax\Api\Data;
 
-
-interface GrandTotalRatesInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+interface GrandTotalRatesInterface
 {
     /**
      * Get tax percentage value
@@ -34,21 +32,4 @@ interface GrandTotalRatesInterface extends \Magento\Framework\Api\ExtensibleData
      * @return $this
      */
     public function setTitle($title);
-
-    /**
-     * Retrieve existing extension attributes object or create a new one.
-     *
-     * @return \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface|null
-     */
-    public function getExtensionAttributes();
-
-    /**
-     * Set an extension attributes object.
-     *
-     * @param \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes
-    );
 }
diff --git a/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php b/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php
index 79cc180e80fceddbf6fde95b704b79c5c09e143b..a3301eb85796a2163d3435005b0a11c80ee6d83a 100644
--- a/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php
+++ b/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php
@@ -7,19 +7,19 @@
 namespace Magento\Tax\Model\Calculation;
 
 use Magento\Tax\Api\Data\GrandTotalDetailsInterface;
-use Magento\Framework\Model\AbstractExtensibleModel;
+use Magento\Framework\Api\AbstractSimpleObject;
 
 /**
  * Grand Total Tax Details Model
  */
-class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDetailsInterface
+class GrandTotalDetails extends AbstractSimpleObject implements GrandTotalDetailsInterface
 {
     /**#@+
      * Constants defined for keys of array, makes typos less likely
      */
-    const AMOUNT        = 'amount';
-    const RATES         = 'rates';
-    const GROUP_ID      = 'group_id';
+    const AMOUNT = 'amount';
+    const RATES = 'rates';
+    const GROUP_ID = 'group_id';
     /**#@-*/
 
     /**
@@ -27,7 +27,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet
      */
     public function getGroupId()
     {
-        return $this->getData(self::GROUP_ID);
+        return $this->_get(self::GROUP_ID);
     }
 
     /**
@@ -43,7 +43,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet
      */
     public function getAmount()
     {
-        return $this->getData(self::AMOUNT);
+        return $this->_get(self::AMOUNT);
     }
 
     /**
@@ -59,7 +59,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet
      */
     public function getRates()
     {
-        return $this->getData(self::RATES);
+        return $this->_get(self::RATES);
     }
 
     /**
@@ -69,26 +69,4 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet
     {
         return $this->setData(self::RATES, $rates);
     }
-
-    /**
-     * {@inheritdoc}
-     *
-     * @return \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface|null
-     */
-    public function getExtensionAttributes()
-    {
-        return $this->_getExtensionAttributes();
-    }
-
-    /**
-     * {@inheritdoc}
-     *
-     * @param \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes
-    ) {
-        return $this->_setExtensionAttributes($extensionAttributes);
-    }
 }
diff --git a/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php b/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php
index 4c23c6444d7236a25ebf661b9d5d75a53f0fa829..b7be0cc4a3d36ab0aa5ae35cd8286245064d62d8 100644
--- a/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php
+++ b/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php
@@ -7,12 +7,12 @@
 namespace Magento\Tax\Model\Calculation;
 
 use Magento\Tax\Api\Data\GrandTotalRatesInterface;
-use Magento\Framework\Model\AbstractExtensibleModel;
+use Magento\Framework\Api\AbstractSimpleObject;
 
 /**
  * Grand Total Tax Details Model
  */
-class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRatesInterface
+class GrandTotalRates extends AbstractSimpleObject implements GrandTotalRatesInterface
 {
     /**#@+
      * Constants defined for keys of array, makes typos less likely
@@ -26,7 +26,7 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates
      */
     public function getTitle()
     {
-        return $this->getData(self::TITLE);
+        return $this->_get(self::TITLE);
     }
 
     /**
@@ -42,7 +42,7 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates
      */
     public function getPercent()
     {
-        return $this->getData(self::PERCENT);
+        return $this->_get(self::PERCENT);
     }
 
     /**
@@ -52,26 +52,4 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates
     {
         return $this->setData(self::PERCENT, $percent);
     }
-
-    /**
-     * {@inheritdoc}
-     *
-     * @return \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface|null
-     */
-    public function getExtensionAttributes()
-    {
-        return $this->_getExtensionAttributes();
-    }
-
-    /**
-     * {@inheritdoc}
-     *
-     * @param \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes
-     * @return $this
-     */
-    public function setExtensionAttributes(
-        \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes
-    ) {
-        return $this->_setExtensionAttributes($extensionAttributes);
-    }
 }
diff --git a/app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php
similarity index 87%
rename from app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php
rename to app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php
index e20684a73b880754f7285dbe561485e298361d28..1de7b6d223d5648f009b1598917b54d46dc6643c 100644
--- a/app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php
+++ b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php
@@ -6,8 +6,9 @@
 namespace Magento\Tax\Model\Quote;
 
 use Magento\Quote\Model\Cart\CartTotalRepository;
+use Magento\Quote\Api\Data\TotalsExtensionFactory;
 
-class GrandTotalDetails
+class GrandTotalDetailsPlugin
 {
     /**
      * @var \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory
@@ -20,7 +21,7 @@ class GrandTotalDetails
     protected $ratesFactory;
 
     /**
-     * @var \Magento\Framework\Api\ExtensionAttributesFactory
+     * @var TotalsExtensionFactory
      */
     protected $extensionFactory;
 
@@ -42,7 +43,7 @@ class GrandTotalDetails
     /**
      * @param \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory $detailsFactory
      * @param \Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory $ratesFactory
-     * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+     * @param TotalsExtensionFactory $extensionFactory
      * @param \Magento\Tax\Model\Config $taxConfig
      * @param \Magento\Quote\Model\Quote\Address\Total\Tax $taxTotal
      * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
@@ -50,7 +51,7 @@ class GrandTotalDetails
     public function __construct(
         \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory $detailsFactory,
         \Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory $ratesFactory,
-        \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+        TotalsExtensionFactory $extensionFactory,
         \Magento\Tax\Model\Config $taxConfig,
         \Magento\Quote\Model\Quote\Address\Total\Tax $taxTotal,
         \Magento\Quote\Model\QuoteRepository $quoteRepository
@@ -81,7 +82,7 @@ class GrandTotalDetails
 
     /**
      * @param CartTotalRepository $subject
-     * @param callable $proceed
+     * @param \Closure $proceed
      * @param int $cartId
      * @return \Magento\Quote\Model\Cart\Totals
      * @throws \Magento\Framework\Exception\NoSuchEntityException
@@ -119,11 +120,13 @@ class GrandTotalDetails
             $finalData[] = $taxDetails;
             $detailsId++;
         }
-        $taxInfo = $this->extensionFactory->create('\\Magento\\Quote\\Model\\Cart\\Totals', []);
-        $taxInfo->setTaxGrandtotalDetails($finalData);
+        $attributes = $result->getExtensionAttributes();
+        if ($attributes === null) {
+            $attributes = $this->extensionFactory->create();
+        }
+        $attributes->setTaxGrandtotalDetails($finalData);
         /** @var $result \Magento\Quote\Model\Cart\Totals */
-        $result->setExtensionAttributes($taxInfo);
-        $result->setTaxAmount($taxes['value']);
+        $result->setExtensionAttributes($attributes);
         return $result;
     }
 }
diff --git a/app/code/Magento/Tax/Model/TaxConfigProvider.php b/app/code/Magento/Tax/Model/TaxConfigProvider.php
index 4f40850d8bfb1657011a84f9d135076b82b4f9a4..8ce354850537f39125869c4f4baf5b01161c19ee 100644
--- a/app/code/Magento/Tax/Model/TaxConfigProvider.php
+++ b/app/code/Magento/Tax/Model/TaxConfigProvider.php
@@ -43,6 +43,7 @@ class TaxConfigProvider implements ConfigProviderInterface
             'reviewTotalsDisplayMode' => $this->getReviewTotalsDisplayMode(),
             'includeTaxInGrandTotal' => $this->isTaxDisplayedInGrandTotal(),
             'isFullTaxSummaryDisplayed' => $this->isFullTaxSummaryDisplayed(),
+            'isZeroTaxDisplayed' => $this->taxConfig->displayCartZeroTax(),
         ];
     }
 
diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cad8010f39cf0056c67efb00f98d427cdbbc9d9a
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php
@@ -0,0 +1,197 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Tax\Test\Unit\Model;
+
+class TaxConfigProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $taxHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $taxConfigMock;
+
+    /**
+     * @var \Magento\Tax\Model\TaxConfigProvider
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->taxHelperMock = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false);
+        $this->taxConfigMock = $this->getMock('Magento\Tax\Model\Config', [], [], '', false);
+
+        $this->model = new \Magento\Tax\Model\TaxConfigProvider($this->taxHelperMock, $this->taxConfigMock);
+    }
+
+    /**
+     * @dataProvider getConfigDataProvider
+     * @param array $expectedResult
+     * @param int $cartShippingBoth
+     * @param int $cartShippingExclTax
+     * @param int $cartBothPrices
+     * @param int $cartPriceExclTax
+     * @param int $cartSubTotalBoth
+     * @param int $cartSubTotalExclTax
+     */
+    public function testGetConfig(
+        $expectedResult,
+        $cartShippingBoth,
+        $cartShippingExclTax,
+        $cartBothPrices,
+        $cartPriceExclTax,
+        $cartSubTotalBoth,
+        $cartSubTotalExclTax
+    ) {
+        $this->taxConfigMock->expects($this->any())->method('displayCartShippingBoth')
+            ->will($this->returnValue($cartShippingBoth));
+        $this->taxConfigMock->expects($this->any())->method('displayCartShippingExclTax')
+            ->will($this->returnValue($cartShippingExclTax));
+
+        $this->taxHelperMock->expects($this->any())->method('displayCartBothPrices')
+            ->will($this->returnValue($cartBothPrices));
+        $this->taxHelperMock->expects($this->any())->method('displayCartPriceExclTax')
+            ->will($this->returnValue($cartPriceExclTax));
+
+        $this->taxConfigMock->expects($this->any())->method('displayCartSubtotalBoth')
+            ->will($this->returnValue($cartSubTotalBoth));
+        $this->taxConfigMock->expects($this->any())->method('displayCartSubtotalExclTax')
+            ->will($this->returnValue($cartSubTotalExclTax));
+
+        $this->taxHelperMock->expects(($this->any()))->method('displayShippingPriceExcludingTax')
+            ->will($this->returnValue(1));
+        $this->taxHelperMock->expects(($this->any()))->method('displayShippingBothPrices')
+            ->will($this->returnValue(1));
+        $this->taxHelperMock->expects(($this->any()))->method('displayFullSummary')
+            ->will($this->returnValue(1));
+        $this->taxConfigMock->expects(($this->any()))->method('displayCartTaxWithGrandTotal')
+            ->will($this->returnValue(1));
+        $this->taxConfigMock->expects(($this->any()))->method('displayCartZeroTax')
+            ->will($this->returnValue(1));
+        $this->assertEquals($expectedResult, $this->model->getConfig());
+    }
+
+    /**
+     * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function getConfigDataProvider()
+    {
+        return [
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'both',
+                    'reviewItemPriceDisplayMode' => 'both',
+                    'reviewTotalsDisplayMode' => 'both',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 1,
+                'cartShippingExclTax' => 1,
+                'cartBothPrices' => 1,
+                'cartPriceExclTax' => 1,
+                'cartSubTotalBoth' => 1,
+                'cartSubTotalExclTax' => 1
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'excluding',
+                    'reviewItemPriceDisplayMode' => 'excluding',
+                    'reviewTotalsDisplayMode' => 'excluding',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 0,
+                'cartShippingExclTax' => 1,
+                'cartBothPrices' => 0,
+                'cartPriceExclTax' => 1,
+                'cartSubTotalBoth' => 0,
+                'cartSubTotalExclTax' => 1
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'including',
+                    'reviewItemPriceDisplayMode' => 'including',
+                    'reviewTotalsDisplayMode' => 'including',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 0,
+                'cartShippingExclTax' => 0,
+                'cartBothPrices' => 0,
+                'cartPriceExclTax' => 0,
+                'cartSubTotalBoth' => 0,
+                'cartSubTotalExclTax' => 0
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'including',
+                    'reviewItemPriceDisplayMode' => 'including',
+                    'reviewTotalsDisplayMode' => 'including',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 0,
+                'cartShippingExclTax' => 0,
+                'cartBothPrices' => 0,
+                'cartPriceExclTax' => 0,
+                'cartSubTotalBoth' => 0,
+                'cartSubTotalExclTax' => 0
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'both',
+                    'reviewItemPriceDisplayMode' => 'both',
+                    'reviewTotalsDisplayMode' => 'both',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 1,
+                'cartShippingExclTax' => 0,
+                'cartBothPrices' => 1,
+                'cartPriceExclTax' => 0,
+                'cartSubTotalBoth' => 1,
+                'cartSubTotalExclTax' => 0
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayShippingPriceExclTax' => 1,
+                    'isDisplayShippingBothPrices' => 1,
+                    'reviewShippingDisplayMode' => 'excluding',
+                    'reviewItemPriceDisplayMode' => 'including',
+                    'reviewTotalsDisplayMode' => 'both',
+                    'includeTaxInGrandTotal' => 1,
+                    'isFullTaxSummaryDisplayed' => 1,
+                    'isZeroTaxDisplayed' => 1
+                ],
+                'cartShippingBoth' => 0,
+                'cartShippingExclTax' => 1,
+                'cartBothPrices' => 0,
+                'cartPriceExclTax' => 0,
+                'cartSubTotalBoth' => 1,
+                'cartSubTotalExclTax' => 0
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Tax/etc/di.xml b/app/code/Magento/Tax/etc/di.xml
index 48b3173d60f09e739305f3c68cf501be8315be96..12dd5b270fc3c2740cf0f272bcd38fdb812d9b0d 100644
--- a/app/code/Magento/Tax/etc/di.xml
+++ b/app/code/Magento/Tax/etc/di.xml
@@ -65,7 +65,7 @@
         <plugin name="add_tax_to_order" type="Magento\Tax\Model\Quote\ToOrderConverter"/>
     </type>
     <type name="Magento\Quote\Model\Cart\CartTotalRepository">
-        <plugin name="add_tax_details" type="Magento\Tax\Model\Quote\GrandTotalDetails"/>
+        <plugin name="add_tax_details" type="Magento\Tax\Model\Quote\GrandTotalDetailsPlugin"/>
     </type>
     <type name="Magento\Tax\Model\Resource\Report\Tax\Createdat">
         <arguments>
diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml
index 85969a844c674559ccb839ed2d3d092807e691bf..db20c4572b1d90cde9ed306a8e68a06ae42a6ada 100644
--- a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml
@@ -15,52 +15,71 @@
                             <item name="children" xsi:type="array">
                                 <item name="steps" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="shipping" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="price" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item>
-                                                    <item name="displayArea" xsi:type="string">price</item>
+                                                <item name="shippingAddress" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="price" xsi:type="array">
+                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item>
+                                                            <item name="displayArea" xsi:type="string">price</item>
+                                                        </item>
+                                                    </item>
                                                 </item>
                                             </item>
                                         </item>
-                                        <item name="review" xsi:type="array">
+                                    </item>
+                                </item>
+                                <item name="summary" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="totals" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="columns" xsi:type="array">
-                                                    <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item>
+                                                <!-- sort order for this totals is configured on admin panel-->
+                                                <!-- Stores->Configuration->SALES->Sales->General->Checkout Totals Sort Order -->
+                                                <item name="subtotal" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/summary/subtotal</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="excludingTaxMessage" xsi:type="string">Excl. Tax</item>
+                                                        <item name="includingTaxMessage" xsi:type="string">Incl. Tax</item>
+                                                    </item>
+                                                </item>
+                                                <item name="shipping" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/summary/shipping</item>
+                                                    <item name="sortOrder" xsi:type="string">20</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="excludingTaxMessage" xsi:type="string">Excl. Tax</item>
+                                                        <item name="includingTaxMessage" xsi:type="string">Incl. Tax</item>
+                                                    </item>
+                                                </item>
+                                                <item name="before_grandtotal" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">uiComponent</item>
+                                                    <item name="sortOrder" xsi:type="string">30</item>
                                                     <item name="children" xsi:type="array">
-                                                        <item name="price" xsi:type="array">
-                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/price</item>
-                                                        </item>
-                                                        <item name="subtotal" xsi:type="array">
-                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/subtotal</item>
-                                                        </item>
+                                                        <!-- merge your components here -->
+                                                    </item>
+                                                </item>
+                                                <item name="tax" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/summary/tax</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="title" xsi:type="string">Tax</item>
+                                                    </item>
+                                                </item>
+                                                <item name="grand-total" xsi:type="array">
+                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/summary/grand-total</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="exclTaxLabel" xsi:type="string">Order Total Excl. Tax</item>
+                                                        <item name="inclTaxLabel" xsi:type="string">Order Total Incl. Tax</item>
+                                                        <item name="basicCurrencyMessage" xsi:type="string">Your credit card will be charged for</item>
+                                                        <item name="title" xsi:type="string">Order Total</item>
                                                     </item>
                                                 </item>
-                                                <item name="totals" xsi:type="array">
+                                            </item>
+                                        </item>
+                                        <item name="cart_items" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="details" xsi:type="array">
                                                     <item name="children" xsi:type="array">
                                                         <item name="subtotal" xsi:type="array">
-                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/subtotal</item>
-                                                            <item name="sortOrder" xsi:type="string">10</item>
-                                                        </item>
-                                                        <item name="shipping" xsi:type="array">
-                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/shipping</item>
-                                                            <item name="sortOrder" xsi:type="string">20</item>
-                                                        </item>
-                                                        <item name="before_grandtotal" xsi:type="array">
-                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/before_grandtotal</item>
-                                                            <item name="sortOrder" xsi:type="string">30</item>
-                                                            <item name="children" xsi:type="array">
-                                                                <!-- merge your components here -->
-                                                            </item>
-                                                        </item>
-                                                        <item name="grandtotal" xsi:type="array">
-                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/grandtotal</item>
-                                                            <item name="sortOrder" xsi:type="string">40</item>
-                                                            <item name="children" xsi:type="array">
-                                                                <item name="grandtotal_tax" xsi:type="array">
-                                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/tax_total</item>
-                                                                </item>
-                                                            </item>
+                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/item/details/subtotal</item>
                                                         </item>
                                                     </item>
                                                 </item>
diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml
new file mode 100644
index 0000000000000000000000000000000000000000..012d3de66d1ddaf42f7320f1cb3c064b9f2c4486
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- TODO remove this file as soon as enhanced checkout is implemented -->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="price" xsi:type="array">
+                                                    <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item>
+                                                    <item name="displayArea" xsi:type="string">price</item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                        <item name="review" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="columns" xsi:type="array">
+                                                    <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item>
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="price" xsi:type="array">
+                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/price</item>
+                                                        </item>
+                                                        <item name="subtotal" xsi:type="array">
+                                                            <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/subtotal</item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                                <item name="totals" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="subtotal" xsi:type="array">
+                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/subtotal</item>
+                                                            <item name="sortOrder" xsi:type="string">10</item>
+                                                        </item>
+                                                        <item name="shipping" xsi:type="array">
+                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/shipping</item>
+                                                            <item name="sortOrder" xsi:type="string">20</item>
+                                                        </item>
+                                                        <item name="before_grandtotal" xsi:type="array">
+                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/before_grandtotal</item>
+                                                            <item name="sortOrder" xsi:type="string">30</item>
+                                                            <item name="children" xsi:type="array">
+                                                                <!-- merge your components here -->
+                                                            </item>
+                                                        </item>
+                                                        <item name="grandtotal" xsi:type="array">
+                                                            <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/grandtotal</item>
+                                                            <item name="sortOrder" xsi:type="string">40</item>
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="grandtotal_tax" xsi:type="array">
+                                                                    <item name="component"  xsi:type="string">Magento_Tax/js/view/checkout/review/tax_total</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
\ No newline at end of file
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js
deleted file mode 100644
index 72f01914f2df6bd4afd9e0478616f8c2a9474373..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'uiComponent'
-    ],
-    function (Component) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                template: 'Magento_Tax/checkout/review/before_grandtotal'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js
deleted file mode 100644
index 839e4a1be856e3fcd8ea4ae7dafaa25ea6030066..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'Magento_Checkout/js/view/review/item/column'
-    ],
-    function (column) {
-        "use strict";
-        var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';
-        return column.extend({
-            defaults: {
-                displayPriceMode: displayPriceMode,
-                ownClass: 'price',
-                columnTitle: 'Price',
-                template: 'Magento_Tax/checkout/review/item/columns/price'
-            },
-            isPriceInclTaxDisplayed: function() {
-                return 'both' == this.displayPriceMode || 'including' == this.displayPriceMode;
-            },
-            isPriceExclTaxDisplayed: function() {
-                return 'both' == this.displayPriceMode || 'excluding' == this.displayPriceMode;
-            },
-            isBothPricesDisplayed: function() {
-                return 'both' == this.displayPriceMode;
-            },
-            getPriceExclTax: function(quoteItem) {
-                return this.getFormattedPrice(quoteItem.price);
-            },
-            getPriceInclTax: function(quoteItem) {
-                return this.getFormattedPrice(quoteItem.price_incl_tax);
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js
deleted file mode 100644
index 2d1bee80d8fb585c4bd0f7277cdec70cb24da129..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'Magento_Tax/js/view/checkout/review/item/columns/price'
-    ],
-    function (Price) {
-        "use strict";
-        var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';
-        return Price.extend({
-            defaults: {
-                displayPriceMode: displayPriceMode,
-                ownClass: 'subtotal',
-                columnTitle: 'Subtotal',
-                template: 'Magento_Tax/checkout/review/item/columns/subtotal'
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js
deleted file mode 100644
index 1fc18683237bb750ea9ca55548be418378c1d5cb..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'jquery',
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils',
-        'Magento_Checkout/js/model/shipping-service'
-    ],
-    function ($, Component, quote, priceUtils, shippingService) {
-        var displayMode = window.checkoutConfig.reviewShippingDisplayMode;
-        return Component.extend({
-            defaults: {
-                displayMode: displayMode,
-                template: 'Magento_Tax/checkout/review/shipping'
-            },
-            getColspan: 3,
-            style: "",
-            quoteIsVirtual: quote.isVirtual(),
-            selectedShippingMethod: quote.getShippingMethod(),
-            getTitle: function() {
-                return "Shipping & Handling" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")";
-            },
-            getExcludingLabel: function() {
-                return "Shipping Excl. Tax" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")";
-            },
-            getIncludingLabel: function() {
-                return "Shipping Incl. Tax" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")";
-            },
-            totals: quote.getTotals(),
-            isBothPricesDisplayed: function() {
-                return 'both' == this.displayMode
-            },
-            isIncludingDisplayed: function() {
-                return 'including' == this.displayMode;
-            },
-            isExcludingDisplayed: function() {
-                return 'excluding' == this.displayMode;
-            },
-            getValue: function() {
-                var price = 0;
-                if (this.totals()) {
-                    price =  this.totals().shipping_amount;
-                }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
-            },
-            getIncludingValue: function() {
-                var price = 0;
-                if (this.totals()) {
-                    price =  this.totals().shipping_incl_tax;
-                }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
-            },
-            getExcludingValue: function() {
-                var price = 0;
-                if (this.totals()) {
-                    price =  this.totals().shipping_amount;
-                }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js
deleted file mode 100644
index 56f70a8993f977d833331dd7c3d76c44d61c37cc..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global alert*/
-define(
-    [
-        'ko',
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
-    ],
-    function (ko, Component, quote, priceUtils) {
-        "use strict";
-        var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal;
-        var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed;
-        return Component.extend({
-            defaults: {
-                isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,
-                template: 'Magento_Tax/checkout/review/tax_total'
-            },
-            colspan: 3,
-            totals: quote.getTotals(),
-            style: "",
-            isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,
-            lastTaxGroupId: null,
-            isDetailsVisible: ko.observable(),
-            getTitle: function() {
-                return "Tax";
-            },
-            getValue: function() {
-                var amount = 0;
-                if (this.totals()) {
-                    amount = this.totals().tax_amount;
-                }
-                return priceUtils.formatPrice(amount, quote.getPriceFormat());
-            },
-            formatPrice: function(amount) {
-                return priceUtils.formatPrice(amount, quote.getPriceFormat());
-            },
-            getDetails: function() {
-                var totals = this.totals();
-                if (totals.extension_attributes) {
-                    return totals.extension_attributes.tax_grandtotal_details;
-                }
-                return [];
-            },
-            toggleDetails: function() {
-                this.isDetailsVisible(!this.isDetailsVisible());
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js
index bdb1256f25678a1a3ac005965ebc90ddc69682c4..018eb3b9d3ef7ea9206f43f5ac1efb2562c1779d 100644
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js
@@ -14,7 +14,7 @@ define(
         "use strict";
         return Component.extend({
             defaults: {
-                template: 'Magento_Tax/checkout/shipping_method/price',
+                template: 'Magento_Tax/checkout/shipping_method/price'
             },
 
             isDisplayShippingPriceExclTax: window.checkoutConfig.isDisplayShippingPriceExclTax,
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js
similarity index 51%
rename from app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js
rename to app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js
index 214e16f531e78aee0aec37621fbbd41ffc62f5e6..2ad991e704ed63d83dd1d3c91bd9e8a69dc63e7c 100644
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js
@@ -6,34 +6,29 @@
 /*global alert*/
 define(
     [
-        'uiComponent',
+        'Magento_Checkout/js/view/summary/abstract-total',
         'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
+        'Magento_Catalog/js/price-utils',
+        'Magento_Checkout/js/model/totals'
     ],
-    function (Component, quote, priceUtils) {
+    function (Component, quote, priceUtils, totals) {
         "use strict";
-        var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal || false;
-        var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed || false;
         return Component.extend({
             defaults: {
-                isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,
-                template: 'Magento_Tax/checkout/review/grandtotal'
-            },
-            getColspan: 3,
-            style: "",
-            exclTaxLabel: 'Grand Total Excl. Tax',
-            inclTaxLabel: 'Grand Total Incl. Tax',
-            basicCurrencyMessage: 'Your credit card will be charged for',
-            getTitle: function() {
-                return "Grand Total";
+                isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,
+                template: 'Magento_Tax/checkout/summary/grand-total'
             },
             totals: quote.getTotals(),
+            isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,
+            isDisplayed: function() {
+                return this.isFullMode();
+            },
             getValue: function() {
                 var price = 0;
                 if (this.totals()) {
-                    price = this.totals().grand_total;
+                    price = totals.getSegment('grand_total').value;
                 }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
+                return this.getFormattedPrice(price);
             },
             getBaseValue: function() {
                 var price = 0;
@@ -42,17 +37,12 @@ define(
                 }
                 return priceUtils.formatPrice(price, quote.getBasePriceFormat());
             },
-            isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,
             getGrandTotalExclTax: function() {
                 var totals = this.totals();
                 if (!totals) {
                     return 0;
                 }
-                var amount = totals.grand_total - totals.tax_amount;
-                if (amount < 0) {
-                    return 0;
-                }
-                return priceUtils.formatPrice(amount, quote.getPriceFormat());
+                return this.getFormattedPrice(totals.grand_total);
             },
             isBaseGrandTotalDisplayNeeded: function() {
                 var totals = this.totals();
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js
new file mode 100644
index 0000000000000000000000000000000000000000..f75c7733bab9a9aa72776d85af6dedf7d5442225
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js
@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'Magento_Checkout/js/view/summary/item/details/subtotal'
+    ],
+    function (subtotal) {
+        "use strict";
+        var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';
+        return subtotal.extend({
+            defaults: {
+                displayPriceMode: displayPriceMode,
+                template: 'Magento_Tax/checkout/summary/item/details/subtotal'
+            },
+            isPriceInclTaxDisplayed: function() {
+                return 'both' == displayPriceMode || 'including' == displayPriceMode;
+            },
+            isPriceExclTaxDisplayed: function() {
+                return 'both' == displayPriceMode || 'excluding' == displayPriceMode;
+            },
+            getValueInclTax: function(quoteItem) {
+                return this.getFormattedPrice(quoteItem['row_total_incl_tax']);
+            },
+            getValueExclTax: function(quoteItem) {
+                return this.getFormattedPrice(quoteItem['row_total']);
+            }
+
+        });
+    }
+);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js
new file mode 100644
index 0000000000000000000000000000000000000000..b6c3631c7869d1b912a046c8b3a097897a973eeb
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js
@@ -0,0 +1,48 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'jquery',
+        'Magento_Checkout/js/view/summary/shipping',
+        'Magento_Checkout/js/model/quote'
+    ],
+    function ($, Component, quote) {
+        var displayMode = window.checkoutConfig.reviewShippingDisplayMode;
+        return Component.extend({
+            defaults: {
+                displayMode: displayMode,
+                template: 'Magento_Tax/checkout/summary/shipping'
+            },
+            isBothPricesDisplayed: function() {
+                return 'both' == this.displayMode
+            },
+            isIncludingDisplayed: function() {
+                return 'including' == this.displayMode;
+            },
+            isExcludingDisplayed: function() {
+                return 'excluding' == this.displayMode;
+            },
+            isCalculated: function() {
+                return this.totals() && this.isFullMode() && null != quote.shippingMethod();
+            },
+            getIncludingValue: function() {
+                if (!this.isCalculated()) {
+                    return this.notCalculatedMessage;
+                }
+                var price =  this.totals().shipping_incl_tax;
+                return this.getFormattedPrice(price);
+            },
+            getExcludingValue: function() {
+                if (!this.isCalculated()) {
+                    return this.notCalculatedMessage;
+                }
+                var price =  this.totals().shipping_amount;
+                return this.getFormattedPrice(price);
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js
similarity index 63%
rename from app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js
rename to app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js
index 06a169784c3f625b7784a67dec4b79905c8d1bad..e9e86cd9fa03119f034eb91a70b48227ad169987 100644
--- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js
@@ -6,23 +6,15 @@
 /*global alert*/
 define(
     [
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote'
     ],
-    function (Component, quote, priceUtils) {
+    function (Component, quote) {
         var displaySubtotalMode = window.checkoutConfig.reviewTotalsDisplayMode;
         return Component.extend({
             defaults: {
                 displaySubtotalMode: displaySubtotalMode,
-                template: 'Magento_Tax/checkout/review/subtotal'
-            },
-            getColspan: 3,
-            style: "",
-            excludingTaxMessage: 'Subtotal (Excl. Tax)',
-            includingTaxMessage: 'Subtotal (Incl. Tax)',
-            getTitle: function() {
-                return "Subtotal"
+                template: 'Magento_Tax/checkout/summary/subtotal'
             },
             totals: quote.getTotals(),
             getValue: function () {
@@ -30,7 +22,7 @@ define(
                 if (this.totals()) {
                     price = this.totals().subtotal;
                 }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
+                return this.getFormattedPrice(price);
             },
             isBothPricesDisplayed: function() {
                 return 'both' == this.displaySubtotalMode;
@@ -43,7 +35,7 @@ define(
                 if (this.totals()) {
                     price = this.totals().subtotal_incl_tax;
                 }
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
+                return this.getFormattedPrice(price);
             }
         });
     }
diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js
new file mode 100644
index 0000000000000000000000000000000000000000..019b0717c70afdebf57d04f73e75e6fdb6564956
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js
@@ -0,0 +1,77 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+/*global alert*/
+define(
+    [
+        'ko',
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/totals'
+    ],
+    function (ko, Component, quote, totals) {
+        "use strict";
+        var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal;
+        var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed;
+        var isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed;
+        return Component.extend({
+            defaults: {
+                isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,
+                notCalculatedMessage: 'Not yet calculated',
+                template: 'Magento_Tax/checkout/summary/tax'
+            },
+            totals: quote.getTotals(),
+            isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,
+            ifShowValue: function() {
+                if (!isTaxDisplayedInGrandTotal) {
+                    return false;
+                }
+                if (!this.totals() || null == totals.getSegment('tax')) {
+                    return true;
+                }
+                if (this.getPureValue() == 0) {
+                    return isZeroTaxDisplayed;
+                }
+                return true;
+            },
+            ifShowDetails: function() {
+                if (!this.isFullMode()) {
+                    return false;
+                }
+                return isTaxDisplayedInGrandTotal && this.getPureValue() > 0 && isFullTaxSummaryDisplayed;
+            },
+            getPureValue: function() {
+                var amount = 0;
+                if (this.totals()) {
+                    var taxTotal = totals.getSegment('tax');
+                    if (taxTotal) {
+                        amount = taxTotal.value;
+                    }
+                }
+                return amount;
+            },
+            isCalculated: function() {
+                return this.totals() && this.isFullMode() && null != totals.getSegment('tax');
+            },
+            getValue: function() {
+                if (!this.isCalculated()) {
+                    return this.notCalculatedMessage;
+                }
+                var amount = totals.getSegment('tax').value;
+                return this.getFormattedPrice(amount);
+            },
+            formatPrice: function(amount) {
+                return this.getFormattedPrice(amount);
+            },
+            getDetails: function() {
+                var totals = this.totals();
+                if (totals.extension_attributes) {
+                    return totals.extension_attributes.tax_grandtotal_details;
+                }
+                return [];
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html
deleted file mode 100644
index 237b692b59a6f20c62fab5b3c9c5ef157ffe37ab..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-
-<!-- ko foreach: elems() -->
-<!-- ko template: getTemplate() --><!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html
deleted file mode 100644
index 8c533bcae6fca5bb34f84282e33adcf595e4167d..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: isTaxDisplayedInGrandTotal -->
-<tr class="grand totals excl">
-    <th data-bind="attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row">
-        <strong data-bind="text: exclTaxLabel"></strong>
-    </th>
-    <td data-bind="attr: {'style': style, 'data-th': exclTaxLabel }" class="amount">
-        <strong data-bind="text: getGrandTotalExclTax()"></strong>
-    </td>
-</tr>
-    <!-- ko foreach: elems() -->
-        <!-- ko template: getTemplate() --><!-- /ko -->
-    <!-- /ko -->
-<tr class="grand totals incl">
-    <th data-bind="attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row">
-        <strong data-bind="text: $t(inclTaxLabel)"></strong>
-    </th>
-    <td data-bind="attr: {'style': style, 'data-th': $t(inclTaxLabel) }" class="amount">
-        <strong data-bind="text: getValue()"></strong>
-    </td>
-</tr>
-<!-- /ko -->
-<!-- ko if: !isTaxDisplayedInGrandTotal -->
-<tr class="grand totals">
-    <th data-bind="attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row">
-        <strong data-bind="text: $t(getTitle())"></strong>
-    </th>
-    <td data-bind="attr: {'style':style, 'data-th': getTitle()}" class="amount">
-        <strong data-bind="text: getValue()"></strong>
-    </td>
-</tr>
-<!-- /ko -->
-<!-- ko if: isBaseGrandTotalDisplayNeeded() -->
-<tr class="totals charge">
-    <th class="mark" data-bind="text: $t(basicCurrencyMessage), attr: { 'colspan': getColspan }" scope="row"></th>
-    <td class="amount" data-bind="text: getBaseValue(), attr: {'data-th': $t(basicCurrencyMessage)}"></td>
-</tr>
-<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html
deleted file mode 100644
index fc596c7d1ac5e35a6d6590ecf2231b0fc88b52e9..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<td data-bind="attr: { 'data-th': $t(getColName()), class: getClass() }">
-    <!-- ko if: isPriceInclTaxDisplayed() -->
-    <span class="price-including-tax" data-bind ="attr:{'data-label': $t('Incl. Tax')}">
-            <!-- ko foreach: getRegion('unit_incl_tax') -->
-                <!-- ko template: getTemplate() --><!-- /ko -->
-            <!-- /ko -->
-    </span>
-
-    <!-- /ko -->
-    <!-- ko if: isPriceExclTaxDisplayed() -->
-    <span class="price-excluding-tax" data-bind ="attr:{'data-label': $t('Excl. Tax')}">
-            <!-- ko foreach: getRegion('unit_excl_tax') -->
-                <!-- ko template: getTemplate() --><!-- /ko -->
-            <!-- /ko -->
-    </span>
-    <!-- /ko -->
-</td>
\ No newline at end of file
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html
deleted file mode 100644
index 6c7900d23315bdf25c4b3ad02a2382295cc1a90d..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: quoteIsVirtual == 0 -->
-    <!-- ko if: isBothPricesDisplayed() -->
-    <tr class="totals shipping excl">
-        <th data-bind="text: $t(getExcludingLabel()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th>
-        <td class="amount" data-bind="text: getExcludingValue(), attr: {'style':style, 'data-th': $t(getExcludingLabel())}"></td>
-    </tr>
-    <tr class="totals shipping incl">
-        <th data-bind="text: $t(getIncludingLabel()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th>
-        <td class="amount" data-bind="text: getIncludingValue(), attr: {'style':style, 'data-th': $t(getIncludingLabel())}"></td>
-    </tr>
-    <!-- /ko -->
-    <!-- ko if: isIncludingDisplayed() -->
-    <tr class="totals shipping incl">
-        <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th>
-        <td class="amount" data-bind="text: getIncludingValue(), attr: {'style':style, 'data-th': $t(getTitle())}"></td>
-    </tr>
-    <!-- /ko -->
-    <!-- ko if: isExcludingDisplayed() -->
-    <tr class="totals shipping excl">
-        <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th>
-        <td  data-bind="text: getValue(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td>
-    </tr>
-    <!-- /ko -->
-<!-- /ko -->
-
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html
deleted file mode 100644
index 022131d8a0cc957a96ea074f4fe05c1292e4616d..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if: isBothPricesDisplayed() -->
-<tr class="totals sub excl">
-    <th data-bind="text: excludingTaxMessage, attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row">
-    </th>
-    <td data-bind="text: getValue(), attr: {'style': style, 'data-th': $t(excludingTaxMessage) }" class="amount"></td>
-</tr>
-<tr class="totals sub incl">
-    <th data-bind="text: includingTaxMessage, attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row">
-    </th>
-    <td data-bind="text: getValueInclTax(), attr: {'style': style, 'data-th': $t(includingTaxMessage) }" class="amount">
-    </td>
-</tr>
-<!-- /ko -->
-<!-- ko if: !isBothPricesDisplayed() && isIncludingTaxDisplayed() -->
-<tr class="totals sub">
-    <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"></th>
-    <td data-bind="text: getValueInclTax(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td>
-</tr>
-<!-- /ko -->
-<!-- ko if: !isBothPricesDisplayed() && !isIncludingTaxDisplayed() -->
-<tr class="totals sub">
-    <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"></th>
-    <td data-bind="text: getValue(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td>
-</tr>
-<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html
deleted file mode 100644
index e22db68f36617b6c3ceb614fcf4fc1d250bf62ed..0000000000000000000000000000000000000000
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko ifnot: isFullTaxSummaryDisplayed -->
-<tr class="totals-tax">
-    <th data-bind="text: getTitle(), attr: {'style':style, 'colspan': colspan}" class="mark" scope="row">
-    </th>
-    <td data-bind="attr: {'style': style, 'data-th': $t(getTitle()) }" class="amount">
-        <span class="price" data-bind="text: getValue()"></span>
-    </td>
-</tr>
-<!-- /ko -->
-<!-- ko if: isFullTaxSummaryDisplayed -->
-    <tr class="totals-tax-summary" data-bind="click: toggleDetails()">
-        <th data-bind="text: getTitle(), attr: {'style':style, 'colspan': colspan}" class="mark" scope="row">
-        </th>
-        <td data-bind="attr: {'style': style, 'data-th': $t(getTitle()) }" class="amount">
-            <span class="price" data-bind="text: getValue()"></span>
-        </td>
-    </tr>
-    <!-- ko foreach: getDetails() -->
-        <!-- ko foreach: rates -->
-        <tr class="totals-tax-details" data-bind="visible: $parents[1].isDetailsVisible">
-            <!-- ko if: percent -->
-                <th class="mark" scope="row" data-bind="text: title + ' (' + percent + '%)', attr: {'style': $parents[1].style, 'colspan': $parents[1].colspan}">
-                </th>
-            <!-- /ko -->
-            <!-- ko if: !percent -->
-                <th class="mark" scope="row" data-bind="text: title, attr: {'style': $parents[1].style, 'colspan': $parents[1].colspan}">
-                </th>
-            <!-- /ko -->
-            <!-- ko if: $index() == 0 -->
-                <td class="amount" data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'style': $parents[1].style, 'rowspan': $parents[0].rates.length }">
-                </td>
-            <!-- /ko -->
-        </tr>
-        <!-- /ko -->
-    <!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html
index e854b9f1e0bc2e4a9a8f50c89ebc77e82f084fce..345b3eea5b0490a15af75cda91627f31bf06ffa6 100644
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html
@@ -5,22 +5,22 @@
  */
 -->
 <!-- ko if:  isDisplayShippingPriceExclTax -->
-<span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_excl_tax)"></span></span>
+<span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_excl_tax)"></span></span>
 <!-- /ko -->
 <!-- ko ifnot: isDisplayShippingPriceExclTax -->
-<!-- ko if:  (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))-->
+<!-- ko if:  (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))-->
 <span class="price-including-tax" data-bind = "attr: {'data-label': $t('Incl. Tax')}">
-    <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span>
+    <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_incl_tax)"></span></span>
 </span>
 <!-- /ko -->
 
-<!-- ko ifnot:  (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))-->
-    <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span>
+<!-- ko ifnot:  (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))-->
+    <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_incl_tax)"></span></span>
 <!-- /ko -->
 
 <!-- /ko -->
-<!-- ko if:  (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))-->
+<!-- ko if:  (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))-->
 <span class="price-excluding-tax" data-bind = "attr: {'data-label': $t('Excl. Tax')}">
-    <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_excl_tax)"></span></span>
+    <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_excl_tax)"></span></span>
 </span>
 <!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html
new file mode 100644
index 0000000000000000000000000000000000000000..d37e8816ae3e05c1cf806e520ac810e4d7a653b2
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html
@@ -0,0 +1,42 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: isTaxDisplayedInGrandTotal && isDisplayed() -->
+<tr class="grand totals incl">
+    <th class="mark" scope="row">
+        <strong data-bind="text: $t(inclTaxLabel)"></strong>
+    </th>
+    <td data-bind="attr: {'data-th': $t(inclTaxLabel) }" class="amount">
+        <strong><span class="price" data-bind="text: getValue()"></span></strong>
+    </td>
+</tr>
+<tr class="grand totals excl">
+    <th class="mark" scope="row">
+        <strong data-bind="text: $t(exclTaxLabel)"></strong>
+    </th>
+    <td data-bind="attr: {'data-th': exclTaxLabel }" class="amount">
+        <strong><span class="price" data-bind="text: getGrandTotalExclTax()"></span></strong>
+    </td>
+</tr>
+<!-- /ko -->
+<!-- ko if: !isTaxDisplayedInGrandTotal && isDisplayed() -->
+<tr class="grand totals">
+    <th class="mark" scope="row">
+        <strong data-bind="text: $t(title)"></strong>
+    </th>
+    <td data-bind="attr: {'data-th': $t(title)}" class="amount">
+        <strong><span class="price" data-bind="text: getValue()"></span></strong>
+    </td>
+</tr>
+<!-- /ko -->
+<!-- ko if: isBaseGrandTotalDisplayNeeded() && isDisplayed() -->
+<tr class="totals charge">
+    <th class="mark" data-bind="text: $t(basicCurrencyMessage)" scope="row"></th>
+    <td class="amount">
+        <span class="price" data-bind="text: getBaseValue(), attr: {'data-th': $t(basicCurrencyMessage)}"></span>
+    </td>
+</tr>
+<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html
similarity index 50%
rename from app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html
rename to app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html
index d489e741ba0474ea1af3e1ca0c72e24d8ac4de85..5d555b1b54f50c13ada9f31da8ffce63f85795a3 100644
--- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html
@@ -4,20 +4,29 @@
  * See COPYING.txt for license details.
  */
 -->
-<td data-bind="attr: { 'data-th': $t(getColName())}" class="col subtotal">
-    <!-- ko if: isPriceInclTaxDisplayed() -->
+<div class="subtotal">
+    <!-- ko if: isPriceInclTaxDisplayed() && !getRegion('row_incl_tax') -->
+    <span class="price-including-tax" data-bind ="text: getValueInclTax($parents[1]), attr:{'data-label': $t('Incl. Tax')}">
+    </span>
+    <!-- /ko -->
+
+    <!-- ko if: isPriceInclTaxDisplayed() && getRegion('row_incl_tax') -->
     <span class="price-including-tax" data-bind ="attr:{'data-label': $t('Incl. Tax')}">
             <!-- ko foreach: getRegion('row_incl_tax') -->
                 <!-- ko template: getTemplate() --><!-- /ko -->
             <!-- /ko -->
     </span>
+    <!-- /ko -->
 
+    <!-- ko if: isPriceExclTaxDisplayed() && !getRegion('row_excl_tax') -->
+    <span class="price-excluding-tax" data-bind ="text: getValueExclTax($parents[1]), attr:{'data-label': $t('Excl. Tax')}">
+    </span>
     <!-- /ko -->
-    <!-- ko if: isPriceExclTaxDisplayed() -->
+    <!-- ko if: isPriceExclTaxDisplayed() && getRegion('row_excl_tax') -->
     <span class="price-excluding-tax" data-bind ="attr:{'data-label': $t('Excl. Tax')}">
             <!-- ko foreach: getRegion('row_excl_tax') -->
                 <!-- ko template: getTemplate() --><!-- /ko -->
             <!-- /ko -->
     </span>
     <!-- /ko -->
-</td>
\ No newline at end of file
+</div>
\ No newline at end of file
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html
new file mode 100644
index 0000000000000000000000000000000000000000..8caba625561dfde89afdef0c04a97dbfb0de6c0e
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html
@@ -0,0 +1,78 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: quoteIsVirtual == 0 -->
+    <!-- ko if: isBothPricesDisplayed() -->
+    <tr class="totals shipping excl">
+        <th class="mark" scope="row">
+            <span class="label" data-bind="text: $t(title) + ' ' + $t(excludingTaxMessage)"></span>
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </th>
+        <td class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getExcludingValue()), attr: {'data-th': $t(excludingTaxMessage)}"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getExcludingValue()), attr: {'data-th': $t(excludingTaxMessage)}"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+    <tr class="totals shipping incl">
+        <th class="mark" scope="row">
+            <span class="label" data-bind="text: $t(title) + ' ' + $t(includingTaxMessage)"></span>
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </th>
+        <td class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+    <!-- /ko -->
+    <!-- ko if: isIncludingDisplayed() -->
+    <tr class="totals shipping incl">
+        <th class="mark" scope="row">
+            <span class="label" data-bind="text: $t(title)"></span>
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </th>
+        <td class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+    <!-- /ko -->
+    <!-- ko if: isExcludingDisplayed() -->
+    <tr class="totals shipping excl">
+        <th class="mark" scope="row">
+            <span class="label" data-bind="text: $t(title)"></span>
+            <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span>
+        </th>
+        <td class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+    <!-- /ko -->
+<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html
new file mode 100644
index 0000000000000000000000000000000000000000..4652d47e5e35a6b7a868c795ac946999b43b6612
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html
@@ -0,0 +1,42 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: isBothPricesDisplayed() -->
+<tr class="totals sub excl">
+    <th class="mark" scope="row">
+        <span data-bind="text: $t(title)"></span>
+        <span data-bind="text: $t(excludingTaxMessage)"></span>
+    </th>
+    <td class="amount">
+        <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(excludingTaxMessage) }"></span>
+    </td>
+</tr>
+<tr class="totals sub incl">
+    <th class="mark" scope="row">
+        <span data-bind="text: $t(title)"></span>
+        <span data-bind="text: $t(includingTaxMessage)"></span>
+    </th>
+    <td class="amount">
+        <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(includingTaxMessage) }"></span>
+    </td>
+</tr>
+<!-- /ko -->
+<!-- ko if: !isBothPricesDisplayed() && isIncludingTaxDisplayed() -->
+<tr class="totals sub">
+    <th data-bind="text: $t(title)" class="mark" scope="row"></th>
+    <td class="amount">
+        <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(title)}"></span>
+    </td>
+</tr>
+<!-- /ko -->
+<!-- ko if: !isBothPricesDisplayed() && !isIncludingTaxDisplayed() -->
+<tr class="totals sub">
+    <th data-bind="text: $t(title)" class="mark" scope="row"></th>
+    <td class="amount">
+        <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(title)}"></span>
+    </td>
+</tr>
+<!-- /ko -->
diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html
new file mode 100644
index 0000000000000000000000000000000000000000..5b2b739402261b01f95e51d363961e015d840c1a
--- /dev/null
+++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html
@@ -0,0 +1,61 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if: ifShowValue() && !ifShowDetails() -->
+<tr class="totals-tax">
+    <th data-bind="text: $t(title)" class="mark" scope="row"></th>
+    <td data-bind="attr: {'data-th': $t(title) }" class="amount">
+        <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getValue())"></span>
+        <!-- /ko -->
+        <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getValue())"></span>
+        <!-- /ko -->
+    </td>
+</tr>
+<!-- /ko -->
+<!-- ko if: ifShowValue() && ifShowDetails() -->
+    <tr class="totals-tax-summary"
+        data-bind="mageInit: {'toggleAdvanced':{'selectorsToggleClass': 'shown', 'baseToggleClass': 'expanded', 'toggleContainers': '.totals-tax-details'}}">
+        <th data-bind="text: $t(title)" class="mark" scope="row"></th>
+        <td data-bind="attr: {'data-th': $t(title) }" class="amount">
+            <!-- ko if: isCalculated() -->
+            <span class="price"
+                  data-bind="text: $t(getValue())"></span>
+            <!-- /ko -->
+            <!-- ko ifnot: isCalculated() -->
+            <span class="not-calculated"
+                  data-bind="text: $t(getValue())"></span>
+            <!-- /ko -->
+        </td>
+    </tr>
+    <!-- ko foreach: getDetails() -->
+        <!-- ko foreach: rates -->
+        <tr class="totals-tax-details">
+            <!-- ko if: percent -->
+                <th class="mark" scope="row" data-bind="text: title + ' (' + percent + '%)'"></th>
+            <!-- /ko -->
+            <!-- ko if: !percent -->
+                <th class="mark" scope="row" data-bind="text: title"></th>
+            <!-- /ko -->
+            <!-- ko if: $index() == 0 -->
+                <td class="amount">
+                    <!-- ko if: $parents[1].isCalculated() -->
+                    <span class="price"
+                          data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'rowspan': $parents[0].rates.length }"></span>
+                    <!-- /ko -->
+                    <!-- ko ifnot: $parents[1].isCalculated() -->
+                    <span class="not-calculated"
+                          data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'rowspan': $parents[0].rates.length }"></span>
+                    <!-- /ko -->
+                </td>
+            <!-- /ko -->
+        </tr>
+        <!-- /ko -->
+    <!-- /ko -->
+<!-- /ko -->
diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php
index c7af5b3f471c7c084826bc98c45a0ab6c2610cb2..0a15bafe9915faa5aefea6f006e169ea626523db 100644
--- a/app/code/Magento/Ui/Component/AbstractComponent.php
+++ b/app/code/Magento/Ui/Component/AbstractComponent.php
@@ -8,14 +8,13 @@ namespace Magento\Ui\Component;
 use Magento\Framework\Object;
 use Magento\Framework\View\Element\UiComponentInterface;
 use Magento\Framework\View\Element\UiComponent\ContextInterface;
-use Magento\Framework\View\Element\UiComponent\JsConfigInterface;
 use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
 
 /**
  * Abstract class AbstractComponent
  * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
-abstract class AbstractComponent extends Object implements UiComponentInterface, JsConfigInterface
+abstract class AbstractComponent extends Object implements UiComponentInterface
 {
     /**
      * Render context
@@ -227,6 +226,7 @@ abstract class AbstractComponent extends Object implements UiComponentInterface,
      *
      * @param array $dataSource
      * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function prepareDataSource(array & $dataSource)
     {
diff --git a/app/code/Magento/Ui/Component/Container.php b/app/code/Magento/Ui/Component/Container.php
index 6b642b9a3e04525c63ac0df53a8c6113eb44cf66..352dfdf2942bcd5d1557d1f9df5041c588f1074e 100644
--- a/app/code/Magento/Ui/Component/Container.php
+++ b/app/code/Magento/Ui/Component/Container.php
@@ -5,8 +5,6 @@
  */
 namespace Magento\Ui\Component;
 
-use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
-
 /**
  * Class Container
  */
diff --git a/app/code/Magento/Ui/Component/Form.php b/app/code/Magento/Ui/Component/Form.php
index ed0b344658a30c610169de97e9de8aaeb20d41f8..ee1e32e30e07e954786963644079ba439842ae0a 100644
--- a/app/code/Magento/Ui/Component/Form.php
+++ b/app/code/Magento/Ui/Component/Form.php
@@ -5,8 +5,6 @@
  */
 namespace Magento\Ui\Component;
 
-use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
-
 /**
  * Class Form
  */
diff --git a/app/code/Magento/Ui/Component/Form/Element/Multiline.php b/app/code/Magento/Ui/Component/Form/Element/Multiline.php
index 5f508343d4316fbf6b3f788fddab37057d669474..3669cd079a44f56e85d0c816da41f7cdb78b675e 100644
--- a/app/code/Magento/Ui/Component/Form/Element/Multiline.php
+++ b/app/code/Magento/Ui/Component/Form/Element/Multiline.php
@@ -5,6 +5,11 @@
  */
 namespace Magento\Ui\Component\Form\Element;
 
+use Magento\Ui\Component\Form\Field;
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+
 /**
  * Class Multiline
  */
@@ -12,6 +17,35 @@ class Multiline extends AbstractElement
 {
     const NAME = 'multiline';
 
+    const FORM_ELEMENT = 'input';
+
+    const DATA_TYPE = 'text';
+
+    /**
+     * UI component factory
+     *
+     * @var UiComponentFactory
+     */
+    protected $uiComponentFactory;
+
+    /**
+     * Constructor
+     *
+     * @param ContextInterface $context
+     * @param UiComponentFactory $uiComponentFactory
+     * @param UiComponentInterface[] $components
+     * @param array $data
+     */
+    public function __construct(
+        ContextInterface $context,
+        UiComponentFactory $uiComponentFactory,
+        array $components = [],
+        array $data = []
+    ) {
+        $this->uiComponentFactory = $uiComponentFactory;
+        parent::__construct($context, $components, $data);
+    }
+
     /**
      * Get component name
      *
@@ -23,10 +57,37 @@ class Multiline extends AbstractElement
     }
 
     /**
-     * @return mixed|string
+     * Prepare component configuration
+     *
+     * @return void
      */
-    public function getType()
+    public function prepare()
     {
-        return $this->getData('input_type') ? $this->getData('input_type') : 'text';
+        $size = abs((int) $this->getData('config/size'));
+        $validation = [$this->getData('config/validation')];
+        while ($size--) {
+            $identifier = $this->getName() . '_' . $size;
+            $arguments = [
+                'data' => [
+                    'name' => $identifier,
+                    'config' => [
+                        'dataScope' => $size,
+                        'dataType' => static::DATA_TYPE,
+                        'formElement' => static::FORM_ELEMENT,
+                        'sortOrder' => $size,
+                    ]
+                ]
+            ];
+
+            if (!empty($validation[$size])) {
+                $arguments['data']['config']['validation'] = $validation[$size];
+            }
+
+            $component = $this->uiComponentFactory->create($identifier, Field::NAME, $arguments);
+            $component->prepare();
+
+            $this->components[$identifier] = $component;
+        }
+        parent::prepare();
     }
 }
diff --git a/app/code/Magento/Ui/Component/Form/Field.php b/app/code/Magento/Ui/Component/Form/Field.php
index 670fa9004b6752f1afad78854824a9a0b66547c3..d2ff377ae5bd4868179d4bef1db12cf640df4fb5 100644
--- a/app/code/Magento/Ui/Component/Form/Field.php
+++ b/app/code/Magento/Ui/Component/Form/Field.php
@@ -80,23 +80,23 @@ class Field extends AbstractComponent
             $formElement,
             array_merge(['context' => $this->getContext()], (array)$this->getData())
         );
+        $this->wrappedComponent->setData(
+            'config',
+            array_replace_recursive(
+                (array) $this->wrappedComponent->getData('config'),
+                (array) $this->getData('config')
+            )
+        );
         $this->wrappedComponent->prepare();
+        $this->components = $this->wrappedComponent->getChildComponents();
         // Merge JS configuration with wrapped component configuration
         $wrappedComponentConfig = $this->getJsConfig($this->wrappedComponent);
-        $jsConfig = array_replace_recursive(
-            $wrappedComponentConfig,
-            $this->getJsConfig($this)
-        );
+
+        $jsConfig = array_replace_recursive($wrappedComponentConfig, $this->getJsConfig($this));
         $jsConfig['extends'] = $this->wrappedComponent->getComponentName();
         $this->setData('js_config', $jsConfig);
 
-        $this->setData(
-            'config',
-            array_replace_recursive(
-                (array)$this->wrappedComponent->getData('config'),
-                (array)$this->getData('config')
-            )
-        );
+        $this->setData('config', $this->wrappedComponent->getData('config'));
 
         parent::prepare();
     }
diff --git a/app/code/Magento/Ui/Component/Form/Fieldset.php b/app/code/Magento/Ui/Component/Form/Fieldset.php
index 00a1b0579e9e8e6767a2fcd17e41ed46be0f2cd1..45d03c005f602734617487639dda3f1f91748d7a 100644
--- a/app/code/Magento/Ui/Component/Form/Fieldset.php
+++ b/app/code/Magento/Ui/Component/Form/Fieldset.php
@@ -5,7 +5,6 @@
  */
 namespace Magento\Ui\Component\Form;
 
-use Magento\Framework\Exception\LocalizedException;
 use Magento\Ui\Component\Container;
 use Magento\Ui\Component\AbstractComponent;
 use Magento\Framework\View\Element\UiComponentFactory;
@@ -104,7 +103,7 @@ class Fieldset extends AbstractComponent
                     'config' => $fieldData
                 ]
             ];
-            $fieldComponent = $this->uiComponentFactory->create($name, 'field', $argument);
+            $fieldComponent = $this->uiComponentFactory->create($name, Field::NAME, $argument);
             $fieldComponent->prepare();
             $this->addComponent($name, $fieldComponent);
         } else {
diff --git a/app/code/Magento/Ui/Component/Layout/Generic.php b/app/code/Magento/Ui/Component/Layout/Generic.php
index 0d8ee7d0cea07c5dcda4197b2dcf68833aa572ae..92d0a406f38e067fd5fc189ae3e1821fd788eeac 100644
--- a/app/code/Magento/Ui/Component/Layout/Generic.php
+++ b/app/code/Magento/Ui/Component/Layout/Generic.php
@@ -6,7 +6,6 @@
 namespace Magento\Ui\Component\Layout;
 
 use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
-use Magento\Framework\View\Element\UiComponent\JsConfigInterface;
 use Magento\Framework\View\Element\UiComponent\LayoutInterface;
 use Magento\Framework\View\Element\UiComponentInterface;
 
diff --git a/app/code/Magento/Ui/Component/Listing.php b/app/code/Magento/Ui/Component/Listing.php
index 7d7d7b692b26042a08d41295f7a24d6536fd1802..363144c10d29a3991d070e65299de367be2425d1 100644
--- a/app/code/Magento/Ui/Component/Listing.php
+++ b/app/code/Magento/Ui/Component/Listing.php
@@ -6,8 +6,6 @@
 namespace Magento\Ui\Component;
 
 use Magento\Ui\Component\Listing\Columns;
-use Magento\Ui\Component\Listing\Columns\Column;
-use Magento\Framework\View\Element\UiComponent\DataSourceInterface;
 
 /**
  * Class Listing
diff --git a/app/code/Magento/Ui/DataProvider/EavValidationRul.php b/app/code/Magento/Ui/DataProvider/EavValidationRules.php
similarity index 96%
rename from app/code/Magento/Ui/DataProvider/EavValidationRul.php
rename to app/code/Magento/Ui/DataProvider/EavValidationRules.php
index 1d338ec30755af34f8653ca99b65f8202b141d7a..28551180b16fb4e33da680fe0f24211639f35bd7 100644
--- a/app/code/Magento/Ui/DataProvider/EavValidationRul.php
+++ b/app/code/Magento/Ui/DataProvider/EavValidationRules.php
@@ -8,9 +8,9 @@ namespace Magento\Ui\DataProvider;
 use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
 
 /**
- * Class EavValidationRul
+ * Class EavValidationRules
  */
-class EavValidationRul
+class EavValidationRules
 {
     /**
      * @var array
diff --git a/app/code/Magento/Ui/Test/Unit/Component/Form/Field/MultilineTest.php b/app/code/Magento/Ui/Test/Unit/Component/Form/Field/MultilineTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1e717c1525fed4c226a20a697b0e9ce5f488172
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Component/Form/Field/MultilineTest.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Component\Form\Field;
+
+use Magento\Ui\Component\Form\Field;
+use Magento\Ui\Component\Form\Element\Multiline;
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+
+/**
+ * Class MultilineTest
+ *
+ * Test for class \Magento\Ui\Component\Form\Element\Multiline
+ */
+class MultilineTest extends \PHPUnit_Framework_TestCase
+{
+    const NAME = 'test-name';
+
+    /**
+     * @var Multiline
+     */
+    protected $multiline;
+
+    /**
+     * @var UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $uiComponentFactoryMock;
+
+    /**
+     * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->uiComponentFactoryMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->contextMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponent\ContextInterface')
+            ->getMockForAbstractClass();
+
+        $this->multiline = new Multiline(
+            $this->contextMock,
+            $this->uiComponentFactoryMock
+        );
+    }
+
+    /**
+     * Run test for prepare method
+     *
+     * @param array $data
+     * @return void
+     *
+     * @dataProvider prepareDataProvider
+     */
+    public function testPrepare(array $data)
+    {
+        $this->uiComponentFactoryMock->expects($this->exactly($data['config']['size']))
+            ->method('create')
+            ->with($this->stringContains(self::NAME . '_'), Field::NAME, $this->logicalNot($this->isEmpty()))
+            ->willReturn($this->getComponentMock($data['config']['size']));
+
+        $this->multiline->setData($data);
+        $this->multiline->prepare();
+
+        $result = $this->multiline->getData();
+
+        $this->assertEquals($data, $result);
+    }
+
+    /**
+     * @param int $exactly
+     * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getComponentMock($exactly)
+    {
+        $componentMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $componentMock->expects($this->exactly($exactly))
+            ->method('prepare');
+
+        return $componentMock;
+    }
+
+    /**
+     * Data provider for testPrepare
+     *
+     * @return array
+     */
+    public function prepareDataProvider()
+    {
+        return [
+            [
+                'data' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'size' => 2,
+                    ]
+                ],
+            ],
+            [
+                'data' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'size' => 3,
+                    ]
+                ],
+            ],
+            [
+                'data' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'size' => 1,
+                    ]
+                ],
+            ],
+            [
+                'data' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'size' => 5,
+                    ]
+                ],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php b/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..86a47115d31129abfedb6fe3ceafafc394879912
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php
@@ -0,0 +1,177 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Component\Form;
+
+use Magento\Ui\Component\Form\Field;
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+
+/**
+ * Class FieldTest
+ *
+ * Test for class \Magento\Ui\Component\Form\Field
+ */
+class FieldTest extends \PHPUnit_Framework_TestCase
+{
+    const NAME = 'test-name';
+    const COMPONENT_NAME = 'test-name';
+    const COMPONENT_NAMESPACE = 'test-name';
+
+    /**
+     * @var Field
+     */
+    protected $field;
+
+    /**
+     * @var UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $uiComponentFactoryMock;
+
+    /**
+     * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var array
+     */
+    protected $testConfigData = [
+        ['config', null, ['test-key' => 'test-value']],
+        ['js_config', null, ['test-key' => 'test-value']]
+    ];
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->uiComponentFactoryMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->contextMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponent\ContextInterface')
+            ->getMockForAbstractClass();
+
+        $this->field = new Field(
+            $this->contextMock,
+            $this->uiComponentFactoryMock
+        );
+    }
+
+    /**
+     * Run test for prepare method
+     *
+     * @param array $data
+     * @param array $expectedData
+     * @return void
+     *
+     * @dataProvider prepareSuccessDataProvider
+     */
+    public function testPrepareSuccess(array $data, array $expectedData)
+    {
+        $this->uiComponentFactoryMock->expects($this->once())
+            ->method('create')
+            ->with(self::NAME, $data['config']['formElement'], $this->arrayHasKey('context'))
+            ->willReturn($this->getWrappedComponentMock());
+
+        $this->contextMock->expects($this->any())
+            ->method('getNamespace')
+            ->willReturn(self::COMPONENT_NAMESPACE);
+
+        $this->field->setData($data);
+        $this->field->prepare();
+        $result = $this->field->getData();
+
+        $this->assertEquals($expectedData, $result);
+    }
+
+    /**
+     * Data provider for testPrepare
+     *
+     * @return array
+     */
+    public function prepareSuccessDataProvider()
+    {
+        return [
+            [
+                'data' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'formElement' => 'test',
+                    ]
+                ],
+                'expectedData' => [
+                    'name' => self::NAME,
+                    'config' => [
+                        'test-key' => 'test-value',
+                    ],
+                    'js_config' => [
+                        'extends' => self::NAME,
+                        'test-key' => 'test-value',
+                    ]
+                ]
+            ],
+        ];
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject|UiComponentInterface
+     */
+    protected function getWrappedComponentMock()
+    {
+        $wrappedComponentMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $wrappedComponentMock->expects($this->any())
+            ->method('getData')
+            ->willReturnMap($this->testConfigData);
+        $wrappedComponentMock->expects($this->once())
+            ->method('setData')
+            ->with('config', $this->logicalNot($this->isEmpty()));
+        $wrappedComponentMock->expects($this->once())
+            ->method('prepare');
+        $wrappedComponentMock->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn($this->getComponentsMock());
+        $wrappedComponentMock->expects($this->exactly(2))
+            ->method('getComponentName')
+            ->willReturn(self::COMPONENT_NAME);
+        $wrappedComponentMock->expects($this->once())
+            ->method('getContext')
+            ->willReturn($this->contextMock);
+
+        return $wrappedComponentMock;
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject[]|UiComponentInterface[]
+     */
+    protected function getComponentsMock()
+    {
+        $componentMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        return [$componentMock];
+    }
+
+    /**
+     * Run test prepare method (Exception)
+     *
+     * @return void
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage The configuration parameter "formElement" is a required for "test-name" field.
+     */
+    public function testPrepareException()
+    {
+        $this->uiComponentFactoryMock->expects($this->never())
+            ->method('create');
+        $this->field->setData(['name' => self::NAME]);
+        $this->field->prepare();
+    }
+}
diff --git a/app/code/Magento/Ui/etc/ui_components.xsd b/app/code/Magento/Ui/etc/ui_components.xsd
index 86a6f5aaeca39cee9fccbc8f6714446f57d87872..17a80e2f4ac37e725e061d347aeb431e23162244 100644
--- a/app/code/Magento/Ui/etc/ui_components.xsd
+++ b/app/code/Magento/Ui/etc/ui_components.xsd
@@ -177,6 +177,15 @@
             </xs:extension>
         </xs:complexContent>
     </xs:complexType>
+    <xs:complexType name="multiline">
+        <xs:complexContent>
+            <xs:extension base="ui_element">
+                <xs:choice minOccurs="0" maxOccurs="unbounded">
+                    <xs:group ref="configurable"/>
+                </xs:choice>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
     <xs:complexType name="fieldset">
         <xs:complexContent>
             <xs:extension base="ui_element">
diff --git a/app/code/Magento/Ui/etc/ui_definition.xsd b/app/code/Magento/Ui/etc/ui_definition.xsd
index 171b3e1b7dbef8660f7cee0d70f38d39cfb3336f..f0154eecb99647f17d7bb96c9c9c7c554806f0d1 100644
--- a/app/code/Magento/Ui/etc/ui_definition.xsd
+++ b/app/code/Magento/Ui/etc/ui_definition.xsd
@@ -39,6 +39,7 @@
             <xs:element type="select" name="select"/>
             <xs:element type="multiselect" name="multiselect"/>
             <xs:element type="textarea" name="textarea"/>
+            <xs:element type="multiline" name="multiline"/>
             <xs:element type="dataTypeText" name="text"/>
             <xs:element type="dataTypeBoolean" name="boolean"/>
             <xs:element type="dataTypeNumber" name="number"/>
diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
index 54e661645fec41aba65109bd3025aa626c27cb0b..df5cfa21eca0a080805e940d75726c60f188141f 100644
--- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
+++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
@@ -178,6 +178,13 @@
             </item>
         </argument>
     </textarea>
+    <multiline class="Magento\Ui\Component\Form\Element\Multiline">
+        <argument name="data" xsi:type="array">
+            <item name="js_config" xsi:type="array">
+                <item name="component" xsi:type="string">Magento_Ui/js/form/components/group</item>
+            </item>
+        </argument>
+    </multiline>
     <!-- Form elements -->
 
     <!-- Form element data types -->
diff --git a/app/code/Magento/Ui/view/base/web/js/block-loader.js b/app/code/Magento/Ui/view/base/web/js/block-loader.js
new file mode 100644
index 0000000000000000000000000000000000000000..e3cb1b422bb31f070307e26f8f037cb3753f4e99
--- /dev/null
+++ b/app/code/Magento/Ui/view/base/web/js/block-loader.js
@@ -0,0 +1,90 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+    'ko',
+    'jquery',
+    'Magento_Ui/js/lib/loader',
+    'mage/template'
+], function (ko, $, templateLoader, template) {
+    'use strict';
+
+    var blockLoaderTemplatePath = 'ui/block-loader',
+        blockContentLoadingClass = '_block-content-loading',
+        blockLoader,
+        blockLoaderClass,
+        loaderImageHref;
+
+    templateLoader.loadTemplate(blockLoaderTemplatePath).done(function (blockLoaderTemplate) {
+        blockLoader = template($.trim(blockLoaderTemplate), {
+            loaderImageHref: loaderImageHref
+        });
+        blockLoader = $(blockLoader);
+        blockLoaderClass = '.' + blockLoader.attr('class');
+    });
+
+    /**
+     * Helper function to check if blockContentLoading class should be applied.
+     * @param {Object} element
+     * @returns {Boolean}
+     */
+    function isLoadingClassRequired(element) {
+        var position = element.css('position');
+
+        if (position === 'absolute' || position === 'fixed') {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Add loader to block.
+     * @param {Object} element
+     */
+    function addBlockLoader(element) {
+        element.find(':focus').blur();
+        element.find('input:disabled, select:disabled').addClass('_disabled');
+        element.find('input, select').prop('disabled', true);
+
+        if (isLoadingClassRequired(element)) {
+            element.addClass(blockContentLoadingClass);
+        }
+        element.append(blockLoader.clone());
+    }
+
+    /**
+     * Remove loader from block.
+     * @param {Object} element
+     */
+    function removeBlockLoader(element) {
+        if (!element.has(blockLoaderClass).length) {
+            return;
+        }
+        element.find(blockLoaderClass).remove();
+        element.find('input:not("._disabled"), select:not("._disabled")').prop('disabled', false);
+        element.find('input:disabled, select:disabled').removeClass('_disabled');
+        element.removeClass(blockContentLoadingClass);
+    }
+
+    return function (loaderHref) {
+        loaderImageHref = loaderHref;
+        ko.bindingHandlers.blockLoader = {
+            /**
+             * Process loader for block
+             * @param {String} element
+             * @param {Boolean} displayBlockLoader
+             */
+            update: function (element, displayBlockLoader) {
+                element = $(element);
+
+                if (ko.unwrap(displayBlockLoader())) {
+                    addBlockLoader(element);
+                } else {
+                    removeBlockLoader(element);
+                }
+            }
+        };
+    };
+});
diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/group.js b/app/code/Magento/Ui/view/base/web/js/form/components/group.js
index aeb0ce9db858cc9f7a36dd1c7b41684476830e6b..1e0ff9ac97a3259adc764509c57b49bd379c3a0f 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/components/group.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/components/group.js
@@ -35,7 +35,10 @@ define([
          */
         initObservable: function () {
             this._super()
-                .observe('visible required');
+                .observe('visible')
+                .observe({
+                    required: !!+this.required
+                });
 
             return this;
         },
diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal.js b/app/code/Magento/Ui/view/base/web/js/modal/modal.js
index 1b9c0c18860a88b2faccfa8490a5c243746ce6b5..aa415e7aeacebaf5d9ffed007bdc3cbe5a59e9fa 100644
--- a/app/code/Magento/Ui/view/base/web/js/modal/modal.js
+++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js
@@ -8,9 +8,10 @@ define([
     "mage/template",
     "text!ui/template/modal/modal-popup.html",
     "text!ui/template/modal/modal-slide.html",
+    "text!ui/template/modal/modal-custom.html",
     "jquery/ui",
     "mage/translate"
-], function($, _, template, popupTpl, slideTpl){
+], function($, _, template, popupTpl, slideTpl, customTpl){
     "use strict";
 
     /**
@@ -23,6 +24,7 @@ define([
             modalClass: '',
             popupTpl: popupTpl,
             slideTpl: slideTpl,
+            customTpl: customTpl,
             modalVisibleClass: '_show',
             parentModalClass: '_has-modal',
             innerScrollClass: '_inner-scroll',
@@ -36,6 +38,7 @@ define([
             wrapperClass: 'modals-wrapper',
             overlayClass: 'modals-overlay',
             responsiveClass: 'modal-slide',
+            trigger: '',
             modalLeftMargin: 45,
             closeText: $.mage.__('Close'),
             buttons: [{
@@ -56,6 +59,7 @@ define([
             this._createButtons();
 
             this.modal.find(this.options.modalCloseBtn).on('click',  _.bind(this.closeModal, this));
+            $(this.options.trigger).on('click', _.bind(this.toggleModal, this));
             this.element.on('openModal', _.bind(this.openModal, this));
             this.element.on('closeModal', _.bind(this.closeModal, this));
         },
@@ -82,6 +86,13 @@ define([
 
             return elems.filter('.'+this.options.modalVisibleClass).length;
         },
+        toggleModal: function() {
+            if (this.options.isOpen == true) {
+                this.closeModal();
+            } else {
+                this.openModal();
+            }
+        },
         openModal: function() {
             var that = this;
 
diff --git a/app/code/Magento/Ui/view/base/web/templates/block-loader.html b/app/code/Magento/Ui/view/base/web/templates/block-loader.html
new file mode 100644
index 0000000000000000000000000000000000000000..cc98e6a19688cfc7d3e92d4d7c0753075dcd901c
--- /dev/null
+++ b/app/code/Magento/Ui/view/base/web/templates/block-loader.html
@@ -0,0 +1,11 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div data-role="loader" class="loading-mask" style="position: absolute;">
+    <div class="loader">
+        <img src="<%= loaderImageHref %>" alt="Loading..." style="position: absolute;">
+    </div>
+</div>
\ No newline at end of file
diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html
new file mode 100644
index 0000000000000000000000000000000000000000..990630aa02b9c1ee71088b56bd345ed33e4d3a6e
--- /dev/null
+++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html
@@ -0,0 +1,38 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+
+<aside class="modal-<%= data.type %> <%= data.modalClass %>
+       <% if(data.responsive){ %><%= data.responsiveClass %><% } %>
+       <% if(data.innerScroll){ %><%= data.innerScrollClass %><% } %>"
+    data-role="modal"
+    data-type="<%= data.type %>">
+    <div class="modal-inner-wrap">
+        <header class="modal-header">
+            <% if(data.title){ %>
+            <h1 class="modal-title"
+                data-role="title"><%= data.title %></h1>
+            <% } %>
+            <button
+                class="action-close"
+                data-role="closeBtn"
+                type="button">
+                <span><%= data.closeText %></span>
+            </button>
+        </header>
+        <div class="modal-content" data-role="content"></div>
+        <% if(data.buttons.length > 0){ %>
+        <footer class="modal-footer">
+            <% _.each(data.buttons, function(button) { %>
+            <button
+                    class="<%= button.class %>"
+                    type="button"
+                    data-role="action"><span><%= button.text %></span></button>
+            <% }); %>
+        </footer>
+        <% } %>
+    </div>
+</aside>
diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html
index 7c45aefbb35a66ab80274fa4891f31804b246f93..43ac20b2aeb1e26bce6330232755be77e5c4605c 100644
--- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html
+++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html
@@ -13,8 +13,10 @@
     data-type="<%= data.type %>">
     <div class="modal-inner-wrap">
         <header class="modal-header">
+            <% if(data.title){ %>
             <h1 class="modal-title"
                 data-role="title"><%= data.title %></h1>
+            <% } %>
             <button
                 class="action-close"
                 data-role="closeBtn"
@@ -25,6 +27,7 @@
         <div
             class="modal-content"
             data-role="content"></div>
+        <% if(data.buttons.length > 0){ %>
         <footer class="modal-footer">
             <% _.each(data.buttons, function(button) { %>
             <button
@@ -33,5 +36,6 @@
                 data-role="action"><span><%= button.text %></span></button>
             <% }); %>
         </footer>
+        <% } %>
     </div>
 </aside>
diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html
index dbe99544b3e076a5d5fb670caad2ecdd77671437..abffa4573962a7acc129a0f3f0a96c2765240731 100644
--- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html
+++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html
@@ -12,14 +12,17 @@
     data-type="<%= data.type %>">
     <div class="modal-inner-wrap">
         <header class="modal-header">
+            <% if(data.title){ %>
             <h1 class="modal-title"
                 data-role="title"><%= data.title %></h1>
+            <% } %>
             <button
                 class="action-close"
                 data-role="closeBtn"
                 type="button">
                 <span><%= data.closeText %></span>
             </button>
+            <% if(data.buttons.length > 0){ %>
             <div class="page-main-actions">
                 <div class="page-actions">
                     <div class="page-actions-buttons">
@@ -33,6 +36,7 @@
                     </div>
                 </div>
             </div>
+            <% } %>
         </header>
         <div class="modal-content" data-role="content"></div>
     </div>
diff --git a/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js b/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js
deleted file mode 100644
index 4eca983e1f4334cc21901eec3b3a95245956c7d9..0000000000000000000000000000000000000000
--- a/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(['ko'], function(ko) {
-    "use strict";
-    var errors = ko.observableArray([]);
-    return {
-        add: function (error) {
-            var expr = /([%])\w+/g,
-                errorMessage;
-            if (!error.hasOwnProperty('parameters')) {
-                this.clear();
-                errors.push(error.message);
-                return true;
-            }
-            errorMessage = error.message.replace(expr, function(varName) {
-                varName = varName.substr(1);
-                if (error.parameters.hasOwnProperty(varName)) {
-                    return error.parameters[varName];
-                }
-                return error.parameters.shift();
-            });
-            this.clear();
-            errors.push(errorMessage);
-            return true;
-        },
-        remove: function() {
-            errors.shift();
-        },
-        getAll: function () {
-            return errors;
-        },
-        clear: function() {
-            errors.removeAll();
-        }
-    };
-});
diff --git a/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js b/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js
new file mode 100644
index 0000000000000000000000000000000000000000..15da0c25dc7922e8d69a51b5647597c2540c9db0
--- /dev/null
+++ b/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js
@@ -0,0 +1,78 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(['ko'], function (ko) {
+    'use strict';
+
+    var errors = ko.observableArray([]);
+    var success =  ko.observableArray([]);
+
+    return {
+        errors: errors,
+        success: success,
+        /**
+         * Add  message to list.
+         * @param {Object} messageObj
+         * @param {Object} type
+         * @returns {Boolean}
+         */
+        add: function (messageObj, type) {
+            var expr = /([%])\w+/g,
+                message;
+
+            if (!messageObj.hasOwnProperty('parameters')) {
+                this.clear();
+                type.push(messageObj.message);
+
+                return true;
+            }
+            message = messageObj.message.replace(expr, function (varName) {
+                varName = varName.substr(1);
+
+                if (messageObj.parameters.hasOwnProperty(varName)) {
+                    return messageObj.parameters[varName];
+                }
+
+                return messageObj.parameters.shift();
+            });
+            this.clear();
+            errors.push(message);
+
+            return true;
+        },
+        addSuccessMessage: function (message) {
+            return this.add(message, this.success)
+
+        },
+        addErrorMessage: function (message) {
+            return this.add(message, this.errors)
+        },
+        /**
+         * Remove first error message in list
+         */
+        remove: function (type) {
+            type.shift();
+        },
+        /**
+         * Get all error messages
+         * @returns {Object}
+         */
+        getAll: function () {
+            return errors;
+        },
+        /**
+         * Clear error list
+         */
+        clear: function () {
+            errors.removeAll();
+            success.removeAll();
+        },
+        getAllErrors: function () {
+            return errors;
+        },
+        getAllSuccess: function () {
+            return success;
+        }
+    };
+});
diff --git a/app/code/Magento/Ui/view/frontend/web/js/view/errors.js b/app/code/Magento/Ui/view/frontend/web/js/view/errors.js
deleted file mode 100644
index 192a218bb4845cfccbef5d13a1664806bae574c7..0000000000000000000000000000000000000000
--- a/app/code/Magento/Ui/view/frontend/web/js/view/errors.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*global define*/
-define(['uiComponent', '../model/errorlist'], function (Component, errors) {
-    "use strict";
-    return Component.extend({
-        errorList: errors.getAll(),
-        defaults: {
-            template: 'Magento_Ui/errors'
-        }
-    });
-});
diff --git a/app/code/Magento/Ui/view/frontend/web/js/view/messages.js b/app/code/Magento/Ui/view/frontend/web/js/view/messages.js
new file mode 100644
index 0000000000000000000000000000000000000000..02a5a2e6beb0ec893fd22b10c0a360d0984fa2d8
--- /dev/null
+++ b/app/code/Magento/Ui/view/frontend/web/js/view/messages.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(['uiComponent', '../model/messageList'], function (Component, messages) {
+    'use strict';
+
+    return Component.extend({
+        errorList: messages.getAllErrors(),
+        successList: messages.getAllSuccess(),
+
+        defaults: {
+            template: 'Magento_Ui/messages'
+        },
+
+        /**
+         *
+         * @returns {*}
+         */
+        isVisible: function () {
+            return this.errorList().length || this.successList().length;
+        },
+        /**
+         * Remove all errors
+         */
+        removeAll: function () {
+            this.errorList.removeAll();
+            this.successList.removeAll();
+        }
+    });
+});
diff --git a/app/code/Magento/Ui/view/frontend/web/template/errors.html b/app/code/Magento/Ui/view/frontend/web/template/errors.html
deleted file mode 100644
index 15d1bf5d80d2215869aa676d5acd7950a9c9c591..0000000000000000000000000000000000000000
--- a/app/code/Magento/Ui/view/frontend/web/template/errors.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<div class="messages" data-bind="visible: errorList().length">
-    <div class="message message-error error" data-bind="foreach: errorList">
-        <div data-ui-id="checkout-cart-validationmessages-message-error" data-bind="text: $data"></div>
-    </div>
-</div>
\ No newline at end of file
diff --git a/app/code/Magento/Ui/view/frontend/web/template/messages.html b/app/code/Magento/Ui/view/frontend/web/template/messages.html
new file mode 100644
index 0000000000000000000000000000000000000000..d842c4b10ff29428a4427ad00f89a7529ece12ae
--- /dev/null
+++ b/app/code/Magento/Ui/view/frontend/web/template/messages.html
@@ -0,0 +1,18 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<div class="messages" data-bind="visible: isVisible(), click: removeAll">
+    <!-- ko foreach: errorList -->
+    <div class="message message-error error">
+        <div data-ui-id="checkout-cart-validationmessages-message-error" data-bind="text: $data"></div>
+    </div>
+    <!--/ko-->
+    <!-- ko foreach: successList -->
+    <div class="message message-success success">
+        <div data-ui-id="checkout-cart-validationmessages-message-success" data-bind="text: $data"></div>
+    </div>
+    <!--/ko-->
+</div>
\ No newline at end of file
diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html
new file mode 100644
index 0000000000000000000000000000000000000000..b2ef214e944a5e63c14f8b00f6d4297280baa284
--- /dev/null
+++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html
@@ -0,0 +1,13 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+ <div class="field-tooltip toggle">
+    <a class="field-tooltip-action action-help" target="_blank" data-bind="attr: {href: tooltip.link}">
+    </a>
+    <div class="field-tooltip-content">
+        <!-- ko text: tooltip.description --><!-- /ko -->
+    </div>
+</div>
diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html
index 75e6ff74dbe80b383441e20d4eea3dd2014d3743..e35184926cadcfd10f8a83883858be2d6e532761 100644
--- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html
+++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html
@@ -6,6 +6,7 @@
 -->
 <input class="input-text" type="text" data-bind="
     value: value,
+    valueUpdate: 'keyup',
     hasFocus: focused,
     attr: {
         name: inputName,
diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/field.html b/app/code/Magento/Ui/view/frontend/web/templates/form/field.html
index fef8f712455113ecf7aca9f717e58192e7e0b58f..9f746c7e4542408b4e75475866a8d95676308a15 100644
--- a/app/code/Magento/Ui/view/frontend/web/templates/form/field.html
+++ b/app/code/Magento/Ui/view/frontend/web/templates/form/field.html
@@ -12,7 +12,7 @@
         <!-- /ko -->
     </label>
 
-    <div class="control">
+    <div class="control" data-bind="css: {'_with-tooltip': element.tooltip}">
         <!-- ko ifnot: element.hasAddons() -->
             <!-- ko template: element.elementTmpl --><!-- /ko -->
         <!-- /ko -->
diff --git a/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..50df5c58c00ce7af4c6dc661ad541bcdcad91ad4
--- /dev/null
+++ b/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="step-config" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="shipping-rates-validation" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="ups-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Ups/js/view/shipping-rates-validation</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557
--- /dev/null
+++ b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'postcode': {
+                        'required': true
+                    },
+                    'country_id': {
+                        'required': true
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1
--- /dev/null
+++ b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        './shipping-rates-validation-rules',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var self = this;
+                this.validationErrors = [];
+                $.each(validationRules.getRules(), function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+                return !Boolean(this.validationErrors.length);
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js
new file mode 100644
index 0000000000000000000000000000000000000000..42d6e855218d13fa54bad60bd238a4469bb1a565
--- /dev/null
+++ b/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../model/shipping-rates-validator',
+        '../model/shipping-rates-validation-rules'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        upsShippingRatesValidator,
+        upsShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('ups', upsShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('ups', upsShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ed6d123a6e4dfc7c7f443a2339a0f5cbfbac3d2f
--- /dev/null
+++ b/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <body>
+        <referenceBlock name="checkout.root">
+            <arguments>
+                <argument name="jsLayout" xsi:type="array">
+                    <item name="components" xsi:type="array">
+                        <item name="checkout" xsi:type="array">
+                            <item name="children" xsi:type="array">
+                                <item name="steps" xsi:type="array">
+                                    <item name="children" xsi:type="array">
+                                        <item name="shipping-step" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="step-config" xsi:type="array">
+                                                    <item name="children" xsi:type="array">
+                                                        <item name="shipping-rates-validation" xsi:type="array">
+                                                            <item name="children" xsi:type="array">
+                                                                <item name="usps-rates-validation" xsi:type="array">
+                                                                    <item name="component" xsi:type="string">Magento_Usps/js/view/shipping-rates-validation</item>
+                                                                </item>
+                                                            </item>
+                                                        </item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                    </item>
+                                </item>
+                            </item>
+                        </item>
+                    </item>
+                </argument>
+            </arguments>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..85ec105f7e4b3ab6886fa28534b0530b44e1a61c
--- /dev/null
+++ b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [],
+    function () {
+        "use strict";
+        return {
+            getRules: function() {
+                return {
+                    'country_id': {
+                        'required': true
+                    },
+                    'postcode': {
+                        'required': false
+                    }
+                };
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js
new file mode 100644
index 0000000000000000000000000000000000000000..b897eb4e83ccde4647aca4f656c4bbc67b261512
--- /dev/null
+++ b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js
@@ -0,0 +1,40 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*global define*/
+define(
+    [
+        'jquery',
+        'mageUtils',
+        './shipping-rates-validation-rules',
+        'mage/translate'
+    ],
+    function ($, utils, validationRules, $t) {
+        "use strict";
+        var checkoutConfig = window.checkoutConfig;
+
+        return {
+            validationErrors: [],
+            validate: function(address) {
+                var rules = validationRules.getRules(),
+                    self = this;
+
+                $.each(rules, function(field, rule) {
+                    if (rule.required && utils.isEmpty(address[field])) {
+                        var message = $t('Field ') + field + $t(' is required.');
+                        self.validationErrors.push(message);
+                    }
+                });
+
+                if (!Boolean(this.validationErrors.length)) {
+                    if (address.country_id == checkoutConfig.originCountryCode) {
+                        return !utils.isEmpty(address.postcode);
+                    }
+                    return true;
+                }
+                return false;
+            }
+        };
+    }
+);
diff --git a/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js
new file mode 100644
index 0000000000000000000000000000000000000000..c47818efc2ede4a7aef4c48fcf7a4d58c5c712c9
--- /dev/null
+++ b/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'uiComponent',
+        'Magento_Checkout/js/model/shipping-rates-validator',
+        'Magento_Checkout/js/model/shipping-rates-validation-rules',
+        '../model/shipping-rates-validator',
+        '../model/shipping-rates-validation-rules'
+    ],
+    function (
+        Component,
+        defaultShippingRatesValidator,
+        defaultShippingRatesValidationRules,
+        uspsShippingRatesValidator,
+        uspsShippingRatesValidationRules
+    ) {
+        "use strict";
+        defaultShippingRatesValidator.registerValidator('usps', uspsShippingRatesValidator);
+        defaultShippingRatesValidationRules.registerRules('usps', uspsShippingRatesValidationRules);
+        return Component;
+    }
+);
diff --git a/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php b/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..772907c4b11381c761808f215afbaaba8fa9ae78
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php
@@ -0,0 +1,190 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Weee\Test\Unit\Model\Total\Observer\Webapi;
+
+class ItemTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $weeeHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeMock;
+
+    /**
+     * @var \Magento\Weee\Model\Total\Observer\Webapi\Item
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->weeeHelperMock = $this->getMock('Magento\Weee\Helper\Data', [], [], '', false);
+        $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface');
+        $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
+
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock));
+
+        $this->model = new \Magento\Weee\Model\Total\Observer\Webapi\Item(
+            $this->weeeHelperMock,
+            $this->storeManagerMock
+        );
+    }
+
+    /**
+     * @dataProvider processTaxDataDataProvider
+     *
+     * @param bool $helperIsEnabled
+     * @param int $weeeTaxInclTax
+     * @param int $rowTotal
+     * @param bool $weeeTaxRowApplied
+     * @param int $rowTotalInclTax
+     * @param int $rowWeeeInclTax
+     * @param int $weeeTaxApplied
+     * @param int $weeeTaxAppliedAmount
+     * @param bool $includeWeeeFlag
+     * @param int $priceIncTax
+     * @param int $calculationPrice
+     * @param int $expectedRowTotal
+     * @param int $expectedRowInclTax
+     * @param int $expectedPrice
+     * @param int $expectedPriceInclTax
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function testProcessTaxData(
+        $helperIsEnabled,
+        $weeeTaxInclTax,
+        $rowTotal,
+        $weeeTaxRowApplied,
+        $rowTotalInclTax,
+        $rowWeeeInclTax,
+        $weeeTaxApplied,
+        $weeeTaxAppliedAmount,
+        $includeWeeeFlag,
+        $priceIncTax,
+        $calculationPrice,
+        $expectedRowTotal,
+        $expectedRowInclTax,
+        $expectedPrice,
+        $expectedPriceInclTax
+    ) {
+        $observerMock = $this->getMock('Magento\Framework\Object', ['getEvent'], [], '', false);
+        $eventMock = $this->getMock('Magento\Framework\Event', ['getItem'], [], '', false);
+        $itemMock = $this->getMock(
+            'Magento\Quote\Model\Quote\Item',
+            [
+                'setRowTotal', 'setRowTotalInclTax', 'setPrice', 'setPriceInclTax',
+                'getPriceInclTax', 'getCalculationPrice', 'getRowTotal', 'getRowTotalInclTax', 'getWeeeTaxApplied',
+                'getWeeeTaxAppliedRowAmount', 'getWeeeTaxAppliedAmount'
+            ],
+            [],
+            '',
+            false
+        );
+
+        $eventMock->expects($this->once())->method('getItem')->will($this->returnValue($itemMock));
+        $observerMock->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock));
+
+        $this->weeeHelperMock->expects($this->any())->method('isEnabled')
+            ->will($this->returnValue($helperIsEnabled));
+        $this->weeeHelperMock->expects($this->any())->method('getWeeeTaxInclTax')
+            ->with($itemMock)->will($this->returnValue($weeeTaxInclTax));
+        $this->weeeHelperMock->expects($this->any())->method('getRowWeeeTaxInclTax')
+            ->will($this->returnValue($rowWeeeInclTax));
+        $this->weeeHelperMock->expects($this->any())->method('typeOfDisplay')
+            ->will($this->returnValue($includeWeeeFlag));
+
+        $weeeTaxApplied = serialize($weeeTaxApplied);
+        $itemMock->expects($this->any())->method('getPriceInclTax')->will($this->returnValue($priceIncTax));
+        $itemMock->expects($this->any())->method('getCalculationPrice')->will($this->returnValue($calculationPrice));
+        $itemMock->expects($this->any())->method('getRowTotal')->will($this->returnValue($rowTotal));
+        $itemMock->expects($this->any())->method('getRowTotalInclTax')->will($this->returnValue($rowTotalInclTax));
+        $itemMock->expects($this->any())->method('getWeeeTaxApplied')->will($this->returnValue($weeeTaxApplied));
+        $itemMock->expects($this->any())->method('getWeeeTaxAppliedAmount')
+            ->will($this->returnValue($weeeTaxAppliedAmount));
+        $itemMock->expects($this->any())->method('getWeeeTaxAppliedRowAmount')
+            ->will($this->returnValue($weeeTaxRowApplied));
+
+        $itemMock->expects($this->once())->method('setRowTotal')->with($expectedRowTotal)
+            ->will($this->returnSelf());
+        $itemMock->expects($this->once())->method('setRowTotalInclTax')->with($expectedRowInclTax)
+            ->will($this->returnSelf());
+        $itemMock->expects($this->once())->method('setPrice')->with($expectedPrice)
+            ->will($this->returnSelf());
+        $itemMock->expects($this->once())->method('setPriceInclTax')->with($expectedPriceInclTax)
+            ->will($this->returnSelf());
+
+        $this->model->processTaxData($observerMock);
+    }
+
+    /**
+     * @return array
+     */
+    public function processTaxDataDataProvider()
+    {
+        return [
+            [
+                'helperIsEnabled' => false,
+                'weeeTaxInclTax' => 10,
+                'rowTotal' => 17,
+                'weeeTaxRowApplied' => 3,
+                'rowTotalInclTax' => 11,
+                'rowWeeeInclTax' => 14,
+                'weeeTaxApplied' => 4,
+                'weeeTaxAppliedAmount' => 4,
+                'includeWeeeFlag' => false,
+                'priceIncTax' => 5,
+                'calculationPrice' => 12,
+                'expectedRowTotal' => 17,
+                'expectedRowInclTax' => 11,
+                'expectedPrice' => 12,
+                'expectedPriceInclTax' => 5
+            ],
+            [
+                'helperIsEnabled' => true,
+                'weeeTaxInclTax' => 10,
+                'rowTotal' => 17,
+                'weeeTaxRowApplied' => 3,
+                'rowTotalInclTax' => 11,
+                'rowWeeeInclTax' => 14,
+                'weeeTaxApplied' => 4,
+                'weeeTaxAppliedAmount' => 4,
+                'includeWeeeFlag' => false,
+                'priceIncTax' => 5,
+                'calculationPrice' => 12,
+                'expectedRowTotal' => 17,
+                'expectedRowInclTax' => 11,
+                'expectedPrice' => 12,
+                'expectedPriceInclTax' => 5
+            ],
+            [
+                'helperIsEnabled' => true,
+                'weeeTaxInclTax' => 10,
+                'rowTotal' => 17,
+                'weeeTaxRowApplied' => 3,
+                'rowTotalInclTax' => 11,
+                'rowWeeeInclTax' => 14,
+                'weeeTaxApplied' => 4,
+                'weeeTaxAppliedAmount' => 4,
+                'includeWeeeFlag' => true,
+                'priceIncTax' => 5,
+                'calculationPrice' => 12,
+                'expectedRowTotal' => 20,
+                'expectedRowInclTax' => 25,
+                'expectedPrice' => 16,
+                'expectedPriceInclTax' => 15
+            ]
+        ];
+    }
+}
diff --git a/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php b/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..548ad82139b34802fadc77310423804350e08924
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Weee\Test\Unit\Model;
+
+class WeeeConfigProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $weeeHelperMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $weeeConfigMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeMock;
+
+    /**
+     * @var \Magento\Weee\Model\WeeeConfigProvider
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->weeeHelperMock = $this->getMock('Magento\Weee\Helper\Data', [], [], '', false);
+        $this->weeeConfigMock = $this->getMock('Magento\Weee\Model\Config', [], [], '', false);
+        $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface');
+        $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
+
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock));
+
+        $this->model = new \Magento\Weee\Model\WeeeConfigProvider(
+            $this->weeeHelperMock,
+            $this->storeManagerMock,
+            $this->weeeConfigMock
+        );
+    }
+
+    /**
+     * @dataProvider getConfigDataProvider
+     * @param array $expectedResult
+     * @param bool $weeeHelperEnabled
+     * @param bool $displayWeeeDetails
+     * @param bool $weeeConfigEnabled
+     * @param bool $includeInSubtotal
+     */
+    public function testGetConfig(
+        $expectedResult,
+        $weeeHelperEnabled,
+        $displayWeeeDetails,
+        $weeeConfigEnabled,
+        $includeInSubtotal
+    ) {
+        $storeId = 1;
+        $this->storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId));
+        $this->weeeHelperMock->expects($this->any())->method('isEnabled')->with($storeId)
+            ->will($this->returnValue($weeeHelperEnabled));
+        $this->weeeHelperMock->expects($this->any())->method('typeOfDisplay')
+            ->will($this->returnValue($displayWeeeDetails));
+
+        $this->weeeConfigMock->expects($this->any())->method('isEnabled')
+            ->will($this->returnValue($weeeConfigEnabled));
+        $this->weeeConfigMock->expects($this->any())->method('includeInSubtotal')
+            ->will($this->returnValue($includeInSubtotal));
+
+        $this->assertEquals($expectedResult, $this->model->getConfig());
+    }
+
+    /**
+     * @return array
+     */
+    public function getConfigDataProvider()
+    {
+        return [
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => true,
+                    'isWeeeEnabled' => false,
+                    'isIncludedInSubtotal' => true,
+                    'getIncludeWeeeFlag' => true,
+                ],
+                'weeeHelperEnabled' => false,
+                'displayWeeeDetails' => true,
+                'weeeConfigEnabled' => true,
+                'includeInSubtotal' => true,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => true,
+                    'isDisplayFinalPrice' => true,
+                    'isWeeeEnabled' => true,
+                    'isIncludedInSubtotal' => true,
+                    'getIncludeWeeeFlag' => true,
+                ],
+                'weeeHelperEnabled' => true,
+                'displayWeeeDetails' => true,
+                'weeeConfigEnabled' => true,
+                'includeInSubtotal' => true,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => false,
+                    'isWeeeEnabled' => true,
+                    'isIncludedInSubtotal' => true,
+                    'getIncludeWeeeFlag' => false,
+                ],
+                'weeeHelperEnabled' => true,
+                'displayWeeeDetails' => false,
+                'weeeConfigEnabled' => true,
+                'includeInSubtotal' => true,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => false,
+                    'isWeeeEnabled' => false,
+                    'isIncludedInSubtotal' => true,
+                    'getIncludeWeeeFlag' => false,
+                ],
+                'weeeHelperEnabled' => false,
+                'displayWeeeDetails' => false,
+                'weeeConfigEnabled' => true,
+                'includeInSubtotal' => true,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => false,
+                    'isWeeeEnabled' => false,
+                    'isIncludedInSubtotal' => false,
+                    'getIncludeWeeeFlag' => false,
+                ],
+                'weeeHelperEnabled' => false,
+                'displayWeeeDetails' => false,
+                'weeeConfigEnabled' => false,
+                'includeInSubtotal' => true,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => false,
+                    'isWeeeEnabled' => false,
+                    'isIncludedInSubtotal' => false,
+                    'getIncludeWeeeFlag' => false,
+                ],
+                'weeeHelperEnabled' => false,
+                'displayWeeeDetails' => false,
+                'weeeConfigEnabled' => true,
+                'includeInSubtotal' => false,
+            ],
+            [
+                'expectedResult' => [
+                    'isDisplayPriceWithWeeeDetails' => false,
+                    'isDisplayFinalPrice' => false,
+                    'isWeeeEnabled' => false,
+                    'isIncludedInSubtotal' => false,
+                    'getIncludeWeeeFlag' => false,
+                ],
+                'weeeHelperEnabled' => false,
+                'displayWeeeDetails' => false,
+                'weeeConfigEnabled' => false,
+                'includeInSubtotal' => false,
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml
index e5aa37b3c77ed809a449fa828489f38808d2d3fa..6e3439d0775862400bec88a4cf5885f4005358e5 100644
--- a/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml
@@ -5,6 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
+<!-- TODO remove this file as soon as enhanced checkout is implemented -->
 <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>
         <referenceBlock name="checkout.root">
@@ -13,50 +14,36 @@
                     <item name="components" xsi:type="array">
                         <item name="checkout" xsi:type="array">
                             <item name="children" xsi:type="array">
-                                <item name="steps" xsi:type="array">
+                                <item name="summary" xsi:type="array">
                                     <item name="children" xsi:type="array">
-                                        <item name="review" xsi:type="array">
+                                        <item name="totals" xsi:type="array">
                                             <item name="children" xsi:type="array">
-                                                <item name="columns" xsi:type="array">
+                                                <item name="weee" xsi:type="array">
+                                                    <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/summary/weee</item>
+                                                    <item name="config" xsi:type="array">
+                                                        <item name="title" xsi:type="string">FPT</item>
+                                                    </item>
+                                                </item>
+                                            </item>
+                                        </item>
+                                        <item name="cart_items" xsi:type="array">
+                                            <item name="children" xsi:type="array">
+                                                <item name="details" xsi:type="array">
                                                     <item name="children" xsi:type="array">
-                                                        <item name="price" xsi:type="array">
-                                                            <item name="children" xsi:type="array">
-                                                                <item name="unit_incl_tax" xsi:type="array">
-                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/unit_incl_tax</item>
-                                                                    <item name="displayArea" xsi:type="string">unit_incl_tax</item>
-                                                                </item>
-                                                                <item name="unit_excl_tax" xsi:type="array">
-                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/unit_excl_tax</item>
-                                                                    <item name="displayArea" xsi:type="string">unit_excl_tax</item>
-                                                                </item>
-                                                            </item>
-                                                        </item>
                                                         <item name="subtotal" xsi:type="array">
                                                             <item name="children" xsi:type="array">
-                                                                <item name="row_incl_tax" xsi:type="array">
-                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/row_incl_tax</item>
-                                                                    <item name="displayArea" xsi:type="string">row_incl_tax</item>
+                                                                <item name="weee_row_incl_tax" xsi:type="array">
+                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/summary/item/price/row_incl_tax</item>
+                                                                <item name="displayArea" xsi:type="string">row_incl_tax</item>
                                                                 </item>
-                                                                <item name="row_excl_tax" xsi:type="array">
-                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/row_excl_tax</item>
+                                                                <item name="weee_row_excl_tax" xsi:type="array">
+                                                                    <item name="component"  xsi:type="string">Magento_Weee/js/view/checkout/summary/item/price/row_excl_tax</item>
                                                                     <item name="displayArea" xsi:type="string">row_excl_tax</item>
                                                                 </item>
                                                             </item>
                                                         </item>
                                                     </item>
                                                 </item>
-                                                <item name="totals" xsi:type="array">
-                                                    <item name="children" xsi:type="array">
-                                                        <item name="before_grandtotal" xsi:type="array">
-                                                            <item name="children" xsi:type="array">
-                                                                <item name="weee_total" xsi:type="array">
-                                                                    <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/weee_total</item>
-                                                                </item>
-                                                            </item>
-                                                        </item>
-                                                    </item>
-                                                </item>
-
                                             </item>
                                         </item>
                                     </item>
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js
deleted file mode 100644
index 484b00bacb94409548202088b0d36b5dce9c113c..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'Magento_Weee/js/view/checkout/review/item/price/weee'
-    ],
-    function (weee) {
-        "use strict";
-        return weee.extend({
-            defaults: {
-                template: 'Magento_Weee/checkout/review/item/price/unit_excl_tax'
-            },
-
-            getFinalUnitDisplayPriceExclTax: function(item) {
-                var unitExclTax = parseFloat(item.price);
-                if(!window.checkoutConfig.getIncludeWeeeFlag) {
-                    return unitExclTax + parseFloat(item.weee_tax_applied_amount);
-                }
-                return unitExclTax;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js
deleted file mode 100644
index d6e03c37b5e1a9b7c6db4ef86ebd2bb67736a1ce..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'Magento_Weee/js/view/checkout/review/item/price/weee'
-    ],
-    function (weee) {
-        "use strict";
-        return weee.extend({
-            defaults: {
-                template: 'Magento_Weee/checkout/review/item/price/unit_incl_tax'
-            },
-            getFinalUnitDisplayPriceInclTax: function(item) {
-                var unitInclTax = parseFloat(item.price_incl_tax);
-                if(!window.checkoutConfig.getIncludeWeeeFlag) {
-                    return unitInclTax + this.getWeeeTaxInclTax(item);
-                }
-                return unitInclTax;
-            },
-            getWeeeTaxInclTax: function(item) {
-                var weeeTaxAppliedAmounts = JSON.parse(item.weee_tax_applied);
-                var totalWeeeTaxIncTaxApplied = 0;
-                weeeTaxAppliedAmounts.forEach(function (weeeTaxAppliedAmount) {
-                    totalWeeeTaxIncTaxApplied+=parseFloat(Math.max(weeeTaxAppliedAmount.amount_incl_tax, 0));
-                });
-                return totalWeeeTaxIncTaxApplied;
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js
deleted file mode 100644
index 41aec2c8475928ad094bd69f433f7f12fe689020..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
-    [
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
-    ],
-    function (Component,quote, priceUtils) {
-        "use strict";
-        return Component.extend({
-            defaults: {
-                colspan: 3,
-                displayArea: 'before_grandtotal',
-                title: 'FPT',
-                template: 'Magento_Weee/checkout/review/weee_total'
-            },
-            isIncludedInSubtotal: window.checkoutConfig.isIncludedInSubtotal,
-            totals: quote.getTotals(),
-            getColspan: function() {
-                return this.colspan;
-            },
-            getTitle: function() {
-                return this.title;
-            },
-            getPureValue: function() {
-                var items = quote.getItems();
-                var sum = 0;
-                for (var i = 0; i < items.length; i++) {
-                    sum += parseFloat(items[i].weee_tax_applied_row_amount);
-                }
-                return sum;
-            },
-            getValue: function() {
-                var items = quote.getItems();
-                var sum = 0;
-                for (var i = 0; i < items.length; i++) {
-                    sum += parseFloat(items[i].weee_tax_applied_row_amount);
-                }
-                return priceUtils.formatPrice(sum, quote.getPriceFormat());
-            }
-        });
-    }
-);
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js
similarity index 81%
rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js
rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js
index 000d08a5ca07a481989b64f76aa1376ec9cedac8..07c7f94305e991453c0eeb7d8d51550fd94db966 100644
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js
+++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js
@@ -6,13 +6,13 @@
 /*global define*/
 define(
     [
-        'Magento_Weee/js/view/checkout/review/item/price/weee'
+        'Magento_Weee/js/view/checkout/summary/item/price/weee'
     ],
     function (weee) {
         "use strict";
         return weee.extend({
             defaults: {
-                template: 'Magento_Weee/checkout/review/item/price/row_excl_tax'
+                template: 'Magento_Weee/checkout/summary/item/price/row_excl_tax'
             },
 
             getFinalRowDisplayPriceExclTax: function(item) {
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js
similarity index 88%
rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js
rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js
index 6fc8b67643282d0a8bea4cb700baa37b56dbdff4..15aec47fd0f36c377a513757c4f207d05bd71ed0 100644
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js
+++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js
@@ -6,13 +6,13 @@
 /*global define*/
 define(
     [
-        'Magento_Weee/js/view/checkout/review/item/price/weee'
+        'Magento_Weee/js/view/checkout/summary/item/price/weee'
     ],
     function (weee) {
         "use strict";
         return weee.extend({
             defaults: {
-                template: 'Magento_Weee/checkout/review/item/price/row_incl_tax',
+                template: 'Magento_Weee/checkout/summary/item/price/row_incl_tax',
                 displayArea: 'row_incl_tax'
             },
             getFinalRowDisplayPriceInclTax: function(item) {
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js
similarity index 77%
rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js
rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js
index f6c146aa688fb67e68d3d82cf383ec3726605ea9..919504bd6270e066a0caa6aacf47506e69ec4e9b 100644
--- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js
+++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js
@@ -6,11 +6,10 @@
 /*global define*/
 define(
     [
-        'uiComponent',
-        'Magento_Checkout/js/model/quote',
-        'Magento_Catalog/js/price-utils'
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote'
     ],
-    function (Component,quote, priceUtils) {
+    function (Component,quote) {
         "use strict";
         return Component.extend({
 
@@ -26,9 +25,6 @@ define(
                 }
                 return window.checkoutConfig.isDisplayFinalPrice;
             },
-            getFormattedPrice: function (price) {
-                return priceUtils.formatPrice(price, quote.getPriceFormat());
-            },
             getWeeeTaxApplied: function(item) {
                 if (item.weee_tax_applied) {
                     return JSON.parse(item.weee_tax_applied)
diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js
new file mode 100644
index 0000000000000000000000000000000000000000..22209e41d2028a98c61b8b3876345ff5e1d33f4b
--- /dev/null
+++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+    [
+        'Magento_Checkout/js/view/summary/abstract-total',
+        'Magento_Checkout/js/model/quote',
+        'Magento_Checkout/js/model/totals',
+        'Magento_Catalog/js/price-utils'
+    ],
+    function (Component,quote, totals) {
+        "use strict";
+        return Component.extend({
+            defaults: {
+                template: 'Magento_Weee/checkout/summary/weee'
+            },
+            isIncludedInSubtotal: window.checkoutConfig.isIncludedInSubtotal,
+            totals: totals.totals,
+            getValue: function() {
+                return this.getFormattedPrice(this.totals()['weee_tax_applied_amount']);
+            },
+            isDisplayed: function() {
+                return this.isFullMode() && this.isIncludedInSubtotal &&
+                    this.totals()['weee_tax_applied_amount'] > 0;
+            }
+        });
+    }
+);
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html
deleted file mode 100644
index bfaa8c3f176722b4e50b1c0e7ff9f0bff45410af..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+item.item_id}}">
-        <span class="price" data-bind="text: getFormattedPrice(item.row_total_incl_tax)"></span>
-    </span>
-<!-- /ko -->
-<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.row_total_incl_tax)"></span></span>
-<!-- /ko -->
-
-<!--ko if: getWeeeTaxApplied(item).length > 0-->
-<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item))-->
-<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + item.item_id}" style="display: none;"></span>
-<!-- /ko-->
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item))-->
-<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + item.item_id}" style="display: none;">
-         <!-- ko foreach: getWeeeTaxApplied(item)-->
-            <span class="weee" data-bind="attr:{'data-label':title}">
-                <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount_incl_tax)"></span>
-            </span>
-         <!-- /ko-->
-        </span>
-<!-- /ko-->
-
-<!-- ko if: isDisplayFinalPrice(item)-->
-        <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+item.item_id}}">
-            <span class="weee" data-bind="attr: {'data-label':$t('Total Incl. Tax')}">
-                <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceInclTax(item))"></span>
-            </span>
-        </span>
-<!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html
deleted file mode 100644
index eb34f588887cef129456b0c537b5dffc9260bb40..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-tax-total" data-bind="mageInit:{taxToggle: {itemTaxId : '#eunit-item-tax-details' + item.item_id}}">
-        <span class="price" data-bind="text: getFormattedPrice(item.price)"></span>
-    </span>
-<!-- /ko -->
-<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.price)"></span></span>
-<!-- /ko -->
-
-
-<!--ko if:  (getWeeeTaxApplied(item).length > 0)-->
-    <!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item))-->
-        <span class="cart-tax-info" data-bind ="attr: {'id': 'eunit-item-tax-details' + item.item_id}" style="display: none;"></span>
-    <!-- /ko-->
-    <!-- ko if:  (isDisplayPriceWithWeeeDetails(item))-->
-        <span class="cart-tax-info" data-bind ="attr: {'id': 'eunit-item-tax-details' + item.item_id}" style="display: none;">
-             <!-- ko foreach: getWeeeTaxApplied(item)-->
-                <span class="weee" data-bind="attr:{'data-label':title}">
-                    <span class="price" data-bind="text: $parent.getFormattedPrice(amount)"></span>
-                </span>
-            <!-- /ko-->
-            </span>
-    <!-- /ko-->
-
-
-    <!-- ko if: isDisplayFinalPrice(item)-->
-        <span class="cart-tax-total" data-bind="mageInit:{taxToggle: {itemTaxId : '#eunit-item-tax-details' + item.item_id}}">
-            <span class="weee" data-bind="attr: {'data-label':$t('Total')}">
-                <span class="price" data-bind="text: getFormattedPrice(getFinalUnitDisplayPriceExclTax(item))"></span>
-            </span>
-        </span>
-    <!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html
deleted file mode 100644
index 1a67282073225531a6137bd83361a08d60c2287e..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#unit-item-tax-details'+item.item_id}}">
-        <span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span>
-    </span>
-<!-- /ko -->
-<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span>
-<!-- /ko -->
-
-<!--ko if:  (getWeeeTaxApplied(item).length > 0)-->
-    <!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item))-->
-        <span class="cart-tax-info" data-bind ="attr: {'id': 'unit-item-tax-details' + item.item_id}" style="display: none;"></span>
-    <!-- /ko-->
-    <!-- ko if:  (isDisplayPriceWithWeeeDetails(item))-->
-        <span class="cart-tax-info" data-bind ="attr: {'id': 'unit-item-tax-details' + item.item_id}" style="display: none;">
-            <!-- ko foreach: getWeeeTaxApplied(item)-->
-                <span class="weee" data-bind="attr:{'data-label':title}">
-                    <span class="price" data-bind="text: $parent.getFormattedPrice(amount_incl_tax)"></span>
-                </span>
-            <!-- /ko-->
-        </span>
-    <!-- /ko-->
-
-    <!-- ko if: isDisplayFinalPrice(item)-->
-        <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#unit-item-tax-details'+item.item_id}}">
-            <span class="weee"  data-bind="attr: {'data-label':$t('Total Incl. Tax')}">
-                <span class="price" data-bind="text: getFormattedPrice(getFinalUnitDisplayPriceInclTax(item))"></span>
-            </span>
-        </span>
-    <!-- /ko -->
-<!-- /ko -->
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html
deleted file mode 100644
index 3e9b25d84db8239da763e6bc4d740bcd6dc947f1..0000000000000000000000000000000000000000
--- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!--
-/**
-* Copyright © 2015 Magento. All rights reserved.
-* See COPYING.txt for license details.
-*/
--->
-<!-- ko if: isIncludedInSubtotal && getPureValue() > 0 -->
-<tr class="totals">
-    <th data-bind="text: getTitle(), attr: {'colspan': getColspan()}" class="mark" scope="row"></th>
-    <td class="amount" data-bind="attr: {'data-th': $t(getTitle()) }">
-        <span data-bind="text: getValue()"></span>
-    </td>
-</tr>
-<!-- /ko -->
\ No newline at end of file
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html
similarity index 51%
rename from app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html
rename to app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html
index c1a8590e1fe157967c7490e497ba072389d45399..39e2bfa7815e8d8d5658ae91b0838982ce62636b 100644
--- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html
+++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html
@@ -4,22 +4,22 @@
  * See COPYING.txt for license details.
  */
 -->
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+item.item_id}}">
-        <span class="price" data-bind="text: getFormattedPrice(item.row_total)"></span>
+<!-- ko if:  (isDisplayPriceWithWeeeDetails($parents[2])) -->
+    <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+$parents[2].item_id}}">
+        <span class="price" data-bind="text: getFormattedPrice($parents[2].row_total)"></span>
     </span>
 <!-- /ko -->
-<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) -->
-    <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.row_total)"></span></span>
+<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2])) -->
+    <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice($parents[2].row_total)"></span></span>
 <!-- /ko -->
 
-<!--ko if:  (getWeeeTaxApplied(item).length > 0)-->
-<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails(item))-->
-<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + item.item_id}" style="display: none;"></span>
+<!--ko if:  (getWeeeTaxApplied($parents[2]).length > 0)-->
+<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails($parents[2]))-->
+<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"></span>
 <!-- /ko-->
-<!-- ko if:  (isDisplayPriceWithWeeeDetails(item))-->
-<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + item.item_id}" style="display: none;">
-         <!-- ko foreach: getWeeeTaxApplied(item)-->
+<!-- ko if:  (isDisplayPriceWithWeeeDetails($parents[2]))-->
+<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + $parents[2].item_id}" style="display: none;">
+         <!-- ko foreach: getWeeeTaxApplied($parents[2])-->
             <span class="weee" data-bind="attr:{'data-label':title}">
                 <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount)"></span>
             </span>
@@ -27,10 +27,10 @@
         </span>
 <!-- /ko-->
 
-<!-- ko if: isDisplayFinalPrice(item)-->
-        <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+item.item_id}}">
+<!-- ko if: isDisplayFinalPrice($parents[2])-->
+        <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+$parents[2].item_id}}">
             <span class="weee" data-bind="attr: {'data-label':$t('Total')}">
-                <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceExclTax(item))">
+                <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceExclTax($parents[2]))">
 
                 </span>
             </span>
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html
new file mode 100644
index 0000000000000000000000000000000000000000..562bd3293cf960a41046ebb132d3258c8e5a1651
--- /dev/null
+++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html
@@ -0,0 +1,37 @@
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<!-- ko if:  (isDisplayPriceWithWeeeDetails($parents[2])) -->
+    <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+$parents[2].item_id}}">
+        <span class="price" data-bind="text: getFormattedPrice($parents[2].row_total_incl_tax)"></span>
+    </span>
+<!-- /ko -->
+<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2])) -->
+<span class="cart-price"><span class="price" data-bind="text: getFormattedPrice($parents[2].row_total_incl_tax)"></span></span>
+<!-- /ko -->
+
+<!--ko if: getWeeeTaxApplied($parents[2]).length > 0-->
+<!-- ko ifnot:  (isDisplayPriceWithWeeeDetails($parents[2]))-->
+<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"></span>
+<!-- /ko-->
+<!-- ko if:  (isDisplayPriceWithWeeeDetails($parents[2]))-->
+<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + $parents[2].item_id}" style="display: none;">
+         <!-- ko foreach: getWeeeTaxApplied($parents[2])-->
+            <span class="weee" data-bind="attr:{'data-label':title}">
+                <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount_incl_tax)"></span>
+            </span>
+         <!-- /ko-->
+        </span>
+<!-- /ko-->
+
+<!-- ko if: isDisplayFinalPrice($parents[2])-->
+<span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+$parents[2].item_id}}">
+            <span class="weee" data-bind="attr: {'data-label':$t('Total incl. tax')}">
+                <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceInclTax($parents[2]))"></span>
+            </span>
+        </span>
+<!-- /ko -->
+<!-- /ko -->
diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html
new file mode 100644
index 0000000000000000000000000000000000000000..7a3696a829ef86c82efc2a53342c25cadbdb451e
--- /dev/null
+++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html
@@ -0,0 +1,14 @@
+<!--
+/**
+* Copyright © 2015 Magento. All rights reserved.
+* See COPYING.txt for license details.
+*/
+-->
+<!-- ko if: isDisplayed() -->
+<tr class="totals">
+    <th data-bind="text: title" class="mark" scope="row"></th>
+    <td class="amount" data-bind="attr: {'data-th': $t(title) }">
+        <span data-bind="text: getValue()"></span>
+    </td>
+</tr>
+<!-- /ko -->
\ No newline at end of file
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 112f9406bdaf4e664e57478393a6b73409098119..2ed8935a30cf8249df7721e61773a5a955d2d3ad 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
@@ -32,7 +32,8 @@ define([
             this._on(events);
         },
         _updateWishlistData: function(event) {
-            var dataToAdd = {};
+            var dataToAdd = {},
+                isFileUploaded = false;
             if (event.handleObj.selector == this.options.qtyInfo) {
                 this._updateAddToWishlistButton({});
                 event.stopPropagation();
@@ -40,15 +41,22 @@ define([
             }
             var self = this;
             $(event.handleObj.selector).each(function(index, element){
-                if ($(element).attr('type') == 'text') {
+                if ($(element).is('input[type=text]')
+                    || $(element).is('input[type=checkbox]:checked')
+                    || $(element).is('input[type=radio]:checked')
+                    || $('#' + element.id + ' option:selected').length
+                    || $(element).is('textarea')
+                ) {
                     dataToAdd = $.extend({}, dataToAdd, self._getElementData(element));
                     return;
                 }
-                if ($(element).is(':checked') || $(element).find(':checked').length) {
-                    dataToAdd = $.extend({}, dataToAdd, self._getElementData(element));
+                if ($(element).is('input[type=file]') && $(element).val()) {
+                    isFileUploaded = true;
                 }
             });
-
+            if (isFileUploaded) {
+                this.bindFormSubmit();
+            }
             this._updateAddToWishlistButton(dataToAdd);
             event.stopPropagation();
         },
@@ -90,7 +98,9 @@ define([
                     data[elementName + '[' + option + ']'] = option;
                 });
             } else {
-                data[elementName] = elementValue;
+                if (elementValue) {
+                    data[elementName] = elementValue;
+                }
             }
             return data;
         },
@@ -99,6 +109,23 @@ define([
             $.each(dataToRemove, function(key, value) {
                 delete params.data[key];
             });
+        },
+        bindFormSubmit: function() {
+            var self = this;
+            $('[data-action="add-to-wishlist"]').on('click', function(event) {
+                event.stopPropagation();
+                event.preventDefault();
+
+                var element = $('input[type=file]' + self.options.customOptionsInfo),
+                    params = $(event.currentTarget).data('post'),
+                    form = $(element).closest('form'),
+                    action = params.action;
+                if (params.data.uenc) {
+                    action += 'uenc/' + params.data.uenc;
+                }
+
+                $(form).attr('action', action).submit();
+            });
         }
     });
     
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less
index 8795421c0d241fc95cdaf6a43e597fdd2fb8f13e..85932830410a8ee3ef47bc3eabf105116270a9cc 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less
@@ -5,448 +5,4 @@
 
 @import 'module/_cart.less';
 @import 'module/_minicart.less';
-
-@desktop-form-field-vertical-indent: 29px;
-
-//
-//  Common
-//  _____________________________________________
-
-& when (@media-common = true) {
-
-    //
-    //  One Page Checkout
-    //  ---------------------------------------------
-
-    .opc-wrapper:extend(.abs-add-box-sizing all) {
-        .css(padding-bottom, @indent__xl);
-        > .opc:extend(.abs-reset-list all) {
-        }
-        .section {
-            &.allow .step-title {
-                cursor: pointer;
-            }
-            &.active {
-                .step {
-                    &-title {
-                        .css(color, @primary__color__darker);
-                        cursor: default;
-                    }
-                    &-content {
-                        display: block;
-                    }
-                }
-            }
-        }
-        .step {
-            &-title {
-                border-bottom: @border-width__base solid @border-color__base;
-                .css(color, @primary__color__lighter);
-                line-height: 50px;
-                h2,
-                .number {
-                    display: inline-block;
-                    .heading(h3);
-                }
-                .number:after {
-                    content: '.';
-                }
-            }
-            &-content {
-                display: none;
-                padding: @indent__base @indent__s;
-                position: relative;
-                .addresses .control {
-                    margin: @indent__base 0;
-                }
-                .fieldset {
-                    margin-bottom: 0;
-                    &.login {
-                        .form-hasrequired(bottom);
-                        &:after {
-                            margin-top: 35px;
-                            text-align: center;
-                        }
-                    }
-                    > .field {
-                        margin: @form-field__vertical-indent 0 0;
-                    }
-                    &.address {
-                        .field:first-of-type:not(.additional) {
-                            margin: 0;
-                        }
-                    }
-                    .legend.payments-title:extend(.abs-visually-hidden all) {
-                    }
-                }
-                .methods-shipping {
-                    .item-content {
-                        .fieldset {
-                            > .legend:extend(.abs-visually-hidden all) {
-                            }
-                            > .legend + br:extend(.abs-no-display all) {
-                            }
-                            > .field {
-                                margin: @indent__base 0 0;
-                                &:before {
-                                    display: none;
-                                }
-                                .control {
-                                    display: inline-block;
-                                }
-                            }
-                            br + .field {
-                                margin: 0;
-                            }
-                        }
-                    }
-                }
-                .form {
-                    .form-hasrequired(bottom);
-                    &:after {
-                        text-align: center;
-                    }
-                    .field:not(:first-child) {
-                        margin: @indent__base 0 0;
-                    }
-                    > .field.choice {
-                        margin: @form-field__vertical-indent 0 0;
-                    }
-                    .field {
-                        &.month {
-                            padding-right: @indent__s;
-                        }
-                        &.year {
-                            margin-top: 0;
-                        }
-                    }
-                }
-                .form:not(.login),
-                .order-review {
-                    .action.primary:extend(.abs-button-l all) {
-                    }
-                }
-                .actions {
-                    margin-top: @indent__base;
-                }
-                .field.street {
-                    .field.additional {
-                        .label:extend(.abs-visually-hidden all) {
-                        }
-                    }
-                }
-            }
-        }
-
-        .opc-payment-additional {
-            margin: 0 0 @indent__xs;
-            + .opc-payment {
-                margin: @indent__base 0 0;
-            }
-        }
-
-        //
-        //  Order review
-        //  ---------------------------------------------
-
-        .order-review {
-            .fieldset > .field > .label {
-                font-weight: @font-weight__regular;
-            }
-            .product-item-name {
-                margin: 0;
-            }
-        }
-        
-        .data.table:extend(.abs-product-options-list all) {
-            .col {
-                &.price,
-                &.qty {
-                    text-align: center;
-                    white-space: nowrap;
-                }
-            }
-            .item-options:extend(.abs-add-clearfix all) {
-                font-size: @font-size__s;
-                margin: @indent__s 0 0;
-            }
-            .cart-price:extend(.abs-checkout-cart-price all) {
-            }
-        }
-
-        .action.primary.checkout {
-            margin: 0 0 @indent__base;
-        }
-
-        .hidden:extend(.abs-no-display all) {
-        }
-
-        //
-        //  Customer login
-        //  ---------------------------------------------
-
-        .login-wrapper {
-            .block {
-                .block-title:extend(.abs-login-block-title all) {
-                }
-                .fieldset.guest {
-                    margin-top: @indent__base;
-                }
-                .field.choice {
-                    margin-bottom: @indent__s;
-                }
-            }
-        }
-
-        .actions-toolbar {
-            margin: @indent__xl 0 0;
-        }
-    }
-
-    //
-    //  Shipping methods
-    //  ---------------------------------------------
-
-    .methods-shipping {
-        .item-title:extend(.abs-methods-shipping-title all) {
-        }
-        .item-content:extend(.abs-adjustment-incl-excl-tax all) {
-            margin: 0 0 @indent__xl;
-            .price {
-                font-weight: @font-weight__bold;
-            }
-            .field.choice {
-                margin: 0 0 @indent__s;
-                .control {
-                    float: left;
-                }
-                .label {
-                    display: block;
-                    overflow: hidden;
-                }
-            }
-        }
-        .price-box {
-            margin-bottom: @indent__xs;
-            margin-left: @indent__xl;
-            margin-top: @indent__s;
-            .label + .price {
-                font-weight: @font-weight__bold;
-            }
-        }
-        img {
-            vertical-align: middle;
-        }
-    }
-
-    //
-    //  Payment methods
-    //  ---------------------------------------------
-
-    .methods-payment {
-        .item {
-            &-title {
-                font-weight: @font-weight__regular;
-            }
-            &-content {
-                margin: 0 0 0 @indent__base;
-                .label {
-                    font-weight: @font-weight__regular;
-                }
-            }
-        }
-        .fieldset {
-            padding: 15px 0 @indent__m;
-        }
-        .fieldset & {
-            .item-content > .fieldset > .field:first-child {
-                margin-top: 0;
-            }
-        }
-        .redirect {
-            .font-size(@font-size__s);
-            padding: 0 0 15px;
-        }
-        img {
-            margin-right: @indent__xs;
-            vertical-align: middle;
-        }
-    }
-
-    .cart-tax-info + .cart-tax-total {
-        display: block;
-    }
-
-    //
-    //  Checkout Progress
-    //  ---------------------------------------------
-
-    .opc-block-progress:extend(.abs-add-box-sizing all) {
-        margin-bottom: @indent__l;
-        > .title {
-            .css(background, @sidebar__background-color);
-            .heading(h3);
-            margin: 0;
-            padding: 15px 15px @indent__base;
-            strong {
-                font-weight: @font-weight__regular;
-            }
-        }
-        > .content {
-            .css(background, @sidebar__background-color);
-            padding: 0 15px @indent__xs;
-            .item-content.complete {
-                margin: 0 0 15px;
-                overflow: hidden;
-            }
-            .action,
-            .payment-method .title {
-                font-weight: @font-weight__regular;
-            }
-            .data.table {
-                font-size: @font-size__s;
-            }
-        }
-        .payment-method {
-            > .title {
-                font-weight: @font-weight__light;
-            }
-            > .content {
-                margin: 0 0 @indent__s;
-                &:last-child {
-                    margin-bottom: 0;
-                }
-            }
-            .items-cards {
-                margin: 0;
-                > .content {
-                    margin: 0;
-                }
-            }
-            .data.table {
-                th {
-                    padding: @indent__xs @indent__s @indent__xs 0;
-                }
-                td {
-                    padding: @indent__xs 0;
-                }
-            }
-        }
-    }
-
-    //
-    //  Checkout Success
-    //  ---------------------------------------------
-
-    .checkout-onepage-success {
-        .page-title-wrapper {
-            .print:extend(.abs-no-display all) {
-            }
-        }
-    }
-
-    .checkout-success {
-        .actions-toolbar {
-            margin-top: @indent__xl;
-        }
-    }
-
-    .checkout-onepage-index {
-        .nav-toggle:extend(.abs-no-display all) {
-        }
-        .logo {
-            margin-left: 0;
-        }
-    }
-}
-
-//
-//  Mobile
-//  _____________________________________________
-
-.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
-    .opc-wrapper {
-        table.data.table:extend(.abs-checkout-order-review all) {
-        }
-    }
-}
-
-//
-//  Desktop
-//  _____________________________________________
-
-.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) {
-    .checkout-onepage-index .column.main:extend(.abs-add-clearfix-desktop-s all) {
-    }
-
-    .opc-wrapper:extend(.abs-add-box-sizing-desktop-s all) {
-        .layout-column(2, 2, @layout-column-checkout__width-main);
-        .step-content {
-            padding: @indent__base 18px @indent__xl;
-            .addresses .control {
-                margin-bottom: @desktop-form-field-vertical-indent;
-            }
-            .form {
-                &:after {
-                    text-align: right;
-                }
-                &:not(.login) {
-                    .actions-toolbar:extend(.abs-reset-left-margin-desktop-s all) {
-                    }
-                }
-                > .field.choice,
-                .fieldset > .field {
-                    margin: @desktop-form-field-vertical-indent 0 0;
-                }
-                .fieldset.address {
-                    .field:first-of-type:not(.additional) {
-                        margin: 0;
-                    }
-                }
-            }
-            .fieldset.login:after:extend(.abs-margin-for-forms-desktop-s all) {
-                text-align: left;
-            }
-        }
-    }
-
-    .opc-block-progress:extend(.abs-add-box-sizing-desktop-s all) {
-        .layout-column(2, 1, @layout-column-checkout__width-left);
-        padding-right: @layout-column-main__sidebar-offset;
-    }
-
-    .login-wrapper:extend(.abs-add-clearfix-desktop-s all) {
-        .block:extend(.abs-blocks-2columns-s all) {
-        }
-        .field.choice:not(.persistent) {
-            &:before {
-                display: none;
-            }
-        }
-        .fieldset.login {
-            .actions:extend(.abs-margin-for-forms-desktop-s all) {
-            }
-        }
-    }
-
-    //
-    //  Checkout success
-    //  ---------------------------------------------
-
-    .checkout-onepage-success {
-        .page-title-wrapper {
-            .print {
-                display: inline-block;
-                .font-size(14);
-                margin-left: @indent__xl;
-            }
-        }
-    }
-
-    .table-order-review {
-        .col.subtotal,
-        .amount {
-            text-align: right;
-        }
-    }
-}
+@import 'module/_checkout.less';
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less
index 089a66bff442b12dda09f922093d1e215abc9e43..fa4e5ad9ad23c9e319d9291c51799ce02bb1364c 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less
@@ -9,315 +9,236 @@
 
 & when (@media-common = true) {
 
-    //
-    //  Shopping cart
-    //  ---------------------------------------------
+  //
+  //  Shopping cart
+  //  ---------------------------------------------
 
-    .cart {
-        //  Summary block
-        &-summary {
-            &:extend(.abs-add-box-sizing all);
-            .css(background, @sidebar__background-color);
-            margin-bottom: @indent__m;
-            padding: 1px 15px @indent__m;
-            > .title {
-                display: block;
-                .heading(h3);
-            }
-            .block {
-                margin-bottom: 0;
-                > .title {
-                    border-top: @border-width__base solid @border-color__base;
-                    cursor: pointer;
-                    font-weight: @font-weight__semibold;
-                    .icon-font(
-                    @_icon-font-content: @icon-down,
-                    @_icon-font-size: 30px,
-                    @_icon-font-position: after,
-                    @_icon-font-display: block
-                    );
-                    margin-bottom: 0;
-                    overflow: hidden;
-                    padding: 7px @indent__base 7px @indent__xs;
-                    position: relative;
-                    &:after {
-                        position: absolute;
-                        right: 0;
-                        top: -5px;
-                    }
-                    strong {
-                        .column.main & {
-                            .font-size(18);
-                            font-weight: @font-weight__regular;
-                        }
-                    }
-                }
-                > .content {
-                    display: none;
-                }
-                &.active {
-                    > .title {
-                        .icon-font-symbol(
-                        @_icon-font-content: @icon-prev,
-                        @_icon-font-position: after
-                        );
-                    }
-                    > .content {
-                        display: block;
-                    }
-                }
-                .item-options {
-                    margin-left: 0;
-                }
-                .fieldset {
-                    margin: 15px 0 @indent__m @indent__xs;
-                    .field {
-                        margin: 0 0 @indent__s;
-                        &.note {
-                            font-size: @font-size__s;
-                        }
-                    }
-                }
-                .fieldset {
-                    .methods {
-                        .field {
-                            > .label {
-                                display: inline;
-                            }
-                        }
-                    }
-                }
-                .fieldset.estimate {
-                    > .legend,
-                    > .legend + br {
-                        &:extend(.abs-no-display all);
-                    }
-                }
-            }
-            .actions-toolbar {
-                > .primary {
-                    button {
-                        &:extend(.abs-revert-secondary-color all);
-                    }
-                }
-            }
-            &:extend(.abs-adjustment-incl-excl-tax all);
+  .cart {
+    //  Summary block
+    &-summary {
+      &:extend(.abs-add-box-sizing all);
+      .css(background, @sidebar__background-color);
+      margin-bottom: @indent__m;
+      padding: 1px 15px @indent__m;
+      > .title {
+        display: block;
+        .heading(h3);
+      }
+      .block {
+        margin-bottom: 0;
+        > .title {
+          border-top: @border-width__base solid @border-color__base;
+          cursor: pointer;
+          font-weight: @font-weight__semibold;
+          .icon-font(
+          @_icon-font-content: @icon-down,
+          @_icon-font-size: 30px,
+          @_icon-font-position: after,
+          @_icon-font-display: block
+          );
+          margin-bottom: 0;
+          overflow: hidden;
+          padding: 7px @indent__base 7px @indent__xs;
+          position: relative;
+          &:after {
+            position: absolute;
+            right: 0;
+            top: -5px;
+          }
+          strong {
+            .column.main & {
+              .font-size(18);
+              font-weight: @font-weight__regular;
+            }
+          }
         }
-
-        //  Totals block
-        &-totals {
-            border-top: 1px solid @border-color__base;
-            padding-top: 10px;
-            .table-wrapper {
-                overflow: inherit;
-            }
-            .mark {
-                font-weight: @font-weight__regular;
-                padding-left: 4px;
-                strong {
-                    font-weight: @font-weight__regular;
-                }
-            }
-            .amount {
-                padding-right: 4px;
-                text-align: right;
-                strong {
-                    font-weight: @font-weight__regular;
-                }
-            }
-            .grand:last-child {
-                .mark,
-                .amount {
-                    padding-top: @indent__base;
-                }
-                .amount {
-                    padding-right: 4px;
-                    text-align: right;
-                    strong {
-                        font-weight: @font-weight__bold;
-                    }
-                }
-            }
-            .msrp {
-                margin-bottom: @indent__s;
-            }
-            .totals-tax {
-                &-summary {
-                    .mark,
-                    .amount {
-                        border-bottom: @border-width__base solid @border-color__base;
-                        border-top: @border-width__base solid @border-color__base;
-                        cursor: pointer;
-                    }
-                    .amount .price {
-                        .icon-font(
-                        @icon-down,
-                        @_icon-font-size: 30px,
-                        @_icon-font-text-hide: true,
-                        @_icon-font-position: after,
-                        @_icon-font-display: block
-                        );
-                        padding-right: @indent__m;
-                        position: relative;
-                        &:after {
-                            position: absolute;
-                            right: -5px;
-                            top: -12px;
-                        }
-                    }
-                    &.expanded {
-                        .mark,
-                        .amount {
-                            border-bottom: 0;
-                        }
-                        .amount .price {
-                            .icon-font-symbol(
-                            @_icon-font-content: @icon-up,
-                            @_icon-font-position: after
-                            );
-                        }
-                    }
-                }
-                &-details {
-                    border-bottom: @border-width__base solid @border-color__base;
-                    display: none;
-                    &.shown {
-                        display: table-row;
-                    }
-                }
-            }
-            .table-wrapper {
-                margin-bottom: 0;
-            }
-            .table-caption {
-                &:extend(.abs-no-display all);
-            }
+        > .content {
+          display: none;
         }
+        &.active {
+          > .title {
+            .icon-font-symbol(
+            @_icon-font-content: @icon-prev,
+            @_icon-font-position: after
+            );
+          }
+          > .content {
+            display: block;
+          }
+        }
+        .item-options {
+          margin-left: 0;
+        }
+        .fieldset {
+          margin: 15px 0 @indent__m @indent__xs;
+          .field {
+            margin: 0 0 @indent__s;
+            &.note {
+              font-size: @font-size__s;
+            }
+          }
+        }
+        .fieldset {
+          .methods {
+            .field {
+              > .label {
+                display: inline;
+              }
+            }
+          }
+        }
+        .fieldset.estimate {
+          > .legend,
+          > .legend + br {
+            &:extend(.abs-no-display all);
+          }
+        }
+      }
+      .actions-toolbar {
+        > .primary {
+          button {
+            &:extend(.abs-revert-secondary-color all);
+          }
+        }
+      }
+      &:extend(.abs-adjustment-incl-excl-tax all);
+    }
 
-        //  Products table
-        &.table-wrapper {
-            .items {
-                thead + .item {
-                    border-top: @border-width__base solid @border-color__base;
-                }
-                > .item {
-                    border-bottom: @border-width__base solid @border-color__base;
-                    position: relative;
-                }
-            }
-            .col {
-                padding-top: 20px;
-                &.qty {
-                    .input-text {
-                        margin-top: -5px;
-                        &:extend(.abs-input-qty all);
-                    }
-                    .label {
-                        &:extend(.abs-visually-hidden all);
-                    }
-                }
-            }
-            .item {
-                &-actions td {
-                    padding-bottom: @indent__s;
-                    text-align: center;
-                    white-space: normal;
-                }
-                .col {
-                    &.item {
-                        display: block;
-                        min-height: 75px;
-                        padding: @indent__m 0 @indent__s 75px;
-                        position: relative;
-                    }
-                }
-            }
-            .actions-toolbar {
-                &:extend(.abs-add-clearfix all);
-                > .action {
-                    &:extend(button all);
-                    .link-as-button();
-                    margin-bottom: @indent__s;
-                    margin-right: @indent__s;
-                    &:last-child {
-                        margin-right: 0;
-                    }
-                }
-            }
-            .action {
-                &.help.map {
-                    &:extend(.abs-action-button-as-link all);
-                    font-weight: @font-weight__regular;
-                }
-            }
-            .product {
-                &-item-photo {
-                    display: block;
-                    left: 0;
-                    max-width: 60px;
-                    padding: 0;
-                    position: absolute;
-                    top: 15px;
-                    width: 100%;
-                }
-                &-item-details {
-                    white-space: normal;
-                }
-                &-item-name {
-                    display: inline-block;
-                    font-weight: @font-weight__regular;
-                    margin-top: -6px;
-                }
-            }
-            .gift-registry-name-label {
-                &:after {
-                    content: ':';
-                }
-            }
-            //  Product options
-            .item-options {
-                font-size: @font-size__s;
-                margin-bottom: @indent__s;
-                &:extend(.abs-product-options-list all);
-                &:extend(.abs-add-clearfix all);
-            }
-
-            .product-item-name + .item-options {
-                margin-top: @indent__s;
-            }
+    //  Totals block
+    &-totals {
+      border-top: 1px solid @border-color__base;
+      padding-top: 10px;
+      &:extend(.abs-sidebar-totals all);
+      .table-wrapper {
+        margin-bottom: 0;
+        overflow: inherit;
+      }
+    }
 
-            .product-image-wrapper {
-                &:extend(.abs-reset-image-wrapper all);
-            }
-            .action.configure {
-                display: inline-block;
-                margin: 0 0 @indent__base;
-            }
+    //  Products table
+    &.table-wrapper {
+      .items {
+        thead + .item {
+          border-top: @border-width__base solid @border-color__base;
         }
-        &-container {
-            .form-cart {
-                &:extend(.abs-shopping-cart-items all);
-            }
-            .checkout-methods-items {
-                margin-top: @indent__base;
-                &:extend(.abs-reset-list all);
-                text-align: center;
-                .action.primary {
-                    &:extend(.abs-button-l all);
-                    margin-bottom: @indent__s;
-                    width: 100%;
-                }
-            }
+        > .item {
+          border-bottom: @border-width__base solid @border-color__base;
+          position: relative;
         }
-    }
+      }
+      .col {
+        padding-top: 20px;
+        &.qty {
+          .input-text {
+            margin-top: -5px;
+            &:extend(.abs-input-qty all);
+          }
+          .label {
+            &:extend(.abs-visually-hidden all);
+          }
+        }
+      }
+      .item {
+        &-actions td {
+          padding-bottom: @indent__s;
+          text-align: center;
+          white-space: normal;
+        }
+        .col {
+          &.item {
+            display: block;
+            min-height: 75px;
+            padding: @indent__m 0 @indent__s 75px;
+            position: relative;
+          }
+        }
+      }
+      .actions-toolbar {
+        &:extend(.abs-add-clearfix all);
+        > .action {
+          &:extend(button all);
+          .link-as-button();
+          margin-bottom: @indent__s;
+          margin-right: @indent__s;
+          &:last-child {
+            margin-right: 0;
+          }
+        }
+      }
+      .action {
+        &.help.map {
+          &:extend(.abs-action-button-as-link all);
+          font-weight: @font-weight__regular;
+        }
+      }
+      .product {
+        &-item-photo {
+          display: block;
+          left: 0;
+          max-width: 60px;
+          padding: 0;
+          position: absolute;
+          top: 15px;
+          width: 100%;
+        }
+        &-item-details {
+          white-space: normal;
+        }
+        &-item-name {
+          display: inline-block;
+          font-weight: @font-weight__regular;
+          margin-top: -6px;
+        }
+      }
+      .gift-registry-name-label {
+        &:after {
+          content: ':';
+        }
+      }
+      //  Product options
+      .item-options {
+        font-size: @font-size__s;
+        margin-bottom: @indent__s;
+        &:extend(.abs-product-options-list all);
+        &:extend(.abs-add-clearfix all);
+      }
 
-    //
-    //  Cross sell
-    //  ---------------------------------------------
+      .product-item-name + .item-options {
+        margin-top: @indent__s;
+      }
 
-    .block.crosssell {
-        margin-top: 70px;
+      .product-image-wrapper {
+        &:extend(.abs-reset-image-wrapper all);
+      }
+      .action.configure {
+        display: inline-block;
+        margin: 0 0 @indent__base;
+      }
+    }
+    &-container {
+      .form-cart {
+        &:extend(.abs-shopping-cart-items all);
+      }
+      .checkout-methods-items {
+        margin-top: @indent__base;
+        &:extend(.abs-reset-list all);
+        text-align: center;
+        .action.primary {
+          &:extend(.abs-button-l all);
+          margin-bottom: @indent__s;
+          width: 100%;
+        }
+      }
     }
+  }
+
+  //
+  //  Cross sell
+  //  ---------------------------------------------
+
+  .block.crosssell {
+    margin-top: 70px;
+  }
 }
 
 //
@@ -325,48 +246,48 @@
 //  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
-    .cart {
-        &.table-wrapper {
-            thead {
-                .col:not(.item) {
-                    display: none;
-                }
-            }
-            .col {
-                &.qty,
-                &.price,
-                &.subtotal,
-                &.msrp {
-                    box-sizing: border-box;
-                    display: block;
-                    float: left;
-                    text-align: center;
-                    white-space: nowrap;
-                    width: 33%;
-                    &:before {
-                        content: attr(data-th) ':';
-                        display: block;
-                        font-weight: @font-weight__bold;
-                        padding-bottom: 10px;
-                    }
-                }
-                &.msrp {
-                    white-space: normal;
-                }
-            }
-            .item .col.item {
-                padding-bottom: 0;
-            }
+  .cart {
+    &.table-wrapper {
+      thead {
+        .col:not(.item) {
+          display: none;
         }
-        &-container {
-            .form-cart {
-                &:extend(.abs-shopping-cart-items-mobile all);
-            }
+      }
+      .col {
+        &.qty,
+        &.price,
+        &.subtotal,
+        &.msrp {
+          box-sizing: border-box;
+          display: block;
+          float: left;
+          text-align: center;
+          white-space: nowrap;
+          width: 33%;
+          &:before {
+            content: attr(data-th) ':';
+            display: block;
+            font-weight: @font-weight__bold;
+            padding-bottom: 10px;
+          }
         }
-        &.table-wrapper {
-            overflow: inherit;
+        &.msrp {
+          white-space: normal;
         }
+      }
+      .item .col.item {
+        padding-bottom: 0;
+      }
+    }
+    &-container {
+      .form-cart {
+        &:extend(.abs-shopping-cart-items-mobile all);
+      }
     }
+    &.table-wrapper {
+      overflow: inherit;
+    }
+  }
 }
 
 //
@@ -374,69 +295,69 @@
 //  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
-    .cart {
-        &-container {
-            &:extend(.abs-add-clearfix-desktop all);
-            .form-cart {
-                &:extend(.abs-shopping-cart-items-desktop all);
-            }
-            .widget {
-                float: left;
-            }
+  .cart {
+    &-container {
+      &:extend(.abs-add-clearfix-desktop all);
+      .form-cart {
+        &:extend(.abs-shopping-cart-items-desktop all);
+      }
+      .widget {
+        float: left;
+      }
+    }
+    &-summary {
+      float: right;
+      position: relative;
+      width: 23%;
+      .actions-toolbar {
+        .column.main & {
+          &:extend(.abs-reset-left-margin-desktop all);
+          > .secondary {
+            float: none;
+          }
         }
-        &-summary {
-            float: right;
-            position: relative;
-            width: 23%;
-            .actions-toolbar {
-                .column.main & {
-                    &:extend(.abs-reset-left-margin-desktop all);
-                    > .secondary {
-                        float: none;
-                    }
-                }
-            }
-            .block {
-                .fieldset {
-                    .field {
-                        .form-field-type-revert(@_type: block);
-                        margin: 0 0 @indent__s;
-                    }
-                }
-            }
+      }
+      .block {
+        .fieldset {
+          .field {
+            .form-field-type-revert(@_type: block);
+            margin: 0 0 @indent__s;
+          }
         }
+      }
+    }
 
-        &.table-wrapper {
-            .item {
-                .col {
-                    &.item {
-                        padding: 27px 8px @indent__s;
-                    }
-                }
-                &-actions td {
-                    text-align: right;
-                }
-            }
-            .product {
-                &-item-photo {
-                    display: table-cell;
-                    max-width: 100%;
-                    padding-right: @indent__base;
-                    position: static;
-                    vertical-align: top;
-                    width: 1%;
-                }
-                &-item-details {
-                    display: table-cell;
-                    vertical-align: top;
-                    white-space: normal;
-                    width: 99%;
-                }
-            }
-            .item-actions .actions-toolbar {
-                text-align: left;
-                &:extend(.abs-reset-left-margin-desktop all);
-            }
+    &.table-wrapper {
+      .item {
+        .col {
+          &.item {
+            padding: 27px 8px @indent__s;
+          }
+        }
+        &-actions td {
+          text-align: right;
+        }
+      }
+      .product {
+        &-item-photo {
+          display: table-cell;
+          max-width: 100%;
+          padding-right: @indent__base;
+          position: static;
+          vertical-align: top;
+          width: 1%;
+        }
+        &-item-details {
+          display: table-cell;
+          vertical-align: top;
+          white-space: normal;
+          width: 99%;
         }
+      }
+      .item-actions .actions-toolbar {
+        text-align: left;
+        &:extend(.abs-reset-left-margin-desktop all);
+      }
     }
+  }
 }
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less
new file mode 100644
index 0000000000000000000000000000000000000000..db93ffc7fe3f173d56b45df4318ea789099a0b04
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less
@@ -0,0 +1,26 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Page components
+//  ---------------------------------------------
+
+@import 'checkout/_checkout.less';
+@import 'checkout/_estimated-total.less';
+@import 'checkout/_progress-bar.less';
+@import 'checkout/_fields.less';
+@import 'checkout/_modals.less';
+@import 'checkout/_tooltip.less';
+@import 'checkout/_shipping.less';
+@import 'checkout/_shipping-policy.less';
+
+@import 'checkout/_sidebar.less';
+@import 'checkout/_sidebar-shipping-information.less';
+@import 'checkout/_order-summary.less';
+@import 'checkout/_authentication.less';
+
+@import 'checkout/_payments.less';
+@import 'checkout/_payment-options.less';
+@import 'checkout/_checkout-agreements.less';
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
index 535a47ff7f9ee5ddad63365a0f0f07f37b1208c9..317c57334f11c36998d524588599196c5d632184 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
@@ -5,93 +5,93 @@
 
 //
 //  Variables
-//  ---------------------------------------------
+//  _____________________________________________
 
 @minicart__border-color: @color-gray80;
 @minicart__padding-horizontal: @indent__base;
 
 //
 //  Common
-//  ---------------------------------------------
+//  _____________________________________________
 
 & when (@media-common = true) {
 
-//
-//  Minicart
-//  ---------------------------------------------
+    //
+    //  Minicart
+    //  ---------------------------------------------
 
-.block-minicart {
-    .items-total {
-        float: left;
-        margin: 0 @indent__s;
-        .count {
-            font-weight: @font-weight__bold;
+    .block-minicart {
+        .items-total {
+            float: left;
+            margin: 0 @indent__s;
+            .count {
+                font-weight: @font-weight__bold;
+            }
         }
-    }
-    .subtotal {
-        margin: 0 @indent__s;
-        text-align: right;
-        .label {
-            &:extend(.abs-colon all);
+        .subtotal {
+            margin: 0 @indent__s;
+            text-align: right;
+            .label {
+                &:extend(.abs-colon all);
+            }
         }
-    }
-    .amount {
-        .price-wrapper {
-            &:first-child {
-                .price {
-                    font-size: @font-size__l;
-                    font-weight: @font-weight__bold;
+        .amount {
+            .price-wrapper {
+                &:first-child {
+                    .price {
+                        font-size: @font-size__l;
+                        font-weight: @font-weight__bold;
+                    }
                 }
             }
         }
-    }
-    .subtitle {
-        display: none;
-    }
-    .subtitle {
-        &.empty {
-            display: block;
-            padding: @indent__l 0 @indent__base;
-            text-align: center;
-            font-size: 14px;
+        .subtitle {
+            display: none;
         }
-    }
-    .text {
-        &.empty {
-            text-align: center;
+        .subtitle {
+            &.empty {
+                display: block;
+                font-size: 14px;
+                padding: @indent__l 0 @indent__base;
+                text-align: center;
+            }
         }
-    }
-    .block-content {
-        > .actions {
-            margin-top: 15px;
-            text-align: center;
-            > .primary {
-                margin: 0 @indent__s 15px;
-                .action {
-                    &.primary {
-                        &:extend(.abs-button-l all);
-                        display: block;
-                        width: 100%;
-                        margin-bottom: 15px;
-                        &:last-child {
-                            margin-bottom: 0;
+        .text {
+            &.empty {
+                text-align: center;
+            }
+        }
+        .block-content {
+            > .actions {
+                margin-top: 15px;
+                text-align: center;
+                > .primary {
+                    margin: 0 @indent__s 15px;
+                    .action {
+                        &.primary {
+                            &:extend(.abs-button-l all);
+                            display: block;
+                            margin-bottom: 15px;
+                            width: 100%;
+                            &:last-child {
+                                margin-bottom: 0;
+                            }
                         }
                     }
                 }
             }
         }
+        .block-category-link,
+        .block-product-link,
+        .block-cms-link,
+        .block-banners {
+            margin: 15px 0 0;
+            text-align: center;
+        }
     }
-    .block-category-link,
-    .block-product-link,
-    .block-cms-link,
-    .block-banners {
-        margin: 15px 0 0;
-        text-align: center;
-    }
-}
 
-.minicart-wrapper {
-    .dropdown(
+    .minicart-wrapper {
+        .dropdown(
         @_toggle-selector: ~".action.showcart",
         @_options-selector: ~".block-minicart",
         @_dropdown-toggle-icon-content: @icon-cart,
@@ -104,200 +104,229 @@
         @_icon-font-color: @minicart-icons-color,
         @_icon-font-color-hover: @minicart-icons-color-hover,
         @_icon-font-color-active: @minicart-icons-color
-    );
-    float: right;
-    .block-minicart {
-        .css(padding, 25px @minicart__padding-horizontal);
-        right: 0;
-        width: 320px;
-        .block-title {
-            display: none;
-        }
-        &:after {
-            left: auto;
-            right: 25px;
-        }
-        &:before {
-            left: auto;
-            right: 26px;
+        );
+        float: right;
+        .block-minicart {
+            .css(padding, 25px @minicart__padding-horizontal);
+            right: 0;
+            width: 320px;
+            .block-title {
+                display: none;
+            }
+            &:after {
+                left: auto;
+                right: 25px;
+            }
+            &:before {
+                left: auto;
+                right: 26px;
+            }
         }
-    }
-    .product.actions {
-        text-align: right;
-        > .primary,
-        > .secondary {
-            display: inline;
+        .product.actions {
+            text-align: right;
+            > .primary, > .secondary {
+                display: inline;
+            }
         }
-    }
 
-    .action {
-        &.close {
-            width: 40px;
-            height: 40px;
-            top: 0;
-            right: 0;
-            position: absolute;
-            .button-reset();
-            .button-icon(
+        .action {
+            &.close {
+                .button-icon(
                 @icon-remove,
                 @_icon-font-size: 32px,
                 @_icon-font-line-height: 32px,
                 @_icon-font-text-hide: true
-            );
-        }
-        &.showcart {
-            .text {
-                &:extend(.abs-visually-hidden all);
+                );
+                .button-reset();
+                height: 40px;
+                position: absolute;
+                right: 0;
+                top: 0;
+                width: 40px;
             }
-            white-space: nowrap;
-            .counter.qty {
-                &.empty {
-                   display: none;
+            &.showcart {
+                white-space: nowrap;
+                .text {
+                    &:extend(.abs-visually-hidden all);
+                }
+                .counter.qty {
+                    border-radius: 2px;
+                    clip: none;
+                    .css(color, @page__background-color);
+                    .css(background, @active__color);
+                    display: inline-block;
+                    height: 24px;
+                    line-height: 24px;
+                    margin: 3px 0 0;
+                    min-width: 18px;
+                    overflow: hidden;
+                    padding: 0 3px;
+                    text-align: center;
+                    white-space: normal;
+                    &.empty {
+                        &:extend(.abs-no-display all);
+                    }
+                }
+                .counter-label {
+                    &:extend(.abs-visually-hidden all);
                 }
-                .css(background, @active__color);
-                border-radius: 2px;
-                .css(color, @page__background-color);
-                clip: none;
-                display: inline-block;
-                height: 24px;
-                line-height: 24px;
-                min-width: 18px;
-                margin: 3px 0 0;
-                padding: 0 3px;
-                overflow: hidden;
-                text-align: center;
-                white-space: normal;
-            }
-            .counter-label {
-                &:extend(.abs-visually-hidden all);
             }
         }
+        .minicart-widgets {
+            margin-top: 15px;
+        }
     }
-    .minicart-widgets {
-        margin-top: 15px;
-    }
-}
 
-.minicart-items-wrapper {
-    .css(border, 1px solid @minicart__border-color);
-    .css(margin, 0 -@minicart__padding-horizontal);
-    border-left: 0;
-    border-right: 0;
-    overflow-x: auto;
-    padding: 15px;
-}
+    .minicart-items-wrapper {
+        border-left: 0;
+        border-right: 0;
+        .css(margin, 0 -@minicart__padding-horizontal);
+        .css(border, 1px solid @minicart__border-color);
+        overflow-x: auto;
+        padding: 15px;
+    }
 
-.minicart-items {
-    .list-reset-styles(0, 0);
-    .item {
-        &:not(:first-child) {
-            .css(border-top, 1px solid @minicart__border-color);
-        }
-        padding: @indent__base 0;
-        &:first-child {
-            padding-top: 0;
+    .minicart-items {
+        .list-reset-styles(0, 0);
+        .product-item {
+            padding: @indent__base 0;
+            &:not(:first-child) {
+                .css(border-top, 1px solid @minicart__border-color);
+            }
+            &:first-child {
+                padding-top: 0;
+            }
+            > .product {
+                &:extend(.abs-add-clearfix all);
+            }
         }
-        > .product {
-            &:extend(.abs-add-clearfix all);
+        .product-image-wrapper {
+            &:extend(.abs-reset-image-wrapper all);
         }
-    }
-    .product-image-wrapper {
-        &:extend(.abs-reset-image-wrapper all);
-    }
-    .product-item-pricing {
-        .label {
-            display: inline-block;
-            width: 4.5rem;
-         }
-    }
-    .price-minicart {
-        margin-bottom: @indent__xs;
-    }
-    .product-item-photo {
-        float: left;
-    }
-    .product-item-name {
-        font-weight: @font-weight__regular;
-        margin: 0 0 @indent__s;
-        a {
-            .css(color, @link__color);
+        .product-item-pricing {
+            .label {
+                display: inline-block;
+                width: 4.5rem;
+            }
         }
-    }
-    .product-item-details {
-        padding-left: 88px;
-        .price {
-            font-weight: @font-weight__bold;
+        .price-minicart {
+            margin-bottom: @indent__xs;
         }
-        .price-including-tax,
-        .price-excluding-tax {
-            margin: @indent__xs 0;
+        .product {
+            > .product-item-photo,
+            > .product-image-container {
+                float: left;
+            }
+            .toggle {
+                .icon-font(
+                @_icon-font-content: @icon-down,
+                @_icon-font-size: 28px,
+                @_icon-font-line-height: 16px,
+                @_icon-font-text-hide: false,
+                @_icon-font-position: after,
+                @_icon-font-display: block
+                );
+                cursor: pointer;
+                position: relative;
+                &:after {
+                    position: static;
+                    right: @indent__base;
+                    top: 0;
+                }
+            }
+            &.active {
+                > .toggle {
+                    .icon-font-symbol(
+                    @_icon-font-content: @icon-up,
+                    @_icon-font-position: after
+                    );
+                }
+            }
         }
-        .weee[data-label] {
-            .font-size(11);
-            .label {
-                &:extend(.abs-no-display all);
+        .product-item-name {
+            font-weight: @font-weight__regular;
+            margin: 0 0 @indent__s;
+            a {
+                .css(color, @link__color);
             }
         }
-        .details-qty {
-            margin-top: @indent__s;
+        .product-item-details {
+            padding-left: 88px;
+            .price {
+                font-weight: @font-weight__bold;
+            }
+            .price-including-tax,
+            .price-excluding-tax {
+                margin: @indent__xs 0 0;
+            }
+            .weee[data-label] {
+                .font-size(11);
+                .label {
+                    &:extend(.abs-no-display all);
+                }
+            }
+            .details-qty {
+                margin-top: @indent__s;
+            }
         }
-    }
-    .product.options {
-        .tooltip.toggle {
-            .icon-font(
+        .product.options {
+            .tooltip.toggle {
+                .icon-font(
                 @icon-down,
                 @_icon-font-size: 28px,
                 @_icon-font-line-height: 28px,
                 @_icon-font-text-hide: true,
                 @_icon-font-margin: -3px 0 0 7px,
                 @_icon-font-position: after
-            );
-            .details {
-                display: none;
+                );
+                .details {
+                    display: none;
+                }
             }
         }
-    }
-    .details-qty,
-    .price-minicart {
-        .label {
-            &:extend(.abs-colon all);
+        .details-qty,
+        .price-minicart {
+            .label {
+                &:extend(.abs-colon all);
+            }
+        }
+        .item-qty {
+            margin-right: @indent__s;
+            text-align: center;
+            width: 40px;
+        }
+        .item-update {
+            .font-size(11);
+            vertical-align: top;
+        }
+        .subtitle {
+            &:extend(.abs-no-display all);
+        }
+        .action {
+            &.edit,
+            &.delete {
+                .icon-font(
+                @icon-settings,
+                @_icon-font-size: 28px,
+                @_icon-font-line-height: 28px,
+                @_icon-font-text-hide: true,
+                @_icon-font-color: @color-gray19,
+                @_icon-font-color-hover: @color-gray19,
+                @_icon-font-color-active: @color-gray19
+                );
+            }
+            &.delete {
+                .icon-font-symbol(
+                @_icon-font-content: @icon-trash
+                );
+            }
         }
     }
-    .item-qty {
-        width: 40px;
-        text-align: center;
-        margin-right: @indent__s;
-    }
-    .item-update {
-        vertical-align: top;
-        .font-size(11);
-    }
-    .action {
-         &.edit,
-         &.delete {
-             .icon-font(
-                 @icon-settings,
-                 @_icon-font-size: 28px,
-                 @_icon-font-line-height: 28px,
-                 @_icon-font-text-hide: true,
-                 @_icon-font-color: @color-gray19,
-                 @_icon-font-color-hover: @color-gray19,
-                 @_icon-font-color-active: @color-gray19
-             );
-         }
-         &.delete {
-             .icon-font-symbol(
-                 @_icon-font-content: @icon-trash
-             );
-         }
-    }
-}
-
 }
 
 //
 //  Mobile
-//  ---------------------------------------------
+//  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
     .minicart-wrapper .block-minicart {
@@ -313,7 +342,7 @@
 
 //
 //  Desktop
-//  ---------------------------------------------
+//  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .minicart-wrapper {
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less
new file mode 100644
index 0000000000000000000000000000000000000000..26c1ac83c04217bc2ad84483a5ec3b608cecf4ae
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less
@@ -0,0 +1,196 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@block-auth__dropdown__padding: @indent__m;
+@block-auth__dropdown__background-color: @color-white;
+@block-auth__or-label__size: 36px;
+@block-auth__width: 0;
+@block-auth__border: 1px solid @color-gray-light3;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .authentication-dropdown {
+        box-sizing: border-box;
+        .modal-inner-wrap {
+            padding: @block-auth__dropdown__padding;
+        }
+    }
+    .authentication-wrapper {
+        float: right;
+        margin-top: -1.5*@indent__xl;
+        max-width: 50%;
+        position: relative;
+        z-index: 1;
+        ._has-auth-shown & {
+            z-index: @modal__z-index;
+        }
+    }
+    .action-auth-toggle {
+        &:extend(.abs-action-button-as-link all);
+    }
+    .block-authentication {
+        .block-title {
+            .font-size(@h3__font-size);
+            border-bottom: 0;
+            margin-bottom: @indent__m;
+            strong {
+                font-weight: @font-weight__light;
+            }
+        }
+        .field {
+            .label {
+                font-weight: @font-weight__regular;
+            }
+        }
+        .actions-toolbar {
+            margin-bottom: @indent__xs;
+            > .secondary {
+                padding-top: @indent__m;
+                text-align: left;
+            }
+        }
+        .action.action-register,
+        .action.action-login {
+            &:extend(.abs-button-l all);
+        }
+        .block[class] {
+            margin: 0;
+            ul {
+                list-style: none;
+                padding-left: @indent__s;
+            }
+            .field {
+                .control,
+                .label {
+                    float: none;
+                    width: auto;
+                }
+            }
+            & + .block {
+                border-top: 1px solid @color-gray-light5;
+                margin-top: @indent__xl;
+                padding-top: @indent__xl;
+                position: relative;
+                &::before {
+                    .css(height, @block-auth__or-label__size);
+                    .css(line-height, @block-auth__or-label__size - 2px);
+                    .css(margin, -(@block-auth__or-label__size/2 + 1px) 0 0 -(@block-auth__or-label__size / 2));
+                    .css(min-width, @block-auth__or-label__size);
+                    background: @color-white;
+                    border-radius: 50%;
+                    border: 1px solid @color-gray-light5;
+                    box-sizing: border-box;
+                    color: @color-gray-light5;
+                    content: attr(data-label);
+                    display: inline-block;
+                    left: 50%;
+                    letter-spacing: normal;
+                    padding: 0 .2rem;
+                    position: absolute;
+                    text-align: center;
+                    text-transform: uppercase;
+                    top: 0;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .authentication-dropdown {
+        .css(background-color, @block-auth__dropdown__background-color);
+        .css(border, @block-auth__border);
+        position: absolute;
+        text-align: left;
+        top: 100%;
+        transform-origin: 0 0;
+        transform: scale(1,0);
+        transition: transform linear .1s, visibility 0s linear .1s;
+        visibility: hidden;
+        width: 100%;
+        &._show {
+            .css(z-index, @dropdown-list__z-index);
+            transform: scale(1,1);
+            transition: transform linear .1s, visibility 0s linear 0s;
+            visibility: visible;
+        }
+    }
+    .authentication-wrapper {
+        .column-width(@checkout-sidebar__columns);
+        text-align: right;
+    }
+    .block-authentication {
+        .block-title {
+            .font-size(@h2__font-size);
+            border-bottom: 0;
+            margin-bottom: @indent__m;
+        }
+        .actions-toolbar {
+            > .primary {
+                display: inline;
+                float: right;
+                margin-right: 0;
+                .action {
+                    margin-right: 0;
+                }
+            }
+            > .secondary {
+                float: left;
+                margin-right: 2rem;
+                padding-top: 1rem;
+            }
+        }
+    }
+    .popup-authentication {
+        .modal-inner-wrap {
+            min-width: @screen__m;
+            width: 60%;
+        }
+        .block-authentication {
+            .vendor-prefix-display(flex);
+            .vendor-prefix-flex-direction(row);
+            border-top: 1px solid @color-gray-light5;
+        }
+        .block[class],
+        .form-login,
+        .fieldset,
+        .block-content {
+            .vendor-prefix-display(flex);
+            .vendor-prefix-flex-direction(column);
+            .vendor-prefix-flex-grow(1);
+        }
+        .block[class] {
+            box-sizing: border-box;
+            float: left;
+            padding: @indent__s @indent__l 0 0;
+            width: 50%;
+            & + .block {
+                border-left: 1px solid @color-gray-light5;
+                border-top: 0;
+                margin: 0;
+                padding: @indent__s 0 0 @indent__xl;
+                &::before {
+                    left: 0;
+                    top: 50%;
+                }
+            }
+        }
+        .actions-toolbar {
+            margin-bottom: 0;
+            margin-top: auto;
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less
new file mode 100644
index 0000000000000000000000000000000000000000..02fbbeb1faa431e4056b78be1daf0cd0c90cffdd
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less
@@ -0,0 +1,34 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-agreements-block {
+        margin-bottom: @indent__base;
+
+        .action-show {
+            &:extend(.abs-action-button-as-link all);
+            vertical-align: baseline;
+        }
+    }
+
+    // Checkout Agreements in popup
+    .checkout-agreements-items {
+        &:extend(.abs-reset-list all);
+        padding-bottom: @indent__l;
+
+        .checkout-agreements-item {
+            margin-bottom: @indent__base;
+        }
+
+        .checkout-agreements-item-title {
+            &:extend(.abs-checkout-title all);
+            border-bottom: 0;
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less
new file mode 100644
index 0000000000000000000000000000000000000000..6fcaedd24084e3c230ab32cb01186949bfc06b0e
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less
@@ -0,0 +1,86 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-wrapper__margin: @indent__base;
+@checkout-wrapper__columns: 8;
+
+@checkout-step-title__border: @border-width__base solid @color-gray80;
+@checkout-step-title__font-size: 26px;
+@checkout-step-title__font-weight: @font-weight__light;
+@checkout-step-title__margin-bottom: 28px;
+@checkout-step-title__padding: @indent__s;
+
+@checkout-step-title-mobile__font-size: 18px;
+@checkout-step-title-mobile__margin-bottom: @indent__base;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    .checkout-container {
+        &:extend(.abs-add-clearfix all);
+        .css(margin, 0 0 @checkout-wrapper__margin);
+    }
+
+    .opc-wrapper {
+        .css(margin, 0 0 @checkout-wrapper__margin);
+
+        .opc {
+            &:extend(.abs-reset-list all);
+        }
+
+        .step-title {
+            &:extend(.abs-checkout-title all);
+            .css(margin, 0 0 @checkout-step-title__margin-bottom);
+        }
+
+        .step-content {
+            margin: 0 0 @indent__xl;
+        }
+    }
+
+    .checkout-onepage-index {
+        .nav-sections,
+        .nav-toggle {
+            display: none;
+        }
+        .logo {
+            margin-left: 0;
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .opc-wrapper {
+        .step-title {
+            .css(font-size, @checkout-step-title-mobile__font-size);
+            .css(margin-bottom, @checkout-step-title-mobile__margin-bottom);
+            border-bottom: 0;
+            padding-bottom: 0;
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-wrapper {
+        &:extend(.abs-add-box-sizing-desktop-m all);
+        .layout-column(2, 1, @checkout-wrapper__columns);
+        padding-right: @indent__l;
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less
new file mode 100644
index 0000000000000000000000000000000000000000..5119231620d6ee172e9906402baedc181b3f77fd
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less
@@ -0,0 +1,54 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Checkout Estimated Total
+    //  ---------------------------------------------
+
+    .opc-estimated-wrapper {
+        &:extend(.abs-add-clearfix all);
+        &:extend(.abs-no-display-desktop all);
+        .css(border-bottom, @border-width__base solid @color-gray80);
+        margin: 0 0 15px;
+        padding: 18px 15px;
+
+        .estimated-block {
+            .css(font-size, @checkout-step-title-mobile__font-size);
+            .css(font-weight, @font-weight__bold);
+            float: left;
+
+            .estimated-label {
+                margin: 0 0 @indent__xs;
+                display: block;
+            }
+        }
+
+        .minicart-wrapper {
+            .action {
+                &.showcart {
+                    &:before {
+                        .css(color, @primary__color);
+                    }
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) {
+    .opc-estimated-wrapper {
+        display: none;
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less
new file mode 100644
index 0000000000000000000000000000000000000000..17fd35ed14fc6f2229338e1bd568d7ee0dcdfdde
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less
@@ -0,0 +1,33 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-field-validation__border-color: @form-element-validation__border-error;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .field {
+        .control {
+            &._with-tooltip {
+                &:extend(.abs-field-tooltip all);
+            }
+        }
+        &._error {
+            .control {
+                input,
+                select,
+                textarea {
+                    .css(border-color, @checkout-field-validation__border-color);
+                }
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less
new file mode 100644
index 0000000000000000000000000000000000000000..a11423841e94f407b735e34095037f10978ce784
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less
@@ -0,0 +1,61 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-modal-popup__width: 800px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .field-tooltip {
+                .field-tooltip-content {
+                    &:extend(.abs-checkout-tooltip-content-position-top all);
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .form-shipping-address {
+                .css(max-width, @checkout-shipping-address__max-width);
+            }
+            .modal-footer {
+                .action-save-address {
+                    float: right;
+                    margin: 0 0 0 @indent__s;
+                }
+                .action-hide-popup {
+                    &:extend(.abs-action-button-as-link all);
+                }
+            }
+        }
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .modal-inner-wrap {
+                .css(margin-left, -(@checkout-modal-popup__width/2));
+                .css(width, @checkout-modal-popup__width);
+                left: 50%;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less
new file mode 100644
index 0000000000000000000000000000000000000000..0cc46910745bc2c366c049f1fa689ca0c6a7c0e5
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less
@@ -0,0 +1,171 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-summary__background-color: @color-white-smoke;
+@checkout-summary__padding: 22px @indent__l;
+
+@checkout-summary-title__margin: @indent__s;
+@checkout-summary-mark-value__color: @color-gray60;
+
+@checkout-summary-items__max-height: 370px;
+@checkout-summary-items__padding: 15px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Order Summary
+    //  ---------------------------------------------
+
+    .opc-block-summary {
+        &:extend(.abs-add-box-sizing all);
+        .css(background, @checkout-summary__background-color);
+        .css(padding, @checkout-summary__padding);
+        margin: 0 0 @indent__base;
+
+        > .title {
+            &:extend(.abs-checkout-title all);
+            display: block;
+        }
+
+        //  Totals table
+        .table-totals {
+            &:extend(.abs-sidebar-totals all);
+        }
+
+        .mark {
+            .value {
+                .css(color, @checkout-summary-mark-value__color);
+                display: block;
+            }
+        }
+
+        .grand.incl {
+            & + .grand.excl {
+                .mark,
+                .amount {
+                    border-top: 0;
+                    .font-size(14);
+                    padding-top: 0;
+                    strong {
+                        font-weight: @font-weight__regular;
+                    }
+                }
+            }
+        }
+
+        .not-calculated {
+            font-style: italic;
+        }
+
+        //
+        //  Items list
+        //  ---------------------------------------------
+
+        //  Block title
+        .items-in-cart {
+            > .title {
+                border-bottom: @border-width__base solid @border-color__base;
+                .css(padding, @indent__s @indent__xl @indent__s 0);
+                cursor: pointer;
+                .icon-font(
+                @icon-down,
+                @_icon-font-size: 30px,
+                @_icon-font-line-height: 12px,
+                @_icon-font-text-hide: true,
+                @_icon-font-margin: 3px 0 0,
+                @_icon-font-position: after,
+                @_icon-font-display: block
+                );
+                margin-bottom: 0;
+                position: relative;
+                &:after {
+                    position: absolute;
+                    right: 0;
+                    top: @indent__s;
+                }
+                strong {
+                    .font-size(18);
+                    font-weight: @font-weight__light;
+                    margin: 0;
+                }
+            }
+            &.active {
+                > .title {
+                    .icon-font-symbol(
+                    @_icon-font-content: @icon-up,
+                    @_icon-font-position: after
+                    );
+                }
+            }
+            .product {
+                position: relative;
+            }
+        }
+
+        //  Cart items
+        .minicart-items-wrapper {
+            .css(margin, 0 -(@checkout-summary-items__padding) 0 0);
+            .css(max-height, @checkout-summary-items__max-height);
+            .css(padding, @checkout-summary-items__padding @checkout-summary-items__padding 0 0);
+            border: 0;
+        }
+        .column.main & {
+            .product-item {
+                margin: 0;
+                padding-left: 0;
+            }
+        }
+        .product-item {
+            .product-item-inner {
+                display: table;
+                margin: 0 0 @indent__s;
+                width: 100%;
+            }
+            .product-item-name-block {
+                display: table-cell;
+                padding-right: @indent__xs;
+                text-align: left;
+            }
+            .subtotal {
+                display: table-cell;
+                text-align: right;
+            }
+            .price {
+                .font-size(16);
+                font-weight: @font-weight__regular;
+            }
+            .price-including-tax {
+                & + .price-excluding-tax {
+                    margin: 0;
+                    .price {
+                        .font-size(10);
+                    }
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-summary-wrapper {
+        .modal-header {
+            .action-close {
+                display: none;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less
new file mode 100644
index 0000000000000000000000000000000000000000..c9741c735bbf296c192f285242f05704190b1515
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less
@@ -0,0 +1,139 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-payment-option-title__border: @checkout-payment-method-title__border;
+@checkout-payment-option-title__color: @link__color;
+@checkout-payment-option-title__padding: @checkout-payment-method-title__padding;
+@checkout-payment-option-title-mobile__padding: @checkout-payment-method-title-mobile__padding;
+
+@checkout-payment-option-title-icon__font-size: 32px;
+@checkout-payment-option-title-icon__line-height: 16px;
+@checkout-payment-option-title-icon__margin: 0;
+@checkout-payment-option-title-icon__color: @minicart-icons-color;
+@checkout-payment-option-title-icon__hover__color: @primary__color;
+
+@checkout-payment-option-content__padding__xl: @checkout-payment-method-content__padding__xl;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-payment-method {
+        .payment-option {
+            &._active {
+                .payment-option-title {
+                    .action-toggle {
+                        &:after {
+                            content: @icon-up;
+                        }
+                    }
+                }
+            }
+            &._collapsible {
+                .payment-option-title {
+                    cursor: pointer;
+                }
+                .payment-option-content {
+                    display: none;
+                }
+            }
+        }
+
+        .payment-option-title {
+            .css(border-top, @checkout-payment-option-title__border);
+            .css(padding, @checkout-payment-option-title__padding 0);
+
+            .action-toggle {
+                .css(color, @checkout-payment-option-title__color);
+                .icon-font(
+                    @icon-down,
+                    @_icon-font-size: @checkout-payment-option-title-icon__font-size,
+                    @_icon-font-line-height: @checkout-payment-option-title-icon__line-height,
+                    @_icon-font-color: @checkout-payment-option-title-icon__color,
+                    @_icon-font-color-hover: @checkout-payment-option-title-icon__hover__color,
+                    @_icon-font-color-active: @checkout-payment-option-title-icon__color,
+                    @_icon-font-margin: @checkout-payment-option-title-icon__margin,
+                    @_icon-font-position: after
+                );
+            }
+        }
+
+        .payment-option-content {
+            .css(padding, 0 0 @indent__base @checkout-payment-option-content__padding__xl);
+        }
+
+        .payment-option-inner {
+            margin: 0 0 @indent__base;
+        }
+
+        .credit-card-types {
+            padding: 0;
+            .item {
+                display: inline-block;
+                list-style: none;
+                margin: 0 @indent__xs 0 0;
+                &._active {
+                    font-weight: @font-weight__bold;
+                    img {
+                        -webkit-filter: grayscale(0%);
+                        filter: grayscale(0%);
+                        filter: none;
+                    }
+                }
+            }
+            img {
+                -webkit-filter: grayscale(100%); // For Webkit browsers
+                -webkit-transition: all .6s ease; // Fade to color for Chrome and Safari
+                filter: grayscale(100%);
+                filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale"); // Firefox 10+, Firefox on Android
+                filter: gray; // For IE 6 - 9
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
+    .checkout-payment-method {
+        .payment-option {
+            .css(margin, 0 -(@checkout-payment-option-title-mobile__padding));
+
+            .payment-option-title {
+                .css(padding, @checkout-payment-option-title-mobile__padding)
+            }
+
+            .payment-option-content {
+                .css(padding, 0 @checkout-payment-option-title-mobile__padding @indent__base);
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-payment-method {
+        .payment-option-title {
+            .css(padding-left, @checkout-payment-option-content__padding__xl);
+        }
+        .payment-option-content {
+            .payment-option-inner {
+                + .actions-toolbar {
+                    margin-left: 0;
+                }
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less
new file mode 100644
index 0000000000000000000000000000000000000000..b880027e5493df788807dbbeabfaa94d0c36fb0b
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less
@@ -0,0 +1,198 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-payment-method-title__border: @checkout-shipping-method__border;
+@checkout-payment-method-title__padding: @checkout-shipping-method__padding;
+@checkout-payment-method-title-mobile__padding: 15px;
+
+@checkout-payment-method-content__padding__xl: 22px;
+
+@checkout-billing-address-details__line-height: 27px;
+@checkout-billing-address-details__padding: 0 0 0 23px;
+@checkout-billing-address-form__max-width: @checkout-shipping-address__max-width;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-payment-method {
+        .step-title {
+            margin-bottom: 0;
+        }
+        .payment-method {
+            &:first-child {
+                .payment-method-title {
+                    border-top: 0;
+                }
+            }
+            &._active {
+                .payment-method-content {
+                    display: block;
+                }
+            }
+            .action {
+                &.primary {
+                    &:extend(.abs-button-l all);
+                }
+            }
+        }
+
+        .payment-method-title {
+            .css(border-top, @checkout-payment-method-title__border);
+            .css(padding, @checkout-payment-method-title__padding 0);
+            margin: 0;
+
+            .payment-icon {
+                display: inline-block;
+                margin-right: @indent__xs;
+                vertical-align: middle;
+            }
+
+            .action-help {
+                display: inline-block;
+                margin-left: @indent__xs;
+            }
+        }
+
+        .payment-method-content {
+            display: none;
+            .css(padding, 0 0 @indent__base @checkout-payment-method-content__padding__xl);
+            .fieldset {
+                &:not(:last-child) {
+                    margin: 0 0 @indent__base;
+                }
+                > .field {
+                    margin: 0 0 @indent__base;
+                }
+            }
+        }
+
+        .field-select-billing,
+        .billing-address-form {
+            .css(max-width, @checkout-billing-address-form__max-width);
+        }
+
+        .billing-address-same-as-shipping-block {
+            margin: 0 0 @indent__s;
+        }
+
+        .payment-method-billing-address {
+            margin: 0 0 @indent__base;
+
+            .primary {
+                .action-update {
+                    margin-right: 0;
+                }
+            }
+
+            .action-cancel {
+                &:extend(.abs-action-button-as-link all);
+            }
+
+            .billing-address-details {
+                .css(line-height, @checkout-billing-address-details__line-height);
+                .css(padding, @checkout-billing-address-details__padding);
+
+                .action-edit-address {
+                    &:extend(.abs-action-button-as-link all);
+                }
+            }
+        }
+
+        .payment-method-note {
+            & + .payment-method-billing-address {
+                margin-top: @indent__base;
+            }
+        }
+
+        .field-select-billing {
+            > .label {
+                &:extend(.abs-visually-hidden all);
+            }
+        }
+        .payment-method-iframe {
+            background-color: transparent;
+            display: none;
+            width: 100%;
+        }
+        .no-payments-block {
+            margin: @indent__base 0;
+        }
+        .ccard {
+            .legend {
+                &:extend(.abs-visually-hidden all);
+            }
+            .year {
+                padding-left: @indent__l;
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
+    .checkout-payment-method {
+        .payment-methods {
+            .css(margin, 0 -(@checkout-payment-method-title-mobile__padding));
+        }
+
+        .payment-method-title {
+            .css(padding, @checkout-payment-method-title-mobile__padding)
+        }
+
+        .payment-method-content {
+            .css(padding, 0 @checkout-payment-method-title-mobile__padding @indent__base);
+        }
+
+        .payment-method-billing-address {
+            .action-cancel {
+                margin-top: @indent__s;
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-payment-method {
+        .payment-methods {
+            .actions-toolbar {
+                .primary {
+                    float: right;
+                    margin: 0;
+                }
+            }
+        }
+        .fieldset {
+            > .field-select-billing {
+                > .control {
+                    float: none;
+                    width: 100%;
+                }
+            }
+        }
+    }
+    .payment-method-billing-address {
+        .action-update {
+            float: right;
+        }
+        .actions-toolbar {
+            .action-cancel {
+                margin: 6px @indent__base 0 0;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less
new file mode 100644
index 0000000000000000000000000000000000000000..386889c75d410cd854fbced42f136d0ce4bb0dd8
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less
@@ -0,0 +1,169 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-progress-bar__font-size: 18px;
+@checkout-progress-bar__font-weight: @font-weight__light;
+@checkout-progress-bar__margin: @indent__base;
+
+@checkout-progress-bar-item__background-color: @color-gray-middle1;
+@checkout-progress-bar-item__border-radius: 6px;
+@checkout-progress-bar-item__color: @primary__color;
+@checkout-progress-bar-item__margin: @indent__s;
+@checkout-progress-bar-item__width: 185px;
+@checkout-progress-bar-item__active__background-color: @color-orange-red1;
+@checkout-progress-bar-item__complete__color: @link__color;
+
+@checkout-progress-bar-item-element__height: @checkout-progress-bar-item-element__width;
+@checkout-progress-bar-item-element__width: 38px;
+
+@checkout-progress-bar-item-element-inner__background-color: @page__background-color;
+@checkout-progress-bar-item-element-inner__color: @checkout-progress-bar-item__color;
+@checkout-progress-bar-item-element-inner__height: @checkout-progress-bar-item-element-inner__width;
+@checkout-progress-bar-item-element-inner__width: @checkout-progress-bar-item-element__width - (@checkout-progress-bar-item-element-outer-radius__width * 2);
+@checkout-progress-bar-item-element-inner__active__content: @icon-checkmark;
+@checkout-progress-bar-item-element-inner__active__font-size: 28px;
+@checkout-progress-bar-item-element-inner__active__line-height: 1;
+
+@checkout-progress-bar-item-element-outer-radius__width: 6px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Checkout Progress Bar
+    //  ---------------------------------------------
+
+    .opc-progress-bar {
+        &:extend(.abs-reset-list all);
+        .css(margin, 0 0 @checkout-progress-bar__margin);
+        counter-reset: i;
+        font-size: 0;
+    }
+    .opc-progress-bar-item {
+        .css(margin, 0 0 @checkout-progress-bar-item__margin);
+        display: inline-block;
+        position: relative;
+        text-align: center;
+        vertical-align: top;
+        width: 50%;
+
+        &:before { // Horizontal line
+            .css(background, @checkout-progress-bar-item__background-color);
+            .css(top, @checkout-progress-bar-item-element__width/2);
+            content: '';
+            height: 7px;
+            left: 0;
+            position: absolute;
+            width: 100%;
+        }
+
+        &:first-child {
+            &:before {
+                .css(border-radius, @checkout-progress-bar-item__border-radius 0 0 @checkout-progress-bar-item__border-radius);
+            }
+        }
+
+        &:last-child {
+            &:before {
+                .css(border-radius, 0 @checkout-progress-bar-item__border-radius @checkout-progress-bar-item__border-radius 0);
+            }
+        }
+
+        > span {
+            display: inline-block;
+            padding-top: 45px;
+            width: 100%;
+            word-wrap: break-word;
+
+            .typography(
+            @_color: @checkout-progress-bar-item__background-color,
+            @_font-family: false,
+            @_font-size: @checkout-progress-bar__font-size,
+            @_font-style: false,
+            @_font-weight: @checkout-progress-bar__font-weight,
+            @_line-height: false
+            );
+
+            &:before, // Item element
+            &:after {
+                .css(background, @checkout-progress-bar-item__background-color);
+                .css(height, @checkout-progress-bar-item-element__height);
+                .css(margin-left, -(@checkout-progress-bar-item-element__width/2));
+                .css(width, @checkout-progress-bar-item-element__width);
+                border-radius: 50%;
+                content: '';
+                left: 50%;
+                position: absolute;
+                top: 0;
+            }
+
+            &:after { // Item element inner
+                .css(background, @checkout-progress-bar-item-element-inner__background-color);
+                .css(height, @checkout-progress-bar-item-element-inner__height);
+                .css(margin-left, -(@checkout-progress-bar-item-element-inner__width/2));
+                .css(top, @checkout-progress-bar-item-element-outer-radius__width);
+                .css(width, @checkout-progress-bar-item-element-inner__width);
+                content: counter(i);
+                counter-increment: i;
+                .typography(
+                @_color: @checkout-progress-bar-item-element-inner__color,
+                @_font-family: false,
+                @_font-size: @checkout-progress-bar__font-size,
+                @_font-style: false,
+                @_font-weight: @font-weight__semibold,
+                @_line-height: false
+                );
+            }
+        }
+
+        &._active {
+            &:before {
+                background: @checkout-progress-bar-item__active__background-color;
+            }
+            > span {
+                .css(color, @checkout-progress-bar-item__color);
+                &:before {
+                    .css(background, @checkout-progress-bar-item__active__background-color);
+                }
+                &:after {
+                    .css(content, @checkout-progress-bar-item-element-inner__active__content);
+                    .css(font-family, @icons__font-name);
+                    .css(line-height, @checkout-progress-bar-item-element-inner__active__line-height);
+                    .font-size(@checkout-progress-bar-item-element-inner__active__font-size);
+                }
+            }
+        }
+
+        &._complete {
+            cursor: pointer;
+            > span {
+                .css(color, @checkout-progress-bar-item__color);
+                &:after {
+                    .css(content, @checkout-progress-bar-item-element-inner__active__content);
+                    .css(font-family, @icons__font-name);
+                    .css(line-height, @checkout-progress-bar-item-element-inner__active__line-height);
+                    .font-size(@checkout-progress-bar-item-element-inner__active__font-size);
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-progress-bar-item {
+        .css(width, @checkout-progress-bar-item__width);
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less
new file mode 100644
index 0000000000000000000000000000000000000000..adb28706810e8c0f90b112c38936cfe1fc5a9a73
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less
@@ -0,0 +1,67 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-shipping-policy-action__color: @link__color;
+@checkout-shipping-policy-tooltip__width: 420px;
+@checkout-shipping-policy-tooltip-mobile__width: 300px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-shipping-method {
+        position: relative;
+    }
+
+    .shipping-policy-block {
+        &.field-tooltip {
+            top: 12px;
+
+            .field-tooltip-action {
+                .css(color, @checkout-shipping-policy-action__color);
+                cursor: pointer;
+                &:before {
+                   display: none;
+                }
+            }
+
+            .field-tooltip-content {
+                &:extend(.abs-add-box-sizing all);
+                &:extend(.abs-checkout-tooltip-content-position-top all);
+                .css(width, @checkout-shipping-policy-tooltip__width);
+                top: @indent__l;
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .shipping-policy-block {
+        &.field-tooltip {
+            margin-bottom: @indent__base;
+            position: relative;
+            right: auto;
+            top: auto;
+
+            .field-tooltip-content {
+                .css(width, @checkout-shipping-policy-tooltip-mobile__width);
+                right: auto;
+                &:before,
+                &:after {
+                    right: auto;
+                }
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less
new file mode 100644
index 0000000000000000000000000000000000000000..3b052c7401101077be3125a7b522953a515acb3b
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less
@@ -0,0 +1,321 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-shipping-address__max-width: 600px;
+
+@checkout-shipping-item-icon__background-color: @checkout-shipping-item__active__border-color;
+@checkout-shipping-item-icon__color: @color-white;
+@checkout-shipping-item-icon__content: @icon-checkmark;
+
+@checkout-shipping-item__border: 2px solid transparent;
+@checkout-shipping-item__line-height: 30px;
+@checkout-shipping-item__margin: 0 0 @indent__base;
+@checkout-shipping-item__padding: @indent__base (@indent__l + 5px) @indent__base @indent__base;
+@checkout-shipping-item__transition: .3s border-color;
+@checkout-shipping-item__width: 100%/3;
+@checkout-shipping-item-tablet__width: 100%/2;
+@checkout-shipping-item-mobile__width: 100%;
+@checkout-shipping-item__active__border-color: @color-orange-red1;
+
+@checkout-shipping-item-icon__selected__height: 27px;
+@checkout-shipping-item-icon__selected__width: 29px;
+
+@checkout-shipping-item-mobile__padding: 0 0 15px;
+@checkout-shipping-item-mobile__margin: @checkout-shipping-item-mobile__padding;
+@checkout-shipping-item-mobile__active__padding: 15px (@indent__l + 5px) 15px 18px;
+
+@checkout-shipping-item-before__border-color: @color-gray80;
+@checkout-shipping-item-before__height: calc(~"100% - 20px");
+
+@checkout-shipping-method__border: @checkout-step-title__border;
+@checkout-shipping-method__padding: @indent__base;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    .opc-wrapper {
+
+        //
+        //  Shipping Address
+        //  ---------------------------------------------
+
+        .form-login,
+        .form-shipping-address {
+            margin-bottom: @indent__base;
+
+            .fieldset {
+                .field {
+                    .label {
+                        font-weight: @font-weight__regular;
+                    }
+                }
+                .note {
+                    font-size: @font-size__base;
+                    margin-top: @indent__s;
+                }
+            }
+        }
+
+        .shipping-address-items {
+            font-size: 0;
+        }
+
+        .shipping-address-item {
+            &:extend(.abs-add-box-sizing all);
+            .css(border, @checkout-shipping-item__border);
+            .css(line-height, @checkout-shipping-item__line-height);
+            .css(margin, @checkout-shipping-item__margin);
+            .css(padding, @checkout-shipping-item__padding);
+            .css(transition, @checkout-shipping-item__transition);
+            .css(width, @checkout-shipping-item-tablet__width);
+            display: inline-block;
+            font-size: @font-size__base;
+            position: relative;
+            vertical-align: top;
+            word-wrap: break-word;
+
+            &.selected-item {
+                .css(border-color, @checkout-shipping-item__active__border-color);
+
+                &:after {
+                    .css(background, @checkout-shipping-item-icon__background-color);
+                    .css(color, @checkout-shipping-item-icon__color);
+                    .css(content, @checkout-shipping-item-icon__content);
+                    .css(font-family, @icons__font-name);
+                    .css(height, @checkout-shipping-item-icon__selected__height);
+                    .css(width, @checkout-shipping-item-icon__selected__width);
+                    font-size: 27px;
+                    line-height: 21px;
+                    padding-top: 2px;
+                    position: absolute;
+                    right: 0;
+                    text-align: center;
+                    top: 0;
+                }
+
+                .action-select-shipping-item {
+                    &:extend(.abs-no-display-s all);
+                    visibility: hidden;
+                }
+            }
+        }
+
+        .field {
+            &.addresses {
+                &:extend(.abs-add-clearfix all);
+            }
+        }
+
+        .action-show-popup {
+            margin: 0 0 @indent__base;
+            > span {
+                &:before {
+                    content: '+';
+                    padding-right: @indent__xs;
+                }
+            }
+        }
+
+        .action-select-shipping-item {
+            float: right;
+            margin: @indent__base 0 0;
+        }
+
+        .edit-address-link {
+            &:extend(.abs-action-button-as-link all);
+            display: block;
+            float: left;
+            margin: 26px 5px 0 0;
+        }
+    }
+
+    //
+    //  Shipping Methods
+    //  ---------------------------------------------
+
+    .checkout-shipping-method {
+        .step-title {
+            margin-bottom: 0;
+        }
+        .no-quotes-block {
+            margin: @indent__base 0;
+        }
+    }
+
+    .methods-shipping {
+        .actions-toolbar {
+            .action {
+                &.primary {
+                    &:extend(.abs-button-l all);
+                    margin: @indent__base 0 0;
+                }
+            }
+        }
+    }
+
+    .table-checkout-shipping-method {
+        thead {
+            th {
+                display: none;
+            }
+        }
+        tbody {
+            td {
+                .css(border-top, @checkout-shipping-method__border);
+                .css(padding-bottom, @checkout-shipping-method__padding);
+                .css(padding-top, @checkout-shipping-method__padding);
+                &:first-child {
+                    padding-left: 0;
+                    padding-right: 0;
+                    width: 20px;
+                }
+            }
+
+            tr {
+                &:first-child {
+                    td {
+                        border-top: none;
+                    }
+                }
+            }
+            .row-error {
+                td {
+                    border-top: none;
+                    padding-bottom: @indent__s;
+                    padding-top: 0;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .opc-wrapper {
+        .form-login {
+            .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color);
+            .css(margin, @checkout-shipping-item-mobile__padding);
+            .css(padding, @checkout-shipping-item-mobile__padding);
+        }
+        .shipping-address-item {
+            .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color);
+            .css(margin, @checkout-shipping-item-mobile__margin);
+            .css(padding, @checkout-shipping-item-mobile__padding);
+            width: 100%;
+            &.selected-item {
+                .css(padding, @checkout-shipping-item-mobile__active__padding);
+                border-bottom-width: 2px;
+
+                .edit-address-link {
+                    .css(right, @checkout-shipping-item-icon__selected__width + @indent__s);
+                }
+            }
+        }
+
+        .action-select-shipping-item {
+            float: none;
+            margin-top: @indent__s;
+            width: 100%;
+        }
+
+        .action-show-popup {
+            width: 100%;
+        }
+
+        .edit-address-link {
+            .icon-font(
+                @icon-settings,
+                @_icon-font-size: 28px,
+                @_icon-font-line-height: 28px,
+                @_icon-font-text-hide: true,
+                @_icon-font-color: @color-gray19,
+                @_icon-font-color-hover: @color-gray19,
+                @_icon-font-color-active: @color-gray19
+            );
+            margin: 0;
+            position: absolute;
+            right: 0;
+            top: 1px;
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-shipping-method {
+        .actions-toolbar {
+            > .primary {
+                float: right;
+            }
+            .action {
+                &.primary {
+                    margin: 0;
+                }
+            }
+        }
+    }
+
+    .opc-wrapper {
+        .form-login,
+        .form-shipping-address {
+            .css(max-width, @checkout-shipping-address__max-width);
+        }
+    }
+    .table-checkout-shipping-method {
+        width: auto;
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {
+    .opc-wrapper {
+        .shipping-address-item {
+            .css(width, @checkout-shipping-item__width);
+
+            &:before {
+                .css(background, @checkout-shipping-item-before__border-color);
+                .css(height, @checkout-shipping-item-before__height);
+                content: '';
+                left: 0;
+                position: absolute;
+                top: 0;
+                width: 1px;
+            }
+
+            &:nth-child(3n+1) {
+                &:before {
+                    display: none;
+                }
+            }
+
+            &.selected-item {
+                &:before {
+                    display: none;
+                }
+
+                + .shipping-address-item {
+                    &:before {
+                        display: none;
+                    }
+                }
+            }
+        }
+    }
+    .table-checkout-shipping-method {
+        min-width: 500px;
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less
new file mode 100644
index 0000000000000000000000000000000000000000..ed940f5fd3c4b45ee959dbfa48335ae02c642a7c
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less
@@ -0,0 +1,69 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-sidebar-shipping-information__padding: @indent__l;
+@checkout-sidebar-shipping-information__line-height: @checkout-billing-address-details__line-height;
+
+@checkout-sidebar-shipping-information-edit-icon__color: @minicart-icons-color;
+@checkout-sidebar-shipping-information-edit-icon__content: @icon-settings;
+@checkout-sidebar-shipping-information-edit-icon__font-size: 28px;
+@checkout-sidebar-shipping-information-edit-icon__line-height: 28px;
+@checkout-sidebar-shipping-information-edit-icon__top: 2px;
+@checkout-sidebar-shipping-information-edit-icon__hover__color: @primary__color;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Shipping Information
+    //  ---------------------------------------------
+
+    .opc-block-shipping-information {
+        .css(padding, 0 @checkout-sidebar-shipping-information__padding);
+
+        .shipping-information-title {
+            &:extend(.abs-checkout-title all);
+            .css(border-bottom, @checkout-step-title__border);
+            margin: 0 0 @indent__base;
+            position: relative;
+
+            .action-edit {
+                &:extend(.abs-action-button-as-link all);
+                .css(top, @checkout-sidebar-shipping-information-edit-icon__top);
+                .icon-font(
+                    @checkout-sidebar-shipping-information-edit-icon__content,
+                    @_icon-font-size: @checkout-sidebar-shipping-information-edit-icon__font-size,
+                    @_icon-font-line-height: @checkout-sidebar-shipping-information-edit-icon__line-height,
+                    @_icon-font-text-hide: true,
+                    @_icon-font-color: @checkout-sidebar-shipping-information-edit-icon__color,
+                    @_icon-font-color-hover: @checkout-sidebar-shipping-information-edit-icon__hover__color,
+                    @_icon-font-color-active: @checkout-sidebar-shipping-information-edit-icon__color
+                );
+                margin: 0;
+                position: absolute;
+                right: 0;
+            }
+        }
+
+        .shipping-information-content {
+            .css(line-height, @checkout-sidebar-shipping-information__line-height);
+            .actions-toolbar {
+                margin-left: 0;
+            }
+        }
+
+        .ship-to,
+        .ship-via {
+            margin: 0 0 @indent__base;
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less
new file mode 100644
index 0000000000000000000000000000000000000000..83934eaf6aab5185021cf59db52d2ea4f7c69c9a
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less
@@ -0,0 +1,23 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-sidebar__margin: @indent__base;
+@checkout-sidebar__margin__xl: 46px;
+@checkout-sidebar__columns: 4;
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-sidebar {
+        .css(margin, @checkout-sidebar__margin__xl 0 @checkout-sidebar__margin);
+        .layout-column(2, 2, @checkout-sidebar__columns);
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less
new file mode 100644
index 0000000000000000000000000000000000000000..d867cc3387355f400f35932bbad34242d21c4c06
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less
@@ -0,0 +1,137 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-tooltip__hover__z-index: @tooltip__z-index;
+@checkout-tooltip-breakpoint__screen-m: @modal-popup-breakpoint-screen__m;
+
+@checkout-tooltip-icon-arrow__font-size: 10px;
+@checkout-tooltip-icon-arrow__left: -( @checkout-tooltip-content__padding + @checkout-tooltip-icon-arrow__font-size - @checkout-tooltip-content__border-width);
+
+@checkout-tooltip-icon__color: @color-gray-light2;
+@checkout-tooltip-icon__content: @icon-help;
+@checkout-tooltip-icon__font-size: 24px;
+@checkout-tooltip-icon__hover__color: @primary__color;
+
+@checkout-tooltip-content__background-color: @color-gray-light01;
+@checkout-tooltip-content__border-color: @color-gray60;
+@checkout-tooltip-content__border-width: 1px;
+@checkout-tooltip-content__font-size: @font-size__base;
+@checkout-tooltip-content__padding: 12px;
+@checkout-tooltip-content__width: 270px;
+@checkout-tooltip-content__active__border-color: darken(@checkout-tooltip-content__border-color, 20%);
+
+@checkout-tooltip-content-mobile-popup__width: 200px;
+@checkout-tooltip-content-mobile__right: -(@indent__s);
+@checkout-tooltip-content-mobile__top: 30px + @checkout-tooltip-icon-arrow__font-size;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    .field-tooltip {
+        position: absolute;
+        right: 0;
+        top: 1px;
+
+        &:hover {
+            .css(z-index, @checkout-tooltip__hover__z-index);
+            cursor: pointer;
+            .field-tooltip-content {
+                display: block;
+            }
+            .field-tooltip-action {
+                &:before {
+                    .css(color, @checkout-tooltip-icon__hover__color);
+                }
+            }
+        }
+
+        .field-tooltip-action {
+            .icon-font(
+            @checkout-tooltip-icon__content,
+            @_icon-font-size: @checkout-tooltip-icon__font-size,
+            @_icon-font-text-hide: true,
+            @_icon-font-color: @checkout-tooltip-icon__color,
+            @_icon-font-color-hover: @checkout-tooltip-icon__hover__color,
+            @_icon-font-color-active: false
+            );
+            &:focus {
+                &:before {
+                    .css(color, @checkout-tooltip-icon__hover__color);
+                }
+                + .field-tooltip-content {
+                    display: block;
+                }
+            }
+        }
+
+        .field-tooltip-content {
+            .css(background, @checkout-tooltip-content__background-color);
+            .css(border, @checkout-tooltip-content__border-width solid @checkout-tooltip-content__border-color);
+            .css(border-radius, @checkout-tooltip-content__border-width);
+            .css(font-size, @checkout-tooltip-content__font-size);
+            .css(padding, @checkout-tooltip-content__padding);
+            .css(width, @checkout-tooltip-content__width);
+            display: none;
+            left: 38px;
+            position: absolute;
+            text-transform: none;
+            top: -9px;
+            word-wrap: break-word;
+            z-index: 2;
+
+            &:before,
+            &:after {
+                .arrow(
+                @_position: left,
+                @_size: @checkout-tooltip-icon-arrow__font-size,
+                @_color: @checkout-tooltip-content__background-color
+                );
+                .css(left, @checkout-tooltip-icon-arrow__left);
+                .css(top, @checkout-tooltip-content__padding);
+                content: '';
+                display: block;
+                position: absolute;
+                z-index: 3;
+            }
+            &:before {
+                .css(border-right-color, @checkout-tooltip-content__active__border-color);
+            }
+            &:after {
+                .css(border-right-color, @checkout-tooltip-content__background-color);
+                width: 1px;
+                z-index: 4;
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
+    .modal-popup {
+        .field-tooltip {
+            .field-tooltip-content {
+                .css(width, @checkout-tooltip-content-mobile-popup__width);
+            }
+        }
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @checkout-tooltip-breakpoint__screen-m) {
+    .field-tooltip {
+        .field-tooltip-content {
+            &:extend(.abs-checkout-tooltip-content-position-top-mobile all);
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less
new file mode 100644
index 0000000000000000000000000000000000000000..8361a32c5e8f3a20e2278ab8896b015237ade8c0
--- /dev/null
+++ b/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less
@@ -0,0 +1,21 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .opc-wrapper {
+        .form-discount {
+            max-width: 500px;
+            .field {
+                .label {
+                    &:extend(.abs-visually-hidden all);
+                }
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/web/css/_styles.less b/app/design/frontend/Magento/blank/web/css/_styles.less
index e1f7113c61eafb29ebc4494b82ab2269961c86f9..75ff8775d8c8a10a656cc55c1d0bfd163bb4f800 100644
--- a/app/design/frontend/Magento/blank/web/css/_styles.less
+++ b/app/design/frontend/Magento/blank/web/css/_styles.less
@@ -5,3 +5,4 @@
 
 @import 'source/lib/_lib.less'; // Global lib
 @import 'source/_sources.less'; // Theme styles
+@import 'source/_components.less'; // Components styles (modal/sliding panel)
diff --git a/app/design/frontend/Magento/blank/web/css/source/_components.less b/app/design/frontend/Magento/blank/web/css/source/_components.less
new file mode 100644
index 0000000000000000000000000000000000000000..9f6db89c38d126d254ae3e4423ed7fccf8d3e1ed
--- /dev/null
+++ b/app/design/frontend/Magento/blank/web/css/source/_components.less
@@ -0,0 +1,11 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Components
+//  _____________________________________________
+
+@import 'components/_modals.less'; // from lib
+@import 'components/_modals_extend.less'; // local
diff --git a/app/design/frontend/Magento/blank/web/css/source/_extends.less b/app/design/frontend/Magento/blank/web/css/source/_extends.less
index df818e7003ce2e68d7f529b31d2af5e2f82e6943..19705339dae3c4f0430aac361f16a2952ef1350c 100644
--- a/app/design/frontend/Magento/blank/web/css/source/_extends.less
+++ b/app/design/frontend/Magento/blank/web/css/source/_extends.less
@@ -507,6 +507,12 @@
     }
 }
 
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .abs-add-box-sizing-desktop-m {
+        @abs-add-box-sizing();
+    }
+}
+
 //
 //  Revert field type
 //  ---------------------------------------------
@@ -1022,9 +1028,176 @@
 }
 
 //
-//    Form Field Date Input
-//--------------------------------------
+//  Form Field Date Input
+//  ---------------------------------------------
+
 .abs-field-date-input {
-    margin-right: @indent__s;
+    .css(margin-right, @indent__s);
     width: calc(~"100% - (@{icon-calendar__font-size} + @{indent__s})");
 }
+
+//
+//  Form Field Tooltip
+//  ---------------------------------------------
+
+.abs-field-tooltip {
+    &:extend(.abs-add-box-sizing all);
+    position: relative;
+    input {
+        .css(margin-right, @indent__s);
+        width: calc(~"100% - (@{checkout-tooltip-icon__font-size} + @{indent__s} + @{indent__xs})");
+        &:focus {
+            + .field-tooltip {
+                .field-tooltip-action {
+                    &:before {
+                        .css(color, @checkout-tooltip-icon__hover__color);
+                    }
+                }
+                .field-tooltip-content {
+                    display: block;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Checkout Tooltip Content (position: top)
+//  ---------------------------------------------
+
+@abs-checkout-tooltip-content-position-top: {
+    .css(right, @checkout-tooltip-content-mobile__right);
+    .css(top, @checkout-tooltip-content-mobile__top);
+    left: auto;
+
+    &:before,
+    &:after {
+        .arrow(
+        @_position: top,
+        @_size: @checkout-tooltip-icon-arrow__font-size,
+        @_color: @checkout-tooltip-content__background-color
+        );
+        .css(margin-top, @checkout-tooltip-icon-arrow__left);
+        .css(right, @indent__s);
+        left: auto;
+        top: 0%;
+    }
+    &:before {
+        .css(border-bottom-color, @checkout-tooltip-content__border-color);
+    }
+    &:after {
+        .css(border-bottom-color, @checkout-tooltip-content__background-color);
+        top: 1px;
+    }
+};
+
+.abs-checkout-tooltip-content-position-top {
+    @abs-checkout-tooltip-content-position-top();
+}
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) {
+    .abs-checkout-tooltip-content-position-top-mobile {
+        @abs-checkout-tooltip-content-position-top();
+    }
+}
+
+//
+//  Checkout title
+//  ---------------------------------------------
+
+.abs-checkout-title {
+    .css(border-bottom, @checkout-step-title__border);
+    .css(padding-bottom, @checkout-step-title__padding);
+    .typography(
+    @_font-size: @checkout-step-title__font-size,
+    @_font-weight: @checkout-step-title__font-weight,
+    @_font-family: false,
+    @_font-style: false,
+    @_line-height: false
+    );
+}
+
+//
+//  Shopping cart sidebar and checkout sidebar totals
+//  ---------------------------------------------
+
+.abs-sidebar-totals {
+    .mark {
+        font-weight: @font-weight__regular;
+        padding-left: 4px;
+        strong {
+            font-weight: @font-weight__regular;
+        }
+    }
+    .amount {
+        padding-right: 4px;
+        text-align: right;
+        strong {
+            font-weight: @font-weight__regular;
+        }
+    }
+    .grand {
+        .mark,
+        .amount {
+            padding-top: @indent__base;
+        }
+        .amount {
+            padding-right: 4px;
+            text-align: right;
+            strong {
+                font-weight: @font-weight__bold;
+            }
+        }
+    }
+    .msrp {
+        margin-bottom: @indent__s;
+    }
+    .totals-tax {
+        &-summary {
+            .mark,
+            .amount {
+                .css(border-top, @border-width__base solid @border-color__base);
+                .css(border-bottom, @border-width__base solid @border-color__base);
+                cursor: pointer;
+            }
+            .amount .price {
+                position: relative;
+                padding-right: @indent__m;
+                .icon-font(
+                @icon-down,
+                @_icon-font-size: 30px,
+                @_icon-font-text-hide: true,
+                @_icon-font-position: after,
+                @_icon-font-display: block
+                );
+                &:after {
+                    position: absolute;
+                    right: -5px;
+                    top: -12px;
+                }
+            }
+            &.expanded {
+                .mark,
+                .amount {
+                    border-bottom: 0;
+                }
+                .amount .price {
+                    .icon-font-symbol(
+                    @_icon-font-content: @icon-up,
+                    @_icon-font-position: after
+                    );
+                }
+            }
+        }
+        &-details {
+            display: none;
+            .css(border-bottom, @border-width__base solid @border-color__base);
+            &.shown {
+                display: table-row;
+            }
+        }
+    }
+    .table-caption {
+        &:extend(.abs-no-display all);
+    }
+}
diff --git a/app/design/frontend/Magento/blank/web/css/source/_loaders.less b/app/design/frontend/Magento/blank/web/css/source/_loaders.less
index 0c608a402d54782d412ab447990f01e045c00e73..576c7b2ca933ec7e365f24e50e12163c6819dfe5 100644
--- a/app/design/frontend/Magento/blank/web/css/source/_loaders.less
+++ b/app/design/frontend/Magento/blank/web/css/source/_loaders.less
@@ -9,25 +9,34 @@
 
 & when (@media-common = true) {
 
-.load.indicator {
-    .loader();
-    position: absolute;
-    > span {
-        display: none;
+    .load.indicator {
+        .loader();
+        position: absolute;
+        > span {
+            display: none;
+        }
     }
-}
 
-.loading-mask {
-    .loading-mask();
-    background: rgba(255, 255, 255, .5);
-    .loader {
-        > img {
-            .loading-mask();
+    .loading-mask {
+        .loading-mask();
+        background: rgba(255, 255, 255, .5);
+        .loader {
+            > img {
+                .loading-mask();
+            }
+            > p {
+                display: none;
+            }
         }
-        > p {
-            display: none;
+    }
+
+    body {
+        > .loading-mask {
+            z-index: @loader-overlay__z-index;
         }
     }
-}
 
+    ._block-content-loading {
+        position: relative;
+    }
 }
diff --git a/app/design/frontend/Magento/blank/web/css/source/_navigation.less b/app/design/frontend/Magento/blank/web/css/source/_navigation.less
index c16516b0e20bd4069c4f9ee32df098ffb00ac623..f1809aeafb167fec419655d62d4f7969d68b8485 100644
--- a/app/design/frontend/Magento/blank/web/css/source/_navigation.less
+++ b/app/design/frontend/Magento/blank/web/css/source/_navigation.less
@@ -149,7 +149,7 @@
         height: 100%;
         width: 100%;
         .page-wrapper {
-            height:100%;
+            height: 100%;
             overflow: hidden;
             position: relative;
             left: 0;
diff --git a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less
new file mode 100644
index 0000000000000000000000000000000000000000..e4b01ecd0df6e5d9a9c0c10e275d6ccc5098efa1
--- /dev/null
+++ b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less
@@ -0,0 +1,166 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Components -> Modals
+//  _____________________________________________
+
+//
+//  Variables
+//  ---------------------------------------------
+
+@modal-title__color: @text__color;
+@modal-title__border: 1px solid @color-gray-light5;
+
+@modal-popup-title__font-size: 26px;
+@modal-popup-title-mobile__font-size: @font-size__base;
+@modal-popup-breakpoint-screen__m: @screen__m + 1;
+
+@modal-slide__first__indent-left: 44px;
+@modal-slide-mobile__background-color: @color-gray-light01;
+@modal-overlay__background-color: fade(@color-gray20, 55%);
+
+@modal-action-close__color: @primary__color;
+@modal-action-close__font-size: 32px;
+@modal-action-close__hover__color: darken(@primary__color, 10%);
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .modal-custom,
+    .modal-popup,
+    .modal-slide {
+        .action-close {
+            .button-reset();
+            .button-icon(
+                @icon-remove,
+                @_icon-font-color: @minicart-icons-color,
+                @_icon-font-size: @modal-action-close__font-size,
+                @_icon-font-line-height: @modal-action-close__font-size,
+                @_icon-font-text-hide: true
+            );
+            position: absolute;
+            right: 0;
+            top: 0;
+            &:hover {
+                &:before {
+                    color: @modal-action-close__hover__color;
+                }
+            }
+        }
+    }
+    .modal-custom {
+        .action-close {
+            .css(margin, @indent__m);
+        }
+    }
+    .modal-popup {
+        .modal-title {
+            .css(border-bottom, @modal-title__border);
+            .css(font-weight, @font-weight__light);
+            .css(padding-bottom, @indent__s);
+            font-size: @modal-popup-title__font-size;
+            margin-bottom: 0;
+            min-height: 1em;
+            word-wrap: break-word;
+        }
+        .action-close {
+            padding: @modal-popup__padding;
+        }
+    }
+
+    .modal-slide {
+        .action-close {
+            padding: @modal-slide-header__padding-vertical @modal-slide__padding;
+        }
+        .page-main-actions {
+            margin-top: @modal-slide-header__padding-vertical;
+            margin-bottom: @modal-slide-header__padding-vertical - (@indent__l/2);
+        }
+    }
+
+    .modals-overlay {
+        .css(background-color, @modal-overlay__background-color);
+        bottom: 0;
+        left: 0;
+        position: fixed;
+        right: 0;
+        top: 0;
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @modal-popup-breakpoint-screen__m) {
+    .modal-popup {
+        &.modal-slide {
+            .modal-inner-wrap[class] {
+                .css(background-color, @modal-slide-mobile__background-color);
+            }
+            &._inner-scroll {
+                &._show {
+                    -webkit-overflow-scrolling: touch;
+                    overflow-y: auto;
+                }
+                .modal-inner-wrap {
+                    height: auto;
+                    min-height: 100%;
+                }
+            }
+        }
+        .modal-title {
+            .css(font-size, @modal-popup-title-mobile__font-size);
+            .css(font-weight, @font-weight__bold);
+        }
+    }
+    .custom-slide {
+        .abs-modal();
+        .abs-modal-slide();
+        &._show {
+            -webkit-overflow-scrolling: touch;
+            overflow-y: auto;
+            overflow-x: hidden;
+        }
+        .modal-inner-wrap {
+            .css(background-color, @modal-slide-mobile__background-color);
+            box-sizing: border-box;
+            height: auto;
+            min-height: 100%;
+        }
+    }
+    body._has-modal-custom {
+        height: 100vh;
+        overflow: hidden;
+        width: 100vw;
+        .modal-custom-overlay {
+            .css(background-color, @modal-overlay__background-color);
+            height: 100vh;
+            left: 0;
+            position: fixed;
+            top: 0;
+            width: 100vw;
+            z-index: @overlay__z-index;
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @modal-popup-breakpoint-screen__m) {
+    .modal-popup {
+        &.modal-slide {
+            .modal-footer {
+                .css(border-top, @modal-title__border);
+                text-align: right;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less
index 9b111f1353784f0f84d6b39f63bd79fc1d246df1..85932830410a8ee3ef47bc3eabf105116270a9cc 100644
--- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less
@@ -5,647 +5,4 @@
 
 @import 'module/_cart.less';
 @import 'module/_minicart.less';
-
-@opc-margin-left: 10%;
-
-//
-//  Common
-//  _____________________________________________
-
-& when (@media-common = true) {
-
-    //
-    //  One Page Checkout
-    //  ---------------------------------------------
-
-    .opc-wrapper:extend(.abs-add-box-sizing all) {
-        .field select {
-            max-width: none;
-        }
-        > .opc:extend(.abs-reset-list all) {
-        }
-        .section {
-            &.allow {
-                .step-title {
-                    cursor: pointer;
-                    .icon-font(
-                    @icon-edit,
-                    @_icon-font-size: 20px,
-                    @_icon-font-display: block,
-                    @_icon-font-position: after
-                    );
-                    &:after {
-                        position: absolute;
-                        right: 18px;
-                        top: 12px;
-                    }
-                }
-                &.active {
-                    .step-title {
-                        cursor: default;
-                    }
-                    .step-title:after {
-                        display: none;
-                    }
-                }
-            }
-            .step-content {
-                display: none;
-            }
-            &.active {
-                .step-title {
-                    .css(color, @primary__color);
-                }
-                .step-content {
-                    display: block;
-                }
-            }
-        }
-        .step {
-            &-title {
-                .css(background, @sidebar__background-color);
-                .css(color, lighten(@primary__color, 40%));
-                margin-bottom: 2px;
-                padding: 13px @indent__m;
-                position: relative;
-                h2 {
-                    .font-size(18);
-                    font-weight: @font-weight__semibold;
-                    margin: 0;
-                }
-                .number {
-                    display: none;
-                }
-            }
-
-            &-content {
-                padding: 35px @indent__m 80px;
-                position: relative;
-                .addresses .control {
-                    margin: @indent__base 0 @indent__l;
-                }
-                .fieldset {
-                    margin-bottom: 0;
-                    &.login {
-                        .form-hasrequired(bottom);
-                        &:after {
-                            margin-top: 35px;
-                            text-align: center;
-                        }
-                    }
-                    .legend.payments-title:extend(.abs-visually-hidden all) {
-                    }
-                }
-                .methods-shipping {
-                    .item-content {
-                        .fieldset {
-                            > .legend:extend(.abs-visually-hidden all) {
-                            }
-                            > .legend + br:extend(.abs-no-display all) {
-                            }
-                            > .field {
-                                margin-bottom: 15px;
-                                &:before {
-                                    display: none;
-                                }
-                                .control {
-                                    display: inline-block;
-                                }
-                            }
-                        }
-                    }
-                }
-                .form {
-                    .form-hasrequired(bottom);
-                    &:after {
-                        text-align: center;
-                    }
-                    > .choice {
-                        margin-top: @form-field__vertical-indent;
-                    }
-                }
-                .form:not(.login),
-                .order-review {
-                    .action.primary:extend(.abs-button-l all) {
-                    }
-                }
-                .actions {
-                    margin-top: @indent__xl;
-                }
-                .field.street {
-                    .field.additional {
-                        .label:extend(.abs-visually-hidden all) {
-                        }
-                    }
-                }
-            }
-
-            .fieldset > .field:last-of-type {
-                margin-bottom: 0;
-            }
-        }
-
-        //
-        //  Customer login
-        //  ---------------------------------------------
-
-        .login-wrapper {
-            .block {
-                .block-title {
-                    margin-bottom: @indent__l;
-                    strong {
-                        .font-size(22);
-                        font-weight: @font-weight__light;
-                        margin: 0;
-                    }
-                }
-                .fieldset.guest {
-                    margin-top: @indent__base;
-                }
-                .field {
-                    &.choice {
-                        margin-bottom: @indent__s;
-                    }
-                    &.note {
-                        margin-bottom: @indent__l;
-                    }
-                }
-            }
-        }
-
-        .opc-payment-additional {
-            margin: 0 0 @indent__s 15px;
-            + .opc-payment {
-                margin: @indent__xl 0 0;
-            }
-        }
-
-        .action.primary.checkout {
-            margin: 0 0 @indent__base;
-        }
-
-        .hidden:extend(.abs-no-display all) {
-        }
-
-        .actions-toolbar {
-            margin: @indent__xl 0 0;
-        }
-
-        .field {
-            &.month {
-                padding-right: @indent__s;
-                .control {
-                    position: relative;
-                    &:after {
-                        color: @primary__color__light;
-                        content: '/';
-                        position: absolute;
-                        right: -9px;
-                        top: @indent__xs;
-                    }
-                }
-            }
-            &.cvv {
-                width: 30%;
-                .control {
-                    position: relative;
-                }
-                .note {
-                    position: absolute;
-                    right: -23px;
-                    top: 0;
-                    &:before {
-                        display: none;
-                    }
-                    > a {
-                        .icon-font(
-                        @_icon-font-content: @icon-help,
-                        @_icon-font-size: 16px,
-                        @_icon-font-color: @primary__color__light,
-                        @_icon-font-color-hover: @primary__color,
-                        @_icon-font-text-hide: true
-                        );
-                    }
-                }
-            }
-        }
-    }
-
-    //
-    //  Shipping methods
-    //  ---------------------------------------------
-
-    .methods-shipping {
-        .item-title:extend(.abs-methods-shipping-title all) {
-        }
-        .item-content:extend(.abs-adjustment-incl-excl-tax all) {
-            margin: 0 0 35px;
-            .field {
-                margin-bottom: 15px;
-                .price {
-                    font-weight: @font-weight__bold;
-                }
-                &.choice {
-                    .control {
-                        float: left;
-                    }
-                    .label {
-                        display: block;
-                        overflow: hidden;
-                    }
-                }
-            }
-        }
-        .price.box {
-            > .price {
-                display: block;
-            }
-            .regular .price,
-            .price .price {
-                font-weight: @font-weight__bold;
-            }
-        }
-        .price-box {
-            margin-bottom: @indent__xs;
-            margin-left: @indent__base;
-            margin-top: @indent__s;
-        }
-    }
-
-    //
-    //  Payment methods
-    //  ---------------------------------------------
-
-    .methods-payment {
-        border-bottom: @border-width__base solid @border-color__base;
-        .item-title {
-            border-top: @border-width__base solid @border-color__base;
-            font-weight: @font-weight__regular;
-            margin: 0;
-            padding: 16px 15px 15px;
-        }
-        .item-content {
-            margin: 0;
-            > .fieldset {
-                padding: 0 @indent__s @indent__xl;
-                &.redirect {
-                    margin: @indent__s 0 @indent__l 37px;
-                    padding: 0;
-                    width: 80%;
-                }
-            }
-        }
-        img {
-            margin-right: @indent__xs;
-            vertical-align: middle;
-        }
-    }
-
-    //
-    //  Order review
-    //  ---------------------------------------------
-    .table-order-review:extend(.abs-product-options-list all) {
-        thead tr:first-child th {
-            padding-top: 0;
-        }
-        .col {
-            &.price,
-            &.qty {
-                text-align: center;
-                white-space: nowrap;
-            }
-            &.price:extend(.abs-incl-excl-tax all),
-            &.subtotal:extend(.abs-incl-excl-tax all) {
-            }
-        }
-        .item-options:extend(.abs-add-clearfix all) {
-            margin: @indent__base 0 0;
-            .price {
-                font-weight: @font-weight__bold;
-            }
-        }
-        .product-item-name:extend(.abs-checkout-product-name all) {
-        }
-        .cart-price:extend(.abs-checkout-cart-price all) {
-        }
-        .grand.totals {
-            .font-size(16);
-            th,
-            td {
-                padding: 0 @indent__s;
-            }
-        }
-    }
-
-    .cart-tax-info + .cart-tax-total,
-    .order-details-items .table-wrapper .cart-tax-info + .cart-tax-total {
-        display: block;
-    }
-
-    //
-    //  Checkout Progress
-    //  ---------------------------------------------
-
-    .opc-block-progress-wrapper {
-        margin-bottom: @indent__l;
-        margin-top: @indent__base;
-    }
-
-    .opc-block-progress:extend(.abs-add-box-sizing all) {
-        display: none;
-        &.order-review-step {
-            display: block;
-        }
-        > .title {
-            .css(background, @sidebar__background-color);
-            .font-size(18);
-            font-weight: @font-weight__light;
-            margin: 0;
-            padding: @indent__s 15px;
-            strong {
-                font-weight: @font-weight__regular;
-            }
-        }
-        > .content {
-            .css(background, @sidebar__background-color);
-            padding: 0 15px;
-            .items {
-                margin: 0;
-            }
-            .item-title {
-                border-top: @border-width__base solid @border-color__base;
-                display: none;
-                margin: 0;
-                padding: 15px 0 7px;
-                &.complete {
-                    display: block;
-                }
-                span {
-                    .font-size(16);
-                    font-weight: @font-weight__semibold;
-                }
-            }
-            .item-content {
-                display: none;
-                margin: 0;
-                overflow: hidden;
-                padding: 0 0 15px;
-                &.complete {
-                    display: block;
-                }
-            }
-            .action {
-                font-weight: @font-weight__regular;
-            }
-            .data.table {
-                font-size: @font-size__s;
-            }
-        }
-        .payment-method {
-            > .title {
-                font-weight: @font-weight__light;
-            }
-            > .content {
-                margin: 0 0 @indent__s;
-                &:last-child {
-                    margin-bottom: 0;
-                }
-            }
-            .items-cards {
-                margin: 0;
-                > .content {
-                    margin: 0;
-                }
-            }
-            .data.table {
-                th {
-                    padding: @indent__xs @indent__s @indent__xs 0;
-                }
-                td {
-                    padding: @indent__xs 0;
-                }
-            }
-        }
-    }
-
-    //
-    //  Checkout Success
-    //  ---------------------------------------------
-
-    .checkout-onepage-success {
-        .page-title-wrapper {
-            .print:extend(.abs-no-display all) {
-            }
-        }
-    }
-
-    .checkout-success {
-        .actions-toolbar {
-            margin-top: 50px;
-        }
-    }
-
-    .checkout-onepage-index {
-        .nav-toggle:extend(.abs-no-display all) {
-        }
-        .logo {
-            margin-left: 0;
-        }
-    }
-}
-
-//
-//  Mobile
-//  _____________________________________________
-
-.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
-    .table-wrapper.order-review-wrapper:extend(.abs-no-border-top all) {
-        .table.table-order-review:extend(.abs-checkout-order-review all) {
-            tbody tr {
-                td {
-                    &:not(:last-child) {
-                        border: none;
-                    }
-                }
-                &:first-child td:first-child {
-                    padding-top: 0;
-                }
-            }
-        }
-
-        .table.table-order-review:not(.totals):not(.cart):not(.table-comparison) tbody > tr > td:last-child {
-            border-bottom: none;
-            border-top: none;
-        }
-    }
-}
-
-//
-//  Desktop
-//  _____________________________________________
-
-.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) {
-    .checkout-onepage-index .column.main:extend(.abs-add-clearfix-desktop-s all) {
-    }
-
-    .opc-wrapper:extend(.abs-add-box-sizing-desktop-s all) {
-        .layout-column(2, 2, @layout-column-checkout__width-main);
-        .step-content:extend(.abs-form-field-column-2-s all) {
-            .form {
-                &.shipping.address,
-                &.billing,
-                &.methods-shipping {
-                    margin-left: @opc-margin-left;
-                    width: 80%;
-                }
-                &:after {
-                    text-align: right;
-                }
-            }
-
-            .field {
-                &.street,
-                &.choice {
-                    width: 100%;
-                }
-                &.street .field.additional {
-                    padding: 0;
-                    width: 100%;
-                }
-            }
-
-            .payments,
-            .order-review {
-                .field:extend(.abs-form-field-revert-column-1-s all) {
-                    &:nth-last-child(1),
-                    &:nth-last-child(2) {
-                        margin-bottom: @indent__base;
-                    }
-                    &:last-child {
-                        margin: 0;
-                    }
-                }
-            }
-
-            .toolbar {
-                text-align: left;
-            }
-        }
-
-        //
-        //  Login or register
-        //  ---------------------------------------------
-
-        .login-wrapper:extend(.abs-add-clearfix-desktop-s all) {
-            .block:extend(.abs-blocks-2columns-s all) {
-                margin-bottom: 0;
-            }
-            .fieldset {
-                .field {
-                    padding: 0;
-                    width: 100%;
-                }
-                &.login:after {
-                    text-align: left;
-                }
-            }
-            .field.choice:not(.persistent):before {
-                display: none;
-            }
-        }
-
-        .checkout-submit-order .actions-toolbar > .primary {
-            float: right;
-        }
-    }
-
-    //
-    //  Payment methods
-    //  ---------------------------------------------
-
-    .methods-payment .item-content > .fieldset,
-    .order-review .fieldset {
-        margin: @indent__s 0 @indent__l @opc-margin-left;
-        padding: 0;
-        width: 46%;
-        .field .field {
-            &.cvv {
-                display: inline-block;
-                width: 30%;
-            }
-            &.date {
-                display: inline-block;
-                width: 70%;
-            }
-            &.month {
-                padding-right: 12px;
-            }
-            &.month,
-            &.year {
-                margin-bottom: 0;
-            }
-        }
-    }
-
-    .checkout-success .subtitle .print {
-        margin-left: @indent__xl;
-    }
-
-    .table-order-review {
-        .col.subtotal,
-        .amount {
-            text-align: right;
-        }
-        .col.item {
-            width: 70%;
-        }
-        .grand.totals {
-            .font-size(16);
-            th,
-            td {
-                padding: 0 0 @indent__xl;
-            }
-            strong {
-                border-top: @border-width__base solid @border-color__base;
-                display: block;
-                padding-top: 11px;
-            }
-            .mark {
-                strong {
-                    margin-left: @indent__s;
-                    padding-right: @indent__s;
-                }
-            }
-            .amount {
-                strong {
-                    margin-right: @indent__s;
-                    padding-left: @indent__s;
-                }
-            }
-        }
-    }
-
-    //
-    //  Checkout success
-    //  ---------------------------------------------
-
-    .checkout-onepage-success {
-        .page-title-wrapper {
-            .print:extend(.abs-action-print-s all) {
-                display: inline-block;
-                .font-size(14);
-                margin-left: @indent__xl;
-            }
-        }
-    }
-
-    .opc-block-progress-wrapper:extend(.abs-add-box-sizing-desktop-s all) {
-        .layout-column(2, 1, @layout-column-checkout__width-left);
-        margin-top: 0;
-        padding-right: @layout-column-main__sidebar-offset;
-    }
-
-    .opc-block-progress.active {
-        display: block;
-    }
-}
+@import 'module/_checkout.less';
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less
index 84fe60c7262910782021ee8c38b2d319cc66efc7..9157adac7398e56430135bd4835ffc768cc3d304 100644
--- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less
@@ -13,453 +13,366 @@
 
 & when (@media-common = true) {
 
-    //
-    //  Shopping cart
-    //  ---------------------------------------------
-
-    .checkout-cart-index {
-        .page-main {
-            padding-left: 0;
-            padding-right: 0;
-        }
-        .page-title-wrapper {
-            padding-left: @layout__width-xs-indent;
-            padding-right: @layout__width-xs-indent;
-        }
+  //
+  //  Shopping cart
+  //  ---------------------------------------------
+
+  .checkout-cart-index {
+    .page-main {
+      padding-left: 0;
+      padding-right: 0;
+    }
+    .page-title-wrapper {
+      padding-left: @layout__width-xs-indent;
+      padding-right: @layout__width-xs-indent;
+    }
+  }
+  .cart {
+    //  Cart container
+    &-container {
+      .form-cart {
+        &:extend(.abs-shopping-cart-items all);
+      }
     }
-    .cart {
-        //  Cart container
-        &-container {
-            .form-cart {
-                &:extend(.abs-shopping-cart-items all);
-            }
-        }
-
-        //  Summary block
-        &-summary {
-            &:extend(.abs-add-box-sizing all);
-            .css(background, @sidebar__background-color);
-            margin-bottom: 25px;
-            padding: 1px 0 25px;
-            > .title {
-                display: none;
-                .font-size(24);
-                font-weight: @font-weight__light;
-                margin: 12px 0;
-            }
-
-            .block {
-                form:not(:last-of-type) {
-                    .fieldset {
-                        margin: 0 0 @indent__m;
-                    }
-                }
-
-                .price {
-                    font-weight: @font-weight__bold;
-                }
-
-                .field {
-                    margin: 0 0 16px;
-                    &.note {
-                        display: none;
-                    }
-                }
-
-                .actions-toolbar {
-                    > .primary {
-                        text-align: left;
-                        .action.primary {
-                            &:extend(.abs-revert-to-action-secondary all);
-                            width: auto;
-                        }
-                    }
-                }
-
-                .fieldset.estimate {
-                    > .legend,
-                    > .legend + br {
-                        &:extend(.abs-no-display all);
-                    }
-                }
-                &:extend(.abs-cart-block all);
-                .title {
-                    strong {
-                        .font-size(14);
-                        font-weight: @font-weight__semibold;
-                    }
-                }
-                .item-options {
-                    margin: 0 0 16px;
-                    .field {
-                        .radio {
-                            float: left;
-                        }
-                        .radio {
-                            + .label {
-                                display: block;
-                                margin: 0;
-                                overflow: hidden;
-                            }
-                        }
-                    }
-                }
-            }
-
-            .page-main & {
-                .block {
-                    margin-bottom: 0;
-                }
-            }
-
-            .checkout-methods-items {
-                &:extend(.abs-reset-list all);
-                margin: 20px 0 0;
-                padding: 0 @mobile-cart-padding;
-                text-align: center;
-                .action.primary.checkout {
-                    &:extend(.abs-button-l all);
-                    width: 100%;
-                }
-                .item {
-                    margin-bottom: 25px;
-                    &:last-child {
-                        margin-bottom: 0;
-                    }
-                }
-            }
 
-            .message {
-                padding-left: 20px;
-                > *:first-child:before {
-                    display: none;
-                }
-            }
-            &:extend(.abs-adjustment-incl-excl-tax all);
-        }
-
-        //  Totals block
-        &-totals {
-            border-top: 1px solid @border-color__base;
-            padding-top: 10px;
-            tbody,
-            tfoot {
-                .mark {
-                    border: 0;
-                    font-weight: @font-weight__regular;
-                    padding: 6px 0;
-                    text-align: left;
-                }
-                .amount {
-                    border: 0;
-                    font-weight: @font-weight__regular;
-                    padding: 6px 0 6px 14px;
-                    text-align: right;
-                }
-            }
-            .table-caption {
-                &:extend(.abs-no-display all);
-            }
-            .grand {
-                th,
-                td {
-                    padding: 11px 0;
-                }
-                .mark {
-                    border-top: 1px solid @border-color__base;
-                    .font-size(16);
-                    padding-right: @indent__s;
-                    strong {
-                        display: inline-block;
-                        font-weight: @font-weight__regular;
-                        padding: 3px 0 0;
-                    }
-                }
-                .amount {
-                    border-top: 1px solid @border-color__base;
-                    .font-size(18);
-                }
-            }
-            .msrp {
-                margin-bottom: @indent__s;
-            }
-            tbody tr:last-child td {
-                padding-bottom: 19px;
-            }
-            .totals-tax {
-                &-summary {
-                    .mark,
-                    .amount {
-                        border-bottom: @border-width__base solid @border-color__base;
-                        border-top: @border-width__base solid @border-color__base;
-                        cursor: pointer;
-                    }
-                    .amount .price {
-                        .icon-font(
-                        @icon-down,
-                        @_icon-font-size: 12px,
-                        @_icon-font-line-height: 12px,
-                        @_icon-font-text-hide: true,
-                        @_icon-font-position: after
-                        );
-                        padding-right: 20px;
-                        position: relative;
-                        &:after {
-                            position: absolute;
-                            right: 3px;
-                            top: 3px;
-                        }
-                    }
-                    &.expanded {
-                        .mark,
-                        .amount {
-                            border-bottom: 0;
-                        }
-                        .amount .price {
-                            .icon-font-symbol(
-                            @_icon-font-content: @icon-up,
-                            @_icon-font-position: after
-                            );
-                        }
-                    }
-                }
-                &-details {
-                    border-bottom: @border-width__base solid @border-color__base;
-                    display: none;
-                    &.shown {
-                        display: table-row;
-                    }
-                }
-            }
-            .table-wrapper {
-                margin-bottom: 0;
-            }
+    //  Summary block
+    &-summary {
+      &:extend(.abs-add-box-sizing all);
+      .css(background, @sidebar__background-color);
+      margin-bottom: 25px;
+      padding: 1px 0 25px;
+      > .title {
+        display: none;
+        .font-size(24);
+        font-weight: @font-weight__light;
+        margin: 12px 0;
+      }
+
+      .block {
+        form:not(:last-of-type) {
+          .fieldset {
+            margin: 0 0 @indent__m;
+          }
         }
 
-        //  Products table
-        &.table-wrapper {
-            .cart {
-                thead {
-                    tr th.col {
-                        border-bottom: @border-width__base solid @border-color__base;
-                        padding-bottom: 15px;
-                        padding-top: 24px;
-                    }
-                }
-                tbody {
-                    td {
-                        border: 0;
-                    }
-                }
-                > .item {
-                    border-bottom: @border-width__base solid @border-color__base;
-                    position: relative;
-                }
-            }
-            .col {
-                padding-top: 15px;
-                &.price,
-                &.subtotal,
-                &.msrp {
-                    padding: @cart-item-cell-padding-top 11px @indent__s;
-                    text-align: center;
-                    &:extend(.abs-incl-excl-tax all);
-                }
-                &.qty {
-                    padding: 20px 11px @indent__s;
-                    text-align: center;
-                    .label {
-                        &:extend(.abs-visually-hidden all);
-                    }
-                    .input-text {
-                        height: 36px;
-                        margin-top: -7px;
-                        text-align: center;
-                        width: 45px;
-                    }
-                }
-                > .price {
-                    .css(color, @primary__color__lighter);
-                    .font-size(18);
-                    font-weight: @font-weight__bold;
-                }
-            }
+        .price {
+          font-weight: @font-weight__bold;
+        }
 
-            .item-actions {
-                td {
-                    padding-bottom: 0;
-                    padding-left: @mobile-cart-padding;
-                    padding-right: @mobile-cart-padding;
-                    white-space: normal;
-                }
-            }
-            .item {
-                .col.item {
-                    display: block;
-                    min-height: 75px;
-                    padding: 15px @mobile-cart-padding @indent__s 90px;
-                    position: relative;
-                }
-            }
+        .field {
+          margin: 0 0 16px;
+          &.note {
+            display: none;
+          }
+        }
 
-            .actions-toolbar {
-                &:extend(.abs-add-clearfix all);
-                min-height: 20px;
-                padding-bottom: 15px;
-                position: relative;
-                > .action-edit,
-                > .action-delete {
-                    position: absolute;
-                    right: 16px;
-                    top: 0;
-                    .icon-font(
-                    @icon-edit,
-                    @_icon-font-size: 18px,
-                    @_icon-font-line-height: 20px,
-                    @_icon-font-text-hide: true,
-                    @_icon-font-color: @minicart-icons-color,
-                    @_icon-font-color-hover: @primary__color,
-                    @_icon-font-color-active: @minicart-icons-color
-                    );
-                }
-                > .action-delete {
-                    right: 0;
-                    .icon-font-symbol(
-                    @_icon-font-content: @icon-trash
-                    );
-                }
-            }
-            .action {
-                margin-right: @indent__m;
-                &:last-child {
-                    margin-right: 0;
-                }
-                &.help.map {
-                    &:extend(.abs-action-button-as-link all);
-                    font-weight: @font-weight__regular;
-                }
+        .actions-toolbar {
+          > .primary {
+            text-align: left;
+            .action.primary {
+              &:extend(.abs-revert-to-action-secondary all);
+              width: auto;
             }
+          }
+        }
 
-            .product {
-                &-item-photo {
-                    display: block;
-                    left: @mobile-cart-padding;
-                    max-width: 65px;
-                    padding: 0;
-                    position: absolute;
-                    top: 15px;
-                    width: 100%;
-                }
-                &-item-name {
-                    display: block;
-                    .font-size(18);
-                    margin: -3px 0 @indent__xs;
-                }
-            }
-            .gift-registry-name-label {
-                &:after {
-                    content: ':';
-                }
+        .fieldset.estimate {
+          > .legend,
+          > .legend + br {
+            &:extend(.abs-no-display all);
+          }
+        }
+        &:extend(.abs-cart-block all);
+        .title {
+          strong {
+            .font-size(14);
+            font-weight: @font-weight__semibold;
+          }
+        }
+        .item-options {
+          margin: 0 0 16px;
+          .field {
+            .radio {
+              float: left;
+            }
+            .radio {
+              + .label {
+                display: block;
+                margin: 0;
+                overflow: hidden;
+              }
             }
+          }
+        }
+      }
 
-            //  Product options
-            .item-options {
-                margin-bottom: 0;
-                &:extend(.abs-product-options-list all);
-                &:extend(.abs-add-clearfix all);
-            }
+      .page-main & {
+        .block {
+          margin-bottom: 0;
+        }
+      }
+
+      .checkout-methods-items {
+        &:extend(.abs-reset-list all);
+        margin: 20px 0 0;
+        padding: 0 @mobile-cart-padding;
+        text-align: center;
+        .action.primary.checkout {
+          &:extend(.abs-button-l all);
+          width: 100%;
+        }
+        .item {
+          margin-bottom: 25px;
+          &:last-child {
+            margin-bottom: 0;
+          }
+        }
+      }
 
-            .product-item-name + .item-options {
-                margin-top: @indent__base;
-            }
+      .message {
+        padding-left: 20px;
+        > *:first-child:before {
+          display: none;
+        }
+      }
+      &:extend(.abs-adjustment-incl-excl-tax all);
+    }
 
-            .cart-tax-total {
-                &:extend(.abs-tax-total all);
-                &-expanded {
-                    &:extend(.abs-tax-total-expanded all);
-                }
-            }
-            .product-image-wrapper {
-                &:extend(.abs-reset-image-wrapper all);
-            }
-            .action.configure {
-                display: inline-block;
-                margin: @indent__s 0 0;
-            }
-            .item .message {
-                margin-top: @indent__base;
-            }
+    //  Totals block
+    &-totals {
+      &:extend(.abs-sidebar-totals all);
+      tbody,
+      tfoot {
+        .mark {
+          text-align: left;
         }
+      }
+    }
 
-        //  Discount
-        &-discount {
+    //  Products table
+    &.table-wrapper {
+      .cart {
+        thead {
+          tr th.col {
             border-bottom: @border-width__base solid @border-color__base;
-            clear: left;
-            .block {
-                &:extend(.abs-cart-block all);
-                > .title {
-                    strong {
-                        color: @color-blue1;
-                        font-weight: @font-weight__regular;
-                    }
-                }
-            }
-            .fieldset > .field > .label {
-                display: none;
-            }
-            .actions-toolbar .primary {
-                .action {
-                    &.primary,
-                    &.cancel {
-                        &:extend(.abs-revert-to-action-secondary all);
-                        border-bottom-left-radius: 0;
-                        border-top-left-radius: 0;
-                    }
-                }
-            }
-            .action.check {
-                &:extend(.abs-action-button-as-link all);
-                font-weight: @font-weight__regular;
-            }
-            .fieldset {
-                display: table;
-                width: 100%;
-            }
-            .field {
-                display: table-cell;
-            }
-            .actions-toolbar {
-                display: table-cell;
-                vertical-align: top;
-                width: 1%;
-                .action {
-                    &.primary,
-                    &.cancel {
-                        border-bottom-left-radius: 0;
-                        border-top-left-radius: 0;
-                        margin: 0 0 0 -1px;
-                        white-space: nowrap;
-                        width: auto;
-                    }
-                }
-                .secondary {
-                    bottom: 5px;
-                    left: @mobile-cart-padding;
-                    position: absolute;
-                }
-            }
+            padding-bottom: 15px;
+            padding-top: 24px;
+          }
         }
-
-        //  Empty cart
-        &-empty {
-            padding-left: @layout__width-xs-indent;
-            padding-right: @layout__width-xs-indent;
+        tbody {
+          td {
+            border: 0;
+          }
+        }
+        > .item {
+          border-bottom: @border-width__base solid @border-color__base;
+          position: relative;
+        }
+      }
+      .col {
+        padding-top: 15px;
+        &.price,
+        &.subtotal,
+        &.msrp {
+          padding: @cart-item-cell-padding-top 11px @indent__s;
+          text-align: center;
+          &:extend(.abs-incl-excl-tax all);
+        }
+        &.qty {
+          padding: 20px 11px @indent__s;
+          text-align: center;
+          .label {
+            &:extend(.abs-visually-hidden all);
+          }
+          .input-text {
+            height: 36px;
+            margin-top: -7px;
+            text-align: center;
+            width: 45px;
+          }
+        }
+        > .price {
+          .css(color, @primary__color__lighter);
+          .font-size(18);
+          font-weight: @font-weight__bold;
+        }
+      }
+
+      .item-actions {
+        td {
+          padding-bottom: 0;
+          padding-left: @mobile-cart-padding;
+          padding-right: @mobile-cart-padding;
+          white-space: normal;
+        }
+      }
+      .item {
+        .col.item {
+          display: block;
+          min-height: 75px;
+          padding: 15px @mobile-cart-padding @indent__s 90px;
+          position: relative;
+        }
+      }
+
+      .actions-toolbar {
+        &:extend(.abs-add-clearfix all);
+        min-height: 20px;
+        padding-bottom: 15px;
+        position: relative;
+        > .action-edit,
+        > .action-delete {
+          position: absolute;
+          right: 16px;
+          top: 0;
+          .icon-font(
+          @icon-edit,
+          @_icon-font-size: 18px,
+          @_icon-font-line-height: 20px,
+          @_icon-font-text-hide: true,
+          @_icon-font-color: @minicart-icons-color,
+          @_icon-font-color-hover: @primary__color,
+          @_icon-font-color-active: @minicart-icons-color
+          );
+        }
+        > .action-delete {
+          right: 0;
+          .icon-font-symbol(
+          @_icon-font-content: @icon-trash
+          );
+        }
+      }
+      .action {
+        margin-right: @indent__m;
+        &:last-child {
+          margin-right: 0;
+        }
+        &.help.map {
+          &:extend(.abs-action-button-as-link all);
+          font-weight: @font-weight__regular;
+        }
+      }
+
+      .product {
+        &-item-photo {
+          display: block;
+          left: @mobile-cart-padding;
+          max-width: 65px;
+          padding: 0;
+          position: absolute;
+          top: 15px;
+          width: 100%;
         }
+        &-item-name {
+          display: block;
+          .font-size(18);
+          margin: -3px 0 @indent__xs;
+        }
+      }
+      .gift-registry-name-label {
+        &:after {
+          content: ':';
+        }
+      }
+
+      //  Product options
+      .item-options {
+        margin-bottom: 0;
+        &:extend(.abs-product-options-list all);
+        &:extend(.abs-add-clearfix all);
+      }
+
+      .product-item-name + .item-options {
+        margin-top: @indent__base;
+      }
+
+      .cart-tax-total {
+        &:extend(.abs-tax-total all);
+        &-expanded {
+          &:extend(.abs-tax-total-expanded all);
+        }
+      }
+      .product-image-wrapper {
+        &:extend(.abs-reset-image-wrapper all);
+      }
+      .action.configure {
+        display: inline-block;
+        margin: @indent__s 0 0;
+      }
+      .item .message {
+        margin-top: @indent__base;
+      }
+    }
 
-        .cart-tax-info + .cart-tax-total {
-            display: block;
+    //  Discount
+    &-discount {
+      border-bottom: @border-width__base solid @border-color__base;
+      clear: left;
+      .block {
+        &:extend(.abs-cart-block all);
+        > .title {
+          strong {
+            color: @color-blue1;
+            font-weight: @font-weight__regular;
+          }
         }
+      }
+      .fieldset > .field > .label {
+        display: none;
+      }
+      .actions-toolbar .primary {
+        .action {
+          &.primary,
+          &.cancel {
+            &:extend(.abs-revert-to-action-secondary all);
+            border-bottom-left-radius: 0;
+            border-top-left-radius: 0;
+          }
+        }
+      }
+      .action.check {
+        &:extend(.abs-action-button-as-link all);
+        font-weight: @font-weight__regular;
+      }
+      .fieldset {
+        display: table;
+        width: 100%;
+      }
+      .field {
+        display: table-cell;
+      }
+      .actions-toolbar {
+        display: table-cell;
+        vertical-align: top;
+        width: 1%;
+        .action {
+          &.primary,
+          &.cancel {
+            border-bottom-left-radius: 0;
+            border-top-left-radius: 0;
+            margin: 0 0 0 -1px;
+            white-space: nowrap;
+            width: auto;
+          }
+        }
+        .secondary {
+          bottom: 5px;
+          left: @mobile-cart-padding;
+          position: absolute;
+        }
+      }
     }
+
+    //  Empty cart
+    &-empty {
+      padding-left: @layout__width-xs-indent;
+      padding-right: @layout__width-xs-indent;
+    }
+
+    .cart-tax-info + .cart-tax-total {
+      display: block;
+    }
+  }
 }
 
 //
@@ -467,110 +380,97 @@
 //  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
-    .cart {
-        &-totals {
-            .table.totals {
-                th {
-                    &:extend(.abs-col-no-prefix all);
-                    display: table-cell;
-                }
-                td {
-                    &:extend(.abs-col-no-prefix all);
-                    display: table-cell;
-                }
-                tbody tr:not(:last-child) td {
-                    &:extend(.abs-no-border-bottom-top all);
-                }
-                .amount {
-                    text-align: right;
-                }
-            }
-        }
-        .table.items {
-            .col.item,
-            .item-actions td {
-                &:extend(.abs-col-no-prefix all);
-            }
-            .col.qty {
-                text-align: center;
-            }
-            tbody > tr > td:last-child {
-                &:extend(.abs-no-border-bottom-top all);
-            }
-        }
+  .cart {
+    &-totals {
+      .totals {
+        &:extend(.abs-sidebar-totals-mobile all);
+      }
+    }
+    .table.items {
+      .col.item,
+      .item-actions td {
+        &:extend(.abs-col-no-prefix all);
+      }
+      .col.qty {
+        text-align: center;
+      }
+      tbody > tr > td:last-child {
+        &:extend(.abs-no-border-bottom-top all);
+      }
     }
+  }
 }
 
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
-    .cart {
-        //  Cart container
-        &-container {
-            .form-cart {
-                .actions.main {
-                    text-align: center;
-                }
-            }
+  .cart {
+    //  Cart container
+    &-container {
+      .form-cart {
+        .actions.main {
+          text-align: center;
         }
+      }
+    }
 
-        &-discount {
-            border-bottom: @border-width__base solid @border-color__base;
-        }
+    &-discount {
+      border-bottom: @border-width__base solid @border-color__base;
+    }
 
-        &.table-wrapper {
-            border-top: @border-width__base solid @border-color__base;
-            thead {
-                .col {
-                    &.item,
-                    &.qty,
-                    &.price,
-                    &.subtotal,
-                    &.msrp {
-                        display: none;
-                    }
-                }
-            }
-            .col {
-                &.qty,
-                &.price,
-                &.subtotal,
-                &.msrp {
-                    box-sizing: border-box;
-                    display: block;
-                    float: left;
-                    white-space: nowrap;
-                    width: 33%;
-                    &:before {
-                        content: attr(data-th);
-                        display: block;
-                        font-weight: @font-weight__semibold;
-                        padding-bottom: 10px;
-                    }
-                }
-                &.msrp {
-                    white-space: normal;
-                }
-            }
-            .item .col.item {
-                padding-bottom: 0;
-            }
-            tbody > tr > td:last-child {
-                border: 0;
-            }
+    &.table-wrapper {
+      border-top: @border-width__base solid @border-color__base;
+      thead {
+        .col {
+          &.item,
+          &.qty,
+          &.price,
+          &.subtotal,
+          &.msrp {
+            display: none;
+          }
+        }
+      }
+      .col {
+        &.qty,
+        &.price,
+        &.subtotal,
+        &.msrp {
+          box-sizing: border-box;
+          display: block;
+          float: left;
+          white-space: nowrap;
+          width: 33%;
+          &:before {
+            content: attr(data-th);
+            display: block;
+            font-weight: @font-weight__semibold;
+            padding-bottom: 10px;
+          }
         }
+        &.msrp {
+          white-space: normal;
+        }
+      }
+      .item .col.item {
+        padding-bottom: 0;
+      }
+      tbody > tr > td:last-child {
+        border: 0;
+      }
+    }
 
-        &-totals {
-            padding-left: @mobile-cart-padding;
-            padding-right: @mobile-cart-padding;
-            .table-wrapper {
-                border-top: 0;
-            }
-            .totals {
-                tbody > tr:not(:last-child) > td:last-child {
-                    border: 0;
-                }
-            }
+    &-totals {
+      padding-left: @mobile-cart-padding;
+      padding-right: @mobile-cart-padding;
+      .table-wrapper {
+        border-top: 0;
+      }
+      .totals {
+        tbody > tr:not(:last-child) > td:last-child {
+          border: 0;
         }
+      }
     }
+  }
 }
 
 
@@ -579,14 +479,14 @@
 //  _____________________________________________
 
 & when (@media-common = true) {
-    //  Cross sell
-    .block.crosssell {
-        margin-top: 70px;
-        .css(padding, 0 @mobile-cart-padding);
-        .product-item-info {
-            width: 200px;
-        }
+  //  Cross sell
+  .block.crosssell {
+    margin-top: 70px;
+    .css(padding, 0 @mobile-cart-padding);
+    .product-item-info {
+      width: 200px;
     }
+  }
 }
 
 //
@@ -594,150 +494,150 @@
 //  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
-    .checkout-cart-index {
-        .page-main {
-            padding-left: @layout__width-xs-indent;
-            padding-right: @layout__width-xs-indent;
-        }
-        .page-title-wrapper {
-            &:extend(.abs-revert-side-paddings all);
-        }
+  .checkout-cart-index {
+    .page-main {
+      padding-left: @layout__width-xs-indent;
+      padding-right: @layout__width-xs-indent;
     }
-    .cart {
-        //  Cart container
-        &-container {
-            &:extend(.abs-add-clearfix-desktop all);
-            .form-cart {
-                &:extend(.abs-shopping-cart-items-desktop all);
-                .actions.main {
-                    text-align: right;
-                }
-            }
-            .widget {
-                float: left;
-            }
+    .page-title-wrapper {
+      &:extend(.abs-revert-side-paddings all);
+    }
+  }
+  .cart {
+    //  Cart container
+    &-container {
+      &:extend(.abs-add-clearfix-desktop all);
+      .form-cart {
+        &:extend(.abs-shopping-cart-items-desktop all);
+        .actions.main {
+          text-align: right;
         }
+      }
+      .widget {
+        float: left;
+      }
+    }
 
-        //  Summary block
-        &-summary {
-            .layout-column(2, 2, @layout-column-checkout__width-left);
-            padding: 1px @indent__base @indent__m;
-            position: relative;
-            > .title {
-                display: block;
-            }
-            .fieldset .actions-toolbar {
-                margin-left: 0;
-                > .secondary {
-                    float: none;
-                }
-            }
-            .block {
-                > .title {
-                    padding-left: 0;
-                    &:after {
-                        right: 3px;
-                    }
-                }
-                .content {
-                    &:extend(.abs-revert-side-paddings all);
-                }
-                .fieldset {
-                    .field {
-                        .form-field-type-revert(@_type: block);
-                        margin: 0 0 @indent__s;
-                    }
-                }
-            }
-            .checkout-methods-items {
-                padding: 0;
-            }
+    //  Summary block
+    &-summary {
+      .layout-column(2, 2, @layout-column-checkout__width-left);
+      padding: 1px @indent__base @indent__m;
+      position: relative;
+      > .title {
+        display: block;
+      }
+      .fieldset .actions-toolbar {
+        margin-left: 0;
+        > .secondary {
+          float: none;
         }
+      }
+      .block {
+        > .title {
+          padding-left: 0;
+          &:after {
+            right: 3px;
+          }
+        }
+        .content {
+          &:extend(.abs-revert-side-paddings all);
+        }
+        .fieldset {
+          .field {
+            .form-field-type-revert(@_type: block);
+            margin: 0 0 @indent__s;
+          }
+        }
+      }
+      .checkout-methods-items {
+        padding: 0;
+      }
+    }
 
-        //  Products table
-        &.table-wrapper {
-            tbody td {
-                padding-top: @cart-item-cell-padding-top;
-            }
-
-            .item {
-                .col.item {
-                    padding: @cart-item-cell-padding-top 8px 20px 0;
-                }
-            }
-
-            .item-actions td {
-                padding: 0;
-            }
+    //  Products table
+    &.table-wrapper {
+      tbody td {
+        padding-top: @cart-item-cell-padding-top;
+      }
 
-            .product {
-                &-item-photo {
-                    display: table-cell;
-                    max-width: 100%;
-                    padding-right: 20px;
-                    position: static;
-                    vertical-align: top;
-                    width: 1%;
-                }
-                &-item-details {
-                    padding-bottom: 35px;
-                }
-                &-item-details {
-                    display: table-cell;
-                    vertical-align: top;
-                    white-space: normal;
-                    width: 99%;
-                }
-            }
+      .item {
+        .col.item {
+          padding: @cart-item-cell-padding-top 8px 20px 0;
         }
-
-        //  Discount
-        &-discount {
-            border: 0;
-            .layout-column(2, 1, @layout-column-checkout__width-main);
-            &:extend(.abs-add-box-sizing-desktop all);
-            padding-right: 4%;
-            .block {
-                &:extend(.abs-blocks-2columns all);
-                width: 48%;
-                > .title {
-                    border: 0;
-                    cursor: default;
-                    padding: 0 0 10px;
-                    .column.main & strong {
-                        .font-size(16);
-                    }
-                    &:after {
-                        display: none;
-                    }
-                }
-                .content {
-                    display: block !important; // Need for overwriting collapsible widget
-                    padding: 0;
-                }
-            }
-            .actions-toolbar {
-                .secondary {
-                    bottom: -30px;
-                    left: 0;
-                    position: absolute;
-                }
-            }
+      }
+
+      .item-actions td {
+        padding: 0;
+      }
+
+      .product {
+        &-item-photo {
+          display: table-cell;
+          max-width: 100%;
+          padding-right: 20px;
+          position: static;
+          vertical-align: top;
+          width: 1%;
         }
-
-        //  Empty cart
-        &-empty {
-            &:extend(.abs-revert-side-paddings all);
+        &-item-details {
+          padding-bottom: 35px;
         }
+        &-item-details {
+          display: table-cell;
+          vertical-align: top;
+          white-space: normal;
+          width: 99%;
+        }
+      }
     }
 
-    //  Cross sell
-    .block.crosssell {
-        .layout-column(2, 1, @layout-column-checkout__width-main);
-        &:extend(.abs-add-box-sizing-desktop all);
-        padding: 0 4% 0 0;
-        .products-grid .product-item {
-            width: 100%/4;
+    //  Discount
+    &-discount {
+      border: 0;
+      .layout-column(2, 1, @layout-column-checkout__width-main);
+      &:extend(.abs-add-box-sizing-desktop all);
+      padding-right: 4%;
+      .block {
+        &:extend(.abs-blocks-2columns all);
+        width: 48%;
+        > .title {
+          border: 0;
+          cursor: default;
+          padding: 0 0 10px;
+          .column.main & strong {
+            .font-size(16);
+          }
+          &:after {
+            display: none;
+          }
+        }
+        .content {
+          display: block !important; // Need for overwriting collapsible widget
+          padding: 0;
         }
+      }
+      .actions-toolbar {
+        .secondary {
+          bottom: -30px;
+          left: 0;
+          position: absolute;
+        }
+      }
+    }
+
+    //  Empty cart
+    &-empty {
+      &:extend(.abs-revert-side-paddings all);
+    }
+  }
+
+  //  Cross sell
+  .block.crosssell {
+    .layout-column(2, 1, @layout-column-checkout__width-main);
+    &:extend(.abs-add-box-sizing-desktop all);
+    padding: 0 4% 0 0;
+    .products-grid .product-item {
+      width: 100%/4;
     }
+  }
 }
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
index ddeb77db7fdfda33523a0f4a167f393ece533d43..86564ca26cb6aa19691789f4b16a2917b8f84744 100644
--- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
@@ -5,330 +5,332 @@
 
 //
 //  Variables
-//  ---------------------------------------------
+//  _____________________________________________
 
 @minicart__border-color: @color-gray80;
 @minicart__padding-horizontal: @indent__base;
 
 //
 //  Common
-//  ---------------------------------------------
+//  _____________________________________________
 
 & when (@media-common = true) {
 
-//
-//  Minicart
-//  ---------------------------------------------
+    //
+    //  Minicart
+    //  ---------------------------------------------
 
-.block-minicart {
-    .items-total {
-        float: left;
-        margin: 0 @indent__s;
-        .count {
-            font-weight: @font-weight__bold;
+    .block-minicart {
+        .items-total {
+            float: left;
+            margin: 0 @indent__s;
+            .count {
+                font-weight: @font-weight__bold;
+            }
         }
-    }
-    .subtotal {
-        margin: 0 @indent__s;
-        text-align: right;
-        .label {
-            &:extend(.abs-colon all);
+        .subtotal {
+            margin: 0 @indent__s;
+            text-align: right;
+            .label {
+                &:extend(.abs-colon all);
+            }
         }
-    }
-    .amount {
-        .price-wrapper {
-            &:first-child {
-                .price {
-                    font-size: @font-size__l;
-                    font-weight: @font-weight__bold;
+        .amount {
+            .price-wrapper {
+                &:first-child {
+                    .price {
+                        font-size: @font-size__l;
+                        font-weight: @font-weight__bold;
+                    }
                 }
             }
         }
-    }
-    .subtitle {
-        display: none;
-    }
-    .subtitle {
-        &.empty {
-            display: block;
-            padding: @indent__l 0 @indent__base;
-            text-align: center;
-            font-size: 14px;
-        }
-    }
-    .text {
-        &.empty {
-            text-align: center;
+        .subtitle {
+            display: none;
+            &.empty {
+                display: block;
+                padding: @indent__l 0 @indent__base;
+                text-align: center;
+                font-size: 14px;
+            }
         }
-    }
-    .block-content {
-        > .actions {
-            margin-top: 15px;
-            > .secondary {
+        .text {
+            &.empty {
                 text-align: center;
             }
-            > .primary {
-                margin: 0 @indent__s 15px;
-                .action {
-                    &.primary {
-                        &:extend(.abs-button-l all);
-                        display: block;
-                        width: 100%;
+        }
+        .block-content {
+            > .actions {
+                margin-top: 15px;
+                > .secondary {
+                    text-align: center;
+                }
+                > .primary {
+                    margin: 0 @indent__s 15px;
+                    .action {
+                        &.primary {
+                            &:extend(.abs-button-l all);
+                            display: block;
+                            width: 100%;
+                        }
                     }
                 }
-            }
-            .paypal-logo {
-                margin-top: 15px;
-                text-align: center;
+                .paypal-logo {
+                    margin-top: 15px;
+                    text-align: center;
+                }
             }
         }
+        .block-category-link,
+        .block-product-link,
+        .block-cms-link,
+        .block-banners {
+            margin: 15px 0 0;
+            text-align: center;
+        }
     }
-    .block-category-link,
-    .block-product-link,
-    .block-cms-link,
-    .block-banners {
-        margin: 15px 0 0;
-        text-align: center;
-    }
-}
 
-.minicart-wrapper {
-    .dropdown(
-        @_toggle-selector: ~".action.showcart",
-        @_options-selector: ~".block-minicart",
-        @_dropdown-toggle-icon-content: @icon-cart,
-        @_dropdown-toggle-active-icon-content: @icon-cart,
-        @_dropdown-list-item-padding: false,
-        @_dropdown-list-item-hover: false,
-        @_icon-font-position: before,
-        @_icon-font-size: 22px,
-        @_icon-font-line-height: 28px,
-        @_icon-font-color: @minicart-icons-color,
-        @_icon-font-color-hover: @minicart-icons-color-hover,
-        @_icon-font-color-active: @minicart-icons-color
-    );
-    float: right;
-    .block-minicart {
-        .css(padding, 25px @minicart__padding-horizontal);
-        right: 0;
-        width: 320px;
-        .block-title {
-            display: none;
-        }
-        &:after {
-            left: auto;
-            right: 25px;
-        }
-        &:before {
-            left: auto;
-            right: 26px;
+    .minicart-wrapper {
+        .dropdown(
+            @_toggle-selector: ~".action.showcart",
+            @_options-selector: ~".block-minicart",
+            @_dropdown-toggle-icon-content: @icon-cart,
+            @_dropdown-toggle-active-icon-content: @icon-cart,
+            @_dropdown-list-item-padding: false,
+            @_dropdown-list-item-hover: false,
+            @_icon-font-position: before,
+            @_icon-font-size: 22px,
+            @_icon-font-line-height: 28px,
+            @_icon-font-color: @minicart-icons-color,
+            @_icon-font-color-hover: @minicart-icons-color-hover,
+            @_icon-font-color-active: @minicart-icons-color
+        );
+        float: right;
+        .block-minicart {
+            .css(padding, 25px @minicart__padding-horizontal);
+            right: 0;
+            width: 320px;
+            .block-title {
+                display: none;
+            }
+            &:after {
+                left: auto;
+                right: 25px;
+            }
+            &:before {
+                left: auto;
+                right: 26px;
+            }
         }
-    }
-    .product {
-        .actions {
-            float: right;
-            margin: -24px 0 0;
-            > .primary,
-            > .secondary {
-                display: inline;
-                &:not(:last-child) {
-                    margin-right: 15px;
+        .product {
+            .actions {
+                float: right;
+                margin: -24px 0 0;
+                > .primary,
+                > .secondary {
+                    display: inline;
+                    &:not(:last-child) {
+                        margin-right: 15px;
+                    }
                 }
             }
         }
-    }
-    .action {
-        &.close {
-            width: 40px;
-            height: 40px;
-            top: 0;
-            right: 0;
-            position: absolute;
-            .button-reset();
-            .button-icon(
-                @icon-remove,
-                @_icon-font-color: @minicart-icons-color,
-                @_icon-font-size: 16px,
-                @_icon-font-line-height: 16px,
-                @_icon-font-text-hide: true
-            );
-        }
-        &.showcart {
-            .text {
-                &:extend(.abs-visually-hidden all);
+        .action {
+            &.close {
+                width: 40px;
+                height: 40px;
+                top: 0;
+                right: 0;
+                position: absolute;
+                .button-reset();
+                .button-icon(
+                    @icon-remove,
+                    @_icon-font-color: @minicart-icons-color,
+                    @_icon-font-size: 16px,
+                    @_icon-font-line-height: 16px,
+                    @_icon-font-text-hide: true
+                );
             }
-            white-space: nowrap;
-            .counter.qty {
-                &.empty {
-                   display: none;
+            &.showcart {
+                .text {
+                    &:extend(.abs-visually-hidden all);
+                }
+                white-space: nowrap;
+                .counter.qty {
+                    &.empty {
+                       display: none;
+                    }
+                    .css(background, @active__color);
+                    border-radius: 2px;
+                    .css(color, @page__background-color);
+                    clip: none;
+                    display: inline-block;
+                    height: 24px;
+                    line-height: 24px;
+                    min-width: 18px;
+                    margin: 3px 0 0;
+                    padding: 0 3px;
+                    overflow: hidden;
+                    text-align: center;
+                    white-space: normal;
+                }
+                .counter-label {
+                    &:extend(.abs-visually-hidden all);
                 }
-                .css(background, @active__color);
-                border-radius: 2px;
-                .css(color, @page__background-color);
-                clip: none;
-                display: inline-block;
-                height: 24px;
-                line-height: 24px;
-                min-width: 18px;
-                margin: 3px 0 0;
-                padding: 0 3px;
-                overflow: hidden;
-                text-align: center;
-                white-space: normal;
-            }
-            .counter-label {
-                &:extend(.abs-visually-hidden all);
             }
         }
+        .minicart-widgets {
+            margin-top: 15px;
+        }
     }
-    .minicart-widgets {
-        margin-top: 15px;
-    }
-}
 
-.minicart-items-wrapper {
-    .css(border, 1px solid @minicart__border-color);
-    .css(margin, 0 -@minicart__padding-horizontal);
-    border-left: 0;
-    border-right: 0;
-    overflow-x: auto;
-    padding: 15px;
-}
+    .minicart-items-wrapper {
+        .css(border, 1px solid @minicart__border-color);
+        .css(margin, 0 -@minicart__padding-horizontal);
+        border-left: 0;
+        border-right: 0;
+        overflow-x: auto;
+        padding: 15px;
+    }
 
-.minicart-items {
-    .list-reset-styles(0, 0);
-    .item {
-        &:not(:first-child) {
-            .css(border-top, 1px solid @minicart__border-color);
-        }
-        padding: @indent__base 0;
-        &:first-child {
-            padding-top: 0;
-        }
-        > .product {
-            &:extend(.abs-add-clearfix all);
+    .minicart-items {
+        .list-reset-styles(0, 0);
+        .product-item {
+            &:not(:first-child) {
+                .css(border-top, 1px solid @minicart__border-color);
+            }
+            padding: @indent__base 0;
+            &:first-child {
+                padding-top: 0;
+            }
+            > .product {
+                &:extend(.abs-add-clearfix all);
+            }
         }
-    }
-    .product-image-wrapper {
-        &:extend(.abs-reset-image-wrapper all);
-    }
-    .product-item-pricing {
-        .label {
-            display: inline-block;
-            width: 4.5rem;
+        .product-image-wrapper {
+            &:extend(.abs-reset-image-wrapper all);
         }
-    }
-    .price-minicart {
-        margin-bottom: @indent__xs;
-    }
-    .product-item-photo {
-        float: left;
-    }
-    .product-item-name {
-        font-weight: @font-weight__regular;
-        margin: 0 0 @indent__s;
-        a {
-            .css(color, @link__color);
-        }
-    }
-    .product-item-details {
-        padding-left: 88px;
-        .price {
-            font-weight: @font-weight__bold;
+        .product-item-pricing {
+            .label {
+                display: inline-block;
+                width: 4.5rem;
+            }
         }
-        .price-including-tax,
-        .price-excluding-tax {
-            margin: @indent__xs 0;
+        .price-minicart {
+            margin-bottom: @indent__xs;
         }
-        .weee[data-label] {
-            .font-size(11);
-            .label {
-                &:extend(.abs-no-display all);
+        .product-item-name {
+            font-weight: @font-weight__regular;
+            margin: 0 0 @indent__s;
+            a {
+                .css(color, @link__color);
             }
         }
-        .details-qty {
-            margin-top: @indent__s;
+        .product-item-details {
+            padding-left: 88px;
+            .price {
+                font-weight: @font-weight__bold;
+            }
+            .price-including-tax,
+            .price-excluding-tax {
+                margin: @indent__xs 0;
+            }
+            .weee[data-label] {
+                .font-size(11);
+                .label {
+                    &:extend(.abs-no-display all);
+                }
+            }
+            .details-qty {
+                margin-top: @indent__s;
+            }
         }
-    }
-    .product {
-        .toggle {
-            &:extend(.abs-toggling-title all);
-            &:after {
-                position: static;
-                margin: 0 0 0 @indent__xs;
-                .css(color, @color-gray56);
+        .product {
+            > .product-item-photo,
+            > .product-image-container {
+                float: left;
+            }
+            .toggle {
+                &:extend(.abs-toggling-title all);
+                &:after {
+                    position: static;
+                    margin: 0 0 0 @indent__xs;
+                    .css(color, @color-gray56);
+                }
+                border: 0;
+                padding: 0 @indent__xl @indent__xs 0;
+            }
+            .active {
+                > .toggle {
+                    .icon-font-symbol(
+                        @_icon-font-content: @icon-up,
+                        @_icon-font-position: after
+                    );
+                }
+            }
+            &.pricing {
+                margin-top: 3px;
+            }
+            &.options {
+                .tooltip.toggle {
+                    .icon-font(
+                        @icon-down,
+                        @_icon-font-size: 12px,
+                        @_icon-font-line-height: 12px,
+                        @_icon-font-text-hide: true,
+                        @_icon-font-margin: -3px 0 0 7px,
+                        @_icon-font-position: after
+                    );
+                }
+                .details {
+                    display: none;
+                }
             }
-            border: 0;
-            padding: 0 @indent__xl @indent__xs 0;
         }
-        .active {
-            > .toggle {
-                .icon-font-symbol(
-                    @_icon-font-content: @icon-up,
-                    @_icon-font-position: after
-                );
+        .details-qty,
+        .price-minicart {
+            .label {
+                &:extend(.abs-colon all);
             }
         }
-        &.pricing {
-            margin-top: 3px;
+        .item-qty {
+            width: 40px;
+            text-align: center;
+            margin-right: @indent__s;
+        }
+        .update-cart-item {
+            vertical-align: top;
+            .font-size(11);
         }
-        &.options {
-            .tooltip.toggle {
+        .action {
+            &.edit,
+            &.delete {
                 .icon-font(
-                    @icon-down,
-                    @_icon-font-size: 12px,
-                    @_icon-font-line-height: 12px,
+                    @icon-edit,
+                    @_icon-font-size: 18px,
+                    @_icon-font-line-height: 20px,
                     @_icon-font-text-hide: true,
-                    @_icon-font-margin: -3px 0 0 7px,
-                    @_icon-font-position: after
+                    @_icon-font-color: @minicart-icons-color,
+                    @_icon-font-color-hover: @primary__color,
+                    @_icon-font-color-active: @minicart-icons-color
                 );
             }
-            .details {
-                display: none;
+            &.delete {
+                .icon-font-symbol(
+                    @_icon-font-content: @icon-trash
+                );
             }
         }
-    }
-    .details-qty,
-    .price-minicart {
-        .label {
-            &:extend(.abs-colon all);
-        }
-    }
-    .item-qty {
-        width: 40px;
-        text-align: center;
-        margin-right: @indent__s;
-    }
-    .update-cart-item {
-        vertical-align: top;
-        .font-size(11);
-    }
-    .action {
-        &.edit,
-        &.delete {
-            .icon-font(
-                @icon-edit,
-                @_icon-font-size: 18px,
-                @_icon-font-line-height: 20px,
-                @_icon-font-text-hide: true,
-                @_icon-font-color: @minicart-icons-color,
-                @_icon-font-color-hover: @primary__color,
-                @_icon-font-color-active: @minicart-icons-color
-            );
-        }
-        &.delete {
-            .icon-font-symbol(
-                @_icon-font-content: @icon-trash
-            );
+        .subtitle {
+            display: none;
         }
     }
-}
 
 }
 
 //
 //  Mobile
-//  ---------------------------------------------
+//  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
     .minicart-wrapper .block-minicart {
@@ -345,7 +347,7 @@
 
 //
 //  Desktop
-//  ---------------------------------------------
+//  _____________________________________________
 
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .minicart-wrapper {
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less
new file mode 100644
index 0000000000000000000000000000000000000000..f8f2ee61ddae6ef52ea6ee2ca6a73c0b2c118cde
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less
@@ -0,0 +1,94 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-wrapper__margin: @indent__base;
+@checkout-wrapper__columns: 16;
+
+@checkout-step-title__border: @border-width__base solid @color-gray80;
+@checkout-step-title__font-size: 26px;
+@checkout-step-title__font-weight: @font-weight__light;
+@checkout-step-title__margin-bottom: 28px;
+@checkout-step-title__padding: @indent__s;
+
+@checkout-step-title-mobile__font-size: 18px;
+@checkout-step-title-mobile__margin-bottom: @indent__base;
+
+@checkout-step-content-mobile__background: @color-gray-light01;
+@checkout-step-content-mobile__margin-s: 15px;
+@checkout-step-content-mobile__margin: 0 -(@checkout-step-content-mobile__margin-s) @checkout-step-content-mobile__margin-s;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    .checkout-container {
+        &:extend(.abs-add-clearfix all);
+        .css(margin, 0 0 @checkout-wrapper__margin);
+    }
+
+    .opc-wrapper {
+        .css(margin, 0 0 @checkout-wrapper__margin);
+
+        .opc {
+            &:extend(.abs-reset-list all);
+        }
+
+        .step-title {
+            &:extend(.abs-checkout-title all);
+            .css(border-bottom, @checkout-step-title__border);
+            .css(margin, 0 0 @checkout-step-title__margin-bottom);
+        }
+
+        .step-content {
+            margin: 0 0 @indent__xl;
+        }
+    }
+
+    .checkout-onepage-index {
+        .nav-sections,
+        .nav-toggle {
+            display: none;
+        }
+        .logo {
+            margin-left: 0;
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .opc-wrapper {
+        .step-title {
+            .css(font-size, @checkout-step-title-mobile__font-size);
+            .css(margin-bottom, @checkout-step-title-mobile__margin-bottom);
+            border-bottom: 0;
+            padding-bottom: 0;
+        }
+        .step-content {
+            .css(margin, 0 0 @checkout-step-content-mobile__margin-s);
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-wrapper {
+       &:extend(.abs-add-box-sizing-desktop-m all);
+        .layout-column(2, 1, @checkout-wrapper__columns);
+        padding-right: @indent__l;
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less
new file mode 100644
index 0000000000000000000000000000000000000000..ccef519f1cbb1cbb51a1937d9a1ee524e74d621b
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less
@@ -0,0 +1,58 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Checkout Estimated Total
+    //  ---------------------------------------------
+
+    .opc-estimated-wrapper {
+        &:extend(.abs-no-display-desktop all);
+        &:extend(.abs-add-clearfix all);
+        .css(background, @checkout-step-content-mobile__background);
+        .css(border-bottom, @checkout-step-title__border);
+        .css(border-top, @checkout-step-title__border);
+        .css(margin, -21px -(@checkout-step-content-mobile__margin-s) @checkout-step-content-mobile__margin-s);
+        padding: 18px 15px;
+
+        .estimated-block {
+            .css(font-size, @checkout-step-title-mobile__font-size);
+            float: left;
+            font-weight: @font-weight__bold;
+
+            .estimated-label {
+                display: block;
+                margin: 0 0 @indent__xs;
+            }
+        }
+
+        .minicart-wrapper {
+            button {
+                // todo ui: Change .action.showcart to .action-showcart
+                &.action.showcart {
+                    .button-reset();
+                    &:before {
+                        .css(color, @primary__color);
+                    }
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) {
+    .opc-estimated-wrapper {
+        display: none;
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less
new file mode 100644
index 0000000000000000000000000000000000000000..7b2c5a55d6aa4e9000be31b548c098fa17adf33d
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less
@@ -0,0 +1,90 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-modal-popup__width: 800px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .field-tooltip {
+                .field-tooltip-content {
+                    &:extend(.abs-checkout-tooltip-content-position-top all);
+                }
+            }
+            .fieldset {
+                .field {
+                    .label {
+                        font-weight: @font-weight__regular;
+                    }
+                }
+            }
+            .modal-footer {
+                .action-hide-popup {
+                    &:extend(.abs-action-button-as-link all);
+                    margin-top: 8px;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .modal-footer {
+                .action-save-address {
+                    width: 100%;
+                }
+                .action-hide-popup {
+                    margin-top: @indent__base;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .form-shipping-address {
+                .css(max-width, @checkout-shipping-address__max-width);
+            }
+            .modal-footer {
+                .action-save-address {
+                    float: right;
+                    margin: 0 0 0 @indent__base;
+                }
+            }
+        }
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {
+    .checkout-onepage-index {
+        .modal-popup {
+            .modal-inner-wrap {
+                .css(margin-left, -(@checkout-modal-popup__width/2));
+                .css(width, @checkout-modal-popup__width);
+                left: 50%;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less
new file mode 100644
index 0000000000000000000000000000000000000000..b77969dddddadfcd9985ed4fde68e3ef7aa9a5b6
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less
@@ -0,0 +1,188 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-summary__background-color: @color-white-smoke;
+@checkout-summary__padding: 22px @indent__l;
+
+@checkout-summary-title__margin: @indent__s;
+@checkout-summary-mark-value__color: @color-gray60;
+
+@checkout-summary-items__max-height: 370px;
+@checkout-summary-items__padding: 15px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Order Summary
+    //  ---------------------------------------------
+
+    .opc-block-summary {
+        .css(background, @checkout-summary__background-color);
+        .css(margin, 0 0 @checkout-sidebar__margin);
+        .css(padding, @checkout-summary__padding);
+        &:extend(.abs-add-box-sizing all);
+
+        > .title {
+            &:extend(.abs-checkout-title all);
+            display: block;
+        }
+
+        //  Totals table
+        .table-totals {
+            &:extend(.abs-sidebar-totals all);
+        }
+
+        .mark {
+            .value {
+                .css(color, @checkout-summary-mark-value__color);
+                display: block;
+            }
+        }
+
+        .grand.incl {
+            & + .grand.excl {
+                .mark,
+                .amount {
+                    border-top: 0;
+                    .font-size(14);
+                    padding-top: 0;
+                    strong {
+                        font-weight: @font-weight__regular;
+                    }
+                }
+            }
+        }
+
+        .not-calculated {
+            font-style: italic;
+        }
+
+        //
+        //  Items list
+        //  ---------------------------------------------
+
+        //  Block title
+        .items-in-cart {
+            > .title {
+                border-bottom: @border-width__base solid @border-color__base;
+                .css(padding, @indent__s @indent__xl @indent__s 0);
+                cursor: pointer;
+                .icon-font(
+                @icon-down,
+                @_icon-font-size: 12px,
+                @_icon-font-line-height: 12px,
+                @_icon-font-text-hide: true,
+                @_icon-font-margin: 3px 0 0,
+                @_icon-font-position: after,
+                @_icon-font-display: block
+                );
+                margin-bottom: 0;
+                position: relative;
+                &:after {
+                    position: absolute;
+                    right: 0;
+                    top: @indent__s;
+                }
+                strong {
+                    .font-size(18);
+                    font-weight: @font-weight__light;
+                    margin: 0;
+                }
+            }
+            &.active {
+                > .title {
+                    .icon-font-symbol(
+                    @_icon-font-content: @icon-up,
+                    @_icon-font-position: after
+                    );
+                }
+            }
+            .product {
+                position: relative;
+            }
+        }
+
+        //  Cart items
+        .minicart-items-wrapper {
+            .css(margin, 0 -(@checkout-summary-items__padding) 0 0);
+            .css(max-height, @checkout-summary-items__max-height);
+            .css(padding, @checkout-summary-items__padding @checkout-summary-items__padding 0 0);
+            border: 0;
+        }
+        .column.main & {
+            .product-item {
+                margin: 0;
+                padding-left: 0;
+            }
+        }
+        .product-item {
+            .product-item-inner {
+                display: table;
+                margin: 0 0 @indent__s;
+                width: 100%;
+            }
+            .product-item-name-block {
+                display: table-cell;
+                padding-right: @indent__xs;
+                text-align: left;
+            }
+            .subtotal {
+                display: table-cell;
+                text-align: right;
+            }
+            .price {
+                .font-size(16);
+                font-weight: @font-weight__regular;
+            }
+            .price-including-tax {
+                & + .price-excluding-tax {
+                    .price {
+                        .font-size(10);
+                    }
+                }
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .opc-block-summary {
+        > .title {
+            border-bottom: 0;
+            .css(font-size, @checkout-step-title-mobile__font-size);
+            .css(margin-bottom, @checkout-step-title-mobile__margin-bottom);
+            padding-bottom: 0;
+        }
+        .totals {
+            &:extend(.abs-sidebar-totals-mobile all);
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .opc-summary-wrapper {
+        .modal-header {
+            .action-close {
+                display: none;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less
new file mode 100644
index 0000000000000000000000000000000000000000..13b59d044d72bef7d86ee8c84ee5979a3745407c
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less
@@ -0,0 +1,181 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-progress-bar__font-size: 18px;
+@checkout-progress-bar__font-weight: @font-weight__light;
+@checkout-progress-bar__margin: @indent__base;
+
+@checkout-progress-bar-item__background-color: @color-gray-middle1;
+@checkout-progress-bar-item__border-radius: 6px;
+@checkout-progress-bar-item__color: @primary__color;
+@checkout-progress-bar-item__margin: @indent__s;
+@checkout-progress-bar-item__transition: background .3s;
+@checkout-progress-bar-item__width: 185px;
+
+@checkout-progress-bar-item__active__background-color: @color-orange-red1;
+@checkout-progress-bar-item__complete__color: @link__color;
+@checkout-progress-bar-item__hover__background-color: darken(@checkout-progress-bar-item__background-color, 5%);
+
+@checkout-progress-bar-item-element__height: @checkout-progress-bar-item-element__width;
+@checkout-progress-bar-item-element__width: 38px;
+
+@checkout-progress-bar-item-element-inner__background-color: @page__background-color;
+@checkout-progress-bar-item-element-inner__color: @checkout-progress-bar-item__color;
+@checkout-progress-bar-item-element-inner__height: @checkout-progress-bar-item-element-inner__width;
+@checkout-progress-bar-item-element-inner__width: @checkout-progress-bar-item-element__width - ( @checkout-progress-bar-item-element-outer-radius__width*2 );
+@checkout-progress-bar-item-element-inner__active__content: @icon-checkmark;
+
+@checkout-progress-bar-item-element-outer-radius__width: 6px;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    //
+    //  Checkout Progress Bar
+    //  ---------------------------------------------
+
+    .opc-progress-bar {
+        &:extend(.abs-no-display-s all);
+        &:extend(.abs-reset-list all);
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) {
+
+    .opc-progress-bar {
+        .css(margin, 0 0 @checkout-progress-bar__margin);
+        counter-reset: i;
+        font-size: 0;
+    }
+
+    .opc-progress-bar-item {
+        .css(margin, 0 0 @checkout-progress-bar-item__margin);
+        .css(width, @checkout-progress-bar-item__width);
+        display: inline-block;
+        position: relative;
+        text-align: center;
+        vertical-align: top;
+
+        &:before { // Horizontal line
+            .css(background, @checkout-progress-bar-item__background-color);
+            .css(top, @checkout-progress-bar-item-element__width/2);
+            .css(transition, @checkout-progress-bar-item__transition);
+            content: '';
+            height: 7px;
+            left: 0;
+            position: absolute;
+            width: 100%;
+        }
+
+        &:first-child {
+            &:before {
+                .css(border-radius, @checkout-progress-bar-item__border-radius 0 0 @checkout-progress-bar-item__border-radius);
+            }
+        }
+
+        &:last-child {
+            &:before {
+                .css(border-radius, 0 @checkout-progress-bar-item__border-radius @checkout-progress-bar-item__border-radius 0);
+            }
+        }
+
+        > span {
+            display: inline-block;
+            padding-top: 45px;
+            width: 100%;
+            word-wrap: break-word;
+
+            .typography(
+            @_color: @checkout-progress-bar-item__background-color,
+            @_font-family: false,
+            @_font-size: @checkout-progress-bar__font-size,
+            @_font-style: false,
+            @_font-weight: @checkout-progress-bar__font-weight,
+            @_line-height: false
+            );
+
+            &:before, // Item element
+            &:after {
+                .css(background, @checkout-progress-bar-item__background-color);
+                .css(height, @checkout-progress-bar-item-element__height);
+                .css(margin-left, -(@checkout-progress-bar-item-element__width/2));
+                .css(transition, @checkout-progress-bar-item__transition);
+                .css(width, @checkout-progress-bar-item-element__width);
+                border-radius: 50%;
+                content: '';
+                left: 50%;
+                position: absolute;
+                top: 0;
+            }
+
+            &:after { // Item element inner
+                .css(background, @checkout-progress-bar-item-element-inner__background-color);
+                .css(height, @checkout-progress-bar-item-element-inner__height);
+                .css(margin-left, -(@checkout-progress-bar-item-element-inner__width/2));
+                .css(top, @checkout-progress-bar-item-element-outer-radius__width);
+                .css(width, @checkout-progress-bar-item-element-inner__width);
+                content: counter(i);
+                counter-increment: i;
+                .typography(
+                @_color: @checkout-progress-bar-item-element-inner__color,
+                @_font-family: false,
+                @_font-size: @checkout-progress-bar__font-size,
+                @_font-style: false,
+                @_font-weight: @font-weight__semibold,
+                @_line-height: false
+                );
+            }
+        }
+
+        &._complete {
+            cursor: pointer;
+            &:hover {
+                &:before {
+                    .css(background, @checkout-progress-bar-item__hover__background-color);
+                }
+                > span {
+                    &:before {
+                        .css(background, @checkout-progress-bar-item__hover__background-color);
+                    }
+                }
+            }
+            > span {
+                .css(color, @checkout-progress-bar-item__complete__color);
+
+                &:after {
+                    .css(font-family, @icons__font-name);
+                    .css(content, @checkout-progress-bar-item-element-inner__active__content);
+                }
+            }
+        }
+
+        &._active {
+            &:before {
+                background: @checkout-progress-bar-item__active__background-color;
+            }
+            > span {
+                .css(color, @checkout-progress-bar-item__color);
+                &:before {
+                    .css(background, @checkout-progress-bar-item__active__background-color);
+                }
+                &:after {
+                    .css(font-family, @icons__font-name);
+                    .css(content, @checkout-progress-bar-item-element-inner__active__content);
+                }
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less
new file mode 100644
index 0000000000000000000000000000000000000000..fb2d200134402a5cc74cf30552da410b542dc21e
--- /dev/null
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less
@@ -0,0 +1,340 @@
+// /**
+//  * Copyright © 2015 Magento. All rights reserved.
+//  * See COPYING.txt for license details.
+//  */
+
+//
+//  Variables
+//  _____________________________________________
+
+@checkout-shipping-address__max-width: 500px;
+
+@checkout-shipping-item-icon__background-color: @checkout-shipping-item__active__border-color;
+@checkout-shipping-item-icon__color: @color-white;
+@checkout-shipping-item-icon__content: @icon-checkmark;
+
+@checkout-shipping-item__border: 2px solid transparent;
+@checkout-shipping-item__line-height: 30px;
+@checkout-shipping-item__margin: 0 0 @indent__base;
+@checkout-shipping-item__padding: @indent__base (@indent__l + 5px) @indent__base @indent__base;
+@checkout-shipping-item__transition: .3s border-color;
+@checkout-shipping-item__width: 100%/3;
+@checkout-shipping-item-tablet__width: 100%/2;
+@checkout-shipping-item-mobile__width: 100%;
+@checkout-shipping-item__active__border-color: @color-orange-red1;
+
+@checkout-shipping-item-icon__selected__height: 27px;
+@checkout-shipping-item-icon__selected__width: 29px;
+
+@checkout-shipping-item-mobile__padding: 0 0 15px;
+@checkout-shipping-item-mobile__margin: @checkout-shipping-item-mobile__padding;
+@checkout-shipping-item-mobile__active__padding: 15px (@indent__l + 5px) 15px 18px;
+
+@checkout-shipping-item-before__border-color: @color-gray80;
+@checkout-shipping-item-before__height: calc(~"100% - 20px");
+
+@checkout-shipping-method__border: @checkout-step-title__border;
+@checkout-shipping-method__padding: @indent__base;
+
+//
+//  Common
+//  _____________________________________________
+
+& when (@media-common = true) {
+
+    .opc-wrapper {
+
+        //
+        //  Shipping Address
+        //  ---------------------------------------------
+
+        .form-login,
+        .form-shipping-address {
+            .css(margin-bottom, @checkout-step-title__margin-bottom);
+            .fieldset {
+                .field {
+                    .label {
+                        font-weight: @font-weight__regular;
+                    }
+                }
+                .note {
+                    font-size: @font-size__base;
+                    margin-top: @indent__s;
+                }
+            }
+        }
+
+        .shipping-address-items {
+            font-size: 0;
+        }
+
+        .shipping-address-item {
+            &:extend(.abs-add-box-sizing all);
+            .css(border, @checkout-shipping-item__border);
+            .css(font-size, @font-size__base);
+            .css(line-height, @checkout-shipping-item__line-height);
+            .css(margin, @checkout-shipping-item__margin);
+            .css(padding, @checkout-shipping-item__padding);
+            .css(transition, @checkout-shipping-item__transition);
+            .css(width, @checkout-shipping-item-tablet__width);
+            display: inline-block;
+            position: relative;
+            vertical-align: top;
+            word-wrap: break-word;
+
+            &.selected-item {
+                .css(border-color, @checkout-shipping-item__active__border-color);
+
+                &:after {
+                    .css(background, @checkout-shipping-item-icon__background-color);
+                    .css(color, @checkout-shipping-item-icon__color);
+                    .css(content, @checkout-shipping-item-icon__content);
+                    .css(font-family, @icons__font-name);
+                    .css(height, @checkout-shipping-item-icon__selected__height);
+                    .css(width, @checkout-shipping-item-icon__selected__width);
+                    font-size: 19px;
+                    line-height: 21px;
+                    padding-top: 2px;
+                    position: absolute;
+                    right: 0;
+                    text-align: center;
+                    top: 0;
+                }
+
+                .action-select-shipping-item {
+                    &:extend(.abs-no-display-s all);
+                    visibility: hidden;
+                }
+            }
+        }
+
+        .field {
+            &.addresses {
+                &:extend(.abs-add-clearfix all);
+            }
+        }
+
+        .action-show-popup {
+            margin: 0 0 @indent__base;
+            > span {
+                &:before {
+                    content: '+';
+                    padding-right: @indent__xs;
+                }
+            }
+        }
+
+        .action-select-shipping-item {
+            float: right;
+            margin: @indent__base 0 0;
+        }
+
+        .edit-address-link {
+            &:extend(.abs-action-button-as-link all);
+            display: block;
+            float: left;
+            margin: 26px 5px 0 0;
+        }
+    }
+
+    //
+    //  Shipping Methods
+    //  ---------------------------------------------
+
+    .checkout-shipping-method {
+        .step-title {
+            margin-bottom: 0;
+        }
+        .no-quotes-block {
+            margin: @indent__base 0;
+        }
+    }
+
+    .methods-shipping {
+        .actions-toolbar {
+            .action {
+                &.primary {
+                    &:extend(.abs-button-l all);
+                    margin: @indent__base 0 0;
+                }
+            }
+        }
+    }
+
+    .table-checkout-shipping-method {
+        thead {
+            th {
+                display: none;
+            }
+        }
+        tbody {
+            td {
+                .css(border-top, @checkout-shipping-method__border);
+                .css(padding-bottom, @checkout-shipping-method__padding);
+                .css(padding-top, @checkout-shipping-method__padding);
+                &:first-child {
+                    padding-left: 0;
+                    padding-right: 0;
+                    width: 20px;
+                }
+            }
+            tr {
+                &:first-child {
+                    td {
+                        border-top: none;
+                    }
+                }
+            }
+            .col-price {
+                font-weight: @font-weight__semibold;
+            }
+            .row-error {
+                td {
+                    border-top: none;
+                    padding-bottom: @indent__s;
+                    padding-top: 0;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Mobile
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .opc-wrapper {
+        .form-login,
+        .form-shipping-address,
+        .methods-shipping {
+            .css(background, @checkout-step-content-mobile__background);
+            .css(margin, @checkout-step-content-mobile__margin);
+            .css(padding, @indent__base @checkout-step-content-mobile__margin-s);
+        }
+
+        .form-login {
+            + .form-shipping-address {
+                .css(margin-top, -(@checkout-step-content-mobile__margin-s));
+            }
+        }
+
+        .shipping-address-item {
+            .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color);
+            .css(margin, @checkout-shipping-item-mobile__margin);
+            .css(padding, @checkout-shipping-item-mobile__padding);
+            .css(width, @checkout-shipping-item-mobile__width);
+            &.selected-item {
+                .css(padding, @checkout-shipping-item-mobile__active__padding);
+                border-bottom-width: 2px;
+
+                .edit-address-link {
+                    .css(right, @checkout-shipping-item-icon__selected__width + @indent__s);
+                }
+            }
+        }
+
+        .action-select-shipping-item {
+            float: none;
+            margin-top: @indent__s;
+            width: 100%;
+        }
+
+        .action-show-popup {
+            width: 100%;
+        }
+
+        .methods-shipping {
+            .css(border-bottom, @checkout-step-title__border);
+            padding-top: @indent__l;
+        }
+
+        .edit-address-link {
+            .icon-font(
+                @icon-edit,
+                @_icon-font-size: 18px,
+                @_icon-font-line-height: 20px,
+                @_icon-font-text-hide: true,
+                @_icon-font-color: @minicart-icons-color,
+                @_icon-font-color-hover: @primary__color,
+                @_icon-font-color-active: @minicart-icons-color
+            );
+            margin: 0;
+            position: absolute;
+            right: 0;
+            top: 5px;
+        }
+    }
+}
+
+//
+//  Desktop
+//  _____________________________________________
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .checkout-shipping-method {
+        .actions-toolbar {
+            > .primary {
+                float: right;
+            }
+            .action {
+                &.primary {
+                    margin: 0;
+                }
+            }
+        }
+    }
+    .opc-wrapper {
+        .form-login,
+        .form-shipping-address {
+            .css(max-width, @checkout-shipping-address__max-width);
+        }
+
+        .form-login {
+            .css(border-bottom, @checkout-step-title__border);
+            .css(padding-bottom, @checkout-step-title__margin-bottom);
+        }
+    }
+    .table-checkout-shipping-method {
+        width: auto;
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {
+    .opc-wrapper {
+        .shipping-address-item {
+            .css(width, @checkout-shipping-item__width);
+
+            &:before {
+                .css(background, @checkout-shipping-item-before__border-color);
+                .css(height, @checkout-shipping-item-before__height);
+                content: '';
+                left: 0;
+                position: absolute;
+                top: 0;
+                width: 1px;
+            }
+
+            &:nth-child(3n+1) {
+                &:before {
+                    display: none;
+                }
+            }
+
+            &.selected-item {
+                &:before {
+                    display: none;
+                }
+
+                + .shipping-address-item {
+                    &:before {
+                        display: none;
+                    }
+                }
+            }
+        }
+    }
+    .table-checkout-shipping-method {
+        min-width: 500px;
+    }
+}
diff --git a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less
index 0d3b4cd47ec03767fba0a2a1291fccd7235b6d4e..d10ebc66f56eaf506ac65e19b8f07dbb1ade7c37 100644
--- a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less
@@ -274,13 +274,19 @@
         }
         .gift-content {
             border-top: @border-width__base solid @color-gray-light5;
-            margin-left: -@mobile-cart-padding;
             margin-right: -@mobile-cart-padding;
             padding-left: @mobile-cart-padding;
             padding-right: @mobile-cart-padding;
             overflow: hidden;
         }
     }
+
+    .gift-options-cart-item {
+        & + .action-towishlist {
+            left: 43px;
+            position: absolute;
+        }
+    }
 }
 
 //
diff --git a/app/design/frontend/Magento/luma/web/css/source/_extends.less b/app/design/frontend/Magento/luma/web/css/source/_extends.less
index cc4ab06b849cb5eec4233e701e915deedb4285ed..04018f6977c016c96c9444e206a8eb64ba787fff 100644
--- a/app/design/frontend/Magento/luma/web/css/source/_extends.less
+++ b/app/design/frontend/Magento/luma/web/css/source/_extends.less
@@ -4,8 +4,9 @@
 //  */
 
 //
-//    List default styles reset
-//--------------------------------------
+//  List default styles reset
+//  ---------------------------------------------
+
 .abs-reset-list {
     .list-reset-styles();
     > li {
@@ -14,16 +15,18 @@
 }
 
 //
-//    Primary button
-//--------------------------------------
+//  Primary button
+//  ---------------------------------------------
+
 .action-primary {
     .button-primary();
     .css(border-radius, @button__border-radius);
 }
 
 //
-//    Secondary button
-//--------------------------------------
+//  Secondary button
+//  ---------------------------------------------
+
 .abs-revert-to-action-secondary {
     &:extend(.abs-revert-secondary-color all);
     .css(border-radius, @button__border-radius);
@@ -36,8 +39,9 @@
 }
 
 //
-//    Link as a button
-//--------------------------------------
+//  Link as a button
+//  ---------------------------------------------
+
 .abs-action-link-button {
     .button();
     .link-as-button();
@@ -46,7 +50,8 @@
 
 //
 //   Button as a link
-//--------------------------------------
+//  ---------------------------------------------
+
 .abs-action-button-as-link {
     .button-as-link(
         @_margin: false
@@ -61,28 +66,32 @@
 
 //
 //   Button revert secondary color
-//--------------------------------------
+//  ---------------------------------------------
+
 .abs-revert-secondary-color {
     .button-revert-secondary-color();
 }
 
 //
 //   Button revert secondary size
-//--------------------------------------
+//  ---------------------------------------------
+
 .abs-revert-secondary-size {
     .button-revert-secondary-size();
 }
 
 //
 //   Large button
-//--------------------------------------
+//  ---------------------------------------------
+
 .abs-button-l {
     .button-l();
 }
 
 //
-//    Product options list
-//--------------------------------------
+//  Product options list
+//  ---------------------------------------------
+
 @abs-product-options-list: {
     dt {
         float: left;
@@ -104,8 +113,9 @@
 }
 
 //
-//    Desktop
-//--------------------------------------
+//  Desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-product-options-list-desktop {
         @abs-product-options-list();
@@ -113,8 +123,9 @@
 }
 
 //
-//    Button reset width, floats, margins
-//--------------------------------------
+//  Button reset width, floats, margins
+//  ---------------------------------------------
+
 .abs-button-responsive {
     .button-responsive();
 }
@@ -126,8 +137,9 @@
 }
 
 //
-//    Blocks in 2 columns
-//--------------------------------------
+//  Blocks in 2 columns
+//  ---------------------------------------------
+
 @abs-blocks-2columns: {
     width: 48%;
     &:nth-child(1) {
@@ -155,8 +167,9 @@
 }
 
 //
-//    Reset image alignment in container
-//--------------------------------------
+//  Reset image alignment in container
+//  ---------------------------------------------
+
 .abs-reset-image-wrapper {
     height: auto;
     padding: 0!important;
@@ -166,8 +179,9 @@
 }
 
 //
-//    Adaptive images
-//--------------------------------------
+//  Adaptive images
+//  ---------------------------------------------
+
 .abs-adaptive-images {
     display: block;
     height: auto;
@@ -182,8 +196,9 @@
 }
 
 //
-//    Title for login blocks
-//--------------------------------------
+//  Title for login blocks
+//  ---------------------------------------------
+
 .abs-login-block-title {
     strong {
         font-weight: 500;
@@ -195,8 +210,9 @@
 }
 
 //
-//    Simple Dropdown
-//--------------------------------------
+//  Simple Dropdown
+//  ---------------------------------------------
+
 .abs-dropdown-simple {
     .dropdown(
         @_dropdown-list-item-padding: 5px 5px 5px 23px,
@@ -210,16 +226,18 @@
 }
 
 //
-//    Input quantity
-//--------------------------------------
+//  Input quantity
+//  ---------------------------------------------
+
 .abs-input-qty {
     width: 54px;
     text-align: center;
 }
 
 //
-//    Marging for blocks & widgets
-//--------------------------------------
+//  Marging for blocks & widgets
+//  ---------------------------------------------
+
 .abs-margin-for-blocks-and-widgets {
     margin-bottom: @indent__xl;
 }
@@ -231,8 +249,9 @@
 }
 
 //
-//    Remove button for blocks
-//--------------------------------------
+//  Remove button for blocks
+//  ---------------------------------------------
+
 .abs-remove-button-for-blocks {
     .icon-font(
         @icon-remove,
@@ -246,8 +265,9 @@
 }
 
 //
-//    Product link
-//--------------------------------------
+//  Product link
+//  ---------------------------------------------
+
 .abs-product-link {
     font-weight: @font-weight__regular;
     > a {
@@ -265,8 +285,9 @@
 }
 
 //
-//    Link
-//--------------------------------------
+//  Link
+//  ---------------------------------------------
+
 .abs-like-link {
     .link();
     cursor: pointer;
@@ -274,7 +295,8 @@
 
 //
 //   Reset left margin
-//--------------------------------------
+//  ---------------------------------------------
+
 @abs-reset-left-margin: {
     margin-left: 0;
 };
@@ -296,8 +318,9 @@
 }
 
 //
-//    Action with icon remove with text
-//--------------------------------------
+//  Action with icon remove with text
+//  ---------------------------------------------
+
 .abs-action-remove {
     &:extend(.abs-action-button-as-link all);
     width: auto;
@@ -308,8 +331,9 @@
 }
 
 //
-//    Action with icon remove with text for desktop
-//--------------------------------------
+//  Action with icon remove with text for desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-action-remove-desktop {
         margin-left: 90%;
@@ -317,8 +341,9 @@
 }
 
 //
-//    Add Recipient
-//--------------------------------------
+//  Add Recipient
+//  ---------------------------------------------
+
 .abs-add-fields {
     .fieldset {
         .field {
@@ -360,8 +385,9 @@
 }
 
 //
-//    Add Recipient for desktop
-//--------------------------------------
+//  Add Recipient for desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-add-fields-desktop {
         .fieldset {
@@ -382,8 +408,9 @@
 }
 
 //
-//    Margin for forms
-//--------------------------------------
+//  Margin for forms
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-margin-for-forms-desktop {
         .css(margin-left, @form-field-type-label-inline__width);
@@ -391,8 +418,9 @@
 }
 
 //
-//    Visibility hidden / show visibility hidden
-//--------------------------------------
+//  Visibility hidden / show visibility hidden
+//  ---------------------------------------------
+
 @abs-hidden: {
     .visibility-hidden();
 };
@@ -402,8 +430,9 @@
 }
 
 //
-//    Visually hidden / show visually hidden
-//--------------------------------------
+//  Visually hidden / show visually hidden
+//  ---------------------------------------------
+
 @abs-visually-hidden: {
     .visually-hidden();
 };
@@ -437,8 +466,9 @@
 }
 
 //
-//    Clearfix
-//--------------------------------------
+//  Clearfix
+//  ---------------------------------------------
+
 @abs-add-clearfix: {
     .clearfix();
 };
@@ -472,8 +502,9 @@
 }
 
 //
-//    Box-sizing
-//--------------------------------------
+//  Box-sizing
+//  ---------------------------------------------
+
 @abs-add-box-sizing: {
     box-sizing: border-box;
 };
@@ -494,9 +525,16 @@
     }
 }
 
+.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
+    .abs-add-box-sizing-desktop-m {
+        @abs-add-box-sizing();
+    }
+}
+
 //
-//    Revert field type
-//--------------------------------------
+//  Revert field type
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-revert-field-type-desktop {
         .fieldset {
@@ -512,8 +550,9 @@
 }
 
 //
-//    Settings icons
-//--------------------------------------
+//  Settings icons
+//  ---------------------------------------------
+
 .abs-navigation-icon {
     .icon-font(
         @_icon-font-content: @icon-down,
@@ -530,8 +569,9 @@
 }
 
 //
-//    Split button
-//--------------------------------------
+//  Split button
+//  ---------------------------------------------
+
 .abs-split-button {
     .dropdown-split(
         @_options-selector : ~".items",
@@ -541,8 +581,9 @@
 }
 
 //
-//    Field 2 column
-//--------------------------------------
+//  Field 2 column
+//  ---------------------------------------------
+
 @abs-form-field-column-2: {
     .fieldset {
         .field {
@@ -572,8 +613,9 @@
 }
 
 //
-//    Field 1 column
-//--------------------------------------
+//  Field 1 column
+//  ---------------------------------------------
+
 @abs-form-field-revert-column-1: {
     .form-field-column-number(@_column-number: 1);
 };
@@ -591,8 +633,9 @@
 }
 
 //
-//    Checkout shipping methods title
-//--------------------------------------
+//  Checkout shipping methods title
+//  ---------------------------------------------
+
 .abs-methods-shipping-title {
     .font-size(16);
     margin-bottom: 15px;
@@ -600,8 +643,9 @@
 }
 
 //
-//    Checkout order review
-//--------------------------------------
+//  Checkout order review
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-checkout-order-review {
         tbody > tr {
@@ -642,8 +686,9 @@
 }
 
 //
-//    Add to Actions
-//--------------------------------------
+//  Add to Actions
+//  ---------------------------------------------
+
 .abs-actions-addto {
     .css(color, @addto-color);
     display: inline-block;
@@ -664,15 +709,17 @@
 }
 
 //
-//    Box-tocart block
-//--------------------------------------
+//  Box-tocart block
+//  ---------------------------------------------
+
 .abs-box-tocart {
     margin: 0 0 @indent__l;
 }
 
 //
-//    General pages forms
-//--------------------------------------
+//  General pages forms
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-forms-general-desktop {
         max-width: 500px;
@@ -686,8 +733,9 @@
 }
 
 //
-//    Revert side paddings
-//--------------------------------------
+//  Revert side paddings
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-revert-side-paddings {
         padding-left: 0;
@@ -696,8 +744,9 @@
 }
 
 //
-//    Abstract toggle title block
-//--------------------------------------
+//  Abstract toggle title block
+//  ---------------------------------------------
+
 @abs-toggling-title: {
     .css(border-top, @border-width__base solid @border-color__base);
     cursor: pointer;
@@ -747,8 +796,9 @@
 }
 
 //
-//    Cart discount block
-//--------------------------------------
+//  Cart discount block
+//  ---------------------------------------------
+
 .abs-cart-block {
     margin: 0;
     > .title {
@@ -780,8 +830,9 @@
 }
 
 //
-//    Checkout order review price
-//--------------------------------------
+//  Checkout order review price
+//  ---------------------------------------------
+
 .abs-checkout-cart-price {
     .css(color, @primary__color__lighter);
     .font-size(16);
@@ -789,8 +840,9 @@
 }
 
 //
-//    Checkout order product name
-//--------------------------------------
+//  Checkout order product name
+//  ---------------------------------------------
+
 .abs-checkout-product-name {
     .font-size(18);
     font-weight: @font-weight__light;
@@ -798,8 +850,9 @@
 }
 
 //
-//    Mobile checkout order product name
-//--------------------------------------
+//  Mobile checkout order product name
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-product-items-summary {
         tbody {
@@ -838,8 +891,9 @@
 }
 
 //
-//    Account pages: title
-//--------------------------------------
+//  Account pages: title
+//  ---------------------------------------------
+
 .abs-account-title {
     > strong,
     > span {
@@ -852,8 +906,9 @@
 }
 
 //
-//    Account pages: block font size
-//--------------------------------------
+//  Account pages: block font size
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-account-block-font-size {
         .font-size(16);
@@ -861,15 +916,17 @@
 }
 
 //
-//    Account pages: block line-height
-//--------------------------------------
+//  Account pages: block line-height
+//  ---------------------------------------------
+
 .abs-account-block-line-height {
     line-height: 24px;
 }
 
 //
-//    Account pages: margin for table
-//--------------------------------------
+//  Account pages: margin for table
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-account-table-margin-mobile {
         .css(margin-top, -@indent__base);
@@ -882,8 +939,9 @@
 }
 
 //
-//    Account pages: table col actions
-//--------------------------------------
+//  Account pages: table col actions
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-col-no-prefix {
         &:before {
@@ -893,8 +951,9 @@
 }
 
 //
-//    Account pages: order table summary
-//--------------------------------------
+//  Account pages: order table summary
+//  ---------------------------------------------
+
 .abs-account-summary {
     td {
         .css(background, @sidebar__background-color);
@@ -902,8 +961,9 @@
 }
 
 //
-//    Action print with icon
-//--------------------------------------
+//  Action print with icon
+//  ---------------------------------------------
+
 @abs-action-print: {
     .icon-font(
         @icon-print,
@@ -930,8 +990,9 @@
 }
 
 //
-//    Excl/Incl tax
-//--------------------------------------
+//  Excl/Incl tax
+//  ---------------------------------------------
+
 .abs-incl-excl-tax {
     .price-including-tax,
     .price-excluding-tax {
@@ -965,8 +1026,9 @@
 }
 
 //
-//    Cart tax total
-//--------------------------------------
+//  Cart tax total
+//  ---------------------------------------------
+
 .abs-tax-total {
     cursor: pointer;
     position: relative;
@@ -993,15 +1055,17 @@
 }
 
 //
-//    Forms: margin-bottom for small forms
-//--------------------------------------
+//  Forms: margin-bottom for small forms
+//  ---------------------------------------------
+
 .abs-forms-margin-small {
     .css(margin-bottom, @indent__base);
 }
 
 //
-//    Forms: margin-bottom for small forms
-//--------------------------------------
+//  Forms: margin-bottom for small forms
+//  ---------------------------------------------
+
 .abs-rating-summary {
     .rating {
         &-summary {
@@ -1022,8 +1086,9 @@
 }
 
 //
-//    Account pages: actions
-//--------------------------------------
+//  Account pages: actions
+//  ---------------------------------------------
+
 .abs-account-actions {
     &:after {
         content: "";
@@ -1041,8 +1106,9 @@
 }
 
 //
-//    Account blocks
-//--------------------------------------
+//  Account blocks
+//  ---------------------------------------------
+
 .abs-account-blocks {
     .block-title {
         &:extend(.abs-account-title all);
@@ -1064,8 +1130,9 @@
 }
 
 //
-//    Add colon
-//--------------------------------------
+//  Add colon
+//  ---------------------------------------------
+
 .abs-colon {
     &:after {
         content: ": ";
@@ -1073,8 +1140,9 @@
 }
 
 //
-//    Icon - create add
-//--------------------------------------
+//  Icon - create add
+//  ---------------------------------------------
+
 .abs-icon-add {
     .icon-font(
         @_icon-font-content: @icon-expand,
@@ -1098,8 +1166,9 @@
 }
 
 //
-//    Dropdown items - create new
-//--------------------------------------
+//  Dropdown items - create new
+//  ---------------------------------------------
+
 .abs-dropdown-items-new {
     .items .item:last-child {
         &:hover {
@@ -1116,8 +1185,9 @@
 }
 
 //
-//    Abstract no display
-//--------------------------------------
+//  Abstract no display
+//  ---------------------------------------------
+
 @abs-no-display: {
     display: none;
 };
@@ -1139,8 +1209,9 @@
 }
 
 //
-//    Status
-//--------------------------------------
+//  Status
+//  ---------------------------------------------
+
 .abs-status {
     .css(border, 2px solid @border-color__base);
     border-radius: 3px;
@@ -1159,8 +1230,9 @@
 }
 
 //
-//    Page title - orders pages
-//--------------------------------------
+//  Page title - orders pages
+//  ---------------------------------------------
+
 .abs-title-orders {
     .page-main {
         .page-title-wrapper {
@@ -1208,8 +1280,9 @@
 }
 
 //
-//    Table striped
-//--------------------------------------
+//  Table striped
+//  ---------------------------------------------
+
 .abs-table-striped {
     .table-striped(
         @_stripped-highlight: even
@@ -1228,8 +1301,9 @@
 }
 
 //
-//    Table bordered desktop
-//--------------------------------------
+//  Table bordered desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-table-bordered-desktop {
         .table-bordered(
@@ -1240,8 +1314,9 @@
 }
 
 //
-//    Pager toolbar for non-catalog pages desktop
-//--------------------------------------
+//  Pager toolbar for non-catalog pages desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .abs-pager-toolbar {
         position: relative;
@@ -1263,8 +1338,9 @@
 }
 
 //
-//    Items counter in blocks
-//--------------------------------------
+//  Items counter in blocks
+//  ---------------------------------------------
+
 .abs-block-items-counter {
     .css(color, @primary__color__lighter);
     .font-size(12px);
@@ -1272,8 +1348,9 @@
 }
 
 //
-//    Sidebar and widget blocks title
-//--------------------------------------
+//  Sidebar and widget blocks title
+//  ---------------------------------------------
+
 .abs-block-widget-title {
     strong {
         font-size: @font-size__l;
@@ -1283,8 +1360,9 @@
 }
 
 //
-//    Shopping cart items
-//--------------------------------------
+//  Shopping cart items
+//  ---------------------------------------------
+
 .abs-shopping-cart-items {
     margin-bottom: @indent__base;
     .actions.main {
@@ -1305,8 +1383,9 @@
 }
 
 //
-//    Remove top border
-//--------------------------------------
+//  Remove top border
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-no-border-top {
         border-top: 0;
@@ -1314,7 +1393,7 @@
 }
 
 //
-//    Remove bottom border
+//  Remove bottom border
 //--------------------------------------
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
     .abs-no-border-bottom {
@@ -1323,8 +1402,9 @@
 }
 
 //
-//    Form Field Date
-//--------------------------------------
+//  Form Field Date
+//  ---------------------------------------------
+
 .abs-field-date {
     .control {
         position: relative;
@@ -1336,9 +1416,207 @@
 }
 
 //
-//    Form Field Date Input
-//--------------------------------------
+//  Form Field Date Input
+//  ---------------------------------------------
+
 .abs-field-date-input {
-    margin-right: @indent__s;
+    .css(margin-right, @indent__s);
     width: calc(~"100% - (@{icon-calendar__font-size} + @{indent__s})");
 }
+
+//
+//  Form Field Tooltip
+//  ---------------------------------------------
+
+.abs-field-tooltip {
+    &:extend(.abs-add-box-sizing all);
+    position: relative;
+    input {
+        .css(margin-right, @indent__s);
+        width: calc(~"100% - (@{checkout-tooltip-icon__font-size} + @{indent__s} + @{indent__xs})");
+        &:focus {
+            + .field-tooltip {
+                .field-tooltip-action {
+                    &:before {
+                        .css(color, @checkout-tooltip-icon__hover__color);
+                    }
+                }
+                .field-tooltip-content {
+                    display: block;
+                }
+            }
+        }
+    }
+}
+
+//
+//  Checkout Tooltip Content (position: top)
+//  ---------------------------------------------
+
+@abs-checkout-tooltip-content-position-top: {
+    .css(right, @checkout-tooltip-content-mobile__right);
+    .css(top, @checkout-tooltip-content-mobile__top);
+    left: auto;
+
+    &:before,
+    &:after {
+        .arrow(
+            @_position: top,
+            @_size: @checkout-tooltip-icon-arrow__font-size,
+            @_color: @checkout-tooltip-content__background-color
+        );
+        .css(margin-top, @checkout-tooltip-icon-arrow__left);
+        .css(right, @indent__s);
+        left: auto;
+        top: 0%;
+    }
+    &:before {
+        .css(border-bottom-color, @checkout-tooltip-content__active__border-color);
+    }
+    &:after {
+        .css(border-bottom-color, @checkout-tooltip-content__background-color);
+        top: 1px;
+    }
+};
+
+.abs-checkout-tooltip-content-position-top {
+    @abs-checkout-tooltip-content-position-top();
+}
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) {
+    .abs-checkout-tooltip-content-position-top-mobile {
+        @abs-checkout-tooltip-content-position-top();
+    }
+}
+
+//
+//  Checkout title
+//  ---------------------------------------------
+
+.abs-checkout-title {
+    .css(padding-bottom, @checkout-step-title__padding);
+    .typography(
+    @_font-size: @checkout-step-title__font-size,
+    @_font-weight: @checkout-step-title__font-weight,
+    @_font-family: false,
+    @_font-style: false,
+    @_line-height: false
+    );
+}
+
+//
+//  Shopping cart sidebar and checkout sidebar totals
+//  ---------------------------------------------
+
+.abs-sidebar-totals {
+    border-top: 1px solid @border-color__base;
+    padding-top: 10px;
+    tbody,
+    tfoot {
+        .mark {
+            border: 0;
+            font-weight: @font-weight__regular;
+            padding: 6px 0;
+        }
+        .amount {
+            border: 0;
+            font-weight: @font-weight__regular;
+            padding: 6px 0 6px 14px;
+            text-align: right;
+        }
+    }
+    .table-caption {
+        &:extend(.abs-no-display all);
+    }
+    .grand {
+        th,
+        td {
+            padding: 11px 0;
+        }
+        strong {
+            display: inline-block;
+            font-weight: @font-weight__semibold;
+            padding: 3px 0 0;
+        }
+        .mark {
+            border-top: 1px solid @border-color__base;
+            .font-size(18);
+            padding-right: @indent__s;
+        }
+        .amount {
+            border-top: 1px solid @border-color__base;
+            .font-size(18);
+        }
+    }
+    .msrp {
+        margin-bottom: @indent__s;
+    }
+    tbody tr:last-child td {
+        padding-bottom: 19px;
+    }
+    .totals-tax {
+        &-summary {
+            .mark,
+            .amount {
+                border-top: @border-width__base solid @border-color__base;
+                border-bottom: @border-width__base solid @border-color__base;
+                cursor: pointer;
+            }
+            .amount .price {
+                position: relative;
+                padding-right: @indent__base;
+                .icon-font(
+                @icon-down,
+                @_icon-font-size: 12px,
+                @_icon-font-line-height: 12px,
+                @_icon-font-text-hide: true,
+                @_icon-font-position: after
+                );
+                &:after {
+                    position: absolute;
+                    right: 3px;
+                    top: 3px;
+                }
+            }
+            &.expanded {
+                .mark,
+                .amount {
+                    border-bottom: 0;
+                }
+                .amount .price {
+                    .icon-font-symbol(
+                    @_icon-font-content: @icon-up,
+                    @_icon-font-position: after
+                    );
+                }
+            }
+        }
+        &-details {
+            display: none;
+            border-bottom: @border-width__base solid @border-color__base;
+            &.shown {
+                display: table-row;
+            }
+        }
+    }
+    .table-wrapper {
+        margin-bottom: 0;
+    }
+}
+
+.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
+    .abs-sidebar-totals-mobile {
+        th {
+            &:extend(.abs-col-no-prefix all);
+        }
+        td {
+            &:extend(.abs-col-no-prefix all);
+        }
+        tbody tr:not(:last-child) td {
+            &:extend(.abs-no-border-bottom-top all);
+        }
+        .amount {
+            text-align: right;
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/luma/web/css/source/_theme.less b/app/design/frontend/Magento/luma/web/css/source/_theme.less
index f293d18d117a1911f079065f25280984a9fd54a7..52914c1bd64117c7cba4af7e2086731a7ae19870 100644
--- a/app/design/frontend/Magento/luma/web/css/source/_theme.less
+++ b/app/design/frontend/Magento/luma/web/css/source/_theme.less
@@ -248,3 +248,23 @@
 @overlay__opacity-old: 70;
 
 @gallery-thumb-border-color-active: @active__color;
+
+//  Modal popup
+@modal-action-close__font-size: @font-size__base;
+
+//  Checkout tooltip icon
+@checkout-tooltip-icon__font-size: 21px;
+
+// Checkout Payment Option icon
+@checkout-payment-option-title-icon__font-size: 14px;
+@checkout-payment-option-title-icon__line-height: 16px;
+@checkout-payment-option-title-icon__margin: 0 0 0 @indent__s;
+
+// Checkout Sidebar Shipping Information
+@checkout-sidebar-shipping-information-edit-icon__content: @icon-edit;
+@checkout-sidebar-shipping-information-edit-icon__font-size: 18px;
+@checkout-sidebar-shipping-information-edit-icon__line-height: 20px;
+@checkout-sidebar-shipping-information-edit-icon__top: @indent__s;
+
+// Checkout
+@checkout-sidebar__columns: 8;
diff --git a/app/design/frontend/Magento/luma/web/css/source/_variables.less b/app/design/frontend/Magento/luma/web/css/source/_variables.less
index dbdbeb65ad660dccec8e724925392cf18b254c96..ee76525dd8cc68c2906c4bfa5aecdbaede9c7f32 100644
--- a/app/design/frontend/Magento/luma/web/css/source/_variables.less
+++ b/app/design/frontend/Magento/luma/web/css/source/_variables.less
@@ -26,7 +26,6 @@
 @icon-success: '\e60e';
 @icon-error: '\e61f';
 @icon-edit: '\e601';
-@icon-help: '\e623';
 @icon-print: '\e624';
 @icon-star-empty: '\e625';
 @icon-download: '\e626';
diff --git a/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg b/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg
index 5e68e79f8e3e44488f98f45b6a4d1408f485d2ec..fa092836d03823258384bc553188cc92e412a02f 100644
--- a/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg
+++ b/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg"><defs><font id="Luma-Icons" horiz-adv-x="512"><font-face units-per-em="512" ascent="480" descent="-32"/><missing-glyph horiz-adv-x="512"/><glyph unicode="&#x20;" d="" horiz-adv-x="256"/><glyph unicode="&#xe600;" d="M436.608 435.568c-65.68 31.424-144.064 2.832-174.976-63.84-2.16-4.64-4.016-10.448-5.664-17.2-1.648 6.752-3.504 12.56-5.632 17.2-30.944 66.672-109.248 95.264-174.944 63.84-65.6-31.424-93.744-110.96-62.832-177.648 30.928-66.672 243.344-257.84 243.344-257.84s0.016 0.224 0.048 0.576c0.048-0.352 0.064-0.576 0.064-0.576s212.512 191.168 243.44 257.84c30.896 66.688 2.832 146.224-62.848 177.648z"/><glyph unicode="&#xe601;" d="M362.533 425.051c-49.81-49.792-20.809-20.772-20.809-20.772l96.402-96.384c0 0-31.067-31.049 20.772 20.773s-46.611 146.194-96.365 96.384zM320.147 383.671l-227.987-227.986 0.329-0.293-54.071-146.524 149.833 50.688 0.311-0.311 0.786 0.805v0.019l227.2 227.2-96.403 96.403zM179.036 104.375l-78.811-33.28 37.047 75.044 38.345 38.363 41.764-41.783-38.345-38.345z"/><glyph unicode="&#xe602;" d="M255.952 480l-255.952-448h512l-256.048 448zM287.12 353.808v-65.36l-16.688-128.544h-27.088l-18.032 128.544-0.992 65.36h62.8zM224.096 64.112v64.112h64.24v-64.112h-64.24z"/><glyph unicode="&#xe603;" d="M363.923 112.019c-29.805-28.764-68.663-43.502-108.013-43.538-35.145 0.036-70.199 11.757-99.347 35.932-37.029 30.829-56.046 74.971-56.1 119.661 0 7.442 0.549 14.829 1.591 22.18l-60.672-11.374c-0.164-3.602-0.292-7.186-0.292-10.807-0.036-61.495 26.459-122.899 77.549-165.285 40.009-33.335 88.887-49.683 137.252-49.683h0.128c56.211 0 112.164 22.217 153.746 64.914l39.844-39.772 0.311 124.745-131.803 0.348 45.805-47.324zM393.344 389.23c-40.046 33.335-88.923 49.664-137.271 49.664-55.808 0-111.397-21.833-152.923-63.945l-37.687 34.798-0.677-120.722 130.487-0.75-46.336 48.493c29.641 28.252 68.188 42.697 107.154 42.733 35.108-0.036 70.217-11.721 99.328-35.932 37.029-30.829 56.046-74.935 56.137-119.698 0-6.437-0.457-12.892-1.225-19.365l60.435 11.593c0.036 2.615 0.164 5.212 0.164 7.772-0.036 61.549-26.514 122.899-77.587 165.357z"/><glyph unicode="&#xe604;" d="M95.792-32h320.4v320.080h-320.4v-320.080zM318.336 228.512c0 9.904 8.032 17.904 17.952 17.904 9.904 0 17.936-8 17.936-17.904v-188.736c0-9.888-8.032-17.92-17.936-17.92-9.92 0-17.952 8.032-17.952 17.92v188.736zM238.048 228.512c0 9.904 8.032 17.904 17.92 17.904s17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92s-17.92 8.032-17.92 17.92v188.736zM157.6 228.512c0 9.904 8 17.904 17.92 17.904 9.888 0 17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92-9.92 0-17.92 8.032-17.92 17.92v188.736zM423.216 416.528h-71.232v10.896c0 29.040-19.76 52.576-48.8 52.576h-94.72c-29.008 0-48.48-23.536-48.48-52.576v-10.896h-71.232c-13.696 0-24.768-11.088-24.768-24.752v-71.984h384v71.984c0 13.664-11.040 24.752-24.768 24.752zM319.936 416.528h-128.192v14.704c0.032 9.248 7.488 16.736 16.72 16.768h94.72c9.216-0.032 16.704-7.52 16.752-16.768v-14.704z"/><glyph unicode="&#xe605;" d="M511.52 278.496c-1.312 4.096-5.152 6.88-9.44 6.88h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 6.992 3.6 11.088z"/><glyph unicode="&#xe606;" d="M473.015 200.375v49.371l-7.003 2.268-52.882 17.244-14.116 34.103 27.154 57.381-34.908 34.907-6.583-3.309-49.555-25.198-34.103 14.117-21.394 59.757h-49.371l-2.286-6.985-17.262-52.882-34.048-14.099-57.399 27.136-34.925-34.926 3.309-6.564 25.18-49.591-14.080-34.029-59.758-21.412v-49.39l6.949-2.249 52.901-17.28 14.099-34.067-27.118-57.38 34.925-34.925 6.528 3.328 49.591 25.197 34.066-14.116 21.394-59.757h49.371l2.286 6.985 17.28 52.882 34.029 14.116 57.399-27.136 34.944 34.908-3.346 6.546-25.197 49.572 14.116 34.067 59.813 21.413zM256 154.861c-38.199 0-69.156 30.957-69.156 69.139 0 38.217 30.958 69.156 69.156 69.156 38.163 0 69.156-30.94 69.156-69.156 0-38.18-31.012-69.139-69.156-69.139z"/><glyph unicode="&#xe607;" d="M31.008 351.36l224.992-239.984 225.040 239.984z"/><glyph unicode="&#xe608;" d="M383.415 226.596l-212.571 218.587-37.285-34.981 178.286-183.277-183.278-188.452 36.48-35.657 205.659 211.456-0.201 0.201z"/><glyph unicode="&#xe609;" d="M52.928 345.2h406.144c11.056 0 20 8.976 20 20.016 0 11.072-8.944 20.032-20 20.032h-406.144c-11.056 0-20.016-8.96-20.016-20.032 0-11.040 8.96-20.016 20.016-20.016zM459.072 244.016h-406.144c-11.056 0-20.016-8.944-20.016-20.016s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.016-20 20.016zM459.072 102.8h-406.144c-11.056 0-20.016-8.96-20.016-20.032s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.032-20 20.032z"/><glyph unicode="&#xe60a;" d="M256.144 480c-89.12 0-161.344-72.24-161.344-161.376 0-89.104 161.344-350.624 161.344-350.624s161.376 261.52 161.376 350.624c0 89.136-72.192 161.376-161.376 161.376zM256.144 269.616c-27.056 0-49.024 21.952-49.024 49.008 0 27.072 21.984 49.024 49.024 49.024 27.104 0 49.088-21.952 49.088-49.024 0-27.056-21.984-49.008-49.088-49.008z"/><glyph unicode="&#xe60b;" d="M0 256.144h224.032v223.808h-224.032v-223.808zM288.128 479.952v-95.728h224.176v95.728h-224.176zM0-32h224.032v223.808h-224.032v-223.808zM288.128 256.144h224.176v95.728h-224.176v-95.728zM288.128 96.080h224.176v95.728h-224.176v-95.728zM288.128-32h224.176v95.712h-224.176v-95.712z"/><glyph unicode="&#xe60c;" d="M332.764 119.003c-9.216 0-45.495-56.027-65.243-56.027-5.284 0-7.863 4.644-7.863 9.216 0 10.569 7.241 27.044 11.154 36.937l47.397 128.384c23.772 63.891-6.546 81.024-34.871 81.024-38.217 0-72.448-19.091-98.779-44.124-8.576-8.576-37.523-36.206-37.523-48.091 0-3.932 3.931-8.576 8.576-8.576 11.813 0 43.447 57.308 67.803 57.308 5.285 0 11.191-5.924 6.583-17.755l-46.080-115.968c-4.644-11.154-27.044-65.171-27.044-96.786 0-25.015 16.476-36.188 40.192-36.188 66.523 0 143.543 81.645 143.543 100.755-0.019 5.925-4.589 9.892-7.844 9.892zM319.543 439.661c-28.947 0-54.016-23.68-54.016-52.663 0-27.008 17.792-44.8 44.837-44.8 29.55 0 54.62 22.4 54.62 52.7 0 27.008-19.072 44.764-45.44 44.764z"/><glyph unicode="&#xe60d;" d="M0 351.552h128.464v128.448h-128.464v-128.448zM191.76 351.552h128.528v128.448h-128.528v-128.448zM383.568 480v-128.448h128.496v128.448h-128.496zM0 159.744h128.464v128.464h-128.464v-128.464zM191.76 159.744h128.528v128.464h-128.528v-128.464zM383.568 159.744h128.496v128.464h-128.496v-128.464zM0-32h128.464v128h-128.464v-128zM191.76-32h128.528v128h-128.528v-128zM383.568-32h128.496v128h-128.496v-128z"/><glyph unicode="&#xe60e;" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM231.936 94.576l-125.936 128.032 32.208 25.936 72.864-57.088c29.76 35.424 96 106.032 187.312 161.984l7.696-17.792c-83.808-77.088-152.48-185.6-174.144-241.072z"/><glyph unicode="&#xe60f;" d="M0 241.12h512v-34.064h-512v34.064z"/><glyph unicode="&#xe610;" d="M478.263 426.149c-142.555-87.388-245.98-197.632-292.48-252.947l-113.792 89.161-50.267-40.539 196.663-199.973c33.847 86.674 141.056 256.11 271.872 376.485l-11.995 27.813z"/><glyph unicode="&#xe611;" d="M220.576 83.248c-26.352 0-47.696-21.376-47.696-47.712s21.344-47.664 47.696-47.664c26.336 0 47.696 21.328 47.696 47.664s-21.36 47.712-47.696 47.712zM385.344 83.248c-26.4 0-47.76-21.376-47.76-47.712s21.344-47.664 47.76-47.664c26.288 0 47.632 21.328 47.632 47.664s-21.344 47.712-47.632 47.712zM459.856 350.32c-122.384 0-319.856 0-319.856 0s-19.152 52.608-37.392 84.864c-14.128 24.976-43.344 23.968-43.344 23.968-20.096 0-33.024-12.288-33.024-32.4 0-20.096 15.92-36.16 36.032-36.16l8.496-0.080 95.2-262.192 266.832-0.208c0 0 48.784 199.632 46.272 191.888 8.944 27.68-2.448 30.32-19.216 30.32zM166.528 257.344c-14 0-25.36 11.36-25.36 25.376s11.36 25.392 25.36 25.392c14.016 0 25.36-11.376 25.36-25.392s-11.344-25.376-25.36-25.376zM220.768 172.64c-14.016 0-25.376 11.376-25.376 25.392 0 13.984 11.36 25.36 25.376 25.36 14 0 25.36-11.376 25.36-25.36 0.016-14.016-11.36-25.392-25.36-25.392zM248.656 257.344c-14 0-25.376 11.36-25.376 25.376s11.36 25.392 25.376 25.392c14 0 25.36-11.376 25.36-25.392s-11.36-25.376-25.36-25.376zM302.896 172.64c-14 0-25.36 11.376-25.36 25.392 0 13.984 11.36 25.36 25.36 25.36 14.048 0 25.44-11.376 25.44-25.36 0-14.016-11.392-25.392-25.44-25.392zM330.848 257.344c-14 0-25.408 11.36-25.408 25.376s11.408 25.392 25.408 25.392c14 0 25.328-11.376 25.328-25.392s-11.328-25.376-25.328-25.376zM385.040 172.64c-13.984 0-25.328 11.376-25.328 25.392 0 13.984 11.36 25.36 25.328 25.36 14 0 25.408-11.376 25.408-25.36 0-14.016-11.408-25.392-25.408-25.392zM412.96 257.344c-14.016 0-25.36 11.36-25.36 25.376s11.344 25.392 25.36 25.392c14.048 0 25.376-11.376 25.376-25.392s-11.328-25.376-25.376-25.376z"/><glyph unicode="&#xe612;" d="M142.992 332.768c10.352 0 18.8 8.4 18.8 18.8v67.68c0 10.368-8.432 18.784-18.8 18.784-10.384 0-18.8-8.4-18.8-18.784v-67.68c0-10.4 8.416-18.8 18.8-18.8zM394.384 383.344v-0.32c7.776-6.944 12.72-17.008 12.72-28.288 0-20.816-16.88-37.712-37.744-37.712s-37.76 16.912-37.76 37.712c0 11.264 4.976 21.344 12.784 28.288v0.32h-176.416v-0.32c7.824-6.944 12.768-17.008 12.768-28.288 0-20.816-16.896-37.712-37.728-37.712-20.864 0-37.744 16.912-37.744 37.712 0 11.264 4.928 21.344 12.752 28.288v0.32h-85.536v-383.6h447.248v383.6h-85.344zM448.72 32.832h-383.152v254.72h383.152v-254.72zM369.36 332.768c10.384 0 18.784 8.4 18.784 18.8v67.68c0 10.368-8.4 18.784-18.784 18.784-10.352 0-18.816-8.4-18.816-18.784v-67.68c0-10.4 8.464-18.8 18.816-18.8zM349.216 184.128h-47.936v-47.872h47.952v47.872zM349.216 256.112h-47.936v-47.824h47.952v47.824zM349.216 114.112h-47.936v-47.872h47.952v47.872zM416.656 256.112h-47.92v-47.824h47.92v47.824zM416.656 184.128h-47.92v-47.872h47.92v47.872zM281.696 256.112h-47.872v-47.824h47.872v47.824zM146.8 184.128h-47.856v-47.872h47.856v47.872zM214.288 114.112h-47.888v-47.872h47.872v47.872zM146.8 114.112h-47.856v-47.872h47.856v47.872zM281.696 184.128h-47.872v-47.872h47.872v47.872zM281.696 114.112h-47.872v-47.872h47.872v47.872zM214.288 184.128h-47.888v-47.872h47.872v47.872zM214.288 256.112h-47.888v-47.824h47.872v47.824z"/><glyph unicode="&#xe613;" d="M256 444.727l-200.814-243.291h131.054v-198.144h139.575v198.144h131.017z"/><glyph unicode="&#xe614;" d="M325.779 246.583v198.144h-139.593v-198.144h-130.999l200.832-243.292 200.813 243.292z"/><glyph unicode="&#xe615;" d="M487.232 35.872c0 0-78.176 80.288-109.328 111.312-13.552 13.552-22.832 22.752-22.832 22.752 10.56 15.088 18.816 31.616 24.704 49.392 5.84 17.76 8.752 36.496 8.752 56.192 0 25.36-4.816 49.2-14.448 71.552-9.664 22.32-22.784 41.824-39.456 58.432-16.64 16.688-36.144 29.824-58.496 39.472-22.336 9.664-46.176 14.496-71.536 14.496-25.344 0-49.184-4.848-71.552-14.496-22.336-9.648-41.712-22.784-58.192-39.472-16.416-16.608-29.52-36.128-39.152-58.448-9.664-22.336-14.496-46.192-14.496-71.552 0-25.376 4.848-49.216 14.496-71.552 9.632-22.304 22.72-41.792 39.152-58.464 16.464-16.608 35.856-29.776 58.176-39.456 22.368-9.664 46.208-14.448 71.552-14.448 19.68 0 38.416 2.88 56.208 8.768 17.776 5.856 34.288 14.144 49.36 24.72 0 0 8.576-8.512 21.2-21.216 34.512-34.64 110.416-113.392 110.416-113.392 11.456-4.992 29.712 0.336 38.848 8.064 9.040 7.776 14.096 23.984 6.624 37.344zM327.792 223.28c-7.008-16.192-16.576-30.336-28.624-42.336-12.096-12.048-26.192-21.616-42.336-28.608-16.128-7.024-33.392-10.528-51.68-10.528-18.704 0-36.096 3.504-52.256 10.528-16.16 7.008-30.288 16.56-42.336 28.608-12.048 12.016-21.616 26.16-28.608 42.336-7.008 16.112-10.512 33.568-10.512 52.24 0 18.272 3.504 35.632 10.512 51.984 6.992 16.336 16.56 30.56 28.608 42.592 12.048 12.096 26.176 21.664 42.336 28.608 16.16 7.056 33.552 10.512 52.256 10.512 18.288 0 35.552-3.456 51.68-10.512 16.144-6.96 30.24-16.512 42.336-28.608 12.032-12.032 21.616-26.256 28.624-42.592 7.008-16.352 10.48-33.712 10.48-51.984 0.016-18.672-3.456-36.128-10.48-52.24z"/><glyph unicode="&#xe616;" d="M483.255 415.177l-36.023 35.968-191.25-191.268-191.25 191.268-35.986-35.968 191.268-191.269-191.123-191.14 35.968-35.932 191.14 191.104 191.123-191.104 35.932 35.932-191.104 191.123z"/><glyph unicode="&#xe617;" d="M200.21 226.889l178.213 183.315-37.248 34.981-212.608-218.588 218.459-223.78 36.389 35.657z"/><glyph unicode="&#xe618;" d="M256 335.168l-224.992-239.984h450.032z"/><glyph unicode="&#xe619;" d="M96.624 451.12v-454.24l312.928 227.12z"/><glyph unicode="&#xe61a;" d="M102.992 224l312.912-227.12v454.24z"/><glyph unicode="&#xe61b;" d="M0 0.464h63.984v479.536h-63.984v-479.536zM512.080 480h-415.824v-287.888h415.824l-138.208 142.032 138.208 145.856z"/><glyph unicode="&#xe61c;" d="M512 241.12h-238.512v238.88h-34.016v-238.88h-239.472v-34.064h239.472v-239.056h34.016v239.056h238.512z"/><glyph unicode="&#xe61d;" d="M255.968 228.064l221.488 155.84c-2.656 0.528-5.344 0.848-8.128 0.848h-426.656c-2.8 0-5.504-0.32-8.144-0.848l221.44-155.84zM256.928 168.496l-0.96 1.408-0.944-1.408-254.56 179.136c-0.176-1.6-0.464-3.2-0.464-4.816v-267.712c0-23.904 19.104-43.312 42.672-43.312h426.656c23.6 0 42.688 19.408 42.688 43.312v267.712c0 1.632-0.288 3.216-0.496 4.816l-254.592-179.136z"/><glyph unicode="&#xe61e;" d="M127.584 31.776v127.632h-127.584v-127.632h127.584zM319.248 416.24h-126.928v-384.448h126.928v384.448zM511.584 287.472h-127.376v-255.68h127.376v255.68z"/><glyph unicode="&#xe61f;" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM372.16 144.832l-37.104-37.104-79.088 79.056-79.056-79.040-37.12 37.136 79.024 79.024-79.136 79.12 37.136 37.136 79.12-79.136 79.184 79.184 37.152-37.152-79.2-79.168 79.088-79.056z"/><glyph unicode="&#xe620;" d="M262.748 418.688c-113.664 2.249-207.214-67.803-208.969-156.435-0.585-30.829 9.984-59.813 28.8-84.644l-4.919 4.955c32.384-41.618-31.104-153.308-31.104-153.308l142.281 70.345c22.51-7.095 44.16-11.923 69.724-12.452 113.664-2.231 205.111 78.355 206.848 167.004 1.755 88.631-88.96 162.304-202.661 164.535z"/><glyph unicode="&#xe621;" d="M259.163 285.422l201.837-196.224 38.546 41.070-240.713 234.021-246.363-240.476 39.26-40.101z"/><glyph unicode="&#xe622;" d="M252.819 162.579l-201.82 196.224-38.528-41.070 240.677-234.021 246.4 240.476-39.332 40.101z"/><glyph unicode="&#xe623;" d="M256-33.248c-141.408 0-256 114.624-256 256s114.592 256 256 256c141.376 0 256-114.624 256-256s-114.608-256-256-256zM256 447.76c-124.048 0-225.008-100.96-225.008-225.008s100.96-225.024 225.008-225.024 224.992 100.96 224.992 225.008-100.928 225.024-224.992 225.024zM320.24 219.152l-15.6-12.128c-8.496-6.624-14.128-14.32-16.912-23.152-1.776-5.6-3.008-12.256-3.168-24h-59.712c0.88 24.848 3.504 39.968 7.328 49.472 3.808 9.472 13.632 20.368 29.44 32.72l16.032 12.528c5.28 4 9.536 8.32 12.752 13.024 5.872 8.064 8.784 16.976 8.784 26.656 0 11.152-3.248 21.312-9.776 30.496-6.496 9.184-18.4 13.808-35.712 13.808-17.008 0-29.056-5.68-36.16-17.008s-10.592-21.664-10.592-33.84h-63.68c1.744 41.872 16.32 70.16 43.776 87.632 17.344 11.152 38.656 16.752 63.904 16.752 33.216 0 60.784-7.936 82.752-23.808 21.968-15.84 34.8-48.432 34.8-79.6 0-19.088-6.624-26.096-16.144-39.184-5.584-7.92-16.272-18.048-32.112-30.368zM287.728 64h-63.504v63.68h63.504v-63.68z"/><glyph unicode="&#xe624;" d="M416.656 128v135.696h-320.672v-135.696h-95.984v199.344c0 13.76 11.168 24.912 24.944 24.912h462.144c13.744 0 24.912-11.152 24.912-24.912v-199.344h-95.344zM464.304 324.624c-11.024 0-19.92-8.928-19.92-19.936s8.896-19.952 19.92-19.952c10.992 0 19.968 8.96 19.968 19.952 0 11.008-8.992 19.936-19.968 19.936zM127.728 480h256v-96.192h-256v96.192zM160.976 31.664h191.232v192.336h31.824v-224.080h-255.984v224.080h32.912v-192.336z"/><glyph unicode="&#xe625;" d="M502.080 285.376h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 7.008 3.6 11.088-1.312 4.096-5.168 6.88-9.44 6.88zM333.424 170.256l48.208-148.064-125.632 91.36-125.968-91.44 48.256 148.128-125.168 91.136h154.576l48.256 147.376 48.016-147.376h154.832l-125.376-91.12z"/><glyph unicode="&#xe626;" d="M319.376 223.824v127.76h-126.752v-127.76h-89.744l153.168-188.608 153.088 188.608zM256.016 480c-141.392 0-256-114.608-256-255.984 0-141.392 114.608-256.016 256-256.016 141.376 0 256 114.624 256 256.016 0 141.376-114.624 255.984-256 255.984zM256.016 0c-123.52 0-224 100.496-224 224.016 0 123.504 100.48 223.984 224 223.984s224-100.48 224-223.984c0-123.52-100.48-224.016-224-224.016z"/><glyph unicode="&#xe627;" d="M255.982 440.594c-119.607 0-216.576-96.969-216.576-216.594s96.969-216.595 216.576-216.595c119.625 0 216.595 96.969 216.595 216.595s-96.951 216.595-216.595 216.595zM255.982 419.913c108.051 0 195.913-87.881 195.913-195.913 0-45.184-15.507-86.711-41.325-119.899-3.108 1.134-6.217 2.195-9.197 3.456-19.748 8.265-41.709 17.957-61.421 26.094-5.632 1.536-11.264 3.072-16.896 4.608-6.692 4.589-13.33 19.986-16.914 27.666-3.548 0.512-7.149 1.005-10.752 1.481 0.531 11.868 7.881 12.544 10.752 21.541 2.541 7.954 0.293 18.341 4.279 25.728 2.779 5.12 9.125 5.12 12.233 9.545 2.853 3.95 4.772 10.917 5.668 15.799 1.609 8.905 3.017 21.12-1.207 29.988-2.432 5.065-3.968 5.577-4.644 11.739-0.823 7.516 2.212 31.891 2.341 37.175 0.293 13.678-0.055 14.793-3.346 28.123 0 0-4.005 12.087-10.295 15.726l-12.58 2.158-7.772 7.186c-31.305 19.273-64.877 5.76-82.834-1.499-25.911-8.43-42.295-33.792-30.867-87.955 1.957-9.289-5.065-13.421-4.608-18.468 1.042-11.045 1.207-37.614 11.648-44.124 0.969-0.603 8.375-2.469 8.339-1.938 1.006-10.752 2.048-21.522 3.054-32.238 2.615-7.149 8.869-7.954 10.679-18.048l-7.991-1.92c-3.602-7.68-10.185-23.077-16.896-27.666-5.65-1.517-11.282-3.053-16.915-4.589-19.731-8.119-41.655-17.829-61.422-26.094-1.079-0.439-2.213-0.786-3.291-1.207-24.759 32.786-39.625 73.454-39.625 117.632 0 108.032 87.881 195.913 195.895 195.913z"/><glyph unicode="&#xe628;" d="M94.8 322.592l-93.424 78.464-0.496-321.968 316.688 56.336-89.216 74.96c182.112 167.52 227.904-8.128 246.272-204.784 65.936 574.064-229.84 445.328-379.824 316.992z"/><glyph unicode="&#xe629;" d="M428.432 224h-20.080v96.176c0 43.36-16.448 83.104-43.632 112.144-27.056 29.056-65.632 47.712-108.16 47.68-42.544 0.032-81.12-18.624-108.192-47.68-27.184-29.040-43.632-68.784-43.648-112.144v-96.176h-20.816c-10.816 0-19.584-8.752-19.584-19.584v-216.8c0-10.848 8.768-19.616 19.584-19.616h344.528c10.8 0 19.584 8.768 19.584 19.632v216.8c0 10.816-8.784 19.568-19.584 19.568zM176.816 320.176c0 25.024 9.472 47.168 24.192 62.928 14.848 15.728 34.144 24.784 55.552 24.816 21.376-0.032 40.688-9.072 55.536-24.816 14.704-15.744 24.176-37.888 24.176-62.928v-96.176h-159.44v96.176z"/><glyph unicode="&#xe62a;" d="M150.896 316.944h-112.192c-9.040 0-16.384-7.312-16.384-16.368v-80c0-9.056 7.344-16.368 16.384-16.368h112.192c9.056 0 16.432 7.312 16.432 16.368v80c0 9.056-7.376 16.368-16.432 16.368zM150.896 171.056h-79.376c-9.056 0-16.432-7.312-16.432-16.368v-170.32c-0.016-9.056 7.36-16.368 16.432-16.368h79.376c9.056 0 16.432 7.312 16.432 16.368v170.32c0 9.056-7.376 16.368-16.432 16.368zM473.328 316.944h-244.88c-9.056 0-16.368-7.312-16.368-16.368v-80c0-9.056 7.312-16.368 16.368-16.368h244.88c8.992 0 16.368 7.312 16.368 16.368v80c0 9.056-7.36 16.368-16.368 16.368zM439.52 169.376h-210.56c-9.056 0-16.368-7.344-16.368-16.4v-168.592c0-9.056 7.312-16.368 16.368-16.368h210.56c9.056 0 16.368 7.312 16.368 16.368v168.592c0 9.056-7.312 16.4-16.368 16.4zM251.952 335.68c19.12-3.504 37.568-5.536 54.816-5.536 86.688 0 133.68 46.592 133.936 90.464 0.128 28.256-20.752 58.88-68.368 59.376-63.808 0-103.312-45.056-123.872-78.496-20.944 33.312-60.624 77.472-124.56 77.472-46.256-0.464-67.2-31.088-67.008-59.328 0.176-43.888 47.248-90.512 133.936-90.512v0c18.752 0 38.88 2.128 59.872 6.336l1.248 0.224zM373.264 439.008c8-0.064 26.56-2 26.432-18.192-0.064-20.624-28.992-49.68-92.944-49.68-8.816 0-18 0.56-27.632 1.68 14.576 25.648 45.216 66.192 94.144 66.192zM190.832 370.128v0c-63.936 0-92.88 29.056-92.992 49.68-0.080 16.16 18.496 18.096 27.36 18.192 48.368 0 78.816-40.56 93.184-66.224-9.552-1.088-18.736-1.648-27.552-1.648z"/><glyph unicode="&#xe62b;" d="M182.256 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.776c-9.216 0-16.72 7.472-16.72 16.72v59.872c0 9.216 7.504 16.72 16.72 16.72h9.776c9.184 0 16.688-7.504 16.688-16.72v-59.872zM373.072 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.744c-9.248 0-16.688 7.472-16.688 16.72v59.872c0 9.216 7.424 16.72 16.688 16.72h9.744c9.184 0 16.688-7.504 16.688-16.72v-59.872zM398.816 253.152l-33.936 27.664-133.68-163.872-71.312 56.688-25.28-31.728 105.184-83.648zM471.952 434h-62.432v-26.064c0-27.68-22.56-50.192-50.128-50.192h-9.808c-27.68 0-50.128 22.496-50.128 50.192v26.064h-85.504v-26.064c0-27.68-22.496-50.192-50.128-50.192h-9.76c-27.664 0-50.16 22.496-50.16 50.192v26.064h-63.808c-9.216 0-16.72-7.504-16.72-16.688v-432.592c0-9.216 7.504-16.72 16.72-16.72h431.84c9.184 0 16.688 7.504 16.688 16.72v432.592c0.016 9.184-7.488 16.688-16.672 16.688zM438.512 42.592c0-9.248-7.504-16.72-16.752-16.72h-331.504c-9.248 0-16.752 7.472-16.752 16.72v252.096c0 9.248 7.504 16.688 16.752 16.688h331.504c9.248 0 16.752-7.44 16.752-16.688v-252.096z"/></font></defs></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg"><defs><font-face units-per-em="512" ascent="480" descent="-32" /><missing-glyph horiz-adv-x="512" /><glyph unicode="&#x20;" d="" horiz-adv-x="256" /><glyph unicode="&#xe600;" d="M436.608 435.568c-65.68 31.424-144.064 2.832-174.976-63.84-2.16-4.64-4.016-10.448-5.664-17.2-1.648 6.752-3.504 12.56-5.632 17.2-30.944 66.672-109.248 95.264-174.944 63.84-65.6-31.424-93.744-110.96-62.832-177.648 30.928-66.672 243.344-257.84 243.344-257.84s0.016 0.224 0.048 0.576c0.048-0.352 0.064-0.576 0.064-0.576s212.512 191.168 243.44 257.84c30.896 66.688 2.832 146.224-62.848 177.648z" /><glyph unicode="&#xe601;" d="M362.533 425.051c-49.81-49.792-20.809-20.772-20.809-20.772l96.402-96.384c0 0-31.067-31.049 20.772 20.773s-46.611 146.194-96.365 96.384zM320.147 383.671l-227.987-227.986 0.329-0.293-54.071-146.524 149.833 50.688 0.311-0.311 0.786 0.805v0.019l227.2 227.2-96.403 96.403zM179.036 104.375l-78.811-33.28 37.047 75.044 38.345 38.363 41.764-41.783-38.345-38.345z" /><glyph unicode="&#xe602;" d="M255.952 480l-255.952-448h512l-256.048 448zM287.12 353.808v-65.36l-16.688-128.544h-27.088l-18.032 128.544-0.992 65.36h62.8zM224.096 64.112v64.112h64.24v-64.112h-64.24z" /><glyph unicode="&#xe603;" d="M363.923 112.019c-29.805-28.764-68.663-43.502-108.013-43.538-35.145 0.036-70.199 11.757-99.347 35.932-37.029 30.829-56.046 74.971-56.1 119.661 0 7.442 0.549 14.829 1.591 22.18l-60.672-11.374c-0.164-3.602-0.292-7.186-0.292-10.807-0.036-61.495 26.459-122.899 77.549-165.285 40.009-33.335 88.887-49.683 137.252-49.683h0.128c56.211 0 112.164 22.217 153.746 64.914l39.844-39.772 0.311 124.745-131.803 0.348 45.805-47.324zM393.344 389.23c-40.046 33.335-88.923 49.664-137.271 49.664-55.808 0-111.397-21.833-152.923-63.945l-37.687 34.798-0.677-120.722 130.487-0.75-46.336 48.493c29.641 28.252 68.188 42.697 107.154 42.733 35.108-0.036 70.217-11.721 99.328-35.932 37.029-30.829 56.046-74.935 56.137-119.698 0-6.437-0.457-12.892-1.225-19.365l60.435 11.593c0.036 2.615 0.164 5.212 0.164 7.772-0.036 61.549-26.514 122.899-77.587 165.357z" /><glyph unicode="&#xe604;" d="M95.792-32h320.4v320.080h-320.4v-320.080zM318.336 228.512c0 9.904 8.032 17.904 17.952 17.904 9.904 0 17.936-8 17.936-17.904v-188.736c0-9.888-8.032-17.92-17.936-17.92-9.92 0-17.952 8.032-17.952 17.92v188.736zM238.048 228.512c0 9.904 8.032 17.904 17.92 17.904s17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92s-17.92 8.032-17.92 17.92v188.736zM157.6 228.512c0 9.904 8 17.904 17.92 17.904 9.888 0 17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92-9.92 0-17.92 8.032-17.92 17.92v188.736zM423.216 416.528h-71.232v10.896c0 29.040-19.76 52.576-48.8 52.576h-94.72c-29.008 0-48.48-23.536-48.48-52.576v-10.896h-71.232c-13.696 0-24.768-11.088-24.768-24.752v-71.984h384v71.984c0 13.664-11.040 24.752-24.768 24.752zM319.936 416.528h-128.192v14.704c0.032 9.248 7.488 16.736 16.72 16.768h94.72c9.216-0.032 16.704-7.52 16.752-16.768v-14.704z" /><glyph unicode="&#xe605;" d="M511.52 278.496c-1.312 4.096-5.152 6.88-9.44 6.88h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 6.992 3.6 11.088z" /><glyph unicode="&#xe606;" d="M473.015 200.375v49.371l-7.003 2.268-52.882 17.244-14.116 34.103 27.154 57.381-34.908 34.907-6.583-3.309-49.555-25.198-34.103 14.117-21.394 59.757h-49.371l-2.286-6.985-17.262-52.882-34.048-14.099-57.399 27.136-34.925-34.926 3.309-6.564 25.18-49.591-14.080-34.029-59.758-21.412v-49.39l6.949-2.249 52.901-17.28 14.099-34.067-27.118-57.38 34.925-34.925 6.528 3.328 49.591 25.197 34.066-14.116 21.394-59.757h49.371l2.286 6.985 17.28 52.882 34.029 14.116 57.399-27.136 34.944 34.908-3.346 6.546-25.197 49.572 14.116 34.067 59.813 21.413zM256 154.861c-38.199 0-69.156 30.957-69.156 69.139 0 38.217 30.958 69.156 69.156 69.156 38.163 0 69.156-30.94 69.156-69.156 0-38.18-31.012-69.139-69.156-69.139z" /><glyph unicode="&#xe607;" d="M31.008 351.36l224.992-239.984 225.040 239.984z" /><glyph unicode="&#xe608;" d="M383.415 226.596l-212.571 218.587-37.285-34.981 178.286-183.277-183.278-188.452 36.48-35.657 205.659 211.456-0.201 0.201z" /><glyph unicode="&#xe609;" d="M52.928 345.2h406.144c11.056 0 20 8.976 20 20.016 0 11.072-8.944 20.032-20 20.032h-406.144c-11.056 0-20.016-8.96-20.016-20.032 0-11.040 8.96-20.016 20.016-20.016zM459.072 244.016h-406.144c-11.056 0-20.016-8.944-20.016-20.016s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.016-20 20.016zM459.072 102.8h-406.144c-11.056 0-20.016-8.96-20.016-20.032s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.032-20 20.032z" /><glyph unicode="&#xe60a;" d="M256.144 480c-89.12 0-161.344-72.24-161.344-161.376 0-89.104 161.344-350.624 161.344-350.624s161.376 261.52 161.376 350.624c0 89.136-72.192 161.376-161.376 161.376zM256.144 269.616c-27.056 0-49.024 21.952-49.024 49.008 0 27.072 21.984 49.024 49.024 49.024 27.104 0 49.088-21.952 49.088-49.024 0-27.056-21.984-49.008-49.088-49.008z" /><glyph unicode="&#xe60b;" d="M0 256.144h224.032v223.808h-224.032v-223.808zM288.128 479.952v-95.728h224.176v95.728h-224.176zM0-32h224.032v223.808h-224.032v-223.808zM288.128 256.144h224.176v95.728h-224.176v-95.728zM288.128 96.080h224.176v95.728h-224.176v-95.728zM288.128-32h224.176v95.712h-224.176v-95.712z" /><glyph unicode="&#xe60c;" d="M332.764 119.003c-9.216 0-45.495-56.027-65.243-56.027-5.284 0-7.863 4.644-7.863 9.216 0 10.569 7.241 27.044 11.154 36.937l47.397 128.384c23.772 63.891-6.546 81.024-34.871 81.024-38.217 0-72.448-19.091-98.779-44.124-8.576-8.576-37.523-36.206-37.523-48.091 0-3.932 3.931-8.576 8.576-8.576 11.813 0 43.447 57.308 67.803 57.308 5.285 0 11.191-5.924 6.583-17.755l-46.080-115.968c-4.644-11.154-27.044-65.171-27.044-96.786 0-25.015 16.476-36.188 40.192-36.188 66.523 0 143.543 81.645 143.543 100.755-0.019 5.925-4.589 9.892-7.844 9.892zM319.543 439.661c-28.947 0-54.016-23.68-54.016-52.663 0-27.008 17.792-44.8 44.837-44.8 29.55 0 54.62 22.4 54.62 52.7 0 27.008-19.072 44.764-45.44 44.764z" /><glyph unicode="&#xe60d;" d="M0 351.552h128.464v128.448h-128.464v-128.448zM191.76 351.552h128.528v128.448h-128.528v-128.448zM383.568 480v-128.448h128.496v128.448h-128.496zM0 159.744h128.464v128.464h-128.464v-128.464zM191.76 159.744h128.528v128.464h-128.528v-128.464zM383.568 159.744h128.496v128.464h-128.496v-128.464zM0-32h128.464v128h-128.464v-128zM191.76-32h128.528v128h-128.528v-128zM383.568-32h128.496v128h-128.496v-128z" /><glyph unicode="&#xe60e;" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM231.936 94.576l-125.936 128.032 32.208 25.936 72.864-57.088c29.76 35.424 96 106.032 187.312 161.984l7.696-17.792c-83.808-77.088-152.48-185.6-174.144-241.072z" /><glyph unicode="&#xe60f;" d="M0 241.12h512v-34.064h-512v34.064z" /><glyph unicode="&#xe610;" d="M478.263 426.149c-142.555-87.388-245.98-197.632-292.48-252.947l-113.792 89.161-50.267-40.539 196.663-199.973c33.847 86.674 141.056 256.11 271.872 376.485l-11.995 27.813z" /><glyph unicode="&#xe611;" d="M220.576 83.248c-26.352 0-47.696-21.376-47.696-47.712s21.344-47.664 47.696-47.664c26.336 0 47.696 21.328 47.696 47.664s-21.36 47.712-47.696 47.712zM385.344 83.248c-26.4 0-47.76-21.376-47.76-47.712s21.344-47.664 47.76-47.664c26.288 0 47.632 21.328 47.632 47.664s-21.344 47.712-47.632 47.712zM459.856 350.32c-122.384 0-319.856 0-319.856 0s-19.152 52.608-37.392 84.864c-14.128 24.976-43.344 23.968-43.344 23.968-20.096 0-33.024-12.288-33.024-32.4 0-20.096 15.92-36.16 36.032-36.16l8.496-0.080 95.2-262.192 266.832-0.208c0 0 48.784 199.632 46.272 191.888 8.944 27.68-2.448 30.32-19.216 30.32zM166.528 257.344c-14 0-25.36 11.36-25.36 25.376s11.36 25.392 25.36 25.392c14.016 0 25.36-11.376 25.36-25.392s-11.344-25.376-25.36-25.376zM220.768 172.64c-14.016 0-25.376 11.376-25.376 25.392 0 13.984 11.36 25.36 25.376 25.36 14 0 25.36-11.376 25.36-25.36 0.016-14.016-11.36-25.392-25.36-25.392zM248.656 257.344c-14 0-25.376 11.36-25.376 25.376s11.36 25.392 25.376 25.392c14 0 25.36-11.376 25.36-25.392s-11.36-25.376-25.36-25.376zM302.896 172.64c-14 0-25.36 11.376-25.36 25.392 0 13.984 11.36 25.36 25.36 25.36 14.048 0 25.44-11.376 25.44-25.36 0-14.016-11.392-25.392-25.44-25.392zM330.848 257.344c-14 0-25.408 11.36-25.408 25.376s11.408 25.392 25.408 25.392c14 0 25.328-11.376 25.328-25.392s-11.328-25.376-25.328-25.376zM385.040 172.64c-13.984 0-25.328 11.376-25.328 25.392 0 13.984 11.36 25.36 25.328 25.36 14 0 25.408-11.376 25.408-25.36 0-14.016-11.408-25.392-25.408-25.392zM412.96 257.344c-14.016 0-25.36 11.36-25.36 25.376s11.344 25.392 25.36 25.392c14.048 0 25.376-11.376 25.376-25.392s-11.328-25.376-25.376-25.376z" /><glyph unicode="&#xe612;" d="M142.992 332.768c10.352 0 18.8 8.4 18.8 18.8v67.68c0 10.368-8.432 18.784-18.8 18.784-10.384 0-18.8-8.4-18.8-18.784v-67.68c0-10.4 8.416-18.8 18.8-18.8zM394.384 383.344v-0.32c7.776-6.944 12.72-17.008 12.72-28.288 0-20.816-16.88-37.712-37.744-37.712s-37.76 16.912-37.76 37.712c0 11.264 4.976 21.344 12.784 28.288v0.32h-176.416v-0.32c7.824-6.944 12.768-17.008 12.768-28.288 0-20.816-16.896-37.712-37.728-37.712-20.864 0-37.744 16.912-37.744 37.712 0 11.264 4.928 21.344 12.752 28.288v0.32h-85.536v-383.6h447.248v383.6h-85.344zM448.72 32.832h-383.152v254.72h383.152v-254.72zM369.36 332.768c10.384 0 18.784 8.4 18.784 18.8v67.68c0 10.368-8.4 18.784-18.784 18.784-10.352 0-18.816-8.4-18.816-18.784v-67.68c0-10.4 8.464-18.8 18.816-18.8zM349.216 184.128h-47.936v-47.872h47.952v47.872zM349.216 256.112h-47.936v-47.824h47.952v47.824zM349.216 114.112h-47.936v-47.872h47.952v47.872zM416.656 256.112h-47.92v-47.824h47.92v47.824zM416.656 184.128h-47.92v-47.872h47.92v47.872zM281.696 256.112h-47.872v-47.824h47.872v47.824zM146.8 184.128h-47.856v-47.872h47.856v47.872zM214.288 114.112h-47.888v-47.872h47.872v47.872zM146.8 114.112h-47.856v-47.872h47.856v47.872zM281.696 184.128h-47.872v-47.872h47.872v47.872zM281.696 114.112h-47.872v-47.872h47.872v47.872zM214.288 184.128h-47.888v-47.872h47.872v47.872zM214.288 256.112h-47.888v-47.824h47.872v47.824z" /><glyph unicode="&#xe613;" d="M256 444.727l-200.814-243.291h131.054v-198.144h139.575v198.144h131.017z" /><glyph unicode="&#xe614;" d="M325.779 246.583v198.144h-139.593v-198.144h-130.999l200.832-243.292 200.813 243.292z" /><glyph unicode="&#xe615;" d="M487.232 35.872c0 0-78.176 80.288-109.328 111.312-13.552 13.552-22.832 22.752-22.832 22.752 10.56 15.088 18.816 31.616 24.704 49.392 5.84 17.76 8.752 36.496 8.752 56.192 0 25.36-4.816 49.2-14.448 71.552-9.664 22.32-22.784 41.824-39.456 58.432-16.64 16.688-36.144 29.824-58.496 39.472-22.336 9.664-46.176 14.496-71.536 14.496-25.344 0-49.184-4.848-71.552-14.496-22.336-9.648-41.712-22.784-58.192-39.472-16.416-16.608-29.52-36.128-39.152-58.448-9.664-22.336-14.496-46.192-14.496-71.552 0-25.376 4.848-49.216 14.496-71.552 9.632-22.304 22.72-41.792 39.152-58.464 16.464-16.608 35.856-29.776 58.176-39.456 22.368-9.664 46.208-14.448 71.552-14.448 19.68 0 38.416 2.88 56.208 8.768 17.776 5.856 34.288 14.144 49.36 24.72 0 0 8.576-8.512 21.2-21.216 34.512-34.64 110.416-113.392 110.416-113.392 11.456-4.992 29.712 0.336 38.848 8.064 9.040 7.776 14.096 23.984 6.624 37.344zM327.792 223.28c-7.008-16.192-16.576-30.336-28.624-42.336-12.096-12.048-26.192-21.616-42.336-28.608-16.128-7.024-33.392-10.528-51.68-10.528-18.704 0-36.096 3.504-52.256 10.528-16.16 7.008-30.288 16.56-42.336 28.608-12.048 12.016-21.616 26.16-28.608 42.336-7.008 16.112-10.512 33.568-10.512 52.24 0 18.272 3.504 35.632 10.512 51.984 6.992 16.336 16.56 30.56 28.608 42.592 12.048 12.096 26.176 21.664 42.336 28.608 16.16 7.056 33.552 10.512 52.256 10.512 18.288 0 35.552-3.456 51.68-10.512 16.144-6.96 30.24-16.512 42.336-28.608 12.032-12.032 21.616-26.256 28.624-42.592 7.008-16.352 10.48-33.712 10.48-51.984 0.016-18.672-3.456-36.128-10.48-52.24z" /><glyph unicode="&#xe616;" d="M483.255 415.177l-36.023 35.968-191.25-191.268-191.25 191.268-35.986-35.968 191.268-191.269-191.123-191.14 35.968-35.932 191.14 191.104 191.123-191.104 35.932 35.932-191.104 191.123z" /><glyph unicode="&#xe617;" d="M200.21 226.889l178.213 183.315-37.248 34.981-212.608-218.588 218.459-223.78 36.389 35.657z" /><glyph unicode="&#xe618;" d="M256 335.168l-224.992-239.984h450.032z" /><glyph unicode="&#xe619;" d="M96.624 451.12v-454.24l312.928 227.12z" /><glyph unicode="&#xe61a;" d="M102.992 224l312.912-227.12v454.24z" /><glyph unicode="&#xe61b;" d="M0 0.464h63.984v479.536h-63.984v-479.536zM512.080 480h-415.824v-287.888h415.824l-138.208 142.032 138.208 145.856z" /><glyph unicode="&#xe61c;" d="M512 241.12h-238.512v238.88h-34.016v-238.88h-239.472v-34.064h239.472v-239.056h34.016v239.056h238.512z" /><glyph unicode="&#xe61d;" d="M255.968 228.064l221.488 155.84c-2.656 0.528-5.344 0.848-8.128 0.848h-426.656c-2.8 0-5.504-0.32-8.144-0.848l221.44-155.84zM256.928 168.496l-0.96 1.408-0.944-1.408-254.56 179.136c-0.176-1.6-0.464-3.2-0.464-4.816v-267.712c0-23.904 19.104-43.312 42.672-43.312h426.656c23.6 0 42.688 19.408 42.688 43.312v267.712c0 1.632-0.288 3.216-0.496 4.816l-254.592-179.136z" /><glyph unicode="&#xe61e;" d="M127.584 31.776v127.632h-127.584v-127.632h127.584zM319.248 416.24h-126.928v-384.448h126.928v384.448zM511.584 287.472h-127.376v-255.68h127.376v255.68z" /><glyph unicode="&#xe61f;" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM372.16 144.832l-37.104-37.104-79.088 79.056-79.056-79.040-37.12 37.136 79.024 79.024-79.136 79.12 37.136 37.136 79.12-79.136 79.184 79.184 37.152-37.152-79.2-79.168 79.088-79.056z" /><glyph unicode="&#xe620;" d="M262.748 418.688c-113.664 2.249-207.214-67.803-208.969-156.435-0.585-30.829 9.984-59.813 28.8-84.644l-4.919 4.955c32.384-41.618-31.104-153.308-31.104-153.308l142.281 70.345c22.51-7.095 44.16-11.923 69.724-12.452 113.664-2.231 205.111 78.355 206.848 167.004 1.755 88.631-88.96 162.304-202.661 164.535z" /><glyph unicode="&#xe621;" d="M259.163 285.422l201.837-196.224 38.546 41.070-240.713 234.021-246.363-240.476 39.26-40.101z" /><glyph unicode="&#xe622;" d="M252.819 162.579l-201.82 196.224-38.528-41.070 240.677-234.021 246.4 240.476-39.332 40.101z" /><glyph unicode="&#xe623;" d="M256-33.248c-141.408 0-256 114.624-256 256s114.592 256 256 256c141.376 0 256-114.624 256-256s-114.608-256-256-256zM256 447.76c-124.048 0-225.008-100.96-225.008-225.008s100.96-225.024 225.008-225.024 224.992 100.96 224.992 225.008-100.928 225.024-224.992 225.024zM320.24 219.152l-15.6-12.128c-8.496-6.624-14.128-14.32-16.912-23.152-1.776-5.6-3.008-12.256-3.168-24h-59.712c0.88 24.848 3.504 39.968 7.328 49.472 3.808 9.472 13.632 20.368 29.44 32.72l16.032 12.528c5.28 4 9.536 8.32 12.752 13.024 5.872 8.064 8.784 16.976 8.784 26.656 0 11.152-3.248 21.312-9.776 30.496-6.496 9.184-18.4 13.808-35.712 13.808-17.008 0-29.056-5.68-36.16-17.008s-10.592-21.664-10.592-33.84h-63.68c1.744 41.872 16.32 70.16 43.776 87.632 17.344 11.152 38.656 16.752 63.904 16.752 33.216 0 60.784-7.936 82.752-23.808 21.968-15.84 34.8-48.432 34.8-79.6 0-19.088-6.624-26.096-16.144-39.184-5.584-7.92-16.272-18.048-32.112-30.368zM287.728 64h-63.504v63.68h63.504v-63.68z" /><glyph unicode="&#xe624;" d="M416.656 128v135.696h-320.672v-135.696h-95.984v199.344c0 13.76 11.168 24.912 24.944 24.912h462.144c13.744 0 24.912-11.152 24.912-24.912v-199.344h-95.344zM464.304 324.624c-11.024 0-19.92-8.928-19.92-19.936s8.896-19.952 19.92-19.952c10.992 0 19.968 8.96 19.968 19.952 0 11.008-8.992 19.936-19.968 19.936zM127.728 480h256v-96.192h-256v96.192zM160.976 31.664h191.232v192.336h31.824v-224.080h-255.984v224.080h32.912v-192.336z" /><glyph unicode="&#xe625;" d="M502.080 285.376h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 7.008 3.6 11.088-1.312 4.096-5.168 6.88-9.44 6.88zM333.424 170.256l48.208-148.064-125.632 91.36-125.968-91.44 48.256 148.128-125.168 91.136h154.576l48.256 147.376 48.016-147.376h154.832l-125.376-91.12z" /><glyph unicode="&#xe626;" d="M319.376 223.824v127.76h-126.752v-127.76h-89.744l153.168-188.608 153.088 188.608zM256.016 480c-141.392 0-256-114.608-256-255.984 0-141.392 114.608-256.016 256-256.016 141.376 0 256 114.624 256 256.016 0 141.376-114.624 255.984-256 255.984zM256.016 0c-123.52 0-224 100.496-224 224.016 0 123.504 100.48 223.984 224 223.984s224-100.48 224-223.984c0-123.52-100.48-224.016-224-224.016z" /><glyph unicode="&#xe627;" d="M255.982 440.594c-119.607 0-216.576-96.969-216.576-216.594s96.969-216.595 216.576-216.595c119.625 0 216.595 96.969 216.595 216.595s-96.951 216.595-216.595 216.595zM255.982 419.913c108.051 0 195.913-87.881 195.913-195.913 0-45.184-15.507-86.711-41.325-119.899-3.108 1.134-6.217 2.195-9.197 3.456-19.748 8.265-41.709 17.957-61.421 26.094-5.632 1.536-11.264 3.072-16.896 4.608-6.692 4.589-13.33 19.986-16.914 27.666-3.548 0.512-7.149 1.005-10.752 1.481 0.531 11.868 7.881 12.544 10.752 21.541 2.541 7.954 0.293 18.341 4.279 25.728 2.779 5.12 9.125 5.12 12.233 9.545 2.853 3.95 4.772 10.917 5.668 15.799 1.609 8.905 3.017 21.12-1.207 29.988-2.432 5.065-3.968 5.577-4.644 11.739-0.823 7.516 2.212 31.891 2.341 37.175 0.293 13.678-0.055 14.793-3.346 28.123 0 0-4.005 12.087-10.295 15.726l-12.58 2.158-7.772 7.186c-31.305 19.273-64.877 5.76-82.834-1.499-25.911-8.43-42.295-33.792-30.867-87.955 1.957-9.289-5.065-13.421-4.608-18.468 1.042-11.045 1.207-37.614 11.648-44.124 0.969-0.603 8.375-2.469 8.339-1.938 1.006-10.752 2.048-21.522 3.054-32.238 2.615-7.149 8.869-7.954 10.679-18.048l-7.991-1.92c-3.602-7.68-10.185-23.077-16.896-27.666-5.65-1.517-11.282-3.053-16.915-4.589-19.731-8.119-41.655-17.829-61.422-26.094-1.079-0.439-2.213-0.786-3.291-1.207-24.759 32.786-39.625 73.454-39.625 117.632 0 108.032 87.881 195.913 195.895 195.913z" /><glyph unicode="&#xe628;" d="M94.8 322.592l-93.424 78.464-0.496-321.968 316.688 56.336-89.216 74.96c182.112 167.52 227.904-8.128 246.272-204.784 65.936 574.064-229.84 445.328-379.824 316.992z" /><glyph unicode="&#xe629;" d="M428.432 224h-20.080v96.176c0 43.36-16.448 83.104-43.632 112.144-27.056 29.056-65.632 47.712-108.16 47.68-42.544 0.032-81.12-18.624-108.192-47.68-27.184-29.040-43.632-68.784-43.648-112.144v-96.176h-20.816c-10.816 0-19.584-8.752-19.584-19.584v-216.8c0-10.848 8.768-19.616 19.584-19.616h344.528c10.8 0 19.584 8.768 19.584 19.632v216.8c0 10.816-8.784 19.568-19.584 19.568zM176.816 320.176c0 25.024 9.472 47.168 24.192 62.928 14.848 15.728 34.144 24.784 55.552 24.816 21.376-0.032 40.688-9.072 55.536-24.816 14.704-15.744 24.176-37.888 24.176-62.928v-96.176h-159.44v96.176z" /><glyph unicode="&#xe62a;" d="M150.896 316.944h-112.192c-9.040 0-16.384-7.312-16.384-16.368v-80c0-9.056 7.344-16.368 16.384-16.368h112.192c9.056 0 16.432 7.312 16.432 16.368v80c0 9.056-7.376 16.368-16.432 16.368zM150.896 171.056h-79.376c-9.056 0-16.432-7.312-16.432-16.368v-170.32c-0.016-9.056 7.36-16.368 16.432-16.368h79.376c9.056 0 16.432 7.312 16.432 16.368v170.32c0 9.056-7.376 16.368-16.432 16.368zM473.328 316.944h-244.88c-9.056 0-16.368-7.312-16.368-16.368v-80c0-9.056 7.312-16.368 16.368-16.368h244.88c8.992 0 16.368 7.312 16.368 16.368v80c0 9.056-7.36 16.368-16.368 16.368zM439.52 169.376h-210.56c-9.056 0-16.368-7.344-16.368-16.4v-168.592c0-9.056 7.312-16.368 16.368-16.368h210.56c9.056 0 16.368 7.312 16.368 16.368v168.592c0 9.056-7.312 16.4-16.368 16.4zM251.952 335.68c19.12-3.504 37.568-5.536 54.816-5.536 86.688 0 133.68 46.592 133.936 90.464 0.128 28.256-20.752 58.88-68.368 59.376-63.808 0-103.312-45.056-123.872-78.496-20.944 33.312-60.624 77.472-124.56 77.472-46.256-0.464-67.2-31.088-67.008-59.328 0.176-43.888 47.248-90.512 133.936-90.512v0c18.752 0 38.88 2.128 59.872 6.336l1.248 0.224zM373.264 439.008c8-0.064 26.56-2 26.432-18.192-0.064-20.624-28.992-49.68-92.944-49.68-8.816 0-18 0.56-27.632 1.68 14.576 25.648 45.216 66.192 94.144 66.192zM190.832 370.128v0c-63.936 0-92.88 29.056-92.992 49.68-0.080 16.16 18.496 18.096 27.36 18.192 48.368 0 78.816-40.56 93.184-66.224-9.552-1.088-18.736-1.648-27.552-1.648z" /><glyph unicode="&#xe62b;" d="M182.256 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.776c-9.216 0-16.72 7.472-16.72 16.72v59.872c0 9.216 7.504 16.72 16.72 16.72h9.776c9.184 0 16.688-7.504 16.688-16.72v-59.872zM373.072 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.744c-9.248 0-16.688 7.472-16.688 16.72v59.872c0 9.216 7.424 16.72 16.688 16.72h9.744c9.184 0 16.688-7.504 16.688-16.72v-59.872zM398.816 253.152l-33.936 27.664-133.68-163.872-71.312 56.688-25.28-31.728 105.184-83.648zM471.952 434h-62.432v-26.064c0-27.68-22.56-50.192-50.128-50.192h-9.808c-27.68 0-50.128 22.496-50.128 50.192v26.064h-85.504v-26.064c0-27.68-22.496-50.192-50.128-50.192h-9.76c-27.664 0-50.16 22.496-50.16 50.192v26.064h-63.808c-9.216 0-16.72-7.504-16.72-16.688v-432.592c0-9.216 7.504-16.72 16.72-16.72h431.84c9.184 0 16.688 7.504 16.688 16.72v432.592c0.016 9.184-7.488 16.688-16.672 16.688zM438.512 42.592c0-9.248-7.504-16.72-16.752-16.72h-331.504c-9.248 0-16.752 7.472-16.752 16.72v252.096c0 9.248 7.504 16.688 16.752 16.688h331.504c9.248 0 16.752-7.44 16.752-16.688v-252.096z" /></font></defs></svg>
\ No newline at end of file
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php
index ae4604fd1c322d09f41da047fc23ae9fcff6934f..158a3ef5a771179f7fca114d3eaaf2c5f3d41fcc 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php
@@ -24,6 +24,11 @@ use OAuth\OAuth1\Token\TokenInterface;
  */
 class OauthClient extends AbstractService
 {
+    /**
+     * The maximum timeout for http request in seconds
+     */
+    const DEFAULT_TIMEOUT = 120;
+
     /** @var string|null */
     protected $_oauthVerifier = null;
 
@@ -36,6 +41,7 @@ class OauthClient extends AbstractService
     ) {
         if (!isset($httpClient)) {
             $httpClient = new \OAuth\Common\Http\Client\StreamClient();
+            $httpClient->setTimeout(self::DEFAULT_TIMEOUT);
         }
         if (!isset($storage)) {
             $storage = new \OAuth\Common\Storage\Session();
diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php
deleted file mode 100644
index 9081283ffa462a2520d277f2826c088e965061c6..0000000000000000000000000000000000000000
--- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Quote\Api;
-
-class AddressDetailsManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
-{
-    const SERVICE_VERSION = 'V1';
-    const SERVICE_NAME = 'quoteAddressDetailsManagementV1';
-    const RESOURCE_PATH = '/V1/carts/';
-
-    /**
-     * @var \Magento\TestFramework\ObjectManager
-     */
-    protected $objectManager;
-
-    protected function setUp()
-    {
-        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-    }
-
-    /**
-     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
-     */
-    public function testSaveAddresses()
-    {
-        /** @var \Magento\Quote\Model\Quote $quote */
-        $quote = $this->objectManager->create('Magento\Quote\Model\Quote');
-        $quote->load('test_order_1', 'reserved_order_id');
-
-        $serviceInfo = [
-            'rest' => [
-                'resourcePath' => self::RESOURCE_PATH . 'mine/addresses',
-                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
-            ],
-            'soap' => [
-                'service' => self::SERVICE_NAME,
-                'serviceVersion' => self::SERVICE_VERSION,
-                'operation' => self::SERVICE_NAME . 'SaveAddresses',
-            ],
-        ];
-
-        $addressData = [
-            'firstname' => 'John',
-            'lastname' => 'Smith',
-            'email' => 'cat@dog.com',
-            'company' => 'eBay Inc',
-            'street' => ['Typical Street', 'Tiny House 18'],
-            'city' => 'Big City',
-            'region_id' => 12,
-            'region' => 'California',
-            'region_code' => 'CA',
-            'postcode' => '0985432',
-            'country_id' => 'US',
-            'telephone' => '88776655',
-            'fax' => '44332255',
-        ];
-        $requestData = [
-            'cart_id' => $quote->getId(),
-            'billingAddress' => $addressData,
-            'shippingAddress' => $addressData
-        ];
-
-        $response = $this->_webApiCall($serviceInfo, $requestData);
-
-        $this->assertArrayHasKey('shipping_methods', $response);
-        $this->assertCount(1, $response['shipping_methods']);
-        $this->assertEquals('flatrate', $response['shipping_methods'][0]['method_code']);
-
-        $this->assertArrayHasKey('payment_methods', $response);
-        $this->assertCount(2, $response['payment_methods']);
-        $this->assertEquals('checkmo', $response['payment_methods'][0]['code']);
-    }
-}
diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
index 1380a7251302f4d63ac9f61358ecb24a6bd8643c..bef10d5a5cfb5ab0114aab0bc7e4e60d5fc4e0cc 100644
--- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
@@ -77,6 +77,7 @@ class CartTotalRepositoryTest extends WebapiAbstract
             Totals::KEY_BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(),
             Totals::KEY_BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(),
             Totals::KEY_QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(),
+            Totals::KEY_ITEMS_QTY => $quote->getItemsQty(),
             Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)],
         ];
 
@@ -85,6 +86,10 @@ class CartTotalRepositoryTest extends WebapiAbstract
         $data = $this->formatTotalsData($data);
         $actual = $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData);
         unset($actual['items'][0]['options']);
+        unset($actual['weee_tax_applied_amount']);
+
+        /** TODO: cover total segments with separate test */
+        unset($actual['total_segments']);
         if (array_key_exists('extension_attributes', $actual)) {
             unset($actual['extension_attributes']);
         }
@@ -231,12 +236,17 @@ class CartTotalRepositoryTest extends WebapiAbstract
             Totals::KEY_BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(),
             Totals::KEY_BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(),
             Totals::KEY_QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(),
+            Totals::KEY_ITEMS_QTY => $quote->getItemsQty(),
             Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)],
         ];
 
         $data = $this->formatTotalsData($data);
         $actual = $this->_webApiCall($serviceInfo);
         unset($actual['items'][0]['options']);
+        unset($actual['weee_tax_applied_amount']);
+
+        /** TODO: cover total segments with separate test */
+        unset($actual['total_segments']);
         if (array_key_exists('extension_attributes', $actual)) {
             unset($actual['extension_attributes']);
         }
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions.php
new file mode 100644
index 0000000000000000000000000000000000000000..0cdd46da28ece5bf94756fde012f0bec0a0e7e1f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\GiftMessage\Test\Block\Cart;
+
+use Magento\GiftMessage\Test\Fixture\GiftMessage;
+use Magento\Mtf\Block\Form;
+
+/**
+ * Class GiftOptions
+ * Add gift options on checkout cart order level
+ */
+class GiftOptions extends Form
+{
+    /**
+     * Selector for gift message on order form
+     *
+     * @var string
+     */
+    protected $giftMessageOrderForm = ".gift-message fieldset";
+
+    /**
+     * Allow gift message on order level
+     *
+     * @var string
+     */
+    protected $allowGiftOptions = '.title';
+
+    /**
+     * Selector for apply Gift Message button on item
+     *
+     * @var string
+     */
+    protected $giftMessageOrderButton = ".action-update";
+
+    /**
+     * Selector for Gift Message Summary
+     *
+     * @var string
+     */
+    protected $giftMessageSummary = ".gift-message-summary";
+
+    /**
+     * Fill gift message form on order level
+     *
+     * @param GiftMessage $giftMessage
+     * @return void
+     */
+    public function fillGiftMessageOrder(GiftMessage $giftMessage)
+    {
+        /** @var \Magento\GiftMessage\Test\Block\Cart\GiftOptions\GiftMessageForm $giftMessageForm */
+        if ($giftMessage->getAllowGiftMessagesForOrder() === 'Yes') {
+            $this->_rootElement->find($this->allowGiftOptions)->click();
+            $giftMessageForm = $this->blockFactory->create(
+                'Magento\GiftMessage\Test\Block\Cart\GiftOptions\GiftMessageForm',
+                ['element' => $this->_rootElement->find($this->giftMessageOrderForm)]
+            );
+            $giftMessageForm->fill($giftMessage);
+            $this->_rootElement->find($this->giftMessageOrderButton)->click();
+            $this->waitForElementVisible($this->giftMessageSummary);
+        }
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.php
similarity index 80%
rename from dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.php
rename to dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.php
index 2c1a696e6929dc5c6bec4daa66abe309ccb4432a..a8b0c26d710726878c7a7d147fc9c1f077156fce 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.php
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.php
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\GiftMessage\Test\Block\Message\Inline;
+namespace Magento\GiftMessage\Test\Block\Cart\GiftOptions;
 
 use Magento\Mtf\Block\Form;
 
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.xml
similarity index 58%
rename from dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.xml
rename to dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.xml
index 220c89ef22a04bc1c04c9a3f4542b53512d9c39b..43407c31535f56a199a96b9bcca36b21f3095fb3 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline/GiftMessageForm.xml
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/GiftOptions/GiftMessageForm.xml
@@ -8,13 +8,13 @@
 <mapping strict="0">
     <fields>
         <sender>
-            <selector>[id^='gift-message'][name$='[from]']</selector>
+            <selector>[id='gift-message-whole-from']</selector>
         </sender>
         <recipient>
-            <selector>[id^='gift-message'][name$='[to]']</selector>
+            <selector>[id='gift-message-whole-to']</selector>
         </recipient>
         <message>
-            <selector>[id^='gift-message'][name$='[message]']</selector>
+            <selector>[id='gift-message-whole-message']</selector>
         </message>
     </fields>
 </mapping>
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/Item/GiftOptions.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/Item/GiftOptions.php
new file mode 100644
index 0000000000000000000000000000000000000000..78ce8fe619261744f1a8dfd817ea6980fce21a32
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/Item/GiftOptions.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\GiftMessage\Test\Block\Cart\Item;
+
+use Magento\GiftMessage\Test\Fixture\GiftMessage;
+use Magento\Mtf\Block\Form;
+use Magento\Mtf\Client\Locator;
+
+/**
+ * Add gift options on checkout cart item level
+ */
+class GiftOptions extends Form
+{
+    /**
+     * Selector for gift message on item form
+     *
+     * @var string
+     */
+    protected $giftMessageItemForm = '//div[@class="gift-message"]//fieldset[ancestor::tbody[contains(.,"%s")]]';
+
+    /**
+     * Allow Gift Options for items
+     *
+     * @var string
+     */
+    protected $allowGiftOptions = '//a[contains(@class,"action-gift")][ancestor::tbody[contains(.,"%s")]]';
+
+    /**
+     * Selector for apply Gift Message button on order
+     *
+     * @var string
+     */
+    protected $giftMessageItemButton = ".action-update";
+
+    /**
+     * Selector for Gift Message Summary
+     *
+     * @var string
+     */
+    protected $giftMessageSummary = '//div[@class="gift-message-summary"][ancestor::tbody[contains(.,"%s")]]';
+
+    /**
+     * Fill gift message form on item level
+     *
+     * @param GiftMessage $giftMessage
+     * @param array $products
+     * @return void
+     */
+    public function fillGiftMessageItem(GiftMessage $giftMessage, $products = [])
+    {
+        /** @var \Magento\GiftMessage\Test\Block\Cart\GiftOptions\GiftMessageForm $giftMessageForm */
+        if ($giftMessage->getAllowGiftOptionsForItems() === 'Yes') {
+            foreach ($products as $product) {
+                if ($product->getIsVirtual() !== 'Yes') {
+                    $this->_rootElement->find(
+                        sprintf($this->allowGiftOptions, $product->getName()),
+                        Locator::SELECTOR_XPATH
+                    )->click();
+                    $giftMessageForm = $this->blockFactory->create(
+                        'Magento\GiftMessage\Test\Block\Cart\GiftOptions\GiftMessageForm',
+                        [
+                            'element' => $this->_rootElement->find(
+                                sprintf($this->giftMessageItemForm, $product->getName()),
+                                Locator::SELECTOR_XPATH
+                            )
+                        ]
+                    );
+                    $giftMessageForm->fill($giftMessage);
+                    $this->_rootElement->find($this->giftMessageItemButton)->click();
+                    $this->waitForElementVisible(
+                        sprintf($this->giftMessageSummary, $product->getName()),
+                        Locator::SELECTOR_XPATH
+                    );
+                }
+            }
+        }
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/Item/GiftOptions.xml
similarity index 100%
rename from dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline.xml
rename to dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Cart/Item/GiftOptions.xml
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline.php
deleted file mode 100644
index 0c41872447b7796c0ee47861fa32e44403797dbf..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Inline.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\GiftMessage\Test\Block\Message;
-
-use Magento\GiftMessage\Test\Fixture\GiftMessage;
-use Magento\Mtf\Block\Form;
-use Magento\Mtf\Client\Locator;
-
-/**
- * Class Inline
- * Checkout add gift options
- */
-class Inline extends Form
-{
-    /**
-     * Selector for gift message on item form
-     *
-     * @var string
-     */
-    protected $giftMessageItemForm = ".//li[@class='item'][contains(.,'%s')]/div[@class='options']";
-
-    /**
-     * Selector for gift message on order form
-     *
-     * @var string
-     */
-    protected $giftMessageOrderForm = ".gift-messages-order";
-
-    /**
-     * Selector for "Gift Message" button on order
-     *
-     * @var string
-     */
-    protected $giftMessageItemButton = ".//li[@class='item'][contains(.,'%s')]/div[@class='options']/a";
-
-    /**
-     * Selector for "Gift Message" button on item
-     *
-     * @var string
-     */
-    protected $giftMessageOrderButton = "#allow-gift-options-for-order-container > a";
-
-    /**
-     * Fill gift message form
-     *
-     * @param GiftMessage $giftMessage
-     * @param array $products
-     * @return void
-     */
-    public function fillGiftMessage(GiftMessage $giftMessage, $products = [])
-    {
-        $this->fill($giftMessage);
-
-        /** @var \Magento\GiftMessage\Test\Block\Message\Inline\GiftMessageForm $giftMessageForm */
-        if ($giftMessage->getAllowGiftMessagesForOrder() === 'Yes') {
-            $this->_rootElement->find($this->giftMessageOrderButton)->click();
-            $giftMessageForm = $this->blockFactory->create(
-                'Magento\GiftMessage\Test\Block\Message\Inline\GiftMessageForm',
-                ['element' => $this->_rootElement->find($this->giftMessageOrderForm)]
-            );
-            $giftMessageForm->fill($giftMessage);
-        }
-
-        if ($giftMessage->getAllowGiftOptionsForItems() === 'Yes') {
-            foreach ($products as $product) {
-                $this->_rootElement->find(
-                    sprintf($this->giftMessageItemButton, $product->getName()),
-                    Locator::SELECTOR_XPATH
-                )->click();
-                $giftMessageForm = $this->blockFactory->create(
-                    'Magento\GiftMessage\Test\Block\Message\Inline\GiftMessageForm',
-                    [
-                        'element' => $this->_rootElement->find(
-                            sprintf($this->giftMessageItemForm, $product->getName()),
-                            Locator::SELECTOR_XPATH
-                        )
-                    ]
-                );
-                $giftMessageForm->fill($giftMessage);
-            }
-        }
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Order/Items/View.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Order/Items/View.php
index b3c29e2252085a4470eaeb586d78fe42b8d8109a..c680b61b485b4b7addb8334a548ea6f2c91a4121 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Order/Items/View.php
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Message/Order/Items/View.php
@@ -57,6 +57,9 @@ class View extends Block
      */
     public function getGiftMessage($itemName)
     {
+        if (!$this->giftMessageButtonIsVisible($itemName)) {
+            return [];
+        }
         $message = [];
         $labelsToSkip = [];
         $this->clickGiftMessageButton($itemName);
@@ -88,4 +91,18 @@ class View extends Block
             Locator::SELECTOR_XPATH
         )->click();
     }
+
+    /**
+     * Click "Gift Message" for special item.
+     *
+     * @param string $itemName
+     * @return bool
+     */
+    protected function giftMessageButtonIsVisible($itemName)
+    {
+        return $this->_rootElement->find(
+            sprintf($this->giftMessageButtonSelector, $itemName),
+            Locator::SELECTOR_XPATH
+        )->isVisible();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Constraint/AssertGiftMessageInFrontendOrderItems.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Constraint/AssertGiftMessageInFrontendOrderItems.php
index a9a17c123c4c1b44d43312727d49111b29735da7..932115cdf37abb0a769342973706c00a20f05734 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Constraint/AssertGiftMessageInFrontendOrderItems.php
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Constraint/AssertGiftMessageInFrontendOrderItems.php
@@ -62,6 +62,10 @@ class AssertGiftMessageInFrontendOrderItems extends AbstractConstraint
                     'message' => $itemGiftMessage->getMessage(),
                 ];
             }
+            if ($product->getIsVirtual() == 'Yes') {
+                $expectedData = [];
+            }
+
             \PHPUnit_Framework_Assert::assertEquals(
                 $expectedData,
                 $customerOrderView->getGiftMessageForItemBlock()->getGiftMessage($product->getName()),
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutCart.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutCart.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c911cebf77f4afe51df39d6159bc5ef6f2874499
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutCart.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd">
+  <page name="CheckoutCart" mca="checkout/cart">
+    <block name="giftMessagesItemBlock" class="Magento\GiftMessage\Test\Block\Cart\Item\GiftOptions" locator=".gift-options-cart-item" strategy="css selector"/>
+    <block name="giftMessagesOrderBlock" class="Magento\GiftMessage\Test\Block\Cart\GiftOptions" locator=".cart-gift-item" strategy="css selector"/>
+  </page>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutOnepage.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutOnepage.xml
deleted file mode 100644
index 0a83605791e225384c20d3572d861bfd0d31b927..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Page/CheckoutOnepage.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
- -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd">
-  <page name="CheckoutOnepage" mca="checkout/onepage">
-    <block name="giftMessagesBlock" class="Magento\GiftMessage\Test\Block\Message\Inline" locator=".gift-message" strategy="css selector"/>
-  </page>
-</config>
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestStep/AddGiftMessageStep.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestStep/AddGiftMessageStep.php
index 190de05c9eecdf1d89c29a6aeea3cc18416de37e..35c7994df9e5434e5f647e3bf5716433ce8de6de 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestStep/AddGiftMessageStep.php
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestStep/AddGiftMessageStep.php
@@ -6,7 +6,7 @@
 
 namespace Magento\GiftMessage\Test\TestStep;
 
-use Magento\Checkout\Test\Page\CheckoutOnepage;
+use Magento\Checkout\Test\Page\CheckoutCart;
 use Magento\GiftMessage\Test\Fixture\GiftMessage;
 use Magento\Mtf\TestStep\TestStepInterface;
 
@@ -19,9 +19,9 @@ class AddGiftMessageStep implements TestStepInterface
     /**
      * Onepage checkout page
      *
-     * @var CheckoutOnepage
+     * @var CheckoutCart
      */
-    protected $checkoutOnepage;
+    protected $checkoutCart;
 
     /**
      * Gift message fixture
@@ -39,13 +39,13 @@ class AddGiftMessageStep implements TestStepInterface
 
     /**
      * @constructor
-     * @param CheckoutOnepage $checkoutOnepage
+     * @param CheckoutCart $checkoutCart
      * @param GiftMessage $giftMessage
      * @param array $products
      */
-    public function __construct(CheckoutOnepage $checkoutOnepage, GiftMessage $giftMessage, array $products = [])
+    public function __construct(CheckoutCart $checkoutCart, GiftMessage $giftMessage, array $products = [])
     {
-        $this->checkoutOnepage = $checkoutOnepage;
+        $this->checkoutCart = $checkoutCart;
         $this->giftMessage = $giftMessage;
         $this->products = $products;
     }
@@ -57,6 +57,8 @@ class AddGiftMessageStep implements TestStepInterface
      */
     public function run()
     {
-        $this->checkoutOnepage->getGiftMessagesBlock()->fillGiftMessage($this->giftMessage, $this->products);
+        $this->checkoutCart->open();
+        $this->checkoutCart->getGiftMessagesItemBlock()->fillGiftMessageItem($this->giftMessage, $this->products);
+        $this->checkoutCart->getGiftMessagesOrderBlock()->fillGiftMessageOrder($this->giftMessage, $this->products);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml
index de5469059a9b89883c6210b648f0783b8af43fd8..0dfdf20437f1c1d626d645680346d0d8f31f2228 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml
@@ -13,10 +13,10 @@
         <step name="createProducts" module="Magento_Catalog" next="createCustomer" />
         <step name="createCustomer" module="Magento_Customer" next="loginCustomerOnFrontend" />
         <step name="loginCustomerOnFrontend" module="Magento_Customer" next="addProductsToTheCart" />
-        <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" />
+        <step name="addProductsToTheCart" module="Magento_Checkout" next="addGiftMessage" />
+        <step name="addGiftMessage" module="Magento_GiftMessage" next="proceedToCheckout" />
         <step name="proceedToCheckout" module="Magento_Checkout" next="fillBillingInformation" />
-        <step name="fillBillingInformation" module="Magento_Checkout" next="addGiftMessage" />
-        <step name="addGiftMessage" module="Magento_GiftMessage" next="fillShippingMethod" />
+        <step name="fillBillingInformation" module="Magento_Checkout" next="fillShippingMethod" />
         <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" />
         <step name="selectPaymentMethod" module="Magento_Checkout" next="placeOrder" />
         <step name="placeOrder" module="Magento_Checkout" />
diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_address.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_address.php
index cf8a02f20f8489eebb0a4d52c3b9e4172e274bff..becd0114cd30e313f035823e5c7d42b49db79338 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_address.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_address.php
@@ -5,9 +5,11 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
+
 /** @var \Magento\Customer\Model\Address $customerAddress */
 $customerAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
     ->create('Magento\Customer\Model\Address');
+
 $customerAddress->isObjectNew(true);
 $customerAddress->setData(
     [
diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_two_addresses.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_two_addresses.php
index b715451581bf1796b04556498e444ae0a1503267..72b4ffaa01c12d3e2d6dc1166c9f38ed5556bac3 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_two_addresses.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_two_addresses.php
@@ -11,6 +11,7 @@ require 'customer_address.php';
 /** @var \Magento\Customer\Model\Address $customerAddress */
 $customerAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
     ->create('Magento\Customer\Model\Address');
+
 $customerAddress->isObjectNew(true);
 $customerAddress->setData(
     [
diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2869eb4f6c6a3148ae69e322a02353addd06ab4
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Directory\Model\Country\Postcode;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+class ValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Directory\Model\Country\Postcode\ValidatorInterface
+     */
+    protected $validator;
+
+    protected function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->validator = $objectManager->create('Magento\Directory\Model\Country\Postcode\ValidatorInterface');
+    }
+
+    /**
+     * @dataProvider getPostcodesDataProvider
+     */
+    public function testPostCodes($countryId, $validPostcode)
+    {
+        try {
+            $this->assertTrue($this->validator->validate($validPostcode, $countryId));
+            $this->assertFalse($this->validator->validate('INVALID-100', $countryId));
+        } catch (\InvalidArgumentException $ex) {
+            //skip validation test for none existing countryId
+        }
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Provided countryId does not exist.
+     */
+    public function testPostCodesThrowsExceptionIfCountryDoesNotExist()
+    {
+        $this->validator->validate('12345', 'INVALID-CODE');
+    }
+
+    /**
+     * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function getPostcodesDataProvider()
+    {
+        return [
+            ['countryId' => 'DZ', 'postcode' => '12345'],
+            ['countryId' => 'AS', 'postcode' => '12345'],
+            ['countryId' => 'AR', 'postcode' => '1234'],
+            ['countryId' => 'AM', 'postcode' => '123456'],
+            ['countryId' => 'AU', 'postcode' => '1234'],
+            ['countryId' => 'AT', 'postcode' => '1234'],
+            ['countryId' => 'AZ', 'postcode' => '1234'],
+            ['countryId' => 'AZ', 'postcode' => '123456'],
+            ['countryId' => 'BD', 'postcode' => '1234'],
+            ['countryId' => 'BY', 'postcode' => '123456'],
+            ['countryId' => 'BE', 'postcode' => '1234'],
+            ['countryId' => 'BA', 'postcode' => '12345'],
+            ['countryId' => 'BR', 'postcode' => '12345'],
+            ['countryId' => 'BR', 'postcode' => '12345-678'],
+            ['countryId' => 'BN', 'postcode' => 'PS1234'],
+            ['countryId' => 'BG', 'postcode' => '1234'],
+            ['countryId' => 'CA', 'postcode' => 'P9M 3T6'],
+            ['countryId' => 'IC', 'postcode' => '12345'],
+            ['countryId' => 'CN', 'postcode' => '123456'],
+            ['countryId' => 'HR', 'postcode' => '12345'],
+            ['countryId' => 'CU', 'postcode' => '12345'],
+            ['countryId' => 'CY', 'postcode' => '1234'],
+            ['countryId' => 'CZ', 'postcode' => '123 45'],
+            ['countryId' => 'DK', 'postcode' => '1234'],
+            ['countryId' => 'EE', 'postcode' => '12345'],
+            ['countryId' => 'FI', 'postcode' => '12345'],
+            ['countryId' => 'FR', 'postcode' => '12345'],
+            ['countryId' => 'GF', 'postcode' => '12345'],
+            ['countryId' => 'GE', 'postcode' => '1234'],
+            ['countryId' => 'DE', 'postcode' => '12345'],
+            ['countryId' => 'GR', 'postcode' => '123 45'],
+            ['countryId' => 'GL', 'postcode' => '1234'],
+            ['countryId' => 'GP', 'postcode' => '12345'],
+            ['countryId' => 'GU', 'postcode' => '12345'],
+            ['countryId' => 'GG', 'postcode' => 'PL5 7TH'],
+            ['countryId' => 'HU', 'postcode' => '1234'],
+            ['countryId' => 'IS', 'postcode' => '123'],
+            ['countryId' => 'IN', 'postcode' => '123456'],
+            ['countryId' => 'ID', 'postcode' => '12345'],
+            ['countryId' => 'IL', 'postcode' => '12345'],
+            ['countryId' => 'IT', 'postcode' => '12345'],
+            ['countryId' => 'JP', 'postcode' => '123-4567'],
+            ['countryId' => 'JP', 'postcode' => '123'],
+            ['countryId' => 'JE', 'postcode' => 'TY8 9PL'],
+            ['countryId' => 'KZ', 'postcode' => '123456'],
+            ['countryId' => 'KE', 'postcode' => '12345'],
+            ['countryId' => 'KR', 'postcode' => '123-456'],
+            ['countryId' => 'KG', 'postcode' => '123456'],
+            ['countryId' => 'LV', 'postcode' => '1234'],
+            ['countryId' => 'LI', 'postcode' => '1234'],
+            ['countryId' => 'LT', 'postcode' => '12345'],
+            ['countryId' => 'LU', 'postcode' => '1234'],
+            ['countryId' => 'MK', 'postcode' => '1234'],
+            ['countryId' => 'MG', 'postcode' => '123'],
+            ['countryId' => 'MY', 'postcode' => '12345'],
+            ['countryId' => 'MV', 'postcode' => '12345'],
+            ['countryId' => 'MV', 'postcode' => '1234'],
+            ['countryId' => 'MT', 'postcode' => 'WRT 123'],
+            ['countryId' => 'MT', 'postcode' => 'WRT 45'],
+            ['countryId' => 'MH', 'postcode' => '12345'],
+            ['countryId' => 'MQ', 'postcode' => '12345'],
+            ['countryId' => 'MX', 'postcode' => '12345'],
+            ['countryId' => 'MD', 'postcode' => '1234'],
+            ['countryId' => 'MC', 'postcode' => '12345'],
+            ['countryId' => 'MN', 'postcode' => '123456'],
+            ['countryId' => 'MA', 'postcode' => '12345'],
+            ['countryId' => 'NL', 'postcode' => '1234 TR'],
+            ['countryId' => 'NO', 'postcode' => '1234'],
+            ['countryId' => 'PK', 'postcode' => '12345'],
+            ['countryId' => 'PH', 'postcode' => '1234'],
+            ['countryId' => 'PL', 'postcode' => '12-345'],
+            ['countryId' => 'PT', 'postcode' => '1234'],
+            ['countryId' => 'PT', 'postcode' => '1234-567'],
+            ['countryId' => 'PR', 'postcode' => '12345'],
+            ['countryId' => 'RE', 'postcode' => '12345'],
+            ['countryId' => 'RO', 'postcode' => '123456'],
+            ['countryId' => 'RU', 'postcode' => '123456'],
+            ['countryId' => 'MP', 'postcode' => '12345'],
+            ['countryId' => 'CS', 'postcode' => '12345'],
+            ['countryId' => 'SG', 'postcode' => '123456'],
+            ['countryId' => 'SK', 'postcode' => '123 45'],
+            ['countryId' => 'SI', 'postcode' => '1234'],
+            ['countryId' => 'ZA', 'postcode' => '1234'],
+            ['countryId' => 'ES', 'postcode' => '12345'],
+            ['countryId' => 'XY', 'postcode' => '12345'],
+            ['countryId' => 'SZ', 'postcode' => 'R123'],
+            ['countryId' => 'SE', 'postcode' => '123 45'],
+            ['countryId' => 'CH', 'postcode' => '1234'],
+            ['countryId' => 'TW', 'postcode' => '123'],
+            ['countryId' => 'TW', 'postcode' => '12345'],
+            ['countryId' => 'TJ', 'postcode' => '123456'],
+            ['countryId' => 'TH', 'postcode' => '12345'],
+            ['countryId' => 'TR', 'postcode' => '12345'],
+            ['countryId' => 'TM', 'postcode' => '123456'],
+            ['countryId' => 'UA', 'postcode' => '12345'],
+            ['countryId' => 'GB', 'postcode' => 'PL12 3RT'],
+            ['countryId' => 'GB', 'postcode' => 'P1L 2RT'],
+            ['countryId' => 'GB', 'postcode' => 'QW1 2RT'],
+            ['countryId' => 'GB', 'postcode' => 'QW1R 2TG'],
+            ['countryId' => 'GB', 'postcode' => 'L12 3PL'],
+            ['countryId' => 'GB', 'postcode' => 'Q1 2PL'],
+            ['countryId' => 'US', 'postcode' => '12345-6789'],
+            ['countryId' => 'US', 'postcode' => '12345'],
+            ['countryId' => 'UY', 'postcode' => '12345'],
+            ['countryId' => 'UZ', 'postcode' => '123456'],
+            ['countryId' => 'VI', 'postcode' => '12345'],
+        ];
+    }
+}
diff --git a/dev/tests/performance/benchmark.jmx b/dev/tests/performance/benchmark.jmx
index 6fda461b91e00c23daa17bf64a3f578f456c5ffc..92ac0e689898c76a1dd489ec125330ad1f4d3c61 100644
--- a/dev/tests/performance/benchmark.jmx
+++ b/dev/tests/performance/benchmark.jmx
@@ -892,19 +892,16 @@
           <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp>
         </ConstantTimer>
         <hashTree/>
-        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout billing/shipping addresses" enabled="true">
+        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping information" enabled="true">
           <boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
           <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
             <collectionProp name="Arguments.arguments">
               <elementProp name="" elementType="HTTPArgument">
                 <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                <stringProp name="Argument.value">{&quot;shippingAddress&quot;:{&quot;company&quot;:&quot;&quot;,&quot;fax&quot;:&quot;&quot;,&quot;city&quot;:&quot;Culver City&quot;,&quot;firstname&quot;:&quot;Name&quot;,&quot;lastname&quot;:&quot;Lastname&quot;&#xd;
-,&quot;street&quot;:{&quot;0&quot;:&quot;10441 Jefferson Blvd, ste 200&quot;,&quot;1&quot;:&quot;&quot;},&quot;telephone&quot;:&quot;1-310-945-0345&quot;,&quot;postcode&quot;:&quot;90232&quot;&#xd;
-,&quot;region_id&quot;:&quot;12&quot;,&quot;country_id&quot;:&quot;US&quot;,&quot;region&quot;:&quot;&quot;,&quot;save_in_address_book&quot;:&quot;1&quot;,&quot;email&quot;:&quot;test@example.com&quot;&#xd;
-,&quot;same_as_billing&quot;:1},&quot;billingAddress&quot;:{&quot;company&quot;:&quot;&quot;,&quot;fax&quot;:&quot;&quot;,&quot;city&quot;:&quot;Culver City&quot;,&quot;firstname&quot;:&quot;Name&quot;&#xd;
-,&quot;lastname&quot;:&quot;Lastname&quot;,&quot;street&quot;:{&quot;0&quot;:&quot;10441 Jefferson Blvd, ste 200&quot;,&quot;1&quot;:&quot;&quot;},&quot;telephone&quot;:&quot;1-310-945-0345&quot;&#xd;
-,&quot;postcode&quot;:&quot;90232&quot;,&quot;region_id&quot;:&quot;12&quot;,&quot;country_id&quot;:&quot;US&quot;,&quot;region&quot;:&quot;&quot;,&quot;save_in_address_book&quot;:&quot;1&quot;,&quot;email&quot;&#xd;
-:&quot;test@example.com&quot;,&quot;same_as_billing&quot;:1},&quot;additionalData&quot;:{&quot;extensionAttributes&quot;:{}}}</stringProp>
+                <stringProp name="Argument.value">{&quot;addressInformation&quot;:{&quot;shipping_address&quot;:{&quot;countryId&quot;:&quot;US&quot;,&quot;regionId&quot;:&quot;12&quot;,&quot;regionCode&quot;:&quot;CA&quot;,&quot;region&quot;&#xd;
+:&quot;California&quot;,&quot;street&quot;:[&quot;10441 Jefferson Blvd&quot;,&quot;ste 200&quot;],&quot;company&quot;:&quot;&quot;,&quot;telephone&quot;:&quot;1-310-945-0345&quot;,&quot;fax&quot;&#xd;
+:&quot;&quot;,&quot;postcode&quot;:&quot;90232&quot;,&quot;city&quot;:&quot;Culver City&quot;,&quot;firstname&quot;:&quot;Firstname&quot;,&quot;lastname&quot;:&quot;Lastname&quot;,&quot;saveInAddressBook&quot;&#xd;
+:true},&quot;shipping_method_code&quot;:&quot;flatrate&quot;,&quot;shipping_carrier_code&quot;:&quot;flatrate&quot;}}</stringProp>
                 <stringProp name="Argument.metadata">=</stringProp>
               </elementProp>
             </collectionProp>
@@ -915,7 +912,7 @@
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/addresses</stringProp>
+          <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/shipping-information</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -948,7 +945,7 @@
           <hashTree/>
           <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true">
             <collectionProp name="Asserion.test_strings">
-              <stringProp name="-768590464">{&quot;shipping_methods&quot;:</stringProp>
+              <stringProp name="-1494218646">{&quot;payment_methods&quot;:</stringProp>
             </collectionProp>
             <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
             <boolProp name="Assertion.assume_success">false</boolProp>
@@ -960,15 +957,17 @@
           <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp>
         </ConstantTimer>
         <hashTree/>
-        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping/payment method" enabled="true">
+        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout payment information" enabled="true">
           <boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
           <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
             <collectionProp name="Arguments.arguments">
               <elementProp name="" elementType="HTTPArgument">
                 <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                <stringProp name="Argument.value">{&quot;cartId&quot;:&quot;${cart_id}&quot;,&quot;paymentMethod&quot;:{&quot;method&quot;:&quot;checkmo&quot;,&quot;po_number&quot;:null,&quot;cc_owner&quot;&#xd;
-:null,&quot;cc_number&quot;:null,&quot;cc_type&quot;:null,&quot;cc_exp_year&quot;:null,&quot;cc_exp_month&quot;:null,&quot;additional_data&quot;:null}&#xd;
-,&quot;shippingCarrierCode&quot;:&quot;flatrate&quot;,&quot;shippingMethodCode&quot;:&quot;flatrate&quot;}</stringProp>
+                <stringProp name="Argument.value">{&quot;cartId&quot;:&quot;${cart_id}&quot;,&quot;paymentMethod&quot;:{&quot;method&quot;:&quot;checkmo&quot;,&quot;po_number&quot;:null,&quot;cc_owner&quot;:null,&quot;cc_number&quot;:null&#xd;
+,&quot;cc_type&quot;:null,&quot;cc_exp_year&quot;:null,&quot;cc_exp_month&quot;:null,&quot;additional_data&quot;:null},&quot;billingAddress&quot;:{&quot;countryId&quot;&#xd;
+:&quot;US&quot;,&quot;regionId&quot;:&quot;12&quot;,&quot;regionCode&quot;:&quot;CA&quot;,&quot;region&quot;:&quot;California&quot;,&quot;street&quot;:[&quot;10441 Jefferson Blvd&quot;,&quot;ste 200&quot;&#xd;
+],&quot;company&quot;:&quot;&quot;,&quot;telephone&quot;:&quot;1-310-945-0345&quot;,&quot;fax&quot;:&quot;&quot;,&quot;postcode&quot;:&quot;90232&quot;,&quot;city&quot;:&quot;Culver City&quot;,&quot;firstname&quot;&#xd;
+:&quot;Firstname&quot;,&quot;lastname&quot;:&quot;Lastname&quot;,&quot;saveInAddressBook&quot;:true}}</stringProp>
                 <stringProp name="Argument.metadata">=</stringProp>
               </elementProp>
             </collectionProp>
@@ -979,70 +978,8 @@
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/collect-totals</stringProp>
-          <stringProp name="HTTPSampler.method">PUT</stringProp>
-          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
-          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
-          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
-          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
-          <boolProp name="HTTPSampler.monitor">false</boolProp>
-          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
-        </HTTPSamplerProxy>
-        <hashTree>
-          <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
-            <collectionProp name="HeaderManager.headers">
-              <elementProp name="" elementType="Header">
-                <stringProp name="Header.name">Referer</stringProp>
-                <stringProp name="Header.value">http://mage2.com/checkout/onepage/</stringProp>
-              </elementProp>
-              <elementProp name="" elementType="Header">
-                <stringProp name="Header.name">Content-Type</stringProp>
-                <stringProp name="Header.value">application/json; charset=UTF-8 </stringProp>
-              </elementProp>
-              <elementProp name="" elementType="Header">
-                <stringProp name="Header.name">Accept</stringProp>
-                <stringProp name="Header.value">application/json</stringProp>
-              </elementProp>
-              <elementProp name="" elementType="Header">
-                <stringProp name="Header.name">X-Requested-With</stringProp>
-                <stringProp name="Header.value">XMLHttpRequest</stringProp>
-              </elementProp>
-            </collectionProp>
-          </HeaderManager>
-          <hashTree/>
-          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
-            <collectionProp name="Asserion.test_strings">
-              <stringProp name="629313218">{&quot;grand_total&quot;:</stringProp>
-            </collectionProp>
-            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
-            <boolProp name="Assertion.assume_success">false</boolProp>
-            <intProp name="Assertion.test_type">2</intProp>
-          </ResponseAssertion>
-          <hashTree/>
-        </hashTree>
-        <ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Constant Timer" enabled="true">
-          <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp>
-        </ConstantTimer>
-        <hashTree/>
-        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout place order" enabled="true">
-          <boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
-          <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
-            <collectionProp name="Arguments.arguments">
-              <elementProp name="" elementType="HTTPArgument">
-                <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                <stringProp name="Argument.value"></stringProp>
-                <stringProp name="Argument.metadata">=</stringProp>
-              </elementProp>
-            </collectionProp>
-          </elementProp>
-          <stringProp name="HTTPSampler.domain"></stringProp>
-          <stringProp name="HTTPSampler.port"></stringProp>
-          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
-          <stringProp name="HTTPSampler.response_timeout"></stringProp>
-          <stringProp name="HTTPSampler.protocol">http</stringProp>
-          <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/order</stringProp>
-          <stringProp name="HTTPSampler.method">PUT</stringProp>
+          <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/payment-information</stringProp>
+          <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
           <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
@@ -1143,7 +1080,7 @@
         <hashTree>
           <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true">
             <collectionProp name="Asserion.test_strings">
-              <stringProp name="890055751">You are signed out.</stringProp>
+              <stringProp name="1723813687">You are signed out.</stringProp>
             </collectionProp>
             <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
             <boolProp name="Assertion.assume_success">false</boolProp>
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
index c563b677620382c5b08c868fec60488247f6d359..e342206fe0b6e802e9ccf4e216e16d0cbcddbd22 100755
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
@@ -3657,6 +3657,8 @@ return [
     ['Magento\Centinel\Test\TestCase\CentinelPaymentsValidCcTest'],
     ['Magento\Centinel\CreateOrderTest'],
     ['Magento\Payment\Model\Checks\PaymentMethodChecksInterface', 'Magento\Payment\Model\MethodInterface'],
+    ['Magento\Ui\DataProvider\EavValidationRul', 'Magento\Ui\DataProvider\EavValidationRules'],
+    ['Magento\Framework\View\Element\UiComponent\JsConfigInterface'],
     ['Magento\GiftMessage\Model\Plugin\TotalsDataProcessorPlugin'],
     ['Magento\Catalog\Model\Product\Attribute\Backend\Startdate', 'Magento\Catalog\Model\Attribute\Backend\Startdate'],
 ];
diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php
index 3573fdb87f541e900636e9ed6d921649e35fedc7..737a51721f8a75798c56ec4fd6547afed332e3cc 100755
--- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php
+++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php
@@ -577,6 +577,7 @@ abstract class AbstractDb extends \Magento\Framework\Data\Collection
                     $item->setIdFieldName($this->getIdFieldName());
                 }
                 $item->addData($row);
+                $this->beforeAddLoadedItem($item);
                 $this->addItem($item);
             }
         }
@@ -585,6 +586,17 @@ abstract class AbstractDb extends \Magento\Framework\Data\Collection
         return $this;
     }
 
+    /**
+     * Let do something before add loaded item in collection
+     *
+     * @param \Magento\Framework\Object $item
+     * @return \Magento\Framework\Object
+     */
+    protected function beforeAddLoadedItem(\Magento\Framework\Object $item)
+    {
+        return $item;
+    }
+
     /**
      * Returns a collection item that corresponds to the fetched row
      * and moves the internal data pointer ahead
diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php
index 1c702229061d364526c8e48def6afc36be4b1227..72f6357f06c9fd8a59a3afdb75da20bb7219efe9 100644
--- a/lib/internal/Magento/Framework/Model/AbstractModel.php
+++ b/lib/internal/Magento/Framework/Model/AbstractModel.php
@@ -3,7 +3,6 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\Framework\Model;
 
 use Magento\Framework\Phrase;
@@ -937,4 +936,14 @@ abstract class AbstractModel extends \Magento\Framework\Object
     {
         return $this->storedData;
     }
+
+    /**
+     * Returns _eventPrefix
+     *
+     * @return string
+     */
+    public function getEventPrefix()
+    {
+        return $this->_eventPrefix;
+    }
 }
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php
index 87732d71a0f068818c993fd836d8baa8bb9d9d3a..824b0d5128a8d3329b0a85037d00cd4cf5b1bd6b 100644
--- a/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php
@@ -13,6 +13,7 @@ use Magento\Framework\Exception\LocalizedException;
  * Abstract resource model class
  * @SuppressWarnings(PHPMD.NumberOfChildren)
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
  */
 abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractResource
 {
@@ -394,6 +395,7 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso
      * @param \Magento\Framework\Model\AbstractModel $object
      * @return $this
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @throws \Exception
      * @api
      */
     public function save(\Magento\Framework\Model\AbstractModel $object)
@@ -401,13 +403,16 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso
         if ($object->isDeleted()) {
             return $this->delete($object);
         }
-        if (!$object->hasDataChanges()) {
-            return $this;
-        }
 
         $this->beginTransaction();
 
         try {
+            if (!$this->isModified($object)) {
+                $this->processNotModifiedSave($object);
+                $this->commit();
+                $object->setHasDataChanges(false);
+                return $this;
+            }
             $object->validateBeforeSave();
             $object->beforeSave();
             if ($object->isSaveAllowed()) {
@@ -415,53 +420,13 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso
                 $this->_beforeSave($object);
                 $this->_checkUnique($object);
                 $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
-                if ($object->getId() !== null && (!$this->_useIsObjectNew || !$object->isObjectNew())) {
-                    $condition = $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $object->getId());
-                    /**
-                     * Not auto increment primary key support
-                     */
-                    if ($this->_isPkAutoIncrement) {
-                        $data = $this->prepareDataForUpdate($object);
-                        if (!empty($data)) {
-                            $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
-                        }
-                    } else {
-                        $select = $this->_getWriteAdapter()->select()->from(
-                            $this->getMainTable(),
-                            [$this->getIdFieldName()]
-                        )->where(
-                            $condition
-                        );
-                        if ($this->_getWriteAdapter()->fetchOne($select) !== false) {
-                            $data = $this->prepareDataForUpdate($object);
-                            if (!empty($data)) {
-                                $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
-                            }
-                        } else {
-                            $this->_getWriteAdapter()->insert(
-                                $this->getMainTable(),
-                                $this->_prepareDataForSave($object)
-                            );
-                        }
-                    }
+                if ($this->isObjectNotNew($object)) {
+                    $this->updateObject($object);
                 } else {
-                    $bind = $this->_prepareDataForSave($object);
-                    if ($this->_isPkAutoIncrement) {
-                        unset($bind[$this->getIdFieldName()]);
-                    }
-                    $this->_getWriteAdapter()->insert($this->getMainTable(), $bind);
-
-                    $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));
-
-                    if ($this->_useIsObjectNew) {
-                        $object->isObjectNew(false);
-                    }
+                    $this->saveNewObject($object);
                 }
-
                 $this->unserializeFields($object);
-                $this->_afterSave($object);
-
-                $object->afterSave();
+                $this->processAfterSaves($object);
             }
             $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
             $object->setHasDataChanges(false);
@@ -798,4 +763,111 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso
 
         return $data;
     }
+
+    /**
+     * Check if object is new
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return bool
+     */
+    protected function isObjectNotNew(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $object->getId() !== null && (!$this->_useIsObjectNew || !$object->isObjectNew());
+    }
+
+    /**
+     * Save New Object
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @throws LocalizedException
+     * @return void
+     */
+    protected function saveNewObject(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $bind = $this->_prepareDataForSave($object);
+        if ($this->_isPkAutoIncrement) {
+            unset($bind[$this->getIdFieldName()]);
+        }
+        $this->_getWriteAdapter()->insert($this->getMainTable(), $bind);
+
+        $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));
+
+        if ($this->_useIsObjectNew) {
+            $object->isObjectNew(false);
+        }
+    }
+
+    /**
+     * Update existing object
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @throws LocalizedException
+     * @return void
+     */
+    protected function updateObject(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $condition = $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $object->getId());
+        /**
+         * Not auto increment primary key support
+         */
+        if ($this->_isPkAutoIncrement) {
+            $data = $this->prepareDataForUpdate($object);
+            if (!empty($data)) {
+                $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
+            }
+        } else {
+            $select = $this->_getWriteAdapter()->select()->from(
+                $this->getMainTable(),
+                [$this->getIdFieldName()]
+            )->where(
+                $condition
+            );
+            if ($this->_getWriteAdapter()->fetchOne($select) !== false) {
+                $data = $this->prepareDataForUpdate($object);
+                if (!empty($data)) {
+                    $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
+                }
+            } else {
+                $this->_getWriteAdapter()->insert(
+                    $this->getMainTable(),
+                    $this->_prepareDataForSave($object)
+                );
+            }
+        }
+    }
+
+    /**
+     * Sequences of after save call
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return void
+     */
+    protected function processAfterSaves(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $this->_afterSave($object);
+        $object->afterSave();
+    }
+
+    /**
+     * Check if object was modified
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return bool
+     */
+    protected function isModified(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $object->hasDataChanges();
+    }
+
+    /**
+     * Process object which was modified
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return $this
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    protected function processNotModifiedSave(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $this;
+    }
 }
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/AbstractDb.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/AbstractDb.php
new file mode 100644
index 0000000000000000000000000000000000000000..78c6a1b4c05bb70ed2e0f3363b42e0755cde4f89
--- /dev/null
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/AbstractDb.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
+
+/**
+ * Class AbstractDb with snapshot saving and relation save processing
+ */
+abstract class AbstractDb extends \Magento\Framework\Model\Resource\Db\AbstractDb
+{
+    /**
+     * @var Snapshot
+     */
+    protected $entitySnapshot;
+
+    /**
+     * @var RelationComposite
+     */
+    protected $entityRelationComposite;
+
+    /**
+     * @param Snapshot $entitySnapshot
+     * @param RelationComposite $entityRelationComposite
+     * @param \Magento\Framework\Model\Resource\Db\Context $context
+     * @param string $resourcePrefix
+     */
+    public function __construct(
+        \Magento\Framework\Model\Resource\Db\Context $context,
+        Snapshot $entitySnapshot,
+        RelationComposite $entityRelationComposite,
+        $resourcePrefix = null
+    ) {
+        $this->entitySnapshot = $entitySnapshot;
+        $this->entityRelationComposite = $entityRelationComposite;
+        parent::__construct($context, $resourcePrefix);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $this->entitySnapshot->registerSnapshot($object);
+        return parent::_afterLoad($object);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function processAfterSaves(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $this->_afterSave($object);
+        $this->entitySnapshot->registerSnapshot($object);
+        $object->afterSave();
+        $this->entityRelationComposite->processRelations($object);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function isModified(\Magento\Framework\Model\AbstractModel $object)
+    {
+        return $this->entitySnapshot->isModified($object);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function processNotModifiedSave(\Magento\Framework\Model\AbstractModel $object)
+    {
+        $this->entityRelationComposite->processRelations($object);
+        return $this;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Collection.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Collection.php
new file mode 100644
index 0000000000000000000000000000000000000000..84f2334021e834c56d4aaa436c426a4eaf49d906
--- /dev/null
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Collection.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
+
+/**
+ * Class Collection
+ */
+abstract class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+{
+    /**
+     * @var Snapshot
+     */
+    protected $entitySnapshot;
+
+    /**
+     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
+     * @param \Psr\Log\LoggerInterface $logger
+     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
+     * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param Snapshot $entitySnapshot
+     * @param \Zend_Db_Adapter_Abstract $connection
+     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
+     */
+    public function __construct(
+        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
+        \Psr\Log\LoggerInterface $logger,
+        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
+        \Magento\Framework\Event\ManagerInterface $eventManager,
+        Snapshot $entitySnapshot,
+        $connection = null,
+        \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
+    ) {
+        $this->entitySnapshot = $entitySnapshot;
+        parent::__construct(
+            $entityFactory,
+            $logger,
+            $fetchStrategy,
+            $eventManager,
+            $connection,
+            $resource
+        );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function fetchItem()
+    {
+        $item = parent::fetchItem();
+        if ($item) {
+            $this->entitySnapshot->registerSnapshot($item);
+        }
+        return $item;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function beforeAddLoadedItem(\Magento\Framework\Object $item)
+    {
+        $this->entitySnapshot->registerSnapshot($item);
+        return $item;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Metadata.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Metadata.php
new file mode 100644
index 0000000000000000000000000000000000000000..b761d22717f2f0ecb5fe99f5b3c15e43405f58c4
--- /dev/null
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Metadata.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
+
+/**
+ * Class Metadata represents a list of entity fields that are applicable for persistence operations
+ */
+class Metadata
+{
+    /**
+     * @var array
+     */
+    protected $metadataInfo = [];
+
+    /**
+     * Returns list of entity fields that are applicable for persistence operations
+     *
+     * @param \Magento\Framework\Object $entity
+     * @return array
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function getFields(\Magento\Framework\Object $entity)
+    {
+        $entityClass = get_class($entity);
+        if (!isset($this->metadataInfo[$entityClass])) {
+            $this->metadataInfo[$entityClass] =
+                array_fill_keys(
+                    array_keys(
+                        $entity->getResource()->getReadConnection()->describeTable(
+                            $entity->getResource()->getMainTable()
+                        )
+                    ),
+                    null
+                );
+        }
+        return $this->metadataInfo[$entityClass];
+    }
+}
diff --git a/app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationComposite.php
similarity index 81%
rename from app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php
rename to lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationComposite.php
index 3c367791a20f82990084b87525e54e77455596e2..42a2496f284447fd7dcec95dda0507c8987df2fc 100644
--- a/app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationComposite.php
@@ -3,16 +3,15 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
 
-namespace Magento\Sales\Model\Resource;
-
-use Magento\Sales\Model\AbstractModel;
+use Magento\Framework\Model\AbstractModel;
 use Magento\Framework\Event\ManagerInterface as EventManager;
 
 /**
- * Class EntityRelationComposite
+ * Class RelationComposite
  */
-class EntityRelationComposite
+class RelationComposite
 {
     /**
      * @var array
@@ -37,13 +36,15 @@ class EntityRelationComposite
     }
 
     /**
+     * Process model's relations saves
+     *
      * @param AbstractModel $object
      * @return void
      */
     public function processRelations(AbstractModel $object)
     {
         foreach ($this->relationProcessors as $processor) {
-            /**@var $processor \Magento\Sales\Model\Resource\EntityRelationInterface*/
+            /**@var $processor RelationInterface*/
             $processor->processRelation($object);
         }
         $this->eventManager->dispatch(
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationInterface.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..b16d44509381ae2231c707610f51e6df26daa998
--- /dev/null
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/RelationInterface.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
+
+/**
+ * Interface RelationInterface
+ */
+interface RelationInterface
+{
+    /**
+     * Process object relations
+     *
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return void
+     */
+    public function processRelation(\Magento\Framework\Model\AbstractModel $object);
+}
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Snapshot.php b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Snapshot.php
new file mode 100644
index 0000000000000000000000000000000000000000..dc837426020a4361561a6a5d013367bb1f0e659f
--- /dev/null
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/VersionControl/Snapshot.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Model\Resource\Db\VersionControl;
+
+/**
+ * Class Snapshot register snapshot of entity data, for tracking changes
+ */
+class Snapshot
+{
+    /**
+     * Array of snapshots of entities data
+     *
+     * @var array
+     */
+    protected $snapshotData = [];
+
+    /**
+     * @var Metadata
+     */
+    protected $metadata;
+
+    /**
+     * Initialization
+     *
+     * @param Metadata $metadata
+     */
+    public function __construct(
+        Metadata $metadata
+    ) {
+        $this->metadata = $metadata;
+    }
+
+    /**
+     * Register snapshot of entity data, for tracking changes
+     *
+     * @param \Magento\Framework\Object $entity
+     * @return void
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
+     */
+    public function registerSnapshot(\Magento\Framework\Object $entity)
+    {
+        $metaData = $this->metadata->getFields($entity);
+        $filteredData = array_intersect_key($entity->getData(), $metaData);
+        $data = array_merge($metaData, $filteredData);
+        $this->snapshotData[get_class($entity)][$entity->getId()] = $data;
+    }
+
+    /**
+     * Check is current entity has changes, by comparing current object state with stored snapshot
+     *
+     * @param \Magento\Framework\Object $entity
+     * @return bool
+     */
+    public function isModified(\Magento\Framework\Object $entity)
+    {
+        if (!$entity->getId()) {
+            return true;
+        }
+
+        $entityClass = get_class($entity);
+        if (!isset($this->snapshotData[$entityClass][$entity->getId()])) {
+            return true;
+        }
+        foreach ($this->snapshotData[$entityClass][$entity->getId()] as $field => $value) {
+            if ($entity->getDataByKey($field) != $value) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityMetadataTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/MetadataTest.php
similarity index 80%
rename from app/code/Magento/Sales/Test/Unit/Model/Resource/EntityMetadataTest.php
rename to lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/MetadataTest.php
index bfb0c1ab8c0325d064ad3ce6cd663fe07cc86edf..553ea15c2be9a1d8324d10ac14981d10bbc9da29 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityMetadataTest.php
+++ b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/MetadataTest.php
@@ -3,22 +3,22 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Sales\Test\Unit\Model\Resource;
+namespace Magento\Framework\Model\Test\Unit\Resource\Db\VersionControl;
 
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
- * Class EntityMetadataTest
+ * Class Version Control MetadataTest
  */
-class EntityMetadataTest extends \PHPUnit_Framework_TestCase
+class MetadataTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Sales\Model\Resource\EntityMetadata
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Metadata
      */
     protected $entityMetadata;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Sales\Model\AbstractModel
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Model\AbstractModel
      */
     protected $model;
 
@@ -39,7 +39,7 @@ class EntityMetadataTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = new ObjectManager($this);
         $this->model = $this->getMock(
-            'Magento\Sales\Model\AbstractModel',
+            'Magento\Framework\Model\AbstractModel',
             [],
             [],
             '',
@@ -63,13 +63,15 @@ class EntityMetadataTest extends \PHPUnit_Framework_TestCase
         );
         $this->model->expects($this->any())->method('getResource')->willReturn($this->resource);
         $this->resource->expects($this->any())->method('getReadConnection')->willReturn($this->connection);
-        $this->entityMetadata = $objectManager->getObject('Magento\Sales\Model\Resource\EntityMetadata');
+        $this->entityMetadata = $objectManager->getObject(
+            'Magento\Framework\Model\Resource\Db\VersionControl\Metadata'
+        );
     }
 
     public function testGetFields()
     {
         $mainTable = 'main_table';
-        $expectedDescribedTable = 'described_table';
+        $expectedDescribedTable = ['described_table' => null];
         $this->resource->expects($this->any())->method('getMainTable')->willReturn($mainTable);
         $this->connection->expects($this->once())->method('describeTable')->with($mainTable)->willReturn(
             $expectedDescribedTable
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/RelationCompositeTest.php
similarity index 56%
rename from app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php
rename to lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/RelationCompositeTest.php
index 9da63a991cd7e6b5b973b1e2bc429fe4807a1efa..942b5bd8c59238101fa0b3b3ef0255772a878d36 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php
+++ b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/RelationCompositeTest.php
@@ -4,25 +4,25 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Sales\Test\Unit\Model\Resource;
+namespace Magento\Framework\Model\Test\Unit\Resource\Db\VersionControl;
 
 /**
- * Class EntityRelationCompositeTest
+ * Class RelationCompositeTest
  */
-class EntityRelationCompositeTest extends \PHPUnit_Framework_TestCase
+class RelationCompositeTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Sales\Model\Resource\EntityRelationComposite
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite
      */
     protected $entityRelationComposite;
 
     /**
-     * @var \Magento\Sales\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $salesModelMock;
+    protected $modelMock;
 
     /**
-     * @var \Magento\Sales\Model\Resource\EntityRelationInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface
      */
     protected $relationProcessorMock;
 
@@ -33,7 +33,7 @@ class EntityRelationCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function setUp()
     {
-        $this->salesModelMock = $this->getMockBuilder('Magento\Sales\Model\AbstractModel')
+        $this->modelMock = $this->getMockBuilder('Magento\Framework\Model\AbstractModel')
             ->disableOriginalConstructor()
             ->setMethods(
                 [
@@ -41,16 +41,17 @@ class EntityRelationCompositeTest extends \PHPUnit_Framework_TestCase
                 ]
             )
             ->getMockForAbstractClass();
-        $this->relationProcessorMock = $this->getMockBuilder('Magento\Sales\Model\AbstractModel')
+        $this->relationProcessorMock = $this->getMockBuilder('Magento\Framework\Model\AbstractModel')
             ->disableOriginalConstructor()
             ->getMockForAbstractClass();
         $this->eventManagerMock = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface')
             ->disableOriginalConstructor()
             ->getMockForAbstractClass();
-        $this->relationProcessorMock = $this->getMockBuilder('Magento\Sales\Model\Resource\EntityRelationInterface')
-            ->disableOriginalConstructor()
-            ->getMockForAbstractClass();
-        $this->entityRelationComposite = new \Magento\Sales\Model\Resource\EntityRelationComposite(
+        $this->relationProcessorMock = $this->getMockBuilder(
+            'Magento\Framework\Model\Resource\Db\VersionControl\RelationInterface'
+        )->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->entityRelationComposite = new \Magento\Framework\Model\Resource\Db\VersionControl\RelationComposite(
             $this->eventManagerMock,
             [
                 'default' => $this->relationProcessorMock
@@ -62,18 +63,18 @@ class EntityRelationCompositeTest extends \PHPUnit_Framework_TestCase
     {
         $this->relationProcessorMock->expects($this->once())
             ->method('processRelation')
-            ->with($this->salesModelMock);
-        $this->salesModelMock->expects($this->once())
+            ->with($this->modelMock);
+        $this->modelMock->expects($this->once())
             ->method('getEventPrefix')
-            ->willReturn('sales_event_prefix');
+            ->willReturn('custom_event_prefix');
         $this->eventManagerMock->expects($this->once())
             ->method('dispatch')
             ->with(
-                'sales_event_prefix_process_relation',
+                'custom_event_prefix_process_relation',
                 [
-                    'object' => $this->salesModelMock
+                    'object' => $this->modelMock
                 ]
             );
-        $this->entityRelationComposite->processRelations($this->salesModelMock);
+        $this->entityRelationComposite->processRelations($this->modelMock);
     }
 }
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntitySnapshotTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/SnapshotTest.php
similarity index 62%
rename from app/code/Magento/Sales/Test/Unit/Model/Resource/EntitySnapshotTest.php
rename to lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/SnapshotTest.php
index 6a7b4c896a0449f535d37589ece506fbc84ea42c..34aa803dae17641c5c679a9adb9078f869e9da31 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntitySnapshotTest.php
+++ b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/VersionControl/SnapshotTest.php
@@ -3,27 +3,27 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Sales\Test\Unit\Model\Resource;
+namespace Magento\Framework\Model\Test\Unit\Resource\Db\VersionControl;
 
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
- * Class EntitySnapshotTest
+ * Class SnapshotTest
  */
-class EntitySnapshotTest extends \PHPUnit_Framework_TestCase
+class SnapshotTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Sales\Model\Resource\EntitySnapshot
+     * @var \Magento\Framework\Model\Resource\Db\VersionControl\Snapshot
      */
     protected $entitySnapshot;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Sales\Model\Resource\EntityMetadata
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Model\Resource\Db\VersionControl\Metadata
      */
     protected $entityMetadata;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Sales\Model\AbstractModel
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Model\AbstractModel
      */
     protected $model;
 
@@ -34,24 +34,24 @@ class EntitySnapshotTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = new ObjectManager($this);
         $this->model = $this->getMock(
-            'Magento\Sales\Model\AbstractModel',
-            [],
+            'Magento\Framework\Model\AbstractModel',
+            ['getId'],
             [],
             '',
             false
         );
 
         $this->entityMetadata = $this->getMock(
-            'Magento\Sales\Model\Resource\EntityMetadata',
-            [],
+            'Magento\Framework\Model\Resource\Db\VersionControl\Metadata',
+            ['getFields'],
             [],
             '',
             false
         );
 
         $this->entitySnapshot = $objectManager->getObject(
-            'Magento\Sales\Model\Resource\EntitySnapshot',
-            ['entityMetadata' => $this->entityMetadata]
+            'Magento\Framework\Model\Resource\Db\VersionControl\Snapshot',
+            ['metadata' => $this->entityMetadata]
         );
     }
 
@@ -65,14 +65,16 @@ class EntitySnapshotTest extends \PHPUnit_Framework_TestCase
             'custom_not_present_attribute' => ''
         ];
         $fields = [
-            'id',
-            'name',
-            'description'
+            'id' => [],
+            'name' => [],
+            'description' => []
         ];
-        $this->model->expects($this->once())->method('getData')->willReturn($data);
-        $this->model->expects($this->once())->method('getId')->willReturn($entityId);
-        $this->entityMetadata->expects($this->once())->method('getFields')->with($this->model)->willReturn($fields);
+        $this->assertTrue($this->entitySnapshot->isModified($this->model));
+        $this->model->setData($data);
+        $this->model->expects($this->any())->method('getId')->willReturn($entityId);
+        $this->entityMetadata->expects($this->any())->method('getFields')->with($this->model)->willReturn($fields);
         $this->entitySnapshot->registerSnapshot($this->model);
+        $this->assertFalse($this->entitySnapshot->isModified($this->model));
     }
 
     public function testIsModified()
@@ -90,15 +92,11 @@ class EntitySnapshotTest extends \PHPUnit_Framework_TestCase
             'description' => []
         ];
         $modifiedData = array_merge($data, ['name' => 'newName']);
-        $this->model->expects($this->exactly(4))->method('getData')->willReturnOnConsecutiveCalls(
-            $data,
-            $modifiedData,
-            $modifiedData,
-            $modifiedData
-        );
         $this->model->expects($this->any())->method('getId')->willReturn($entityId);
-        $this->entityMetadata->expects($this->exactly(4))->method('getFields')->with($this->model)->willReturn($fields);
+        $this->entityMetadata->expects($this->exactly(2))->method('getFields')->with($this->model)->willReturn($fields);
+        $this->model->setData($data);
         $this->entitySnapshot->registerSnapshot($this->model);
+        $this->model->setData($modifiedData);
         $this->assertTrue($this->entitySnapshot->isModified($this->model));
         $this->entitySnapshot->registerSnapshot($this->model);
         $this->assertFalse($this->entitySnapshot->isModified($this->model));
diff --git a/lib/internal/Magento/Framework/View/Element/Template.php b/lib/internal/Magento/Framework/View/Element/Template.php
index 8e1c8e4cb27946799946680b342aff3ae78949df..a9928ab157baac5bdcbc1a0826a825254813ee5f 100644
--- a/lib/internal/Magento/Framework/View/Element/Template.php
+++ b/lib/internal/Magento/Framework/View/Element/Template.php
@@ -55,13 +55,6 @@ class Template extends AbstractBlock
      */
     protected $_filesystem;
 
-    /**
-     * View file system
-     *
-     * @var \Magento\Framework\View\FileSystem
-     */
-    protected $_viewFileSystem;
-
     /**
      * Path to template file in theme.
      *
@@ -116,6 +109,16 @@ class Template extends AbstractBlock
      */
     protected $pageConfig;
 
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Resolver
+     */
+    protected $resolver;
+
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Validator
+     */
+    protected $validator;
+
     /**
      * Constructor
      *
@@ -124,8 +127,9 @@ class Template extends AbstractBlock
      */
     public function __construct(Template\Context $context, array $data = [])
     {
+        $this->validator = $context->getValidator();
+        $this->resolver = $context->getResolver();
         $this->_filesystem = $context->getFilesystem();
-        $this->_viewFileSystem = $context->getViewFileSystem();
         $this->templateEnginePool = $context->getEnginePool();
         $this->_storeManager = $context->getStoreManager();
         $this->_appState = $context->getAppState();
@@ -199,8 +203,7 @@ class Template extends AbstractBlock
         if ($area) {
             $params['area'] = $area;
         }
-        $templateName = $this->_viewFileSystem->getTemplateFileName($template ?: $this->getTemplate(), $params);
-        return $templateName;
+        return $this->resolver->getTemplateFileName($template ?: $this->getTemplate(), $params);
     }
 
     /**
@@ -246,7 +249,7 @@ class Template extends AbstractBlock
             ['group' => 'TEMPLATE', 'file_name' => $relativeFilePath]
         );
 
-        if ($this->isTemplateFileValid($fileName)) {
+        if ($this->validator->isValid($fileName)) {
             $extension = pathinfo($fileName, PATHINFO_EXTENSION);
             $templateEngine = $this->templateEnginePool->get($extension);
             $html = $templateEngine->render($this->templateContext, $fileName, $this->_viewVars);
@@ -312,22 +315,6 @@ class Template extends AbstractBlock
         ];
     }
 
-    /**
-     * Get is allowed symliks flag
-     *
-     * @return bool
-     */
-    protected function isAllowSymlinks()
-    {
-        if (null === $this->_allowSymlinks) {
-            $this->_allowSymlinks = $this->_scopeConfig->isSetFlag(
-                self::XML_PATH_TEMPLATE_ALLOW_SYMLINK,
-                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-            );
-        }
-        return $this->_allowSymlinks;
-    }
-
     /**
      * Instantiates filesystem directory
      *
@@ -354,49 +341,4 @@ class Template extends AbstractBlock
         }
         return $this->mediaDirectory;
     }
-
-    /**
-     * Checks whether the provided file can be rendered.
-     *
-     * Available directories which are allowed to be rendered
-     * (the template file should be located under these directories):
-     *  - app
-     *  - design
-     *
-     * @param string $fileName
-     * @return bool
-     */
-    protected function isTemplateFileValid($fileName)
-    {
-        $fileName = str_replace('\\', '/', $fileName);
-
-        $themesDir = $this->_filesystem->getDirectoryRead(DirectoryList::THEMES)->getAbsolutePath();
-        $appDir = $this->_filesystem->getDirectoryRead(DirectoryList::APP)->getAbsolutePath();
-        $compiledDir = $this->_filesystem->getDirectoryRead(DirectoryList::TEMPLATE_MINIFICATION_DIR)
-            ->getAbsolutePath();
-        return ($this->isPathInDirectory(
-            $fileName,
-            $compiledDir
-        ) || $this->isPathInDirectory(
-            $fileName,
-            $appDir
-        ) || $this->isPathInDirectory(
-            $fileName,
-            $themesDir
-        ) || $this->isAllowSymlinks()) && $this->getRootDirectory()->isFile(
-            $this->getRootDirectory()->getRelativePath($fileName)
-        );
-    }
-
-    /**
-     * Checks whether path related to the directory
-     *
-     * @param string $path
-     * @param string $directory
-     * @return bool
-     */
-    protected function isPathInDirectory($path, $directory)
-    {
-        return 0 === strpos($path, $directory);
-    }
 }
diff --git a/lib/internal/Magento/Framework/View/Element/Template/Context.php b/lib/internal/Magento/Framework/View/Element/Template/Context.php
index 6fddcb67280165d4662656a264035f30e95a5a8c..78251c9ec7991dd713211c9663879bde569a5281 100644
--- a/lib/internal/Magento/Framework/View/Element/Template/Context.php
+++ b/lib/internal/Magento/Framework/View/Element/Template/Context.php
@@ -62,6 +62,17 @@ class Context extends \Magento\Framework\View\Element\Context
     protected $pageConfig;
 
     /**
+     * @var \Magento\Framework\View\Element\Template\File\Resolver
+     */
+    protected $resolver;
+
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Validator
+     */
+    protected $validator;
+
+    /**
+     *
      * @param \Magento\Framework\App\RequestInterface $request
      * @param \Magento\Framework\View\LayoutInterface $layout
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
@@ -85,6 +96,8 @@ class Context extends \Magento\Framework\View\Element\Context
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Framework\View\Page\Config $pageConfig
+     * @param \Magento\Framework\View\Element\Template\File\Resolver $resolver
+     * @param \Magento\Framework\View\Element\Template\File\Validator $validator
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
@@ -111,7 +124,9 @@ class Context extends \Magento\Framework\View\Element\Context
         \Magento\Framework\View\TemplateEnginePool $enginePool,
         \Magento\Framework\App\State $appState,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
-        \Magento\Framework\View\Page\Config $pageConfig
+        \Magento\Framework\View\Page\Config $pageConfig,
+        \Magento\Framework\View\Element\Template\File\Resolver $resolver,
+        \Magento\Framework\View\Element\Template\File\Validator $validator
     ) {
         parent::__construct(
             $request,
@@ -132,7 +147,8 @@ class Context extends \Magento\Framework\View\Element\Context
             $localeDate,
             $inlineTranslation
         );
-
+        $this->resolver = $resolver;
+        $this->validator = $validator;
         $this->_storeManager = $storeManager;
         $this->_appState = $appState;
         $this->_logger = $logger;
@@ -142,6 +158,26 @@ class Context extends \Magento\Framework\View\Element\Context
         $this->pageConfig = $pageConfig;
     }
 
+    /**
+     * Get template file resolver
+     *
+     * @return File\Resolver
+     */
+    public function getResolver()
+    {
+        return $this->resolver;
+    }
+
+    /**
+     * Get validator
+     *
+     * @return File\Validator
+     */
+    public function getValidator()
+    {
+        return $this->validator;
+    }
+
     /**
      * Get filesystem instance
      *
diff --git a/lib/internal/Magento/Framework/View/Element/Template/File/Resolver.php b/lib/internal/Magento/Framework/View/Element/Template/File/Resolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bb7e4884a8b17e87deed5597e14eac2b3be9f25
--- /dev/null
+++ b/lib/internal/Magento/Framework/View/Element/Template/File/Resolver.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\View\Element\Template\File;
+
+/**
+ * Class Resolver
+ * @package Magento\Framework\View\Element\Template\File
+ */
+class Resolver
+{
+    /**
+     * Template files map
+     *
+     * @var []
+     */
+    protected $_templateFilesMap = [];
+
+    /**
+     * View filesystem
+     *
+     * @var \Magento\Framework\View\FileSystem
+     */
+    protected $_viewFileSystem;
+
+    /**
+     * Class constructor
+     *
+     * @param \Magento\Framework\View\FileSystem $viewFileSystem
+     */
+    public function __construct(\Magento\Framework\View\FileSystem $viewFileSystem)
+    {
+        $this->_viewFileSystem = $viewFileSystem;
+    }
+
+    /**
+     * Get template filename
+     *
+     * @param string $template
+     * @param [] $params
+     * @return string|bool
+     */
+    public function getTemplateFileName($template, $params = [])
+    {
+        $key = $template . '_' . serialize($params);
+        if (!isset($this->_templateFilesMap[$key])) {
+            $this->_templateFilesMap[$key] = $this->_viewFileSystem->getTemplateFileName($template, $params);
+        }
+        return $this->_templateFilesMap[$key];
+    }
+}
diff --git a/lib/internal/Magento/Framework/View/Element/Template/File/Validator.php b/lib/internal/Magento/Framework/View/Element/Template/File/Validator.php
new file mode 100644
index 0000000000000000000000000000000000000000..101bae7ad7037e583c6d4cbac150402068d1326e
--- /dev/null
+++ b/lib/internal/Magento/Framework/View/Element/Template/File/Validator.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\View\Element\Template\File;
+
+use \Magento\Framework\App\Filesystem\DirectoryList;
+
+/**
+ * Class Validator
+ * @package Magento\Framework\View\Element\Template\File
+ */
+class Validator
+{
+    /**
+     * Config path to 'Allow Symlinks' template settings
+     */
+    const XML_PATH_TEMPLATE_ALLOW_SYMLINK = 'dev/template/allow_symlink';
+
+    /**
+     * Template files map
+     *
+     * @var []
+     */
+    protected $_templatesValidationResults = [];
+
+    /**
+     * View filesystem
+     *
+     * @var \Magento\Framework\FileSystem
+     */
+    protected $_filesystem;
+
+    /**
+     * Allow symlinks flag
+     *
+     * @var bool
+     */
+    protected $_isAllowSymlinks = false;
+
+    /**
+     * Root directory
+     *
+     * @var bool
+     */
+    protected $directory = null;
+
+    /**
+     * Themes directory
+     *
+     * @var string
+     */
+    protected $_themesDir;
+
+    /**
+     * Application directory
+     *
+     * @var string
+     */
+    protected $_appDir;
+
+    /**
+     * Compiled templates directory
+     *
+     * @var string
+     */
+    protected $_compiledDir;
+
+    /**
+     * Class constructor
+     *
+     * @param \Magento\Framework\Filesystem $filesystem
+     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfigInterface
+     * @param string|null $scope
+     */
+    public function __construct(
+        \Magento\Framework\Filesystem $filesystem,
+        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfigInterface,
+        $scope = null
+    ) {
+        $this->_filesystem = $filesystem;
+        $this->_isAllowSymlinks = $scopeConfigInterface->getValue(self::XML_PATH_TEMPLATE_ALLOW_SYMLINK, $scope);
+        $this->_themesDir = $this->_filesystem->getDirectoryRead(DirectoryList::THEMES)->getAbsolutePath();
+        $this->_appDir = $this->_filesystem->getDirectoryRead(DirectoryList::APP)->getAbsolutePath();
+        $this->_compiledDir = $this->_filesystem->getDirectoryRead(DirectoryList::TEMPLATE_MINIFICATION_DIR)
+            ->getAbsolutePath();
+    }
+
+    /**
+     * Checks whether the provided file can be rendered.
+     *
+     * Available directories which are allowed to be rendered
+     * (the template file should be located under these directories):
+     *  - app
+     *  - design
+     *
+     * @param string $filename
+     * @return bool
+     */
+    public function isValid($filename)
+    {
+        $filename = str_replace('\\', '/', $filename);
+        if (!isset($this->_templatesValidationResults[$filename])) {
+            $this->_templatesValidationResults[$filename] =
+                ($this->isPathInDirectory($filename, $this->_compiledDir)
+                || $this->isPathInDirectory($filename, $this->_appDir)
+                || $this->isPathInDirectory($filename, $this->_themesDir)
+                || $this->_isAllowSymlinks)
+                && $this->getRootDirectory()->isFile($this->getRootDirectory()->getRelativePath($filename));
+        }
+        return $this->_templatesValidationResults[$filename];
+    }
+
+    /**
+     * Checks whether path related to the directory
+     *
+     * @param string $path
+     * @param string $directory
+     * @return bool
+     */
+    protected function isPathInDirectory($path, $directory)
+    {
+        return 0 === strpos($path, $directory);
+    }
+
+    /**
+     * Instantiates filesystem directory
+     *
+     * @return \Magento\Framework\Filesystem\Directory\ReadInterface
+     */
+    protected function getRootDirectory()
+    {
+        if (null === $this->directory) {
+            $this->directory = $this->_filesystem->getDirectoryRead(DirectoryList::ROOT);
+        }
+        return $this->directory;
+    }
+}
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php
index 7e7e27bed013d0205c3f2f00c2112b9ba635b39e..5ea6d07f40505b7aff8d8d9bfeec2bba237410c4 100644
--- a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php
@@ -5,7 +5,9 @@
  */
 namespace Magento\Framework\View\Element\UiComponent\Config\Provider\Component;
 
+use Magento\Framework\Phrase;
 use Magento\Framework\Config\CacheInterface;
+use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\View\Element\UiComponent\Config\Converter;
 use Magento\Framework\View\Element\UiComponent\ArrayObjectFactory;
 use Magento\Framework\View\Element\UiComponent\Config\UiReaderInterface;
@@ -66,9 +68,18 @@ class Definition
      *
      * @param string $name
      * @return array
+     * @throws LocalizedException
      */
     public function getComponentData($name)
     {
+        if (!$this->componentData->offsetExists($name)) {
+            throw new LocalizedException(
+                new Phrase(
+                    'The requested component ("' . $name . '") is not found. '
+                    . 'Before using, you must add the implementation.'
+                )
+            );
+        }
         return (array) $this->componentData->offsetGet($name);
     }
 
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
index 3ff2d6934ce46ce7108dbc886fff3d28def47715..a5792024f66313ad80f7d5d89a605c4990366697 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/LinkTest.php
@@ -53,8 +53,27 @@ class LinkTest extends \PHPUnit_Framework_TestCase
             ->method('getUrl')
             ->will($this->returnArgument('http://site.com/link.html'));
 
+        $validtorMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\File\Validator')
+            ->setMethods(['isValid'])->disableOriginalConstructor()->getMock();
+
+        $scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config')
+            ->setMethods(['isSetFlag'])->disableOriginalConstructor()->getMock();
+
+        $resolverMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\File\Resolver')
+            ->setMethods([])->disableOriginalConstructor()->getMock();
+
         $contextMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\Context')
-            ->setMethods(['getEscaper', 'getUrlBuilder'])->disableOriginalConstructor()->getMock();
+            ->setMethods(['getEscaper', 'getUrlBuilder', 'getValidator', 'getResolver', 'getScopeConfig'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $contextMock->expects($this->any())
+            ->method('getValidator')
+            ->will($this->returnValue($validtorMock));
+
+        $contextMock->expects($this->any())
+            ->method('getResolver')
+            ->will($this->returnValue($resolverMock));
 
         $contextMock->expects($this->any())
             ->method('getEscaper')
@@ -64,6 +83,10 @@ class LinkTest extends \PHPUnit_Framework_TestCase
             ->method('getUrlBuilder')
             ->will($this->returnValue($urlBuilderMock));
 
+        $contextMock->expects($this->any())
+            ->method('getScopeConfig')
+            ->will($this->returnValue($scopeConfigMock));
+
         /** @var \Magento\Framework\View\Element\Html\Link $linkWithAttributes */
         $linkWithAttributes = $objectManagerHelper->getObject(
             'Magento\Framework\View\Element\Html\Link',
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
index 60e4d21af3ab3a5a1bc4a9274da581ca80bc3d95..6e39e1cb47191b43e72bfb49bcc4493e0c67fe2b 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
@@ -38,6 +38,21 @@ class CookieTest extends \PHPUnit_Framework_TestCase
         $this->ipValidatorMock = $this->getMockBuilder('Magento\Framework\Validator\Ip')
             ->disableOriginalConstructor()
             ->getMock();
+
+        $validtorMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\File\Validator')
+            ->setMethods(['isValid'])->disableOriginalConstructor()->getMock();
+
+        $scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config')
+            ->setMethods(['isSetFlag'])->disableOriginalConstructor()->getMock();
+
+        $this->contextMock->expects($this->any())
+            ->method('getScopeConfig')
+            ->will($this->returnValue($scopeConfigMock));
+
+        $this->contextMock->expects($this->any())
+            ->method('getValidator')
+            ->will($this->returnValue($validtorMock));
+
         $this->model = new \Magento\Framework\View\Element\Js\Cookie(
             $this->contextMock,
             $this->sessionConfigMock,
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ResolverTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ResolverTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..31dd64c547cd6b2a1984fdae9dd1c40f615fb782
--- /dev/null
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ResolverTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\View\Test\Unit\Element\Template\File;
+
+/**
+ * Class ResolverTest
+ * @package Magento\Framework\View\Test\Unit\Element\Template\File
+ */
+class ResolverTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Resolver object
+     *
+     * @var \Magento\Framework\View\Element\Template\File\Resolver
+     */
+    protected $_resolver;
+
+    /**
+     * Mock for view file system
+     *
+     * @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_viewFileSystemMock;
+
+    /**
+     * Test Setup
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_viewFileSystemMock = $this->getMock('\Magento\Framework\View\FileSystem', [], [], '', false);
+        $this->_resolver = new \Magento\Framework\View\Element\Template\File\Resolver(
+            $this->_viewFileSystemMock
+        );
+    }
+
+    /**
+     * Resolver get template file name test
+     *
+     * @return void
+     */
+    public function testGetTemplateFileName()
+    {
+        $template = 'template.phtml';
+        $this->_viewFileSystemMock->expects($this->once())
+            ->method('getTemplateFileName')
+            ->with($template)
+            ->will($this->returnValue('path_to' . $template));
+        $this->assertEquals('path_to' . $template, $this->_resolver->getTemplateFileName($template));
+        $this->assertEquals('path_to' . $template, $this->_resolver->getTemplateFileName($template));
+    }
+}
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ValidatorTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..befcf7e5a8c9f2d7397c049b7b704da5d72e0b6a
--- /dev/null
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Template/File/ValidatorTest.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\View\Test\Unit\Element\Template\File;
+
+use \Magento\Framework\App\Filesystem\DirectoryList;
+use \Magento\Framework\Filesystem\DriverPool;
+
+/**
+ * Class ValidatorTest
+ * @package Magento\Framework\View\Test\Unit\Element\Template\File
+ */
+class ValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Resolver object
+     *
+     * @var \Magento\Framework\View\Element\Template\File\Validator
+     */
+    protected $_validator;
+
+    /**
+     * Mock for view file system
+     *
+     * @var \Magento\Framework\FileSystem|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_fileSystemMock;
+
+    /**
+     * Mock for scope config
+     *
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_scopeConfigMock;
+
+    /**
+     * Mock for root directory reader
+     *
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $rootDirectoryMock;
+
+    /**
+     * Mock for app directory reader
+     *
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $appDirectoryMock;
+
+    /**
+     * Mock for themes directory reader
+     *
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $themesDirectoryMock;
+
+    /**
+     * Mock for compiled directory reader
+     *
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $compiledDirectoryMock;
+
+    /**
+     * Test Setup
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_fileSystemMock = $this->getMock('\Magento\Framework\Filesystem', [], [], '', false);
+        $this->_scopeConfigMock = $this->getMock('\Magento\Framework\App\Config\ScopeConfigInterface');
+        $this->rootDirectoryMock = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface');
+        $this->appDirectoryMock = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface');
+        $this->themesDirectoryMock = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface');
+        $this->compiledDirectoryMock = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface');
+
+        $this->_fileSystemMock->expects($this->any())
+            ->method('getDirectoryRead')
+            ->will($this->returnValueMap(
+                [
+                    [DirectoryList::ROOT, DriverPool::FILE, $this->rootDirectoryMock],
+                    [DirectoryList::THEMES, DriverPool::FILE, $this->themesDirectoryMock],
+                    [DirectoryList::APP, DriverPool::FILE, $this->appDirectoryMock],
+                    [DirectoryList::TEMPLATE_MINIFICATION_DIR, DriverPool::FILE, $this->compiledDirectoryMock],
+                ]
+            ));
+
+        $this->compiledDirectoryMock->expects($this->any())
+            ->method('getAbsolutePath')
+            ->will($this->returnValue('/magento/var/compiled'));
+
+        $this->appDirectoryMock->expects($this->any())
+            ->method('getAbsolutePath')
+            ->will($this->returnValue('/magento/app'));
+
+        $this->themesDirectoryMock->expects($this->any())
+            ->method('getAbsolutePath')
+            ->will($this->returnValue('/magento/themes'));
+
+        $this->_validator = new \Magento\Framework\View\Element\Template\File\Validator(
+            $this->_fileSystemMock,
+            $this->_scopeConfigMock
+        );
+    }
+
+    /**
+     * Test is file valid
+     *
+     * @param string $file
+     * @param bool $expectedResult
+     *
+     * @dataProvider testIsValidDataProvider
+     *
+     * @return void
+     */
+    public function testIsValid($file, $expectedResult)
+    {
+
+        $this->rootDirectoryMock->expects($this->any())->method('isFile')->will($this->returnValue(true));
+        $this->assertEquals($expectedResult, $this->_validator->isValid($file));
+    }
+
+    /**
+     * Data provider for testIsValid
+     *
+     * @return []
+     */
+    public function testIsValidDataProvider()
+    {
+        return [
+            'empty' => ['', false],
+            '/magento/var/compiled/template.phtml' => ['/magento/var/compiled/template.phtml', true],
+            '/magento/themes/default/template.phtml' => ['/magento/themes/default/template.phtml', true],
+            '/magento/app/code/Some/Module/template.phtml' => ['/magento/app/code/Some/Module/template.phtml', true],
+            '/magento/x' => ['/magento/x', false],
+        ];
+    }
+}
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/TemplateTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/TemplateTest.php
index 0a462c8fd4f453e24df96106c9789d68bb9e09e7..33bba78c6238eee8d64ba66a4a6bde7378986acb 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/TemplateTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/TemplateTest.php
@@ -25,9 +25,14 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
     protected $_templateEngine;
 
     /**
-     * @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\View\Element\Template\File\Resolver|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_viewFileSystem;
+    protected $_resolver;
+
+    /**
+     * @var \Magento\Framework\View\Element\Template\File\Validator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_validator;
 
     /**
      * @var \Magento\Framework\Filesystem\Directory\Read|\PHPUnit_Framework_MockObject_MockObject
@@ -36,7 +41,21 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->_viewFileSystem = $this->getMock('\Magento\Framework\View\FileSystem', [], [], '', false);
+        $this->_resolver = $this->getMock(
+            'Magento\Framework\View\Element\Template\File\Resolver',
+            [],
+            [],
+            '',
+            false
+        );
+
+        $this->_validator = $this->getMock(
+            'Magento\Framework\View\Element\Template\File\Validator',
+            [],
+            [],
+            '',
+            false
+        );
 
         $this->rootDirMock = $this->getMock('Magento\Framework\Filesystem\Directory\Read', [], [], '', false);
         $this->rootDirMock->expects($this->any())
@@ -55,7 +74,10 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
                 [\Magento\Framework\App\Filesystem\DirectoryList::THEMES, DriverPool::FILE, $themesDirMock],
                 [\Magento\Framework\App\Filesystem\DirectoryList::APP, DriverPool::FILE, $appDirMock],
                 [\Magento\Framework\App\Filesystem\DirectoryList::ROOT, DriverPool::FILE, $this->rootDirMock],
-                [\Magento\Framework\App\Filesystem\DirectoryList::TEMPLATE_MINIFICATION_DIR, DriverPool::FILE, $this->rootDirMock],
+                [
+                    \Magento\Framework\App\Filesystem\DirectoryList::TEMPLATE_MINIFICATION_DIR, DriverPool::FILE,
+                    $this->rootDirMock
+                ],
             ]));
 
         $this->_templateEngine = $this->getMock(
@@ -76,7 +98,8 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
             [
                 'filesystem' => $this->_filesystem,
                 'enginePool' => $this->_templateEngine,
-                'viewFileSystem' => $this->_viewFileSystem,
+                'resolver' => $this->_resolver,
+                'validator' => $this->_validator,
                 'appState' => $appState,
                 'data' => ['template' => 'template.phtml', 'module_name' => 'Fixture_Module']
             ]
@@ -86,7 +109,7 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
     public function testGetTemplateFile()
     {
         $params = ['module' => 'Fixture_Module', 'area' => 'frontend'];
-        $this->_viewFileSystem->expects($this->once())->method('getTemplateFileName')->with('template.phtml', $params);
+        $this->_resolver->expects($this->once())->method('getTemplateFileName')->with('template.phtml', $params);
         $this->_block->getTemplateFile();
     }
 
@@ -94,8 +117,8 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
     {
         $this->expectOutputString('');
         $template = 'themedir/template.phtml';
-        $this->rootDirMock->expects($this->once())
-            ->method('isFile')
+        $this->_validator->expects($this->once())
+            ->method('isValid')
             ->with($template)
             ->will($this->returnValue(true));
 
@@ -109,11 +132,12 @@ class TemplateTest extends \PHPUnit_Framework_TestCase
     public function testSetTemplateContext()
     {
         $template = 'themedir/template.phtml';
-        $this->rootDirMock->expects($this->once())
-            ->method('isFile')
+        $context = new \Magento\Framework\Object();
+        $this->_validator->expects($this->once())
+            ->method('isValid')
             ->with($template)
             ->will($this->returnValue(true));
-        $context = new \Magento\Framework\Object();
+
         $this->_templateEngine->expects($this->once())->method('render')->with($context);
         $this->_block->setTemplateContext($context);
         $this->_block->fetchView($template);
diff --git a/lib/internal/Magento/Framework/Webapi/Soap/ClientFactory.php b/lib/internal/Magento/Framework/Webapi/Soap/ClientFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..42d62ab67c334df5d03979441cafad633f0b769d
--- /dev/null
+++ b/lib/internal/Magento/Framework/Webapi/Soap/ClientFactory.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Webapi\Soap;
+
+/**
+ * Class ClientFactory
+ * @package Magento\Framework\Webapi\Soap
+ */
+class ClientFactory
+{
+    /**
+     * Factory method for \SoapClient
+     *
+     * @param string $wsdl
+     * @param array $options
+     * @return \SoapClient
+     */
+    public function create($wsdl, array $options = [])
+    {
+        return new \SoapClient($wsdl, $options);
+    }
+}
diff --git a/lib/web/css/source/components/_modals.less b/lib/web/css/source/components/_modals.less
index df5c973eef2de55b58b941178d1acf677ee0a219..a57580c88722424f70b28214ed1500e94a4ed6c0 100644
--- a/lib/web/css/source/components/_modals.less
+++ b/lib/web/css/source/components/_modals.less
@@ -46,6 +46,7 @@
     &._show {
         visibility: visible;
         .modal-inner-wrap {
+            -webkit-transform: translate(0, 0);
             transform: translate(0, 0);
         }
     }
@@ -62,6 +63,7 @@
     z-index: @modal-slide__z-index;
     &._show {
         .modal-inner-wrap {
+            -webkit-transform: translateX(0);
             transform: translateX(0);
         }
     }
@@ -69,9 +71,11 @@
         height: 100%;
         overflow-y: auto;
         position: static;
+        -webkit-transform: translateX(100%);
         transform: translateX(100%);
         transition-duration: .3s;
         transition-timing-function: ease-in-out;
+        -webkit-transition-property: -webkit-transform, visibility;
         transition-property: transform, visibility;
         width: auto;
     }
@@ -83,18 +87,24 @@
     z-index: @modal-popup__z-index;
     &._show {
         .modal-inner-wrap {
+            -webkit-transform: translateY(0);
             transform: translateY(0);
         }
     }
     .modal-inner-wrap {
+        box-sizing: border-box;
         .vendor-prefix-display(flex);
         .vendor-prefix-flex-direction(column);
         height: auto;
-        margin: @modal-popup__indent-vertical (100% - @modal-popup__width) / 2;
+        left: 0;
+        right: 0;
+        margin: @modal-popup__indent-vertical auto;
         position: absolute;
+        -webkit-transform: translateY(-200%);
         transform: translateY(-200%);
         transition-duration: .2s;
         transition-timing-function: ease;
+        -webkit-transition-property: -webkit-transform, visibility;
         transition-property: transform, visibility;
         width: @modal-popup__width;
     }
@@ -102,10 +112,12 @@
 
 //
 
-._has-modal {
-    height: 100vh;
-    overflow: hidden;
-    width: 100vw;
+body {
+    &._has-modal {
+        height: 100%;
+        overflow: hidden;
+        width: 100%;
+    }
 }
 
 // Modals overlay
@@ -156,8 +168,16 @@
     //  If applied, switching outer popup scroll to inner
     &._inner-scroll {
         overflow-y: visible;
+        .ie10 &,
+        .ie9 & {
+            overflow-y: auto;
+        }
         .modal-inner-wrap {
             max-height: 90%;
+            .ie10 &,
+            .ie9 & {
+                max-height: none;
+            }
         }
         .modal-content {
             overflow-y: auto;
diff --git a/lib/web/css/source/lib/_responsive.less b/lib/web/css/source/lib/_responsive.less
index 42388a0be5b45753d628afbe2cd916ea13d99a99..105a06e6b5018a5886bc496c713bd3c484a00fc2 100644
--- a/lib/web/css/source/lib/_responsive.less
+++ b/lib/web/css/source/lib/_responsive.less
@@ -39,6 +39,10 @@
         .media-width('max', @screen__m);
     }
 
+    @media only screen and (max-width: @screen__m) {
+        .media-width('max', (@screen__m + 1));
+    }
+
     @media all and (min-width: @screen__s) {
         .media-width('min', @screen__s);
     }
@@ -56,6 +60,11 @@
         .media-width('min', @screen__m);
     }
 
+    @media all and (min-width: (@screen__m + 1)),
+    print {
+        .media-width('min', (@screen__m + 1));
+    }
+
     @media all and (min-width: @screen__l),
     print {
         .media-width('min', @screen__l);
diff --git a/lib/web/css/source/lib/variables/_icons.less b/lib/web/css/source/lib/variables/_icons.less
index 999e9c2cf7922b5a9acb500e499ba271a116e992..ac6e0c0c9bd0c422c4c6f3fda7cb99f30b197858 100644
--- a/lib/web/css/source/lib/variables/_icons.less
+++ b/lib/web/css/source/lib/variables/_icons.less
@@ -75,10 +75,11 @@
 @icon-comment: '\e620';
 @icon-up: '\e621';
 @icon-down: '\e622';
-@icon-arrow-up-thin: '\e623';
+@icon-help: '\e623';
 @icon-arrow-right-thin: '\e624';
 @icon-arrow-left-thin: '\e625';
 @icon-arrow-down-thin: '\e626';
 @icon-account: '\e627';
 @icon-gift-registry: '\e628';
 @icon-present: '\e629';
+@icon-arrow-up-thin: '\e633';
diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot
index 9bc3197afaa63854e2a13d3f79f31488bf1fe4db..806461187aa48e9ad6e425d4308f8f93c61fe3f4 100644
Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot differ
diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg
index 85f6bf6ddeca82ba961382a061b92c7b6da011b7..37d511d157533ea09dca32f6568390647d2540e4 100644
--- a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg
+++ b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg"><defs><font id="Blank-Theme-Icons" horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64"/><missing-glyph horiz-adv-x="1024"/><glyph unicode="&#x20;" d="" horiz-adv-x="512"/><glyph unicode="&#xe600;" d="M676.571 637.696c-59.867 28.197-131.255 2.523-159.415-57.307-1.975-4.133-3.657-9.362-5.157-15.397-1.499 6.034-3.182 11.264-5.157 15.397-28.197 59.831-99.547 85.504-159.415 57.307-59.831-28.197-85.504-99.547-57.271-159.378 28.197-59.867 221.806-231.424 221.806-231.424s0 0.219 0.037 0.585c0.037-0.366 0.037-0.585 0.037-0.585s193.646 171.557 221.806 231.424c28.233 59.831 2.597 131.182-57.271 159.378z"/><glyph unicode="&#xe601;" d="M676.571 637.696c-59.831 28.197-131.218 2.523-159.451-57.307-1.938-4.133-3.657-9.362-5.157-15.397-1.463 6.034-3.182 11.264-5.157 15.397-28.16 59.831-99.547 85.504-159.378 57.307s-85.467-99.547-57.271-159.378 221.806-231.424 221.806-231.424 0 0.219 0.037 0.585c0-0.402 0-0.622 0-0.622s193.646 171.557 221.842 231.424c28.233 59.867 2.597 131.218-57.271 159.415zM690.213 479.232c-25.417-43.776-174.007-184.722-174.007-184.722l-1.573 2.999c0 0-155.465 140.398-181.211 183.991-30.61 51.822-7.753 108.946 38.949 128.439 43.52 18.176 101.888-27.319 123.502-73.143 1.499-3.182 17.627-1.463 18.798-6.107 1.134 4.645 12.727 2.926 14.226 6.107 21.577 45.824 81.042 93.989 128 72.411 46.007-21.138 66.926-72.155 33.317-129.975z"/><glyph unicode="&#xe602;" d="M512 704.11l-296.85-512.256h593.701l-296.85 512.256zM544.219 254.135h-62.757v49.92h62.757v-49.92zM528.713 343.369h-31.269l-20.809 140.654-1.207 72.704h72.521v-72.704l-19.237-140.654z"/><glyph unicode="&#xe603;" d="M628.846 588.544c-34.085 28.343-75.63 42.24-116.773 42.24-47.47 0-94.757-18.578-130.085-54.382l-32.073 29.586-0.585-102.693 110.994-0.658-39.424 41.253c25.198 24.027 58.002 36.315 91.136 36.352 29.842-0.037 59.721-9.947 84.517-30.574 31.488-26.222 47.689-63.744 47.726-101.815 0-5.449-0.366-10.971-1.024-16.457l51.383 9.874c0.073 2.231 0.146 4.425 0.146 6.619 0.037 52.37-22.491 104.521-65.938 140.654zM603.794 352.768c-25.307-24.466-58.405-37.010-91.867-37.047-29.879 0.037-59.721 9.984-84.517 30.574-31.488 26.222-47.689 63.744-47.726 101.778 0 6.327 0.475 12.617 1.353 18.871l-51.602-9.691c-0.146-3.072-0.256-6.107-0.256-9.179-0.037-52.334 22.491-104.521 65.975-140.617 34.048-28.343 75.593-42.24 116.736-42.24h0.11c47.799 0 95.378 18.907 130.743 55.223l33.938-33.829 0.219 106.094-112.055 0.293 38.949-40.229z"/><glyph unicode="&#xe604;" d="M696.942 624.933l-19.273 6.107h-74.496v38.583l-12.544 21.029-22.711 13.495h-111.141l-23.333-13.495-12.581-21.029v-38.619h-73.765l-18.761-6.656-17.189-14.153v-88.869h19.017v-0.073h17.554v-329.435h36.571v0.293h255.415v-0.293h36.571v329.435h18.286v0.073h18.286v86.601l-15.909 17.006zM457.435 667.575h109.129v-36.571h-109.129v36.571zM639.707 228.718h-255.415v292.571h255.415v-292.571zM676.279 557.934h-328.558v36.498h328.558v-36.498zM457.435 483.511h-36.571v-218.587h36.571v218.587zM530.578 483.511h-36.571v-218.587h36.571v218.587zM603.721 483.511h-36.571v-218.587h36.571v218.587z"/><glyph unicode="&#xe605;" d="M804.645 515.401c-1.499 4.681-5.888 7.899-10.789 7.899h-206.958l-64.073 196.754c-1.536 4.645-5.888 7.826-10.825 7.826-4.901 0-9.289-3.182-10.825-7.863l-64.439-196.754h-206.592c-4.901 0-9.289-3.218-10.825-7.863-1.499-4.681 0.146-9.874 4.096-12.763l167.205-121.783-64.439-197.851c-1.536-4.681 0.146-9.838 4.133-12.727 3.95-2.889 9.399-2.889 13.349 0l168.338 122.185 167.936-122.149c2.011-1.463 4.315-2.231 6.693-2.231s4.681 0.768 6.693 2.231c4.023 2.889 5.669 8.009 4.133 12.727l-64.439 197.851 167.57 121.783c3.95 2.889 5.632 8.046 4.059 12.727z"/><glyph unicode="&#xe606;" d="M807.241 415.854v67.145l-9.509 3.145-71.936 23.442-19.2 46.373 36.937 78.080-47.506 47.506-8.923-4.498-67.438-34.304-46.373 19.2-29.111 81.298h-67.182l-26.624-81.445-46.336-19.163-78.043 36.901-47.506-47.506 4.498-8.96 34.267-67.438-19.2-46.336-81.298-29.074v-67.218l9.472-3.072 71.973-23.515 19.163-46.373-36.901-78.080 47.506-47.506 8.887 4.498 67.474 34.304 46.373-19.2 29.111-81.298h67.182l3.072 9.509 23.515 71.936 46.373 19.2 78.080-36.937 47.506 47.506-4.498 8.923-34.304 67.438 19.2 46.373 81.298 29.147zM512 353.938c-51.968 0-94.062 42.13-94.062 94.062 0 52.005 42.094 94.062 94.062 94.062 51.931 0 94.098-42.057 94.098-94.062-0.037-51.931-42.167-94.062-94.098-94.062z"/><glyph unicode="&#xe607;" d="M339.602 539.941l172.398-183.881 172.398 183.881z"/><glyph unicode="&#xe608;" d="M606.939 449.938l-158.391 162.853-27.794-26.075 132.827-136.558-136.521-140.361 27.173-26.587 153.198 157.55-0.146 0.146z"/><glyph unicode="&#xe609;" d="M127.634 740.571v-73.143h768.731v73.143h-768.731zM127.634 411.429h768.731v73.143h-768.731v-73.143zM127.634 155.429h768.731v73.143h-768.731v-73.143z"/><glyph unicode="&#xe60a;" d="M512 742.217c-102.437 0-185.417-83.054-185.417-185.454 0-102.437 185.417-403.017 185.417-403.017s185.454 300.581 185.454 403.017c-0.037 102.437-83.017 185.454-185.454 185.454zM512 500.443c-31.122 0-56.357 25.198-56.357 56.357 0 31.086 25.234 56.357 56.357 56.357 31.159 0 56.393-25.271 56.393-56.357-0.037-31.159-25.271-56.357-56.393-56.357z"/><glyph unicode="&#xe60b;" d="M219.429 485.595h255.927v254.793h-255.927v-254.793zM548.571 740.389v-109.349h256v109.349h-256zM219.429 156.453h255.927v254.793h-255.927v-254.793zM548.571 484.754h256v109.349h-256v-109.349zM548.571 301.897h256v109.349h-256v-109.349zM548.571 155.611h256v109.349h-256v-109.349z"/><glyph unicode="&#xe60c;" d="M579.511 677.010c-30.793 0-57.381-25.161-57.381-55.954 0-28.635 18.907-47.579 47.579-47.579 31.415 0 58.002 23.771 58.002 55.991 0 28.709-20.224 47.543-48.201 47.543zM593.518 336.494c-9.801 0-48.311-59.502-69.266-59.502-5.595 0-8.375 4.937-8.375 9.801 0 11.227 7.68 28.709 11.849 39.205l50.322 136.375c25.198 67.84-6.985 86.016-37.047 86.016-40.558 0-76.946-20.297-104.887-46.848-9.106-9.070-39.863-38.437-39.863-51.054 0-4.133 4.169-9.070 9.106-9.070 12.544 0 46.153 60.855 72.009 60.855 5.595 0 11.886-6.29 6.985-18.871l-48.896-123.173c-4.937-11.849-28.709-69.23-28.709-102.802 0-26.587 17.518-38.437 42.679-38.437 70.656 0 152.43 86.711 152.43 107.008 0 6.29-4.864 10.496-8.338 10.496z"/><glyph unicode="&#xe60d;" d="M219.063 593.92h147.017v147.017h-147.017v-147.017zM438.491 593.92h147.017v147.017h-147.017v-147.017zM657.92 740.937v-147.017h147.017v147.017h-147.017zM219.063 374.491h147.017v147.017h-147.017v-147.017zM438.491 374.491h147.017v147.017h-147.017v-147.017zM657.92 374.491h147.017v147.017h-147.017v-147.017zM219.063 155.063h147.017v147.017h-147.017v-147.017zM438.491 155.063h147.017v147.017h-147.017v-147.017zM657.92 155.063h147.017v147.017h-147.017v-147.017z"/><glyph unicode="&#xe60e;" d="M711.607 401.591l-5.486-5.522c21.065 27.794 32.878 60.197 32.219 94.72-1.975 99.218-106.679 177.627-233.874 175.141-127.232-2.487-228.791-84.992-226.816-184.21 1.938-99.182 106.679-177.554 233.911-175.067 28.635 0.585 50.432-5.815 75.63 2.121l159.232-78.702c-0.037-0.037-71.058 124.965-34.816 171.52z"/><glyph unicode="&#xe60f;" d="M236.946 466.286h550.107v-36.571h-550.107v36.571z"/><glyph unicode="&#xe610;" d="M749.129 663.698c-152.101-93.257-262.473-210.907-312.064-269.934l-121.417 95.159-53.65-43.264 209.847-213.394c36.096 92.489 150.491 273.298 290.158 401.737l-12.873 29.696z"/><glyph unicode="&#xe611;" d="M434.871 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.182 0 63.707 28.489 63.707 63.671 0 35.218-28.526 63.744-63.707 63.744zM654.848 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.145 0 63.707 28.489 63.707 63.671 0 35.218-28.562 63.744-63.707 63.744zM784.274 616.741c-163.511 0-427.227 0-427.227 0s-25.929 70.071-49.957 113.371c-24.027 43.227-57.893 32.037-57.893 32.037-26.843 0-39.314-16.055-39.314-42.971 0-26.843 16.457-48.64 43.337-48.64l16.603-14.848 121.929-330.533 356.425-0.256c0 0 65.17 261.705 61.806 251.355 11.959 36.974-3.255 40.485-25.71 40.485zM392.485 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM464.933 379.392c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM502.199 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM574.647 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.177 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM611.913 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902zM684.361 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.141 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM721.627 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902z"/><glyph unicode="&#xe612;" d="M642.487 578.304c11.959 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.691 21.65-21.65 21.65-11.922 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.728-21.65 21.65-21.65zM381.842 578.304c11.922 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.728 21.65-21.65 21.65-11.959 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.691-21.65 21.65-21.65zM671.269 636.562v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.483-43.447-23.991 0-43.447 19.456-43.447 43.447 0 12.946 5.705 24.576 14.702 32.549v0.402h-203.154v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.447-43.447-24.027 0-43.447 19.456-43.447 43.447 0 12.946 5.669 24.576 14.665 32.549v0.402h-96.841v-440.101h511.561v440.101h-96.512zM732.087 234.569h-437.76v291.694h437.76v-291.694zM619.301 407.113h-55.15v-55.113h55.15v55.113zM619.301 490.021h-55.15v-55.113h55.15v55.113zM619.301 326.51h-55.15v-55.15h55.15v55.15zM696.942 490.021h-55.15v-55.113h55.15v55.113zM696.942 407.113h-55.15v-55.113h55.15v55.113zM386.267 326.51h-55.113v-55.15h55.113v55.15zM463.982 326.51h-55.15v-55.15h55.15v55.15zM463.982 407.113h-55.15v-55.113h55.15v55.113zM386.267 407.113h-55.113v-55.113h55.113v55.113zM541.586 407.113h-55.113v-55.113h55.113v55.113zM541.586 490.021h-55.113v-55.113h55.113v55.113zM463.982 490.021h-55.15v-55.113h55.15v55.113zM541.586 326.51h-55.113v-55.15h55.113v55.15z"/><glyph unicode="&#xe613;" d="M512 677.742l-209.006-253.257h136.338v-206.19h145.298v206.19h136.375z"/><glyph unicode="&#xe614;" d="M584.631 471.515v206.226h-145.298v-206.226h-136.338l209.006-253.221 209.006 253.221z"/><glyph unicode="&#xe615;" d="M836.462 183.918c0 0-109.641 112.677-153.381 156.233-19.054 19.017-32.073 31.927-32.073 31.927 14.848 21.211 26.405 44.361 34.633 69.339s12.361 51.237 12.361 78.848c0 35.621-6.802 69.083-20.334 100.462-13.568 31.305-32 58.697-55.406 82.030-23.369 23.442-50.725 41.874-82.066 55.406-31.305 13.605-64.768 20.37-100.389 20.37-35.584 0-69.047-6.802-100.425-20.37-31.305-13.531-58.551-31.963-81.664-55.406-23.077-23.296-41.435-50.688-54.967-81.993-13.568-31.378-20.334-64.841-20.334-100.462s6.802-69.083 20.334-100.389c13.531-31.305 31.89-58.661 54.967-82.103 23.113-23.333 50.322-41.801 81.664-55.369 31.378-13.568 64.841-20.297 100.425-20.297 27.648 0 53.943 4.023 78.885 12.288s48.091 19.858 69.303 34.706c0 0 11.922-11.959 29.696-29.806 48.421-48.603 155.026-159.159 155.026-159.159 16.018-6.985 41.728 0.439 54.455 11.337s19.858 33.682 9.289 52.407zM612.718 447.013c-9.838-22.747-23.223-42.569-40.155-59.429-16.933-16.933-36.718-30.354-59.429-40.192-22.638-9.874-46.848-14.775-72.521-14.775-26.258 0-50.688 4.937-73.362 14.775s-42.496 23.259-59.429 40.192c-16.896 16.859-30.354 36.681-40.155 59.429-9.838 22.601-14.738 47.104-14.738 73.289 0 25.673 4.901 50.030 14.738 72.997 9.838 22.93 23.259 42.898 40.155 59.794 16.933 16.969 36.754 30.354 59.429 40.155 22.674 9.911 47.104 14.738 73.362 14.738 25.673 0 49.883-4.864 72.521-14.738 22.674-9.801 42.496-23.186 59.429-40.155 16.933-16.933 30.318-36.901 40.155-59.831 9.874-22.967 14.738-47.323 14.738-72.997 0-26.149-4.901-50.651-14.738-73.253z"/><glyph unicode="&#xe616;" d="M695.845 602.661l-29.147 29.111-154.697-154.734-154.734 154.734-29.111-29.111 154.734-154.734-154.624-154.624 29.111-29.074 154.624 154.587 154.661-154.587 29.038 29.074-154.587 154.624z"/><glyph unicode="&#xe617;" d="M470.418 450.158l132.791 136.558-27.794 26.075-158.354-162.853 9.618-9.033-0.11-0.146 153.234-157.55 27.136 26.587z"/><glyph unicode="&#xe618;" d="M512 539.941l-172.398-183.881h344.795z"/><glyph unicode="&#xe619;" d="M392.119 622.043v-348.087l239.726 174.043z"/><glyph unicode="&#xe61a;" d="M392.119 448l239.726-174.043v348.087z"/><glyph unicode="&#xe61b;" d="M237.714 191.159h73.728v513.682h-73.728v-513.682zM786.286 703.086h-440.283v-292.169h440.283l-148.078 144.128 148.078 148.041z"/><glyph unicode="&#xe61c;" d="M787.054 466.359h-256.219v256.695h-36.571v-256.695h-257.317v-36.571h257.317v-256.841h36.571v256.841h256.219z"/><glyph unicode="&#xe61d;" d="M769.134 594.286v36.571h-513.17v-25.271l-1.097-1.097 1.097-1.097v-9.106h0.622v-292.571h-0.622v-8.558l-1.097-1.097 1.097-1.097v-25.819h513.17v36.571h-0.585v292.571h0.585zM703.89 301.714h-387.657l119.881 119.881-25.856 25.856-117.138-117.138v236.361l220.014-217.088 25.856 25.856-1.39 1.353 194.377 194.341v-245.87l-122.149 122.149-25.856-25.856 119.918-119.845zM317.221 594.286h386.158l-191.781-191.781-194.377 191.781z"/><glyph unicode="&#xe61e;" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM604.050 355.584v-145.225h109.202v145.225h-109.202zM457.399 210.359h109.202v475.319h-109.202v-475.319z"/><glyph unicode="&#xe61f;" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM347.941 503.625h36.864v-256.768h-36.864v256.768zM604.050 355.584v-145.225h109.202v145.225h-109.202zM677.339 246.711h-36.827v71.863h36.827v-71.863zM457.399 210.359h109.202v475.319h-109.202v-475.319zM494.263 649.838h36.827v-402.834h-36.827v402.834z"/><glyph unicode="&#xe620;" d="M519.57 665.893c-127.232 2.487-231.936-75.922-233.911-175.141-0.695-34.487 11.154-66.926 32.219-94.72l-5.486 5.522c36.242-46.519-34.816-171.52-34.816-171.52l159.232 78.702c25.161-7.936 46.994-1.536 75.63-2.121 127.232-2.487 231.973 75.886 233.911 175.067 2.011 99.255-99.511 181.723-226.779 184.21z"/><glyph unicode="&#xe621;" d="M514.158 489.582l136.558-132.791 26.075 27.794-162.853 158.354-166.729-162.743 26.587-27.136z"/><glyph unicode="&#xe622;" d="M509.842 406.418l-136.558 132.791-26.075-27.794 162.853-158.354 166.729 162.743-26.587 27.136z"/><glyph unicode="&#xe623;" d="M938.824 426.028l-0.504 106.238-426.32 426.322-426.322-426.322-0.504-106.238 389.444 389.442v-880.006h74.764v880.006z"/><glyph unicode="&#xe624;" d="M1.994 518.75h748.928l-283.278 291.206h200.254l354.108-363.956-354.108-363.956h-200.254l283.278 291.174h-748.928v145.532z"/><glyph unicode="&#xe625;" d="M1022.006 375.25h-748.928l283.278-291.206h-200.254l-354.108 363.956 354.108 363.956h200.254l-283.278-291.174h748.928v-145.532z"/><glyph unicode="&#xe626;" d="M85.174 468.026l0.504-106.238 426.322-426.324 426.32 426.324 0.504 106.238-389.444-389.444 0.002 880.006h-74.764v-880.004z"/><glyph unicode="&#xe627;" d="M511.963 831.086c-211.529 0-383.049-171.52-383.049-383.086s171.483-383.086 383.049-383.086c211.602 0 383.086 171.483 383.086 383.086s-171.483 383.086-383.086 383.086zM511.963 794.514c191.086 0 346.514-155.429 346.514-346.514 0-79.909-27.429-153.344-73.070-212.041-5.486 1.975-11.008 3.84-16.274 6.107-34.926 14.629-73.801 31.781-108.654 46.153-9.911 2.706-19.931 5.413-29.842 8.155-11.849 8.155-23.589 35.365-29.915 48.933-6.29 0.914-12.654 1.792-19.017 2.633 0.914 20.992 13.934 22.126 19.017 38.071 4.498 14.080 0.512 32.439 7.57 45.495 4.937 9.070 16.128 9.070 21.65 16.933 5.083 6.985 8.411 19.273 9.984 27.941 2.853 15.799 5.339 37.339-2.158 53.029-4.279 8.96-6.985 9.874-8.229 20.736-1.426 13.275 3.913 56.43 4.133 65.755 0.512 24.21-0.073 26.149-5.925 49.737 0 0-7.058 21.358-18.213 27.831l-22.272 3.803-13.714 12.727c-55.369 34.085-114.761 10.167-146.505-2.67-45.824-14.885-74.789-59.758-54.565-155.538 3.474-16.421-8.96-23.698-8.155-32.658 1.829-19.566 2.158-66.487 20.59-78.080 1.719-1.061 14.811-4.352 14.738-3.438 1.792-19.017 3.621-38.071 5.376-57.015 4.608-12.654 15.689-14.080 18.907-31.927l-14.153-3.438c-6.363-13.568-17.993-40.777-29.879-48.933-9.947-2.706-19.931-5.413-29.879-8.155-34.889-14.373-73.691-31.488-108.654-46.153-1.902-0.768-3.877-1.39-5.815-2.158-43.776 58.112-70.071 130.011-70.071 208.165 0 191.086 155.429 346.514 346.478 346.514z"/><glyph unicode="&#xe628;" d="M427.703 653.019c0-10.569-8.558-19.090-19.090-19.090h-11.154c-10.533 0-19.090 8.521-19.090 19.090v68.462c0 10.533 8.594 19.090 19.090 19.090h11.154c10.533 0 19.090-8.558 19.090-19.090v-68.462zM645.778 653.019c0-10.569-8.521-19.090-19.054-19.090h-11.154c-10.533 0-19.054 8.521-19.054 19.090v68.462c-0.037 10.533 8.485 19.090 19.054 19.090h11.154c10.533 0 19.054-8.558 19.054-19.090v-68.462zM675.182 481.317l-38.729 31.598-152.795-187.282-81.518 64.805-28.891-36.242 120.21-95.634zM758.784 687.982h-71.351v-29.769c0-31.634-25.746-57.344-57.271-57.344h-11.227c-31.598 0-57.271 25.71-57.271 57.344v29.769h-97.682v-29.769c0-31.634-25.71-57.344-57.307-57.344h-11.154c-31.598 0-57.307 25.71-57.307 57.344v29.769h-72.96c-10.533 0-19.090-8.521-19.090-19.054v-494.373c-0.037-10.569 8.558-19.127 19.090-19.127h493.531c10.533 0 19.054 8.558 19.054 19.090v494.409c0 10.533-8.521 19.054-19.054 19.054zM720.567 240.677c0-10.569-8.558-19.090-19.090-19.090h-378.917c-10.569 0-19.090 8.521-19.090 19.090v288.11c0 10.569 8.521 19.054 19.090 19.054h378.88c10.533 0 19.090-8.485 19.090-19.054v-288.11z"/><glyph unicode="&#xe629;" d="M391.863 554.203h-128.219c-10.35 0-18.761-8.375-18.761-18.725v-91.429c0-10.35 8.375-18.725 18.761-18.725h128.219c10.35 0 18.761 8.375 18.761 18.725v91.429c0 10.386-8.375 18.725-18.761 18.725zM391.863 387.511h-90.734c-10.35 0-18.761-8.375-18.761-18.725v-194.633c0-10.35 8.411-18.725 18.761-18.725h90.734c10.35 0 18.761 8.375 18.761 18.725v194.633c0 10.35-8.375 18.725-18.761 18.725zM760.357 554.203h-279.845c-10.35 0-18.725-8.375-18.725-18.725v-91.429c0-10.35 8.375-18.725 18.725-18.725h279.845c10.313 0 18.725 8.375 18.725 18.725v91.429c-0.037 10.386-8.411 18.725-18.725 18.725zM721.701 385.573h-240.64c-10.313 0-18.725-8.375-18.725-18.761v-192.695c0-10.35 8.375-18.725 18.725-18.725h240.64c10.35 0 18.725 8.375 18.725 18.725v192.695c0 10.35-8.375 18.761-18.725 18.761zM507.355 575.634c21.87-3.986 42.971-6.327 62.647-6.327 99.072 0 152.832 53.248 153.088 103.387 0.183 32.293-23.698 67.291-78.117 67.84-72.923 0-118.089-51.493-141.605-89.71-23.918 38.107-69.266 88.576-142.373 88.576-52.882-0.549-76.763-35.547-76.581-67.84 0.256-50.139 54.016-103.424 153.088-103.424 0.037 0 0.037 0 0.037 0 21.394 0 44.398 2.414 68.425 7.241l1.39 0.256zM645.998 693.723c9.143-0.073 30.354-2.304 30.245-20.773-0.11-23.589-33.17-56.795-106.24-56.795-10.057 0-20.553 0.658-31.525 1.938 16.567 29.294 51.566 75.63 107.52 75.63zM437.504 614.985v0c-73.106 0-106.167 33.207-106.277 56.795-0.11 18.469 21.102 20.699 31.305 20.809 55.259 0 90.039-46.373 106.496-75.666-10.935-1.28-21.467-1.938-31.525-1.938z"/></font></defs></svg>
+<svg xmlns="http://www.w3.org/2000/svg"><defs><font horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64" /><missing-glyph horiz-adv-x="1024" /><glyph unicode="&#x20;" d="" horiz-adv-x="512" /><glyph unicode="&#xe600;" d="M676.571 637.696c-59.867 28.197-131.255 2.523-159.415-57.307-1.975-4.133-3.657-9.362-5.157-15.397-1.499 6.034-3.182 11.264-5.157 15.397-28.197 59.831-99.547 85.504-159.415 57.307-59.831-28.197-85.504-99.547-57.271-159.378 28.197-59.867 221.806-231.424 221.806-231.424s0 0.219 0.037 0.585c0.037-0.366 0.037-0.585 0.037-0.585s193.646 171.557 221.806 231.424c28.233 59.831 2.597 131.182-57.271 159.378z" /><glyph unicode="&#xe601;" d="M676.571 637.696c-59.831 28.197-131.218 2.523-159.451-57.307-1.938-4.133-3.657-9.362-5.157-15.397-1.463 6.034-3.182 11.264-5.157 15.397-28.16 59.831-99.547 85.504-159.378 57.307s-85.467-99.547-57.271-159.378 221.806-231.424 221.806-231.424 0 0.219 0.037 0.585c0-0.402 0-0.622 0-0.622s193.646 171.557 221.842 231.424c28.233 59.867 2.597 131.218-57.271 159.415zM690.213 479.232c-25.417-43.776-174.007-184.722-174.007-184.722l-1.573 2.999c0 0-155.465 140.398-181.211 183.991-30.61 51.822-7.753 108.946 38.949 128.439 43.52 18.176 101.888-27.319 123.502-73.143 1.499-3.182 17.627-1.463 18.798-6.107 1.134 4.645 12.727 2.926 14.226 6.107 21.577 45.824 81.042 93.989 128 72.411 46.007-21.138 66.926-72.155 33.317-129.975z" /><glyph unicode="&#xe602;" d="M512 704.11l-296.85-512.256h593.701l-296.85 512.256zM544.219 254.135h-62.757v49.92h62.757v-49.92zM528.713 343.369h-31.269l-20.809 140.654-1.207 72.704h72.521v-72.704l-19.237-140.654z" /><glyph unicode="&#xe603;" d="M628.846 588.544c-34.085 28.343-75.63 42.24-116.773 42.24-47.47 0-94.757-18.578-130.085-54.382l-32.073 29.586-0.585-102.693 110.994-0.658-39.424 41.253c25.198 24.027 58.002 36.315 91.136 36.352 29.842-0.037 59.721-9.947 84.517-30.574 31.488-26.222 47.689-63.744 47.726-101.815 0-5.449-0.366-10.971-1.024-16.457l51.383 9.874c0.073 2.231 0.146 4.425 0.146 6.619 0.037 52.37-22.491 104.521-65.938 140.654zM603.794 352.768c-25.307-24.466-58.405-37.010-91.867-37.047-29.879 0.037-59.721 9.984-84.517 30.574-31.488 26.222-47.689 63.744-47.726 101.778 0 6.327 0.475 12.617 1.353 18.871l-51.602-9.691c-0.146-3.072-0.256-6.107-0.256-9.179-0.037-52.334 22.491-104.521 65.975-140.617 34.048-28.343 75.593-42.24 116.736-42.24h0.11c47.799 0 95.378 18.907 130.743 55.223l33.938-33.829 0.219 106.094-112.055 0.293 38.949-40.229z" /><glyph unicode="&#xe604;" d="M696.942 624.933l-19.273 6.107h-74.496v38.583l-12.544 21.029-22.711 13.495h-111.141l-23.333-13.495-12.581-21.029v-38.619h-73.765l-18.761-6.656-17.189-14.153v-88.869h19.017v-0.073h17.554v-329.435h36.571v0.293h255.415v-0.293h36.571v329.435h18.286v0.073h18.286v86.601l-15.909 17.006zM457.435 667.575h109.129v-36.571h-109.129v36.571zM639.707 228.718h-255.415v292.571h255.415v-292.571zM676.279 557.934h-328.558v36.498h328.558v-36.498zM457.435 483.511h-36.571v-218.587h36.571v218.587zM530.578 483.511h-36.571v-218.587h36.571v218.587zM603.721 483.511h-36.571v-218.587h36.571v218.587z" /><glyph unicode="&#xe605;" d="M804.645 515.401c-1.499 4.681-5.888 7.899-10.789 7.899h-206.958l-64.073 196.754c-1.536 4.645-5.888 7.826-10.825 7.826-4.901 0-9.289-3.182-10.825-7.863l-64.439-196.754h-206.592c-4.901 0-9.289-3.218-10.825-7.863-1.499-4.681 0.146-9.874 4.096-12.763l167.205-121.783-64.439-197.851c-1.536-4.681 0.146-9.838 4.133-12.727 3.95-2.889 9.399-2.889 13.349 0l168.338 122.185 167.936-122.149c2.011-1.463 4.315-2.231 6.693-2.231s4.681 0.768 6.693 2.231c4.023 2.889 5.669 8.009 4.133 12.727l-64.439 197.851 167.57 121.783c3.95 2.889 5.632 8.046 4.059 12.727z" /><glyph unicode="&#xe606;" d="M807.241 415.854v67.145l-9.509 3.145-71.936 23.442-19.2 46.373 36.937 78.080-47.506 47.506-8.923-4.498-67.438-34.304-46.373 19.2-29.111 81.298h-67.182l-26.624-81.445-46.336-19.163-78.043 36.901-47.506-47.506 4.498-8.96 34.267-67.438-19.2-46.336-81.298-29.074v-67.218l9.472-3.072 71.973-23.515 19.163-46.373-36.901-78.080 47.506-47.506 8.887 4.498 67.474 34.304 46.373-19.2 29.111-81.298h67.182l3.072 9.509 23.515 71.936 46.373 19.2 78.080-36.937 47.506 47.506-4.498 8.923-34.304 67.438 19.2 46.373 81.298 29.147zM512 353.938c-51.968 0-94.062 42.13-94.062 94.062 0 52.005 42.094 94.062 94.062 94.062 51.931 0 94.098-42.057 94.098-94.062-0.037-51.931-42.167-94.062-94.098-94.062z" /><glyph unicode="&#xe607;" d="M339.602 539.941l172.398-183.881 172.398 183.881z" /><glyph unicode="&#xe608;" d="M606.939 449.938l-158.391 162.853-27.794-26.075 132.827-136.558-136.521-140.361 27.173-26.587 153.198 157.55-0.146 0.146z" /><glyph unicode="&#xe609;" d="M127.634 740.571v-73.143h768.731v73.143h-768.731zM127.634 411.429h768.731v73.143h-768.731v-73.143zM127.634 155.429h768.731v73.143h-768.731v-73.143z" /><glyph unicode="&#xe60a;" d="M512 742.217c-102.437 0-185.417-83.054-185.417-185.454 0-102.437 185.417-403.017 185.417-403.017s185.454 300.581 185.454 403.017c-0.037 102.437-83.017 185.454-185.454 185.454zM512 500.443c-31.122 0-56.357 25.198-56.357 56.357 0 31.086 25.234 56.357 56.357 56.357 31.159 0 56.393-25.271 56.393-56.357-0.037-31.159-25.271-56.357-56.393-56.357z" /><glyph unicode="&#xe60b;" d="M219.429 485.595h255.927v254.793h-255.927v-254.793zM548.571 740.389v-109.349h256v109.349h-256zM219.429 156.453h255.927v254.793h-255.927v-254.793zM548.571 484.754h256v109.349h-256v-109.349zM548.571 301.897h256v109.349h-256v-109.349zM548.571 155.611h256v109.349h-256v-109.349z" /><glyph unicode="&#xe60c;" d="M579.511 677.010c-30.793 0-57.381-25.161-57.381-55.954 0-28.635 18.907-47.579 47.579-47.579 31.415 0 58.002 23.771 58.002 55.991 0 28.709-20.224 47.543-48.201 47.543zM593.518 336.494c-9.801 0-48.311-59.502-69.266-59.502-5.595 0-8.375 4.937-8.375 9.801 0 11.227 7.68 28.709 11.849 39.205l50.322 136.375c25.198 67.84-6.985 86.016-37.047 86.016-40.558 0-76.946-20.297-104.887-46.848-9.106-9.070-39.863-38.437-39.863-51.054 0-4.133 4.169-9.070 9.106-9.070 12.544 0 46.153 60.855 72.009 60.855 5.595 0 11.886-6.29 6.985-18.871l-48.896-123.173c-4.937-11.849-28.709-69.23-28.709-102.802 0-26.587 17.518-38.437 42.679-38.437 70.656 0 152.43 86.711 152.43 107.008 0 6.29-4.864 10.496-8.338 10.496z" /><glyph unicode="&#xe60d;" d="M219.063 593.92h147.017v147.017h-147.017v-147.017zM438.491 593.92h147.017v147.017h-147.017v-147.017zM657.92 740.937v-147.017h147.017v147.017h-147.017zM219.063 374.491h147.017v147.017h-147.017v-147.017zM438.491 374.491h147.017v147.017h-147.017v-147.017zM657.92 374.491h147.017v147.017h-147.017v-147.017zM219.063 155.063h147.017v147.017h-147.017v-147.017zM438.491 155.063h147.017v147.017h-147.017v-147.017zM657.92 155.063h147.017v147.017h-147.017v-147.017z" /><glyph unicode="&#xe60e;" d="M711.607 401.591l-5.486-5.522c21.065 27.794 32.878 60.197 32.219 94.72-1.975 99.218-106.679 177.627-233.874 175.141-127.232-2.487-228.791-84.992-226.816-184.21 1.938-99.182 106.679-177.554 233.911-175.067 28.635 0.585 50.432-5.815 75.63 2.121l159.232-78.702c-0.037-0.037-71.058 124.965-34.816 171.52z" /><glyph unicode="&#xe60f;" d="M236.946 466.286h550.107v-36.571h-550.107v36.571z" /><glyph unicode="&#xe610;" d="M749.129 663.698c-152.101-93.257-262.473-210.907-312.064-269.934l-121.417 95.159-53.65-43.264 209.847-213.394c36.096 92.489 150.491 273.298 290.158 401.737l-12.873 29.696z" /><glyph unicode="&#xe611;" d="M434.871 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.182 0 63.707 28.489 63.707 63.671 0 35.218-28.526 63.744-63.707 63.744zM654.848 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.145 0 63.707 28.489 63.707 63.671 0 35.218-28.562 63.744-63.707 63.744zM784.274 616.741c-163.511 0-427.227 0-427.227 0s-25.929 70.071-49.957 113.371c-24.027 43.227-57.893 32.037-57.893 32.037-26.843 0-39.314-16.055-39.314-42.971 0-26.843 16.457-48.64 43.337-48.64l16.603-14.848 121.929-330.533 356.425-0.256c0 0 65.17 261.705 61.806 251.355 11.959 36.974-3.255 40.485-25.71 40.485zM392.485 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM464.933 379.392c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM502.199 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM574.647 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.177 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM611.913 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902zM684.361 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.141 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM721.627 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902z" /><glyph unicode="&#xe612;" d="M642.487 578.304c11.959 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.691 21.65-21.65 21.65-11.922 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.728-21.65 21.65-21.65zM381.842 578.304c11.922 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.728 21.65-21.65 21.65-11.959 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.691-21.65 21.65-21.65zM671.269 636.562v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.483-43.447-23.991 0-43.447 19.456-43.447 43.447 0 12.946 5.705 24.576 14.702 32.549v0.402h-203.154v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.447-43.447-24.027 0-43.447 19.456-43.447 43.447 0 12.946 5.669 24.576 14.665 32.549v0.402h-96.841v-440.101h511.561v440.101h-96.512zM732.087 234.569h-437.76v291.694h437.76v-291.694zM619.301 407.113h-55.15v-55.113h55.15v55.113zM619.301 490.021h-55.15v-55.113h55.15v55.113zM619.301 326.51h-55.15v-55.15h55.15v55.15zM696.942 490.021h-55.15v-55.113h55.15v55.113zM696.942 407.113h-55.15v-55.113h55.15v55.113zM386.267 326.51h-55.113v-55.15h55.113v55.15zM463.982 326.51h-55.15v-55.15h55.15v55.15zM463.982 407.113h-55.15v-55.113h55.15v55.113zM386.267 407.113h-55.113v-55.113h55.113v55.113zM541.586 407.113h-55.113v-55.113h55.113v55.113zM541.586 490.021h-55.113v-55.113h55.113v55.113zM463.982 490.021h-55.15v-55.113h55.15v55.113zM541.586 326.51h-55.113v-55.15h55.113v55.15z" /><glyph unicode="&#xe613;" d="M512 677.742l-209.006-253.257h136.338v-206.19h145.298v206.19h136.375z" /><glyph unicode="&#xe614;" d="M584.631 471.515v206.226h-145.298v-206.226h-136.338l209.006-253.221 209.006 253.221z" /><glyph unicode="&#xe615;" d="M836.462 183.918c0 0-109.641 112.677-153.381 156.233-19.054 19.017-32.073 31.927-32.073 31.927 14.848 21.211 26.405 44.361 34.633 69.339s12.361 51.237 12.361 78.848c0 35.621-6.802 69.083-20.334 100.462-13.568 31.305-32 58.697-55.406 82.030-23.369 23.442-50.725 41.874-82.066 55.406-31.305 13.605-64.768 20.37-100.389 20.37-35.584 0-69.047-6.802-100.425-20.37-31.305-13.531-58.551-31.963-81.664-55.406-23.077-23.296-41.435-50.688-54.967-81.993-13.568-31.378-20.334-64.841-20.334-100.462s6.802-69.083 20.334-100.389c13.531-31.305 31.89-58.661 54.967-82.103 23.113-23.333 50.322-41.801 81.664-55.369 31.378-13.568 64.841-20.297 100.425-20.297 27.648 0 53.943 4.023 78.885 12.288s48.091 19.858 69.303 34.706c0 0 11.922-11.959 29.696-29.806 48.421-48.603 155.026-159.159 155.026-159.159 16.018-6.985 41.728 0.439 54.455 11.337s19.858 33.682 9.289 52.407zM612.718 447.013c-9.838-22.747-23.223-42.569-40.155-59.429-16.933-16.933-36.718-30.354-59.429-40.192-22.638-9.874-46.848-14.775-72.521-14.775-26.258 0-50.688 4.937-73.362 14.775s-42.496 23.259-59.429 40.192c-16.896 16.859-30.354 36.681-40.155 59.429-9.838 22.601-14.738 47.104-14.738 73.289 0 25.673 4.901 50.030 14.738 72.997 9.838 22.93 23.259 42.898 40.155 59.794 16.933 16.969 36.754 30.354 59.429 40.155 22.674 9.911 47.104 14.738 73.362 14.738 25.673 0 49.883-4.864 72.521-14.738 22.674-9.801 42.496-23.186 59.429-40.155 16.933-16.933 30.318-36.901 40.155-59.831 9.874-22.967 14.738-47.323 14.738-72.997 0-26.149-4.901-50.651-14.738-73.253z" /><glyph unicode="&#xe616;" d="M695.845 602.661l-29.147 29.111-154.697-154.734-154.734 154.734-29.111-29.111 154.734-154.734-154.624-154.624 29.111-29.074 154.624 154.587 154.661-154.587 29.038 29.074-154.587 154.624z" /><glyph unicode="&#xe617;" d="M470.418 450.158l132.791 136.558-27.794 26.075-158.354-162.853 9.618-9.033-0.11-0.146 153.234-157.55 27.136 26.587z" /><glyph unicode="&#xe618;" d="M512 539.941l-172.398-183.881h344.795z" /><glyph unicode="&#xe619;" d="M392.119 622.043v-348.087l239.726 174.043z" /><glyph unicode="&#xe61a;" d="M392.119 448l239.726-174.043v348.087z" /><glyph unicode="&#xe61b;" d="M237.714 191.159h73.728v513.682h-73.728v-513.682zM786.286 703.086h-440.283v-292.169h440.283l-148.078 144.128 148.078 148.041z" /><glyph unicode="&#xe61c;" d="M787.054 466.359h-256.219v256.695h-36.571v-256.695h-257.317v-36.571h257.317v-256.841h36.571v256.841h256.219z" /><glyph unicode="&#xe61d;" d="M769.134 594.286v36.571h-513.17v-25.271l-1.097-1.097 1.097-1.097v-9.106h0.622v-292.571h-0.622v-8.558l-1.097-1.097 1.097-1.097v-25.819h513.17v36.571h-0.585v292.571h0.585zM703.89 301.714h-387.657l119.881 119.881-25.856 25.856-117.138-117.138v236.361l220.014-217.088 25.856 25.856-1.39 1.353 194.377 194.341v-245.87l-122.149 122.149-25.856-25.856 119.918-119.845zM317.221 594.286h386.158l-191.781-191.781-194.377 191.781z" /><glyph unicode="&#xe61e;" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM604.050 355.584v-145.225h109.202v145.225h-109.202zM457.399 210.359h109.202v475.319h-109.202v-475.319z" /><glyph unicode="&#xe61f;" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM347.941 503.625h36.864v-256.768h-36.864v256.768zM604.050 355.584v-145.225h109.202v145.225h-109.202zM677.339 246.711h-36.827v71.863h36.827v-71.863zM457.399 210.359h109.202v475.319h-109.202v-475.319zM494.263 649.838h36.827v-402.834h-36.827v402.834z" /><glyph unicode="&#xe620;" d="M519.57 665.893c-127.232 2.487-231.936-75.922-233.911-175.141-0.695-34.487 11.154-66.926 32.219-94.72l-5.486 5.522c36.242-46.519-34.816-171.52-34.816-171.52l159.232 78.702c25.161-7.936 46.994-1.536 75.63-2.121 127.232-2.487 231.973 75.886 233.911 175.067 2.011 99.255-99.511 181.723-226.779 184.21z" /><glyph unicode="&#xe621;" d="M514.158 489.582l136.558-132.791 26.075 27.794-162.853 158.354-166.729-162.743 26.587-27.136z" /><glyph unicode="&#xe622;" d="M509.842 406.418l-136.558 132.791-26.075-27.794 162.853-158.354 166.729 162.743-26.587 27.136z" /><glyph unicode="&#xe623;" d="M512 52.005c-218.77 0-396.032 177.298-396.032 395.995s177.262 395.995 396.032 395.995c218.661 0 396.032-177.298 396.032-395.995s-177.371-395.995-396.032-395.995zM512 796.087c-191.89 0-348.087-156.197-348.087-348.087 0-191.927 156.197-348.087 348.087-348.087s348.050 156.16 348.050 348.087c-0.037 191.927-156.16 348.087-348.050 348.087zM611.328 442.441l-24.101-18.761c-13.166-10.24-21.87-22.126-26.185-35.84-2.743-8.558-4.681-18.907-4.901-37.12h-92.343c1.353 38.473 5.413 61.842 11.301 76.581 5.925 14.592 21.102 31.488 45.531 50.578l24.795 19.383c8.192 6.181 14.738 12.91 19.785 20.187 8.997 12.471 13.495 26.222 13.495 41.216 0 17.262-5.010 32.987-15.104 47.214-10.057 14.226-28.453 21.321-55.259 21.321-26.295 0-44.946-8.777-55.918-26.295s-16.384-33.463-16.384-52.37h-98.523c2.706 64.805 25.234 108.544 67.73 135.57 26.843 17.298 59.794 25.929 98.889 25.929 51.383 0 94.025-12.288 128-36.827 34.011-24.503 53.87-74.935 53.87-123.173 0-29.55-10.24-40.338-25.051-60.599-8.558-12.288-25.125-27.941-49.627-46.994zM561.042 202.423h-98.231v98.487h98.231v-98.487z" /><glyph unicode="&#xe624;" d="M1.994 518.75h748.928l-283.278 291.206h200.254l354.108-363.956-354.108-363.956h-200.254l283.278 291.174h-748.928v145.532z" /><glyph unicode="&#xe625;" d="M1022.006 375.25h-748.928l283.278-291.206h-200.254l-354.108 363.956 354.108 363.956h200.254l-283.278-291.174h748.928v-145.532z" /><glyph unicode="&#xe626;" d="M85.174 468.026l0.504-106.238 426.322-426.324 426.32 426.324 0.504 106.238-389.444-389.444 0.002 880.006h-74.764v-880.004z" /><glyph unicode="&#xe627;" d="M511.963 831.086c-211.529 0-383.049-171.52-383.049-383.086s171.483-383.086 383.049-383.086c211.602 0 383.086 171.483 383.086 383.086s-171.483 383.086-383.086 383.086zM511.963 794.514c191.086 0 346.514-155.429 346.514-346.514 0-79.909-27.429-153.344-73.070-212.041-5.486 1.975-11.008 3.84-16.274 6.107-34.926 14.629-73.801 31.781-108.654 46.153-9.911 2.706-19.931 5.413-29.842 8.155-11.849 8.155-23.589 35.365-29.915 48.933-6.29 0.914-12.654 1.792-19.017 2.633 0.914 20.992 13.934 22.126 19.017 38.071 4.498 14.080 0.512 32.439 7.57 45.495 4.937 9.070 16.128 9.070 21.65 16.933 5.083 6.985 8.411 19.273 9.984 27.941 2.853 15.799 5.339 37.339-2.158 53.029-4.279 8.96-6.985 9.874-8.229 20.736-1.426 13.275 3.913 56.43 4.133 65.755 0.512 24.21-0.073 26.149-5.925 49.737 0 0-7.058 21.358-18.213 27.831l-22.272 3.803-13.714 12.727c-55.369 34.085-114.761 10.167-146.505-2.67-45.824-14.885-74.789-59.758-54.565-155.538 3.474-16.421-8.96-23.698-8.155-32.658 1.829-19.566 2.158-66.487 20.59-78.080 1.719-1.061 14.811-4.352 14.738-3.438 1.792-19.017 3.621-38.071 5.376-57.015 4.608-12.654 15.689-14.080 18.907-31.927l-14.153-3.438c-6.363-13.568-17.993-40.777-29.879-48.933-9.947-2.706-19.931-5.413-29.879-8.155-34.889-14.373-73.691-31.488-108.654-46.153-1.902-0.768-3.877-1.39-5.815-2.158-43.776 58.112-70.071 130.011-70.071 208.165 0 191.086 155.429 346.514 346.478 346.514z" /><glyph unicode="&#xe628;" d="M427.703 653.019c0-10.569-8.558-19.090-19.090-19.090h-11.154c-10.533 0-19.090 8.521-19.090 19.090v68.462c0 10.533 8.594 19.090 19.090 19.090h11.154c10.533 0 19.090-8.558 19.090-19.090v-68.462zM645.778 653.019c0-10.569-8.521-19.090-19.054-19.090h-11.154c-10.533 0-19.054 8.521-19.054 19.090v68.462c-0.037 10.533 8.485 19.090 19.054 19.090h11.154c10.533 0 19.054-8.558 19.054-19.090v-68.462zM675.182 481.317l-38.729 31.598-152.795-187.282-81.518 64.805-28.891-36.242 120.21-95.634zM758.784 687.982h-71.351v-29.769c0-31.634-25.746-57.344-57.271-57.344h-11.227c-31.598 0-57.271 25.71-57.271 57.344v29.769h-97.682v-29.769c0-31.634-25.71-57.344-57.307-57.344h-11.154c-31.598 0-57.307 25.71-57.307 57.344v29.769h-72.96c-10.533 0-19.090-8.521-19.090-19.054v-494.373c-0.037-10.569 8.558-19.127 19.090-19.127h493.531c10.533 0 19.054 8.558 19.054 19.090v494.409c0 10.533-8.521 19.054-19.054 19.054zM720.567 240.677c0-10.569-8.558-19.090-19.090-19.090h-378.917c-10.569 0-19.090 8.521-19.090 19.090v288.11c0 10.569 8.521 19.054 19.090 19.054h378.88c10.533 0 19.090-8.485 19.090-19.054v-288.11z" /><glyph unicode="&#xe629;" d="M391.863 554.203h-128.219c-10.35 0-18.761-8.375-18.761-18.725v-91.429c0-10.35 8.375-18.725 18.761-18.725h128.219c10.35 0 18.761 8.375 18.761 18.725v91.429c0 10.386-8.375 18.725-18.761 18.725zM391.863 387.511h-90.734c-10.35 0-18.761-8.375-18.761-18.725v-194.633c0-10.35 8.411-18.725 18.761-18.725h90.734c10.35 0 18.761 8.375 18.761 18.725v194.633c0 10.35-8.375 18.725-18.761 18.725zM760.357 554.203h-279.845c-10.35 0-18.725-8.375-18.725-18.725v-91.429c0-10.35 8.375-18.725 18.725-18.725h279.845c10.313 0 18.725 8.375 18.725 18.725v91.429c-0.037 10.386-8.411 18.725-18.725 18.725zM721.701 385.573h-240.64c-10.313 0-18.725-8.375-18.725-18.761v-192.695c0-10.35 8.375-18.725 18.725-18.725h240.64c10.35 0 18.725 8.375 18.725 18.725v192.695c0 10.35-8.375 18.761-18.725 18.761zM507.355 575.634c21.87-3.986 42.971-6.327 62.647-6.327 99.072 0 152.832 53.248 153.088 103.387 0.183 32.293-23.698 67.291-78.117 67.84-72.923 0-118.089-51.493-141.605-89.71-23.918 38.107-69.266 88.576-142.373 88.576-52.882-0.549-76.763-35.547-76.581-67.84 0.256-50.139 54.016-103.424 153.088-103.424 0.037 0 0.037 0 0.037 0 21.394 0 44.398 2.414 68.425 7.241l1.39 0.256zM645.998 693.723c9.143-0.073 30.354-2.304 30.245-20.773-0.11-23.589-33.17-56.795-106.24-56.795-10.057 0-20.553 0.658-31.525 1.938 16.567 29.294 51.566 75.63 107.52 75.63zM437.504 614.985v0c-73.106 0-106.167 33.207-106.277 56.795-0.11 18.469 21.102 20.699 31.305 20.809 55.259 0 90.039-46.373 106.496-75.666-10.935-1.28-21.467-1.938-31.525-1.938z" /><glyph unicode="&#xe633;" d="M938.824 426.028l-0.504 106.238-426.32 426.322-426.322-426.322-0.504-106.238 389.444 389.442v-880.006h74.764v880.006z" /></font></defs></svg>
\ No newline at end of file
diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf
index eaec02d1df42b6b0208db02f1da2a3fb3bcae7fd..6fabe5c3e89948ff20801ea1e43e18b15c9c4da1 100644
Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf differ
diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff
index e9e8395b2574bc6cfbb3c2606213ca204179bf51..a8e688940c486205bcbc8bb9b787af33c1a8db86 100644
Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff differ
diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2
index 1d60f2f95c0facb689b7a0079cfb2b2312bcab17..e1fc31afbdaf56fd0fc3cfb09180f52be6f1b569 100644
Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 differ
diff --git a/lib/web/fonts/Blank-Theme-Icons/selection.json b/lib/web/fonts/Blank-Theme-Icons/selection.json
index e3a71a30c6ae96426ed01b4041c20ae392e1e909..2e8beab777f8a696acbbbb6d6b4ce523f9d2f481 100644
--- a/lib/web/fonts/Blank-Theme-Icons/selection.json
+++ b/lib/web/fonts/Blank-Theme-Icons/selection.json
@@ -1,6 +1,34 @@
 {
 	"IcoMoonType": "selection",
 	"icons": [
+		{
+			"icon": {
+				"paths": [
+					"M512 907.995c-218.77 0-396.032-177.298-396.032-395.995s177.262-395.995 396.032-395.995c218.661 0 396.032 177.298 396.032 395.995s-177.371 395.995-396.032 395.995zM512 163.913c-191.89 0-348.087 156.197-348.087 348.087 0 191.927 156.197 348.087 348.087 348.087s348.050-156.16 348.050-348.087c-0.037-191.927-156.16-348.087-348.050-348.087zM611.328 517.559l-24.101 18.761c-13.166 10.24-21.87 22.126-26.185 35.84-2.743 8.558-4.681 18.907-4.901 37.12h-92.343c1.353-38.473 5.413-61.842 11.301-76.581 5.925-14.592 21.102-31.488 45.531-50.578l24.795-19.383c8.192-6.181 14.738-12.91 19.785-20.187 8.997-12.471 13.495-26.222 13.495-41.216 0-17.262-5.010-32.987-15.104-47.214-10.057-14.226-28.453-21.321-55.259-21.321-26.295 0-44.946 8.777-55.918 26.295s-16.384 33.463-16.384 52.37h-98.523c2.706-64.805 25.234-108.544 67.73-135.57 26.843-17.298 59.794-25.929 98.889-25.929 51.383 0 94.025 12.288 128 36.827 34.011 24.503 53.87 74.935 53.87 123.173 0 29.55-10.24 40.338-25.051 60.599-8.558 12.288-25.125 27.941-49.627 46.994zM561.042 757.577h-98.231v-98.487h98.231v98.487z"
+				],
+				"attrs": [
+					{}
+				],
+				"isMulticolor": false,
+				"grid": 0,
+				"tags": [
+					"help"
+				]
+			},
+			"attrs": [
+				{}
+			],
+			"properties": {
+				"order": 44,
+				"id": 37,
+				"prevSize": 32,
+				"code": 58915,
+				"name": "help"
+			},
+			"setIdx": 0,
+			"setId": 1,
+			"iconIdx": 0
+		},
 		{
 			"icon": {
 				"paths": [
@@ -36,7 +64,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 0
+			"iconIdx": 1
 		},
 		{
 			"icon": {
@@ -76,7 +104,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 1
+			"iconIdx": 2
 		},
 		{
 			"icon": {
@@ -100,7 +128,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 2
+			"iconIdx": 3
 		},
 		{
 			"icon": {
@@ -118,13 +146,13 @@
 				"order": 36,
 				"id": 3,
 				"prevSize": 32,
-				"code": 58915,
+				"code": 58931,
 				"name": "arrow-up-thin",
 				"ligatures": ""
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 3
+			"iconIdx": 4
 		},
 		{
 			"icon": {
@@ -148,7 +176,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 4
+			"iconIdx": 5
 		},
 		{
 			"icon": {
@@ -172,7 +200,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 5
+			"iconIdx": 6
 		},
 		{
 			"icon": {
@@ -196,7 +224,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 6
+			"iconIdx": 7
 		},
 		{
 			"icon": {
@@ -220,7 +248,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 7
+			"iconIdx": 8
 		},
 		{
 			"icon": {
@@ -244,7 +272,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 8
+			"iconIdx": 9
 		},
 		{
 			"icon": {
@@ -268,7 +296,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 9
+			"iconIdx": 10
 		},
 		{
 			"icon": {
@@ -292,7 +320,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 10
+			"iconIdx": 11
 		},
 		{
 			"icon": {
@@ -316,7 +344,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 11
+			"iconIdx": 12
 		},
 		{
 			"icon": {
@@ -340,7 +368,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 12
+			"iconIdx": 13
 		},
 		{
 			"icon": {
@@ -364,7 +392,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 13
+			"iconIdx": 14
 		},
 		{
 			"icon": {
@@ -388,7 +416,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 14
+			"iconIdx": 15
 		},
 		{
 			"icon": {
@@ -412,7 +440,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 15
+			"iconIdx": 16
 		},
 		{
 			"icon": {
@@ -436,7 +464,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 16
+			"iconIdx": 17
 		},
 		{
 			"icon": {
@@ -460,7 +488,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 17
+			"iconIdx": 18
 		},
 		{
 			"icon": {
@@ -484,7 +512,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 18
+			"iconIdx": 19
 		},
 		{
 			"icon": {
@@ -508,7 +536,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 19
+			"iconIdx": 20
 		},
 		{
 			"icon": {
@@ -532,7 +560,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 20
+			"iconIdx": 21
 		},
 		{
 			"icon": {
@@ -556,7 +584,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 21
+			"iconIdx": 22
 		},
 		{
 			"icon": {
@@ -580,7 +608,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 22
+			"iconIdx": 23
 		},
 		{
 			"icon": {
@@ -604,7 +632,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 23
+			"iconIdx": 24
 		},
 		{
 			"icon": {
@@ -628,7 +656,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 24
+			"iconIdx": 25
 		},
 		{
 			"icon": {
@@ -652,7 +680,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 25
+			"iconIdx": 26
 		},
 		{
 			"icon": {
@@ -676,7 +704,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 26
+			"iconIdx": 27
 		},
 		{
 			"icon": {
@@ -700,7 +728,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 27
+			"iconIdx": 28
 		},
 		{
 			"icon": {
@@ -724,7 +752,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 28
+			"iconIdx": 29
 		},
 		{
 			"icon": {
@@ -748,7 +776,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 29
+			"iconIdx": 30
 		},
 		{
 			"icon": {
@@ -772,7 +800,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 30
+			"iconIdx": 31
 		},
 		{
 			"icon": {
@@ -796,7 +824,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 31
+			"iconIdx": 32
 		},
 		{
 			"icon": {
@@ -820,7 +848,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 32
+			"iconIdx": 33
 		},
 		{
 			"icon": {
@@ -844,7 +872,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 33
+			"iconIdx": 34
 		},
 		{
 			"icon": {
@@ -868,7 +896,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 34
+			"iconIdx": 35
 		},
 		{
 			"icon": {
@@ -892,7 +920,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 35
+			"iconIdx": 36
 		},
 		{
 			"icon": {
@@ -916,7 +944,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 36
+			"iconIdx": 37
 		},
 		{
 			"icon": {
@@ -940,7 +968,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 37
+			"iconIdx": 38
 		},
 		{
 			"icon": {
@@ -964,7 +992,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 38
+			"iconIdx": 39
 		},
 		{
 			"icon": {
@@ -988,7 +1016,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 39
+			"iconIdx": 40
 		},
 		{
 			"icon": {
@@ -1012,7 +1040,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 40
+			"iconIdx": 41
 		},
 		{
 			"icon": {
@@ -1036,7 +1064,7 @@
 			},
 			"setIdx": 0,
 			"setId": 1,
-			"iconIdx": 41
+			"iconIdx": 42
 		}
 	],
 	"height": 1024,
diff --git a/lib/web/mage/dropdown.js b/lib/web/mage/dropdown.js
index 61e44e1ee501264a5757973d94e7e6bade643118..dbf04d0da9387841fa28ab1050894fcf3b5fb236 100644
--- a/lib/web/mage/dropdown.js
+++ b/lib/web/mage/dropdown.js
@@ -36,6 +36,7 @@ define([
             autoSize: false,
             draggable: false,
             resizable: false,
+            bodyClass: '',
             buttons: [
                 {
                     'class': "action close",
@@ -111,6 +112,9 @@ define([
             if(_self.options.parentClass) {
                 $(_self.options.appendTo).addClass(_self.options.parentClass);
             }
+            if(_self.options.bodyClass) {
+                $('body').addClass(_self.options.bodyClass);
+            }
 
             if (_self.options.shadowHinter) {
                 _self._setShadowHinterPosition();
@@ -132,6 +136,9 @@ define([
             if(this.options.parentClass) {
                 $(this.options.appendTo).removeClass(this.options.parentClass);
             }
+            if(this.options.bodyClass) {
+                $('body').removeClass(this.options.bodyClass);
+            }
             if(timer) {
                 clearTimeout(timer);
             }
diff --git a/lib/web/mage/loader.js b/lib/web/mage/loader.js
index a4bfc58b7859edd2cff3c200bd37a67733fc32c7..455ba80c692df017ad30293b761036b0b54f9f56 100644
--- a/lib/web/mage/loader.js
+++ b/lib/web/mage/loader.js
@@ -194,18 +194,10 @@ define([
         },
 
         _onAjaxComplete: function (e, jqxhr, settings) {
-            var ariaSelected = $('[aria-selected="true"]');
-
             $(this.options.defaultContainer)
                 .removeClass(this.options.loadingClass)
                 .attr('aria-busy', false);
 
-            // ARIA support
-            if (ariaSelected.length) {
-                ariaSelected.first().focus();
-                $(this.options.defaultContainer).addClass('_keyfocus');
-            }
-
             if (settings && settings.showLoader) {
                 this._getJqueryObj(settings.loaderContext).trigger('processStop');
             }
diff --git a/lib/web/mage/storage.js b/lib/web/mage/storage.js
index ea0b6b432ba9d0b8316b1f714c92c50e697f3d62..3c6bd89ca1ebf0de4d964a4533cf9ffd1ff8e20d 100644
--- a/lib/web/mage/storage.js
+++ b/lib/web/mage/storage.js
@@ -2,34 +2,83 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*global define*/
 define(['jquery', 'mage/url'], function ($, urlBuilder) {
-    "use strict";
+    'use strict';
+
     return {
-        get: function (url, contentType) {
+        /**
+         * Perform asynchronous GET request to server.
+         * @param {String} url
+         * @param {Boolean} global
+         * @param {String} contentType
+         * @returns {Deferred}
+         */
+        get: function (url, global, contentType) {
+            global = global === undefined ? true : global;
             contentType = contentType || 'application/json';
+
             return $.ajax({
                 url: urlBuilder.build(url),
                 type: 'GET',
-                async: false,
+                global: global,
                 contentType: contentType
             });
         },
-        post: function(url, data, contentType) {
+        /**
+         * Perform asynchronous POST request to server.
+         * @param {String} url
+         * @param {String} data
+         * @param {Boolean} global
+         * @param {String} contentType
+         * @returns {Deferred}
+         */
+        post: function (url, data, global, contentType) {
+            global = global === undefined ? true : global;
             contentType = contentType || 'application/json';
+
             return $.ajax({
                 url: urlBuilder.build(url),
                 type: 'POST',
                 data: data,
+                global: global,
                 contentType: contentType
             });
         },
-        put: function(url, data, contentType) {
+        /**
+         * Perform asynchronous PUT request to server.
+         * @param {String} url
+         * @param {String} data
+         * @param {Boolean} global
+         * @param {String} contentType
+         * @returns {Deferred}
+         */
+        put: function(url, data, global, contentType) {
+            global = global === undefined ? true : global;
             contentType = contentType || 'application/json';
+
             return $.ajax({
                 url: urlBuilder.build(url),
                 type: 'PUT',
                 data: data,
+                global: global,
+                contentType: contentType
+            });
+        },
+        /**
+         * Perform asynchronous DELETE request to server.
+         * @param {String} url
+         * @param {Boolean} global
+         * @param {String} contentType
+         * @returns {Deferred}
+         */
+        delete: function(url, global, contentType) {
+            global = global === undefined ? true : global;
+            contentType = contentType || 'application/json';
+
+            return $.ajax({
+                url: urlBuilder.build(url),
+                type: 'DELETE',
+                global: global,
                 contentType: contentType
             });
         }