Marty is correct, although I would like to temper the description of this being "unfortunate" a bit with some background on why the security policy is in place. In order for us to satisfy our internal security audits and architectural reviews which allowed us, for the first time ever in our presentation layer, to provide a supported mechanism to allow salesforce authored code and customer/ISV/partner authored code to coexist in the same JavaScript space we had to tighten things down significantly. Here are some of the things currently enforced:
- Content security policy, or CSP, a relatively new browser technology that allows us to have fine-grained control over access to all external references to scripts, images, stylesheets, etc. Our policy is extremely restrictive right now and not extensible but we had plans to open up a white listing capability in the near future.
- Lightning applications are served from a separate domain in much the same manner that visual force pages are today. The difference here is that you are actually in the same application, running right next to our client-side code and not relegated to live in an iframe silo. Those silos have presented significant challenges around producing high performance, high fidelity, engaging user experiences that integrates directly into core salesforce functionality for many years.
- The lightning application separate domain also uses a special lightning session ID that does not have direct API access. The fact that you can currently provide indirect access to a fully API capable session ID is a great example of why our content security policy is currently so restrictive. Leaking an API said back to the client in a way that malicious JavaScript can easily steal is precisely why we have things locked down so tightly today. What should happen if you attempted to serialize an API session ID from an apex controller? That session ID is supposed to be the same restricted access Aura session ID but we apparently have a leak in that underlying logic. Our belt and suspenders approach with CSP combined with serving from a separate domain actually thwarted this potential attack.
Why did we do these things? Most of it boils down to "protect Setup". Without these safeguards in place is almost trivial for malicious client side code to gain height and privileges and access to administrative level functionality by remote controlling the setup user interface Also, much of what we have done so far represent cross site scripting (XSS) attack countermeasures.
There is definitely much more to the story but hopefully this gives you some of the back story to better understand our decisions and direction. This is not the end, rather just the beginning, and we are hard at work on improving and refining our approach to balancing the security requirements that we have to satisfy along with providing all of you with the tools that you need to build what you want.
@Praveen, yes, this is totally normal. Here is what is happening:
When we say that the body attribute is defined on all components we mean that it's defined on the base <aura:component/>
from which all components inherit. Here is a simplified version.
<aura:component/>
<aura:attribute name="body" type="Aura.Component[]"/>
{!v.body}
</aura:component>
As you can see, the base component outputs the body tag that it receives in its own body, otherwise, nothing would be rendered. Angular calls that process "transclusion", the inclusion of content from another context.
When you write this:
<aura:component>
<div>Body part</div>
<ui:button label="Push Me" press="{!c.printCmpBody}"/>
</aura:component>
You are setting the body tag of the parent component. Everything defined in your component is the "lexical definition", and it's passed to its parent. If you want to read it, you could use cmp.getSuper().get("v.body")
but it's a deprecated API, and it will probably not work. However, that's the idea behind it.
Why is it working like this? Let's call your component c:myComponent
and use it inside an app:
<c:myComponent>
<i>Instance Part</i>
</c:myComponent>
This is equivalent to this format:
<c:myComponent>
<aura:set attribute="body>
<i>Hello</i>
</aura:set>
<c:myComponent>
As you see, every component needs to receive an attribute body independently of what it defines internally. You can try this format, it does work, but it's unnecessary except to illustrate how to set the body of a component.
Now, your component can ignore its body attribute as in your original code, or it can use it like this:
<aura:component>
<div>Body part</div>
{!v.body}
<ui:button label="Push Me" press="{!c.printCmpBody}"/>
</aura:component>
You can place the expression {!v.body}
anywhere you want.
The rendered content will then be equal to the instance's v.body
plus the component-defined lexical definition:
v.body = <i>Instance Part</i>
+
lexical scope = <div>Body part</div>{!v.body}...
=
Rendered: <div>Body part</div><i>Instance Part</i>...
You can get more information on how the attribute body works by looking at slides 24, 25, and 27:
Mastering the Lightning Framework - Part 1
And the explications are at around 15:00 minute here:
Mastering the Lightning Framework - Part 1
Best Answer
You can use aura:unescapedHtml to inject almost any kind of HTML. As usual in this case, make sure that you trust the source code to avoid injection attacks, or at least do some minimal scrubbing of potentially dangerous tags.