Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use secureRender to fix CSP problems with new magento #66

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Block/Matomo.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,30 @@ class Matomo extends \Magento\Framework\View\Element\Template
*/
protected $_dataHelper = null;

protected \Magento\Csp\Helper\CspNonceProvider $_cspNonceProvider;

/**
* Constructor
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
* @param \Chessio\Matomo\Model\Tracker $tracker
* @param \Chessio\Matomo\Helper\Data $dataHelper
* @param \Magento\Csp\Helper\CspNonceProvider $cspNonceProvider
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Framework\Json\EncoderInterface $jsonEncoder,
\Chessio\Matomo\Model\Tracker $tracker,
\Chessio\Matomo\Helper\Data $dataHelper,
\Magento\Csp\Helper\CspNonceProvider $cspNonceProvider,
array $data = []
) {
$this->_jsonEncoder = $jsonEncoder;
$this->_tracker = $tracker;
$this->_dataHelper = $dataHelper;
$this->_cspNonceProvider = $cspNonceProvider;
parent::__construct($context, $data);
}

Expand Down Expand Up @@ -116,7 +121,8 @@ public function getJsOptions()
'scriptUrl' => $this->getScriptUrl(),
'trackerUrl' => $this->getTrackerUrl(),
'siteId' => $this->getSiteId(),
'actions' => $this->getTracker()->toArray()
'actions' => $this->getTracker()->toArray(),
'nonce' => $this->_cspNonceProvider->generateNonce(),
];
}

Expand Down
30 changes: 19 additions & 11 deletions view/frontend/templates/matomo.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
* along with Chessio_Matomo. If not, see <http://www.gnu.org/licenses/>.
*/

/** @var \Chessio\Matomo\Block\Matomo $block */
/** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */
?>
<?php /** @var \Chessio\Matomo\Block\Matomo $block */ ?>
<?php ?>
<script type="text/x-magento-init">
<?= $block->jsonEncode([
'*' => [
Expand All @@ -29,35 +31,39 @@
]); ?>
</script>
<?php
// Render tage without echo so it's added to the dynamic CSP.
$secureRenderer->renderTag('script', ['src' => $block->getScriptUrl()]);

// The following script can be omitted in which case the
// `Chessio_Matomo/js/tracker' component will inject the tracker script instead.
// However that might cause the tracker script to miss the `DOMContentLoaded'
// event which breaks the link tracking feature.
?>
<script type="text/javascript">
$scriptString = <<<script
(function (w, d) {
w._paq = w._paq || [];
w._paq.push(['setTrackerUrl', '<?= $block->escapeJsQuote($block->getTrackerUrl()); ?>']);
w._paq.push(['setSiteId', <?= (int) $block->getSiteId(); ?>]);
w._paq.push(['setTrackerUrl', '{$block->escapeJsQuote($block->getTrackerUrl())}']);
w._paq.push(['setSiteId', {$block->getSiteId()}]);
var g = d.createElement('script'),
s = d.getElementsByTagName('script')[0];
g.type = 'text/javascript';
g.async = true;
g.defer = true;
g.src = '<?= $block->escapeJsQuote($block->getScriptUrl()); ?>';
g.src = '{$block->escapeJsQuote($block->getScriptUrl())}';
s.parentNode.insertBefore(g, s);
})(window, document);
</script>
<?php
script;

echo $secureRenderer->renderTag('script', [], $scriptString, false);

// The following script is a workaround that prevents the checkout loader
// overlay from spinning indefinitely in cases where a browser plugin such as
// AdBlock stops the tracker JS component from loading. The loader indicator
// relies on require's module registry to decide when to hide itself so here we
// export a mocked version of the component if we get an `errback' from require.
// @see vendor/magento/module-checkout/view/frontend/web/js/checkout-loader.js
// @see lib/web/mage/requirejs/resolver.js
?>
<script type="text/javascript">

$scriptString = <<<script
(function (require, undefined) {
'use strict';
var moduleName = 'Chessio_Matomo/js/tracker';
Expand All @@ -83,7 +89,9 @@
}
});
})(require);
</script>
script;
echo $secureRenderer->renderTag('script', [], $scriptString, false);
?>
<noscript>
<p>
<img src="<?= $block->getTrackingPixelUrl(); ?>"
Expand Down
5 changes: 3 additions & 2 deletions view/frontend/web/js/tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,13 @@ define([
*
* @param {String} scriptUrl
*/
function injectScript(scriptUrl) {
function injectScript(scriptUrl, nonce) {
$('<script>')
.attr('type', 'text/javascript')
.attr('async', true)
.attr('defer', true)
.attr('src', scriptUrl)
.attr('nonce', nonce)
.appendTo('head');
}

Expand Down Expand Up @@ -312,7 +313,7 @@ define([
['setSiteId', defaultSiteId],
['setTrackerUrl', defaultTrackerUrl]
]);
injectScript(options.scriptUrl);
injectScript(options.scriptUrl, options.nonce);
}
} else {
// If we already have the Matomo object we can resolve any pending
Expand Down