diff --git a/app/code/Magento/Csp/Model/BlockCache.php b/app/code/Magento/Csp/Model/BlockCache.php index f0469c3251379..fac0beec51c07 100644 --- a/app/code/Magento/Csp/Model/BlockCache.php +++ b/app/code/Magento/Csp/Model/BlockCache.php @@ -111,7 +111,7 @@ public function save($data, $identifier, $tags = [], $lifeTime = null) ]; } } - $data = $this->serializer->serialize(['policies' => $policiesData, 'html' => $data]); + $data = $this->serializer->serialize(['policies' => $policiesData, 'html' => (string)$data]); } return $this->cache->save($data, $identifier, $tags, $lifeTime); diff --git a/app/code/Magento/Csp/Model/Collector/CompositeMerger.php b/app/code/Magento/Csp/Model/Collector/CompositeMerger.php new file mode 100644 index 0000000000000..16430f1ff8aa9 --- /dev/null +++ b/app/code/Magento/Csp/Model/Collector/CompositeMerger.php @@ -0,0 +1,57 @@ +mergers = $mergers; + } + + /** + * @inheritDoc + */ + public function merge(PolicyInterface $policy1, PolicyInterface $policy2): PolicyInterface + { + foreach ($this->mergers as $merger) { + if ($merger->canMerge($policy1, $policy2)) { + return $merger->merge($policy1, $policy2); + } + } + + throw new \RuntimeException('Cannot merge 2 policies of ' .get_class($policy1)); + } + + /** + * @inheritDoc + */ + public function canMerge(PolicyInterface $policy1, PolicyInterface $policy2): bool + { + foreach ($this->mergers as $merger) { + if ($merger->canMerge($policy1, $policy2)) { + return true; + } + } + + return false; + } +} diff --git a/app/code/Magento/Csp/Model/Collector/DynamicCollector.php b/app/code/Magento/Csp/Model/Collector/DynamicCollector.php index 6478e9622f910..743f77c93f3d8 100644 --- a/app/code/Magento/Csp/Model/Collector/DynamicCollector.php +++ b/app/code/Magento/Csp/Model/Collector/DynamicCollector.php @@ -20,6 +20,19 @@ class DynamicCollector implements PolicyCollectorInterface */ private $added = []; + /** + * @var MergerInterface + */ + private $merger; + + /** + * @param MergerInterface $merger + */ + public function __construct(MergerInterface $merger) + { + $this->merger = $merger; + } + /** * Add a policy for current page. * @@ -28,7 +41,15 @@ class DynamicCollector implements PolicyCollectorInterface */ public function add(PolicyInterface $policy): void { - $this->added[] = $policy; + if (array_key_exists($policy->getId(), $this->added)) { + if ($this->merger->canMerge($this->added[$policy->getId()], $policy)) { + $this->added[$policy->getId()] = $this->merger->merge($this->added[$policy->getId()], $policy); + } else { + throw new \RuntimeException('Cannot merge a policy of ' .get_class($policy)); + } + } else { + $this->added[$policy->getId()] = $policy; + } } /** @@ -36,6 +57,6 @@ public function add(PolicyInterface $policy): void */ public function collect(array $defaultPolicies = []): array { - return array_merge($defaultPolicies, $this->added); + return array_merge($defaultPolicies, array_values($this->added)); } } diff --git a/app/code/Magento/Csp/etc/di.xml b/app/code/Magento/Csp/etc/di.xml index 7b1129a0e1a41..238392fe1c8d1 100644 --- a/app/code/Magento/Csp/etc/di.xml +++ b/app/code/Magento/Csp/etc/di.xml @@ -15,6 +15,17 @@ + + + + + Magento\Csp\Model\Collector\FetchPolicyMerger + Magento\Csp\Model\Collector\FlagPolicyMerger + Magento\Csp\Model\Collector\PluginTypesPolicyMerger + Magento\Csp\Model\Collector\SandboxPolicyMerger + + + @@ -24,10 +35,7 @@ Magento\Csp\Model\Collector\DynamicCollector\Proxy - Magento\Csp\Model\Collector\FetchPolicyMerger - Magento\Csp\Model\Collector\FlagPolicyMerger - Magento\Csp\Model\Collector\PluginTypesPolicyMerger - Magento\Csp\Model\Collector\SandboxPolicyMerger + Magento\Csp\Model\Collector\MergerInterface @@ -93,6 +101,7 @@ configured_block_cache + Magento\Framework\Serialize\Serializer\Serialize