Commit d427b2e4 authored by jbroman@chromium.org's avatar jbroman@chromium.org

Move plugin placeholder style to CSS, and allow it to bypass main world CSP.

<style> elements inside UA shadow roots are permitted to load inline style,
even if the host document CSP disallows this, since the style is supplied by
the user agent.

BUG=364716

Review URL: https://codereview.chromium.org/516273002

git-svn-id: svn://svn.chromium.org/blink/trunk@184015 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e1544430
<!DOCTYPE html>
<link rel="stylesheet" href="plugin-placeholder.css">
<div class="plugin">
<div class="plugin-placeholder">
<div class="plugin-placeholder-content">
<div class="plugin-placeholder-message">
This box should be styled despite CSP.
</div>
</div>
</div>
</div>
<!DOCTYPE html>
<!-- Forbid inline style. -->
<meta http-equiv="Content-Security-Policy" content="style-src 'none'">
<!-- The message inserted below should be shown with some suitable style. -->
<embed type="application/x-fake-plugin"></embed>
<script>
var plugin = document.querySelector("embed");
internals.forcePluginPlaceholder(plugin, { message: "This box should be styled despite CSP." });
</script>
<!DOCTYPE html> <!DOCTYPE html>
<style> <link rel="stylesheet" href="plugin-placeholder.css">
.plugin {
display: block;
width: 300px;
height: 150px;
}
.plugin-placeholder {
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
align-items: center;
background-color: gray;
font: 12px -webkit-control;
}
.plugin-placeholder-content {
text-align: center;
margin: auto;
}
</style>
<div class="plugin"> <div class="plugin">
<div class="plugin-placeholder"> <div class="plugin-placeholder">
......
.plugin {
display: block;
width: 300px;
height: 150px;
}
.plugin-placeholder {
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
align-items: center;
background-color: gray;
font: 12px -webkit-control;
}
.plugin-placeholder-content {
text-align: center;
margin: auto;
}
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "core/dom/Element.h" #include "core/dom/Element.h"
#include "core/dom/ScriptableDocumentParser.h" #include "core/dom/ScriptableDocumentParser.h"
#include "core/dom/StyleEngine.h" #include "core/dom/StyleEngine.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLStyleElement.h" #include "core/html/HTMLStyleElement.h"
...@@ -141,6 +142,21 @@ void StyleElement::clearSheet(Element* ownerElement) ...@@ -141,6 +142,21 @@ void StyleElement::clearSheet(Element* ownerElement)
m_sheet.release()->clearOwnerNode(); m_sheet.release()->clearOwnerNode();
} }
static bool shouldBypassMainWorldCSP(Element* element)
{
// Main world CSP is bypassed within an isolated world.
LocalFrame* frame = element->document().frame();
if (frame && frame->script().shouldBypassMainWorldCSP())
return true;
// Main world CSP is bypassed for style elements in user agent shadow DOM.
ShadowRoot* root = element->containingShadowRoot();
if (root && root->type() == ShadowRoot::UserAgentShadowRoot)
return true;
return false;
}
void StyleElement::createSheet(Element* e, const String& text) void StyleElement::createSheet(Element* e, const String& text)
{ {
ASSERT(e); ASSERT(e);
...@@ -149,13 +165,8 @@ void StyleElement::createSheet(Element* e, const String& text) ...@@ -149,13 +165,8 @@ void StyleElement::createSheet(Element* e, const String& text)
if (m_sheet) if (m_sheet)
clearSheet(e); clearSheet(e);
// Inline style added from an isolated world should bypass the main world's
// CSP just as an inline script would.
LocalFrame* frame = document.frame();
bool shouldBypassMainWorldCSP = frame && frame->script().shouldBypassMainWorldCSP();
const ContentSecurityPolicy* csp = document.contentSecurityPolicy(); const ContentSecurityPolicy* csp = document.contentSecurityPolicy();
bool passesContentSecurityPolicyChecks = shouldBypassMainWorldCSP bool passesContentSecurityPolicyChecks = shouldBypassMainWorldCSP(e)
|| csp->allowStyleWithHash(text) || csp->allowStyleWithHash(text)
|| csp->allowStyleWithNonce(e->fastGetAttribute(HTMLNames::nonceAttr)) || csp->allowStyleWithNonce(e->fastGetAttribute(HTMLNames::nonceAttr))
|| csp->allowInlineStyle(e->document().url(), m_startPosition.m_line); || csp->allowInlineStyle(e->document().url(), m_startPosition.m_line);
......
...@@ -5,27 +5,36 @@ ...@@ -5,27 +5,36 @@
'use strict'; 'use strict';
installClass('PluginPlaceholderElement', function(PluginPlaceholderElementPrototype) { installClass('PluginPlaceholderElement', function(PluginPlaceholderElementPrototype) {
PluginPlaceholderElementPrototype.createdCallback = function() { // FIXME: Load this from a .css file.
// FIXME: Move style out of script and into CSS. var styleSource =
'#plugin-placeholder {' +
' width: 100%;' +
' height: 100%;' +
' overflow: hidden;' +
' display: flex;' +
' align-items: center;' +
' background: gray;' +
' font: 12px -webkit-control;' +
'}' +
'#plugin-placeholder-content {' +
' text-align: center;' +
' margin: auto;' +
'}';
PluginPlaceholderElementPrototype.createdCallback = function() {
this.id = 'plugin-placeholder'; this.id = 'plugin-placeholder';
this.style.width = '100%';
this.style.height = '100%'; var styleElement = document.createElement('style');
this.style.overflow = 'hidden'; styleElement.textContent = styleSource;
this.style.display = 'flex';
this.style.alignItems = 'center';
this.style.backgroundColor = 'gray';
this.style.font = '12px -webkit-control';
var contentElement = document.createElement('div'); var contentElement = document.createElement('div');
contentElement.id = 'plugin-placeholder-content'; contentElement.id = 'plugin-placeholder-content';
contentElement.style.textAlign = 'center';
contentElement.style.margin = 'auto';
var messageElement = document.createElement('div'); var messageElement = document.createElement('div');
messageElement.id = 'plugin-placeholder-message'; messageElement.id = 'plugin-placeholder-message';
contentElement.appendChild(messageElement); contentElement.appendChild(messageElement);
this.appendChild(styleElement);
this.appendChild(contentElement); this.appendChild(contentElement);
this.messageElement = messageElement; this.messageElement = messageElement;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment